├── .github
├── FUNDING.yml
└── workflows
│ ├── build.yml
│ ├── codecov.yml
│ ├── lint.yml
│ ├── mobile.yml
│ └── test.yml
├── .gitignore
├── .rustfmt.toml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.md
├── codecov.yml
├── descriptors
├── Cargo.toml
└── src
│ ├── deduction.rs
│ ├── derive.rs
│ ├── descriptor.rs
│ ├── input.rs
│ ├── lib.rs
│ └── templates.rs
├── doc
└── assets
│ └── comparison.png
├── hd
├── Cargo.toml
└── src
│ ├── account.rs
│ ├── derive.rs
│ ├── indexes.rs
│ ├── lib.rs
│ ├── path.rs
│ ├── ranges.rs
│ ├── standards.rs
│ ├── traits.rs
│ ├── unsatisfiable.rs
│ ├── xkey.rs
│ └── xpubref.rs
├── libbitcoin
├── Cargo.lock
├── Cargo.toml
└── src
│ ├── helpers.rs
│ ├── lib.rs
│ └── signer.rs
├── license_header
├── onchain
├── Cargo.toml
└── src
│ ├── blockchain.rs
│ ├── lib.rs
│ ├── network.rs
│ └── resolvers
│ ├── electrum.rs
│ └── mod.rs
├── psbt
├── Cargo.toml
├── README.md
└── src
│ ├── construct
│ └── mod.rs
│ ├── errors.rs
│ ├── global.rs
│ ├── input.rs
│ ├── lex_order.rs
│ ├── lib.rs
│ ├── output.rs
│ ├── p2c.rs
│ ├── proprietary.rs
│ └── sign
│ ├── inmem.rs
│ ├── mod.rs
│ └── signer.rs
├── rust-toolchain.toml
├── slip132
├── Cargo.toml
├── README.md
└── src
│ └── lib.rs
└── src
├── bin
├── btc-cold.rs
├── btc-expl.rs
└── btc-hot.rs
├── cli
└── mod.rs
└── lib.rs
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [dr-orlovsky]
4 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | default:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Install rust stable
18 | uses: actions-rs/toolchain@v1
19 | with:
20 | toolchain: stable
21 | override: true
22 | - name: Default build
23 | uses: actions-rs/cargo@v1
24 | with:
25 | command: check
26 | args: --workspace
27 | binary:
28 | runs-on: ubuntu-latest
29 | steps:
30 | - uses: actions/checkout@v2
31 | - name: Install rust stable
32 | uses: actions-rs/toolchain@v1
33 | with:
34 | toolchain: stable
35 | override: true
36 | - name: Default build
37 | uses: actions-rs/cargo@v1
38 | with:
39 | command: build
40 | args: --bin btc-hot --bin btc-cold --features cli,serde,hot,electrum
41 | features:
42 | runs-on: ubuntu-latest
43 | strategy:
44 | fail-fast: false
45 | matrix:
46 | feature:
47 | - miniscript
48 | - compiler
49 | - electrum
50 | - strict_encoding
51 | - keygen
52 | - construct
53 | - sign
54 | - hot
55 | - cli
56 | - serde
57 | steps:
58 | - uses: actions/checkout@v2
59 | - name: Install rust stable
60 | uses: actions-rs/toolchain@v1
61 | with:
62 | toolchain: stable
63 | override: true
64 | - name: Feature ${{ matrix.feature }}
65 | uses: actions-rs/cargo@v1
66 | with:
67 | command: check
68 | args: --no-default-features --features=${{ matrix.feature }}
69 | - name: Defaults + ${{ matrix.feature }}
70 | uses: actions-rs/cargo@v1
71 | with:
72 | command: check
73 | args: --features=${{ matrix.feature }}
74 | platforms:
75 | runs-on: ${{ matrix.os }}
76 | strategy:
77 | fail-fast: false
78 | matrix:
79 | os: [ ubuntu-20.04, ubuntu-22.04, macos-11, macos-12, windows-2019, windows-2022 ]
80 | steps:
81 | - uses: actions/checkout@v2
82 | - name: Install rust stable
83 | uses: actions-rs/toolchain@v1
84 | with:
85 | toolchain: stable
86 | override: true
87 | - name: Build with all features
88 | uses: actions-rs/cargo@v1
89 | with:
90 | command: check
91 | args: --workspace --all-targets --all-features
92 | toolchains:
93 | runs-on: ubuntu-latest
94 | strategy:
95 | fail-fast: false
96 | matrix:
97 | toolchain: [ nightly, beta, stable, 1.70.0 ]
98 | steps:
99 | - uses: actions/checkout@v2
100 | - name: Install rust ${{ matrix.toolchain }}
101 | uses: actions-rs/toolchain@v1
102 | with:
103 | toolchain: ${{ matrix.toolchain }}
104 | override: true
105 | - name: All features
106 | uses: actions-rs/cargo@v1
107 | with:
108 | command: check
109 | args: --workspace --all-targets --all-features
110 |
--------------------------------------------------------------------------------
/.github/workflows/codecov.yml:
--------------------------------------------------------------------------------
1 | name: Codecov
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | codecov:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Install latest nightly
18 | uses: actions-rs/toolchain@v1
19 | with:
20 | toolchain: nightly
21 | override: true
22 | - name: Build & test
23 | uses: actions-rs/cargo@v1
24 | with:
25 | command: test
26 | args: --workspace --all-features --no-fail-fast
27 | env:
28 | CARGO_INCREMENTAL: '0'
29 | RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
30 | RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
31 | - id: coverage
32 | name: Generate coverage
33 | uses: actions-rs/grcov@0.2-proto
34 | with:
35 | args: >
36 | -t lcov
37 | --llvm
38 | --ignore-not-existing
39 | --ignore "/*"
40 | -o ./target/lcov.info
41 | ./target/debug/
42 | - name: Upload coverage to Codecov
43 | uses: codecov/codecov-action@v1
44 | with:
45 | file: ${{ steps.coverage.outputs.report }}
46 | directory: ./coverage/reports/
47 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lints
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | fmt:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Install rustc nightly
18 | uses: actions-rs/toolchain@v1
19 | with:
20 | toolchain: nightly
21 | override: true
22 | components: rustfmt
23 | - uses: actions-rs/cargo@v1
24 | name: Formatting
25 | with:
26 | command: fmt
27 | args: --all -- --check
28 | clippy:
29 | runs-on: ubuntu-latest
30 | steps:
31 | - uses: actions/checkout@v2
32 | - name: Install rustc stable
33 | uses: actions-rs/toolchain@v1
34 | with:
35 | toolchain: stable
36 | override: true
37 | components: clippy
38 | - uses: actions-rs/cargo@v1
39 | name: Clippy
40 | with:
41 | command: clippy
42 | args: --workspace --all-features
43 | doc:
44 | runs-on: ubuntu-latest
45 | steps:
46 | - uses: actions/checkout@v2
47 | - name: Install rustc nightly
48 | uses: actions-rs/toolchain@v1
49 | with:
50 | toolchain: nightly
51 | override: true
52 | components: rust-docs
53 | - uses: actions-rs/cargo@v1
54 | name: Clippy
55 | with:
56 | command: doc
57 | args: --workspace --all-features
58 |
--------------------------------------------------------------------------------
/.github/workflows/mobile.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | android:
14 | runs-on: ubuntu-latest
15 | env:
16 | NDK_VERSION: 20.1.5948944
17 | ANDROID_CLI_ZIP: commandlinetools-linux-6858069_latest.zip
18 | ANDROID_CLI_SHA256: 87f6dcf41d4e642e37ba03cb2e387a542aa0bd73cb689a9e7152aad40a6e7a08
19 | steps:
20 | - uses: actions/checkout@v2
21 | - name: Install rust
22 | uses: actions-rs/toolchain@v1
23 | with:
24 | toolchain: stable
25 | override: true
26 | - name: set environment variables
27 | run: |
28 | ANDROID_SDK_ROOT="$GITHUB_WORKSPACE/sdk"
29 | NDK_HOME="$ANDROID_SDK_ROOT/ndk/$NDK_VERSION"
30 | echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" >> $GITHUB_ENV
31 | echo "NDK_HOME=$NDK_HOME" >> $GITHUB_ENV
32 | echo "PATH=$PATH:$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_ENV
33 | - name: Install NDK
34 | run: |
35 | wget -nv https://dl.google.com/android/repository/$ANDROID_CLI_ZIP
36 | echo "$ANDROID_CLI_SHA256 $ANDROID_CLI_ZIP" > SHA256SUMS
37 | sha256sum -c SHA256SUMS
38 | unzip $ANDROID_CLI_ZIP
39 | mkdir -p $ANDROID_SDK_ROOT/cmdline-tools && mv cmdline-tools $ANDROID_SDK_ROOT/cmdline-tools/3.0
40 | yes 2>/dev/null | $ANDROID_SDK_ROOT/cmdline-tools/3.0/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT \
41 | "build-tools;29.0.3" "platforms;android-29" "ndk;$NDK_VERSION" |grep -v '\[='; true
42 | - name: Add rust targets
43 | run: |
44 | rustup target add aarch64-linux-android x86_64-linux-android armv7-linux-androideabi i686-linux-android
45 | - name: Build for aarch64-linux-android
46 | run: |
47 | export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang"
48 | export CC="aarch64-linux-android21-clang"
49 | export CFLAGS="--sysroot=$NDK_HOME/sysroot -I$NDK_HOME/sysroot/usr/include -I$NDK_HOME/sysroot/usr/include/aarch64-linux-android"
50 | export CXX="aarch64-linux-android21-clang++"
51 | export CXXFLAGS="$CFLAGS -nostdlib++ -I$NDK_HOME/sources/cxx-stl/llvm-libc++/include"
52 | export LDFLAGS="--sysroot=$NDK_HOME/platforms/android-21/arch-arm64"
53 | cargo check --features mobile --target=aarch64-linux-android
54 | - name: Build for x86_64-linux-android
55 | run: |
56 | export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android26-clang"
57 | export CC="x86_64-linux-android21-clang"
58 | export CFLAGS="--sysroot=$NDK_HOME/sysroot -I$NDK_HOME/sysroot/usr/include -I$NDK_HOME/sysroot/usr/include/x86_64-linux-android"
59 | export CXX="x86_64-linux-android21-clang++"
60 | export CXXFLAGS="$CFLAGS -nostdlib++ -I$NDK_HOME/sources/cxx-stl/llvm-libc++/include"
61 | export LDFLAGS="--sysroot=$NDK_HOME/platforms/android-21/arch-x86_64"
62 | cargo check --features mobile --target=x86_64-linux-android
63 | - name: Build for armv7-linux-androideabi
64 | run: |
65 | export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi26-clang"
66 | export CC="armv7a-linux-androideabi21-clang"
67 | export CFLAGS="--sysroot=$NDK_HOME/sysroot -I$NDK_HOME/sysroot/usr/include -I$NDK_HOME/sysroot/usr/include/arm-linux-androideabi"
68 | export CXX="armv7a-linux-androideabi21-clang++"
69 | export CXXFLAGS="$CFLAGS -nostdlib++ -I$NDK_HOME/sources/cxx-stl/llvm-libc++/include"
70 | export LDFLAGS="--sysroot=$NDK_HOME/platforms/android-21/arch-arm -L$NDK_HOME/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a"
71 | cargo check --features mobile --target=armv7-linux-androideabi
72 | - name: Build for i686-linux-android
73 | run: |
74 | export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android26-clang"
75 | export CC="i686-linux-android21-clang"
76 | export CFLAGS="--sysroot=$NDK_HOME/sysroot -I$NDK_HOME/sysroot/usr/include -I$NDK_HOME/sysroot/usr/include/i686-linux-android"
77 | export CXX="i686-linux-android21-clang++"
78 | export CXXFLAGS="$CFLAGS -nostdlib++ -I$NDK_HOME/sources/cxx-stl/llvm-libc++/include"
79 | export LDFLAGS="--sysroot=$NDK_HOME/platforms/android-21/arch-x86"
80 | cargo check --features mobile --target=i686-linux-android
81 | ios:
82 | runs-on: macos-latest
83 | steps:
84 | - uses: actions/checkout@v2
85 | - name: Install rust
86 | uses: actions-rs/toolchain@v1
87 | with:
88 | toolchain: stable
89 | override: true
90 | - name: Dependencies and targets
91 | run: |
92 | rustup target add aarch64-apple-ios x86_64-apple-ios
93 | cargo install cargo-lipo
94 | - name: build
95 | uses: actions-rs/cargo@v1
96 | with:
97 | command: lipo
98 | args: --features mobile --verbose
99 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | testing:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Install latest stable
18 | uses: actions-rs/toolchain@v1
19 | with:
20 | toolchain: stable
21 | override: true
22 | - name: Test main lib
23 | uses: actions-rs/cargo@v1
24 | with:
25 | command: test
26 | args: --workspace --all-features --no-fail-fast
27 | - name: Test slip132
28 | uses: actions-rs/cargo@v1
29 | with:
30 | command: test
31 | args: --manifest-path slip132/Cargo.toml --all-features --no-fail-fast
32 | testing-c-lib:
33 | runs-on: ubuntu-latest
34 | steps:
35 | - uses: actions/checkout@v2
36 | - name: Install latest nightly
37 | uses: actions-rs/toolchain@v1
38 | with:
39 | toolchain: nightly
40 | override: true
41 | - name: Build & test
42 | uses: actions-rs/cargo@v1
43 | with:
44 | command: test
45 | args: --manifest-path libbitcoin/Cargo.toml --all-features --no-fail-fast
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | target/
4 |
5 | # These are backup files generated by rustfmt
6 | **/*.rs.bk
7 |
8 | .idea
9 | .vscode
10 |
11 | *.swp
12 |
13 | /dep_test
14 |
15 | /wallets
--------------------------------------------------------------------------------
/.rustfmt.toml:
--------------------------------------------------------------------------------
1 | max_width = 100
2 | format_code_in_doc_comments = true
3 | fn_single_line = true
4 | format_macro_matchers = true
5 | format_strings = true
6 | merge_derives = false
7 | imports_granularity = "Module"
8 | overflow_delimited_expr = true
9 | group_imports = "StdExternalCrate"
10 | use_field_init_shorthand = true
11 | use_try_shorthand = true
12 | wrap_comments = true
13 | comment_width = 80
14 | unstable_features = true
15 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | We do not apply any code of conduct expectations for contributors and
4 | maintainers in their live and behaviour outside the scope of this project.
5 | We believe that a restriction is the word of sin: free people write code, take
6 | their decisions and act in a way they will, taking responsibility for the
7 | consequences.
8 |
9 | Moreover, we will try to protect the freedom of speech of contributors, and
10 | explicit distance from personal or public life of contributors, as long as
11 | they behave in a civil and productive way when contributing and interacting
12 | within the project, and will go to great lengths to not deny anyone
13 | participation.
14 |
15 | Actions within the technical scope of the project (code quality, spamming etc),
16 | as well as interaction with other maintainers and contributors of course is
17 | a factor of the access to the project development and lifecycle. The decision in
18 | these cases will be made by the project maintainers, with the right of veto or
19 | overriding vote reserved for the original project author, Maxim Orlovsky.
20 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing to LNP/BP projects
2 | ===============================
3 |
4 | :+1::tada:
5 | First and foremost, thanks for taking the time to contribute!
6 | :tada::+1:
7 |
8 | The following is a set of guidelines for contributing to [LNP/BP Standards
9 | Association](https://lnp-bp.org) projects, which are hosted in the GitHub
10 | organizations listed in [readme](https://github.com/LNP-BP#Working-groups).
11 | These are mostly guidelines, not rules. Use your best judgment, and feel free to
12 | propose changes to this document in a pull request.
13 |
14 | #### Table Of Contents
15 | - [General](#general)
16 | - [Communication channels](#communication-channels)
17 | - [Asking questions](#asking-questions)
18 | - [Contribution workflow](#contribution-workflow)
19 | * [Preparing PRs](#preparing-prs)
20 | * [Peer review](#peer-review)
21 | - [Coding conventions](#coding-conventions)
22 | - [Security](#security)
23 | - [Testing](#testing)
24 | - [Going further](#going-further)
25 |
26 |
27 | General
28 | -------
29 | The LNP/BP projects operate an open contributor model where anyone is welcome to
30 | contribute towards development in the form of peer review, documentation,
31 | testing and patches.
32 |
33 | Anyone is invited to contribute without regard to technical experience,
34 | "expertise", OSS experience, age, or other concern. However, the development of
35 | standards & reference implementations demands a high-level of rigor, adversarial
36 | thinking, thorough testing and risk-minimization. Any bug may cost users real
37 | money. That being said, we deeply welcome people contributing for the first time
38 | to an open source project or pick up Rust while contributing. Don't be shy,
39 | you'll learn.
40 |
41 | Communications Channels
42 | -----------------------
43 | Communication about LNP/BP standards & implementations happens primarily
44 | on #lnp-pb IRC chat on Freenode with the logs available at
45 |
46 |
47 | Discussion about code base improvements happens in GitHub issues and on pull
48 | requests.
49 |
50 | Major projects are tracked [here](https://github.com/orgs/LNP-BP/projects).
51 | Project roadmap is tracked in each repository GitHub milestones.
52 |
53 | Asking Questions
54 | ----------------
55 | > **Note:** Please don't file an issue to ask a question. Each repository - or
56 | > GitHub organization has a "Discussions" with Q&A section; please post your
57 | > questions there. You'll get faster results by using this channel.
58 |
59 | Alternatively, we have a dedicated developer channel on IRC, #lnp-bp@libera.chat
60 | where you may get helpful advice if you have questions.
61 |
62 | Contribution Workflow
63 | ---------------------
64 | The codebase is maintained using the "contributor workflow" where everyone
65 | without exception contributes patch proposals using "pull requests". This
66 | facilitates social contribution, easy testing and peer review.
67 |
68 | To contribute a patch, the workflow is a as follows:
69 |
70 | 1. Fork Repository
71 | 2. Create topic branch
72 | 3. Commit patches
73 |
74 | In general commits should be atomic and diffs should be easy to read. For this
75 | reason do not mix any formatting fixes or code moves with actual code changes.
76 | Further, each commit, individually, should compile and pass tests, in order to
77 | ensure git bisect and other automated tools function properly.
78 |
79 | When adding a new feature thought must be given to the long term technical debt.
80 | Every new features should be covered by unit tests.
81 |
82 | When refactoring, structure your PR to make it easy to review and don't hesitate
83 | to split it into multiple small, focused PRs.
84 |
85 | The Minimal Supported Rust Version is nightly for the period of active
86 | development; it is enforced by our Travis. Later we plan to fix to some specific
87 | Rust version after the initial library release.
88 |
89 | Commits should cover both the issue fixed and the solution's rationale.
90 | These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in
91 | mind.
92 |
93 | To facilitate communication with other contributors, the project is making use
94 | of GitHub's "assignee" field. First check that no one is assigned and then
95 | comment suggesting that you're working on it. If someone is already assigned,
96 | don't hesitate to ask if the assigned party or previous commenters are still
97 | working on it if it has been awhile.
98 |
99 | ### Preparing PRs
100 |
101 | The main library development happens in the `master` branch. This branch must
102 | always compile without errors (using Travis CI). All external contributions are
103 | made within PRs into this branch.
104 |
105 | Prerequisites that a PR must satisfy for merging into the `master` branch:
106 | * the tip of any PR branch must compile and pass unit tests with no errors, with
107 | every feature combination (including compiling the fuzztests) on MSRV, stable
108 | and nightly compilers (this is partially automated with CI, so the rule
109 | is that we will not accept commits which do not pass GitHub CI);
110 | * contain all necessary tests for the introduced functional (either as a part of
111 | commits, or, more preferably, as separate commits, so that it's easy to
112 | reorder them during review and check that the new tests fail without the new
113 | code);
114 | * contain all inline docs for newly introduced API and pass doc tests;
115 | * be based on the recent `master` tip from the original repository at.
116 |
117 | NB: reviewers may run more complex test/CI scripts, thus, satisfying all the
118 | requirements above is just a preliminary, but not necessary sufficient step for
119 | getting the PR accepted as a valid candidate PR for the `master` branch.
120 |
121 | Additionally, to the `master` branch some repositories may have `develop` branch
122 | for any experimental developments. This branch may not compile and should not be
123 | used by any projects depending on the library.
124 |
125 | ### Peer review
126 |
127 | Anyone may participate in peer review which is expressed by comments in the pull
128 | request. Typically reviewers will review the code for obvious errors, as well as
129 | test out the patch set and opine on the technical merits of the patch. PR should
130 | be reviewed first on the conceptual level before focusing on code style or
131 | grammar fixes.
132 |
133 | Coding Conventions
134 | ------------------
135 | Our CI enforces [clippy's](https://github.com/rust-lang/rust-clippy)
136 | [default linting](https://rust-lang.github.io/rust-clippy/rust-1.52.0/index.html)
137 | and [rustfmt](https://github.com/rust-lang/rustfmt) formatting defined by rules
138 | in [.rustfmt.toml](./.rustfmt.toml). The linter should be run with current
139 | stable rust compiler, while formatter requires nightly version due to the use of
140 | unstable formatting parameters.
141 |
142 | If you use rustup, to lint locally you may run the following instructions:
143 |
144 | ```console
145 | rustup component add clippy
146 | rustup component add fmt
147 | cargo +stable clippy --workspace --all-features
148 | cargo +nightly fmt --all
149 | ```
150 |
151 | Security
152 | --------
153 | Security is the primary focus of LNP/BP libraries; disclosure of security
154 | vulnerabilities helps prevent user loss of funds. If you believe a vulnerability
155 | may affect other implementations, please inform them. Guidelines for a
156 | responsible disclosure can be found in [SECURITY.md](./SECURITY.md) file in the
157 | project root.
158 |
159 | Note that some of LNP/BP projects are currently considered "pre-production".
160 | Such projects can be distinguished by the absence of `SECURITY.md`. In such
161 | cases there are no special handling of security issues; please simply open
162 | an issue on GitHub.
163 |
164 | Testing
165 | -------
166 | Related to the security aspect, LNP/BP developers take testing very seriously.
167 | Due to the modular nature of the project, writing new functional tests is easy
168 | and good test coverage of the codebase is an important goal.
169 |
170 | Fuzzing is heavily encouraged: feel free to add related material under `fuzz/`
171 |
172 | Mutation testing is planned; any contribution there would be warmly welcomed.
173 |
174 | Going further
175 | -------------
176 | You may be interested in Jon Atack guide on
177 | [How to review Bitcoin Core PRs][Review] and [How to make Bitcoin Core PRs][PR].
178 | While there are differences between the projects in terms of context and
179 | maturity, many of the suggestions offered apply to this project.
180 |
181 | Overall, have fun :)
182 |
183 | [Review]: https://github.com/jonatack/bitcoin-development/blob/master/how-to-review-bitcoin-core-prs.md
184 | [PR]: https://github.com/jonatack/bitcoin-development/blob/master/how-to-make-bitcoin-core-prs.md
185 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [".", "slip132", "descriptors", "hd", "psbt", "onchain"]
3 | default-members = ["."]
4 | exclude = ["contrib", "libbitcoin"]
5 |
6 | [workspace.package]
7 | version = "0.10.2"
8 | license = "Apache-2.0"
9 | authors = ["Dr. Maxim Orlovsky "]
10 | repository = "https://github.com/BP-WG/descriptor-wallet"
11 | homepage = "https://lnp-bp.org"
12 | categories = ["cryptography::cryptocurrencies", "encoding", "parsing"]
13 | readme = "README.md"
14 | edition = "2021"
15 | rust-version = "1.70.0" # due to clap
16 |
17 | [workspace.dependencies]
18 | amplify = "3.14.2"
19 | strict_encoding = "0.9.0"
20 | secp256k1 = { version = "0.24.3", features = ["global-context"] }
21 | bitcoin = "0.29.2"
22 | bitcoin_scripts = "0.10.0"
23 | bitcoin_blockchain = "0.10.0"
24 | bitcoin_hd = { version = "0.10.2", path = "./hd" }
25 | bitcoin_onchain = { version = "0.10.2", path = "./onchain" }
26 | descriptors = { version = "0.10.2", path = "./descriptors", default-features = false }
27 | psbt = { version = "0.10.2", path = "./psbt", default-features = false }
28 | slip132 = { version = "0.10.0", path = "./slip132" }
29 | miniscript_crate = { package = "miniscript", version = "9.0.1" }
30 | chrono = "0.4.19"
31 | clap = { version = "4.1.13", features = ["derive"] }
32 |
33 | [package]
34 | name = "descriptor-wallet"
35 | version = { workspace = true }
36 | license = { workspace = true }
37 | authors = { workspace = true }
38 | description = "Libraries and command line tool for building descriptor-based bitcoin wallets"
39 | repository = { workspace = true }
40 | homepage = { workspace = true }
41 | keywords = ["bitcoin", "wallet", "cryptocurrency", "descriptor", "miniscript"]
42 | categories = { workspace = true }
43 | readme = { workspace = true }
44 | edition = { workspace = true }
45 | rust-version = { workspace = true }
46 | exclude = [".github", "contrib", "slip132", "libbitcoin", "descriptors", "scripts", "hd", "psbt"]
47 |
48 | [lib]
49 | name = "wallet"
50 | path = "src/lib.rs"
51 | crate-type = ["rlib", "staticlib"]
52 |
53 | [[bin]]
54 | name = "btc-hot"
55 | required-features = ["hot", "cli"]
56 |
57 | [[bin]]
58 | name = "btc-cold"
59 | required-features = ["cli"]
60 |
61 | [[bin]]
62 | name = "btc-expl"
63 | required-features = ["cli", "compiler"]
64 |
65 | [dependencies]
66 | amplify = { workspace = true }
67 | strict_encoding_crate = { package = "strict_encoding", version = "0.9.0", features = ["bitcoin", "derive"], optional = true }
68 | bitcoin = { workspace = true }
69 | bitcoin_scripts = { workspace = true }
70 | bitcoin_blockchain = { workspace = true }
71 | bitcoin_hd = { workspace = true }
72 | bitcoin_onchain = { workspace = true }
73 | descriptors = { workspace = true }
74 | psbt = { workspace = true }
75 | slip132 = { workspace = true }
76 | miniscript_crate = { workspace = true, optional = true }
77 | electrum-client = { version = "0.14.0", optional = true }
78 | serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true }
79 | serde_with = { version = "2.3", features = ["hex"], optional = true }
80 | serde_yaml = { version = "0.9", optional = true }
81 | chrono = { workspace = true }
82 | clap = { workspace = true, optional = true }
83 | bip39 = { version = "2.0.0", optional = true }
84 | aes = { version = "0.8.2", optional = true }
85 | rpassword = { version = "7.2.0", optional = true }
86 | colored = { version = "2", optional = true }
87 |
88 | [dev-dependencies]
89 | bitcoin = { version = "0.29.2", features = ["rand"] }
90 |
91 | [features]
92 | default = []
93 | all = [
94 | "mobile",
95 | "miniscript",
96 | "electrum",
97 | "strict_encoding",
98 | "keygen",
99 | "construct",
100 | "compiler",
101 | "sign",
102 | "hot",
103 | "cli",
104 | "serde",
105 | ]
106 | mobile = ["miniscript", "compiler", "electrum", "strict_encoding", "hot", "construct"]
107 | miniscript = [
108 | "strict_encoding_crate/miniscript",
109 | "bitcoin_hd/miniscript",
110 | "bitcoin_onchain/miniscript_descriptors",
111 | "descriptors/miniscript",
112 | "psbt/miniscript",
113 | ]
114 | compiler = ["miniscript", "miniscript_crate/compiler"]
115 | electrum = [
116 | "electrum-client",
117 | "bitcoin_onchain/electrum"
118 | ]
119 | strict_encoding = [
120 | "slip132/strict_encoding"
121 | ]
122 | sign = ["psbt/sign"]
123 | construct = ["psbt/construct"]
124 | hot = [
125 | "keygen",
126 | "bip39",
127 | "aes",
128 | "rpassword",
129 | "sign"
130 | ]
131 | cli = [
132 | "electrum",
133 | "construct",
134 | "miniscript",
135 | "miniscript_crate",
136 | "strict_encoding",
137 | "strict_encoding_crate",
138 | "serde",
139 | "colored",
140 | "clap",
141 | "bitcoin_hd/clap",
142 | "serde_yaml",
143 | "bitcoin/base64"
144 | ]
145 | keygen = ["bitcoin/rand", "amplify/rand", "descriptors/rand"]
146 | serde = [
147 | "slip132/serde",
148 | "bitcoin_onchain/serde",
149 | "bitcoin_hd/serde",
150 | "psbt/serde",
151 | "descriptors/serde"
152 | ]
153 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # This image uses cargo-chef to build the application in order to compile
2 | # the dependencies apart from the main application. This allows the compiled
3 | # dependencies to be cached in the Docker layer and greatly reduce the
4 | # build time when there isn't any dependency changes.
5 | #
6 | # https://github.com/LukeMathWalker/cargo-chef
7 |
8 | ARG SRC_DIR=/usr/local/src/bp-descriptor-wallet
9 | ARG BUILDER_DIR=/srv/bp-descriptor-wallet
10 |
11 | # Base image
12 | FROM rust:1.59.0-slim-bullseye as chef
13 |
14 | ARG SRC_DIR
15 | ARG BUILDER_DIR
16 |
17 | RUN rustup default stable
18 | RUN rustup update
19 | RUN cargo install cargo-chef --locked
20 |
21 | WORKDIR $SRC_DIR
22 |
23 | # Cargo chef step that analyzes the project to determine the minimum subset of
24 | # files (Cargo.lock and Cargo.toml manifests) required to build it and cache
25 | # dependencies
26 | FROM chef AS planner
27 |
28 | COPY . .
29 | RUN cargo chef prepare --recipe-path recipe.json
30 |
31 | FROM chef AS builder
32 |
33 | ARG SRC_DIR
34 | ARG BUILDER_DIR
35 |
36 | COPY --from=planner "${SRC_DIR}/recipe.json" recipe.json
37 |
38 | # Build dependencies - this is the caching Docker layer
39 | RUN cargo chef cook --release --recipe-path recipe.json --target-dir "${BUILDER_DIR}"
40 |
41 | # Copy all files and build application
42 | COPY . .
43 | RUN cargo build --release --target-dir "${BUILDER_DIR}" --bins --all-features
44 |
45 | # Final image with binaries
46 | FROM debian:bullseye-slim as final
47 |
48 | ARG BUILDER_DIR
49 | ARG BIN_DIR=/usr/local/bin
50 | ARG DATA_DIR=/var/lib/bp-descriptor-wallet
51 | ARG USER=bp
52 |
53 | RUN adduser --home "${DATA_DIR}" --shell /bin/bash --disabled-login \
54 | --gecos "${USER} user" ${USER}
55 |
56 | COPY --from=builder --chown=${USER}:${USER} \
57 | "${BUILDER_DIR}/release" "${BIN_DIR}"
58 |
59 | WORKDIR "${BIN_DIR}"
60 |
61 | # Remove build artifacts in order to keep only the binaries
62 | RUN rm -rf */ *.d .[^.] .??*
63 |
64 | USER ${USER}
65 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 | Copyright (c) 2020-2022 LNP/BP Standards Association
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Descriptor wallet library
2 |
3 | 
4 | 
5 | 
6 | [](https://codecov.io/gh/BP-WG/descriptor-wallet)
7 |
8 | [](https://crates.io/crates/descriptor-wallet)
9 | [](https://docs.rs/descriptor-wallet)
10 | [](https://github.com/rust-secure-code/safety-dance/)
11 | [](./LICENSE)
12 |
13 | Library for building descriptor-based bitcoin wallets. Everything a modern
14 | cold and hot bitcoin wallet needs, but which is not (yet) a part of
15 | [rust-bitcoin](https://crates.io/bitcoin) library.
16 |
17 | The library clearly separates parts requiring access to private keys from
18 | those which should operate never touching them. It is advised that wallets
19 | should be designed in a way assuming zero private key access for all of their
20 | operations aside from transaction signing; this part must be separated into
21 | other repository/library and be strictly controlled. One may look after
22 | command-line `btc-hot` and `btc-cold` wallets in [`bin`](bin) directory for an
23 | example of how this can be done.
24 |
25 | Library provides
26 |
27 | - efficient manipulations with BIP-32 derivation paths, separating derivations
28 | requiring private key access from those, which will always operate without;
29 | - miniscript & classical bitcoin descriptors;
30 | - PSBT constructor using input descriptors, which allow to specify custom
31 | information about RBFs, previous public key P2C tweaks and custom hash types
32 | on a per-input basis;
33 | - PSBT signer, supporting RBFs, relative and absolute timelocks, all sighash
34 | types, complex scripts, including witness- and taproot-based;
35 | - script templates allowing embedding extended pubkeys into bitcoin script
36 | assembly;
37 | - lexicographic ordering of transaction & PSBT inputs & oututs;
38 | - script type system;
39 | - helper types for working with hash-lock contracts;
40 | - PSBT utility functions (retrieving previous output, computing fee);
41 | - transaction resolver API on top of Electrum Server API for convenience
42 | computation of already-mined transaction fees etc;
43 | - support for SLIP-32/132 extended pubkey types (`ypub`, `zprv` etc).
44 |
45 | 
46 |
47 | ## Command-line wallets
48 |
49 | One may install command-line wallets with the following command (requires
50 | rust compiler and `rustup` tools to be already installed on a system):
51 |
52 | ```console
53 | $ rustup default stable
54 | $ rustup update
55 | $ git clone https://github.com/BP-WG/descriptor-wallet
56 | $ cd descriptor-wallet
57 | $ cargo install --path . --locked --all-features
58 | ```
59 |
60 | This will add `btc-hot` and `btc-cold` commands to the system.
61 |
62 | [bin]: https://github.com/BP-WG/descriptor-wallet/tree/master/src/bin
63 |
64 | ### Install with Docker
65 |
66 | #### Build
67 |
68 | Clone the repository and checkout to the desired version (here `v0.8.0`):
69 |
70 | ```console
71 | $ git clone https://github.com/BP-WG/descriptor-wallet
72 | $ cd descriptor-wallet
73 | $ git checkout v0.8.0
74 | ```
75 |
76 | Build and tag the Docker image:
77 |
78 | ```console
79 | $ docker build -t descriptor-wallet:v0.8.0 .
80 | ```
81 |
82 | #### Usage
83 |
84 | ```console
85 | $ docker run descriptor-wallet:v0.8.0 btc-hot --help
86 | $ docker run descriptor-wallet:v0.8.0 btc-cold --help
87 | ```
88 |
89 | #### Examples with files
90 |
91 | ```console
92 | $ docker run -v $PWD/data:/data descriptor-wallet:v0.8.0 btc-hot seed /data/testnet.seed
93 | $ docker run -v $PWD/data:/data descriptor-wallet:v0.8.0 btc-hot derive --testnet /data/testnet.seed /data/testnet
94 | ```
95 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | require_ci_to_pass: no
3 |
4 | coverage:
5 | precision: 1
6 | round: nearest
7 | range: "0...95"
8 | # TODO: Update codecov default requirements after v1.0 release
9 | status:
10 | project:
11 | default:
12 | target: 0%
13 | threshold: 1%
14 | patch:
15 | default:
16 | target: 0%
17 | threshold: 1%
--------------------------------------------------------------------------------
/descriptors/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "descriptors"
3 | version = { workspace = true }
4 | license = { workspace = true }
5 | authors = { workspace = true }
6 | description = "Bitcoin descriptors library (part of descriptor-wallet)"
7 | repository = { workspace = true }
8 | homepage = { workspace = true }
9 | keywords = ["bitcoin", "wallet", "cryptocurrency", "descriptor", "bip32"]
10 | categories = { workspace = true }
11 | readme = { workspace = true }
12 | edition = { workspace = true }
13 | rust-version = { workspace = true }
14 | exclude = []
15 |
16 | [dependencies]
17 | amplify = { workspace = true }
18 | strict_encoding = { workspace = true }
19 | bitcoin = { workspace = true }
20 | bitcoin_scripts = { workspace = true }
21 | bitcoin_blockchain = { workspace = true }
22 | bitcoin_hd = { workspace = true }
23 | miniscript_crate = { workspace = true, features = ["compiler"], optional = true }
24 | chrono = { workspace = true }
25 | serde_crate = { package = "serde", version = "1", optional = true }
26 | serde_with = { version = "2.3", features = ["hex"], optional = true }
27 |
28 | [features]
29 | all = [
30 | "rand",
31 | "miniscript",
32 | "serde"
33 | ]
34 | default = []
35 | rand = [
36 | "bitcoin/rand",
37 | "amplify/rand"
38 | ]
39 | miniscript = [
40 | "miniscript_crate",
41 | "bitcoin_hd/miniscript"
42 | ]
43 | serde = [
44 | "serde_crate",
45 | "serde_with",
46 | "bitcoin_scripts/serde"
47 | ]
48 |
--------------------------------------------------------------------------------
/descriptors/src/deduction.rs:
--------------------------------------------------------------------------------
1 | // Wallet-level libraries for bitcoin protocol by LNP/BP Association
2 | //
3 | // Written in 2020-2022 by
4 | // Dr. Maxim Orlovsky
5 | //
6 | // This software is distributed without any warranty.
7 | //
8 | // You should have received a copy of the Apache-2.0 License
9 | // along with this software.
10 | // If not, see .
11 |
12 | use bitcoin::util::address::WitnessVersion;
13 | use bitcoin_scripts::{PubkeyScript, RedeemScript};
14 |
15 | use crate::CompositeDescrType;
16 |
17 | /// Errors that happens during deduction process
18 | #[derive(
19 | Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error
20 | )]
21 | #[display(doc_comments)]
22 | pub enum DeductionError {
23 | /// input spends non-taproot witness version 1
24 | NonTaprootV1,
25 |
26 | /// input spends future witness version {0}
27 | UnsupportedWitnessVersion(WitnessVersion),
28 |
29 | /// input spends P2SH output, but no `redeedScript` is present in the PSBT
30 | /// input data
31 | P2shWithoutRedeemScript,
32 |
33 | /// redeem script is invalid in context of nested (legacy) P2W*-in-P2SH
34 | /// spending
35 | InvalidRedeemScript,
36 | }
37 |
38 | impl CompositeDescrType {
39 | /// Deduction of a descriptor type from a `scriptPubkey` data and data
40 | /// inside redeem script and witness scripts.
41 | ///
42 | /// # Errors
43 | ///
44 | /// The function may [`DeductionError`]
45 | ///
46 | /// # Panics
47 | ///
48 | /// Panics if PSBT integrity is broken and current input does not have an
49 | /// associated previous output data or these data are incorrect.
50 | pub fn deduce(
51 | spk: &PubkeyScript,
52 | redeem_script: Option<&RedeemScript>,
53 | witness_script_known: bool,
54 | ) -> Result {
55 | let witness_version = spk.witness_version();
56 | match (spk, witness_version) {
57 | (spk, _) if spk.is_p2pk() => Ok(CompositeDescrType::Pk),
58 | (spk, _) if spk.is_p2pkh() => Ok(CompositeDescrType::Pkh),
59 | (spk, _) if spk.is_v0_p2wpkh() => Ok(CompositeDescrType::Wpkh),
60 | (spk, _) if spk.is_v0_p2wsh() => Ok(CompositeDescrType::Wsh),
61 | (spk, _) if spk.is_v1_p2tr() => Ok(CompositeDescrType::Tr),
62 | (spk, _) if spk.is_p2sh() => {
63 | let redeem_script = if let Some(redeem_script) = redeem_script {
64 | redeem_script
65 | } else {
66 | return Err(DeductionError::P2shWithoutRedeemScript);
67 | };
68 | if witness_script_known {
69 | if redeem_script.is_v0_p2wpkh() {
70 | Ok(CompositeDescrType::ShWpkh)
71 | } else if redeem_script.is_v0_p2wsh() {
72 | Ok(CompositeDescrType::ShWsh)
73 | } else {
74 | Err(DeductionError::InvalidRedeemScript)
75 | }
76 | } else {
77 | Ok(CompositeDescrType::Sh)
78 | }
79 | }
80 | (_, Some(WitnessVersion::V1)) => Err(DeductionError::NonTaprootV1),
81 | (_, Some(version)) => Err(DeductionError::UnsupportedWitnessVersion(version)),
82 | (_, None) => Ok(CompositeDescrType::Bare),
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/descriptors/src/derive.rs:
--------------------------------------------------------------------------------
1 | // Wallet-level libraries for bitcoin protocol by LNP/BP Association
2 | //
3 | // Written in 2020-2022 by
4 | // Dr. Maxim Orlovsky
5 | //
6 | // This software is distributed without any warranty.
7 | //
8 | // You should have received a copy of the Apache-2.0 License
9 | // along with this software.
10 | // If not, see .
11 |
12 | use bitcoin::secp256k1::{Secp256k1, Verification};
13 | use bitcoin::{Network, Script};
14 | #[cfg(feature = "miniscript")]
15 | use bitcoin_hd::{DerivationAccount, DerivePatternError};
16 | use bitcoin_hd::{DeriveError, UnhardenedIndex};
17 | use bitcoin_scripts::address::AddressCompat;
18 |
19 | #[cfg(not(feature = "miniscript"))]
20 | pub mod miniscript {
21 | #[derive(
22 | Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error
23 | )]
24 | #[display(Debug)]
25 | pub enum Error {}
26 | }
27 |
28 | /// Methods for deriving from output descriptor.
29 | pub trait DeriveDescriptor {
30 | /// Generated descriptor type as an output from
31 | /// [`DeriveDescriptor::derive_descriptor`].
32 | type Output;
33 |
34 | /// Translates descriptor to a specifically-derived form.
35 | fn derive_descriptor(
36 | &self,
37 | secp: &Secp256k1,
38 | pat: impl AsRef<[UnhardenedIndex]>,
39 | ) -> Result;
40 | }
41 |
42 | /// Standard methods which should be supported by descriptors of different
43 | /// sorts.
44 | pub trait Descriptor {
45 | /// Checks sanity of the output descriptor (see [`DeriveError`] for the list
46 | /// of possible inconsistencies).
47 | fn check_sanity(&self) -> Result<(), DeriveError>;
48 |
49 | /// Measures length of the derivation wildcard pattern accross all keys
50 | /// participating descriptor
51 | fn derive_pattern_len(&self) -> Result;
52 |
53 | /// Detects bitcoin network which should be used with the provided
54 | /// descriptor
55 | fn network(&self, regtest: bool) -> Result;
56 |
57 | /// Generates address from the descriptor for specific derive pattern
58 | fn address(
59 | &self,
60 | secp: &Secp256k1,
61 | pat: impl AsRef<[UnhardenedIndex]>,
62 | regtest: bool,
63 | ) -> Result;
64 |
65 | /// Creates scriptPubkey for specific derive pattern in pre-taproot
66 | /// descriptors
67 | fn script_pubkey_pretr(
68 | &self,
69 | secp: &Secp256k1,
70 | pat: impl AsRef<[UnhardenedIndex]>,
71 | ) -> Result