diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 97c7dedf..d309edc6 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,3 @@
# These are supported funding model platforms
-github: [dr-orlovsky]
+github: [lnp-bp, dr-orlovsky]
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1a91fee3..e784120e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -10,13 +10,26 @@ env:
CARGO_TERM_COLOR: always
jobs:
+ default:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install rust stable
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: stable
+ override: true
+ - name: Default build
+ uses: actions-rs/cargo@v1
+ with:
+ command: check
+ args: --workspace
features:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
feature:
- - async
- serde
steps:
- uses: actions/checkout@v2
@@ -40,33 +53,25 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ ubuntu-20.04, ubuntu-latest, macos-latest, windows-2019, windows-latest ]
+ os: [ ubuntu-20.04, ubuntu-22.04, macos-11, macos-12, windows-2019, windows-2022 ]
steps:
- uses: actions/checkout@v2
- - name: Install macos dependencies
- if: startsWith(matrix.os, 'macos')
- run: brew install pkg-config
- name: Install rust stable
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- - name: Build with no features
+ - name: Build with all features
uses: actions-rs/cargo@v1
with:
command: check
- args: --no-default-features
- - name: Build with defaults
- uses: actions-rs/cargo@v1
- with:
- command: check
- args: --all-features
+ args: --workspace --all-targets --all-features
toolchains:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
- toolchain: [ nightly, beta, stable, 1.59.0 ]
+ toolchain: [ nightly, beta, stable, 1.66.0 ]
steps:
- uses: actions/checkout@v2
- name: Install rust ${{ matrix.toolchain }}
@@ -79,26 +84,3 @@ jobs:
with:
command: check
args: --workspace --all-targets --all-features
- dependency:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Install latest stable
- uses: actions-rs/toolchain@v1
- with:
- toolchain: stable
- override: true
- - name: Create dependency
- run: |
- cargo new dep_test
- cp test/depCargo.toml dep_test/Cargo.toml
- cd dep_test
- - name: Build dependency
- uses: actions-rs/cargo@v1
- with:
- command: check
- args: --verbose
- - name: Clean up
- run: |
- cd ..
- rm -rf dep_test
diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml
index 4ba22c88..9fd96f0e 100644
--- a/.github/workflows/codecov.yml
+++ b/.github/workflows/codecov.yml
@@ -26,7 +26,7 @@ jobs:
args: --workspace --all-features --no-fail-fast
env:
CARGO_INCREMENTAL: '0'
- RUSTFLAGS: '--cfg codecov -Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
+ RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
- id: coverage
name: Generate coverage
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index c37f2246..b8979f05 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -39,7 +39,7 @@ jobs:
name: Clippy
with:
command: clippy
- args: --workspace --all-features
+ args: --workspace --all-features --all-targets
doc:
runs-on: ubuntu-latest
steps:
@@ -51,7 +51,7 @@ jobs:
override: true
components: rust-docs
- uses: actions-rs/cargo@v1
- name: Clippy
+ name: Doc
with:
command: doc
args: --workspace --all-features
diff --git a/.rustfmt.toml b/.rustfmt.toml
index 58fbbb99..952a2846 100644
--- a/.rustfmt.toml
+++ b/.rustfmt.toml
@@ -1,14 +1,27 @@
-max_width = 80
+edition = "2021"
+version = "Two"
+
+max_width = 100
+array_width = 100
+attr_fn_like_width = 100
+fn_call_width = 100
+
format_code_in_doc_comments = true
fn_single_line = true
format_macro_matchers = true
+format_macro_bodues = true
format_strings = true
merge_derives = false
-imports_granularity = "Module"
overflow_delimited_expr = true
-group_imports = "StdExternalCrate"
+reorder_modules = false
use_field_init_shorthand = true
use_try_shorthand = true
wrap_comments = true
-comment_width = 80
+where_single_line = true
unstable_features = true
+empty_item_single_line = true
+
+binop_separator = "Back"
+
+imports_granularity = "Module"
+group_imports = "StdExternalCrate"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 51d8aa01..66acff98 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,21 +1,12 @@
-Contributing to LNP/BP projects
-===============================
+Contributing guidelines
+=======================
-:+1::tada:
-First and foremost, thanks for taking the time to contribute!
-:tada::+1:
-
-The following is a set of guidelines for contributing to [LNP/BP Standards
-Association](https://lnp-bp.org) projects, which are hosted in the GitHub
-organizations listed in [readme](https://github.com/LNP-BP#Working-groups).
-These are mostly guidelines, not rules. Use your best judgment, and feel free to
-propose changes to this document in a pull request.
+Contributions are very welcome. When contributing code, please follow these
+simple guidelines.
#### Table Of Contents
-- [General](#general)
-- [Communication channels](#communication-channels)
-- [Asking questions](#asking-questions)
- [Contribution workflow](#contribution-workflow)
+ * [Proposing changes](#proposing-changes)
* [Preparing PRs](#preparing-prs)
* [Peer review](#peer-review)
- [Coding conventions](#coding-conventions)
@@ -23,41 +14,22 @@ propose changes to this document in a pull request.
- [Testing](#testing)
- [Going further](#going-further)
+Overview
+--------
-General
--------
-The LNP/BP projects operate an open contributor model where anyone is welcome to
-contribute towards development in the form of peer review, documentation,
-testing and patches.
-
-Anyone is invited to contribute without regard to technical experience,
-"expertise", OSS experience, age, or other concern. However, the development of
-standards & reference implementations demands a high-level of rigor, adversarial
-thinking, thorough testing and risk-minimization. Any bug may cost users real
-money. That being said, we deeply welcome people contributing for the first time
-to an open source project or pick up Rust while contributing. Don't be shy,
-you'll learn.
-
-Communications Channels
------------------------
-Communication about LNP/BP standards & implementations happens primarily
-on #lnp-pb IRC chat on Freenode with the logs available at
-
-
-Discussion about code base improvements happens in GitHub issues and on pull
-requests.
-
-Major projects are tracked [here](https://github.com/orgs/LNP-BP/projects).
-Project roadmap is tracked in each repository GitHub milestones.
+* Before adding any code dependencies, check with the maintainers if this is okay.
+* Write properly formatted comments: they should be English sentences, eg:
-Asking Questions
-----------------
-> **Note:** Please don't file an issue to ask a question. Each repository - or
-> GitHub organization has a "Discussions" with Q&A section; please post your
-> questions there. You'll get faster results by using this channel.
+ // Return the current UNIX time.
-Alternatively, we have a dedicated developer channel on IRC, #lnp-bp@libera.chat
-where you may get helpful advice if you have questions.
+* Read the DCO and make sure all commits are signed off, using `git commit -s`.
+* Follow the guidelines when proposing code changes (see below).
+* Write properly formatted git commits (see below).
+* Run the tests with `cargo test --workspace --all-features`.
+* Make sure you run `rustfmt` on your code (see below details).
+* Please don't file an issue to ask a question. Each repository - or
+ GitHub organization has a "Discussions" with Q&A section; please post your
+ questions there. You'll get faster results by using this channel.
Contribution Workflow
---------------------
@@ -67,39 +39,49 @@ facilitates social contribution, easy testing and peer review.
To contribute a patch, the workflow is a as follows:
- 1. Fork Repository
- 2. Create topic branch
- 3. Commit patches
+1. Fork Repository
+2. Create topic branch
+3. Commit patches
-In general commits should be atomic and diffs should be easy to read. For this
-reason do not mix any formatting fixes or code moves with actual code changes.
-Further, each commit, individually, should compile and pass tests, in order to
+In general commits should be atomic and diffs should be easy to read. For this
+reason do not mix any formatting fixes or code moves with actual code changes.
+Further, each commit, individually, should compile and pass tests, in order to
ensure git bisect and other automated tools function properly.
-When adding a new feature thought must be given to the long term technical debt.
+When adding a new feature thought must be given to the long term technical debt.
Every new features should be covered by unit tests.
When refactoring, structure your PR to make it easy to review and don't hesitate
to split it into multiple small, focused PRs.
-The Minimal Supported Rust Version is nightly for the period of active
-development; it is enforced by our Travis. Later we plan to fix to some specific
-Rust version after the initial library release.
-
Commits should cover both the issue fixed and the solution's rationale.
-These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in
+These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in
mind.
-To facilitate communication with other contributors, the project is making use
-of GitHub's "assignee" field. First check that no one is assigned and then
-comment suggesting that you're working on it. If someone is already assigned,
-don't hesitate to ask if the assigned party or previous commenters are still
+To facilitate communication with other contributors, the project is making use
+of GitHub's "assignee" field. First check that no one is assigned and then
+comment suggesting that you're working on it. If someone is already assigned,
+don't hesitate to ask if the assigned party or previous commenters are still
working on it if it has been awhile.
+### Proposing changes
+
+When proposing changes via a pull-request or patch:
+
+* Isolate changes in separate commits to make the review process easier.
+* Don't make unrelated changes, unless it happens to be an obvious improvement to
+ code you are touching anyway ("boyscout rule").
+* Rebase on `master` when needed.
+* Keep your changesets small, specific and uncontroversial, so that they can be
+ merged more quickly.
+* If the change is substantial or requires re-architecting certain parts of the
+ codebase, write a proposal in English first, and get consensus on that before
+ proposing the code changes.
+
### Preparing PRs
-The main library development happens in the `master` branch. This branch must
-always compile without errors (using Travis CI). All external contributions are
+The main library development happens in the `master` branch. This branch must
+always compile without errors (using Travis CI). All external contributions are
made within PRs into this branch.
Prerequisites that a PR must satisfy for merging into the `master` branch:
@@ -122,20 +104,60 @@ Additionally, to the `master` branch some repositories may have `develop` branch
for any experimental developments. This branch may not compile and should not be
used by any projects depending on the library.
+### Writing Git commit messages
+
+A properly formed git commit subject line should always be able to complete the
+following sentence:
+
+ If applied, this commit will _____
+
+In addition, it should be capitalized and *must not* include a period.
+
+For example, the following message is well formed:
+
+ Add support for .gif files
+
+While these ones are **not**: `Adding support for .gif files`,
+`Added support for .gif files`.
+
+When it comes to formatting, here's a model git commit message[1]:
+
+ Capitalized, short (50 chars or less) summary
+
+ More detailed explanatory text, if necessary. Wrap it to about 72
+ characters or so. In some contexts, the first line is treated as the
+ subject of an email and the rest of the text as the body. The blank
+ line separating the summary from the body is critical (unless you omit
+ the body entirely); tools like rebase can get confused if you run the
+ two together.
+
+ Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
+ or "Fixes bug." This convention matches up with commit messages generated
+ by commands like git merge and git revert.
+
+ Further paragraphs come after blank lines.
+
+ - Bullet points are okay, too.
+
+ - Typically a hyphen or asterisk is used for the bullet, followed by a
+ single space, with blank lines in between, but conventions vary here.
+
+ - Use a hanging indent.
+
### Peer review
Anyone may participate in peer review which is expressed by comments in the pull
request. Typically reviewers will review the code for obvious errors, as well as
test out the patch set and opine on the technical merits of the patch. PR should
-be reviewed first on the conceptual level before focusing on code style or
+be reviewed first on the conceptual level before focusing on code style or
grammar fixes.
Coding Conventions
------------------
-Our CI enforces [clippy's](https://github.com/rust-lang/rust-clippy)
+Our CI enforces [clippy's](https://github.com/rust-lang/rust-clippy)
[default linting](https://rust-lang.github.io/rust-clippy/rust-1.52.0/index.html)
and [rustfmt](https://github.com/rust-lang/rustfmt) formatting defined by rules
-in [.rustfmt.toml](./.rustfmt.toml). The linter should be run with current
+in [.rustfmt.toml](./.rustfmt.toml). The linter should be run with current
stable rust compiler, while formatter requires nightly version due to the use of
unstable formatting parameters.
@@ -150,35 +172,25 @@ cargo +nightly fmt --all
Security
--------
-Security is the primary focus of LNP/BP libraries; disclosure of security
-vulnerabilities helps prevent user loss of funds. If you believe a vulnerability
-may affect other implementations, please inform them. Guidelines for a
-responsible disclosure can be found in [SECURITY.md](./SECURITY.md) file in the
-project root.
-
-Note that some of LNP/BP projects are currently considered "pre-production".
-Such projects can be distinguished by the absence of `SECURITY.md`. In such
-cases there are no special handling of security issues; please simply open
+Responsible disclosure of security vulnerabilities helps prevent user loss of
+privacy. If you believe a vulnerability may affect other implementations, please
+inform them. Guidelines for a responsible disclosure can be found in
+[SECURITY.md](./SECURITY.md) file in the project root.
+
+Note that some of our projects are currently considered "pre-production".
+Such projects can be distinguished by the absence of `SECURITY.md`. In such
+cases there are no special handling of security issues; please simply open
an issue on GitHub.
-Testing
--------
-Related to the security aspect, LNP/BP developers take testing very seriously.
-Due to the modular nature of the project, writing new functional tests is easy
-and good test coverage of the codebase is an important goal.
-
-Fuzzing is heavily encouraged: feel free to add related material under `fuzz/`
-
-Mutation testing is planned; any contribution there would be warmly welcomed.
-
Going further
-------------
-You may be interested in Jon Atack guide on
+You may be interested in Jon Atack guide on
[How to review Bitcoin Core PRs][Review] and [How to make Bitcoin Core PRs][PR].
-While there are differences between the projects in terms of context and
+While there are differences between the projects in terms of context and
maturity, many of the suggestions offered apply to this project.
Overall, have fun :)
+[1]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[Review]: https://github.com/jonatack/bitcoin-development/blob/master/how-to-review-bitcoin-core-prs.md
[PR]: https://github.com/jonatack/bitcoin-development/blob/master/how-to-make-bitcoin-core-prs.md
diff --git a/Cargo.lock b/Cargo.lock
index 6283a940..0b764199 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,27 +4,40 @@ version = 3
[[package]]
name = "amplify"
-version = "3.13.0"
+version = "4.0.0-beta.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "116019a174e912931d5b19ca7ab6a22596d12cdb1320358fad3368f0aba135a9"
+checksum = "414f38fa6badd4440d87c4e3abb6abb2d99cce34cff3af50ad6ee83004f03716"
dependencies = [
+ "amplify_apfloat",
"amplify_derive",
"amplify_num",
- "amplify_syn",
+ "amplify_syn 1.1.6",
+ "ascii",
"serde",
"serde_json",
"serde_yaml",
"stringly_conversions",
"toml",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "amplify_apfloat"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a958199f6993a34e74b9d22b22709e5c6e527e901d7083b24f0a532445dbfc84"
+dependencies = [
+ "amplify_num",
+ "bitflags",
]
[[package]]
name = "amplify_derive"
-version = "2.11.3"
+version = "4.0.0-alpha.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c3de270e75f27a4468a7c344070109046656e85cb522141f7d40ab4b83803ac"
+checksum = "88541432753e17756ae72f8064335d2f2c048165ff4822094334d767108762ca"
dependencies = [
- "amplify_syn",
+ "amplify_syn 2.0.0-beta.1",
"proc-macro2",
"quote",
"syn",
@@ -32,9 +45,9 @@ dependencies = [
[[package]]
name = "amplify_num"
-version = "0.4.1"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f27d3d00d3d115395a7a8a4dc045feb7aa82b641e485f7e15f4e67ac16f4f56d"
+checksum = "ddce3bc63e807ea02065e8d8b702695f3d302ae4158baddff8b0ce5c73947251"
dependencies = [
"serde",
]
@@ -51,19 +64,10 @@ dependencies = [
]
[[package]]
-name = "android_system_properties"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "async-trait"
-version = "0.1.63"
+name = "amplify_syn"
+version = "2.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1"
+checksum = "5eba488aa4b78ca719aff57edfbe634efef62232110c35442cd9136c67cedf39"
dependencies = [
"proc-macro2",
"quote",
@@ -71,57 +75,48 @@ dependencies = [
]
[[package]]
-name = "atty"
-version = "0.2.14"
+name = "arrayref"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
-name = "autocfg"
-version = "1.1.0"
+name = "arrayvec"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]]
-name = "base64"
-version = "0.13.1"
+name = "ascii"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
+dependencies = [
+ "serde",
+]
[[package]]
-name = "bech32"
-version = "0.9.1"
+name = "autocfg"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "bitcoin"
-version = "0.29.2"
+name = "baid58"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3"
+checksum = "16db9f8a10cac6c74b78f8922bfb4b3eb5bbbed4734fb9fa8218af32b5e381f4"
dependencies = [
- "base64",
- "bech32",
- "bitcoin_hashes",
- "secp256k1",
- "serde",
+ "base58",
+ "blake3",
+ "mnemonic",
]
[[package]]
-name = "bitcoin_blockchain"
-version = "0.9.0"
+name = "base58"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edb38270e9c10c1858bf6c939a700ea249e7dd0e8b36e3258b55ce7c9bdd2499"
-dependencies = [
- "amplify",
- "chrono",
- "strict_encoding",
-]
+checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581"
[[package]]
name = "bitcoin_hashes"
@@ -133,99 +128,82 @@ dependencies = [
]
[[package]]
-name = "bitcoin_hd"
-version = "0.9.0"
+name = "bitflags"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aae39db6b04c44c76c50b8f8dd09799adb71ae7807a1de2efe3d127169c04160"
-dependencies = [
- "amplify",
- "bitcoin",
- "secp256k1",
- "slip132",
- "strict_encoding",
-]
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
-name = "bitcoin_onchain"
-version = "0.9.0"
+name = "blake3"
+version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e4a6744365c862b8c74cb33a21532f91f1f32f4082361fd3aab5d22c1afd482"
+checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef"
dependencies = [
- "amplify",
- "bitcoin",
- "bitcoin_hd",
- "chrono",
- "strict_encoding",
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+ "digest",
]
[[package]]
-name = "bitcoin_scripts"
-version = "0.9.0"
+name = "block-buffer"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f8b08389e5391cf8311fd4de09a340ed98b4b7c2f87c956125c22341b5d14fb"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
dependencies = [
- "amplify",
- "bitcoin",
- "secp256k1",
- "serde",
- "serde_with",
- "stability",
- "strict_encoding",
+ "generic-array",
]
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
[[package]]
name = "bp-core"
-version = "0.9.0"
+version = "0.10.0-beta.1"
dependencies = [
"amplify",
- "bitcoin",
"bp-dbc",
+ "bp-primitives",
"bp-seals",
- "clap",
- "colored",
"commit_verify",
- "electrum-client",
- "psbt",
"serde",
- "serde_with",
"single_use_seals",
"strict_encoding",
]
[[package]]
name = "bp-dbc"
-version = "0.9.0"
+version = "0.10.0-beta.1"
+dependencies = [
+ "amplify",
+ "bp-primitives",
+ "commit_verify",
+ "secp256k1",
+ "serde",
+ "strict_encoding",
+]
+
+[[package]]
+name = "bp-primitives"
+version = "0.10.0-beta.1"
dependencies = [
"amplify",
- "bitcoin",
- "bitcoin_scripts",
"commit_verify",
- "psbt",
"secp256k1",
"serde",
- "serde_with",
"strict_encoding",
]
[[package]]
name = "bp-seals"
-version = "0.9.0"
+version = "0.10.0-beta.1"
dependencies = [
"amplify",
- "async-trait",
- "bitcoin",
- "bitcoin_onchain",
+ "baid58",
"bp-dbc",
+ "bp-primitives",
"commit_verify",
- "lnpbp_bech32",
+ "rand",
"serde",
- "serde_with",
"single_use_seals",
"strict_encoding",
]
@@ -244,9 +222,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
-version = "1.0.78"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
@@ -254,216 +232,56 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-[[package]]
-name = "chrono"
-version = "0.4.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
-dependencies = [
- "iana-time-zone",
- "js-sys",
- "num-integer",
- "num-traits",
- "time",
- "wasm-bindgen",
- "winapi",
-]
-
-[[package]]
-name = "clap"
-version = "3.2.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
-dependencies = [
- "atty",
- "bitflags",
- "clap_derive",
- "clap_lex",
- "indexmap",
- "once_cell",
- "strsim",
- "termcolor",
- "textwrap",
-]
-
-[[package]]
-name = "clap_derive"
-version = "3.2.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "clap_lex"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
-dependencies = [
- "os_str_bytes",
-]
-
-[[package]]
-name = "codespan-reporting"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
-dependencies = [
- "termcolor",
- "unicode-width",
-]
-
-[[package]]
-name = "colored"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
-dependencies = [
- "atty",
- "lazy_static",
- "winapi",
-]
-
[[package]]
name = "commit_verify"
-version = "0.9.0"
+version = "0.10.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7f422e4e3f14f628b3cc3a241c0ea53b6457d100dda2980e2d7e719f1e41cf7"
+checksum = "f7ce27ce9d56cac2631f9701984dc4fd162abbd7b563d97e4440db56f7282cc9"
dependencies = [
"amplify",
"bitcoin_hashes",
"rand",
"serde",
- "serde_with",
"strict_encoding",
]
[[package]]
-name = "core-foundation-sys"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
-
-[[package]]
-name = "cxx"
-version = "1.0.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b61a7545f753a88bcbe0a70de1fcc0221e10bfc752f576754fa91e663db1622e"
-dependencies = [
- "cc",
- "cxxbridge-flags",
- "cxxbridge-macro",
- "link-cplusplus",
-]
-
-[[package]]
-name = "cxx-build"
-version = "1.0.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f464457d494b5ed6905c63b0c4704842aba319084a0a3561cdc1359536b53200"
-dependencies = [
- "cc",
- "codespan-reporting",
- "once_cell",
- "proc-macro2",
- "quote",
- "scratch",
- "syn",
-]
-
-[[package]]
-name = "cxxbridge-flags"
-version = "1.0.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43c7119ce3a3701ed81aca8410b9acf6fc399d2629d057b87e2efa4e63a3aaea"
-
-[[package]]
-name = "cxxbridge-macro"
-version = "1.0.87"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65e07508b90551e610910fa648a1878991d367064997a596135b86df30daf07e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "darling"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.13.4"
+name = "constant_time_eq"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
+checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
[[package]]
-name = "darling_macro"
-version = "0.13.4"
+name = "crypto-common"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
- "darling_core",
- "quote",
- "syn",
+ "generic-array",
+ "typenum",
]
[[package]]
-name = "electrum-client"
-version = "0.12.0"
+name = "digest"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82a232d46710f8064b7bb2029d82819fc1f5fba053687e0e3bb47cc762af24f6"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
- "bitcoin",
- "byteorder",
- "libc",
- "log",
- "rustls",
- "serde",
- "serde_json",
- "webpki",
- "webpki-roots",
- "winapi",
+ "block-buffer",
+ "crypto-common",
+ "subtle",
]
[[package]]
-name = "encoding_derive_helpers"
-version = "0.8.1"
+name = "generic-array"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8a2293d9a54744b73b753fad2e3c16295345504dc230696ee8aa5dbfd276ab4"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
- "amplify",
- "proc-macro2",
- "quote",
- "syn",
+ "typenum",
+ "version_check",
]
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
[[package]]
name = "getrandom"
version = "0.2.8"
@@ -472,7 +290,7 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
]
[[package]]
@@ -483,54 +301,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "iana-time-zone"
-version = "0.1.53"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "wasm-bindgen",
- "winapi",
-]
-
-[[package]]
-name = "iana-time-zone-haiku"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
-dependencies = [
- "cxx",
- "cxx-build",
-]
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "indexmap"
@@ -548,15 +321,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
-[[package]]
-name = "js-sys"
-version = "0.3.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
-dependencies = [
- "wasm-bindgen",
-]
-
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -569,35 +333,6 @@ version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
-[[package]]
-name = "link-cplusplus"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "linked-hash-map"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
-
-[[package]]
-name = "lnpbp_bech32"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecdbd10fe8d9d53febf413b4f8bbaa1911492597b19bfbb84a598f37062eab96"
-dependencies = [
- "amplify",
- "bech32",
- "bitcoin_hashes",
- "serde",
- "serde_with",
- "strict_encoding",
-]
-
[[package]]
name = "log"
version = "0.4.17"
@@ -608,22 +343,13 @@ dependencies = [
]
[[package]]
-name = "num-integer"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
-dependencies = [
- "autocfg",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.15"
+name = "mnemonic"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+checksum = "29fae0e4c0b155d3b019a7cbc27abe4a90e15c06814d27889ce9f5f44e2faf77"
dependencies = [
- "autocfg",
+ "byteorder",
+ "lazy_static",
]
[[package]]
@@ -632,12 +358,6 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
-[[package]]
-name = "os_str_bytes"
-version = "6.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
-
[[package]]
name = "paste"
version = "1.0.11"
@@ -650,30 +370,6 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2",
- "quote",
- "version_check",
-]
-
[[package]]
name = "proc-macro2"
version = "1.0.50"
@@ -683,22 +379,6 @@ dependencies = [
"unicode-ident",
]
-[[package]]
-name = "psbt"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e53ad01c5e6d2e9375b5594ce166a0374182562b1ec82318a7f039ed2efda759"
-dependencies = [
- "amplify",
- "bitcoin",
- "bitcoin_blockchain",
- "bitcoin_hd",
- "bitcoin_onchain",
- "bitcoin_scripts",
- "commit_verify",
- "strict_encoding",
-]
-
[[package]]
name = "quote"
version = "1.0.23"
@@ -738,62 +418,18 @@ dependencies = [
"getrandom",
]
-[[package]]
-name = "ring"
-version = "0.16.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
-dependencies = [
- "cc",
- "libc",
- "once_cell",
- "spin",
- "untrusted",
- "web-sys",
- "winapi",
-]
-
-[[package]]
-name = "rustls"
-version = "0.20.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
-dependencies = [
- "log",
- "ring",
- "sct",
- "webpki",
-]
-
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
-[[package]]
-name = "scratch"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
-
-[[package]]
-name = "sct"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
-dependencies = [
- "ring",
- "untrusted",
-]
-
[[package]]
name = "secp256k1"
-version = "0.24.3"
+version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62"
+checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894"
dependencies = [
- "bitcoin_hashes",
"rand",
"secp256k1-sys",
"serde",
@@ -801,9 +437,9 @@ dependencies = [
[[package]]
name = "secp256k1-sys"
-version = "0.6.1"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b"
+checksum = "642a62736682fdd8c71da0eb273e453c8ac74e33b9fb310e22ba5b03ec7651ff"
dependencies = [
"cc",
]
@@ -849,99 +485,48 @@ dependencies = [
"serde_derive",
]
-[[package]]
-name = "serde_with"
-version = "1.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff"
-dependencies = [
- "hex",
- "serde",
- "serde_with_macros",
-]
-
-[[package]]
-name = "serde_with_macros"
-version = "1.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "serde_yaml"
-version = "0.8.26"
+version = "0.9.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b"
+checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567"
dependencies = [
"indexmap",
+ "itoa",
"ryu",
"serde",
- "yaml-rust",
+ "unsafe-libyaml",
]
[[package]]
name = "single_use_seals"
-version = "0.9.0"
+version = "0.10.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e092f1d5411486816ec67cd7d0280acb0e05a1bd509721bc3dde3b1ffa5bfa0e"
+checksum = "2ea7651417b98128263b5c3d2dc836400eecd7f4fba8470d4ca17f129f9a1b4a"
dependencies = [
"amplify_derive",
- "async-trait",
-]
-
-[[package]]
-name = "slip132"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41a2947cb179006a73896fca01015ee5255c05b8b83e74c5e9d623ed4480abe2"
-dependencies = [
- "amplify",
- "bitcoin",
-]
-
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "stability"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce"
-dependencies = [
- "quote",
- "syn",
]
[[package]]
name = "strict_encoding"
-version = "0.9.0"
+version = "2.0.0-beta.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0be7060b49729cd0b9b2391114632ef64c363a4055d91de049f5555b466193bb"
+checksum = "e8ce22c5bba8139f2182001358188f145b40b177a9a442545cf15574335fba88"
dependencies = [
"amplify",
- "bitcoin",
- "bitcoin_hashes",
- "chrono",
"strict_encoding_derive",
]
[[package]]
name = "strict_encoding_derive"
-version = "0.9.0"
+version = "2.0.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34c9cabafb397fc1144463228ad4ba57c3c670a0117505fe59b15d8c74449716"
+checksum = "4cb9b35c9d7429212d20ae38bb86ecbc6cd3b3ccf5db6a12d1e2aafa7cedf5b0"
dependencies = [
- "amplify_syn",
- "encoding_derive_helpers",
+ "amplify_syn 2.0.0-beta.1",
+ "heck",
"proc-macro2",
+ "quote",
"syn",
]
@@ -956,10 +541,10 @@ dependencies = [
]
[[package]]
-name = "strsim"
-version = "0.10.0"
+name = "subtle"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
@@ -972,32 +557,6 @@ dependencies = [
"unicode-ident",
]
-[[package]]
-name = "termcolor"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
-
-[[package]]
-name = "time"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
-dependencies = [
- "libc",
- "wasi 0.10.0+wasi-snapshot-preview1",
- "winapi",
-]
-
[[package]]
name = "toml"
version = "0.5.11"
@@ -1008,22 +567,22 @@ dependencies = [
]
[[package]]
-name = "unicode-ident"
-version = "1.0.6"
+name = "typenum"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
-name = "unicode-width"
-version = "0.1.10"
+name = "unicode-ident"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
-name = "untrusted"
-version = "0.7.1"
+name = "unsafe-libyaml"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2"
[[package]]
name = "version_check"
@@ -1031,12 +590,6 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-[[package]]
-name = "wasi"
-version = "0.10.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
-
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@@ -1045,9 +598,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.83"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1055,9 +608,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.83"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log",
@@ -1070,9 +623,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.83"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1080,9 +633,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.83"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2",
"quote",
@@ -1093,75 +646,6 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
-
-[[package]]
-name = "web-sys"
-version = "0.3.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "webpki"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "webpki-roots"
-version = "0.22.6"
+version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
-dependencies = [
- "webpki",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "yaml-rust"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
-dependencies = [
- "linked-hash-map",
-]
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
diff --git a/Cargo.toml b/Cargo.toml
index 8e3c5e50..1463cb8a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,56 +1,62 @@
+[workspace]
+members = [
+ "primitives",
+ "dbc",
+ "seals",
+ "."
+]
+default-members = [
+ "primitives",
+ "dbc",
+ "seals",
+ "."
+]
+
+[workspace.package]
+authors = ["Dr Maxim Orlovsky "]
+homepage = "https://github.com/BP-WG"
+repository = "https://github.com/BP-WG/bp-core"
+rust-version = "1.66" # Due to strict encoding library (caused by GAD)
+edition = "2021"
+license = "Apache-2.0"
+
[package]
name = "bp-core"
-version = "0.9.0"
-license = "Apache-2.0"
-authors = ["Dr. Maxim Orlovsky "]
-description = "Bitcoin Protocol Core Library (BP Core Lib)"
-repository = "https://github.com/LNP-BP/bp-core"
-homepage = "https://github.com/LNP-BP"
-keywords = ["lnp-bp", "cryptocurrency", "smart-contracts", "bitcoin"]
-categories = ["cryptography::cryptocurrencies", "encoding", "parsing"]
+version = "0.10.0-beta.1"
+description = "Bitcoin protocol core library (BP Core Lib)"
+keywords = ["lnp-bp", "smart-contracts", "bitcoin", "blockchain"]
+categories = ["cryptography"]
+authors = { workspace = true }
+repository = { workspace = true }
+homepage = { workspace = true }
+edition = { workspace = true }
+license = { workspace = true }
+rust-version = { workspace = true }
readme = "README.md"
-edition = "2021"
-rust-version = "1.59.0"
-exclude = [".github", "dbc", "seals", "dbc-legacy", "seals-legacy"]
+exclude = [".github", "primitives", "dbc", "seals"]
[lib]
name = "bp"
path = "src/lib.rs"
-[[bin]]
-name = "dbc"
-required-features = ["cli", "serde"]
-
-[[bin]]
-name = "seals"
-required-features = ["cli", "serde"]
-
[dependencies]
-amplify = "3.13.0"
-strict_encoding = "0.9.0"
-commit_verify = "0.9.0"
-single_use_seals = "0.9.0"
-bitcoin = "0.29.2"
-psbt = { version = "0.9.0", optional = true }
-bp-dbc = { version = "0.9.0", path = "./dbc" }
-bp-seals = { version = "0.9.0", path = "./seals" }
+amplify = "4.0.0-beta.11"
+strict_encoding = "2.0.0-beta.3"
+commit_verify = "0.10.0-beta.1"
+single_use_seals = "0.10.0-beta.1"
+bp-primitives = { version = "0.10.0-beta.1", path = "./primitives" }
+bp-dbc = { version = "0.10.0-beta.1", path = "./dbc" }
+bp-seals = { version = "0.10.0-beta.1", path = "./seals" }
serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true }
-serde_with = { version = "1.14", optional = true }
-electrum-client = { version = "0.12.0", optional = true }
-clap = { version = "~3.2.23", optional = true, features = ["derive"] }
-colored = { version = "2", optional = true }
[features]
default = []
-all = ["async", "serde", "cli", "wallet"]
-cli = ["clap", "colored", "electrum-client", "wallet"]
-wallet = ["psbt", "bp-dbc/wallet"]
-async = ["bp-seals/async"]
-serde = ["amplify/serde", "bitcoin/serde",
- "commit_verify/serde", "bp-dbc/serde", "bp-seals/serde",
- "serde_crate", "serde_with"]
+all = ["serde"]
+serde = [
+ "serde_crate",
+ "bp-dbc/serde",
+ #"bp-seals/serde",
+]
-[workspace]
-members = [".", "dbc", "seals"]
-default-members = [".", "dbc", "seals"]
-exclude = ["dbc-legacy"]
+[package.metadata.docs.rs]
+features = [ "all" ]
diff --git a/DCO b/DCO
new file mode 100644
index 00000000..69175c98
--- /dev/null
+++ b/DCO
@@ -0,0 +1,28 @@
+Developer's Certificate of Origin 1.1
+Copyright © 2004, 2006 The Linux Foundation and its contributors.
+
+---
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+(c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+(d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
diff --git a/LICENSE b/LICENSE
index a6a3b8bc..e1720699 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2019-2022 LNP/BP Standards Association, Switzerland
+ Copyright 2019-2023 LNP/BP Standards Association, Switzerland
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
new file mode 100644
index 00000000..a3af1e08
--- /dev/null
+++ b/MAINTAINERS.md
@@ -0,0 +1,6 @@
+Maxim Orlovsky
+---------------
+- GitHub: [@dr-orlovsky](https://github.com/dr-orlovsky)
+- GPG: `EAE730CEC0C663763F028A5860094BAF18A26EC9`
+- SSH: `BoSGFzbyOKC7Jm28MJElFboGepihCpHop60nS8OoG/A`
+- EMail: [dr@orlovsky.ch](mailto:dr@orlovsky.ch)
diff --git a/MANIFEST.yml b/MANIFEST.yml
new file mode 100644
index 00000000..6ec60bd5
--- /dev/null
+++ b/MANIFEST.yml
@@ -0,0 +1,14 @@
+Name: strict_encoding
+Type: Library
+Kind: Free software
+License: Apache-2.0
+Language: Rust
+Compiler: 1.66
+Author: Maxim Orlovsky
+Maintained: UBIDECO Institute, Switzerland
+Maintainers:
+ Maxim Orlovsky:
+ GitHub: @dr-orlovsky
+ GPG: EAE730CEC0C663763F028A5860094BAF18A26EC9
+ SSH: BoSGFzbyOKC7Jm28MJElFboGepihCpHop60nS8OoG/A
+ EMail: dr@orlovsky.ch
diff --git a/README.md b/README.md
index 6bc724c5..e79e822f 100644
--- a/README.md
+++ b/README.md
@@ -10,72 +10,59 @@
[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
[![Apache-2 licensed](https://img.shields.io/crates/l/bp-core)](./LICENSE)
-The library implements components necessary for [client-side-validation] in bitcoin
-protocol, specifically
+The library implements components necessary for [client-side-validation] in
+bitcoin protocol, specifically
-- deterministic bitcoin commitments API (LNPBP-14, 6 standards)
-- bitcoin-based single-use-seal API (LNPBP-10 and LNPBP-39 standards)
+- deterministic bitcoin commitments API ([LNPBP-1], [LNPBP-2], [LNPBP-3], [LNPBP-6], [LNPBP-11] & [LNPBP-12] standards)
+- bitcoin-based single-use-seal API ([LNPBP-10] standards)
Client-side-validation is a paradigm for distributed computing, based on top of
proof-of-publication/commitment medium layer, which may be a bitcoin blockchain
or other type of distributed consensus system.
-The development of the library is supported by [LNP/BP Standards Association](https://lnp-bp.org).
+The development of the library is supported by [LNP/BP Standards Association][lnpbp-web]
+and is performed on its [GitHub page][lnpbp-github].
-## Usage
-
-To use libraries, you just need latest version of libraries, published to
-[crates.io](https://crates.io) into `[dependencies]` section of your project
-`Cargo.toml`. Here is the full list of available libraries from this repository:
+The original idea of client-side-validation was proposed by Peter Todd with its
+possible applications designed by Giacomo Zucco. It was shaped into the protocol
+design by Dr Maxim Orlovsky with a big input from the community.
-```toml
-bp-dbc = "0.5" # Deterministic bitcoin commitments crate
-bp-seals = "0.5" # Bitcoin single-use-seals crate
-bp-core = "0.5" # Library including both of the previous crates
-```
+Minimum supported rust version for the library (MSRV) is 1.66 and 2021 rust
+edition.
-`bp-core` crate is an "umbrella" library containing both deterministic bitcoin
-commitments and bitcoin seals crates inside.
-## Command-line utilities
+## Documentation
-One may install command-line utilities with the following command (requires
-rust compiler and `rustup` tools to be already installed on a system):
+Detailed developer & API documentation for all libraries can be accessed at:
+-
+-
+-
+-
-```console
-$ rustup default stable
-$ rustup update
-$ git clone https://github.com/BP-WG/bp-core
-$ cd bp-core
-$ cargo install --path . --bins --locked --all-features
-```
+To learn about the technologies enabled by the library please check
+[slides from our tech presentations][presentations] and
+[LNP/BP tech talks videos][lnpbp-youtube].
-This will add `seals` and `dbc` commands to the system.
-### Install with Docker
+## Usage
-#### Build
+The repository contains rust libraries for client-side validation.
-Clone the repository and checkout to the desired version (here `v0.8.0`):
+### Use library in other projects
-```console
-$ git clone https://github.com/BP-WG/bp-core
-$ cd bp-core
-$ git checkout v0.8.0
-```
-
-Build and tag the Docker image:
+To use libraries, you just need latest version of libraries, published to
+[crates.io](https://crates.io) into `[dependencies]` section of your project
+`Cargo.toml`. Here is the full list of available libraries from this repository:
-```console
-$ docker build -t bp-core:v0.8.0 .
+```toml
+bp-primitives = "1" # Bitcoin protocol primitives crate
+bp-dbc = "1" # Deterministic bitcoin commitments crate
+bp-seals = "1" # Bitcoin single-use-seals crate
+bp-core = "1" # Library including both of the previous crates
```
-#### Usage
-
-```console
-$ docker run bp-core:v0.8.0 seals --help
-$ docker run bp-core:v0.8.0 dbc --help
-```
+`bp-core` crate is an "umbrella" library containing both deterministic bitcoin
+commitments and bitcoin seals crates inside.
## Known applications
@@ -94,7 +81,7 @@ Contribution guidelines can be found in [CONTRIBUTING](CONTRIBUTING.md)
### MSRV
-This library requires minimum rust compiler version (MSRV) 1.41.1.
+This library requires minimum rust compiler version (MSRV) 1.66.0.
### Policy on altcoins
@@ -104,8 +91,19 @@ be declined.
### Licensing
-See [LICENCE](LICENSE) file.
+The libraries are distributed on the terms of Apache 2.0 opensource license.
+See [LICENCE](LICENSE) file for the license details.
+
+
+[lnpbp-web]: https://lnp-bp.org
+[lnpbp-github]: https://github.com/LNP-BP
+[lnpbp-youtube]: https://www.youtube.com/@LNPBP
+[presentations]: https://github.com/LNP-BP/FAQ/blob/master/Presentation%20slides/
-[rust-bitcoin]: https://github.com/rust-bitcoin/rust-bitcoin
-[descriptor-wallet]: https://github.com/LNP-BP/descriptor-wallet
-[client-side-validation]: https://docs.rs/client_side_validation/
+[LNPBP-1]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0001.md
+[LNPBP-2]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0002.md
+[LNPBP-3]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0003.md
+[LNPBP-6]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0006.md
+[LNPBP-10]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0010.md
+[LNPBP-11]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0011.md
+[LNPBP-12]: https://github.com/LNP-BP/LNPBPs/blob/master/lnpbp-0012.md
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..22101c1e
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,59 @@
+# Security
+
+We take the security of our software products and services seriously, which
+includes all source code repositories managed through our GitHub organizations.
+
+If you believe you have found a security vulnerability in any of our repository
+that meets [definition of a security vulnerability][definition], please report
+it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the repository maintainers by sending a **GPG
+encrypted e-mail** to _all maintainers of a specific repo_ using their GPG keys.
+
+A list of repository maintainers and their keys and e-mail addresses are
+provided inside MAINTANERS.md file and MANIFEST.yml, with the latter also
+included in the README.md as a manifest block, which looks in the following way:
+
+```yaml
+Name:
+...
+Maintained:
+Maintainers:
+ :
+ GPG:
+ EMail:
+ :
+ ...
+```
+
+You should receive a response within 72 hours. If for some reason you do not,
+please follow up via email to ensure we received your original message.
+
+Please include the requested information listed below (as much as you can
+provide) to help us better understand the nature and scope of the possible
+issue:
+
+* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+* Full paths of source file(s) related to the manifestation of the issue
+* The location of the affected source code (tag/branch/commit or direct URL)
+* Any special configuration required to reproduce the issue
+* Step-by-step instructions to reproduce the issue
+* Proof-of-concept or exploit code (if possible)
+* Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+We follow the principle of [Coordinated Vulnerability Disclosure][disclosure].
+
+[definition]: https://aka.ms/opensource/security/definition
+[disclosure]: https://aka.ms/opensource/security/cvd
diff --git a/codecov.yml b/codecov.yml
index fcaf8f20..240d7310 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -8,9 +8,12 @@ coverage:
status:
project:
default:
- target: 85%
+ target: 75%
threshold: 1%
+ branches:
+ - master
patch:
default:
- target: 75%
- threshold: 1%
\ No newline at end of file
+ target: 60%
+ threshold: 1%
+ only_pulls: true
diff --git a/dbc-legacy/Cargo.toml b/dbc-legacy/Cargo.toml
deleted file mode 100644
index 562ccefe..00000000
--- a/dbc-legacy/Cargo.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-[package]
-name = "bp-dbc"
-version = "0.6.0-alpha.1"
-license = "Apache-2.0"
-authors = ["Dr. Maxim Orlovsky "]
-description = "Deterministic bitcoin commitments library"
-repository = "https://github.com/LNP-BP/bp-core"
-homepage = "https://github.com/LNP-BP"
-keywords = ["lnp-bp", "bitcoin", "cryptography", "smart-contracts", "single-use-seals"]
-categories = ["cryptography::cryptocurrencies", "encoding"]
-readme = "../README.md"
-edition = "2018"
-
-[lib]
-name = "dbc"
-path = "src/lib.rs"
-
-[dependencies]
-amplify = "3.12.0"
-bitcoin = "0.28.0-rc.1"
-secp256k1 = { version = "0.21.3", features = ["global-context"] }
-bitcoin_scripts = "0.6.0-beta.2"
-descriptors = { version = "0.6.0-beta.1", default-features = false }
-strict_encoding = "1.8.0-rc.1"
-commit_verify = "0.6.0-alpha.1"
-miniscript_crate = { package = "miniscript", version = "6.0.1", git = "https://github.com/rust-bitcoin/rust-miniscript", optional = true }
-serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true }
-serde_with = { version = "1.8", optional = true }
-
-[features]
-default = []
-all = ["serde", "miniscript"]
-miniscript = ["miniscript_crate", "bitcoin_scripts/miniscript", "descriptors/miniscript"]
-serde = ["amplify/serde", "bitcoin/use-serde", "bitcoin_scripts/serde", "commit_verify/serde", "serde_crate", "serde_with"]
diff --git a/dbc-legacy/src/container.rs b/dbc-legacy/src/container.rs
deleted file mode 100644
index 11a6692c..00000000
--- a/dbc-legacy/src/container.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use crate::{Error, Proof};
-
-pub trait Container: Sized {
- type Supplement;
- type Host;
-
- /// Reconstructs commitment container from the extra-transaction proof
- /// and protocol-specific data.
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- host: &Self::Host,
- ) -> Result;
-
- fn deconstruct(self) -> (Proof, Self::Supplement);
-
- fn to_proof(&self) -> Proof;
- fn into_proof(self) -> Proof;
-}
diff --git a/dbc-legacy/src/error.rs b/dbc-legacy/src/error.rs
deleted file mode 100644
index a0b36e20..00000000
--- a/dbc-legacy/src/error.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-#[cfg(feature = "miniscript")]
-use miniscript::policy::compiler::CompilerError;
-
-use crate::spk::lnpbp1;
-
-#[cfg(not(feature = "miniscript"))]
-#[derive(
- Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error
-)]
-#[display(Debug)]
-pub enum CompilerError {}
-
-/// Different error types which may happen during deterministic bitcoin
-/// commitment generation procedures
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Error, From)]
-#[display(doc_comments)]
-pub enum Error {
- /// Indicates failure of applying commitment tweak to a public key
- #[from]
- Lnpbp1Commitment(lnpbp1::Error),
-
- /// Unable to verify commitment due to an incorrect proof data structure
- InvalidProofStructure,
-
- /// LNPBP-2 standard requires OP_RETURN-based commitments to be produced
- /// only if serialized version of a tweaked pubkey starts with `02` byte.
- /// This error indicates that the provided public key does not satisfy this
- /// condition
- InvalidOpReturnKey,
-
- /// Can't deserealized public key from bitcoin script push op code
- InvalidKeyData,
-
- /// Wrong witness version, may be you need to upgrade used library version
- UnsupportedWitnessVersion,
-
- /// Miniscript was unable to parse provided script data; they are either
- /// invalid or miniscript library contains a bug
- #[cfg_attr(
- feature = "miniscript",
- from(bitcoin_scripts::PubkeyParseError)
- )]
- LockscriptParseError,
-
- /// Provided script contains no keys, so commitment or its verification is
- /// impossible
- LockscriptContainsNoKeys,
-
- /// Bitcoin script contains public key hashes with no matching public
- /// keys provided. Commitment procedure fails since it can't ensure that
- /// commitment include all public key.
- LockscriptContainsUnknownHashes,
-
- /// Attempt to commit into LockScript has failed: the key that must contain
- /// the commitment/tweak was not found either in plain nor hash form in
- /// any of the script branches
- LockscriptKeyNotFound,
-
- /// Policy compilation error
- #[from]
- #[display(inner)]
- PolicyCompilation(CompilerError),
-
- /// Deterministic bitcoin commitments require use of compressed public keys
- UncompressedKey,
-}
-
-impl From for Error {
- fn from(err: descriptors::Error) -> Self {
- match err {
- descriptors::Error::InvalidKeyData => Error::InvalidKeyData,
- descriptors::Error::UnsupportedWitnessVersion => {
- Error::UnsupportedWitnessVersion
- }
- #[cfg(feature = "miniscript")]
- descriptors::Error::PolicyCompilation(err) => {
- Error::PolicyCompilation(err)
- }
- #[cfg(not(feature = "miniscript"))]
- descriptors::Error::PolicyCompilation(_) => unreachable!(
- "policy compilation error when miniscript is disabled",
- ),
- descriptors::Error::UncompressedKeyInSegWitContext => {
- Error::UncompressedKey
- }
- // Since we never parse strings, this error must not happen
- descriptors::Error::CantParseDescriptor => {
- unreachable!("miniscript parses string representation")
- }
- // If other errors appear this must crash so we know about that the
- // new implementation is required
- _ => unimplemented!("not all of descriptor errors is supported"),
- }
- }
-}
diff --git a/dbc-legacy/src/lib.rs b/dbc-legacy/src/lib.rs
deleted file mode 100644
index a9ecebf4..00000000
--- a/dbc-legacy/src/lib.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-// Coding conventions
-#![recursion_limit = "256"]
-#![deny(dead_code, /* missing_docs, */ warnings)]
-
-#[macro_use]
-extern crate amplify;
-#[macro_use]
-extern crate strict_encoding;
-#[cfg(feature = "serde")]
-#[macro_use]
-extern crate serde_crate as serde;
-#[cfg(feature = "miniscript")]
-extern crate miniscript_crate as miniscript;
-
-pub mod container;
-mod error;
-pub mod proof;
-pub mod sigs;
-pub mod spk;
-pub mod tapret;
-pub mod txout;
-
-pub use container::Container;
-pub use error::Error;
-pub use proof::Proof;
diff --git a/dbc-legacy/src/pktweak/keyset.rs b/dbc-legacy/src/pktweak/keyset.rs
deleted file mode 100644
index 0f32c785..00000000
--- a/dbc-legacy/src/pktweak/keyset.rs
+++ /dev/null
@@ -1,226 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-//! # LNPBP-1 related
-
-use std::collections::BTreeSet;
-
-use bitcoin::hashes::{sha256, Hmac};
-use commit_verify::EmbedCommitVerify;
-use miniscript::Segwitv0;
-
-use crate::lnpbp1;
-use crate::{Container, Error, Proof, ScriptEncodeData};
-
-/// Container for LNPBP-1 commitments. In order to be constructed, commitment
-/// requires an original public key and a protocol-specific tag, which
-/// must be hashed during commitment process. Here we use pre-hashed version
-/// of the tag in order to maximize performance for multiple commitments.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct KeysetContainer {
- /// The original public key: host for the commitment
- pub pubkey: secp256k1::PublicKey,
- /// Other keys that will participate the commitment procedure
- pub keyset: BTreeSet,
- /// Single SHA256 hash of the protocol-specific tag
- pub tag: sha256::Hash,
- /// Tweaking factor stored after [`KeysetCommitment::embed_commit`]
- /// procedure
- pub tweaking_factor: Option>,
-}
-
-impl Container for KeysetContainer {
- /// Out supplement is a protocol-specific tag in its hashed form
- type Supplement = sha256::Hash;
-
- /// Proof contains both original public key and all participating keys
- /// (inside it's script), so we don't need host here
- type Host = Option<()>;
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- _: &Self::Host,
- ) -> Result {
- if let ScriptEncodeData::LockScript(ref script) = proof.source {
- Ok(Self {
- pubkey: proof.pubkey,
- keyset: script
- .extract_pubkeyset::()?
- .into_iter()
- .map(|pk| pk.key)
- .collect(),
- tag: *supplement,
- tweaking_factor: None,
- })
- } else {
- Err(Error::InvalidProofStructure)
- }
- }
-
- #[inline]
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- (Proof::from(self.pubkey), self.tag)
- }
-
- /// Important: this method should not be used. KeysetContainer does not
- /// support proof generation, use more advanced structures like LockScript
- /// container to generate the proof
- #[inline]
- fn to_proof(&self) -> Proof {
- panic!("KeysetContainer does not support proof generation")
- }
-
- /// Important: this method should not be used. KeysetContainer does not
- /// support proof generation, use more advanced structures like LockScript
- /// container to generate the proof
- #[inline]
- fn into_proof(self) -> Proof {
- panic!("KeysetContainer does not support proof generation")
- }
-}
-
-/// Public key committed to some message plus a sum of other public keys via
-/// LNPBP2-based tweaking procedure
-#[derive(Wrapper, Clone, Copy, PartialEq, Eq, Hash, Debug, Display, From)]
-#[display("{0}", alt = "{_0:#}*")]
-#[wrapper(FromStr, LowerHex)]
-pub struct KeysetCommitment(secp256k1::PublicKey);
-
-impl EmbedCommitVerify for KeysetCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = KeysetContainer;
- type Error = lnpbp1::Error;
-
- // #[consensus_critical("RGB")]
- // #[standard_critical("LNPBP-1")]
- fn embed_commit(
- keyset_container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- let mut keyset = keyset_container.keyset.clone();
- let mut pubkey = keyset_container.pubkey;
- keyset.insert(pubkey);
-
- let tweaking_factor = lnpbp1::commit(
- &mut keyset,
- &mut pubkey,
- &keyset_container.tag,
- msg,
- )?;
-
- keyset_container.tweaking_factor = Some(tweaking_factor);
-
- // Returning tweaked public key
- Ok(KeysetCommitment(pubkey))
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::iter::FromIterator;
- use std::str::FromStr;
-
- use amplify::hex::ToHex;
- use amplify::Wrapper;
- use bitcoin::hashes::{sha256, Hash};
-
- use super::*;
- use crate::lnpbp1::test_helpers::*;
- use crate::pubkey::*;
-
- #[test]
- fn test_lnpbp1_vs_lnpbp2() {
- let tag = sha256::Hash::hash(b"TEST_TAG2");
- let msg = "test message";
- gen_secp_pubkeys(9).into_iter().for_each(|pubkey| {
- let lnpbp1_commitment = PubkeyCommitment::embed_commit(
- &mut PubkeyContainer {
- pubkey,
- tag,
- tweaking_factor: None,
- },
- &msg,
- )
- .unwrap();
- let lnpbp2_commitment = KeysetCommitment::embed_commit(
- &mut KeysetContainer {
- pubkey,
- keyset: BTreeSet::new(),
- tag,
- tweaking_factor: None,
- },
- &msg,
- )
- .unwrap();
-
- assert_eq!(
- lnpbp1_commitment.into_inner(),
- lnpbp2_commitment.into_inner()
- );
- });
- }
-
- #[test]
- fn test_keyset_commitment() {
- let tag = sha256::Hash::hash(b"TEST_TAG2");
- let pubkey = secp256k1::PublicKey::from_str(
- "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166",
- )
- .unwrap();
- (1..9).into_iter().for_each(|n_keys| {
- embed_commit_verify_suite::, KeysetCommitment>(
- gen_messages(),
- &mut KeysetContainer {
- pubkey,
- keyset: BTreeSet::from_iter(gen_secp_pubkeys(n_keys)),
- tag,
- tweaking_factor: None,
- },
- );
- });
- }
-
- #[test]
- fn test_keyset_tweaking_results() {
- let tag = sha256::Hash::hash(b"TEST_TAG2");
- let msg = "test message";
- let pubkey = secp256k1::PublicKey::from_str(
- "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166",
- )
- .unwrap();
- let keyset = BTreeSet::from_iter(vec![secp256k1::PublicKey::from_str(
- "03cfb81a7609a4d40914dfd41860f501209c30468d91834c8af1af34ce73f4f3fd",
- )
- .unwrap()]);
-
- let commitment = KeysetCommitment::embed_commit(
- &mut KeysetContainer {
- pubkey,
- keyset,
- tag,
- tweaking_factor: None,
- },
- &msg,
- )
- .unwrap();
- assert_eq!(
- commitment.as_inner().to_hex(),
- "02e47bb42c041f158ecfcf1099018f08650ef569a9a51bbb317e8787cdf3e06890"
- );
- }
-}
diff --git a/dbc-legacy/src/pktweak/lnpbp1.rs b/dbc-legacy/src/pktweak/lnpbp1.rs
deleted file mode 100644
index a4fc63ce..00000000
--- a/dbc-legacy/src/pktweak/lnpbp1.rs
+++ /dev/null
@@ -1,628 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-//! # LNPBP-1
-//!
-//! Module for Secp256k1 elliptic curve based collision-resistant commitments,
-//! implementing [LNPBP-1](https://github.com/LNP-BP/lnpbps/blob/master/lnpbp-0001.md)
-
-use std::collections::BTreeSet;
-
-use bitcoin::hashes::{sha256, Hash, HashEngine, Hmac, HmacEngine};
-
-/// Single SHA256 hash of "LNPBP1" string according to LNPBP-1 acting as a
-/// prefix to the message in computing tweaking factor
-pub static LNPBP1_HASHED_TAG: [u8; 32] = [
- 245, 8, 242, 142, 252, 192, 113, 82, 108, 168, 134, 200, 224, 124, 105,
- 212, 149, 78, 46, 201, 252, 82, 171, 140, 204, 209, 41, 17, 12, 0, 64, 175,
-];
-
-/// Deterministically-organized set of all public keys used by this mod
-/// internally
-type Keyset = BTreeSet;
-
-/// Errors that may happen during LNPBP-1 commitment procedure or because of
-/// incorrect arguments provided to [`commit()`] function.
-#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Error, From)]
-#[display(doc_comments)]
-pub enum Error {
- /// Keyset must include target public key, but no target key found it
- /// the provided set.
- NotKeysetMember,
-
- /// Elliptic curve point addition resulted in point in infinity; you
- /// must select different source public keys
- SumInfiniteResult,
-
- /// LNPBP-1 commitment either is outside of Secp256k1 order `n` (this event
- /// has negligible probability <~2^-64), or, when added to the provided
- /// keyset, results in point at infinity. You may try with a different
- /// source message or public keys.
- InvalidTweak,
-}
-
-/// Function performs commitment procedure according to LNPBP-1.
-///
-/// # Parameters
-///
-/// - A set of public keys for committing during the LNPBP-1 procedure
-/// - Target public key for tweaking. Must be a part of the keyset, otherwise
-/// function will fail with [`Error::NotKeysetMember`]
-/// - Protocol-specific tag in form of 32-byte hash
-/// - Message to commit to, which must be representable as a byte slice using
-/// [`AsRef::as_ref()`]
-///
-/// # Returns
-///
-/// Function mutates two of its parameters,
-/// - `target_pubkey`, with a tweaked version of the public key containing
-/// commitment to the message and the rest of keyset,
-/// - `keyset`, by replacing original `target_pubkey` with its tweaked version
-/// and returns `tweaking_factor` as a return parameter wrapped into
-/// [`Result::Ok`].
-///
-/// If the function fails with any error, value for `target_pubkey` and `keyset`
-/// is undefined and must be discarded.
-///
-/// # Errors
-///
-/// Function may fail because of one of the following circumstances:
-/// - If `target_pubkey` is not a part of `keyset` ([`Error::NotKeysetMember`])
-/// - If keyset deliberately constructed in a way that sum of some of its keys
-/// is equivalent to negation of some other keys. In this case function fails
-/// with [`Error::SumInfiniteResult`]
-/// - With negligible probability because of elliptic curve Secp256k1 point
-/// addition overflow; in this case function returns either
-/// [`Error::SumInfiniteResult`], if it happens during summation of public
-/// keys from the `keyset`, or [`Error::InvalidTweak`], if it happens during
-/// tweaking factor addition to the `target_pubkey`.
-///
-/// # Protocol:
-///
-/// Please refer to the original document for the verification:
-///
-
-// #[consensus_critical("RGB")]
-// #[standard_critical("LNPBP-1")]
-pub fn commit(
- keyset: &mut Keyset,
- target_pubkey: &mut secp256k1::PublicKey,
- protocol_tag: &sha256::Hash,
- message: &impl AsRef<[u8]>,
-) -> Result, Error> {
- if !keyset.remove(target_pubkey) {
- return Err(Error::NotKeysetMember);
- }
-
- // ! [CONSENSUS-CRITICAL]:
- // ! [STANDARD-CRITICAL]: We commit to the sum of all public keys,
- // not a single pubkey. For single key the set
- // is represented by itself
- let pubkey_sum = keyset
- .iter()
- .try_fold(*target_pubkey, |sum, pubkey| sum.combine(pubkey))
- .map_err(|_| Error::SumInfiniteResult)?;
-
- // ! [CONSENSUS-CRITICAL]:
- // ! [STANDARD-CRITICAL]: HMAC engine is based on sha256 hash
- let mut hmac_engine =
- HmacEngine::::new(&pubkey_sum.serialize());
-
- // ! [CONSENSUS-CRITICAL]:
- // ! [STANDARD-CRITICAL]: Hash process started with consuming first
- // protocol prefix: single SHA256 hash of
- // ASCII "LNPBP1" string.
- // NB: We use the same hash as in LNPBP-1 so when there is no other
- // keys involved the commitment would not differ.
- hmac_engine.input(&LNPBP1_HASHED_TAG[..]);
-
- // ! [CONSENSUS-CRITICAL]:
- // ! [STANDARD-CRITICAL]: The second prefix comes from the upstream
- // protocol as a part of the container
- hmac_engine.input(&protocol_tag[..]);
-
- // ! [CONSENSUS-CRITICAL]:
- // ! [STANDARD-CRITICAL]: Next we hash the message. The message must be
- // prefixed with the protocol-specific prefix:
- // another single SHA256 hash of protocol name.
- // However this is not the part of this function,
- // the function expect that the `msg` is already
- // properly prefixed
- hmac_engine.input(&sha256::Hash::hash(message.as_ref()));
-
- // Producing tweaking factor
- let tweaking_factor = Hmac::from_engine(hmac_engine);
-
- // Applying tweaking factor to public key
- target_pubkey
- .add_exp_assign(secp256k1::SECP256K1, &tweaking_factor[..])
- .map_err(|_| Error::InvalidTweak)?;
-
- keyset.insert(*target_pubkey);
-
- // Returning tweaked public key
- Ok(tweaking_factor)
-}
-
-/// Function verifies commitment created according to LNPBP-1.
-///
-/// # Parameters
-///
-/// - `verified_pubkey`: public key containing LNPBP-1 commitment, i.e. the one
-/// modified by [`commit()`] procedure as its second parameter `target_key`
-/// - `original_keyset`: set of public keys provided to the [`commit()`]
-/// procedure. This set must include orignal pubkey specified in the next
-/// parameter `taget_pubkey`
-/// - `target_pubkey`: one of public keys included into the original keyset and
-/// that was provided to the [`commit()`] procedure as `target_pubkey`. This
-/// must be an original version of public key from the `verified_pubkey`
-/// parameter before the tweak was applied
-/// - `protocol_tag`: protocol-specific tag in form of 32-byte hash
-/// - `message`: message to commit to, which must be representable as a byte
-/// slice using [`AsRef::as_ref()`]
-///
-/// # Returns
-///
-/// - `true`, if verification succeeds,
-/// - `false`, if verification fails, indicating that the provided
-/// `verified_pubkey` is not committed to the data given in the rest of
-/// function parameters.
-///
-/// # Procedure
-///
-/// Please refer to the original document for the general algotirhm:
-///
-///
-/// Function verifies commitment by running LNPBP-1 commitment procedure once
-/// again with the provided data as a source data, and comparing the result of
-/// the commitment to the `verified_pubkey`. If the commitment function fails,
-/// it means that it was not able to commit with the provided data, meaning that
-/// the commitment was not created. Thus, we return that verification have not
-/// passed, and not a error. Verification succeeds if the commitment procedure
-/// produces public key equivalent to the `verified_pubkey`.
-pub fn verify(
- verified_pubkey: secp256k1::PublicKey,
- original_keyset: &Keyset,
- mut target_pubkey: secp256k1::PublicKey,
- protocol_tag: &sha256::Hash,
- message: &impl AsRef<[u8]>,
-) -> bool {
- match commit(
- &mut original_keyset.clone(),
- &mut target_pubkey,
- protocol_tag,
- message,
- ) {
- // If the commitment function fails, it means that it was not able to
- // commit with the provided data, meaning that the commitment was not
- // created. Thus, we return that verification have not passed, and not
- // a error.
- Err(_) => false,
-
- // Verification succeeds if the commitment procedure produces public key
- // equivalent to the verified one
- Ok(_) => target_pubkey == verified_pubkey,
- }
-}
-
-/// Helpers for writing test functions working with commit-verify scheme
-#[cfg(test)]
-pub mod test_helpers {
- use std::collections::HashSet;
- use std::fmt::Debug;
-
- use amplify::hex::FromHex;
- use commit_verify::EmbedCommitVerify;
-
- use super::*;
-
- /// Generates a set of messages for testing purposes
- ///
- /// All of these messages MUST produce different commitments, otherwise the
- /// commitment algorithm is not collision-resistant
- pub fn gen_messages() -> Vec> {
- vec![
- // empty message
- b"".to_vec(),
- // zero byte message
- b"\x00".to_vec(),
- // text message
- b"test".to_vec(),
- // text length-extended message
- b"test*".to_vec(),
- // short binary message
- Vec::from_hex("deadbeef").unwrap(),
- // length-extended version
- Vec::from_hex("deadbeef00").unwrap(),
- // prefixed version
- Vec::from_hex("00deadbeef").unwrap(),
- // serialized public key as text
- b"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798".to_vec(),
- // the same public key binary data
- Vec::from_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")
- .unwrap(),
- // different public key
- Vec::from_hex("02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9")
- .unwrap(),
- ]
- }
-
- pub fn gen_secp_pubkeys(n: usize) -> Vec {
- let mut ret = Vec::with_capacity(n);
- let mut sk = [0; 32];
-
- for i in 1..n + 1 {
- sk[0] = i as u8;
- sk[1] = (i >> 8) as u8;
- sk[2] = (i >> 16) as u8;
-
- ret.push(secp256k1::PublicKey::from_secret_key(
- &secp256k1::SECP256K1,
- &secp256k1::SecretKey::from_slice(&sk[..]).unwrap(),
- ));
- }
- ret
- }
-
- /// Runs round-trip of commitment-embed-verify for a given set of messages
- /// and provided container
- pub fn embed_commit_verify_suite(
- messages: Vec,
- container: &mut CMT::Container,
- ) where
- MSG: AsRef<[u8]> + Eq,
- CMT: EmbedCommitVerify + Eq + std::hash::Hash + Debug,
- {
- messages.iter().fold(
- HashSet::::with_capacity(messages.len()),
- |mut acc, msg| {
- let commitment = CMT::embed_commit(container, msg).unwrap();
-
- // Commitments MUST be deterministic: each message should
- // produce unique commitment
- (1..10).for_each(|_| {
- assert_eq!(
- CMT::embed_commit(container, msg).unwrap(),
- commitment
- );
- });
-
- // Testing verification
- assert!(commitment.verify(container, msg).unwrap());
-
- messages.iter().for_each(|m| {
- // Testing that commitment verification succeeds only
- // for the original message and fails for the rest
- assert_eq!(
- commitment.verify(container, m).unwrap(),
- m == msg
- );
- });
-
- acc.iter().for_each(|cmt| {
- // Testing that verification against other commitments
- // returns `false`
- assert!(!cmt.verify(container, msg).unwrap());
- });
-
- // Detecting collision
- assert!(acc.insert(commitment));
-
- acc
- },
- );
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::str::FromStr;
-
- use super::*;
- use crate::lnpbp1::test_helpers::*;
-
- #[test]
- fn test_lnpbp1_tag() {
- assert_eq!(
- sha256::Hash::hash(b"LNPBP1").into_inner(),
- LNPBP1_HASHED_TAG
- );
- assert_ne!(
- sha256::Hash::hash(b"LNPBP2").into_inner(),
- LNPBP1_HASHED_TAG
- );
- assert_ne!(
- sha256::Hash::hash(b"LNPBP-1").into_inner(),
- LNPBP1_HASHED_TAG
- );
- assert_ne!(
- sha256::Hash::hash(b"LNPBP_1").into_inner(),
- LNPBP1_HASHED_TAG
- );
- assert_ne!(
- sha256::Hash::hash(b"lnpbp1").into_inner(),
- LNPBP1_HASHED_TAG
- );
- assert_ne!(
- sha256::Hash::hash(b"lnpbp-1").into_inner(),
- LNPBP1_HASHED_TAG
- );
- assert_ne!(
- sha256::Hash::hash(b"lnpbp_1").into_inner(),
- LNPBP1_HASHED_TAG
- );
- }
-
- #[test]
- fn test_single_key() {
- let tag = sha256::Hash::hash(b"ProtoTag");
- let tag2 = sha256::Hash::hash(b"Prototag");
- let messages = gen_messages();
- let all_keys = gen_secp_pubkeys(6);
- let other_key = all_keys[0];
- for msg in &messages {
- for mut pk in all_keys[1..].to_vec() {
- let original = pk.clone();
- let mut keyset = bset![pk];
- let mut keyset2 = bset![pk];
- let mut pk2 = pk.clone();
- let factor1 = commit(&mut keyset, &mut pk, &tag, &msg).unwrap();
- let factor2 =
- commit(&mut keyset2, &mut pk2, &tag2, &msg).unwrap();
-
- // Ensure that changing tag changes commitment and tweaking
- // factor (and tag is case-sensitive!)
- assert_ne!(factor1, factor2);
- assert_ne!(pk, pk2);
-
- // Ensure that factor value is not trivial
- assert_ne!(factor1, Hmac::from_slice(&[0u8; 32]).unwrap());
- assert_ne!(factor1, Hmac::from_slice(&[1u8; 32]).unwrap());
- assert_ne!(factor1, Hmac::from_slice(&[0xFFu8; 32]).unwrap());
- assert_ne!(&factor1[..], &tag[..]);
- assert_ne!(&factor1[..], &msg[..]);
-
- // Verify that the key was indeed tweaked
- assert_ne!(pk, original);
-
- // Verify that the set updated
- assert_ne!(bset![original], keyset);
- assert_eq!(bset![pk], keyset);
-
- // Do commitment by hand
- let mut engine =
- HmacEngine::::new(&original.serialize());
- engine.input(&LNPBP1_HASHED_TAG);
- engine.input(&tag.into_inner());
- engine.input(&sha256::Hash::hash(msg));
- let hmac = Hmac::from_engine(engine);
- let tweaking_factor = *hmac.as_inner();
- let mut altkey = original;
- altkey
- .add_exp_assign(&secp256k1::SECP256K1, &tweaking_factor[..])
- .unwrap();
- assert_eq!(altkey, pk);
-
- // Now try commitment with a different key, but the same data
- if other_key != original {
- let mut other_commitment = other_key;
- let mut other_keyset = bset![other_commitment];
- let factor3 = commit(
- &mut other_keyset,
- &mut other_commitment,
- &tag,
- &msg,
- )
- .unwrap();
-
- // Make sure we commit to the key value
- assert_ne!(factor1, factor3);
-
- // Make sure commitment value is not the same
- assert_ne!(pk, other_commitment);
-
- // Make sure we can't cross-verify
- assert_eq!(
- verify(
- other_commitment,
- &bset![original],
- original,
- &tag,
- &msg
- ),
- false
- );
- }
-
- // Verify commitment
- assert!(verify(pk, &bset![original], original, &tag, &msg));
-
- // Make sure we can't cross-verify with different tag
- assert_eq!(
- verify(pk, &bset![original], original, &tag2, &msg),
- false
- );
-
- // Make sure we can't cross-verify with different message
- assert_eq!(
- verify(
- pk,
- &bset![original],
- original,
- &tag2,
- &b"some other message"
- ),
- false
- );
- }
- }
- }
-
- #[test]
- fn test_keyset() {
- let tag = sha256::Hash::hash(b"ProtoTag");
- let tag2 = sha256::Hash::hash(b"Prototag");
- let messages = gen_messages();
- let all_keys = gen_secp_pubkeys(6);
- let other_key = all_keys[0];
- let original_keyset: BTreeSet<_> =
- all_keys[1..].to_vec().into_iter().collect();
- for msg in &messages {
- for mut pk in original_keyset.clone() {
- let original = pk.clone();
- let mut keyset = original_keyset.clone();
- let mut keyset2 = original_keyset.clone();
- let mut pk2 = pk.clone();
- let factor1 = commit(&mut keyset, &mut pk, &tag, &msg).unwrap();
- let factor2 =
- commit(&mut keyset2, &mut pk2, &tag2, &msg).unwrap();
-
- // Ensure that changing tag changes commitment and tweaking
- // factor (and tag is case-sensitive!)
- assert_ne!(factor1, factor2);
- assert_ne!(pk, pk2);
-
- // Ensure that factor value is not trivial
- assert_ne!(factor1, Hmac::from_slice(&[0u8; 32]).unwrap());
- assert_ne!(factor1, Hmac::from_slice(&[1u8; 32]).unwrap());
- assert_ne!(factor1, Hmac::from_slice(&[0xFFu8; 32]).unwrap());
- assert_ne!(&factor1[..], &tag[..]);
- assert_ne!(&factor1[..], &msg[..]);
-
- // Verify that the key was indeed tweaked
- assert_ne!(pk, original);
-
- // Verify that the set updated
- assert_ne!(original_keyset.clone(), keyset);
- // ... but only original key is touched
- let mut set = keyset.clone();
- set.remove(&pk);
- set.insert(original);
- assert_eq!(set, original_keyset);
-
- // Do commitment by hand
- let mut engine =
- HmacEngine::::new(&original.serialize());
- engine.input(&LNPBP1_HASHED_TAG);
- engine.input(&tag.into_inner());
- engine.input(msg);
- let hmac = Hmac::from_engine(engine);
- let tweaking_factor = *hmac.as_inner();
- let mut altkey = original;
- altkey
- .add_exp_assign(&secp256k1::SECP256K1, &tweaking_factor[..])
- .unwrap();
- // It must not match because done with a single key, not
- // their sum
- assert_ne!(altkey, pk);
-
- // Now try commitment with a different key, but the same
- // data
- if other_key != original {
- let mut other_pk = other_key;
- let mut other_keyset = original_keyset.clone();
- assert!(!other_keyset.contains(&other_pk));
- other_keyset.remove(&pk);
- other_keyset.insert(other_pk);
- let factor3 =
- commit(&mut other_keyset, &mut other_pk, &tag, &msg)
- .unwrap();
-
- // Make sure we commit to the key value
- assert_ne!(factor1, factor3);
-
- // Make sure commitment value is not the same
- assert_ne!(pk, other_pk);
-
- // Make sure we can't cross-verify
- assert_eq!(
- verify(
- other_pk,
- &bset![original],
- original,
- &tag,
- &msg
- ),
- false
- );
- assert_eq!(
- verify(
- other_pk,
- &original_keyset,
- original,
- &tag,
- &msg
- ),
- false
- );
- }
-
- // Verify commitment
- assert!(verify(pk, &original_keyset, original, &tag, &msg));
-
- // Make sure we can't cross-verify with a single key in a set
- assert_eq!(
- verify(pk, &bset![original], original, &tag, &msg),
- false
- );
-
- // Make sure we can't cross-verify with different tag
- assert_eq!(
- verify(pk, &original_keyset, original, &tag2, &msg),
- false
- );
-
- // Make sure we can't cross-verify with different message
- assert_eq!(
- verify(
- pk,
- &original_keyset,
- original,
- &tag2,
- &b"some other message"
- ),
- false
- );
- }
- }
- }
-
- #[test]
- #[should_panic(expected = "NotKeysetMember")]
- fn test_failure_not_in_keyset() {
- let tag = sha256::Hash::hash(b"ProtoTag");
- let all_keys = gen_secp_pubkeys(6);
- let mut pk = all_keys[0];
- let mut keyset: BTreeSet<_> =
- all_keys[1..].to_vec().into_iter().collect();
- let _ = commit(&mut keyset, &mut pk, &tag, b"Message").unwrap();
- }
-
- #[test]
- #[should_panic(expected = "SumInfiniteResult")]
- fn test_crafted_negation() {
- let tag = sha256::Hash::hash(b"ProtoTag");
- let mut pubkey = secp256k1::PublicKey::from_str(
- "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166",
- )
- .unwrap();
- let negkey = secp256k1::PublicKey::from_str(
- "0318845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166",
- )
- .unwrap();
- let mut keyset = bset![pubkey, negkey];
- let _ = commit(&mut keyset, &mut pubkey, &tag, b"Message").unwrap();
- }
-}
diff --git a/dbc-legacy/src/pktweak/lockscript.rs b/dbc-legacy/src/pktweak/lockscript.rs
deleted file mode 100644
index 0d31332a..00000000
--- a/dbc-legacy/src/pktweak/lockscript.rs
+++ /dev/null
@@ -1,503 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-//! # LNPBP-2
-//!
-//! Module implementing LNPBP-2 standard:
-//! Deterministic embedding of LNPBP1-type commitments into `scriptPubkey` of a
-//! transaction output
-//! [LNPBP-2](https://github.com/LNP-BP/lnpbps/blob/master/lnpbp-0002.md)
-//!
-//! The standard defines an algorithm for deterministic embedding and
-//! verification of cryptographic commitments based on elliptic-curve public and
-//! private key modifications (tweaks) inside all the existing types of Bitcoin
-//! transaction output and arbitrary complex Bitcoin scripts.
-
-use core::cell::RefCell;
-use std::collections::{BTreeSet, HashSet};
-
-use bitcoin::hashes::{hash160, sha256, Hmac};
-use bitcoin::{secp256k1, PubkeyHash};
-use bitcoin_scripts::LockScript;
-use commit_verify::EmbedCommitVerify;
-use miniscript::Segwitv0;
-
-use super::{KeysetCommitment, KeysetContainer};
-use crate::{Container, Error, Proof};
-
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct LockscriptContainer {
- pub script: LockScript,
- pub pubkey: secp256k1::PublicKey,
- /// Single SHA256 hash of the protocol-specific tag
- pub tag: sha256::Hash,
- /// Tweaking factor stored after [`LockscriptCommitment::embed_commit`]
- /// procedure
- pub tweaking_factor: Option>,
-}
-
-impl Container for LockscriptContainer {
- /// Out supplement is a protocol-specific tag in its hashed form
- type Supplement = sha256::Hash;
-
- type Host = Option<()>;
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- _: &Self::Host,
- ) -> Result {
- if let ScriptEncodeData::LockScript(ref script) = proof.source {
- Ok(Self {
- pubkey: proof.pubkey,
- script: script.clone(),
- tag: *supplement,
- tweaking_factor: None,
- })
- } else {
- Err(Error::InvalidProofStructure)
- }
- }
-
- #[inline]
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- (
- Proof {
- source: ScriptEncodeData::LockScript(self.script),
- pubkey: self.pubkey,
- },
- self.tag,
- )
- }
-
- #[inline]
- fn to_proof(&self) -> Proof {
- Proof {
- source: ScriptEncodeData::LockScript(self.script.clone()),
- pubkey: self.pubkey,
- }
- }
-
- #[inline]
- fn into_proof(self) -> Proof {
- Proof {
- source: ScriptEncodeData::LockScript(self.script),
- pubkey: self.pubkey,
- }
- }
-}
-
-/// [`LockScript`] containing public keys which sum is commit to some message
-/// according to LNPBP-2
-#[derive(
- Wrapper, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug,
- Display, From
-)]
-#[display(inner)]
-#[wrapper(LowerHex, UpperHex)]
-pub struct LockscriptCommitment(LockScript);
-
-impl EmbedCommitVerify for LockscriptCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = LockscriptContainer;
- type Error = Error;
-
- /// Function implements commitment procedure according to LNPBP-2.
- ///
- /// ## LNPBP-2 Specification extract:
- ///
- /// 1. The provided script MUST be parsed with Miniscript parser; if the
- /// parser fails the procedure MUST fail.
- /// 2. Iterate over all branches of the abstract syntax tree generated by
- /// the Miniscript parser, running the following algorithm for each node:
- /// - if a public key hash is met (`pk_h` Miniscript command) and it
- /// can't be resolved against known public keys or other public keys
- /// extracted from the script, fail the procedure;
- /// - if a public key is found (`pk`) add it to the list of the collected
- /// public keys;
- /// - for all other types of Miniscript commands iterate over their
- /// branches.
- /// 3. Select unique public keys (i.e. if some public key is repeated in
- /// different parts of the script/in different script branches, pick a
- /// single instance of it). Compressed and uncompressed versions of the
- /// same public key must be treaded as the same public key under this
- /// procedure.
- /// 4. If no public keys were found fail the procedure; return the collected
- /// keys otherwise.
- ///
- /// **NB: SUBJECT TO CHANGE UPON RELEASE**
- /// By "miniscript" we mean usage of `rust-miniscript` library at commit
- /// `a5ba1219feb8b5a289c8f12176d632635eb8a959`
- /// which may be found on
- ///
- // #[consensus_critical]
- // #[standard_critical("LNPBP-1")]
- fn embed_commit(
- container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- let original_hash =
- bitcoin::PublicKey::new(container.pubkey).pubkey_hash();
-
- let (keys, hashes) =
- container.script.extract_pubkey_hash_set::()?;
- if keys.is_empty() && hashes.is_empty() {
- return Err(Error::LockscriptContainsNoKeys);
- }
-
- let mut key_hashes: HashSet =
- keys.iter().map(bitcoin::PublicKey::pubkey_hash).collect();
- key_hashes.insert(original_hash);
- let keys: BTreeSet<_> = keys.into_iter().map(|pk| pk.key).collect();
-
- if hashes.is_empty() {
- keys.get(&container.pubkey)
- .ok_or(Error::LockscriptKeyNotFound)?;
- } else if hashes.into_iter().any(|hash| !key_hashes.contains(&hash)) {
- return Err(Error::LockscriptContainsUnknownHashes);
- }
-
- let mut keyset_container = KeysetContainer {
- pubkey: container.pubkey,
- keyset: keys,
- tag: container.tag,
- tweaking_factor: None,
- };
-
- let tweaked_pubkey =
- KeysetCommitment::embed_commit(&mut keyset_container, msg)?;
-
- container.tweaking_factor = keyset_container.tweaking_factor;
-
- let tweaked_hash =
- bitcoin::PublicKey::new(*tweaked_pubkey).pubkey_hash();
-
- let found = RefCell::new(0);
-
- // ! [CONSENSUS-CRITICAL]:
- // ! [STANDARD-CRITICAL]: Iterate over all branches of the abstract
- // syntax tree generated by the Miniscript
- // parser, running the following
- // algorithm for each node:
- let lockscript = container
- .script
- .replace_pubkeys_and_hashes::(
- |pubkey: &bitcoin::PublicKey| match pubkey.key
- == container.pubkey
- {
- true => {
- *found.borrow_mut() += 1;
- bitcoin::PublicKey::new(*tweaked_pubkey)
- }
- false => *pubkey,
- },
- |hash: &hash160::Hash| match *hash == original_hash.as_hash() {
- true => {
- *found.borrow_mut() += 1;
- tweaked_hash.as_hash()
- }
- false => *hash,
- },
- )?;
-
- Ok(lockscript.into())
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::str::FromStr;
-
- use bitcoin::hashes::{hash160, sha256, Hash};
- use miniscript::{Miniscript, Segwitv0};
-
- use super::*;
- use crate::Error;
-
- macro_rules! ms_str {
- ($($arg:tt)*) => (Miniscript::::from_str_insane(&format!($($arg)*)).unwrap())
- }
-
- macro_rules! policy_str {
- ($($arg:tt)*) => (miniscript::policy::Concrete::::from_str(&format!($($arg)*)).unwrap())
- }
-
- fn pubkeys(n: usize) -> Vec {
- let mut ret = Vec::with_capacity(n);
- let mut sk = [0; 32];
- for i in 1..n + 1 {
- sk[0] = i as u8;
- sk[1] = (i >> 8) as u8;
- sk[2] = (i >> 16) as u8;
-
- let pk =
- bitcoin::PublicKey::new(secp256k1::PublicKey::from_secret_key(
- &secp256k1::SECP256K1,
- &secp256k1::SecretKey::from_slice(&sk[..])
- .expect("secret key"),
- ));
- ret.push(pk);
- }
- ret
- }
-
- fn gen_test_data(
- ) -> (Vec, Vec, Vec) {
- let keys = pubkeys(13);
- let key_hashes =
- keys.iter().map(bitcoin::PublicKey::pubkey_hash).collect();
- let dummy_hashes = (1..13)
- .map(|i| hash160::Hash::from_inner([i; 20]))
- .collect();
- (keys, key_hashes, dummy_hashes)
- }
-
- #[test]
- fn test_no_keys_and_hashes() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, dummy_hashes) = gen_test_data();
- let sha_hash = sha256::Hash::hash(&"(nearly)random string".as_bytes());
-
- let ms = vec![
- ms_str!("older(921)"),
- ms_str!("sha256({})", sha_hash),
- ms_str!("hash256({})", sha_hash),
- ms_str!("hash160({})", dummy_hashes[0]),
- ms_str!("ripemd160({})", dummy_hashes[1]),
- ms_str!("hash160({})", dummy_hashes[2]),
- ];
-
- ms.into_iter()
- .map(|ms: Miniscript<_, _>| LockScript::from(ms.encode()))
- .for_each(|ls| {
- assert_eq!(
- LockscriptCommitment::embed_commit(
- &mut LockscriptContainer {
- script: ls,
- pubkey: keys[0].key,
- tag,
- tweaking_factor: None
- },
- &"Test message"
- )
- .err(),
- Some(Error::LockscriptContainsNoKeys)
- );
- });
- }
-
- #[test]
- fn test_unknown_key() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, _) = gen_test_data();
-
- let mut uncompressed = keys[5];
- uncompressed.compressed = false;
- let ms = vec![
- ms_str!("c:pk_k({})", keys[1]),
- ms_str!("c:pk_k({})", keys[2]),
- ms_str!("c:pk_k({})", keys[3]),
- ms_str!("c:pk_k({})", keys[4]),
- //ms_str!("c:pk({})", uncompressed),
- ];
-
- ms.into_iter()
- .map(|ms| LockScript::from(ms.encode()))
- .for_each(|ls| {
- assert_eq!(
- LockscriptCommitment::embed_commit(
- &mut LockscriptContainer {
- script: ls,
- pubkey: keys[0].key,
- tag,
- tweaking_factor: None
- },
- &"Test message"
- )
- .err(),
- Some(Error::LockscriptKeyNotFound)
- );
- });
- }
-
- #[test]
- fn test_unknown_hash() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, _) = gen_test_data();
-
- let ms = vec![
- ms_str!("c:pk_h({})", keys[1].pubkey_hash()),
- ms_str!("c:pk_h({})", keys[2].pubkey_hash()),
- ms_str!("c:pk_h({})", keys[3].pubkey_hash()),
- ms_str!("c:pk_h({})", keys[4].pubkey_hash()),
- ];
-
- ms.into_iter()
- .map(|ms| LockScript::from(ms.encode()))
- .for_each(|ls| {
- assert_eq!(
- LockscriptCommitment::embed_commit(
- &mut LockscriptContainer {
- script: ls,
- pubkey: keys[0].key,
- tag,
- tweaking_factor: None
- },
- &"Test message"
- )
- .err(),
- Some(Error::LockscriptContainsUnknownHashes)
- );
- });
- }
-
- #[test]
- fn test_known_key() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, _) = gen_test_data();
-
- let mut uncompressed = keys[5];
- uncompressed.compressed = false;
- let ms = vec![
- ms_str!("c:pk_k({})", keys[0]),
- ms_str!("c:pk_k({})", keys[1]),
- ms_str!("c:pk_k({})", keys[2]),
- ms_str!("c:pk_k({})", keys[3]),
- //ms_str!("c:pk_k({})", uncompressed),
- ];
-
- ms.into_iter()
- .map(|ms| LockScript::from(ms.encode()))
- .enumerate()
- .for_each(|(idx, ls)| {
- let container = LockscriptContainer {
- script: ls,
- pubkey: keys[idx].key,
- tag,
- tweaking_factor: None,
- };
- let msg = "Test message";
- let commitment = LockscriptCommitment::embed_commit(
- &mut container.clone(),
- &msg,
- )
- .unwrap();
- assert!(commitment.verify(&container, &msg).unwrap());
- });
- }
-
- #[test]
- fn test_known_hash() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, _) = gen_test_data();
-
- let ms = vec![
- ms_str!("c:pk_h({})", keys[0].pubkey_hash()),
- ms_str!("c:pk_h({})", keys[1].pubkey_hash()),
- ms_str!("c:pk_h({})", keys[2].pubkey_hash()),
- ms_str!("c:pk_h({})", keys[3].pubkey_hash()),
- ];
-
- ms.into_iter()
- .map(|ms| LockScript::from(ms.encode()))
- .enumerate()
- .for_each(|(idx, ls)| {
- let container = LockscriptContainer {
- script: ls,
- pubkey: keys[idx].key,
- tag,
- tweaking_factor: None,
- };
- let msg = "Test message";
- let commitment = LockscriptCommitment::embed_commit(
- &mut container.clone(),
- &msg,
- )
- .unwrap();
- assert!(commitment.verify(&container, &msg).unwrap())
- });
- }
-
- #[test]
- fn test_multisig() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, _) = gen_test_data();
-
- let ms: Vec> = vec![
- policy_str!("thresh(2,pk({}),pk({}))", keys[0], keys[1],),
- policy_str!(
- "thresh(3,pk({}),pk({}),pk({}),pk({}),pk({}))",
- keys[0],
- keys[1],
- keys[2],
- keys[3],
- keys[4]
- ),
- ]
- .into_iter()
- .map(|p| p.compile().unwrap())
- .collect();
-
- ms.into_iter()
- .map(|ms| LockScript::from(ms.encode()))
- .for_each(|ls| {
- let container = LockscriptContainer {
- script: ls,
- pubkey: keys[1].key,
- tag,
- tweaking_factor: None,
- };
- let msg = "Test message";
- let commitment = LockscriptCommitment::embed_commit(
- &mut container.clone(),
- &msg,
- )
- .unwrap();
- assert!(commitment.verify(&container, &msg).unwrap())
- });
- }
-
- #[test]
- fn test_complex_scripts_unique_key() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let (keys, _, _) = gen_test_data();
-
- let ms = policy_str!(
- "or(thresh(3,pk({}),pk({}),pk({})),and(thresh(2,pk({}),pk({})),\
- older(10000)))",
- keys[0],
- keys[1],
- keys[2],
- keys[3],
- keys[4],
- )
- .compile::()
- .unwrap();
-
- let container = LockscriptContainer {
- script: LockScript::from(ms.encode()),
- pubkey: keys[1].key,
- tag,
- tweaking_factor: None,
- };
- let msg = "Test message";
- let commitment =
- LockscriptCommitment::embed_commit(&mut container.clone(), &msg)
- .unwrap();
- assert!(commitment.verify(&container, &msg).unwrap())
- }
-}
diff --git a/dbc-legacy/src/pktweak/mod.rs b/dbc-legacy/src/pktweak/mod.rs
deleted file mode 100644
index 78e2f675..00000000
--- a/dbc-legacy/src/pktweak/mod.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-#[cfg(feature = "miniscript")]
-pub mod keyset;
-pub mod lnpbp1;
-#[cfg(feature = "miniscript")]
-pub mod lockscript;
-pub mod pubkey;
-#[cfg(feature = "miniscript")]
-pub mod scriptpubkey;
-pub mod taproot;
-#[cfg(feature = "miniscript")]
-pub mod txout;
-
-use bitcoin::hashes::sha256;
-use bitcoin_scripts::LockScript;
-#[cfg(feature = "miniscript")]
-pub use keyset::{KeysetCommitment, KeysetContainer};
-#[cfg(feature = "miniscript")]
-pub use lockscript::{LockscriptCommitment, LockscriptContainer};
-pub use pubkey::{PubkeyCommitment, PubkeyContainer};
-#[cfg(feature = "miniscript")]
-pub use scriptpubkey::{
- ScriptEncodeData, ScriptEncodeMethod, SpkCommitment, SpkContainer,
-};
-pub use taproot::{TaprootCommitment, TaprootContainer};
-#[cfg(feature = "miniscript")]
-pub use txout::{TxoutCommitment, TxoutContainer};
-
-/// Structure keeping the minimum of information (bytewise) required to verify
-/// deterministic bitcoin commitment given only the transaction source, its
-/// fee and protocol-specific constants. It is a part of the [`Proof`] data.
-#[derive(Clone, PartialEq, Eq, Hash, Debug, Display)]
-#[derive(StrictEncode, StrictDecode)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-#[display(doc_comments)]
-pub enum ScriptEncodeData {
- /// Public key. Since we keep the original public key as a part of a proof,
- /// and value of the tweaked key can be reconstructed with DBC source data
- /// and the original pubkey, so we do not need to keep any additional data
- /// here).
- SinglePubkey,
-
- /// Any output containing script information, aside from OP_RETURN outputs
- /// (using [`ScriptEncodeData::SinglePubkey`]) and tapscript.
- /// We have to store full original script in it's byte form since when
- /// the deteministic bitcoin commitment is verified, the output may be
- /// still unspent and we will not be able to reconstruct the script without
- /// this data kept in the client-validated part.
- LockScript(LockScript),
-
- // TODO: Add `WrappedWitnessScript(WitnessScript) variant
- /// Taproot-based outputs. We need to keep only the hash of the taprscript
- /// merkle tree root.
- Taproot(sha256::Hash),
-}
diff --git a/dbc-legacy/src/pktweak/pubkey.rs b/dbc-legacy/src/pktweak/pubkey.rs
deleted file mode 100644
index 44964855..00000000
--- a/dbc-legacy/src/pktweak/pubkey.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use bitcoin::hashes::{sha256, Hmac};
-use commit_verify::EmbedCommitVerify;
-
-use super::lnpbp1;
-use crate::{Container, Error, Proof};
-
-/// Container for LNPBP-1 commitments. In order to be constructed, commitment
-/// requires an original public key and a protocol-specific tag, which
-/// must be hashed during commitment process. Here we use pre-hashed version
-/// of the tag in order to maximize performance for multiple commitments.
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct PubkeyContainer {
- /// The original public key: host for commitment
- pub pubkey: secp256k1::PublicKey,
- /// Single SHA256 hash of the protocol-specific tag
- pub tag: sha256::Hash,
- /// Tweaking factor stored after [`PubkeyCommitment::embed_commit`]
- /// procedure
- pub tweaking_factor: Option>,
-}
-
-impl Container for PubkeyContainer {
- /// Our supplement is a protocol-specific tag in its hashed form
- type Supplement = sha256::Hash;
- /// Our proof contains the host, so we don't need host here
- type Host = Option<()>;
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- _: &Self::Host,
- ) -> Result {
- Ok(Self {
- pubkey: proof.public_key()?,
- tag: *supplement,
- tweaking_factor: None,
- })
- }
-
- #[inline]
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- (Proof::from(self.pubkey), self.tag)
- }
-
- // A proof for the LNPBP-1 public key commitment is the original public key
- // value, so the commitment container (original public key) just returns a
- // copy of itself
- #[inline]
- fn to_proof(&self) -> Proof {
- Proof::from(self.pubkey)
- }
-
- #[inline]
- fn into_proof(self) -> Proof {
- Proof::from(self.pubkey)
- }
-}
-
-/// Public key committed to some message via LNPBP1-based tweaking procedure
-#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, Display, From)]
-#[display("{0}", alt = "{_0:#}*")]
-#[wrapper(FromStr, LowerHex)]
-pub struct PubkeyCommitment(secp256k1::PublicKey);
-
-impl EmbedCommitVerify for PubkeyCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = PubkeyContainer;
- type Error = lnpbp1::Error;
-
- // #[consensus_critical("RGB")]
- // #[standard_critical("LNPBP-1")]
- fn embed_commit(
- pubkey_container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- let mut keyset = bset![pubkey_container.pubkey];
- let mut pubkey = pubkey_container.pubkey;
-
- let tweaking_factor = lnpbp1::commit(
- &mut keyset,
- &mut pubkey,
- &pubkey_container.tag,
- msg,
- )?;
-
- pubkey_container.tweaking_factor = Some(tweaking_factor);
-
- // Returning tweaked public key
- Ok(PubkeyCommitment(pubkey))
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::str::FromStr;
-
- use amplify::hex::ToHex;
- use amplify::Wrapper;
- use bitcoin::hashes::{sha256, Hash};
-
- use super::lnpbp1::test_helpers::*;
- use super::*;
-
- #[test]
- fn test_pubkey_commitment() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- gen_secp_pubkeys(9).into_iter().for_each(|pubkey| {
- embed_commit_verify_suite::, PubkeyCommitment>(
- gen_messages(),
- &mut PubkeyContainer {
- pubkey,
- tag,
- tweaking_factor: None,
- },
- );
- });
- }
-
- #[test]
- fn test_tweaking_results() {
- let tag = sha256::Hash::hash(b"TEST_TAG");
- let msg = "test message";
- let pubkey = secp256k1::PublicKey::from_str(
- "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166",
- )
- .unwrap();
- let commitment = PubkeyCommitment::embed_commit(
- &mut PubkeyContainer {
- pubkey,
- tag,
- tweaking_factor: None,
- },
- &msg,
- )
- .unwrap();
- assert_eq!(
- commitment.as_inner().to_hex(),
- "02de6531527f7a453e0b53e4b33a78c60f9bcdb69abbf59866e33de347ceda0bdf"
- );
- }
-}
diff --git a/dbc-legacy/src/pktweak/scriptpubkey.rs b/dbc-legacy/src/pktweak/scriptpubkey.rs
deleted file mode 100644
index 1067d122..00000000
--- a/dbc-legacy/src/pktweak/scriptpubkey.rs
+++ /dev/null
@@ -1,184 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use core::convert::TryFrom;
-
-use amplify::Wrapper;
-use bitcoin::blockdata::script::Script;
-use bitcoin::hashes::{sha256, Hmac};
-use bitcoin_scripts::convert::ToPubkeyScript;
-use bitcoin_scripts::{Category, LockScript, PubkeyScript};
-use commit_verify::EmbedCommitVerify;
-
-use super::{
- LockscriptCommitment, LockscriptContainer, PubkeyCommitment,
- PubkeyContainer, ScriptEncodeData, TaprootCommitment, TaprootContainer,
-};
-use crate::{Container, Error, Proof};
-
-/// Structure with a set of allowed transaction output-based commitment schema.
-///
-/// Transaction output-based commitments can be created with a different
-/// schemata, specific to a specific structure of `scriptPubkey`. Different
-/// client-side-validation protocols, working with output-based commitments may
-/// allow different forms of commitments; for instance RGBv1 requires that
-/// only tapscript-based op_return commitments must be supported inside P2TR
-/// outputs. This structure allows to specify the list of supported commitment
-/// schemata as a set of flags.
-#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default)]
-pub struct CommitmentSchema {
- /// Tweaks of a single pubkey using LNPBP-1 schema inside P2PK output.
- pub p2pk_tweak: bool,
-
- /// Tweaks of a single pubkey using LNPBP-1 schema inside P2PKH output.
- pub p2pkh_tweak: bool,
-
- /// Tweaks of a single pubkey using LNPBP-1 schema inside P2WPKH output.
- pub p2wpkh_tweak: bool,
-
- /// Tweaks of a single pubkey using LNPBP-1 schema inside a legacy
- /// P2WPKH-in-P2SH output.
- pub p2wpkh_sh_tweak: bool,
-
- /// Tweaks of a keyset according to LNPBP-1 schema inside a bare scripts
- /// contained within `pubkeyScript`. The set of keys is extracted from the
- /// script using LNPBP-2 schema.
- pub bare_tweak: bool,
-
- /// Tweaks of a keyset according to LNPBP-1 schema inside a plain
- /// (non-witness-nested) P2SH outputs. The set of keys is extracted from the
- /// script using LNPBP-2 schema.
- pub p2sh_tweak: bool,
-
- /// Tweaks of a keyset according to LNPBP-1 schema inside a non-nested/
- /// non-legacy P2WSH outputs. The set of keys is extracted from the
- /// script using LNPBP-2 schema.
- pub p2wsh_tweak: bool,
-
- /// Tweaks of a keyset according to LNPBP-1 schema inside the nested/
- /// legacy P2WSH-in-P2SH outputs. The set of keys is extracted from the
- /// script using LNPBP-2 schema.
- pub p2wsh_sh_tweak: bool,
-
- /// Commitment directly added to a single and alone `OP_RETURN` operation
- /// contained in a bare `scriptPubkey` in transaction output.
- pub p2pk_return: bool,
-
- /// Commitment put inside a single `OP_RETURN` tapscript code in the first
- /// leaf of taproot script path spending according to LNPBP-6 schema.
- pub p2tr_return: bool,
-}
-
-impl CommitmentSchema {
- /// Sets/clears flags for all commitment schemata based on tweaking of a
- /// single public key (P2PK, P2PKH, P2WPKH, P2WPKH-in-P2SH).
- pub fn update_pubkey_tweaks(&mut self, allow: bool) {
- self.p2pk_tweak = allow;
- self.p2pkh_tweak = allow;
- self.p2wpkh_tweak = allow;
- self.p2wpkh_sh_tweak = allow;
- }
-
- /// Sets/clears flags for all commitment schemata based on tweaking of a
- /// public key set extracted from a script (Bare, P2PSH, P2WSH,
- /// P2WSH-in-P2SH).
- pub fn update_script_tweaks(&mut self, allow: bool) {
- self.bare_tweak = allow;
- self.p2sh_tweak = allow;
- self.p2wsh_tweak = allow;
- self.p2wsh_sh_tweak = allow;
- }
-}
-
-/// Ephemeral/intermediary structure used as a container storing all data
-/// participating in the creation or verification of a specific commitment.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct SpkContainer {
- /// Extra-transaction proof of the commitment
- pub proof: Proof,
-
- /// Set of allowed commitment schemata.
- ///
- /// The set is defined by the specific client-side-validation protocol.
- pub allowed: CommitmentSchema,
-
- /// Single SHA256 hash of the protocol-specific tag
- pub tag: sha256::Hash,
-
- /// Tweaking factor stored after [`SpkCommitment::embed_commit`]
- /// procedure
- pub tweaking_factor: Option>,
-}
-
-impl Container for SpkContainer {
- /// Supplement is a protocol-specific tag in its hashed form and protocol-
- /// defined set of allowed commitment schemata.
- type Supplement = (sha256::Hash, CommitmentSchema);
-
- /// The host for the commitment is a `scriptPubkey` of a transaction output
- /// which is a part of the [`Proof`], so we do not use it here.
- type Host = ();
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- _host: &Self::Host,
- ) -> Result {
- Ok(SpkContainer {
- proof: proof.clone(),
- allowed: supplement.1,
- tag: supplement.0,
- tweaking_factor: None,
- })
- }
-
- #[inline]
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- (self.proof, (self.tag, self.allowed))
- }
-
- #[inline]
- fn to_proof(&self) -> Proof {
- self.proof.clone()
- }
-
- #[inline]
- fn into_proof(self) -> Proof {
- self.proof
- }
-}
-
-/// [`PubkeyScript`] containing LNPBP-2 commitment
-#[derive(
- Wrapper, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug,
- Display, From
-)]
-#[display(inner)]
-#[wrapper(LowerHex, UpperHex)]
-pub struct SpkCommitment(PubkeyScript);
-
-impl EmbedCommitVerify for SpkCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = SpkContainer;
- type Error = super::Error;
-
- fn embed_commit(
- container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- }
-}
diff --git a/dbc-legacy/src/pktweak/taproot.rs b/dbc-legacy/src/pktweak/taproot.rs
deleted file mode 100644
index 0558d57a..00000000
--- a/dbc-legacy/src/pktweak/taproot.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use amplify::Wrapper;
-use bitcoin::hashes::{sha256, Hmac};
-use bitcoin::{secp256k1, XOnlyPublicKey};
-use commit_verify::EmbedCommitVerify;
-
-use super::{PubkeyCommitment, PubkeyContainer};
-use crate::{Container, Error, Proof};
-
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct TaprootContainer {
- pub script_root: sha256::Hash,
- pub intermediate_key: XOnlyPublicKey,
- /// Single SHA256 hash of the protocol-specific tag
- pub tag: sha256::Hash,
- /// Tweaking factor stored after [`TaprootCommitment::embed_commit`]
- /// procedure
- pub tweaking_factor: Option>,
-}
-
-impl Container for TaprootContainer {
- /// Out supplement is a protocol-specific tag in its hashed form
- type Supplement = sha256::Hash;
- /// Our proof contains the host, so we don't need host here
- type Host = Option<()>;
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- _: &Self::Host,
- ) -> Result {
- match proof {
- Proof::XOnlyKeyTaproot {
- internal_key,
- merkle_subroot,
- } => Ok(Self {
- script_root: *merkle_subroot,
- intermediate_key: XOnlyPublicKey::from_slice(
- internal_key.as_inner(),
- )
- .map_err(|_| Error::InvalidProofStructure)?,
- tag: *supplement,
- tweaking_factor: None,
- }),
- _ => Err(Error::InvalidProofStructure),
- }
- }
-
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- (self.to_proof(), self.tag)
- }
-
- #[inline]
- fn to_proof(&self) -> Proof {
- Proof::XOnlyKeyTaproot {
- internal_key: self.intermediate_key.serialize().into(),
- merkle_subroot: self.script_root,
- }
- }
-
- #[inline]
- fn into_proof(self) -> Proof {
- self.to_proof()
- }
-}
-
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct TaprootCommitment {
- pub script_root: sha256::Hash,
- pub intermediate_key_commitment: PubkeyCommitment,
-}
-
-impl EmbedCommitVerify for TaprootCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = TaprootContainer;
- type Error = Error;
-
- fn embed_commit(
- container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- let mut data: Vec = vec![0x02];
- data.extend(container.intermediate_key.serialize().iter());
- let pubkey = secp256k1::PublicKey::from_slice(&data).expect(
- "Failed to construct 33 Publickey from 0x02 appended x-only key",
- );
-
- let mut pubkey_container = PubkeyContainer {
- pubkey,
- tag: container.tag,
- tweaking_factor: None,
- };
-
- let cmt = PubkeyCommitment::embed_commit(&mut pubkey_container, msg)?;
-
- container.tweaking_factor = pubkey_container.tweaking_factor;
-
- Ok(Self {
- script_root: container.script_root,
- intermediate_key_commitment: cmt,
- })
- }
-}
diff --git a/dbc-legacy/src/pktweak/txout.rs b/dbc-legacy/src/pktweak/txout.rs
deleted file mode 100644
index 4fcc0ed8..00000000
--- a/dbc-legacy/src/pktweak/txout.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use amplify::Wrapper;
-use bitcoin::hashes::{sha256, Hmac};
-use bitcoin::{secp256k1, TxOut};
-use bitcoin_scripts::PubkeyScript;
-use commit_verify::EmbedCommitVerify;
-
-use super::{
- ScriptEncodeData, ScriptEncodeMethod, SpkCommitment, SpkContainer,
-};
-use crate::{Container, Error, Proof};
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct TxoutContainer {
- pub value: u64,
- pub script_container: SpkContainer,
- /// Tweaking factor stored after [`TxoutCommitment::embed_commit`]
- /// procedure
- pub tweaking_factor: Option>,
-}
-
-impl TxoutContainer {
- pub fn construct(
- protocol_tag: &sha256::Hash,
- value: u64,
- pubkey: secp256k1::PublicKey,
- source: ScriptEncodeData,
- method: ScriptEncodeMethod,
- ) -> Self {
- Self {
- value,
- script_container: SpkContainer::construct(
- protocol_tag,
- pubkey,
- source,
- method,
- ),
- tweaking_factor: None,
- }
- }
-}
-
-impl Container for TxoutContainer {
- /// Out supplement is a protocol-specific tag in its hashed form
- type Supplement = sha256::Hash;
- type Host = TxOut;
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- host: &Self::Host,
- ) -> Result {
- Ok(Self {
- value: host.value,
- script_container: SpkContainer::reconstruct(
- proof,
- supplement,
- &PubkeyScript::from_inner(host.clone().script_pubkey),
- )?,
- tweaking_factor: None,
- })
- }
-
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- self.script_container.deconstruct()
- }
-
- fn to_proof(&self) -> Proof {
- self.script_container.to_proof()
- }
-
- fn into_proof(self) -> Proof {
- self.script_container.into_proof()
- }
-}
-
-/// [`bitcoin::TxOut`] containing LNPBP-2 commitment
-#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Default, Debug, From)]
-pub struct TxoutCommitment(TxOut);
-
-impl EmbedCommitVerify for TxoutCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = TxoutContainer;
- type Error = Error;
-
- fn embed_commit(
- container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- let commitment = TxOut {
- value: container.value,
- script_pubkey: (**SpkCommitment::embed_commit(
- &mut container.script_container,
- msg,
- )?)
- .clone(),
- };
-
- container.tweaking_factor = container.script_container.tweaking_factor;
-
- Ok(commitment.into())
- }
-}
diff --git a/dbc-legacy/src/proof.rs b/dbc-legacy/src/proof.rs
deleted file mode 100644
index 7c067a5f..00000000
--- a/dbc-legacy/src/proof.rs
+++ /dev/null
@@ -1,164 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use amplify::{Slice32, Wrapper};
-use bitcoin::hashes::sha256;
-
-use crate::Error;
-
-/// Extra-transaction proof of a deterministic bitcoin commitment.
-///
-/// Encodes only extra-transaction data in the most compact form; without
-/// information on which specific commitment type is used. The commitment type
-/// must be determined by the protocol data and transaction structure.
-///
-/// Proof does not stores the actual key data internally not to consume
-/// resources on validating elliptic key points each time the proof is
-/// deserialized (client-side-validated data may contain many thousands of
-/// proofs and such validation may significantly reduce performance).
-#[derive(Clone, PartialEq, Eq, Hash, Debug, Display)]
-#[derive(StrictEncode, StrictDecode)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-#[display("proof({pubkey}, {source}")]
-pub enum Proof {
- /// No extra-transaction data are required
- #[strict_encoding(value = 0x01)]
- Embedded,
-
- /// Extra-transaction proof consists of a single public key.
- ///
- /// This variant covers even public keys, prefixed with `0x02` as a part of
- /// the proof type data.
- #[strict_encoding(value = 0x02)]
- EvenKey(Slice32),
-
- /// Extra-transaction proof consists of a single public key.
- ///
- /// This variant covers odd public keys, prefixed with `0x03` as a part of
- /// the proof type data.
- #[strict_encoding(value = 0x03)]
- OddKey(Slice32),
-
- // 0x04 encoding is skipped to distinguish with a stored uncompressed keys
- /// Extra-transaction proof consists of a single public key as a part of
- /// P2WPKH-in-P2SH nested legacy structure.
- ///
- /// This variant covers even public keys.
- #[strict_encoding(value = 0x05)]
- NestedEvenKey(Slice32),
-
- /// Extra-transaction proof consists of a single public key as a part of
- /// P2WPKH-in-P2SH nested legacy structure.
- ///
- /// This variant covers odd public keys.
- #[strict_encoding(value = 0x06)]
- NestedOddKey(Slice32),
-
- /// Extra-transaction proof consists of a single public key and script.
- ///
- /// This variant covers even public keys.
- #[strict_encoding(value = 0x07)]
- ScriptEvenKey {
- target_key: Slice32,
- script: Box<[u8]>,
- },
-
- /// Extra-transaction proof consists of a single public key and script.
- ///
- /// This variant covers odd public keys.
- #[strict_encoding(value = 0x08)]
- ScriptOddKey {
- target_key: Slice32,
- script: Box<[u8]>,
- },
-
- /// Extra-transaction proof consists of a single public key and witness
- /// script structured as P2WSH-in-P2SH nested legacy structure.
- ///
- /// This variant covers even public keys.
- #[strict_encoding(value = 0x09)]
- NestedScriptEvenKey {
- target_key: Slice32,
- script: Box<[u8]>,
- },
-
- /// Extra-transaction proof consists of a single public key and witness
- /// script structured as P2WSH-in-P2SH nested legacy structure.
- ///
- /// This variant covers odd public keys.
- #[strict_encoding(value = 0x10)]
- NestedScriptOddKey {
- target_key: Slice32,
- script: Box<[u8]>,
- },
-
- /// Extra-transaction proof consists of a taproot internal public key and
- /// a merkle proof for a second branch of the merkle tree in the taproot
- /// script tree.
- #[strict_encoding(value = 0x11)]
- XOnlyKeyTaproot {
- internal_key: Slice32,
- merkle_subroot: sha256::Hash,
- },
-}
-
-impl From for Proof {
- fn from(pubkey: secp256k1::PublicKey) -> Self {
- let data = pubkey.serialize();
- let inner =
- Slice32::from_slice(&data[1..]).expect("fixed-length slice");
- match data[0] {
- 0x02 => Proof::EvenKey(inner),
- 0x03 => Proof::OddKey(inner),
- _ => unreachable!(
- "Secp256k1 public key with non-0x02 and non-0x03 prefix"
- ),
- }
- }
-}
-
-impl Proof {
- pub fn public_key(&self) -> Result {
- let mut data: Vec = Vec::with_capacity(32);
-
- match self {
- Proof::Embedded => return Err(Error::InvalidProofStructure),
- Proof::EvenKey(pk)
- | Proof::NestedEvenKey(pk)
- | Proof::ScriptEvenKey { target_key: pk, .. }
- | Proof::NestedScriptEvenKey { target_key: pk, .. }
- | Proof::XOnlyKeyTaproot {
- internal_key: pk, ..
- } => {
- data.extend([0x02]);
- data.extend(pk.as_inner());
- }
- Proof::OddKey(pk)
- | Proof::NestedOddKey(pk)
- | Proof::ScriptOddKey { target_key: pk, .. }
- | Proof::NestedScriptOddKey { target_key: pk, .. } => {
- data.extend([0x03]);
- data.extend(pk.as_inner());
- }
- }
-
- Ok(secp256k1::PublicKey::from_slice(&data)
- .expect("fixed-size public key"))
- }
-}
diff --git a/dbc-legacy/src/sigtweak/mod.rs b/dbc-legacy/src/sigtweak/mod.rs
deleted file mode 100644
index 72b75294..00000000
--- a/dbc-legacy/src/sigtweak/mod.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
diff --git a/dbc-legacy/src/tapret/mod.rs b/dbc-legacy/src/tapret/mod.rs
deleted file mode 100644
index f66ad8b6..00000000
--- a/dbc-legacy/src/tapret/mod.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-//! Taproot OP_RETURN-based deterministic commitments.
-//!
-//! Option + message -> merkle_path*
-
-use bitcoin::util::taproot::{TaprootMerkleBranch, TaprootSpendInfo};
-use commit_verify::EmbedCommitVerify;
-use secp256k1::XOnlyPublicKey;
-
-pub struct TapretProtocol;
-
-pub enum TaprootCommitError {
- TooDeepTree,
-}
-
-impl EmbedCommitVerify for TaprootMerkleBranch {
- type Proof = TaprootMerkleBranch;
- type Protocol = TapretProtocol;
- type CommitError = TaprootCommitError;
-
- fn embed_commit(
- &mut self,
- msg: &AnchorId,
- ) -> Result {
- let proof = self.clone();
- self.0.push(msg.as_ref());
- Ok(proof)
- }
-}
-
-impl EmbedCommitVerify for TaprootSpendInfo {
- type Proof = (TaprootMerkleBranch, XOnlyPublicKey);
- type Protocol = TapretProtocol;
- type CommitError = TaprootCommitError;
-
- fn embed_commit(
- &mut self,
- msg: &AnchorId,
- ) -> Result {
- self.push_script()
- }
-}
diff --git a/dbc-legacy/src/tx/feeproto.rs b/dbc-legacy/src/tx/feeproto.rs
deleted file mode 100644
index a327a578..00000000
--- a/dbc-legacy/src/tx/feeproto.rs
+++ /dev/null
@@ -1,211 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use amplify::Wrapper;
-use bitcoin::hashes::{sha256, Hmac};
-use bitcoin::{secp256k1, Transaction, TxOut};
-use commit_verify::EmbedCommitVerify;
-
-use crate::spk::{ScriptEncodeData, TxoutCommitment, TxoutContainer};
-use crate::{Container, Error, Proof};
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct TxContainer {
- pub protocol_factor: u32,
- pub fee: u64,
- pub txout_container: TxoutContainer,
- pub tx: Transaction,
- /// Tweaking factor stored after [`TxCommitment::embed_commit`] procedure
- pub tweaking_factor: Option>,
-}
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct TxSupplement {
- pub protocol_factor: u32,
- pub fee: u64,
- /// Single SHA256 hash of the protocol-specific tag
- pub tag: sha256::Hash,
-}
-
-impl TxContainer {
- pub fn construct(
- protocol_factor: u32,
- protocol_tag: &sha256::Hash,
- fee: u64,
- tx: Transaction,
- pubkey: secp256k1::PublicKey,
- source: ScriptEncodeData,
- method: ScriptEncodeMethod,
- ) -> Self {
- let mut me = Self {
- tx,
- fee,
- protocol_factor,
- txout_container: TxoutContainer::construct(
- protocol_tag,
- 0,
- pubkey,
- source,
- method,
- ),
- tweaking_factor: None,
- };
- me.txout_container.value = me.tx.output[me.vout()].value;
- me
- }
-
- pub fn vout(&self) -> usize {
- let nouts = self.tx.output.len() as u16;
- let vout = ((self.fee + (self.protocol_factor as u64)) % (nouts as u64))
- as u16;
- vout as usize
- }
-}
-
-impl Container for TxContainer {
- type Supplement = TxSupplement;
- type Host = Transaction;
-
- fn reconstruct(
- proof: &Proof,
- supplement: &Self::Supplement,
- host: &Self::Host,
- ) -> Result {
- let mut me = Self {
- protocol_factor: supplement.protocol_factor,
- fee: supplement.fee,
- txout_container: TxoutContainer::reconstruct(
- proof,
- &supplement.tag,
- &TxOut::default(),
- )?,
- tx: host.clone(),
- tweaking_factor: None,
- };
- me.txout_container = TxoutContainer::reconstruct(
- proof,
- &supplement.tag,
- &host.output[me.vout()],
- )?;
- Ok(me)
- }
-
- fn deconstruct(self) -> (Proof, Self::Supplement) {
- (
- self.txout_container.clone().into_proof(),
- TxSupplement {
- protocol_factor: self.protocol_factor,
- fee: self.fee,
- tag: self.txout_container.script_container.tag,
- },
- )
- }
-
- fn to_proof(&self) -> Proof {
- self.txout_container.to_proof()
- }
-
- fn into_proof(self) -> Proof {
- self.txout_container.into_proof()
- }
-}
-
-/// [`bitcoin::Transaction`] containing LNPBP-3 commitment
-#[derive(Wrapper, Clone, PartialEq, Eq, Hash, Debug, From)]
-pub struct TxCommitment(Transaction);
-
-impl EmbedCommitVerify for TxCommitment
-where
- MSG: AsRef<[u8]>,
-{
- type Container = TxContainer;
- type Error = Error;
-
- fn embed_commit(
- container: &mut Self::Container,
- msg: &MSG,
- ) -> Result {
- let mut tx = container.tx.clone();
-
- let txout_commitment =
- TxoutCommitment::embed_commit(&mut container.txout_container, msg)?;
- tx.output[container.vout()] = txout_commitment.into_inner();
-
- container.tweaking_factor = container.txout_container.tweaking_factor;
-
- Ok(tx.into())
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::str::FromStr;
-
- use bitcoin::consensus::encode::deserialize;
- use bitcoin::hashes::hex::FromHex;
-
- use super::*;
- use crate::spk::{ScriptEncodeData, ScriptEncodeMethod, SpkContainer};
-
- #[test]
- fn test_ability_to_commit() {
- let tx = deserialize(Vec::from_hex(
- "020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c9100000000\
- 6a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a802201395963\
- 2492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a\
- 7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818\
- dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffff\
- ffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d0\
- 4cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5a\
- b979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c58\
- 8ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b0000000000\
- 1976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a\
- 8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d47\
- 57de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03\
- b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80\
- 328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10d\
- a6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e\
- 10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322\
- a18b920a4dfa887d30700")
- .unwrap().as_slice()).unwrap();
-
- let mut container = TxContainer {
- tx,
- fee: 0,
- protocol_factor: 0,
- txout_container: TxoutContainer {
- value: 0,
- script_container: SpkContainer {
- pubkey: secp256k1::PublicKey::from_str(
- "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166",
- )
- .unwrap(),
- source: ScriptEncodeData::SinglePubkey,
- method: ScriptEncodeMethod::PublicKey,
- tag: Default::default(),
- tweaking_factor: None,
- },
- tweaking_factor: None,
- },
- tweaking_factor: None,
- };
-
- let msg = "message to commit to";
-
- let commitment =
- TxCommitment::embed_commit(&mut container, &msg).unwrap();
- assert_eq!(commitment.verify(&container, &msg).unwrap(), true);
- }
-}
diff --git a/dbc-legacy/src/tx/lnpbp3.rs b/dbc-legacy/src/tx/lnpbp3.rs
deleted file mode 100644
index e69de29b..00000000
diff --git a/dbc-legacy/src/tx/lnpbp9.rs b/dbc-legacy/src/tx/lnpbp9.rs
deleted file mode 100644
index e69de29b..00000000
diff --git a/dbc-legacy/src/tx/mod.rs b/dbc-legacy/src/tx/mod.rs
deleted file mode 100644
index 6a3ddc30..00000000
--- a/dbc-legacy/src/tx/mod.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-// `feeproto` requires support for tweaking arbitrary txout output; which
-// implies requirement for miniscript-based script parsing for collecting
-// all script keys from P2(W)SH outputs
-#[cfg(feature = "miniscript")]
-pub mod feeproto;
diff --git a/dbc/Cargo.toml b/dbc/Cargo.toml
index a5ff8719..c204e9cd 100644
--- a/dbc/Cargo.toml
+++ b/dbc/Cargo.toml
@@ -1,34 +1,38 @@
[package]
name = "bp-dbc"
-version = "0.9.0"
-license = "Apache-2.0"
-authors = ["Dr. Maxim Orlovsky "]
+version = "0.10.0-beta.1"
description = "Deterministic bitcoin commitments library"
-repository = "https://github.com/LNP-BP/bp-core"
-homepage = "https://github.com/LNP-BP"
-keywords = ["lnp-bp", "bitcoin", "cryptography", "smart-contracts", "single-use-seals"]
-categories = ["cryptography::cryptocurrencies", "encoding"]
+keywords = ["lnp-bp", "bitcoin", "blockchain", "smart-contracts", "single-use-seals"]
+categories = ["cryptography", "encoding"]
+authors = { workspace = true }
+repository = { workspace = true }
+homepage = { workspace = true }
+edition = { workspace = true }
+license = { workspace = true }
+rust-version = { workspace = true }
readme = "../README.md"
-edition = "2021"
-rust-version = "1.59.0"
[lib]
name = "dbc"
path = "src/lib.rs"
[dependencies]
-amplify = "3.13.0"
-bitcoin = "0.29.2"
-secp256k1 = { version = "0.24.2", features = ["global-context", "rand-std"] }
-bitcoin_scripts = "0.9.0"
-psbt = { version = "0.9.0", default-features = false, optional = true }
-strict_encoding = "0.9.0"
-commit_verify = { version = "0.9.0", features = ["rand"] }
+amplify = "4.0.0-beta.10"
+bp-primitives = { version = "0.10.0-beta.1", path = "../primitives" }
+secp256k1 = { version = "0.26.0", features = ["global-context", "rand-std"] }
+strict_encoding = "2.0.0-beta.5"
+commit_verify = { version = "0.10.0-beta.1", features = ["rand"] }
serde_crate = { package = "serde", version = "1", features = ["derive"], optional = true }
-serde_with = { version = "1.14", optional = true }
[features]
default = []
-all = ["serde", "wallet"]
-wallet = ["psbt"]
-serde = ["amplify/serde", "bitcoin/serde", "bitcoin_scripts/serde", "commit_verify/serde", "serde_crate", "serde_with"]
+all = ["serde"]
+serde = [
+ "serde_crate",
+ "bp-primitives/serde",
+ "commit_verify/serde",
+ "secp256k1/serde"
+]
+
+[package.metadata.docs.rs]
+features = [ "all" ]
diff --git a/dbc/src/anchor.rs b/dbc/src/anchor.rs
index 55b89443..4805b51e 100644
--- a/dbc/src/anchor.rs
+++ b/dbc/src/anchor.rs
@@ -1,17 +1,23 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
//! Anchors are data structures used in deterministic bitcoin commitments for
//! keeping information about the proof of the commitment in connection to the
@@ -19,83 +25,36 @@
//! defined by LNPBP-4.
use std::cmp::Ordering;
-use std::io::Write;
-
-use amplify::Wrapper;
-use bitcoin::hashes::{sha256, sha256t};
-use bitcoin::{Script, Transaction, Txid};
-use commit_verify::convolve_commit::ConvolveCommitProof;
-use commit_verify::lnpbp4::{self, Message, ProtocolId};
-use commit_verify::{
- CommitEncode, CommitVerify, ConsensusCommit, PrehashedProtocol, TaggedHash,
-};
-#[cfg(feature = "wallet")]
-use commit_verify::{EmbedCommitProof, EmbedCommitVerify, TryCommitVerify};
-#[cfg(feature = "wallet")]
-use psbt::Psbt;
-use strict_encoding::StrictEncode;
-
-#[cfg(feature = "wallet")]
-use crate::tapret::{Lnpbp6, PsbtCommitError, PsbtVerifyError};
+
+use amplify::{Bytes32, Wrapper};
+use bc::{ScriptPubkey, Tx, Txid, LIB_NAME_BP};
+use commit_verify::mpc::{self, Message, ProtocolId};
+use commit_verify::{strategies, CommitStrategy, CommitmentId, ConvolveCommitProof};
+use strict_encoding::{StrictDumb, StrictEncode};
+
use crate::tapret::{TapretError, TapretProof};
/// Default depth of LNPBP-4 commitment tree
pub const ANCHOR_MIN_LNPBP4_DEPTH: u8 = 3;
-static MIDSTATE_ANCHOR_ID: [u8; 32] = [
- 148, 72, 59, 59, 150, 173, 163, 140, 159, 237, 69, 118, 104, 132, 194, 110,
- 250, 108, 1, 140, 74, 248, 152, 205, 70, 32, 184, 87, 20, 102, 127, 20,
-];
-
-/// Tag used for [`AnchorId`] hash type
-pub struct AnchorIdTag;
-
-impl sha256t::Tag for AnchorIdTag {
- #[inline]
- fn engine() -> sha256::HashEngine {
- let midstate = sha256::Midstate::from_inner(MIDSTATE_ANCHOR_ID);
- sha256::HashEngine::from_midstate(midstate, 64)
- }
-}
-
-/// Unique anchor identifier equivalent to the anchor commitment hash
+/// Anchor identifier - a commitment to the anchor data.
+#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
+#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
+#[derive(StrictType, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", transparent)
)]
-#[derive(
- Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From
-)]
-#[wrapper(
- Debug, Display, LowerHex, Index, IndexRange, IndexFrom, IndexTo, IndexFull
-)]
-pub struct AnchorId(sha256t::Hash);
-
-impl CommitVerify for AnchorId
-where
- Msg: AsRef<[u8]>,
-{
- #[inline]
- fn commit(msg: &Msg) -> AnchorId { AnchorId::hash(msg) }
-}
-
-impl strict_encoding::Strategy for AnchorId {
- type Strategy = strict_encoding::strategies::Wrapped;
-}
-
-#[cfg(feature = "wallet")]
-/// Errors working with anchors.
-#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
-#[display(inner)]
-pub enum Error {
- /// Errors embedding LNPBP-4 commitment into PSBT
+pub struct AnchorId(
#[from]
- EmbedCommit(PsbtCommitError),
+ #[from([u8; 32])]
+ Bytes32,
+);
- /// Errors constructing LNPBP-4 commitment
- #[from]
- Lnpbp4(lnpbp4::Error),
+impl CommitStrategy for AnchorId {
+ type Strategy = strategies::Strict;
}
/// Errors verifying anchors.
@@ -107,7 +66,7 @@ pub enum VerifyError {
Tapret(TapretError),
/// LNPBP-4 invalid proof.
- #[from(lnpbp4::UnrelatedProof)]
+ #[from(mpc::UnrelatedProof)]
Lnpbp4UnrelatedProtocol,
}
@@ -115,63 +74,45 @@ pub enum VerifyError {
/// keeping information about the proof of the commitment in connection to the
/// transaction which contains the commitment, and multi-protocol merkle tree as
/// defined by LNPBP-4.
-#[derive(Clone, PartialEq, Eq, Debug, StrictEncode, StrictDecode)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-pub struct Anchor {
+#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
+pub struct Anchor {
/// Transaction containing deterministic bitcoin commitment.
pub txid: Txid,
/// Structured multi-protocol LNPBP-4 data the transaction commits to.
- pub lnpbp4_proof: L,
+ pub mpc_proof: L,
/// Proof of the DBC commitment.
pub dbc_proof: Proof,
}
-impl CommitEncode for Anchor {
- fn commit_encode(&self, mut e: E) -> usize {
- let mut len = self
- .txid
- .strict_encode(&mut e)
- .expect("memory encoders do not fail");
- len += self
- .dbc_proof
- .strict_encode(&mut e)
- .expect("memory encoders do not fail");
- len + self.lnpbp4_proof.commit_encode(e)
- }
+impl CommitStrategy for Anchor {
+ type Strategy = strategies::Strict;
}
-impl ConsensusCommit for Anchor {
- type Commitment = AnchorId;
+impl CommitmentId for Anchor {
+ const TAG: [u8; 32] = *b"urn:lnpbp:lnpbp0011:anchor:v01#A";
+ type Id = AnchorId;
}
-impl Ord for Anchor {
- fn cmp(&self, other: &Self) -> Ordering {
- self.anchor_id().cmp(&other.anchor_id())
- }
+impl Ord for Anchor {
+ fn cmp(&self, other: &Self) -> Ordering { self.anchor_id().cmp(&other.anchor_id()) }
}
-impl PartialOrd for Anchor {
- fn partial_cmp(&self, other: &Self) -> Option {
- Some(self.cmp(other))
- }
+impl PartialOrd for Anchor {
+ fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) }
}
/// Error merging two [`Anchor`]s.
-#[derive(
- Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error,
- From
-)]
+#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum MergeError {
/// Error merging two LNPBP-4 proofs, which are unrelated.
#[display(inner)]
- #[from(lnpbp4::UnrelatedProof)]
+ #[from(mpc::UnrelatedProof)]
Lnpbp4Mismatch,
/// anchors can't be merged since they have different witness transactions
@@ -181,34 +122,20 @@ pub enum MergeError {
ProofMismatch,
}
-impl Anchor {
+impl Anchor {
/// Returns id of the anchor (commitment hash).
#[inline]
- pub fn anchor_id(&self) -> AnchorId { self.consensus_commit() }
-
- /// Convenience constructor for anchor, which also does embedding of LNPBP4
- /// commitment into PSBT.
- #[cfg(feature = "wallet")]
- pub fn commit(
- psbt: &mut Psbt,
- ) -> Result, Error> {
- let anchor = psbt.embed_commit(&PsbtEmbeddedMessage)?;
- Ok(Anchor {
- txid: anchor.txid,
- lnpbp4_proof: lnpbp4::MerkleBlock::from(anchor.lnpbp4_proof),
- dbc_proof: anchor.dbc_proof,
- })
- }
+ pub fn anchor_id(&self) -> AnchorId { self.commitment_id() }
}
-impl Anchor {
+impl Anchor {
/// Returns id of the anchor (commitment hash).
#[inline]
pub fn anchor_id(
&self,
protocol_id: impl Into,
message: Message,
- ) -> Result {
+ ) -> Result {
Ok(self.to_merkle_block(protocol_id, message)?.anchor_id())
}
@@ -217,15 +144,11 @@ impl Anchor {
self,
protocol_id: impl Into,
message: Message,
- ) -> Result, lnpbp4::UnrelatedProof> {
- let lnpbp4_proof = lnpbp4::MerkleBlock::with(
- &self.lnpbp4_proof,
- protocol_id.into(),
- message,
- )?;
+ ) -> Result, mpc::UnrelatedProof> {
+ let lnpbp4_proof = mpc::MerkleBlock::with(&self.mpc_proof, protocol_id.into(), message)?;
Ok(Anchor {
txid: self.txid,
- lnpbp4_proof,
+ mpc_proof: lnpbp4_proof,
dbc_proof: self.dbc_proof,
})
}
@@ -235,7 +158,7 @@ impl Anchor {
&self,
protocol_id: impl Into,
message: Message,
- ) -> Result, lnpbp4::UnrelatedProof> {
+ ) -> Result, mpc::UnrelatedProof> {
self.clone().into_merkle_block(protocol_id, message)
}
@@ -245,13 +168,10 @@ impl Anchor {
&self,
protocol_id: impl Into,
message: Message,
- tx: Transaction,
+ tx: Tx,
) -> Result {
self.dbc_proof
- .verify(
- &self.lnpbp4_proof.convolve(protocol_id.into(), message)?,
- tx,
- )
+ .verify(&self.mpc_proof.convolve(protocol_id.into(), message)?, tx)
.map_err(VerifyError::from)
}
@@ -261,18 +181,18 @@ impl Anchor {
&self,
protocol_id: impl Into,
message: Message,
- ) -> Result {
- self.lnpbp4_proof.convolve(protocol_id.into(), message)
+ ) -> Result {
+ self.mpc_proof.convolve(protocol_id.into(), message)
}
}
-impl Anchor {
+impl Anchor {
/// Conceals all LNPBP-4 data except specific protocol and produces merkle
/// proof anchor.
pub fn to_merkle_proof(
&self,
protocol: impl Into,
- ) -> Result, lnpbp4::LeafNotKnown> {
+ ) -> Result, mpc::LeafNotKnown> {
self.clone().into_merkle_proof(protocol)
}
@@ -281,12 +201,11 @@ impl Anchor {
pub fn into_merkle_proof(
self,
protocol: impl Into,
- ) -> Result, lnpbp4::LeafNotKnown> {
- let lnpbp4_proof =
- self.lnpbp4_proof.to_merkle_proof(protocol.into())?;
+ ) -> Result, mpc::LeafNotKnown> {
+ let lnpbp4_proof = self.mpc_proof.to_merkle_proof(protocol.into())?;
Ok(Anchor {
txid: self.txid,
- lnpbp4_proof,
+ mpc_proof: lnpbp4_proof,
dbc_proof: self.dbc_proof,
})
}
@@ -295,8 +214,8 @@ impl Anchor {
pub fn conceal_except(
&mut self,
protocols: impl AsRef<[ProtocolId]>,
- ) -> Result {
- self.lnpbp4_proof.conceal_except(protocols)
+ ) -> Result {
+ self.mpc_proof.conceal_except(protocols)
}
/// Merges two anchors keeping revealed data.
@@ -307,112 +226,21 @@ impl Anchor {
if self.dbc_proof != other.dbc_proof {
return Err(MergeError::ProofMismatch);
}
- self.lnpbp4_proof.merge_reveal(other.lnpbp4_proof)?;
+ self.mpc_proof.merge_reveal(other.mpc_proof)?;
Ok(self)
}
}
-/// Empty type indicating that the message has to be taken from PSBT proprietary
-/// keys
-#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
-pub struct PsbtEmbeddedMessage;
-
-impl CommitEncode for PsbtEmbeddedMessage {
- fn commit_encode(&self, _: E) -> usize { 0 }
-}
-
-#[cfg(feature = "wallet")]
-impl EmbedCommitProof
- for Anchor
-{
- fn restore_original_container(
- &self,
- psbt: &Psbt,
- ) -> Result {
- match self.dbc_proof {
- Proof::OpretFirst => Ok(psbt.clone()),
- Proof::TapretFirst(ref proof) => {
- let mut psbt = psbt.clone();
- for output in &mut psbt.outputs {
- if output.is_tapret_host() {
- *output = EmbedCommitProof::<_, psbt::Output, Lnpbp6>::restore_original_container(proof, output)?;
- return Ok(psbt);
- }
- }
- Err(PsbtVerifyError::Commit(
- PsbtCommitError::CommitmentImpossible,
- ))
- }
- }
- }
-}
-
-#[cfg(feature = "wallet")]
-impl EmbedCommitVerify for Psbt {
- type Proof = Anchor;
- type CommitError = PsbtCommitError;
- type VerifyError = PsbtVerifyError;
-
- fn embed_commit(
- &mut self,
- _: &PsbtEmbeddedMessage,
- ) -> Result {
- let lnpbp4_tree =
- |output: &mut psbt::Output| -> Result<_, PsbtCommitError> {
- let messages = output.lnpbp4_message_map()?;
- let min_depth = output
- .lnpbp4_min_tree_depth()?
- .unwrap_or(ANCHOR_MIN_LNPBP4_DEPTH);
- let multi_source = lnpbp4::MultiSource {
- min_depth,
- messages,
- };
- Ok(lnpbp4::MerkleTree::try_commit(&multi_source)?)
- };
-
- let (dbc_proof, lnpbp4_proof) = if let Some(output) =
- self.outputs.iter_mut().find(|o| o.is_tapret_host())
- {
- let tree = lnpbp4_tree(output)?;
- let commitment = tree.consensus_commit();
- let proof = output.embed_commit(&commitment)?;
- output.set_tapret_commitment(commitment.into_array(), &proof)?;
- output.set_lnpbp4_entropy(tree.entropy())?;
- (Proof::TapretFirst(proof), tree)
- } else if let Some(output) =
- self.outputs.iter_mut().find(|o| o.is_opret_host())
- {
- let tree = lnpbp4_tree(output)?;
- let commitment = tree.consensus_commit();
- output.script = Script::new_op_return(commitment.as_slice()).into();
- output.set_opret_commitment(commitment.into_array())?;
- output.set_lnpbp4_entropy(tree.entropy())?;
- (Proof::OpretFirst, tree)
- } else {
- return Err(PsbtCommitError::CommitmentImpossible);
- };
-
- Ok(Anchor {
- txid: self.to_txid(),
- lnpbp4_proof,
- dbc_proof,
- })
- }
-}
-
/// Type and type-specific proof information of a deterministic bitcoin
/// commitment.
#[derive(Clone, PartialEq, Eq, Debug)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-#[derive(StrictEncode, StrictDecode)]
-#[strict_encoding(by_order)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP, tags = order)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
#[non_exhaustive]
pub enum Proof {
/// Opret commitment (no extra-transaction proof is required).
+ #[strict_type(dumb)]
OpretFirst,
/// Tapret commitment and a proof of it.
@@ -421,37 +249,17 @@ pub enum Proof {
impl Proof {
/// Verifies validity of the proof.
- pub fn verify(
- &self,
- msg: &lnpbp4::CommitmentHash,
- tx: Transaction,
- ) -> Result {
+ pub fn verify(&self, msg: &mpc::Commitment, tx: Tx) -> Result {
match self {
Proof::OpretFirst => {
- for txout in &tx.output {
+ for txout in &tx.outputs {
if txout.script_pubkey.is_op_return() {
- return Ok(txout.script_pubkey
- == Script::new_op_return(msg.as_slice()));
+ return Ok(txout.script_pubkey == ScriptPubkey::op_return(msg.as_slice()));
}
}
Ok(false)
}
- Proof::TapretFirst(proof) => {
- ConvolveCommitProof::<_, Transaction, _>::verify(proof, msg, tx)
- }
+ Proof::TapretFirst(proof) => ConvolveCommitProof::<_, Tx, _>::verify(proof, msg, tx),
}
}
}
-
-#[cfg(test)]
-mod test {
- use commit_verify::tagged_hash;
-
- use super::*;
-
- #[test]
- fn test_anchor_id_midstate() {
- let midstate = tagged_hash::Midstate::with(b"bp:dbc:anchor");
- assert_eq!(midstate.into_inner().into_inner(), MIDSTATE_ANCHOR_ID);
- }
-}
diff --git a/dbc/src/keytweak/mod.rs b/dbc/src/keytweak/mod.rs
index cf984a2e..95e84c28 100644
--- a/dbc/src/keytweak/mod.rs
+++ b/dbc/src/keytweak/mod.rs
@@ -1,17 +1,23 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
//! Homomorphic key tweaking-based deterministic commitment scheme.
//!
diff --git a/dbc/src/lib.rs b/dbc/src/lib.rs
index 4794515c..f78d9ba1 100644
--- a/dbc/src/lib.rs
+++ b/dbc/src/lib.rs
@@ -1,21 +1,35 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
// Coding conventions
-#![recursion_limit = "256"]
-#![deny(dead_code, missing_docs, warnings)]
+#![deny(
+ non_upper_case_globals,
+ non_camel_case_types,
+ non_snake_case,
+ unused_mut,
+ unused_imports,
+ dead_code,
+ missing_docs
+)]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
//! Deterministic bitcoin commitments library.
//!
@@ -27,8 +41,6 @@
#[macro_use]
extern crate amplify;
-#[cfg(feature = "miniscript")]
-extern crate miniscript_crate as miniscript;
#[cfg(feature = "serde")]
#[macro_use]
extern crate serde_crate as serde;
diff --git a/dbc/src/opret/mod.rs b/dbc/src/opret/mod.rs
index 9b0b0c2e..a087c9e2 100644
--- a/dbc/src/opret/mod.rs
+++ b/dbc/src/opret/mod.rs
@@ -1,17 +1,23 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
//! ScriptPubkey-based OP_RETURN commitments.
//!
diff --git a/dbc/src/sigtweak/mod.rs b/dbc/src/sigtweak/mod.rs
index 1d697b02..76749956 100644
--- a/dbc/src/sigtweak/mod.rs
+++ b/dbc/src/sigtweak/mod.rs
@@ -1,17 +1,23 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
//! Signature tweaking-based deterministic commitment scheme.
//!
diff --git a/dbc/src/tapret/mod.rs b/dbc/src/tapret/mod.rs
index c761805d..97263bb4 100644
--- a/dbc/src/tapret/mod.rs
+++ b/dbc/src/tapret/mod.rs
@@ -1,17 +1,23 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
//! Taproot OP_RETURN-based deterministic bitcoin commitment scheme ("tapret").
//!
@@ -55,44 +61,26 @@
//! b) `TapretProof` / `TweakedPublicKey'`
//! b) `XOnlyPublicKey` / `TapretProof`
-#[cfg(feature = "wallet")]
-mod psbtout;
mod tapscript;
-mod taptree;
mod tx;
mod txout;
mod xonlypk;
-#[cfg(feature = "wallet")]
-pub use psbtout::{PsbtCommitError, PsbtVerifyError};
-pub use tapscript::TAPRET_SCRIPT_COMMITMENT_PREFIX;
-pub use taptree::TapretTreeError;
+pub use bc::LIB_NAME_BP;
pub use tx::TapretError;
+pub use xonlypk::TapretKeyError;
-/// Marker non-instantiable enum defining LNPBP-6 taproot OP_RETURN (`tapret`)
+/// Marker non-instantiable enum defining LNPBP-12 taproot OP_RETURN (`tapret`)
/// protocol.
-pub enum Lnpbp6 {}
-
-use std::io::Read;
+pub enum Lnpbp12 {}
-use bitcoin::hashes::sha256::Midstate;
-use bitcoin::hashes::Hash;
-use bitcoin::schnorr::UntweakedPublicKey;
-use bitcoin::util::taproot::{TapBranchHash, TaprootMerkleBranch};
-use bitcoin::Script;
-use bitcoin_scripts::taproot::TreeNode;
-use bitcoin_scripts::{IntoNodeHash, LeafScript, PubkeyScript, TapNodeHash};
+use bc::{InternalPk, IntoTapHash, LeafScript, ScriptPubkey, TapBranchHash, TapNodeHash};
use commit_verify::CommitmentProtocol;
-use secp256k1::SECP256K1;
-use strict_encoding::{self, StrictDecode};
-
-impl CommitmentProtocol for Lnpbp6 {
- // TaggedHash("LNPBP6")
- const HASH_TAG_MIDSTATE: Option = Some(Midstate([
- 38, 117, 83, 113, 201, 197, 124, 94, 152, 111, 62, 165, 154, 239, 157,
- 166, 10, 195, 217, 29, 15, 182, 55, 211, 190, 230, 184, 41, 241, 198,
- 65, 54,
- ]));
+
+pub use self::tapscript::TAPRET_SCRIPT_COMMITMENT_PREFIX;
+
+impl CommitmentProtocol for Lnpbp12 {
+ const HASH_TAG_MIDSTATE: Option<[u8; 32]> = Some(*b"urn:lnpbp:lnpbp0012:v01#20230203");
}
/// Errors in constructing tapret path proof [`TapretPathProof`].
@@ -112,12 +100,9 @@ pub enum TapretPathError {
/// [`TapretNodePartner::RightBranch`] to ensure correct consensus ordering of
/// the child elements.
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-#[derive(StrictEncode)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
#[display("{left_node_hash}:{right_node_hash}")]
pub struct TapretRightBranch {
left_node_hash: TapNodeHash,
@@ -147,14 +132,11 @@ impl TapretRightBranch {
/// Computes node hash of the partner node defined by this proof.
pub fn node_hash(&self) -> TapNodeHash {
- TapBranchHash::from_node_hashes(
- self.left_node_hash,
- self.right_node_hash,
- )
- .into_node_hash()
+ TapBranchHash::with_nodes(self.left_node_hash, self.right_node_hash).into_tap_hash()
}
}
+/*
impl StrictDecode for TapretRightBranch {
fn strict_decode(
mut d: D,
@@ -173,19 +155,17 @@ impl StrictDecode for TapretRightBranch {
}
}
}
+ */
/// Information proving step of a tapret path in determined way within a given
-/// original [`bitcoin::psbt::TapTree`].
+/// tap tree.
///
/// The structure hosts proofs that the right-side partner at the taproot script
/// tree node does not contain an alternative OP-RETURN commitment script.
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
-#[derive(StrictEncode, StrictDecode)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP, tags = order, dumb = Self::RightLeaf(default!()))]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
#[display(inner)]
pub enum TapretNodePartner {
/// Tapret commitment is on the right side of the tree; i.e the node
@@ -216,24 +196,19 @@ impl TapretNodePartner {
/// Checks that the sibling data does not contain another tapret commitment.
///
- /// The check ensures that if the sibling data are present, their first 32
+ /// The check ensures that if the sibling data are present, their first 31
/// bytes are not equal to [`TAPRET_SCRIPT_COMMITMENT_PREFIX`], and if
/// the sibling is another node, the hash of its first child in the proof
/// is smaller than the hash of the other.
pub fn check_no_commitment(&self) -> bool {
match self {
TapretNodePartner::LeftNode(_) => true,
- TapretNodePartner::RightLeaf(LeafScript { script, .. })
- if script.len() < 32 =>
- {
- true
- }
+ TapretNodePartner::RightLeaf(LeafScript { script, .. }) if script.len() < 64 => true,
TapretNodePartner::RightLeaf(LeafScript { script, .. }) => {
- script[0..32] != TAPRET_SCRIPT_COMMITMENT_PREFIX[..]
+ script[..31] != TAPRET_SCRIPT_COMMITMENT_PREFIX[..]
}
TapretNodePartner::RightBranch(right_branch) => {
- right_branch.left_node_hash()[..]
- != TAPRET_SCRIPT_COMMITMENT_PREFIX[..]
+ right_branch.left_node_hash()[..31] != TAPRET_SCRIPT_COMMITMENT_PREFIX[..]
}
}
}
@@ -244,7 +219,7 @@ impl TapretNodePartner {
match self {
TapretNodePartner::LeftNode(left_node) => *left_node <= other_node,
TapretNodePartner::RightLeaf(leaf_script) => {
- let right_node = leaf_script.tap_leaf_hash().into_node_hash();
+ let right_node = leaf_script.tap_leaf_hash().into_tap_hash();
other_node <= right_node
}
TapretNodePartner::RightBranch(right_branch) => {
@@ -255,30 +230,13 @@ impl TapretNodePartner {
}
/// Computes node hash of the partner node defined by this proof.
- pub fn node_hash(&self) -> TapNodeHash {
+ pub fn tap_node_hash(&self) -> TapNodeHash {
match self {
TapretNodePartner::LeftNode(hash) => *hash,
TapretNodePartner::RightLeaf(leaf_script) => {
- leaf_script.tap_leaf_hash().into_node_hash()
- }
- TapretNodePartner::RightBranch(right_branch) => {
- right_branch.node_hash()
- }
- }
- }
-
- /// Constructs [`TreeNode`] for the node partner.
- pub fn to_tree_node(&self) -> TreeNode {
- match self {
- TapretNodePartner::LeftNode(left_node) => {
- TreeNode::Hidden(*left_node, 1)
- }
- TapretNodePartner::RightLeaf(leaf_script) => {
- TreeNode::Leaf(leaf_script.clone(), 0)
- }
- TapretNodePartner::RightBranch(partner_branch) => {
- TreeNode::Hidden(partner_branch.node_hash(), 1)
+ leaf_script.tap_leaf_hash().into_tap_hash()
}
+ TapretNodePartner::RightBranch(right_branch) => right_branch.node_hash(),
}
}
}
@@ -288,13 +246,10 @@ impl TapretNodePartner {
///
/// Holds information about the sibling at level 1 of the tree in form of
/// [`TapretNodePartner`].
-#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Default)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-#[derive(StrictEncode, StrictDecode)]
+#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
pub struct TapretPathProof {
/// Information about the sibling at level 1 of the tree
partner_node: Option,
@@ -307,13 +262,15 @@ pub struct TapretPathProof {
impl TapretPathProof {
/// Construct new empty path proof.
#[inline]
- pub fn new() -> TapretPathProof { TapretPathProof::default() }
+ pub fn root() -> TapretPathProof {
+ TapretPathProof {
+ partner_node: None,
+ nonce: 0,
+ }
+ }
/// Adds element to the path proof.
- pub fn with(
- elem: TapretNodePartner,
- nonce: u8,
- ) -> Result {
+ pub fn with(elem: TapretNodePartner, nonce: u8) -> Result {
if !elem.check_no_commitment() {
return Err(TapretPathError::InvalidNodePartner(elem));
}
@@ -340,7 +297,7 @@ impl TapretPathProof {
pub fn original_merkle_root(&self) -> Option {
self.partner_node
.as_ref()
- .map(|partner| partner.node_hash())
+ .map(|partner| partner.tap_node_hash())
}
}
@@ -372,12 +329,9 @@ impl<'data> IntoIterator for &'data TapretPathProof {
/// Used both in the commitment procedure for PSBTs and in
/// client-side-validation of the commitment.
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
-#[cfg_attr(
- feature = "serde",
- derive(Serialize, Deserialize),
- serde(crate = "serde_crate")
-)]
-#[derive(StrictEncode, StrictDecode)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
pub struct TapretProof {
/// A merkle path to the commitment inside the taproot script tree. For
/// each node it also must hold information about the sibling in form of
@@ -388,44 +342,15 @@ pub struct TapretProof {
///
/// We need to keep this information client-side since it can't be
/// retrieved from the mined transaction.
- pub internal_key: UntweakedPublicKey,
+ pub internal_pk: InternalPk,
}
impl TapretProof {
/// Restores original scripPubkey before deterministic bitcoin commitment
/// applied.
#[inline]
- pub fn original_pubkey_script(&self) -> PubkeyScript {
- let merkle_root = self
- .path_proof
- .original_merkle_root()
- .map(TapNodeHash::into_inner)
- .map(TapBranchHash::from_inner);
- Script::new_v1_p2tr(SECP256K1, self.internal_key, merkle_root).into()
- }
-}
-
-/// Tapret value: a final tweak applied to the internal taproot key which
-/// includes commitment to both initial taptree merkle root and the OP_RETURN
-/// commitment branch. Represents the taptree merkle root of the modified
-/// taptree.
-#[derive(Wrapper, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
-#[derive(StrictEncode, StrictDecode)]
-pub struct TapretTweak(TaprootMerkleBranch);
-
-#[cfg(test)]
-mod test {
- use amplify::Wrapper;
- use commit_verify::tagged_hash;
-
- use super::*;
-
- #[test]
- fn test_lnpbp6_midstate() {
- let midstate = tagged_hash::Midstate::with(b"LNPBP6");
- assert_eq!(
- midstate.into_inner().into_inner(),
- Lnpbp6::HASH_TAG_MIDSTATE.unwrap().into_inner()
- );
+ pub fn original_pubkey_script(&self) -> ScriptPubkey {
+ let merkle_root = self.path_proof.original_merkle_root();
+ ScriptPubkey::p2tr(self.internal_pk, merkle_root)
}
}
diff --git a/dbc/src/tapret/psbtout.rs b/dbc/src/tapret/psbtout.rs
deleted file mode 100644
index b8f4d403..00000000
--- a/dbc/src/tapret/psbtout.rs
+++ /dev/null
@@ -1,178 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use bitcoin::hashes::Hash;
-use bitcoin::psbt::TapTree;
-use bitcoin::util::taproot::TapBranchHash;
-use bitcoin::Script;
-use bitcoin_scripts::taproot::{Node, TaprootScriptTree, TreeNode};
-use bitcoin_scripts::TapNodeHash;
-use commit_verify::convolve_commit::ConvolveCommitVerify;
-use commit_verify::{lnpbp4, EmbedCommitProof, EmbedCommitVerify};
-use psbt::commit::{
- DfsPathEncodeError, Lnpbp4KeyError, OpretKeyError, TapretKeyError,
-};
-use secp256k1::SECP256K1;
-
-use super::{Lnpbp6, TapretProof};
-use crate::tapret::taptree::{
- TapretProofError, TapretSourceError, TapretSourceInfo,
-};
-
-/// Errors during tapret PSBT commitment process.
-#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
-#[display(doc_comments)]
-pub enum PsbtCommitError {
- /// Invalid taproot script tree source information.
- #[from]
- #[display(inner)]
- SourceError(TapretSourceError),
-
- /// it is impossible to create neither Tapret nor Opret commitment for the
- /// given PSBT file.
- CommitmentImpossible,
-
- /// Error in LNPBP4 PBST data
- #[from]
- #[display(inner)]
- PsbtLnpbp4(Lnpbp4KeyError),
-
- /// Error in LNPBP4 PBST data
- #[from]
- #[display(inner)]
- TapretLnpbp4(TapretKeyError),
-
- /// Error in LNPBP4 PBST data
- #[from]
- #[display(inner)]
- OpretLnpbp4(OpretKeyError),
-
- /// LNPBP4 commitment creation error
- #[from]
- #[display(inner)]
- Lnpbp4(lnpbp4::Error),
-
- /// tapret commitment can't be made in a transaction lacking any taproot
- /// outputs.
- NoTaprootOutput,
-
- /// tapret commitment can't be made due to an absent taproot internal key
- /// in PSBT data.
- InternalKeyMissed,
-
- /// tapret commitment does not change internal key, but the key in PSBT
- /// data and key from the tapret proof differ.
- InternalKeyMismatch,
-
- /// invalid tapret commitment path in PSBT data.
- #[from(DfsPathEncodeError)]
- TapretPathInvalid,
-
- /// PSBT output misses tapret path information.
- TapretPathMissed,
-
- /// producing taptree structure
- TapTreeError,
-}
-
-/// Errors during tapret PSBT commitment process.
-#[derive(Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
-#[display(inner)]
-pub enum PsbtVerifyError {
- /// Error during commitment process.
- #[from]
- #[from(DfsPathEncodeError)]
- #[from(TapretSourceError)]
- Commit(PsbtCommitError),
-
- /// Error during verification process.
- #[from]
- Proof(TapretProofError),
-}
-
-impl EmbedCommitProof
- for TapretProof
-{
- fn restore_original_container(
- &self,
- commit_container: &psbt::Output,
- ) -> Result {
- let mut original_container = commit_container.clone();
-
- let internal_key = original_container
- .tap_internal_key
- .ok_or(PsbtCommitError::InternalKeyMissed)?;
- if internal_key != self.internal_key {
- return Err(PsbtCommitError::InternalKeyMismatch)
- .map_err(PsbtVerifyError::from);
- }
-
- let tap_tree = original_container.tap_tree.map(TaprootScriptTree::from);
- let source = TapretSourceInfo::::with(tap_tree)?;
- let source = self.path_proof.restore_original_container(&source)?;
-
- let merkle_root = source
- .as_root_node()
- .map(TreeNode::node_hash)
- .map(TapNodeHash::into_inner)
- .map(TapBranchHash::from_inner);
- original_container.script =
- Script::new_v1_p2tr(SECP256K1, self.internal_key, merkle_root)
- .into();
-
- original_container.tap_tree = source.into_tap_tree();
-
- Ok(original_container)
- }
-}
-
-impl EmbedCommitVerify for psbt::Output {
- type Proof = TapretProof;
- type CommitError = PsbtCommitError;
- type VerifyError = PsbtVerifyError;
-
- fn embed_commit(
- &mut self,
- msg: &lnpbp4::CommitmentHash,
- ) -> Result {
- // TODO: Check TAPRET_COMMITABLE key
-
- let internal_key = if let Some(internal_key) = self.tap_internal_key {
- internal_key
- } else {
- return Err(PsbtCommitError::InternalKeyMissed);
- };
-
- let mut source =
- TapretSourceInfo::::with(self.tap_tree.clone())?;
-
- let path_proof = source.embed_commit(msg)?;
-
- self.tap_tree = source.into_tap_tree();
-
- let (output_key, _) = internal_key
- .convolve_commit(&path_proof, msg)
- .map_err(|_| PsbtCommitError::TapTreeError)?;
-
- self.script = Script::new_v1_p2tr_tweaked(output_key).into();
-
- let proof = TapretProof {
- path_proof,
- internal_key,
- };
-
- Ok(proof)
- }
-}
diff --git a/dbc/src/tapret/tapscript.rs b/dbc/src/tapret/tapscript.rs
index cf3e7bc6..6db6cd28 100644
--- a/dbc/src/tapret/tapscript.rs
+++ b/dbc/src/tapret/tapscript.rs
@@ -1,48 +1,99 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-use bitcoin::blockdata::opcodes::all;
-use bitcoin::blockdata::script;
-use bitcoin_scripts::TapScript;
-use commit_verify::{lnpbp4, CommitEncode, CommitVerify};
-
-use super::Lnpbp6;
-
-/// Hardcoded tapret script prefix consisting of 30 `OP_RESERVED` pushes,
-/// followed by `OP_RETURN` and `OP_PUSHBYTES_32`.
-pub const TAPRET_SCRIPT_COMMITMENT_PREFIX: [u8; 32] = [
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
- 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x6a, 0x20,
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
+
+use std::io;
+
+use bc::{TapCode, TapScript, LIB_NAME_BP};
+use commit_verify::{mpc, strategies, CommitEncode, CommitStrategy, CommitVerify};
+
+use super::Lnpbp12;
+
+/// Hardcoded tapret script prefix consisting of 29 `OP_RESERVED` pushes,
+/// followed by `OP_RETURN` and `OP_PUSHBYTES_33`.
+pub const TAPRET_SCRIPT_COMMITMENT_PREFIX: [u8; 31] = [
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
+ 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x6a, 0x21,
];
-impl CommitVerify<(lnpbp4::CommitmentHash, u8), Lnpbp6> for TapScript {
- fn commit(msg: &(lnpbp4::CommitmentHash, u8)) -> Self {
- let (msg, nonce) = msg;
- let mut builder = script::Builder::new();
- for _ in 0..30 {
- // Filling first 30 bytes with OP_RESERVED in order to avoid
- // representation of sibling partner script as child hashes.
- builder = builder.push_opcode(all::OP_RESERVED);
+#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
+#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
+#[strict_type(lib = LIB_NAME_BP)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
+pub struct TapretCommitment {
+ /// LNPBP-4 multi-protocol commitment.
+ pub mpc: mpc::Commitment,
+ /// Nonce is used to put the commitment into the correct side of the tree.
+ pub nonce: u8,
+}
+
+impl TapretCommitment {
+ pub fn with(mpc: mpc::Commitment, nonce: u8) -> Self { Self { mpc, nonce } }
+}
+
+impl CommitStrategy for TapretCommitment {
+ type Strategy = strategies::Strict;
+}
+
+impl CommitVerify for TapScript {
+ /// Tapret script consists of 29 `OP_RESERVED` pushes, followed by
+ /// `OP_RETURN`, `OP_PUSHBYTES_33` and serialized commitment data (MPC
+ /// commitment + nonce as a single slice).
+ fn commit(commitment: &TapretCommitment) -> Self {
+ let mut tapret = TapScript::with_capacity(64);
+ for _ in 0..29 {
+ tapret.push_opcode(TapCode::Reserved);
}
- let mut data = msg.commit_serialize();
- data.push(*nonce);
- builder
- .push_opcode(all::OP_RETURN)
- .push_slice(&data)
- .into_script()
- .into()
+ tapret.push_opcode(TapCode::Return);
+ let mut data = io::Cursor::new([0u8; 33]);
+ commitment.commit_encode(&mut data);
+ tapret.push_slice(&data.into_inner());
+ tapret
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use strict_encoding::StrictDumb;
+
+ use super::*;
+
+ pub fn commitment() -> TapretCommitment {
+ TapretCommitment {
+ mpc: mpc::Commitment::strict_dumb(),
+ nonce: 8,
+ }
+ }
+
+ #[test]
+ pub fn commitment_prefix() {
+ let script = TapScript::commit(&commitment());
+ assert_eq!(TAPRET_SCRIPT_COMMITMENT_PREFIX, script[0..31]);
+ }
+
+ #[test]
+ pub fn commiment_serialization() {
+ let commitment = commitment();
+ let script = TapScript::commit(&commitment);
+ eprintln!("{script:x}");
+ assert_eq!(script[63], commitment.nonce);
+ assert_eq!(&script[31..63], commitment.mpc.as_slice());
}
}
diff --git a/dbc/src/tapret/taptree.rs b/dbc/src/tapret/taptree.rs
deleted file mode 100644
index 021ebd98..00000000
--- a/dbc/src/tapret/taptree.rs
+++ /dev/null
@@ -1,379 +0,0 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
-//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
-//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
-//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
-
-//! `EmbedCommit: TapTree, Msg -> TapTree', TapNode`
-
-use core::fmt::Debug;
-use core::hash::Hash;
-
-use bitcoin::psbt::{IncompleteTapTree, TapTree};
-use bitcoin::util::taproot::TaprootBuilderError;
-use bitcoin_scripts::taproot::{
- self, Branch, CutError, DfsOrder, DfsOrdering, DfsPath, DfsTraversalError,
- InstillError, MaxDepthExceeded, Node, TaprootScriptTree, TreeNode,
- UnsplittableTree,
-};
-use bitcoin_scripts::{LeafScript, TapNodeHash, TapScript};
-use commit_verify::{
- lnpbp4, CommitVerify, EmbedCommitProof, EmbedCommitVerify,
-};
-
-use super::{Lnpbp6, TapretNodePartner, TapretPathProof};
-use crate::tapret::TapretPathError;
-
-// TODO: Re-check the use of all error variants
-/// Errors during tapret commitment embedding into tapscript tree.
-#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)]
-#[display(doc_comments)]
-pub enum TapretTreeError {
- /// the provided commitment data can't be strict encoded. Details: {0}
- #[from]
- StrictEncoding(strict_encoding::Error),
-
- /// unable to update tap tree with the commitment. Details: {0}
- #[from]
- TapTree(TaprootBuilderError),
-
- /// the taproot script tree is invalid. Details: {0}
- #[from]
- TreeBuilder(IncompleteTapTree),
-
- /// the tapret commitment is impossible since the taproot script tree
- /// already has the maximal depth.
- #[from(MaxDepthExceeded)]
- MaxDepthExceeded,
-
- /// the provided taproot script tree has no revealed nodes to prove the
- /// commitment.
- IncompleteTree(TaprootScriptTree),
-
- /// tapret node partner {0} contains alternative commitment
- AlternativeCommitment(TapretNodePartner),
-
- /// tapret node partner {0} has an invalid order with the commitment node
- /// {1}
- IncorrectOrdering(TapretNodePartner, TreeNode),
-}
-
-/// Errors during taproot script tree tapret commitment verification and
-/// restoration of the original container structure.
-#[derive(
- Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display, Error, From
-)]
-#[display(doc_comments)]
-pub enum TapretProofError {
- /// the provided tapret proof does not contain a taproot script tree, i.e.
- /// can't contain a commitment
- EmptyTree,
-
- /// the provided tapret proof consists of a single node
- #[from(UnsplittableTree)]
- UnsplittableTree,
-
- /// Errors in the taproot script tree and tapret path proof
- /// correspondences. See [`TapretSourceError`] for details.
- #[from]
- #[display(inner)]
- SourceError(TapretSourceError),
-}
-
-impl From for TapretProofError {
- fn from(err: CutError) -> Self {
- match err {
- CutError::UnsplittableTree => Self::UnsplittableTree,
- CutError::DfsTraversal(e) => Self::SourceError(e.into()),
- }
- }
-}
-
-/// Errors during taproot script tree tapret commitment ebmedding.
-#[derive(
- Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, Display, Error, From
-)]
-#[display(doc_comments)]
-pub enum TapretSourceError {
- /// the length of the constructed tapret path proof exceeds taproot path
- /// length limit.
- #[from(MaxDepthExceeded)]
- MaxDepthExceeded,
-
- /// the node partner {0} at the level 1 can't be proven not to contain an
- /// alternative tapret commitment.
- InvalidNodePartner(TapretNodePartner),
-
- /// unable to produce tapret commitment since the commitment path {0} does
- /// not exist within the tree.
- PathNotExists(DfsPath),
-
- /// the provided taproot script tree contains hidden node {0} at path {1}
- /// and can't be used for tapret commit instillation.
- HiddenNode(TapNodeHash, DfsPath),
-
- /// the provided tapret commitment path {1} points at the leaf node {0}
- /// and can't be used for tapret commit instillation.
- LeafNode(LeafScript, DfsPath),
-}
-
-impl From for TapretSourceError {
- fn from(err: InstillError) -> Self {
- match err {
- InstillError::MaxDepthExceeded => Self::MaxDepthExceeded,
- InstillError::DfsTraversal(e) => e.into(),
- }
- }
-}
-
-impl From for TapretSourceError {
- fn from(err: DfsTraversalError) -> Self {
- match err {
- DfsTraversalError::PathNotExists(path) => Self::PathNotExists(path),
- DfsTraversalError::HiddenNode {
- node_hash,
- failed_path,
- path_leftover: _,
- } => Self::HiddenNode(node_hash, failed_path),
- DfsTraversalError::LeafNode {
- leaf_script,
- failed_path,
- path_leftover: _,
- } => Self::LeafNode(leaf_script, failed_path),
- }
- }
-}
-
-impl From for TapretSourceError {
- fn from(err: TapretPathError) -> Self {
- match err {
- TapretPathError::MaxDepthExceeded => Self::MaxDepthExceeded,
- TapretPathError::InvalidNodePartner(partner) => {
- Self::InvalidNodePartner(partner)
- }
- }
- }
-}
-
-/// Structure wrapping concrete taproot script tree, acting as a source of the
-/// tapret commitment, keeping information about DFS path which should be used
-/// for embedding tapret commit.
-///
-/// The structure can be used with [`TapTree`] and [`TaprootScriptTree`].
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct TapretSourceInfo(Option)
-where
- Tree: Clone + Eq + Debug;
-
-impl TapretSourceInfo {
- /// Validates that the provided path can be used for a tapret commitment
- /// embedding and constructs [`SourceTree`] from the provided
- /// [`TaprootScriptTree`] and a valid path. The path must point to a branch
- /// node in the tree.
- ///
- /// # Errors
- ///
- /// The following errors may happen:
- /// - [`DfsPathError::PathNotExists`], if the path does not exists within
- /// the tree;
- /// - [`DfsPathError::HiddenNode`], if the path passes through a hidden node
- /// of the tree;
- /// - [`DfsPathError::LeafNode`], if the path points at a leaf node.
- pub fn with(
- tap_tree: Option,
- ) -> Result {
- Ok(TapretSourceInfo(tap_tree))
- }
-
- /// Returns reference to the script tree root node, if taproot script tree
- /// is present in the source data.
- pub fn as_root_node(&self) -> Option<&TreeNode> {
- self.0.as_ref().map(TaprootScriptTree::as_root_node)
- }
-
- /// Releases internal [`TapTree`] data, if present.
- #[inline]
- pub fn into_tap_tree(self) -> Option { self.0.map(TapTree::from) }
-}
-
-impl TapretSourceInfo {
- /// Validates that the provided path can be used for a tapret commitment
- /// embedding and constructs [`SourceTree`] from the provided [`TapTree`]
- /// and a valid path. The path must point to a branch node in the tree.
- ///
- /// # Errors
- ///
- /// The following errors may happen:
- /// - [`DfsPathError::PathNotExists`], if the path does not exists within
- /// the tree;
- /// - [`DfsPathError::HiddenNode`], if the path passes through a hidden node
- /// of the tree;
- /// - [`DfsPathError::LeafNode`], if the path points at a leaf node.
- #[inline]
- pub fn with(tap_tree: Option) -> Result {
- TapretSourceInfo::::with(
- tap_tree.map(TaprootScriptTree::from),
- )
- .map(TapretSourceInfo::from)
- }
-
- /// Releases internal [`TapTree`] data, if present.
- #[inline]
- pub fn into_tap_tree(self) -> Option { self.0 }
-}
-
-impl From<&TapretSourceInfo> for TapretSourceInfo {
- fn from(source: &TapretSourceInfo) -> Self {
- let tap_tree = source.0.as_ref().cloned().map(TaprootScriptTree::from);
- TapretSourceInfo(tap_tree)
- }
-}
-
-impl From> for TapretSourceInfo {
- fn from(source: TapretSourceInfo) -> Self {
- let tap_tree = source.0.map(TapTree::from);
- TapretSourceInfo(tap_tree)
- }
-}
-
-impl
- EmbedCommitProof<
- lnpbp4::CommitmentHash,
- TapretSourceInfo,
- Lnpbp6,
- > for TapretPathProof
-{
- fn restore_original_container(
- &self,
- modified_tree: &TapretSourceInfo,
- ) -> Result, TapretProofError> {
- let tap_tree = modified_tree
- .0
- .as_ref()
- .cloned()
- .ok_or(TapretProofError::EmptyTree)?;
-
- match self.partner_node {
- // Taproot has key-only spending
- None => Ok(TapretSourceInfo(None)),
- // Taproot has script spendings
- Some(_) => {
- let (original_tree, _) = tap_tree.split()?;
- Ok(TapretSourceInfo(Some(original_tree)))
- }
- }
- }
-}
-
-impl EmbedCommitVerify
- for TapretSourceInfo
-{
- type Proof = TapretPathProof;
- type CommitError = TapretSourceError;
- type VerifyError = TapretProofError;
-
- fn embed_commit(
- &mut self,
- msg: &lnpbp4::CommitmentHash,
- ) -> Result {
- for nonce in 0..=u8::MAX {
- let commitment_script = TapScript::commit(&(*msg, nonce));
-
- let commitment_node =
- TreeNode::with_tap_script(commitment_script, 0);
- let commitment_subtree = TaprootScriptTree::with(commitment_node)
- .expect("invalid commitment node construction");
-
- let tap_tree = if let Some(ref mut tap_tree) = self.0 {
- tap_tree
- } else {
- self.0 = Some(commitment_subtree);
- return Ok(TapretPathProof::new());
- };
-
- let original_tree = tap_tree.clone();
- *tap_tree =
- original_tree.join(commitment_subtree, DfsOrder::Last)?;
-
- let branch = tap_tree
- .as_root_node()
- .as_branch()
- .expect("instill algorithm is broken");
- let partner = branch.as_dfs_child_node(DfsOrder::First);
-
- let partner_is_left_node =
- branch.dfs_ordering() == DfsOrdering::LeftRight;
-
- let partner_proof = match (partner_is_left_node, partner) {
- (true, node) => TapretNodePartner::LeftNode(node.node_hash()),
- (false, TreeNode::Leaf(script, _)) => {
- TapretNodePartner::RightLeaf(script.clone())
- }
- (false, TreeNode::Hidden(partner_hash, _)) => {
- return Err(TapretSourceError::HiddenNode(
- *partner_hash,
- vec![DfsOrder::First].into(),
- ))
- }
- (false, TreeNode::Branch(partner_branch, _)) => {
- TapretNodePartner::right_branch(
- partner_branch.as_left_node().node_hash(),
- partner_branch.as_right_node().node_hash(),
- )
- }
- };
-
- if partner_is_left_node || nonce == u8::MAX {
- return TapretPathProof::with(partner_proof, nonce)
- .map_err(TapretSourceError::from);
- }
- }
- unreachable!("for cycle always returns before exiting")
- }
-}
-
-impl EmbedCommitProof, Lnpbp6>
- for TapretPathProof
-{
- fn restore_original_container(
- &self,
- modified_container: &TapretSourceInfo,
- ) -> Result, TapretProofError> {
- EmbedCommitProof::<
- _,
- TapretSourceInfo,
- _,
- >::restore_original_container(
- self, &modified_container.into()
- ).map(TapretSourceInfo::into)
- }
-}
-
-impl EmbedCommitVerify
- for TapretSourceInfo
-{
- type Proof = TapretPathProof;
- type CommitError = TapretSourceError;
- type VerifyError = TapretProofError;
-
- fn embed_commit(
- &mut self,
- msg: &lnpbp4::CommitmentHash,
- ) -> Result {
- let mut source = TapretSourceInfo::::from(
- self as &TapretSourceInfo<_>,
- );
- let proof = source.embed_commit(msg)?;
- *self = source.into();
- Ok(proof)
- }
-}
diff --git a/dbc/src/tapret/tx.rs b/dbc/src/tapret/tx.rs
index ce9d7b15..acddc595 100644
--- a/dbc/src/tapret/tx.rs
+++ b/dbc/src/tapret/tx.rs
@@ -1,50 +1,51 @@
-// Deterministic bitcoin commitments library, implementing LNPBP standards
-// Part of bitcoin protocol core library (BP Core Lib)
+// Deterministic bitcoin commitments library.
//
-// Written in 2020-2022 by
-// Dr. Maxim Orlovsky
+// SPDX-License-Identifier: Apache-2.0
//
-// To the extent possible under law, the author(s) have dedicated all
-// copyright and related and neighboring rights to this software to
-// the public domain worldwide. This software is distributed without
-// any warranty.
+// Written in 2019-2023 by
+// Dr. Maxim Orlovsky
//
-// You should have received a copy of the Apache 2.0 License
-// along with this software.
-// If not, see .
+// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
+//
+// 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.
-use bitcoin::Transaction;
-use commit_verify::convolve_commit::{
- ConvolveCommitProof, ConvolveCommitVerify,
-};
-use commit_verify::lnpbp4;
+use bc::Tx;
+use commit_verify::{mpc, ConvolveCommit, ConvolveCommitProof};
-use super::{Lnpbp6, TapretProof, TapretTreeError};
+use super::{Lnpbp12, TapretKeyError, TapretProof};
/// Errors during tapret commitment.
#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)]
pub enum TapretError {
- /// Error embedding tapret commitment into taproot script tree.
+ /// Error embedding tapret commitment into x-only key.
#[from]
#[display(inner)]
- TreeEmbedding(TapretTreeError),
+ KeyEmbedding(TapretKeyError),
/// tapret commitment in a transaction lacking any taproot outputs.
#[display(doc_comments)]
NoTaprootOutput,
}
-impl ConvolveCommitProof