diff --git a/.cargo/mutants.toml b/.cargo/mutants.toml new file mode 100644 index 000000000..005039b02 --- /dev/null +++ b/.cargo/mutants.toml @@ -0,0 +1,64 @@ +additional_cargo_args = ["--all-features"] +examine_globs = ["consensus_encoding/src/**/*.rs", "units/src/**/*.rs", "primitives/src/**/*.rs"] +exclude_globs = [ + "units/src/amount/verification.rs" # kani tests +] +exclude_re = [ + "impl Arbitrary", + "impl Debug", + "impl fmt::Debug", + ".*Error", + "deserialize", # Skip serde mutation tests + "serde_details::", # Skip serde mutation tests + "Iterator", # Mutating operations in an iterator can result in an infinite loop + "::decoder", # Mutant replacing Default::default() is equivalent to returning new() + "::read_limit", # Function is for optimization and does not need to be tested. + + + # ----------------------------------Crate-specific exclusions---------------------------------- + # units + # src/amount/mod.rs + "units/.* parse_signed_to_satoshi", # Can't kill all mutants since there is no denomination smaller than Satoshi + "units/.* fmt_satoshi_in", # Related to formatting/display + "units/.* dec_width", # Replacing num /= 10 with num %=10 in a loop causes a timeout due to infinite loop + # src/locktime/relative.rs + "units/.* LockTime::to_consensus_u32", # Mutant from replacing | with ^, this returns the same value since the XOR is taken against the u16 with an all-zero bitmask + "units/.* FeeRate::fee_vb", # Deprecated + "units/.* FeeRate::fee_wu", # Deprecated + "units/.* SignedAmount::checked_abs", # Deprecated + "units/.* NumberOfBlocks::value", # Deprecated + "units/.* NumberOf512Seconds::to_consensus_u32", # Deprecated + "units/.* MedianTimePast::to_consensus_u32", # Deprecated + "units/.* Height::to_consensus_u32", # Deprecated + "units/.* Sequence::to_hex", # Deprecated + "units/.* Sequence::from_512_second_intervals", # Mutant from replacing | with ^, this returns the same value since the XOR is taken against the u16 with an all-zero bitmask + + # primitives + "primitives/.* Opcode::classify", # Not possible to kill all mutants without individually checking every opcode classification + "primitives/.* Block::cached_witness_root", # Skip getters + "primitives/.* Block::transactions", # Skip getters + "primitives/.* Script::to_bytes", # Deprecated + "primitives/.* decode_cursor", # Mutating operations in decode_cursor can result in an infinite loop + "primitives/.* fmt_debug", # Mutants from formatting/display changes + "primitives/.* fmt_debug_pretty", # Mutants from formatting/display changes + "primitives/.* CompactTarget::to_hex", # Deprecated + "primitives/.* Script::to_hex", # Deprecated + "primitives/.* Script::to_hex", # Deprecated + "primitives/.* ScriptBuf::to_hex", # Deprecated + "primitives/.* ScriptBuf::to_hex", # Deprecated + "primitives/.* >::current_chunk", # Replacing the return with Some(vec![]) causes an infinite loop. + "primitives/.* >::advance", # Replacing the return with true causes an infinite loop. + "primitives/.* ::push_bytes", # Replacing == with != causes an infinite loop + "primitives/.* WitnessDecoder::resize_if_needed", # Replacing *= with += still resizes the buffer making the mutant untestable. + "primitives/.* replace \\+ with \\* in MerkleNode::calculate_root", # Replacing + with * causes an infinite loop + "primitives/.* replace == with != in MerkleNode::calculate_root", # Replacing == with != isn't caught unless alloc is disabled. + + # consensus_encoding - most of these are for mutations in the logic used to determine when to stop encoding or decoding. + "consensus_encoding/.* >::push_bytes", # Mutations cause an infinite loop + "consensus_encoding/.* ::end", # Mutations cause an infinite loop + "consensus_encoding/.* encode_to_vec", # Mutations cause an infinite loop + "consensus_encoding/.* encode_to_writer", # Mutations cause an infinite loop + "consensus_encoding/.* decode_from_slice", # Mutations cause an infinite loop + "consensus_encoding/.* decode_from_read", # Mutations cause an infinite loop + "consensus_encoding/.* ::push_bytes", # Mutations cause an infinite loop +] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..6836cd836 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.rs diff=rust diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..bf1734278 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# Set update schedule for GitHub Actions +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly" + # Defines a cooldown period for dependency updates, + # allowing updates to be delayed for a configurable number of days. + cooldown: + default-days: 60 diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 000000000..884b5961a --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,15 @@ +ci: + - changed-files: + - any-glob-to-any-file: .github/** +test: + - changed-files: + - any-glob-to-any-file: fuzz/** + - any-glob-to-any-file: '*/tests/**' + - any-glob-to-any-file: 'dep_test' + - any-glob-to-any-file: 'contrib/run_task.sh' + - any-glob-to-any-file: 'contrib/test_vars.sh' + - any-glob-to-any-file: '*/contrib/extra_tests.sh' + - any-glob-to-any-file: '*/contrib/test_vars.sh' +doc: + - changed-files: + - any-glob-to-any-file: '**/*.md' diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 000000000..5bb18672f --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,40 @@ +# rust-bitcoin workflow notes + +We are attempting to run max 20 parallel jobs using GitHub actions (usage limit for free tier). + +ref: https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration + +The minimal/recent lock files are handled by CI (`rust.yml`). + +## Jobs + +Run from rust.yml unless stated otherwise. Unfortunately we are now exceeding the 20 job target. +(Prepare is quick and must be run first anyway.) + +0. `Prepare` +1. `Stable - minimal` +2. `Stable - recent` +3. `Nightly - minimal` +4. `Nightly - recent` +5. `MSRV - minimal` +6. `MSRV - recent` +7. `Lint` +8. `Docs` +9. `Docsrs` +10. `Bench` +11. `Arch32bit` +12. `Cross` +13. `Embedded` +14. `ASAN` +15. `WASM` +16. `Kani` +17. `API` +18. `Policy` - enforce repository coding policy. +19. `Re-exports` +20. `DiffMutants` +21. `release` - run by `release.yml` +22. `labeler` - run by `manage-pr.yml` +23. `Shellcheck` - run by `shellcheck.yml` + +If any change touches the `.github/` directory then the `zizmor`, run by `zizmor.yml`, will be +triggered for that PR. diff --git a/.github/workflows/cargo-semver-checks-version b/.github/workflows/cargo-semver-checks-version new file mode 100644 index 000000000..bcce5d06b --- /dev/null +++ b/.github/workflows/cargo-semver-checks-version @@ -0,0 +1 @@ +0.45.0 diff --git a/.github/workflows/cron-daily-fuzz.yml b/.github/workflows/cron-daily-fuzz.yml new file mode 100644 index 000000000..50658c9f1 --- /dev/null +++ b/.github/workflows/cron-daily-fuzz.yml @@ -0,0 +1,100 @@ +# Automatically generated by fuzz/generate-files.sh +name: Fuzz +on: + schedule: + # 5am every day UTC, this correlates to: + # - 10pm PDT + # - 6am CET + # - 4pm AEDT + - cron: '00 05 * * *' +permissions: {} + +jobs: + fuzz: + if: ${{ !github.event.act }} + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + # We only get 20 jobs at a time, we probably don't want to go + # over that limit with fuzzing because of the hour run time. + fuzz_target: [ + bitcoin_arbitrary_block, + bitcoin_arbitrary_script, + bitcoin_arbitrary_transaction, + bitcoin_arbitrary_witness, + bitcoin_deserialize_block, + bitcoin_deserialize_prefilled_transaction, + bitcoin_deserialize_psbt, + bitcoin_deserialize_script, + bitcoin_deserialize_transaction, + bitcoin_deserialize_witness, + bitcoin_parse_address, + bitcoin_parse_outpoint, + bitcoin_script_bytes_to_asm_fmt, + consensus_encoding_decode_array, + consensus_encoding_decode_byte_vec, + consensus_encoding_decode_compact_size, + consensus_encoding_decode_decoder2, + hashes_json, + hashes_ripemd160, + hashes_sha1, + hashes_sha256, + hashes_sha512, + hashes_sha512_256, + p2p_arbitrary_addrv2, + p2p_deserialize_addrv2, + p2p_deserialize_raw_net_msg, + units_arbitrary_weight, + units_parse_amount, + units_parse_int, + units_standard_checks, + ] + steps: + - name: Install test dependencies + run: sudo apt-get update -y && sudo apt-get install -y binutils-dev libunwind8-dev libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc libiberty-dev + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + + id: cache-fuzz + with: + path: | + ~/.cargo/bin + fuzz/target + target + key: cache-${{ matrix.target }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} + - uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + with: + toolchain: '1.74.0' + - name: fuzz + run: | + if [[ "${{ matrix.fuzz_target }}" =~ ^bitcoin ]]; then + export RUSTFLAGS='--cfg=hashes_fuzz --cfg=secp256k1_fuzz' + fi + echo "Using RUSTFLAGS $RUSTFLAGS" + cd fuzz && ./fuzz.sh "${{ matrix.fuzz_target }}" + - run: echo "${{ matrix.fuzz_target }}" >executed_${{ matrix.fuzz_target }} + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: executed_${{ matrix.fuzz_target }} + path: executed_${{ matrix.fuzz_target }} + + verify-execution: + if: ${{ !github.event.act }} + needs: fuzz + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - name: Display structure of downloaded files + run: ls -R + - run: find executed_* -type f -exec cat {} + | sort > executed + - run: source ./fuzz/fuzz-util.sh && listTargetNames | sort | diff - executed diff --git a/.github/workflows/cron-daily-kani.yml b/.github/workflows/cron-daily-kani.yml new file mode 100644 index 000000000..18191a5bc --- /dev/null +++ b/.github/workflows/cron-daily-kani.yml @@ -0,0 +1,19 @@ +# From https://model-checking.github.io/kani/install-github-ci.html +name: Kani CI +on: + schedule: + - cron: '59 23 * * *' # midnight every day. +permissions: {} +jobs: + run-kani: + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: 'Checkout your code.' + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + + - name: 'Run Kani on your code.' + uses: model-checking/kani-github-action@f838096619a707b0f6b2118cf435eaccfa33e51f # v1.1 diff --git a/.github/workflows/cron-weekly-cargo-mutants.yml b/.github/workflows/cron-weekly-cargo-mutants.yml new file mode 100644 index 000000000..1b0a989fd --- /dev/null +++ b/.github/workflows/cron-weekly-cargo-mutants.yml @@ -0,0 +1,49 @@ +name: Weekly cargo-mutants +on: + schedule: + - cron: "0 0 * * 0" # runs weekly on Sunday at 00:00 + workflow_dispatch: # allows manual triggering +permissions: {} +jobs: + cargo-mutants: + runs-on: ubuntu-24.04 + permissions: + contents: read + issues: write + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: taiki-e/install-action@81ee1d48d9194cdcab880cbdc7d36e87d39874cb # v2.62.45 + with: + tool: cargo-mutants + - run: cargo mutants --in-place --no-shuffle + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + if: always() + with: + name: mutants.out + path: mutants.out + - name: Check for new mutants + if: always() + run: | + if [ -s mutants.out/missed.txt ]; then + echo "New missed mutants found" + MUTANTS_VERSION=$(cargo mutants --version) + gh issue create \ + --title "New Mutants Found" \ + --body "$(cat <> $GITHUB_ENV + else + echo "No new mutants found" + echo "create_issue=false" >> $GITHUB_ENV + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/cron-weekly-rustfmt.yml b/.github/workflows/cron-weekly-rustfmt.yml new file mode 100644 index 000000000..81e751ba8 --- /dev/null +++ b/.github/workflows/cron-weekly-rustfmt.yml @@ -0,0 +1,35 @@ +name: Nightly rustfmt +on: + schedule: + - cron: "0 0 * * 0" # runs weekly on Sunday at 00:00 + workflow_dispatch: # allows manual triggering +permissions: {} +jobs: + format: + name: Nightly rustfmt + runs-on: ubuntu-24.04 + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@55d80eb3c5a4228eec5390a083c092095115c6f1 # nightly + with: + components: rustfmt + - name: Run Nightly rustfmt + # Run the formatter and manually remove trailing whitespace. + run: cargo +nightly fmt && git ls-files -- '*.rs' -z | xargs sed -E -i'' -e 's/[[:space:]]+$//' + - name: Get the current date + run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + - name: Create Pull Request + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + author: Fmt Bot + title: Automated nightly rustfmt (${{ env.date }}) + body: | + Automated nightly `rustfmt` changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action + commit-message: ${{ env.date }} automated rustfmt nightly + labels: rustfmt + diff --git a/.github/workflows/cron-weekly-update-cargo-semver-checks.yml b/.github/workflows/cron-weekly-update-cargo-semver-checks.yml new file mode 100644 index 000000000..4f32e1d93 --- /dev/null +++ b/.github/workflows/cron-weekly-update-cargo-semver-checks.yml @@ -0,0 +1,46 @@ +name: Update cargo-semver-checks +on: + schedule: + - cron: "0 0 * * 6" # runs every Saturday at 00:00 + workflow_dispatch: # allows manual triggering +permissions: {} +jobs: + format: + name: Update cargo-semver-checks + runs-on: ubuntu-24.04 + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: Update semver-checks to use latest crates.io published version + run: | + set -x + # Grab the latest version of cargo semver-checks from crates.io + # that is not yanked. + LATEST_VERSION=$(curl --proto '=https' --tlsv1.3 -sSf -H "User-Agent: rust-bitcoin-ci" https://crates.io/api/v1/crates/cargo-semver-checks/versions | jq -r 'first( .versions[] | select(.yanked == false) ) | .num') + # Update the latest version in the reference file. + echo "${LATEST_VERSION}" > ./.github/workflows/cargo-semver-checks-version + echo "cargo_semver_checks_version=${LATEST_VERSION}" >> $GITHUB_ENV + # If somehow the latest version has not changed. In this case don't make an empty PR. + if ! git diff --exit-code > /dev/null; then + echo "Updated cargo-semver-checks. Opening PR." + echo "changes_made=true" >> $GITHUB_ENV + else + echo "Attempted to update cargo-semver-checks but the crates.io version did not change. Not opening any PR." + echo "changes_made=false" >> $GITHUB_ENV + fi + - name: Create Pull Request + if: env.changes_made == 'true' + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ secrets.APOELSTRA_CREATE_PR_TOKEN }} + author: Update cargo-semver-checks Bot + committer: Update cargo-semver-checks Bot + title: Automated weekly update to cargo-semver-checks (to ${{ env.cargo_semver_checks_version }}) + body: | + Automated update to Github CI workflow `semver-checks.yml` by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action + commit-message: Automated update to Github CI to cargo-semver-checks version-${{ env.cargo_semver_checks_version }} + branch: create-pull-request/weekly-cargo-semver-checks-update diff --git a/.github/workflows/cron-weekly-update-nightly.yml b/.github/workflows/cron-weekly-update-nightly.yml new file mode 100644 index 000000000..5363c666f --- /dev/null +++ b/.github/workflows/cron-weekly-update-nightly.yml @@ -0,0 +1,48 @@ +name: Update Nightly rustc +on: + schedule: + - cron: "5 0 * * 6" # Saturday at 00:05 + workflow_dispatch: # allows manual triggering +permissions: {} +jobs: + format: + name: Update nightly rustc + runs-on: ubuntu-24.04 + permissions: + contents: write + id-token: write + pull-requests: write + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@55d80eb3c5a4228eec5390a083c092095115c6f1 # nightly + - name: Update rust.yml to use latest nightly + run: | + set -x + # Not every night has a nightly, so extract the date from whatever + # version of the compiler dtolnay/rust-toolchain gives us. + NIGHTLY_DATE=$(rustc +nightly --verbose --version | sed -ne 's/^commit-date: //p') + # Update the nightly version in the reference file. + echo "nightly-${NIGHTLY_DATE}" > nightly-version + echo "nightly_date=${NIGHTLY_DATE}" >> $GITHUB_ENV + # Some days there is no new nightly. In this case don't make an empty PR. + if ! git diff --exit-code > /dev/null; then + echo "Updated nightly. Opening PR." + echo "changes_made=true" >> $GITHUB_ENV + else + echo "Attempted to update nightly but the latest-nightly date did not change. Not opening any PR." + echo "changes_made=false" >> $GITHUB_ENV + fi + - name: Create Pull Request + if: env.changes_made == 'true' + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ secrets.APOELSTRA_CREATE_PR_TOKEN }} + author: Update Nightly Rustc Bot + committer: Update Nightly Rustc Bot + title: Automated daily update to rustc (to nightly-${{ env.nightly_date }}) + body: | + Automated update to Github CI workflow `rust.yml` by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action + commit-message: Automated update to Github CI to rustc nightly-${{ env.nightly_date }} + branch: create-pull-request/daily-nightly-update diff --git a/.github/workflows/cron-weekly-update-stable.yml b/.github/workflows/cron-weekly-update-stable.yml new file mode 100644 index 000000000..4c2c3f14c --- /dev/null +++ b/.github/workflows/cron-weekly-update-stable.yml @@ -0,0 +1,46 @@ +name: Update Stable rustc +on: + schedule: + - cron: "0 0 * * 5" # runs every Friday at 00:00 (generally rust releases on Thursday) + workflow_dispatch: # allows manual triggering +permissions: {} +jobs: + format: + name: Update stable rustc + runs-on: ubuntu-24.04 + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: Update semver-checks.yml to use latest stable + run: | + set -x + # Extract the version of the compiler dtolnay/rust-toolchain gives us. + STABLE_VERSION=$(rustc --version | sed -ne 's/^rustc //p' | cut -d ' ' -f1) + # Update the stable version in the reference file. + echo "${STABLE_VERSION}" > ./.github/workflows/stable-version + echo "stable_version=${STABLE_VERSION}" >> $GITHUB_ENV + # If somehow the stable version has not changed. In this case don't make an empty PR. + if ! git diff --exit-code > /dev/null; then + echo "Updated stable. Opening PR." + echo "changes_made=true" >> $GITHUB_ENV + else + echo "Attempted to update stable but the latest-stable date did not change. Not opening any PR." + echo "changes_made=false" >> $GITHUB_ENV + fi + - name: Create Pull Request + if: env.changes_made == 'true' + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ secrets.APOELSTRA_CREATE_PR_TOKEN }} + author: Update Stable Rustc Bot + committer: Update Stable Rustc Bot + title: Automated weekly update to rustc stable (to ${{ env.stable_version }}) + body: | + Automated update to Github CI workflow `semver-checks.yml` by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action + commit-message: Automated update to Github CI to rustc stable-${{ env.stable_version }} + branch: create-pull-request/weekly-stable-update diff --git a/.github/workflows/cron-zizmor.yml b/.github/workflows/cron-zizmor.yml new file mode 100644 index 000000000..8d70f3fe3 --- /dev/null +++ b/.github/workflows/cron-zizmor.yml @@ -0,0 +1,33 @@ +name: Automated GitHub Actions Security Analysis with zizmor 🌈 + +on: + schedule: + - cron: "0 0 * * *" # Run every day at midnight + +permissions: {} + +jobs: + zizmor: + name: zizmor latest via PyPI + runs-on: ubuntu-latest + permissions: + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + with: + persist-credentials: false + + - name: Install the latest version of uv + uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v5 + + - name: Run zizmor 🌈 + run: uvx zizmor --format sarif . > results.sarif + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3 + with: + sarif_file: results.sarif + category: zizmor diff --git a/.github/workflows/gh-release.yml b/.github/workflows/gh-release.yml new file mode 100644 index 000000000..c8e330100 --- /dev/null +++ b/.github/workflows/gh-release.yml @@ -0,0 +1,21 @@ +name: GitHub Release + +on: + push: + tags: + - '*' + +permissions: {} + +jobs: + build: + runs-on: ubuntu-24.04 + permissions: + contents: write + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1.20.0 + with: + generateReleaseNotes: true diff --git a/.github/workflows/manage-pr.yml b/.github/workflows/manage-pr.yml new file mode 100644 index 000000000..b22bd3545 --- /dev/null +++ b/.github/workflows/manage-pr.yml @@ -0,0 +1,30 @@ +name: Manage PR +on: + - pull_request_target # zizmor: ignore[dangerous-triggers] +permissions: {} + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-24.04 + steps: + - name: Checkout master + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + path: master + persist-credentials: false + - name: Checkout merge commit + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + path: merge + ref: "refs/pull/${{ github.event.number }}/merge" + persist-credentials: false + - name: Generate label config + run: cd master && SCAN_DIR=../merge ./contrib/gen_label_config.sh + - name: Update labels + uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 + with: + configuration-path: master/.github/labeler.yml + sync-labels: true diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml new file mode 100644 index 000000000..718bd0de7 --- /dev/null +++ b/.github/workflows/miri.yml @@ -0,0 +1,39 @@ +--- # rust-bitcoin CI: If you edit this file please update README.md +on: # yamllint disable-line rule:truthy + push: + branches: + - master + - 'test-ci/**' + pull_request: + +name: Miri + +permissions: {} + +jobs: + Miri: + name: Miri + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Read nightly version" + id: read_toolchain + run: echo "nightly_version=$(cat nightly-version)" >> $GITHUB_OUTPUT + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ steps.read_toolchain.outputs.nightly_version }} + components: miri + - name: "Setup miri" + run: cargo miri setup + - name: "Set dependencies" + run: cp Cargo-recent.lock Cargo.lock + - name: "Run test script" + run: ./contrib/test-miri.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..4f8d40c51 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,27 @@ +on: + push: + branches: + - master + - 0.28.x + - 0.29.x + - 'test-ci/**' + pull_request: + +name: Release +permissions: {} + +jobs: + release: + name: Release - dry-run + runs-on: ubuntu-24.04 + permissions: + contents: write + steps: + - name: Checkout Crate + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: Checkout Toolchain + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: run cargo + run: contrib/release.sh diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 000000000..b6a9f5e6b --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,465 @@ +--- # rust-bitcoin CI: If you edit this file please update README.md +on: # yamllint disable-line rule:truthy + push: + branches: + - master + - 'test-ci/**' + pull_request: + +name: Continuous integration + +permissions: {} + +jobs: + Prepare: + runs-on: ubuntu-24.04 + permissions: + contents: read + outputs: + nightly_version: ${{ steps.read_toolchain.outputs.nightly_version }} + maintainer_tools_version: ${{ steps.read_toolchain.outputs.maintainer_tools_version }} + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Read workspace versions" + id: read_toolchain + run: | + echo "nightly_version=$(cat nightly-version)" >> $GITHUB_OUTPUT + echo "maintainer_tools_version=$(cat maintainer-tools-version)" >> $GITHUB_OUTPUT + + Stable: # 2 jobs, one per manifest. + name: Test - stable toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [minimal, recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh stable + + Nightly: # 2 jobs, one per manifest. + name: Test - nightly toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [minimal, recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh nightly + + MSRV: # 2 jobs, one per manifest. + name: Test - MSRV toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [minimal, recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Free disk space" + uses: endersonmenezes/free-disk-space@6c4664f43348c8c7011b53488d5ca65e9fc5cd1a # v3.0.0 + with: + remove_android: true + remove_dotnet: true + remove_haskell: true + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + with: + toolchain: "1.74.0" + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh msrv + + Lint: + name: Lint - nightly toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + - name: "Install clippy" + run: rustup component add clippy + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh lint + + Docs: + name: Docs - stable toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh docs + + Docsrs: + name: Docs - nightly toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh docsrs + + Bench: + name: Bench - nightly toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Checkout maintainer tools" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + repository: rust-bitcoin/rust-bitcoin-maintainer-tools + ref: ${{ needs.Prepare.outputs.maintainer_tools_version }} + path: maintainer-tools + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run test script" + run: ./maintainer-tools/ci/run_task.sh bench + + Arch32bit: + name: Test 32-bit version + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Add architecture i386" + run: sudo dpkg --add-architecture i386 + - name: "Install i686 gcc" + run: sudo apt-get update -y && sudo apt-get install -y gcc-multilib + - name: "Install target" + run: rustup target add i686-unknown-linux-gnu + - name: "Run test on i686" + run: cargo test --target i686-unknown-linux-gnu + + Cross: + name: Cross test - stable toolchain + if: ${{ !github.event.act }} + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Install target" + run: rustup target add s390x-unknown-linux-gnu + - name: "Install cross" + run: cargo install cross --locked + - name: "Run cross test" + run: cross test --target s390x-unknown-linux-gnu + + Embedded: + name: Embedded - nightly toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + env: + RUSTFLAGS: "-C link-arg=-Tlink.x" + CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER: "qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -nographic -semihosting-config enable=on,target=native -kernel" + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Set up QEMU" + run: sudo apt update && sudo apt install -y qemu-system-arm gcc-arm-none-eabi + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + targets: thumbv7m-none-eabi + - name: "Install rust-src" + run: rustup component add rust-src + - name: "Run bitcoin/embedded" + run: cd bitcoin/embedded && cargo run --target thumbv7m-none-eabi + - name: "Run hashes/embedded no alloc" + run: cd hashes/embedded && cargo run --target thumbv7m-none-eabi + - name: "Run hashes/embedded with alloc and no hex" + run: cd hashes/embedded && cargo run --target thumbv7m-none-eabi --features=alloc + - name: "Run hashes/embedded with alloc and hex" + run: cd hashes/embedded && cargo run --target thumbv7m-none-eabi --features=alloc,hex + + ASAN: # hashes crate only. + name: ASAN - nightly toolchain + needs: Prepare + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + - name: "Install rust-src" + run: rustup component add rust-src + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run sanitizer script" + run: cd ./hashes && ./contrib/sanitizer.sh + + WASM: # hashes crate only. + name: WASM - stable toolchain + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + # Note we do not use the recent lock file for wasm testing. + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Run wasm script" + run: cd hashes && ./contrib/wasm.sh + + Kani: + name: Kani codegen - stable toolchain + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Build Kani proofs" + uses: model-checking/kani-github-action@f838096619a707b0f6b2118cf435eaccfa33e51f # v1.1 + with: + args: "--only-codegen" + + API: + needs: Prepare + name: API - nightly toolchain + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + dep: [recent] + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # v1 + with: + toolchain: ${{ needs.Prepare.outputs.nightly_version }} + - name: "Install cargo-public-api" + run: cargo install --locked cargo-public-api --version 0.50.1 + - name: "Set dependencies" + run: cp Cargo-${{ matrix.dep }}.lock Cargo.lock + - name: "Run API checker script" + run: ./contrib/check-for-api-changes.sh + + Policy: + name: Enforce repo policy - stable toolchain + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Run policy script" + run: ./contrib/check-for-policy-violations.sh + + Re-exports: + name: Check re-exports - stable toolchain + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Run primitives API checker script" + run: | + contrib/generate-primitives-re-export-test.sh && (cd ./primitives && cargo test --all-features) + contrib/generate-bitcoin-re-export-test.sh && (cd ./bitcoin && cargo test --all-features) + + DiffMutants: + name: Check cargo mutants in diff - stable toolchain + runs-on: ubuntu-24.04 + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + fetch-depth: 0 # required for full diff context + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Fetch base branch for diff" + run: git fetch origin master + - name: "Retrieve relative diff" + run: git diff origin/master.. | tee git.diff + - uses: taiki-e/install-action@81ee1d48d9194cdcab880cbdc7d36e87d39874cb # v2.62.45 + with: + tool: cargo-mutants + - run: cargo mutants --no-shuffle --in-diff git.diff diff --git a/.github/workflows/semver-checks-pr-label.yml b/.github/workflows/semver-checks-pr-label.yml new file mode 100644 index 000000000..f525ec6d0 --- /dev/null +++ b/.github/workflows/semver-checks-pr-label.yml @@ -0,0 +1,88 @@ +on: # yamllint disable-line rule:truthy + workflow_run: # zizmor: ignore[dangerous-triggers] + workflows: [Check semver breaks] + types: [completed] + +name: Check semver breaks - Label and Comment PR + +permissions: {} + +jobs: + Download: + name: Download, Unzip and Add Labels/Comments + runs-on: ubuntu-24.04 + permissions: + actions: read + contents: read + pull-requests: write + # only run if CI passes on the "Check semver breaks" workflow + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + - name: "Download artifact" + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + // get all artifacts from the workflow run + let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + + // find the artifact that starts with 'semver-break' + let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name.startsWith('semver-break'); + })[0]; + + // if no artifact found, exit + if (!matchArtifact) { + console.log('No semver-break artifact found'); + process.exit(0); + } + + // otherwise download the artifact + let download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + + // write the artifact to the workspace + let fs = require('fs'); + fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/semver-break.zip`, Buffer.from(download.data)); + - name: "Unzip artifact" + if: ${{ hashFiles('semver-break.zip') != '' }} + run: unzip -n semver-break.zip + - name: "Comment and add label on PR - Semver break" + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + if: ${{ hashFiles('semver-break') != '' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + // sanitize and get the PR number from the semver-break file + const fs = require('fs'); + let issue_number = parseInt(fs.readFileSync('semver-break', 'utf8'), 10); + + // assure that is not NaN using Number.isNaN + // since does not coerce the value to a number like isNaN + if (Number.isNaN(issue_number)) { + console.log('PR_NUMBER is not a number'); + process.exit(1); + } + + // comment on the PR + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: ':rotating_light: API BREAKING CHANGE DETECTED\n\nTo see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.' + }); + + // add the label to the PR + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + labels: ['API break'] + }); diff --git a/.github/workflows/semver-checks.yml b/.github/workflows/semver-checks.yml new file mode 100644 index 000000000..2352b9ef4 --- /dev/null +++ b/.github/workflows/semver-checks.yml @@ -0,0 +1,75 @@ +on: # yamllint disable-line rule:truthy + pull_request: + +name: Check semver breaks +permissions: {} + +jobs: + PR: + name: PR Semver - stable toolchain + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + permissions: + contents: read + pull-requests: write + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 0 # we need full history for cargo semver-checks + persist-credentials: false + - name: "Install Rustup" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Select stable-version" + run: | + rustup default $(cat ./.github/workflows/stable-version) + - name: "Install cargo-binstall" + uses: cargo-bins/cargo-binstall@b3f755e95653da9a2d25b99154edfdbd5b356d0a # v1.15.10 + - name: "Binstall pinned cargo-semver-checks" + run: cargo binstall cargo-semver-checks@$(cat ./.github/workflows/cargo-semver-checks-version) --no-confirm + - name: "Run semver checker script" + run: ./contrib/check-semver-pr.sh + - name: Save PR number + if: ${{ hashFiles('semver-break') != '' }} + env: + PR_NUMBER: ${{ github.event.number }} + run: | + # check if PR_NUMBER is a number + if ! [[ "$PR_NUMBER" =~ ^-?[0-9]+$ ]]; then + echo "$PR_NUMBER is not a number." + exit 1 + fi + echo "$PR_NUMBER" > ./semver-break + - name: "Save breaking state" + if: ${{ hashFiles('semver-break') != '' }} + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: semver-break + path: semver-break + + Feature: + name: Non additive cargo features - stable toolchain + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + permissions: + contents: read + pull-requests: write + steps: + - name: "Checkout repo" + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: "Install Rustup" + uses: dtolnay/rust-toolchain@5d458579430fc14a04a08a1e7d3694f545e91ce6 # stable + - name: "Select stable-version" + run: | + rustup default $(cat ./.github/workflows/stable-version) + - name: "Install cargo-binstall" + uses: cargo-bins/cargo-binstall@b3f755e95653da9a2d25b99154edfdbd5b356d0a # v1.15.10 + - name: "Binstall pinned cargo-semver-checks" + run: cargo binstall cargo-semver-checks@$(cat ./.github/workflows/cargo-semver-checks-version) --no-confirm + - name: "Run semver checker script" + run: ./contrib/check-semver-feature.sh + diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 000000000..84a84841c --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,20 @@ +name: Shellcheck +on: + pull_request: + branches: + - master +permissions: {} +jobs: + shellcheck: + name: Shellcheck + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0 + env: + SHELLCHECK_OPTS: -x # allow outside sources diff --git a/.github/workflows/stable-version b/.github/workflows/stable-version new file mode 100644 index 000000000..7f229af96 --- /dev/null +++ b/.github/workflows/stable-version @@ -0,0 +1 @@ +1.92.0 diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 000000000..0aba6efa0 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,25 @@ +name: GitHub Actions Security Analysis with zizmor 🌈 + +on: + pull_request: + branches: ["**"] + paths: + - '.github/**' + +permissions: {} + +jobs: + zizmor: + name: zizmor latest via PyPI + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v4 + with: + persist-credentials: false + + - name: Install the latest version of uv + uses: astral-sh/setup-uv@85856786d1ce8acfbcc2f13a5f3fbd6b938f9f41 # v5 + + - name: Run zizmor 🌈 + run: uvx zizmor . diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..ab54b690e --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# .gitignore for rust-bitcoin repository workspace. + +# Lock files +Cargo.lock +internals/Cargo.lock +bitcoin/Cargo.lock +hashes/Cargo.lock + +# Build artifacts +target +internals/target +bitcoin/target +hashes/target + +# Test artifacts +bitcoin/dep_test +mutants.out* + +# Fuzz artifacts +hfuzz_target +hfuzz_workspace + +# Local tooling +.maintainer-tools diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..5e74344fb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,10 @@ +# Note for Automated Agents + +## Commit attribution + +If you generate code for this repository, append a commit trailer: + +Format: +``` +Assisted-by: +``` diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..bef93f09b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ + +A changelog is kept per crate, see: + +- [`bitcoin` CHANGELOG](bitcoin/CHANGELOG.md) +- [`addresses` CHANGELOG](addresses/CHANGELOG.md) +- [`base58` CHANGELOG](base58/CHANGELOG.md) +- [`hashes` CHANGELOG](hashes/CHANGELOG.md) +- [`internals` CHANGELOG](internals/CHANGELOG.md) +- [`io` CHANGELOG](io/CHANGELOG.md) +- [`primitives` CHANGELOG](primitives/CHANGELOG.md) +- [`units` CHANGELOG](units/CHANGELOG.md) + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..eef4bd20c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..c71b45096 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,366 @@ +# Contributing to rust-bitcoin + +:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: + +The following is a set of guidelines for contributing to Rust Bitcoin +implementation and other Rust Bitcoin-related projects, which are hosted in the +[Rust Bitcoin Community](https://github.com/rust-bitcoin) on GitHub. These are +mostly guidelines, not rules. Use your best judgment, and feel free to propose +changes to this document in a pull request. + +#### Table Of Contents + +- [General](#general) +- [Communication channels](#communication-channels) +- [Asking questions](#asking-questions) +- [Getting Started](#getting-started) + * [Installing Rust](#installing-rust) + * [Building](#building) +- [Development Tools](#development-tools) + * [Just](#just) + * [Githooks](#githooks) + * [Building the docs](#building-the-docs) +- [Contribution workflow](#contribution-workflow) + * [Preparing PRs](#preparing-prs) + * [Peer review](#peer-review) + * [CI and Merging](#ci-and-merging) + * [Repository maintainers](#repository-maintainers) +- [Coding conventions](#coding-conventions) + * [Naming conventions](#naming-conventions) + * [Upgrading dependencies](#upgrading-dependencies) + * [Unsafe code](#unsafe-code) + * [Policy](#policy) +- [Security](#security) +- [Testing](#testing) + * [Unit/Integration tests](#unitintegration-tests) + * [Benchmarks](#benchmarks) + * [Mutation tests](#mutation-tests) + * [Code verification](#code-verification) +- [Going further](#going-further) + + +## General + +The Rust Bitcoin project operates 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. + +For a more in depth discussion of our coding policy see [policy.md](./docs/policy.md) + +## Communication channels + +Communication about Rust Bitcoin happens primarily in +[#bitcoin-rust](https://web.libera.chat/?channel=#bitcoin-rust) IRC chat on +[Libera](https://libera.chat/) with the logs available at + (starting from Jun 2021 and now on) and + (historical archive before Jun 2021). + +Discussion about code base improvements happens in GitHub issues and on pull +requests. + +Major projects are tracked [here](https://github.com/orgs/rust-bitcoin/projects). +Major milestones are tracked [here](https://github.com/rust-bitcoin/rust-bitcoin/milestones). + + +## Asking questions + +> **Note:** Please don't file an issue to ask a question. You'll get faster +> results by using the resources below. + +We have a dedicated developer channel on IRC, #bitcoin-rust@libera.chat where +you may get helpful advice if you have questions. + + +## Getting Started + +### Installing Rust + +Rust can be installed using your package manager of choice or [rustup.rs](https://rustup.rs). The +former way is considered more secure since it typically doesn't involve trust in the CA system. But +you should be aware that the version of Rust shipped by your distribution might be out of date. +Generally this isn't a problem for `rust-bitcoin` since we support much older versions than the +current stable one (see MSRV section in [README.md](./README.md)). + +### Building + +The library can be built and tested using [`cargo`](https://github.com/rust-lang/cargo/): + +``` +git clone git@github.com:rust-bitcoin/rust-bitcoin.git +cd rust-bitcoin +cargo build +``` + +You can run tests with: + +``` +cargo test +``` + +Please refer to the [`cargo` documentation](https://doc.rust-lang.org/stable/cargo/) for more +detailed instructions. + + +## Development Tools + +### Just + +We support [`just`](https://just.systems/man/en/) for running dev workflow commands. Run `just` from +your shell to see a list of available sub-commands. + +### Githooks + +To assist devs in catching errors _before_ running CI we provide some githooks. Copy the hooks in `githooks/` +to your githooks folder or run `just githooks-install` to copy them all. + +### Building the docs + +We build docs with the nightly toolchain, you may wish to use the following shell alias to check +your documentation changes build correctly. + +``` +alias build-docs='RUSTDOCFLAGS="--cfg docsrs" cargo +nightly rustdoc --features="$FEATURES" -- -D rustdoc::broken-intra-doc-links' +``` + + +## Contribution workflow + +The codebase is maintained using the "contributor workflow" where everyone +without exception contributes patch proposals using "pull requests". This +facilitates social contribution, easy testing and peer review. + +To contribute a patch, the workflow is as follows: + +1. Fork Repository +2. Create topic branch +3. Commit patches + +Please keep commits atomic and diffs 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. + +Please cover every new feature with 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. + +Commits should cover both the issue fixed and the solution's rationale. +Please keep these [guidelines](https://chris.beams.io/posts/git-commit/) in mind. + + +## Preparing PRs + +The main library development happens in the `master` branch. This branch must +always compile without errors (using GitHub CI). All external contributions are +made within PRs into this branch. + +Prerequisites that a PR must satisfy for merging into the `master` branch: +* each commit within a PR must compile and pass unit tests with no errors, with + every feature combination (including compiling the fuzztests) on some + reasonably recent compiler (this is partially automated with CI, so the rule + is that we will not accept commits which do not pass GitHub CI); +* the tip of any PR branch must also compile and pass tests with no errors on + MSRV (check [README.md] on current MSRV requirements) and pass fuzz tests on + nightly rust; +* contain all necessary tests for the introduced functional (either as a part of + commits, or, more preferably, as separate commits, so that it's easy to + reorder them during review and check that the new tests fail without the new + code); +* contain all inline docs for newly introduced API and pass doc tests including + running `just lint` without any errors or warnings; +* be based on the recent `master` tip from the original repository at + . + +NB: reviewers may run more complex test/CI scripts, thus, satisfying all the +requirements above is just a preliminary, but not necessary sufficient step for +getting the PR accepted as a valid candidate PR for the `master` branch. + +High quality commits help us review and merge you contributions. We attempt to +adhere to the ideas presented in the following two blog posts: + +- [How to Write a Git Commit Message](https://cbea.ms/git-commit/) +- [Write Better Commits, Build Better Projects](https://github.blog/2022-06-30-write-better-commits-build-better-projects/) + +### Deprecation and Versioning + +Whenever any part of your code wants to mention the version number the code will +be released in, primarily in deprecation notices, you should use the string +`TBD` (verbatim), so that the release preparation script can detect the +change and the correct version number can be filled in preparation of the +release. + +```rust + #[deprecated(since = "TBD", note = "use `alternative_method()` instead")] +``` + +### 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. Please, +first review PR on the conceptual level before focusing on code style or +grammar fixes. + +### CI and Merging + +We use GitHub for CI as well to test the final state of each PR. + +Also we use a local CI box which runs a large matrix of feature combinations as +well as testing each patch in a PR. This box is often very backlogged, sometimes +by multiple days. Please be patient, we will get to merging your PRs when the +backlog clears. + +### Repository maintainers + +Like all open source projects our maintainers are busy. Please take it easy on +them and only bump if you get no response for a week or two. + +Pull request merge requirements: +- all CI test should pass, +- at least one "accepts"/ACKs from the repository maintainers +- no reasonable "rejects"/NACKs from anybody who reviewed the code. + +Current list of the project maintainers: + +- [Andrew Poelstra](https://github.com/apoelstra) +- [Steven Roose](https://github.com/stevenroose) +- [Matt Corallo](https://github.com/TheBlueMatt) +- [Elichai Turkel](https://github.com/elichai) +- [Sanket Kanjalkar](https://github.com/sanket1729) +- [Martin Habovštiak](https://github.com/Kixunil) +- [Riccardo Casatta](https://github.com/RCasatta) +- [Tobin Harding](https://github.com/tcharding) + +#### Backporting + +We maintain release branches (e.g. `0.32.x` for the `v0.32` releases). + +In order to backport changes to these branches the process we use is as follows: + +- PR change into `master`. +- Mark the PR with the appropriate labels if backporting is needed (e.g. `port-0.32.x`). +- Once PR merges create another PR that targets the appropriate branch. +- If, and only if, the backport PR is identical to the original PR (i.e. created using + `git cherry-pick`) then the PR may be one-ACK merged. + +Any other changes to the release branches should follow the normal 2-ACK merge policy. + +## Coding conventions + +Library reflects Bitcoin Core approach whenever possible. + +### Naming conventions + +Naming of data structures/enums and their fields/variants must follow names used +in Bitcoin Core, with the following exceptions: +- The case should follow Rust standards (i.e. PascalCase for types and snake_case for fields and variants). +- Omit `C`-prefixes. +- If function `foo` needs a private helper function, use `foo_internal`. + +### Upgrading dependencies + +If your change requires a dependency to be upgraded you must do the following: + +1. Modify `Cargo.toml` +2. Run `just update-lock-files`, if necessary install `just` first with `cargo install just`. +3. Test your change +4. Commit both `Cargo-minimal.lock` and `Cargo-recent.lock` together with `Cargo.toml` and your code changes + +### Unsafe code + +Use of `unsafe` code is prohibited unless there is a unanimous decision among +library maintainers on the exclusion from this rule. In such cases there is a +requirement to test unsafe code with sanitizers including Miri. + +### Policy + +For broader project policy and guidelines, see [policy.md](./docs/policy.md). + +### API changes + +All PRs that change the public API of `rust-bitcoin` will be checked on CI for +semversioning compliance. This means that if the PR changes the public API in a +way that is not backwards compatible, the PR will be flagged as a breaking change. +Please check the [`semver-checks` workflow](.github/workflows/semver-checks.yml). +Under the hood we use [`cargo-semver-checks`](https://github.com/obi1kenobi/cargo-semver-checks). + +## Security + +Security is the primary focus for this library; disclosure of security +vulnerabilities helps prevent user loss of funds. If you believe a vulnerability +may affect other implementations, please disclose this information according to +the [security guidelines](./SECURITY.md), work on which is currently in progress. +Before it is completed, feel free to send disclosure to Andrew Poelstra, +apoelstra@wpsoftware.net, encrypted with his public key from +. + + +## Testing + +Related to the security aspect, rust bitcoin developers take testing very +seriously. Due to the modular nature of the project, writing new test cases is +easy and good test coverage of the codebase is an important goal. Refactoring +the project to enable fine-grained unit testing is also an ongoing effort. + +Unit and integration tests are available for those interested, along with benchmarks. For project +developers, especially new contributors looking for something to work on, we do: + +- Fuzz testing with [`Honggfuzz`](https://github.com/rust-fuzz/honggfuzz-rs) +- Mutation testing with [`cargo-mutants`](https://github.com/sourcefrog/cargo-mutants) +- Code verification with [`Kani`](https://github.com/model-checking/kani) + +There are always more tests to write and more bugs to find. PRs are extremely welcomed. +Please consider testing code as a first-class citizen. We definitely do take PRs +improving and cleaning up test code. + +### Unit/Integration tests + +Run as for any other Rust project `cargo test --all-features`. + +### Benchmarks + +We use a custom Rust compiler configuration conditional to guard the bench mark code. To run the +bench marks use: `RUSTFLAGS='--cfg=bench' cargo +nightly bench`. + +### Mutation tests + +We are doing mutation testing with [cargo-mutants](https://github.com/sourcefrog/cargo-mutants). To run +these tests first install with `cargo install --locked cargo-mutants` then run with `cargo mutants --in-place --no-shuffle`. +Note that running these mutation tests will take on the order of 10's of minutes. + +### Code verification + +We have started using [kani](https://github.com/model-checking/kani), install with `cargo install --locked kani-verifier` + (no need to run `cargo kani setup`). Run the tests with `cargo kani`. + + +## LLMs, GitHub bot accounts, and AI agents + +This project does not accept contributions from bot GitHub accounts. All +PRs that appear to come from such an account will be closed. + +Patches created by LLMs and AI agents are also viewed with suspicion unless a +human has reviewed them. All LLM generated patches MUST have text in the git log +and in the PR description that indicates the patch was created using an LLM. +First time contributions by way of LLM generated patches are not welcome. Thanks +for your time, please be respectful of ours. + + +## Going further + +You may be interested in the guide by Jon Atack on +[How to review Bitcoin Core PRs](https://github.com/jonatack/bitcoin-development/blob/master/how-to-review-bitcoin-core-prs.md) +and [How to make Bitcoin Core PRs](https://github.com/jonatack/bitcoin-development/blob/master/how-to-make-bitcoin-core-prs.md). +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 :) diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock new file mode 100644 index 000000000..9c567ce29 --- /dev/null +++ b/Cargo-minimal.lock @@ -0,0 +1,547 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "base58ck" +version = "0.2.0" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes", + "hex_lit", +] + +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bincode" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" +dependencies = [ + "byteorder", + "serde", +] + +[[package]] +name = "bitcoin" +version = "0.33.0-beta.0" +dependencies = [ + "arbitrary", + "base58ck", + "base64", + "bech32", + "bincode", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-primitives", + "bitcoin-units", + "bitcoin_hashes", + "bitcoinconsensus", + "hex-conservative 0.3.0", + "hex_lit", + "secp256k1", + "serde", + "serde_json", + "serde_test", +] + +[[package]] +name = "bitcoin-addresses" +version = "0.0.0" + +[[package]] +name = "bitcoin-bip158" +version = "0.0.0" + +[[package]] +name = "bitcoin-consensus-encoding" +version = "1.0.0-rc.2" +dependencies = [ + "bitcoin-internals", + "hex-conservative 0.3.0", +] + +[[package]] +name = "bitcoin-crypto" +version = "0.0.0" + +[[package]] +name = "bitcoin-fuzz" +version = "0.0.1" +dependencies = [ + "arbitrary", + "bitcoin", + "bitcoin-consensus-encoding", + "bitcoin-p2p-messages", + "honggfuzz", + "serde", + "serde_json", + "standard_test", +] + +[[package]] +name = "bitcoin-internals" +version = "0.4.2" +dependencies = [ + "bincode", + "hex-conservative 0.3.0", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoin-io" +version = "0.3.0" +dependencies = [ + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin_hashes", +] + +[[package]] +name = "bitcoin-p2p-messages" +version = "0.1.0" +dependencies = [ + "arbitrary", + "bitcoin", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative 0.3.0", + "hex_lit", +] + +[[package]] +name = "bitcoin-primitives" +version = "1.0.0-rc.1" +dependencies = [ + "arbitrary", + "arrayvec", + "bincode", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative 0.3.0", + "hex-conservative 1.0.0", + "hex_lit", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoin-units" +version = "1.0.0-rc.3" +dependencies = [ + "arbitrary", + "bincode", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "serde", + "serde_json", + "serde_test", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.18.0" +dependencies = [ + "bitcoin-consensus-encoding", + "bitcoin-internals", + "hex-conservative 0.3.0", + "serde", + "serde_test", +] + +[[package]] +name = "bitcoinconsensus" +version = "0.106.0+26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12cba9cce5043cdda968e07b9df6d05ec6b0b38aa27a9a40bb575cf3e521ae9" +dependencies = [ + "cc", +] + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "byteorder" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60f0b0d4c0a382d2734228fd12b5a6b5dac185c60e938026fd31b265b94f9bd2" + +[[package]] +name = "cc" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20-poly1305" +version = "0.1.2" +dependencies = [ + "hex-conservative 0.3.0", +] + +[[package]] +name = "getrandom" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71393ecc86efbf00e4ca13953979ba8b94cfe549a4b74cc26d8b62f4d8feac2b" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + +[[package]] +name = "hex-conservative" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee770c000993d17c185713463d5ebfbd1af9afae4c17cc295640104383bfbf0" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "honggfuzz" +version = "0.5.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e8319f3cc8fe416e7aa1ab95dcc04fd49f35397a47d0b2f0f225f6dba346a07" +dependencies = [ + "lazy_static", + "memmap2", + "rustc_version", + "semver", +] + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "memmap2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375" +dependencies = [ + "libc", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" + +[[package]] +name = "proc-macro2" +version = "1.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha", + "rand_core", + "zerocopy", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom", + "zerocopy", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" + +[[package]] +name = "secp256k1" +version = "0.32.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5fdc7d6e800869d3fd60ff857c479bf0a83ea7bf44b389e64461e844204994" +dependencies = [ + "rand", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3be00697c88c00fe102af8dc316038cc2062eab8da646e7463f4c0e70ca9fd" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b5842e81eb9bbea19276a9dbbda22ac042532f390a67ab08b895617978abf3" + +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_test" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "482765e11e55174e2d74a611674d09ed96712c00e0777e305a0c416dfef5fa40" +dependencies = [ + "serde", +] + +[[package]] +name = "standard_test" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4bac6cd647192c3cb6e687af2703eb3a30e9187e555c664520cd848443ae70" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "syn" +version = "2.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + +[[package]] +name = "wasi" +version = "0.13.0+wasi-0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "652cd73449d0b957a2743b70c72d79d34a5fa505696488f4ca90b46f6da94118" +dependencies = [ + "bitflags", + "wit-bindgen-rt", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "wit-bindgen-rt" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "026d24a27f6712541fa534f2954bd9e0eb66172f033c2157c0f31d106255c497" + +[[package]] +name = "zerocopy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7885ffcb82507a0f213c593e77c5f13d12cb96588d4e835ad7e9423ba034db" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930ad75608219e8ffdb8962a5433cb2b30064c7ccb564d3b76c2963390b1e435" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo-recent.lock b/Cargo-recent.lock new file mode 100644 index 000000000..ac27a3eba --- /dev/null +++ b/Cargo-recent.lock @@ -0,0 +1,506 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "base58ck" +version = "0.2.0" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes", + "hex_lit", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin" +version = "0.33.0-beta.0" +dependencies = [ + "arbitrary", + "base58ck", + "base64", + "bech32", + "bincode", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-primitives", + "bitcoin-units", + "bitcoin_hashes", + "bitcoinconsensus", + "hex-conservative 0.3.0", + "hex_lit", + "secp256k1", + "serde", + "serde_json", + "serde_test", +] + +[[package]] +name = "bitcoin-addresses" +version = "0.0.0" + +[[package]] +name = "bitcoin-bip158" +version = "0.0.0" + +[[package]] +name = "bitcoin-consensus-encoding" +version = "1.0.0-rc.2" +dependencies = [ + "bitcoin-internals", + "hex-conservative 0.3.0", +] + +[[package]] +name = "bitcoin-crypto" +version = "0.0.0" + +[[package]] +name = "bitcoin-fuzz" +version = "0.0.1" +dependencies = [ + "arbitrary", + "bitcoin", + "bitcoin-consensus-encoding", + "bitcoin-p2p-messages", + "honggfuzz", + "serde", + "serde_json", + "standard_test", +] + +[[package]] +name = "bitcoin-internals" +version = "0.4.2" +dependencies = [ + "bincode", + "hex-conservative 0.3.0", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoin-io" +version = "0.3.0" +dependencies = [ + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin_hashes", +] + +[[package]] +name = "bitcoin-p2p-messages" +version = "0.1.0" +dependencies = [ + "arbitrary", + "bitcoin", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative 0.3.0", + "hex_lit", +] + +[[package]] +name = "bitcoin-primitives" +version = "1.0.0-rc.1" +dependencies = [ + "arbitrary", + "arrayvec", + "bincode", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative 0.3.0", + "hex-conservative 1.0.0", + "hex_lit", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoin-units" +version = "1.0.0-rc.3" +dependencies = [ + "arbitrary", + "bincode", + "bitcoin-consensus-encoding", + "bitcoin-internals", + "serde", + "serde_json", + "serde_test", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.18.0" +dependencies = [ + "bitcoin-consensus-encoding", + "bitcoin-internals", + "hex-conservative 0.3.0", + "serde", + "serde_test", +] + +[[package]] +name = "bitcoinconsensus" +version = "0.106.0+26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12cba9cce5043cdda968e07b9df6d05ec6b0b38aa27a9a40bb575cf3e521ae9" +dependencies = [ + "cc", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chacha20-poly1305" +version = "0.1.2" +dependencies = [ + "hex-conservative 0.3.0", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "hex-conservative" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-conservative" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee770c000993d17c185713463d5ebfbd1af9afae4c17cc295640104383bfbf0" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "honggfuzz" +version = "0.5.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e8319f3cc8fe416e7aa1ab95dcc04fd49f35397a47d0b2f0f225f6dba346a07" +dependencies = [ + "lazy_static", + "memmap2", + "rustc_version", + "semver", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "secp256k1" +version = "0.32.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5fdc7d6e800869d3fd60ff857c479bf0a83ea7bf44b389e64461e844204994" +dependencies = [ + "rand", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3be00697c88c00fe102af8dc316038cc2062eab8da646e7463f4c0e70ca9fd" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_test" +version = "1.0.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "standard_test" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4bac6cd647192c3cb6e687af2703eb3a30e9187e555c664520cd848443ae70" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..e1efd3af1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,136 @@ +[workspace] +members = ["addresses", "base58", "bip158", "bitcoin", "chacha20_poly1305", "consensus_encoding", "crypto", "fuzz", "hashes", "internals", "io", "p2p", "primitives", "units"] +exclude = ["benches"] +resolver = "2" + +[workspace.lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(kani)'] } + +[workspace.lints.clippy] +# Exclude lints we don't think are valuable. +needless_question_mark = "allow" # https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +manual_range_contains = "allow" # More readable than clippy's format. +# Exhaustive list of pedantic clippy lints +assigning_clones = "warn" +bool_to_int_with_if = "warn" +borrow_as_ptr = "warn" +case_sensitive_file_extension_comparisons = "warn" +cast_lossless = "warn" +cast_possible_truncation = "allow" # All casts should include a code comment (except test code). +cast_possible_wrap = "allow" # Same as above re code comment. +cast_precision_loss = "warn" +cast_ptr_alignment = "warn" +cast_sign_loss = "allow" # All casts should include a code comment (except in test code). +checked_conversions = "warn" +cloned_instead_of_copied = "warn" +copy_iterator = "warn" +default_trait_access = "warn" +doc_link_with_quotes = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +explicit_iter_loop = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp = "allow" # Bitcoin floats are typically limited to 8 decimal places and we want them exact. +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_not_else = "warn" +ignored_unit_patterns = "warn" +implicit_clone = "warn" +implicit_hasher = "warn" +inconsistent_struct_constructor = "warn" +index_refutable_slice = "warn" +inefficient_to_string = "warn" +inline_always = "warn" +into_iter_without_iter = "warn" +invalid_upcast_comparisons = "warn" +items_after_statements = "warn" +iter_filter_is_ok = "warn" +iter_filter_is_some = "warn" +iter_not_returning_iterator = "warn" +iter_without_into_iter = "warn" +large_digit_groups = "warn" +large_futures = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +linkedlist = "warn" +macro_use_imports = "warn" +manual_assert = "warn" +manual_instant_elapsed = "warn" +manual_is_power_of_two = "warn" +manual_is_variant_and = "warn" +manual_let_else = "warn" +manual_ok_or = "warn" +manual_string_new = "warn" +many_single_char_names = "warn" +map_unwrap_or = "warn" +match_bool = "allow" # Adds extra indentation and LOC. +match_same_arms = "allow" # Collapses things that are conceptually unrelated to each other. +match_wild_err_arm = "warn" +match_wildcard_for_single_variants = "warn" +maybe_infinite_iter = "warn" +mismatching_type_param_order = "warn" +missing_errors_doc = "warn" +missing_fields_in_debug = "warn" +missing_panics_doc = "warn" +must_use_candidate = "allow" # Useful for audit but many false positives. +mut_mut = "warn" +naive_bytecount = "warn" +needless_bitwise_bool = "warn" +needless_continue = "warn" +needless_for_each = "warn" +needless_pass_by_value = "warn" +needless_raw_string_hashes = "warn" +no_effect_underscore_binding = "warn" +no_mangle_with_rust_abi = "warn" +option_as_ref_cloned = "warn" +option_option = "warn" +ptr_as_ptr = "warn" +ptr_cast_constness = "warn" +pub_underscore_fields = "warn" +range_minus_one = "warn" +range_plus_one = "warn" +redundant_clone = "warn" +redundant_closure_for_method_calls = "warn" +redundant_else = "warn" +ref_as_ptr = "warn" +ref_binding_to_reference = "warn" +ref_option = "warn" +ref_option_ref = "warn" +return_self_not_must_use = "warn" +same_functions_in_if_condition = "warn" +semicolon_if_nothing_returned = "warn" +should_panic_without_expect = "warn" +similar_names = "allow" # Too many (subjectively) false positives. +single_char_pattern = "warn" +single_match_else = "warn" +stable_sort_primitive = "warn" +str_split_at_newline = "warn" +string_add_assign = "warn" +struct_excessive_bools = "warn" +struct_field_names = "allow" # dumb +too_many_lines = "warn" +transmute_ptr_to_ptr = "warn" +trivially_copy_pass_by_ref = "warn" +unchecked_duration_subtraction = "warn" +unicode_not_nfc = "warn" +uninlined_format_args = "allow" # This is a subjective style choice. +unnecessary_box_returns = "warn" +unnecessary_join = "warn" +unnecessary_literal_bound = "warn" +unnecessary_wraps = "warn" +unnested_or_patterns = "warn" +unreadable_literal = "warn" +unsafe_derive_deserialize = "warn" +unused_async = "warn" +unused_self = "warn" +use_self = "warn" +used_underscore_binding = "warn" +used_underscore_items = "warn" +verbose_bit_mask = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..6ca207ef0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,122 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + diff --git a/README.md b/README.md index 92fad33ad..bfa2dcc48 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # rust-bitcoin -Rust Bitcoin library with BitGo customizations. Forked from https://github.com/rust-bitcoin/rust-bitcoin. +Rust Bitcoin library with BitGo customizations. Forked from https://github.com/rust-bitcoin/rust-bitcoin. \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..c299816e6 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,540 @@ +# Security Policy + +This security policy applies to the "core" crates in the rust-bitcoin ecosystem, which are +`bitcoin`, `secp256k1`, `bitcoin_hashes` and `bitcoin-internals`. These crates deal with +cryptography and cryptographic algorithms, and as such, are likely locations for security +vulnerabilities to crop up. + +As a general rule, an issue is a security vulnerability if it could lead to: + +* Loss of funds +* Loss of privacy +* Censorship (including e.g. by attaching an incorrectly low fee to a transaction) +* Any "ordinary" security problem, such as remote code execution or invalid memory access + +In general, use your best judgement in determining whether an issue is a security issue. If not, +go ahead and post it to the public issue tracker. + +**If you believe you are aware of a security issue**, please contact Andrew Poelstra at +`rust-bitcoin-security@wpsoftware.net`. You may GPG-encrypt this email to his public key, which +[can be downloaded from his website here](https://wpsoftware.net/andrew/andrew.gpg) or which is +listed in full below. + +# Andrew Poelstra's GPG Key + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFASGPEBCACwQgoZpLKmYtTFXQ+YAXIn8LtoLqom/eyJP6UbKQJoWPs9P79o +CQpYy3Y6xx8JYKK556htGbi0OXIfqmDakBMG+yxs5fj6z2bTfLMJz6ej4AORC/aV +JrlopIGE8/mhiQ+C1wX/3S3ueSFUmDOju4pucjzQTb3pL8ONob3kwWJAAXMP0SWy +aNQY/ZZQ8k2Q6joI0gd80LbM3tWUdX8ryLArfbE58CITiEgKPA1ghNGHCB78elrh +oMcmhoes+wTHN7Q7wSkoJdPFzAgIXIff/UpsDhm8EUjVAdgi0fo04vxxjdTF86M1 +KaoAYbxtSR5Rb+U101xd9Xsca+Gofm2KsAGLABEBAAG0NUFuZHJldyBQb2Vsc3Ry +YSAoYW5keXRvc2hpKSA8YW5keXRvc2hpQGJpdGNvaW4ubmluamE+iQFWBBMBCABA +AhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AWIQRpmmPvwXrTqaNM/8B60Kkc +QL0AkQUCYQMqwAUJGlcTTQAKCRB60KkcQL0AkQZ2B/9j9UhklerAYJBehQqKJixb +JL6DPdEufL4+PnR51bXV3YRn2OH6Orhq/XXadjdbAcSz0nlGXyFBoPfzZfzZAeqy +jLbKsHCjPNST/K8whZMvUVgUk2kze8DOY2R6miNmQwEf1stMh5ZrTcsj4F1GHeS+ +x022NPvnT+V0A4t3I+/BqaKnQ92eu+l6RWQjde40Ti6COwozaaNjYuxUYiYUyHnJ +3oC4UlVp0AnV/iUo4qVlhfDlrAEgQq+5wPKtvmYmgW8SmiCWDAdBn4r0VeFAPcB2 +ogzM+UT6DWcf0z0upT1QtvcOBU9/DjwCLv1+HcYwRwMkYwFd3dG+XkgQ2uj5H4ZW +iQEcBBMBCAAGBQJV+wjiAAoJEE90TaH18VOBuSQIANeu+vh+7SCzhR1lRtiPlO9c +oDsQ/VXf1V0nLSEOIFphPy5exOeeb/1ReJLzLFEllVblmLm42wnWjrQVPVnRfBkQ +xj8vt7SGlYH9QnvEDF/ewli1BKOZcaBlCDrYCa/MX3kwPl4H9K+JnwujgSQInYgG +ploXiimYqFlzxiGFCqfB02q2QvGDXxXxDkqeGIj/Ari9JYAPwtubUPnoWGPz/Mnb +XBzGaesCFPo21us75cBHOdDQVFdbQy0ppBMK4PEdeN0JYksRex3hLbMSnHBdu0He +NfgTPqqnD1TufBebz8pvNqP6EkvHud614bzTpvY2AYDjnQZIEjqr2bwJQJgJW7eJ +ASAEEAEIAAoFAlX7ED4DBQF4AAoJEHfoBoKoPbQOEQsH/jtK6ipNhgS9e0x2xwia +/+refQMsbLdA/MEQzb6GRr67rXXu8btMWsXorL7/P82WB3OE2nZD0EpRGc5Gcvjj +nMPSGvKMM0yhdELZm3uwAteR3bM0lCRApOcWMwtPjiJds3kZjCIDH0OEzr/fpRHR +4jw9yWJi5mLdHrpC3ATssV1bumfOyQHUrZweZAiI9VkU3wO33epHD6m/uryttlqQ +9nCsPnskEtle8NSbLTzNjNd16roXyQuZbHwxFBC5sDZHUi7LzJbfDwCBjmRLVRa9 +QHvOtCcb8sVXhqg0EdHORlc5wj+6TBjFJ57ISU0YUo/07AiUWyKwFrKHWaY0NyRF +r9qJAhwEEAEIAAYFAlX9oZYACgkQibu4Zj4uZc6OZg/9F+iMKDjW1sSIS/mrU7M3 +UWerLdGRd0JVTuGluUpvyi4UPQwXbtPLi1r+yW1X+YuzvSEOZEQQgqpElFoixvzw +dcdsbfIn40rn3vGW2dOOEMm3lemK3Y2eQSn+4sErW6gzu8uf2EgLHWrbrhOJbS9i +lM22xyksmr3NnlY9Jemauhf7xX2S1xg6KsLCqGOqEn6jhRmLM+OYdYuSZ75t1MAk +dheo08GbL1Jdu1RXw3DwS4soY/ujgbAFoGkVzNv5cEgZ1HnBMIVT7bFwbAWCP64L +B8UToCoEWCB1eNKxDI44NHMbwIBu0JdhCM7iW0GwPOVaFjTlAXDIsgrqqWhr+GaI +vgPnwi1xv45HpB/a+zh9neFqL7uZDocU3KXEUwVCkaP0t3h8/vN4J+QgfCVwWDRP +gQtj9n2oDkM+DqbOSA73/O0O68oBAU2Sd1yJkRutJv5PjKUf6gcKeedtMrwWo7Vo +QrPfEmgWvCoYXs38yLJu7xeKr0h5pAjUx5RhUngeHdkOwxPPOoC2Q8BON+xT0ZoI +l+OO3imgIz0Bz7U4UUPADgCFw+GFc5tqPMj1OVDn9ysQYP7PfUUAwmHxJ6gvjUI9 +ttHQH3ZK11RTLCCN/YQCwlSjUFbzeR1MvaSelrTnSypG/P3C76eDUT3J8FT7UKZw +c9gsvZ633NTfRRIKh7FInMS0K0FuZHJldyBQb2Vsc3RyYSA8YXBvZWxzdHJhQGJs +b2Nrc3RyZWFtLmNvbT6JAVYEEwEIAEACGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIe +AQIXgBYhBGmaY+/BetOpo0z/wHrQqRxAvQCRBQJhAyq+BQkaVxNNAAoJEHrQqRxA +vQCRYzEIAJNMMqFKAHCWi0npDNjaRypWT+zvfbXfnYEctdladHbrs0lGEHzMACeC +JyBX9JOZbkp9AFNmLL7UvFlzLC1MOQ/tp3V8fip0S10lBUkWG1vtsgeM3N9ERFAz +3brFtM+h3l9wohfVWwpY9sLzCWJ43QlBN22pjLcpVJGyv136M4dcfkXWA/csQsuq +XjBt7P4QwmacISnL1KUIJMgWBl9CM1nxiANMQx8EyCINylEu/A9qNy5OApkRy33v ++ww3kJ9PR4hzUDkd/s+R0PevlzYaw+rgdmKET4lh9J8EarSYu7RUG2NimKhzqweH +aLo0OYgwfNfpKiFKNNaZ07NN2MAo3ReJAhwEEAEIAAYFAlX9oiYACgkQibu4Zj4u +Zc4M2Q/7BvWr+ugC/ZJONikubDkn+nJ/TVxl1CBciMWsyJRI/RKLQQcEvY00xIdu +CF2iPvaqlIifDo6suMTrAO0L6wIWlovICWYak9n2RrsN6w693ccj39MzAd3EwaC0 +Va0YlcNFz9pIyqQtRzyzEEXQeBti88RJvwlMOa+3hganU2NOFerFkpIJHBNYBKQR +lnbqWo6fc9fWKCmQI3Chtkl9UtEslBziaEPILPsphfdW82iSgCEsKTN2zoliXZtl +/P10J+2yS5dO7AjMHyVktS7+idR3Qdde3l0W/5uw9Af+DbBTQpsvwZPRhakWa98m +nEiAdSWRwmtBSDxHQDqSdhtMq3NrwmD9qBpQphFfaGM+267wmkM2zEcM+Xc9EKEO +6CnR+RBYEnmvSqZBiRPB8cN9UfhwGRXzXh+KoDyZCK3i245LBmA2du9SvLPlD5zs +3WlYsYX4XsCDT/DPRGMkQmA1P582Ygw4s+GCJt59Ti1ELzGXiQbaN0C5hgkxk5Cy +IXs9mv2YO9r9scw4zO9lgeTC4Y19C1h+XOTqvUHOfsjVjWr7KuSjtYhKk2PAkJCg +1BO7vFqxTWF34X3h+CjPIYIyMVTQk71x7anLFQdqq1qekGCCJqPQ3XZKNH8nCo5M +KxmHbWzXs+5GEuk9DAUIE8EMVY9dzdGD25gi9Oc3b8NqKgJOrhKJARwEEwEIAAYF +AlX7CTAACgkQT3RNofXxU4FaWAgAiPzsB/nInalQQ2p3FrReO/AUELbjomoJoBIV +QDcv5w7C5RtWvzgy1uJ+NLWlVO5zJKyRcDCllhaBWVpZjqRH6w+zjbTc6BXAMUe4 +da5T7Q2TJvun6oIDmobnySx1MBgvXrlAcxJV+kDWaIgUcdODhdg3ScI14BRoBsX7 +TccuTC3dJ/4DXO6cwE7476Nzt99m37AwV5/z9CvpKiHHzulpDSnvarPSXi/w4fun +7YtzND85qfv1i/U+J4ueYRmPQVeuiAjHc3y+09SCWymwFz08o5qcMoZLdoPlFHCl +oTtxJqrY0PLWFikJlmukIRzmqbV3mt2vpTHGYCO92ty8qCzy0IkBIAQQAQgACgUC +VfsQSwMFAXgACgkQd+gGgqg9tA5x1wf/RlDqaZIRlEIj46ZDPgQ4lGB6l3ycu1jl +W8og2vkoSIuncZhzEasOhleqvngaF2zf5UD6FzTFci4pgNP/oCiuLE9x4yBKnawW +ghJTXsIZ/Jd2ZZkVzsjaI+qQ1XFJv+oL+0GVgJlqfZkunszIcx0uIuqKQVjVzK9b +t4B48u/8Mc11xllDe0EuOoe5c5t++8NtFh3CumU52YfwJYCptaBfUY52yWj0syml +HME8TDYClgMeJQia/6XB+t6XRWLrhY6ZsLHdk7rJHNCNZKUEW8GTv+MhaWh3DVXu +K4DT3ApDtHKkRRFBrAnYrhCikRX5Uwz8hpODc2lPcT/az06MCVvaPLQeQW5kcmV3 +IFBvZWxzdHJhIDxhc3AxMUBzZnUuY2E+iQFVBBMBCAA/AhsDBgsJCAcDAgYVCAIJ +CgsEFgIDAQIeAQIXgBYhBGmaY+/BetOpo0z/wHrQqRxAvQCRBQJhAyrABQkaVxNN +AAoJEHrQqRxAvQCRjgQIAJad9AeZK4LcrUwlhFaWMDJ5UHVGkQQhwqN6X74vmRe9 +u4038wiWbhYiii352A0s2Pc3i1dqvclx4BZP4CPRJ22p+MnTY/jkiLUoO0+B6RlR +ABqGpDJBO9EL7hFCl+uIAXMC+8ydxgRj5Mf2TvH2ZEHIj6bdIC3qwFqoFe/aJcHf +Euy3IDZf/oT+n7JLb6+FK5UTP8fNQVXlYPmuGejRFth/i7kq7IVCJioJ6nDbZBLL +ZxAkG2080MLcXqfci28miM6laIrTbMp/lvmmxAf58XRFVTXlPOfaI+LjW99KbR+4 +PuIvcQd5GdExwl86bARLAlgUjXhLEqelRtno3mtKj+KIRgQQEQIABgUCUPDl0wAK +CRArUtddZVtI3frFAJwJT+mDI95JV97R+cBA9HtBtfxByQCffgr0OgSG46R6UbAi +oMWbYzYkMyuJARwEEAECAAYFAlDzG8gACgkQna7c7cP6Lei5vwgApA/2Eak5eXw2 +w1gj+iiPgviiJL9o+BbS110MR1cn/wEHdkMBjAPX59myWKlPWC64wIvt+MsMrCIN +vT7QJUUBKzOcMH1xoRQ3tY0X+M7bLaD2M8+Kgw00D4eyC8aGtcFKauqWHsbxABc5 +18n8J3dP8oaf7UOqgsETfRJgnD3GZA1lhs8INwsuGVqp4+WoWlt5JTGsrMlDnm0r +dWekcozSKzDZkxTkbcC8M5HEvZypmXRa5hVQ/TIICy1YMqULb7GVweZK7Ma7ZXK8 +AQm2OZ4Jjs6byQX3A9Z3PLJzmNQGdwJ/BSh3pET0YSPPcAPYM2E84PJhP6GqaRTN +3yKcsn9pJYkBHAQQAQIABgUCUSPNYgAKCRBy2PuGax8742PBB/49Gfquv8xjz91x +YPNMbXzWjxhkFaF9JEwnSiGq8AQAfotH0bYYHt4Y/vdukY9B4fnqj/U34aOLr5qK +SkymKII3npVCV9bP5eXSAPbYoCy92jHW5RpnTeR4H3O4gn5ICTWfrdOYq/GH2I0E +Eei2nlW9SdgJRTq8AuN5bwtzaeS1gvAQqQeABq9yKUOImggHViigiL5K/55xDms/ +ybgNIHgFA2yMuCTZztiyuVi8AiJHWreeoJW3Cyo4QYx67BOCIEgHYRnF+elbKbF5 +BBViG8tPwDo/QzASBeTwO3TbkMeZsBdw3QJ8jGgW2S5vbWyJcW/nFIdOVxr4I5B6 +98br0XQTiQE+BBMBAgAoBQJQ71MZAhsDBQkB4TOABgsJCAcDAgYVCAIJCgsEFgID +AQIeAQIXgAAKCRB60KkcQL0AkadHB/9V9LW4i55Lu/GSeBiZjdOnkD2HKJSGbvFG +mqT7UEPupBB07v8q9JOLyrDLrxZl/QvpDCTmrmi3NAPXnneILgzoiBJCCXdxM0n2 +WyJmRNl7pHIvGmjl4CDbZe0LnhIe66vam4v394CNsbl2M0I5TLzVmP9Pb+bGJ6cL +M2zhTdCLwfG8IqqjaCf19S79DJwwfaKnnjkv4Sj9vCxKanOZKt9NsR74UIxTS3M7 +FLOK24IUW7uqkzZWsEyU37lVEWZw8i6ov/VbYphTsSwGZvrX5EhPhalQK306esJY +ucTQ+cuQ165QxZRISk1M/teoyhGJP5f+A3Ec0ctF0PO8fbBx1A7TiQF7BBIBCABl +BQJS+Yo3XhSAAAAAABUAQGJsb2NraGFzaEBiaXRjb2luLm9yZzAwMDAwMDAwMDAw +MDAwMDBjODRhMDRhNzAyMzI1Y2YzY2RmNGEzNDQzNjJlZDBjMTllYzgxN2E5MDE0 +ZWVlYzcACgkQf6sRQmfk+gTeWAf+I/v9anL0GzK/MQ1v80qysizrbbfrab8vojLK +n/vVqoX7B85uVE+B/Mp9FDAQ0mMnD1Yn1PsWwX3fr4du4Jr+jRXRqupF5GLU5LlW +NfP1VwY/49zUpUx2ka+aGgOCNhsr0VZrqZPt8qjDSVlvX1twrc7P1bWk0Y/e4Y4z +whBDNZ3luge2fakVuxdk1eoLwrgHARCt2MnFkcNm4pZiNyeTnWlDgcKDFatRkXSE +czC3jTC6cLBaOjR1p7lzXthAAlUPbOUcztNCOhjhoEQu05pQQB8yN9lChCachsc/ +oKGEWkFgl4UsuYtBx8iJB8lYw3Yvl2gEOTA0oIyXzKnRLt6iiokCHAQQAQIABgUC +VA9iQAAKCRBQfh+DfBT/qeW9EACWx2O20PEGQA3QpJfXR4ocJD4iXfYNYwu9Du26 +2RKwLLDpVxCgXDUIlH2EfVaQNQF/jatz78UnukPAbCmQz7n85lvlU64R1P1Mv1/W +80f+211mb+K3V6mAE4vQtJTMis7vW+c4lv30QNwkQ9n4YFz9fqfRm3qacy1ydAdM +wnigV/L+M10IRnYMB6A2Z2lYLmvvCtKWkBSXvl9r8LVJRsVT2DSzw4O762YcuVXN +quLV1aGp5pe/8w0DKd+OYJrEyYi1Qj+Svod2J6OEobDTISqBdi0KGujelaDaCDwB +teTZBdjBgWh+YG+cRBoq6jNPF4tiyU34kcVHsZflyNyCgUmJsSSgJW7D4KqXZoEy +WpsIALAf9xCAh16Uj5zyci3Dyk61Gj9C9ykhdEHfONGVhNF9G8lmGc9SGz8lNoJd +SMQ63TsWqxo62D1Ap+BIzr6EImets16gbRs5J4w1bV1g5Vb22SlpuFScE6wRO+S3 +W+onsr3xfj2Q1faUxmFjkcjAgBPMz2Q2RuV3+m3FusI8RgcpyNpCLr6cJD2JaKTR +udiAafV0a2TEh8olN9f496+/XCw+ZJn9zON+1GVzm5cmr0B/aRqSi7nn9sP3P8Va +EDRV1rkcLVWIDov42/st8hR4JNZ6lapfxn2kzMdgQwoT/g9wF4C56kB3600h1HsE +YnQJ/IhGBBIRCAAGBQJUHfafAAoJEKyFk2KwQTv6kugAoI3lvAuQCG2oqDO2/eoW +diHP7pogAJ9xRwHrbsZX4owUHT5frkXhzAkNDYkBPgQTAQIAKAIbAwYLCQgHAwIG +FQgCCQoLBBYCAwECHgECF4AFAlHz+0sFCQWkSVoACgkQetCpHEC9AJGNtggAoh2B +mpLMurIgXlB4ueaMu3tkskVsh8qWxE7gwOnUCK4SV8jPA1+mfymyBZZbl6BStHD5 +PEw3Ls0TiMFyIML2uAD3vS1vB7HVZTwwJy62FwNMy1Ghrg8JesBlwnbTWA2Bk4kD +G4QVzN9/EGLW7xgHiQUaZieiT5XR8YhfAtmH1ZSJ5xmaRfFrc2fu3uJw6qhs4mI7 +tpSL6mVYET7pY3TaMflSXXqUB3dITBKzXDBaKIdosKfMW+BmCC0Cxy97AF3qqW1c +E/d4bnXSNf4k5Sq5WKTAFQbpDJCQPIWz2cMatKblzvfh0iDBPQinbeAx52D/7rnr +DwakV83cmoxNaD7saokBHAQTAQgABgUCVfsJAgAKCRBPdE2h9fFTgcEOB/9q4au8 +n/tY/jCLo8BLxYVRstSdOBunU2M1lwSZXQHeI955a90gxd59EBageWu1HisuUW51 +mUF2uZA3Eo/xvTt5MzuofP0WQj+PofTr1BHws7Zx5lr83XtnlS8H7cpwI6SmH/dp +30HwwiKnvW2amBATlBawtP3md8UGtNk2vHRjV9qtnpzgPFKIl/zKlLaJZFdQs0Bo +OFyHLADVuphgdQNQBsg+wGK7Qhz5jpW2dJrEpNg+U+Q1VCGGIeew/tCcFJrLaqY+ +2HQAkb9RhkqChpOsGCgcTloDjq06qtBVNo8J+qp3XSsDl5wNPwk5AQvc0wG1gmJQ +QR+dGScOM39Zt5D7iQEgBBABCAAKBQJV+xBCAwUBeAAKCRB36AaCqD20DhjeB/45 +Tt3rljXIIKWhkTsRz6fmEdGV7ShL2BvRBv9R3hA6C7vAxn43sVMXYc+hpNIdYZQ9 +kPiuOjGXk39ZfYUeQZCq7R1E1AuPdoMDPFFKC8s9mkNcn/iq46gWSzQ6LQ3F+2tu +7MWPErvcRv7EaFC8J2bgXh/JaOw5bB9Rvh4Zy9ndHwmsPhwaWZ2Cnx4yEU7cFGDk +IOy++PXZx/fmB8knGrgTbYpihZGOp4w7I12wQGrG/noyklyHvikmJvCoWw/k+L1p +2SEOO/OMG2kGz9/oVbQQ0lQEIp21Pxx97vGNpEp9MTGklCLRjA59IE/lAYUeweCH +ticIjJveWHelks918K8siQIcBBABAgAGBQJV+wPWAAoJEGviztFKmRe8pyMP/3PD +Ra5dQO6kK7gxyEzRV/Wq0wnhdSMx2hhsdmDko1cN0A1s3Id/y7kfjLROW/hp7Thx +nQq5iq+qG4qEjnAqtXeskQ0c0Vif66Q9w+v+PtOAFal157jgw/Szdf9JCe/psBP5 +BMHZT/YXxkA6TODSsVEo7XXgJgvzxwTdviM+j3ZTggFhDVI9zCr2akAniDFsCRRK +8YBp+LPqXXeBSpiCy4nufiaMNiGZBHnj4qpY9D8AsbnqmNYF2FXdOKEKu0WfOCRl +IWepjCICzWHYpbU+tUKUY3b6wGB8wIlw8SJ+Vi73gduXeBLP9CCYzXrIOayamYOF +TgVMOCBtxAPGK8/ZjUCboSpOh71FLvaAZYXzmyt8tBBhT6JIUPu40QFOPXk833+3 +3QNbl5Zmn4pG/NohHP6jhAIBNo6d5Nndf7HTE8/afNUvVtZJLtqPSX2Na9h6C6N5 +efILyg5rfD+U2D9Aa21rbzIyxB+pqrj4XIoKuVgPLA/BVDK2yP9WB0frzN7Lv8Nq +0msfSzuUi9Rbb1cACv4GVKO8qdODktyxfbI73lq/3tbAtetbGbvmiox7cJLxV4Tl +Y8F2CgN9FAyzbjH6oGm1pb/1O4v7Wl1BwGeuyKU+7v5V8iWUEOUR0ryaezehewdo +sqv+dc48vMFKqRU+U8R0WPiizlPqMr6f7oqH1k9uiQIcBBABCAAGBQJV/aHKAAoJ +EIm7uGY+LmXO4FQP/2NSN+RwCrZJLa/3BGeOGfrWaScWLIZK2uDkA0F2IBSzxpAq +bAIrbAq/YtxZ0r8mA9/eKjHATUGzn66ZIyi6ctJCbyZ936mDdks02y4+yGd0o2ME +DNO5vh3HqBjkZX5wHS53VRCWhA3cjG6A9Yy7DB4fY3G7cSAez5TtNOq8YJSpUqEj +/iDs1yXL6R7qOtZ1+s6o+yy7ZujuGsnjCSyvQo0lTD97croT7EwJhVGAcVDADcWS +SZVrQQFlHegCpVjgQepPzUJxYUSW/zeZszQ/Xi8XeaeGjxdZlnoR2nuubnkL25Ok +qbOnBx9sEQ/A4BnSeq2ZmaMLayCTCctfytlhrA0PWaf+KmqPLLsDJ0pQxSr4xJHu +leUhq6k3aeTXODxSH60/rQRgGuP5oBZHepymhJ4al7kUJ5Cu3m4EQ5HOA7xD1Nzm +jho1+0QnIyde0X/ZCKHudNnMwyn+EBpVE4iskVyXVF5PFcBGZtbgMf2aIzMFiDqf +7E3sK1SvuVmG3i5qDc5DihPcxdsN0UTzH0ycuFXiYgfFBQw1KV8l15QBN2JsN7iu +Cup2QbRdctbRzCoYqTWhBAPSP4GA94X1rKEGQuoiB6w7pHc7VdQyVUOHh2KrKBVF +t7Vjcv1Zuf7/Dzz6cdydihaXtOUS1zrZm+T0NzV6oSvW+pq5Appaj3K4xGW7tCpB +bmRyZXcgUG9lbHN0cmEgPGFwb2Vsc3RyYUB3cHNvZnR3YXJlLm5ldD6JAVUEEwEI +AD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEEaZpj78F606mjTP/AetCp +HEC9AJEFAmEDKsAFCRpXE00ACgkQetCpHEC9AJENMAgApv94rvW2PKh6EpdU3AZi +V7urV/l7l1hz0dZfNArzo9mn0Sqh9VxCa8EUytUmRzc3s9zFBHV4Q85i1iqLS7um +9QR/boBRZzsOd3WBxFYKW2mGybf9hxBlBqILPikiw+7wZv1WdDE82x3qBQE4HiiP +QQ0QKXtHf0gE8Q7IBneWQGfIP1YE32AUUWH4FK0akH8wT4XSbSo8qggcHxTJrsI1 +c3jnh/MXJtBm1O1JOfJvfCSO1GBx5Lw7cGmOnPElm1y53kZ0cc97+sk27F//D2Rt +30oRI62VXcysOENWIxBWgI5jMgMQeLG1A/cOcs+qXmZ4n7rRCM3SVM71MNgh5UFj +W4hGBBARAgAGBQJQ8OXYAAoJECtS111lW0jd4ioAoKzv0zQN2vCltURI+WsjPT4p +OuWkAJ9SsVndSL8jQ+Dd5CzPMkNy99wPU4kBHAQQAQIABgUCUPMb0QAKCRCdrtzt +w/ot6DYvB/9cCjJIQTkBc7GxX8nOpQPnu0/QpK+zbJTPLuYPi/XV4XSq72Xtm6ug +Ygv5hwTHMkBSP/4sshFGykx/1055bl12+MQvMYZpnTrHYG7hsF3ob25tcU/bixXO +fDwhvNrY7lM5mHwd7S7+NCHBDdbh/G6ZRRuzdUUgVvxvAM26VsKOS5aikHSaqk9T +Or6edk2wPKl/49glspRwMebppCPVQcwvieK5e8v6WO5L+/5mm5h8Zrpk0fOjaCyK +PPO754p1GNHSKrFfVNDNfMMTY8rp4XjBHHRQw24Ob87kwrctvnkr0Gatih9kbJUW +oPwxIeN1TnU3xTqdag/WNPzjWThkFEEbiQEcBBABAgAGBQJRI81jAAoJEHLY+4Zr +HzvjFBAH/RnY2TRoVfoTF1yjZYYVgIh9iuqVKAolK7oM7TGiNRRjR4UzhzGRTabJ +NlCuKnp/u1Cmng2Gt7Sl4GdIIW5TY+RSBcqepTOz59YyvCZA0pGrAghQDJi3imSw +gc5s53NQtgB2IUbB2mt4p9sc3WROfYiBBYEZWXXCN6r49xDqgs9NmLyc/l2nrG8n +GVESgZVnLtmYi2GWjelqwZwn/a+Lbk1hveABN/QjP+0eehxvPdxdxCpovSrDHRrQ +W1EkH/JA02/ziZ0cLqqLMCpR46QIS7Xkh0cWuP3VXJVR6bT/YqZw0dgKN7M/C1p3 +t52BAeox8gXSkOKS/3svonOpKFdLKbmJAT4EEwECACgFAlASGPECGwMFCQHhM4AG +CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHrQqRxAvQCR2LwH/j11HbaHIlQV ++D7hK67nMpTdl5ZRcK1flNJFHU3jcqxDeaXkHWMMoZqvWx+sbXCOVA8+WIn3l+Cy +clSvGN4M0qEu4hOSbCRdbuSOFUV1sYTxUHdTtocCL/oSGAYtdtwTKMYCZZSMEwiL +fJkrojZ8ceQ5LggqoMK1s9uki+U2fO9FOJXWa1SJB0dq+lNMpGVRxRHGgqavhL7B +3l45sKXM13ynrIaa1d1J9Z5+skbU+d4jbAv+wYAqaDkBsUgXxrdo00UZWKcQEgON +2hcemz0NLI5acFvH2tzoNynWsMgPVVzQ6v0HIMEk+hA4bNh84sUq3gW5snzNN+yi +VIogALfOjGKJAXsEEgEIAGUFAlL5ilpeFIAAAAAAFQBAYmxvY2toYXNoQGJpdGNv +aW4ub3JnMDAwMDAwMDAwMDAwMDAwMGM4NGEwNGE3MDIzMjVjZjNjZGY0YTM0NDM2 +MmVkMGMxOWVjODE3YTkwMTRlZWVjNwAKCRB/qxFCZ+T6BMMOB/9xyr3H+x314Aiw +y0fl3eYFhX35L1+EehCgYMpf11gTzRIxiosbEGxjGXqaoWhNu37J4cpfApsPwOXM +v9GMjLQE80hHwuAfh1jYO/gJk9dutrVd1OMpv6Ltk7c7dfK48LfKAystWpTf8d3c +KaIRlucvQLEmyhT/aYkTb0u3N9DHNKBvbBeHRqufjnKAIYShYrMH1UtWpFzf3IiH +5ctDHk/6Jsv53JunvL13sUKJ9pyqa1wnYfZML7QhR7eVr6f0mn9L+75QfJZznXaF +DEn8yt96yZZNt7WQAp78HUu6XcbnRIeiFHF+XhcsJCrSfYGLmg0dkUaofVFHh7mr +n4WXfv/ViQIcBBABAgAGBQJUD2JAAAoJEFB+H4N8FP+py5wP/1/Yy4DnFr3IsgRq +noTuEcFI8EpXkeycORoZi52EOV1KIY2Eff38ahAv35O6xtSKiYeL8vycBZJLWqZM +w8HyYZa+lyUu/gmO5fUyQipxLCtgXt3umoaYSIWoefnOZxmyUA2Ky7xsmMeFZD/Z +Si/wc2cwVfo5/xSTF1Z6E7uYQTdI5kV/E4xIJGxYVqAlnuK/Z6fVJhjaJSRN1bOJ +yV6fDzqZDw5L/qe94bIRRhThoapHVe1ogSfuUSBjHq/R0hG370UsnOIRVhO3hCSm +qpNVm9AeYWKtn3j8XXgIr1UfIduKVo45u/v/eBTRYeZ5bptEDFyBYDGHKv10xkap +Ma85ggtzOU32Vio/9XqCSPGumUQe/Js07/9bROWP09if/fsyGpyfCO0m81gLN2zV +au39rKI9jPRcApawa4H2stUBFMkFFm2cw3UwVJfE216L4r77X0tj2um96agCy4wV +BIcpHjVK9Q9Wx5bjRjTP/WbVBFg42X7K5VU97u//xCuCYWFH9JRkFdalwJhBAQbD +6vUKyTJMOh3Q1kIJgZW4BFFqBxe0CL/QQfRmo0UHxe5XrsMeERKo0XmAncInCgYd +kUK4xfMEWl1SNzBUSPFHMDpWKft8bczcfhXdX7DRQMxKIYBYFUZHnKPM7STVGDa5 +k300Ew/f9io46wOU/YAMjHl6r0BViEYEEhEIAAYFAlQd9p8ACgkQrIWTYrBBO/qn +vwCgxgz0DNQN/kZXpcosUwzMui4DBZ8AoLa9dpon/9lYtyVsj4YYepkSsKS0iQQc +BBABAgAGBQJUKM0DAAoJEL0ClCQh9IifNkIgAJn9Kk7FURHWg1TSiXXbINBl1AQA +5QKUPp4qKiAT5ObGhAPJ6zcWza3Kq4D2XYodETKGR7YM3CcYJlV9s0/JxW/KdAC2 +WnnSjmWhL+1wrw+E7hJFF7Rm+nhZR8eRjLGFryJxu7UQ3cE9EzJq+s9WH12rPXAj +clME2g4Idf/BYlIVdhROK7qI+j0f6ez1JpTi0rK1emXd2LOjYsf+ZvGEeaZua+3R +FPVGvIdAxCHkYaYAmmRQDUnZm29IYFakEfMHRIPNfFJ6vYNGGypSPozGhO0cen3A +a6lcTJ7Yq83TaF7+vDaPMhWjheImeu3Ku7FQGNKMfm06N5l6LFMjDnZRPfnsDfWs +5atpxPtBDBm7d5v2uVOuKXcNdelTLgIoLLHLU58nQf3HocPJecdWFN4PPcbUwbzX +LodU/TH6hG1a5U5Ph0TO8Ibhp+ui0qJB0StX47k2DK6tnU/c+qBtdZ7BBynnTscD +KfTVyMu9GnNkRZZX9XCq2m/f43UVktS0G6Tbh2G3lr9rm0NQHQn7UFhv4V5EI3V2 +3Jm6TTKtuKaUmqKTXr2FE2lKaWAfcKU55EnIzA71ixRQAYTvkFUvONsOY0vV0HfP +4VBnMYhPffTmcdaMsOqR1W2hYKAh/RSgqal+6GKgVqmWoICIWmg5FpUVmlE5UIU4 +T9Rb96MDfl4eM6jj2ED6eq8BcXnKB8XTQcFzNaAGtf9m8KA8Y2UC/enD5BWuwHLU +Cn03fJo4ouyiBwnEqd92cyfi0oCGspl+NFeLDmDujWKXdmg9zklroH9FsaFNKbpm +FhhghA1D/ALd1GxT9u4WV1DOg9i7gXM9aK4Gnmk8xbdPg5LZfmUNP8z24fRwtw5t +cprp8GKGYNj0euVFCp03X37HIy4RZkCMEQvfDDJsaE8HG89w1bfQpZ9+44aZZ0N3 +S4j5gexBOFGquXm1KcPsuQQxw4B0dSp7aSswsZnWsl5lP2Sul8TAxZBLb5GhzJli +z51X+uKQkGUMQZlDD38k+UAZHnA1DBlDmvwzgVqB7N7pCjifaqw8+jsHL6QqivSF +8TsEFwOQ1komff5EojMJjim+JThUovJzYaLu2U95acGWhqaoEkJzXKCPkGY7M/Fr +TFyyclZEymkDQcTWQIy2j5ZBEfywXwzCFnm4Lf/MxZ28R5nLv54dUwYoYlGmWpUw +rc2r6r86pTrvVFnhFrC4DsJR2/kr8joDR9ifXVeS2CYU241Y357xT7yskb4SMrXL +N9WBkcm5XxrgdAWOvLfOXiocjjLQDp87rL67DdQIlMFAjsbnn+fY/HWv4w/M6COY +OT47WQVcXEGO+G5+vBEgg7ztJGwXXv6thcZp8TTpDhvhnKYQIZe1hvMUh4eJAT4E +EwECACgCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJR8/tNBQkFpElaAAoJ +EHrQqRxAvQCR8dgH/3C4aYaG3376KD/fEpIYAZk1eK6iejhlR8TTpbNZAtDQVn5d +pU/8xjiNCsFa7oGWibPkIyJuhyu1BQdGEazH2x4fKjbQsQlfG9hMVDM4pNs45bzY +f1bqzrIVEhxcJF6zSU6nhTpbQGn5cTj6h3rOvx70bX2BLxtHkzfkAhBEbyNptHzw +TH5X/f1LeSzu2r6al5/wqxL0/MVerRuGmRnkqHNvfjiG9Tx5RJK4dGX2oh2YtDTX +UAfQoYb5jIE6nNWxKT1mUidO1Sa8t1KOnSwjHgZxZszFkpXCsYC5hBicUiWUtatv +jNRUeWiMLiYV7NEvOVfnkhODCaXFgarHP8wnlziJARwEEwEIAAYFAlX7CRgACgkQ +T3RNofXxU4G2Ogf+KQ4Sg36PGVmLbRj4lIMdvI5MM3NCLkcEdG9KKzS9fKmfuFco +H4xPfhdrGWghuTS2WWojKvKh7Lz34D02z0Y8IevVrFjdXhMv+1KmIYqVjS7dvtqd +szVVJEH3FnwyGb5qNDKB/bKgR5GnaIMqUeiFxeYjHOcUCWoka549CSWCEfQ1U1hV +dz3g/Yul83qbtRmt6bVU9UBUh5XntbuMpC/g4cMK/Oa/o7dcta36tEkIx/hg/PHu +J/hW4hlIG7fFHlBQhHZzHnCgsw5xazeMzSZRP0eClxq1bjw9ZVVLg6ysIjHRW0aq +W17LYUwJ96MMR4KUO77zANOHweDsb7Mebgs1D4kBIAQQAQgACgUCVfsQRQMFAXgA +CgkQd+gGgqg9tA79Swf+Iz1P/OCk4MmrEX6pbYVkJWSfSa+7PMfucdUqF769yB3y +3aEdiVKZ+/hDvAGT+d72kRrnGNGTMn2dn+BpuFFhRTKHQdt7TWkVV2CXsitZNGF9 +iE3fGJOuwm/GMOLsE4p1qweVAxHIfKqh9ta7EywATLx4gTDzKKzJF0fXwW4BQZQ2 +d63KpPwqRlgK5QH0HDDxHNCcF7s/kEUtoGsFJZVUJeHmKdX44Caldnhm4qcKU25X +WIr1MzymfRLNh4GnsnY1Hf9pOy7QYrRHIzsqtKyywD8uaAOIeQlaT9W0F9dKWDyB +V4PSaO4HriXVSwkE38Vk8Kle7Gf5J22zDamNY36AeokCHAQQAQIABgUCVfsD1gAK +CRBr4s7RSpkXvDKsD/9QJuq6mVxtdhx6AWLx77P5O3klZjxube/jegLpKSp5BT46 +WsoDtxwcI4qCEpas3HTYyRZLDl2rRQGHA+pB82xQNzjWuyDiog6Qhz8lRd6hZgzD +bCm0ZsXZ1WweNp9IFxJsNTm+kCruIcz8rr5P0eZAn6ogCA2U7k4pykmwtj9WzD7l +3tf2R1nVpfl254eIFUD6SqgVLW3IbWZIG3LxANAbUFP+NgQMw5wQB1iZRV3azk7H +Jxp66d+Mtqpn2+m/SIjYAU8L4Kbu4y27aUuWJ6iS73BOSQRM7+aAP5NZLCl9OeYz +ZqlpZHzlKJuTrU57mMANdmu/La8mPMwZxTDUCE88r1yfEduqqq+61kIod/BqXaYJ +VycrXcRC9vTxFKG0gq1D33jziig0m68tEnnK6g2iV0oGhC5ORWO04XywFqkwAPwM +3uNDWMNF1FnPD9z3mHw1FtJM0T0WNxXrOVkzXaIQG9lu9g6yh4+UneFrn+kmnthl +ieKvMv/D5mDk5x4ipKbgTQjiVdRu+CFYsIT01oi2JI4AsdpFSzWCUVDvy3ORMOZc +OLnTE2Sj1MY5BngeTlmNCSzchnbsTNcVkKxvSIK7pPpmg9A91RcZOhGran/P7t6m +iWsH1nxuUZLhz3vvFjqFFKO0mBcWEGF4OAQviJPt8xNzpRJXYwfXVcHHr9naq4kC +HAQQAQgABgUCVf2iAwAKCRCJu7hmPi5lzjWEEADDf+kXBgFdQITZEVWcPjtS/mlN +OH+mu5Zeny7UUu5KPrqSy3MBDz/V+k4KN/y6FnT0mkCJVIOENysGF2jUbuZe7Le8 +/Lvpgn8wJ0BpbqkvgC1pxy4eZooZSKmO+xjomA6ng6pi/CDC47TCouCm9hhhuyDO +lsm7hCVLILTNH7TVrAKtBJacHYQmAdeT5reseRJUCOaE1Crc0Y1yqasUoByPN+ja +NoC6spOsRDugrNrXCzV2pWAlO8PidDYbhgYWJN/vaaAqJxqky80e9l9RdZl0SbZu +bta1g1trkzbGRxNNhRSdXiLxfeEbFkKrsW2VbiyWKxgKqxkb0k1b25AFOaL4QKRc +phpfVPK3mthha1GaE5j3cYyuFGNViBAaEkPpBS0JOmt66+LIjx+tZ0t4rVHG/oIP +GdD9QMvToWzxGqTI1zjQtcJpud84q0zTokdzKhfZMdc3fC8SJWKhrpUYHlC311Jj +if5IU2TDfPWIQ1Oesz/OcfAxjf/WXBijYj0obbXNkYHqtXKmBg4NQn4yVF0OBpUk +3MdbWAVsUH6mNiVTA16tLPekSr522u+pCo24zQF9RhNOvtrxRuyVjduzzYjFK+kG +47UgZBqjg8gOZdFh2tdjeuevE4yuxAmzcNYhCYLE7czMz+7br3qozHKR7/PGfcqg +WHy8x72OCoutpA1PMtHVydXHARAAAQEAAAAAAAAAAAAAAAD/2P/gABBKRklGAAEB +AQBIAEgAAP/+ADtDUkVBVE9SOiBnZC1qcGVnIHYxLjAgKHVzaW5nIElKRyBKUEVH +IHY2MiksIHF1YWxpdHkgPSA5MAr/2wBDABcQERQRDhcUEhQaGBcbIjklIh8fIkYy +NSk5UkhXVVFIUE5bZoNvW2F8Yk5QcptzfIeLkpSSWG2grJ+OqoOPko3/2wBDARga +GiIeIkMlJUONXlBejY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2N +jY2NjY2NjY2NjY2NjY3/wgARCAEYARgDAREAAhEBAxEB/8QAGQABAQEBAQEAAAAA +AAAAAAAAAAECAwQF/8QAFwEBAQEBAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQ +AAAB92NAAAAACFBBUiigAACFEKIlBGgAAACFAIQyQ80uztZDoWkKAEKCACLFoSLQ +gKQGI5r41zAzbzTRQdz23PSgJACghSBqBBVliKARzXzZvmt50M2CWalhDR1j6Vzo +tABCgECwAUECkeaXzzXIxoOdhFZSqKQ6S+mTsemyigAQoFzQQoIBlfJm+deenOwE +ErKaC0RpbHoPoXNoQpBCkDUoICkgMS/OmuOksynWahiyWalENEBo3H0LnrQQoIAV +rNAAiAcpfnNYoUKklZs0qFAEyU9UnvuVoAQoI1KBCkBmPLLxWLo2QhDNQVUQqHCw +dY+lc6oCgAGs0ACA4xwzeN13jsaMmQZrFQAEThXG52v02elICwJQNywFBAco8udc +rfbHUVkzEJWahAkBivLYPoM96SBbQBG5QECCuceGai++NCsmYzUIQlQIIeWs2eyT +1ayhRRYA6SgSLUEczwTVX3RohCGKyASoEA81c7O8nt1kVSAqB1lCIADkeCa0vtjZ +AQxWSUBEEBwrz2dD6NzZFosADpLYgAIcDxzVX25dKErBDNQGUwUpTjXCyJ9OyyKs +FAp1lRAKQrzy+FdS+6Olco41zOhslZTkvOrHU0mDz6nRPdYktItoQO0okACJwXwt +al+hGU4Lw1Odu5fXmWuOp51xcxPRNdIh5dTZ7mdJQVVIHbNEABDmfNa6y++ORyrz +6zlbNezM1XnrjRLXSNwPFqeg9bNKEqqQO0sikAIczxNJfoRgycq5LT0ySuFc6sU0 +mgePT2s9GatoiWgHaWRakQoMnGa8i/QgczFZOsdKweeoQGypDz2+y86lUWiJaDtK +iWJRAQk145v2M05rirHRBi3hUQDRUhxt9V51KFtIFB2lggCAGZrjNdkpk52yOiBb +wrCCmgkFdbigqFBKF7SiCBACS5m0mqhzXBoydE4acymjSEVqzSVBbUAikveAWQIA +QzLF3BeZAZqHGoaLGrInTWdWIAqgLAl7xBKBACEJFmkuTFCVzJUCI3UTrrNQAUAA +L3lgEQAgIBnQyvAlZusGSWak6yKtne5IIUUgADvLFRACAEBJbLlcVTN1wXNlTciR +WrntcgAAAFHaEogBAQERLZqRm2GDlUqlSRK6WdbmoAAAUg7Z0BAQAiRRC50jKysG +KyUhmym07ayQAUAAV2zqQIEgBCKIXNjWYtYMVgGSWbWp2uLVQAKQBTrnQEQQgIuT +CeLc9GN+vGuBmhismKhs2DV59KqUFAAB2zqECQHM8+nmshisy/S579MsPMcazWRX +STa2IeXpjNz6oho9EUtIFXrLJIeauFcrOVRFWKrO/q89dCmUwcreVVC2JUTxdOeb +BSGo7r646AsYXyWcKgSVIUNFlZ39LnrvComTlXOgVErzaxw3gAADUepeZzIRFACA +GhCb9vPfryqKyc651ASPPueffMQoABSAH//EACUQAAICAAYCAwEBAQAAAAAAAAAB +AhEDECAwMUASIRMyQVAiQv/aAAgBAQABBQL+jZ5DkfJ7+RHmq+SJfZsliJDxWzzZ +5DkWXmpEZWus2SkPZsjNoi76uIyTy/XtQlQp/wCukx/aby/WVrrPC+3Slw5F50Pa +iyDtdGXDyrRRWzhP30G6G8kjxPE8TxPEooooooazi6adrfmPKK9UVnRRRWmSyRD6 +7+Jwz9jxuSGIh0J8Mjyt1kssPoT4fEBb08sPnfn9XxAW9LKLp78+GR5js2eR5Zyy +j7lv4vB+x4HIcmeTE9DZeSykMwud/EX+RcjGOZdiZH2MkMfoV5IlwR5W/PhmHySE +jEVtISIEiWVWKNZIlwQXQlGyWHRDkeTKEhIkMrS+P2PRmf8AS4zoSylrfEeeiyvK +S4HpY9TK9rosUfHQ9DH/AAODyybL00V1K1vWv4a7LdHky2eRZbPea57NFDWuPPbe +uPdepc9da77TmkTxneBJvJ+iyy9CzU+i5JEsY+STPOWVGCqiNWOLWV5paJ/aMnEW +Mj5hYyE72G0h4yQ8ZjnJ6kR4zocUVqbt6LoWMyMlLRLGSJYsmXsog/Wh6py2E6Fj +enjSPJvdw3pemU93/8QAHBEBAAICAwEAAAAAAAAAAAAAARFAAFAgMGBw/9oACAED +AQE/AfJx87fhr7k1M81ybcYHKMjUNE0ZjRaJjRaJQnJpzk+2dG6NsGjOxrR2ujax +2LXOte3/xAAeEQACAgICAwAAAAAAAAAAAAABEQAwQGAQIAJwgP/aAAgBAgEBPwHU +ns49WHaztqi7rLdDxz9TKeWcoouTYOFFWoouxtFaiqNgGQagLf/EACAQAAEDAwUB +AAAAAAAAAAAAACEAAREwMUAQIGBwgFH/2gAIAQEABj8C42OOz063go9Ez48ugE81 +IfBLoK6vhBkUKBX1BXyTtBx4oltL44q//8QAIhAAAgICAgMBAQEBAAAAAAAAAAEQ +ESExIEEwQGFRcVCh/9oACAEBAAE/IfRv/AoUbFpXZlhhC/YWRYmOkxI9eozudIxE +B2Rg2J0McNaRYvhS79dVlSLx7Ki50NlsuOsFJMvyd83opwhiw2XY3oYIbmxM/spw +rh15/nA1sxYy6QnsNbk9CVn8Ev2ENCY3YXm6jUNTFTHZjErEUKhTVH8Mmih+n24W +2UMJUUyhwJFFFGZRR4jnrhQHPI9lkrnPngtU4pGVD8nXDRGnGDRUGHBRRRUXfkKv ++jlSNijohKk5Y+SWhYPivQyDGZ1lj8OgmYe0vnoNUbfiY+NS4IevJ64bh7Q242Pw +rFSJ+JnXB3Y/BiNODcOcIUL4EaBa87UbyJjQdFULJKxyU4LBpCnobhWRLQSpDWOk +VdCcNRVBBqULh2ezWxrFDi08/wCoxksWrBlvIfgHLaGNiVI1kdBcsavcjstyxeej +ku4MVhDQljOUqk2KEihI3CCYx4X4EyLFoGhjYrSaxRUKN0aXn6jSxXDGShCjQ25L +aozstGniXPNUPbKWoITjTgUuFrw7OvBZeRDGdlhPehvBQK7KFNmKm/TrAqCGMqhl +DYGJcdPTehDhnQ3DQyioUpj0e+b0dZHwGVi8CsKMvSfRwuDhQwDUJemOXvg5csNF +cOzb2FwfAy/RvkbPkXxN0JljY3Jsu3CfoPZ2OPg3lGKaDNMQpssass+YaDDY2WJ3 +KrsqhO9PyPWDuOjTgla39Y/zP4Kh5iFZmU/YRsawbaLFm9FO+DhphlDKdjI5pQlM +ky+e0I1wb0SN442MR0dGxitSxo9oQ6KfhXBuslw+KZsMV/QkxwdB2tL4Nnt8WKOj +cuWWPlZ1PA1rTPoBjWB7zDfjRXgTlwcs6vK//9oADAMBAAIAAwAAABAkkkltLJaZ +SQQAgQKTEkkknlv2G4nRAAQCSbksm029R2fvggDbSaZN+r01xjaola46STSRL/7f +l1eTMsAQHbAAEAbNZtyuQdrMH2jAQTTaAlP3aXraL4fEmTSbaQKC07PWf0eRFQsA +RSZCQSbPI3KaXlfLSQAACACS8YDZKTJXccLW7aSAQFaKRYAR9lSh+ABQBJA1DCeJ +aT/64uyJIAYRVpbdlLQFuH2gmbQLbI+STss1d9DwORJKLbLVjBCKpfrKHz1rZBbB +AFQIUoVDLY6e8TYDJb2qPOTYrs9EbvoLZbZY3QDLapMF7hZdBYZZLVQBXb3B55Sf +C5LDDZKGzc3j9arpfrS5IK7ZY4DBPyT1dX94bJCbLZJxeJ8DMralJrdoCZZJRi7T +OqCsHPhb3UhLZTQg30hhX0t9LW43JZIT3IIaA8OP/tv/AAgWwwwVi4Cjcib7Lf8A +zFtllBSJQjExW2223tUtllJdGJmYWZG2y3n0llknJM0NMlaw7+22yNt/35J4hjkq +Jo//AH/vJN/uTlJAH1YBivtt/rb18f3uRY6OLQEl8/qd9eM95QXrOKG2msU3kze8 +0pbTm0hDkmk12Lc0ymnxb1+m8E0A2my//8QAHREAAwADAQEBAQAAAAAAAAAAAAER +ECBAMFAxIf/aAAgBAwEBPxD6MIJEIQhOqCEIQuJhoa6Et0NlKMa5UhLLZcUpdENE +5FmjINDIQWJl8aFlISw8JExNWuWEzCCXgnEkLgY+BC93l8C4WhD4ELgfEQuJ8C9r +q+BfFLWbzKGPgWFo4E7h6iCHh8K1Y2ZDZ1h+DwxvgTFqi+D+MwfFSeL1fKtfF6sQ ++Ix+j2ezx/A+MoFWt3eHyr1Y+VCzCCRCDWHh86elEyjY31kLWl7S+cNc9H9P4fDS +lLhBKen7KUpfKlLqhejGutLq2UvguVUpS+a9Q3fT/8QAHREAAwADAQADAAAAAAAA +AAAAAAERECBAMCExUP/aAAgBAgEBPxD9GlGylKUvTdEIQmaJ87KLCJtCQT5WxYSE +JZhNHi8bHhCCLhbsXGyUSghsbE8vdifExFKN5TL4QXDRsRSlKUpS5pSi43wLDF0l +4IYuBiQ/dMYuBiH7oYuBi2LyXExD87ouJkHutJquFlHogw1hZSGHo+BiQ8oQbGMQ +sJzBvlT3N4SF4LifCuF8S4WMu0wvBcL8lskTjg14LZcr9lysmUhIhCEHleM9mPFL +q8roelzdF0PzQud7LVcyQiiW0JqvrhSFnQbg90hMvRfgmSMj8IILFNj0omUukE1h +NUEJ4PB6r2IQhPRiaLjP/8QAJxAAAgICAwACAwEAAgMAAAAAAAERITFBEFFhIHGB +obGRweEw8PH/2gAIAQEAAT8Q+jLke+0xLPph8aF28C36drjX5NM0zZviMpCcjdVn +nVcLv4a50fXGjDaQjb6HuD/jh4bH/wBnUizOicsZJND7FQmDTUIYmRVga2gWcNmO +yKl22IabYptfLO+JPrns6jiRZhaJ2K2hbjnRLBnwIWhuRvA1k3gY3Mx/Rw3T6JMs +DS3JkW2h3MKLnJNqG66GSh5D1IhLNiZtmVz3PH0YRowa4TF+yIX0TsdL88aFZq+z +C/BRy6X8FZaKCThLQ57dEYtjaSjQ5CTazRHTE0kLO2WKCLwSKRaFbFvIlrQlbrIv +vPE8v9/DY8mZM0i7keHAqS7E7Hr9Fg9lmYvTEikbHtEGVzslZixzFihgyThCmZHr +E5ZGhaQ3+BdTp6E5R8bhXxte8b+Fz3od7wPSfRpbNN9jz6O/0ejQp2JtCWBfoKey +WQYSpLY1Bdh4aahBkhW2SEQHWKiLc6MfYvTCbfwVOiNrJNLc7IMBVfgqS2Okt0MY +8cEknY6aIkeo8HtCFK2MeIHDI/RajREKdsh4QoC0E2dihC2IW7Xx2TPP0O16K75V +0yZhLsdpzcD0MrHFUNdUMnLFOGPStjc7Z0yMgYgV5FI+o22xJMDmLpjc4KEiv0J0 +e/D6+DQ4X+juD/gTo3o0OnI/0xTWxzL8Dti00ib0JIUngJl4O1niPgXga9ESjAy4 +XY5IRJtcr47HVdGFL/JMRtscKXQ8jpT7Jlp60PCO2PLPSJy+yeWhKtEIFRgaDR5E +fAZ8HJEDkbgWaFjugm+J4niSRVnbMnP4EE53hGUvTssibElX0xrdDKBGIXC2MfBB +rlogSFv0PDUj0r4alEkiZJJJJI/s14be/TLFaYnLMP8AYsvhk6QtxRTA3yNwNjvh +q+NEWJIYjmGhqPb4zxJJl+DdqXAqbHhzg14TtIeFIhm8lH9YlDHhj4IPjQ1wjjAS +x1aIRcSL5OoXZhIStjiU4N1geEP9CrueSpYkeg1DMj5GuLHw+GXMdOhjS7GNJsn5 +q21Nofh0k2RqCFN5Q3d4SIlpiJ00NAnw6NDYqYklDDY2NEtjXoQJXsalSYsaUtvB +EHZVF8c8vb2KWkOIH28IfbF7s3exFCG8Iyyh2SxaJSkzGQ1ikbDYx5E5U8HhEWWQ +mk2K3KINUxnkZhqaQyReYoXC4n4oUT9mcG2PoeZPxBCTI2uyJXRIfRPy7IuaTw2N +abQ6zI3TZEysWWNLvBUhxJ96RDIbxR9ogXwNiCV4Y8rxJPxVZG7SNj7NSN4HkdJ3 ++xe4Z+AIogZZH8wJZZfwvdEJElSJa+uCS5eCaSZBJi05NYkyrMWKEv8AQwuBKklG +OF4b4xze7P0PzJiDXh3oVKRUbMa1vKZSPMiwTGB1Bk2P+hE9FaElWMEn0egpURC/ +4CzCNioQiuNC+KGdpDyqxxn/AKGpf0aEpUaJuCRHDjwZzqvY0o/CiShMSBayKhJk +MYoJCCVFPqIK+xUKhcr4vMcLrjCN9iTlL/IvqkJMmiKTArSnlDEGKY4MvYSODEIR +1KcsToo0MPwXxi1BBJxjs10MeDQ8GEJKjIYl4JzrI74KJjdkihCTmxAljTkmeCwS +Wpi6gWE4QuPvlDQdDI0Tdjbl0PFZI7sakbNxoSt0tDSLQo02EySMxuuyW4qQxiSo +kVFwrKaROlpfxXFcv/EPJcekzvA6lkX6zUtmc0hbLWp+CHpW+GBJuBIINWQV4MJC +t5ZAxMTkToboWv8A4oInIzPiFd8Psf7LdbMiTh9kK6WRm5eF0Jzng6ZlgpYwnPg0 +a4Nei3InQ7ZAq+UfD7ELMt0TnpGh4H/6h0O3/TQ8dIdaENVwOax+CcqibiY0jf2J +uhXS3CEhEiQL4RXxXGhzDSMXkeWYiB24R7o7apMP+CojLGuWxX59iy4xxgJG5Y3Y +VigohMliRKFWOJMzZo/vEEcV8cuWyZGNS7eENx6xukJk/wD4TDe30JNO3JnOhsYS +jIsCwIPwkmTRIxBUSTZDcpyPHOTZPEfF5Y8GvTMd8b8yTeKzJhvRN92TI8P+smoR +RKR2MaFE4RBDsJjQhMk9fOfg/wBIdE3AxeEhtpVJovDrInMEGnD/ACNtpJUv6O/p +E70NM1EjhYNZ45iYY4DYFBFSImmJyp1xJ9koniDXFGvP6PPaKSvYs+saEWycNf0Z +uUvy2TVYG1OzdwLcF0SUgsrLHxkFVkn/AINRJAgaBh3xafbgjXC50R23xMIZdR9m +6YlJkXZPZPbJJJJJ4RN9wKYSG/0g2Xg3EuLikhPJuIyXiT6m/wDBa0YnXR1Q7Uej +OG9lg9iq2XCCEJjJeGSlDQNm7ZDaEkzLPoXDNTokro60x+u6Ky/T6xukz2rRJknn +CRE2SYTQ3Lb/AMSE7aS9ZJJW3lIn7HLyIYcXjhE9Kxqji2EVlUQTwSFjkroZfQHL +gJFhC4bEI2wj2R8J2a4njk/GO0oL6rJ097TyhMTJ7I2kv0TS+tQayxv1kjfQzD5X +gWQ0KfVBMnkm0RHCQxiXp3wxfBCO8mhWZHrDHOK+KR1Lz+xg2SSSZQ8jEZQsFGZz +ZIiRuuFihliQ0KzM77Y3fySIPobF6Sf/2YkBVQQTAQgAPwIbAwYLCQgHAwIGFQgC +CQoLBBYCAwECHgECF4AWIQRpmmPvwXrTqaNM/8B60KkcQL0AkQUCYQMqwAUJGlcT +TQAKCRB60KkcQL0AkWgqB/4x0rSeA8SrfwBuzd7q+MGpqaIK3egP3lb3zLhBgOYw +U+/Bf9iH35a5rWuNzpnRDVQLNN/LltKKzaUhyBYf1TbReMcObjousA0LRK0uGQFa +ELIOHDhAjx938tNu/iM+aRh0Xt1KP2X4sWH+Lf4pLhK00ndK3FzRM0xWkO+saHoE +3ouOgQxrKRLSZ3pHjVYNa1vwWJRJYB5N/FPL8hH7ufqDm52EWg/jpgQGaqSoVoq1 +CR8qoIV3wlrO/R8OMVI64IWeLW2oRRK9xQZp4q25p6yiJvM9e1EmD1bUf+7qi4zA +X6BRBTO5SQG0hOJjmf3XrZNEoF8zt0+bp20UJ9CWaNkuiQGBBBIBCABrBQJS/AGa +BYMSzAMAXhSAAAAAABUAQGJsb2NraGFzaEBiaXRjb2luLm9yZzAwMDAwMDAwMDAw +MDAwMDBlYTdkOTk4ZjIzYTJiODM1MjMyNjMwNjY5ZDZlYTA5MDVhMWIwZTAyZThh +YmQ2YmMACgkQf6sRQmfk+gR56ggAqN5hVBXG+DTBjplyUKR3WoYf2m3HSDwSDBaN +9H4ohSzm3GeIzXu866AQI9G+3mFCzMgYgzGh5OVcHCF7Bznt8K8hYjd9OCgWxAyz +cjsA1A8zjgaDg8HskUNU5b53NpCqHoNpqT5u1ckuBIRPwNMxEGj31D4pU7o256L5 +iBPPsJxSa4ouF5YAT023Iy3GqZDwqpQdvjHNf6wjAXx2BZ9xBFR0MtOgA097brKw +13A+T9QZkJlv3XT2WSTBE4jvPDjzg1KttpG+Mg/4juI/JiNsHiRxlbmU7bqtfdYX +patbscGg0bf3S+lQCUB45lWr4hsaHcVK3FX3ALeau9GUsMsOKIkCHAQQAQIABgUC +VA9iQAAKCRBQfh+DfBT/qYBvEACY+T+wpBtLLyOZf1ZW3H1qGKomOxAm7jUrPNq/ +O6nxS6QODUapcSZU8lmOEhE6LXttwMPcR0Nm6Ehnr4+RrZ7ev+7YqHOYhbQwx2Po +YrwlSSBRMSeHrZKGcIvbnyPyffTv7VMicT5dH7UnrrabycyvcRnDa3SIf77u3XqM +5HpLrAO0aHCXtJu6aeLtfs6qtjPpRzN8HpciYk8chgbp/5glPjJWHtkxClVeydUB +EQeMkKXBhE5pib4HPh+BvfKiwsmG6IdHVIPBFo3BpCnh6teUEcoWcH8jIo9M8Fty +6Y8raDH3rnTMUC5LnaVPk65EU/jEXDkSX9Yw7UcuT4schgcICrFZfEVdJQmhSePs +18S6EXoJPhWpW5Z0yfpQkl+vVEQ49FeBtTMXf5ukR/52c7FrGfhSubV07XSkx87j +r2CsmVZofS4LuC5HlISKUZXbpLkUT7Gdg3xB4gs6Iq0Fc82P0JTc0z9K/+ButRb9 +X1rv1PvemKTacgzWkWIEzQdiJj7faythoUaN6SBXqgLZaLk5ArywvTLM8WPl6qq4 +gikO030bgGFsLTlYZLOP/GL/CKKIsiRngk1VqY3w7KVWAWEuMkyvk0nhi8XA6b4W +of1KzMJxvqcb8m+EP4nKMOiE7w5wp/BsIDziQk7vSXnUKt8tsNlYLzy8d35lV+d4 +VJZVKYhGBBIRCAAGBQJUHfafAAoJEKyFk2KwQTv6E4UAn1yhDV5IztOAtP2fYydi +8/2cqhmYAJ94FUEgSeuXyjti4NZ5aueyICXjwokBPgQTAQIAKAUCUvmV3QIbAwUJ +BaRJWgYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQetCpHEC9AJGRXgf9HWkm +R3v6Qbz6UJgRb4AWpfdYTSRQ3qre3zoNKHv7lE5zHgiW9upGBDTyD1Att6Nr8sAo +dS+W8LIcNwJaXWlyZ9FqqEbDfnu7jfDU/mPsDMl70TdgzMaYz8vZY1qEnxJIQCNp +WJ/0iFxcuvTrFzb/OLPpT0u9qQNW6JC1wFzgUZBwz/gkfdGZIawtAc0xk5RUcHDO +RyQ8NgcGZS7/d8sx9agjLnj1bUnoHkY/8VROnHqi2aqsDgvGugBFwx6TVngoZFPq +ecKn3lf9FLh/SM8Cn5SidkiBoMtl7Bye/mXYc3/lm00JdcXBeECXglN2OaCVcOIl +vqJeu2JN0V8aEhy5OYkBIgQTAQgADAUCVfsJUQWDB4YfgAAKCRBPdE2h9fFTgUmQ +CADYxnavHKeqKizht75trGycvUoilAfA87i76/ATkrGDuSz0twk6Zs/XVSMl9xTz +pGzrFCSzTpPSdEHegWxC1kBPgegBYSFUGQn4ZxJXUYkeTKnT07SQpeu8nBQbii2o +lQT2RIqkIwk7OyTz4lVMuFqQm4fkp/L5MvJqB613Ejn6S/eaJCF6Tobbot2pUfsS +gZZeceSVamb6TwHOyOZgYCUxycARg6AZnION5edv7X9lvecdKLrfgCwHEPzaBzK2 +ExR2ND2qGvHKUixUCO6Z3V4cfZ7BIhgSPHoiarjHqB32DjL0RQm2uFPgZln1LqBj +d2yje1iPS8l8z4GV9CrcnyhliQEgBBABCAAKBQJV+xBIAwUBeAAKCRB36AaCqD20 +DpjpB/9p6OJ06jnbdRF22aftOBKBPV2wHZw12Qlwoqc85KXpATAz5HuSIG8+XLHi +fxiKF6shPdJyfRyeAiwZGgA1d30WfiRi/w3zC4THek1Kwf84swPva0Kun3rTmt9+ +CNLSKO1Bg067ZzKJS8ejfv1KhzzHlAv14fvQ6EFJ5Uz8R9KQOc9m1kv+lkoSS6yU +jTfDNGSY7LCkq5EOEZ0WzsZgxhh8wZuxkPPZjd9FMQaCYX8z9GvA8sluEsvewbqW +EYJivcYnKItIrBbsN0/N1vUNV977PxXhhCwgGnpsIo2LQ1laTocgoV8WeWFIZT/H +xtVne4JqmcuJVBPszhTb5+a/EwroiQIcBBABAgAGBQJV+wPWAAoJEGviztFKmRe8 +ZHgP/3/YUdrm8WWzv6zPG2pqCgHK2UFiCq6ICBMG4Lr2NalbSSXJCNuHsnD3ocR7 +UssRgQchbMNIXf6ksNIuUzo1kJSghcLNpHF9K5SSitzwSdapV7PibGhdM9gk83DH +hvxEpNPolJ3oPktUkmelvNCH4kBVV4XbHOwMh6Rsr5mtr6G5DXCdnRXiAG3mEE5e +POefp3V1dDlBoGri5xTHHyZlN5Z1/qGtTenODI1IUsK3CZ6jdq8JUEaWiAHOCGqP +9YBix+PVXzJKxAyCgRk3LSwCWRUYUYB7wIm+Teww4nZHqp9WNON3v2KJ16G40toz +7R4txwFlmRuZ/h6weHrSrJ+PghKBMF+KZ3kAAfCD7vHBG1enQ8G1UkbuVtJDfM1Y +ivRkf5M5rvhgfvnUr5cNA1uXMPDUV0TgyORFoNVi91zEd9eSO2gdnVlzlfAVANmQ +9PKqaHRmGEUXKPuOqviG2Wk9sswnGodSnr1n7T4XZdA8cCxIaIGj96/9d2hTYQfW +1jBONK+wWQSOgmd2Hho+DRXuAd3nW6GHGqFJn484+8PHW/Ko4QpP6GfIrAk4zofz +7mc/NEEHLBRMNbhT9Mgcy1e5RTX2wjyxp4banGQITcx+l6lfCDdPdP7bPpZs4s5k +EAgrmwj40Ftv0jgDyqKRcOW+i3zVEOc0cRENd6vyUpzJJgS/uQENBFASGPEBCADO +lZuRdAJPbVFJgbN8j0vUv5wAlt7oXOo/yNDNeeLC/EvSKHstg3cOvssWorE7fEUr +Evcw+1YcNBJtMeCuSyKS2MZW/FX+IrEbGE0o4yOpPWHcszRgE8Lt06jQ9PKFstDw +3uZLI80MTiTWExN7LVPfZAWlbI+Qnqj2/2Yoy7p7S9SuLlbmVJ7F2PKUHVc5Pgma +lTG5mU37BGQKrdvytPHhDfcvoY8W4U/tRuGHMRq7aoCGoHQ5JKkJX1MbXtEYJqR/ +byI7f9nn9A62/Lfnx20TR6aoOg+uYPOwVqn/UH49c+d5//hEJNjcWLu3xGIcl0zC +gtOxGLR/Tge4JzC57ioTABEBAAGJATwEGAEIACYCGwwWIQRpmmPvwXrTqaNM/8B6 +0KkcQL0AkQUCYQMxXQUJGlcZ7AAKCRB60KkcQL0AkR54B/0c1ZmIjdTtpBCohRmj +kQuw7VuYtI27sx4QGzGLssDZU4VS1jVvLpDJQkOBppngXeALUkZSBiXJwrrqrcI4 +ZQJsD7uTw+21d+DrNqYOctgz+IlSEMNLvnc7/1tA+K9JYRyZZ8nbW7/NsZN6Ph3G +Rt8BaJBH6zh9HaTjx4g3Nij1rkwp9gV+rDS0Wk+WoPHicATJHRaf5jqpBRkGvy2C +YFpe2NoMRgDhlt9ckr99m3uVL3lY3HkrIMGDyMkHR8uW+tk9TcGs3gWDkJG4lNoK +ZS7/gZ79/9sOEG5feGJ7xP/jOfLjaeNdOW9zclm8+iz/Sq0lzvi23Dv4UXwue2Rz +urvOuQINBFKaS+cBEAD10Tq0yWHrCzzelYKtZ25DSl3oPtrg/qpGzXQiYLUkL40z +M9W3q7HuVvdHr9vqC/HYHAJnxOoIRY+M90felUTcphGtOPY8XGh0I4H0k52sRY71 +9RhIcied7AxdB8t1LIWjq2+DqS66CBtTz/N1fYR23A/hFas/3Q+fKYmsJD+gwNHm +HnIdszLK08NaVUDQiOvfJXvdPowFseiBaatu/TAukpttcvy6lnyHsdW89CwiB5BX +TbrkOKXyEjT8kAzO3Z2v8pJCa2fzGhFFO9xeGt2r4JIo4qgYSw+CIPXUIg+GlEJ1 +iedykt95Ir8xsaXou27DvUU0h2SKO3o8hIaL4rErmiHmYmpWRakfW9JWP2G7fRCp +TMoAru3/r23gUpdCqeAmfP9WyTOs3wfi3OmsK11jv5RoJCv2rCzK04zVpKBSuiND +3J9fsv4L9lRHeAfohjc81eNerHb/4vYeFLRCwLzjqaKnn0Svcp2CV4WBBpjuu8PL +IzZmNawylbktPEBFfKUUa3RE/R5DpHt9HP1JwM8DDLRNhPx5ZFIQPprs8+bCwSy6 +W9BNjzvHNjZnLIDhSg3emu+ylatGKV3ZmGL7f4G63qFI04zw/iuKmvL6Xy/+Ek9W +j/4vxRY+VKsWvBhQelnp0KiBedZZ9NBFnk5SfEETTvwPtHwlQVki0BjFA0mW+QAR +AQABiQE8BBgBCAAmAhsMFiEEaZpj78F606mjTP/AetCpHEC9AJEFAmEDMV0FCRfO +5vYACgkQetCpHEC9AJGA7Af9EwJrRiCsFxmiDKePcrsj9o0CV29Ksg2zDmUGrPVc +qjAI56YLorHWpoTbt5eemXCdpTYLYXLZb2Zh8cFB4GgsWriKWY9vMCI5L0Ax6oMI +Vo+aaqlFl7Q1++4HsxVp/b+mgpTsj+kRzvtJ3X7hLTtZ9ZTmPJViQHZF2yIZ7dSg +mWjlsRURUHwwUUs49UiLBPyJKBKHOb/KYSmjv0dolV8tsstm0+OmM45UorVkeUEk +eRm0O0CIl8md9T3l3TNTxdx8YNEB7VMWtW2avdSmA79NrKPs3tEufj+bVQSBMfNb +IuASrezmWSioD7YhMvKZtLTD7JuR5zE98kt0qkQG5PSqqrkBDQRUm2SaAQgArgVZ +BhfUgH4ANVz0VzHdvykwBvBprfVjrWATWZZlEN02s6/HvyRj5QKRAqrqzk8R1Xb2 +ekn+Q2Q8o5ZAQ/akrFxTDzXA0RNGUIoF/a2jN3pD6pkgV9kRHo/yJhe1jxuKesn5 +r1BOBkYES1G23gT2FMZUoeZU26m1N6dUr8Vdtp6fsOT5iejTaaD0FbXwgHCZtXyx +yA1TJevhOAFoJXo8B4sbZr/0+LaVibEurghh16jic9D824pfoNd4Fm0kqVRS60jg +86cf/35ktquY3UNV51QAf5xzmvLrUI3BQXgo6FiGZm2jHo3RPIeYtTXNK1gePjsX +g7R0kGjAMKoqEAWnawARAQABiQE8BBgBCAAmAhsMFiEEaZpj78F606mjTP/AetCp +HEC9AJEFAmEDMV0FCRXNzkMACgkQetCpHEC9AJFV9wf/WRHGp8jvxD1RAe2R78Dv +si54R1Zck7jy5gkT5FG9cDaKyAoVvx4noxDEPCK0G7jBM7iCnbpp3ewWVQg40E19 +v+pYy2ESwDvx72giotTieHdbUCD6kT+ZPlVbrG00K3e+unvyLubmskgukVvceo9V +CRSJ+trtLCqWvSrFSctzU8LokyF6e93CK2xirr1fLhTDE0SVDl0sWZrere73//Uw +7fLuUX/e/VbUi2iFw1AWSrvof0ybNmjMfvm+7cMvyWwO12763meOCnaytKTAtgSR +IEKYIHg3KxvaXs2BDkEyK84ZcdHI++WF/xea9uOJzO0iNqJU1fH5AWszOCTxkABU +3rkBDQRUm2YgAQgAnR2NmQHlMWu5SLBn6i1lkYE7kFuVeztPiP59ZxkOrXK25NEF +Fi3t/651P2Ey4BB/CH1e+EqfUuo2wQjH3nD0VRU2c5x4hfy5bUfl1wkG3p4yXxx3 +MkvzVLRGAZk06cPCKY4QNtXXJ391odqHa0VcaBZJZS0euZ7CsAEUhUm5zxpTH/4O +ZTO/GpmHn6brQD7cwLZu+gIOEl5RM5Q00QLU88aOvftU/D/au1ujxBUZbT8UICDx +IKagLqtEBXpXdaGZSRymoRjJpWccGusPI3DSGTWqcp+u1ocqyy+4ntkA5X4COzTl +Hmn+9OoFPui9wtDvlj1NvdSdTg7/tutscY2+4wARAQABiQJbBBgBCAAmAhsCFiEE +aZpj78F606mjTP/AetCpHEC9AJEFAmEDMV0FCRXNzL0BKcBdIAQZAQIABgUCVJtm +IAAKCRDFiNY85BuXwfX9B/9qXO+H5CVJidWIjwfY9+m1zmMNgTnsw4ZkI/ZIrnHs +YiNieOSy2q21omme37oylFRku0ol4Q1TbV0dpmIMl4TRG0XIr/B+fLWLhBC90AT0 +FYJJ9ROYBQA7T6LqZRTjE7cmZd6fXvTJYEuq3YCh+pFtVHJYR6yu6+5LWEZuXdhK +mWkz/qsZ2U2m9VxRUVRoPHsn2wZq2Kh+j3G8tVgwzU50ggS1IMq79IMU05/2AIqX +sToRYKNGou9fDV8fZRiOE32suJE/SlKCitc+h8YKfzzMLFGYzoCF5XBchbzZnyYA +tWppHoZzttzwfCwi78f/Xw1/GLZsSGdVeotYTyacfacKCRB60KkcQL0AkUvVB/4q +N2pKbx/+EQ89hxSy2dxYwUiRa58lvWSdekom23SUEILfo29ijDZ03w+ek1q12typ +kibymHg9RN9M2sammZji3tm11rqYZkSFEAVq2MBXx/rBXJw8srNENNpY1WEN4o4y +jHk25t/PNBu2KgBGTb6Dlz7zepUsToAN2oZU75mg/KV2vKXR9IjNzM/rdApjuYUN +kKx89cCI2mBa3ke844fy5ifD+NICXZvfOj4YlVfLdYFz48VXqeCRTyTRoDIL4E2E +pN7P/uK85nO2p0s2p1nANJYS9j1A97AyFQDpPCJynlC66IZxrKSULbD0+BOvE2yY +dpxrlOWOxI9jmzuQ75LO +=WxeH +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/addresses/CHANGELOG.md b/addresses/CHANGELOG.md new file mode 100644 index 000000000..4ac809f05 --- /dev/null +++ b/addresses/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.0.0 - Initial dummy release + +- Empty crate to reserve the name on crates.io diff --git a/addresses/Cargo.toml b/addresses/Cargo.toml new file mode 100644 index 000000000..bc9066de2 --- /dev/null +++ b/addresses/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "bitcoin-addresses" +version = "0.0.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +description = "Bitcoin address" +categories = ["cryptography::cryptocurrencies"] +keywords = ["bitcoin", "types"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] + +[dependencies] + +[dev-dependencies] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/addresses/README.md b/addresses/README.md new file mode 100644 index 000000000..a7fdf225a --- /dev/null +++ b/addresses/README.md @@ -0,0 +1,3 @@ +# Bitcoin Receive + +Types and logic required to receive bitcoin - i.e., bitcoin addresses. diff --git a/addresses/contrib/extra_lints.sh b/addresses/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/addresses/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/addresses/contrib/test_vars.sh b/addresses/contrib/test_vars.sh new file mode 100644 index 000000000..92dc09406 --- /dev/null +++ b/addresses/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc" + +# Run these examples. +EXAMPLES="" diff --git a/addresses/src/lib.rs b/addresses/src/lib.rs new file mode 100644 index 000000000..74884fd44 --- /dev/null +++ b/addresses/src/lib.rs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Addresses +//! +//! Bitcoin addresses do not appear on chain; rather, they are conventions used by Bitcoin (wallet) +//! software to communicate where coins should be sent and are based on the output type e.g., P2WPKH. +//! +//! This crate can be used in a no-std environment but requires an allocator. +//! +//! ref: + +// NB: This crate is empty if `alloc` is not enabled. +#![cfg(feature = "alloc")] +#![no_std] +// Experimental features we need. +#![doc(test(attr(warn(unused))))] +// Coding conventions. +#![warn(deprecated_in_future)] +#![warn(missing_docs)] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; diff --git a/api/consensus_encoding/all-features.txt b/api/consensus_encoding/all-features.txt new file mode 100644 index 000000000..80251ed47 --- /dev/null +++ b/api/consensus_encoding/all-features.txt @@ -0,0 +1,461 @@ +impl bitcoin_consensus_encoding::ByteVecDecoder +impl bitcoin_consensus_encoding::CompactSizeDecoder +impl bitcoin_consensus_encoding::CompactSizeEncoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::ByteVecDecoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::CompactSizeDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::BytesEncoder<'_> +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::clone::Clone for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::clone::Clone for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::clone::Clone for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::clone::Clone for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::clone::Clone for bitcoin_consensus_encoding::UnexpectedEofError +impl core::cmp::Eq for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::cmp::Eq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::convert::From for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::default::Default for bitcoin_consensus_encoding::ByteVecDecoder +impl core::default::Default for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::error::Error for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::error::Error for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::error::Error for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::error::Error for bitcoin_consensus_encoding::UnexpectedEofError +impl core::fmt::Debug for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::fmt::Debug for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::fmt::Debug for bitcoin_consensus_encoding::UnexpectedEofError +impl core::fmt::Display for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::fmt::Display for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::fmt::Display for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::fmt::Display for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Freeze for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Freeze for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Freeze for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Send for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Send for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Send for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Send for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Sync for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Sync for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Sync for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Unpin for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Unpin for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Unpin for bitcoin_consensus_encoding::UnexpectedEofError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ByteVecDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::UnexpectedEofError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ByteVecDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::UnexpectedEofError +impl<'e, T: bitcoin_consensus_encoding::Encodable> bitcoin_consensus_encoding::SliceEncoder<'e, T> +impl<'e, T> core::marker::Freeze for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Freeze +impl<'e, T> core::marker::Send for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Send, T: core::marker::Sync +impl<'e, T> core::marker::Sync for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Sync, T: core::marker::Sync +impl<'e, T> core::marker::Unpin for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Unpin +impl<'e, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl<'e, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> bitcoin_consensus_encoding::EncodableByteIter<'s, T> +impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> core::iter::traits::iterator::Iterator for bitcoin_consensus_encoding::EncodableByteIter<'s, T> +impl<'s, T> core::marker::Freeze for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Freeze +impl<'s, T> core::marker::Send for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Send +impl<'s, T> core::marker::Sync for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Sync +impl<'s, T> core::marker::Unpin for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Unpin +impl<'s, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::panic::unwind_safe::RefUnwindSafe +impl<'s, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::panic::unwind_safe::UnwindSafe +impl<'sl> bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Freeze for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Send for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Sync for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Unpin for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder6 +impl core::error::Error for bitcoin_consensus_encoding::Decoder6Error where A: core::error::Error + 'static, B: core::error::Error + 'static, C: core::error::Error + 'static, D: core::error::Error + 'static, E: core::error::Error + 'static, F: core::error::Error + 'static +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder6Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display, D: core::fmt::Display, E: core::fmt::Display, F: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, C: core::marker::Freeze, F: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze, F: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Freeze, F: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, C: core::marker::Send, F: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send, D: core::marker::Send, E: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send, E: core::marker::Send, F: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Send, F: core::marker::Send, A: core::marker::Send, B: core::marker::Send, D: core::marker::Send, E: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder6Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, C: core::marker::Sync, F: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync, F: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Sync, F: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, C: core::marker::Unpin, F: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin, F: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Unpin, F: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder6 where ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder6Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder6 where C: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder6 where ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder6Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder6 where C: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder4 +impl core::error::Error for bitcoin_consensus_encoding::Decoder4Error where A: core::error::Error + 'static, B: core::error::Error + 'static, C: core::error::Error + 'static, D: core::error::Error + 'static +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder4Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display, D: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze, ::Output: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send, ::Output: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder4Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync, ::Output: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin, ::Output: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder4 where ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder4Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder4 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder4 where ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder4Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder4 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder3 +impl core::error::Error for bitcoin_consensus_encoding::Decoder3Error where A: core::error::Error + 'static, B: core::error::Error + 'static, C: core::error::Error + 'static +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder3Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Send, A: core::marker::Send, B: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder3Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder3 where C: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder3Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder3 where C: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder3 where C: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder3Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder3 where C: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder2 +impl core::error::Error for bitcoin_consensus_encoding::Decoder2Error where A: core::error::Error + 'static, B: core::error::Error + 'static +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder2Error where A: core::fmt::Display, B: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Freeze, B: core::marker::Freeze, ::Output: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Send, B: core::marker::Send, ::Output: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Send, B: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Send, B: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder2Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Sync, B: core::marker::Sync, ::Output: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Unpin, B: core::marker::Unpin, ::Output: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Unpin, B: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Unpin, B: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder2 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder2Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder2 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder2 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder2Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder2 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder6 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder4 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder3 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder2 +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder6Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder4Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder3Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder2Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder6Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder4Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder3Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder2Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder6Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder4Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder3Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder2Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder6Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder4Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder3Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder2Error +impl core::fmt::Debug for bitcoin_consensus_encoding::ReadError +impl core::fmt::Display for bitcoin_consensus_encoding::ReadError +impl !core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ReadError +impl !core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ReadError +impl core::convert::From for bitcoin_consensus_encoding::ReadError +impl core::error::Error for bitcoin_consensus_encoding::ReadError where D: core::fmt::Debug + core::fmt::Display + core::error::Error + 'static +impl core::marker::Freeze for bitcoin_consensus_encoding::ReadError where D: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::ReadError where D: core::marker::Send +impl core::marker::Sync for bitcoin_consensus_encoding::ReadError where D: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::ReadError where D: core::marker::Unpin +impl core::clone::Clone for bitcoin_consensus_encoding::VecDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::VecDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::VecDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::VecDecoderError +impl core::convert::From for bitcoin_consensus_encoding::VecDecoderError +impl core::error::Error for bitcoin_consensus_encoding::VecDecoderError where Err: core::error::Error + 'static +impl core::fmt::Display for bitcoin_consensus_encoding::VecDecoderError where Err: core::fmt::Display + core::fmt::Debug +impl core::marker::Freeze for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::VecDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::VecDecoderError where Err: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::VecDecoderError where Err: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::VecDecoder +impl bitcoin_consensus_encoding::VecDecoder +impl core::default::Default for bitcoin_consensus_encoding::VecDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::SliceEncoder<'_, T> +impl bitcoin_consensus_encoding::Encoder for core::option::Option +impl core::marker::Freeze for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Send, T: core::marker::Send +impl core::marker::Sync for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Sync, T: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Unpin, T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::ArrayDecoder +impl bitcoin_consensus_encoding::ArrayEncoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::ArrayDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::ArrayEncoder +impl core::default::Default for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Send for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Send for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Sync for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ArrayEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ArrayDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ArrayEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ArrayDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ArrayEncoder +pub bitcoin_consensus_encoding::Decoder2Error::First(A) +pub bitcoin_consensus_encoding::Decoder2Error::Second(B) +pub bitcoin_consensus_encoding::Decoder3Error::First(A) +pub bitcoin_consensus_encoding::Decoder3Error::Second(B) +pub bitcoin_consensus_encoding::Decoder3Error::Third(C) +pub bitcoin_consensus_encoding::Decoder4Error::First(A) +pub bitcoin_consensus_encoding::Decoder4Error::Fourth(D) +pub bitcoin_consensus_encoding::Decoder4Error::Second(B) +pub bitcoin_consensus_encoding::Decoder4Error::Third(C) +pub bitcoin_consensus_encoding::Decoder6Error::Fifth(E) +pub bitcoin_consensus_encoding::Decoder6Error::First(A) +pub bitcoin_consensus_encoding::Decoder6Error::Fourth(D) +pub bitcoin_consensus_encoding::Decoder6Error::Second(B) +pub bitcoin_consensus_encoding::Decoder6Error::Sixth(F) +pub bitcoin_consensus_encoding::Decoder6Error::Third(C) +pub bitcoin_consensus_encoding::ReadError::Decode(D) +pub bitcoin_consensus_encoding::ReadError::Io(std::io::error::Error) +pub const fn bitcoin_consensus_encoding::ArrayDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::ArrayEncoder::without_length_prefix(arr: [u8; N]) -> Self +pub const fn bitcoin_consensus_encoding::ByteVecDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::BytesEncoder<'sl>::without_length_prefix(sl: &'sl [u8]) -> Self +pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::Decoder2::new(first: A, second: B) -> Self +pub const fn bitcoin_consensus_encoding::Decoder3::new(dec_1: A, dec_2: B, dec_3: C) -> Self +pub const fn bitcoin_consensus_encoding::Decoder4::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self +pub const fn bitcoin_consensus_encoding::Decoder6::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D, dec_5: E, dec_6: F) -> Self +pub const fn bitcoin_consensus_encoding::Encoder2::new(enc_1: A, enc_2: B) -> Self +pub const fn bitcoin_consensus_encoding::Encoder3::new(enc_1: A, enc_2: B, enc_3: C) -> Self +pub const fn bitcoin_consensus_encoding::Encoder4::new(enc_1: A, enc_2: B, enc_3: C, enc_4: D) -> Self +pub const fn bitcoin_consensus_encoding::Encoder6::new(enc_1: A, enc_2: B, enc_3: C, enc_4: D, enc_5: E, enc_6: F) -> Self +pub const fn bitcoin_consensus_encoding::VecDecoder::new() -> Self +pub enum bitcoin_consensus_encoding::Decoder2Error +pub enum bitcoin_consensus_encoding::Decoder3Error +pub enum bitcoin_consensus_encoding::Decoder4Error +pub enum bitcoin_consensus_encoding::Decoder6Error +pub enum bitcoin_consensus_encoding::ReadError +pub fn bitcoin_consensus_encoding::ArrayDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::ArrayDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::ArrayDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::ArrayDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::ArrayEncoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::ArrayEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::ByteVecDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::ByteVecDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::ByteVecDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::ByteVecDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::clone(&self) -> bitcoin_consensus_encoding::ByteVecDecoderError +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::eq(&self, other: &bitcoin_consensus_encoding::ByteVecDecoderError) -> bool +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::BytesEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::BytesEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::clone(&self) -> bitcoin_consensus_encoding::CompactSizeDecoder +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::clone(&self) -> bitcoin_consensus_encoding::CompactSizeDecoderError +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::eq(&self, other: &bitcoin_consensus_encoding::CompactSizeDecoderError) -> bool +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: usize) -> Self +pub fn bitcoin_consensus_encoding::Decodable::decoder() -> Self::Decoder +pub fn bitcoin_consensus_encoding::Decoder2::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder2::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder2::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder2Error::clone(&self) -> bitcoin_consensus_encoding::Decoder2Error +pub fn bitcoin_consensus_encoding::Decoder2Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder2Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder2Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder2Error::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::Decoder3::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder3::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder3::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder3Error::clone(&self) -> bitcoin_consensus_encoding::Decoder3Error +pub fn bitcoin_consensus_encoding::Decoder3Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder3Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder3Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder3Error::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::Decoder4::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder4::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder4::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder4Error::clone(&self) -> bitcoin_consensus_encoding::Decoder4Error +pub fn bitcoin_consensus_encoding::Decoder4Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder4Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder4Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder4Error::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::Decoder6::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder6::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder6::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder6Error::clone(&self) -> bitcoin_consensus_encoding::Decoder6Error +pub fn bitcoin_consensus_encoding::Decoder6Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder6Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder6Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder6Error::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::Decoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Encodable::encoder(&self) -> Self::Encoder +pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::new(encodable: &'s T) -> Self +pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::next(&mut self) -> core::option::Option +pub fn bitcoin_consensus_encoding::Encoder2::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder2::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder3::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder3::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder4::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder4::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder6::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder6::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::LengthPrefixExceedsMaxError::clone(&self) -> bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +pub fn bitcoin_consensus_encoding::LengthPrefixExceedsMaxError::eq(&self, other: &bitcoin_consensus_encoding::LengthPrefixExceedsMaxError) -> bool +pub fn bitcoin_consensus_encoding::LengthPrefixExceedsMaxError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::ReadError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::ReadError::from(e: std::io::error::Error) -> Self +pub fn bitcoin_consensus_encoding::ReadError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::SliceEncoder<'_, T>::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::SliceEncoder<'_, T>::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::SliceEncoder<'e, T>::without_length_prefix(sl: &'e [T]) -> Self +pub fn bitcoin_consensus_encoding::UnexpectedEofError::clone(&self) -> bitcoin_consensus_encoding::UnexpectedEofError +pub fn bitcoin_consensus_encoding::UnexpectedEofError::eq(&self, other: &bitcoin_consensus_encoding::UnexpectedEofError) -> bool +pub fn bitcoin_consensus_encoding::UnexpectedEofError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::VecDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::VecDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::VecDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::VecDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::VecDecoderError::clone(&self) -> bitcoin_consensus_encoding::VecDecoderError +pub fn bitcoin_consensus_encoding::VecDecoderError::eq(&self, other: &bitcoin_consensus_encoding::VecDecoderError) -> bool +pub fn bitcoin_consensus_encoding::VecDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::VecDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_consensus_encoding::VecDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_consensus_encoding::cast_to_usize_if_valid(n: u64) -> core::result::Result +pub fn bitcoin_consensus_encoding::decode_from_read(reader: R) -> core::result::Result::Decoder as bitcoin_consensus_encoding::Decoder>::Error>> where T: bitcoin_consensus_encoding::Decodable, R: std::io::BufRead +pub fn bitcoin_consensus_encoding::decode_from_read_unbuffered(reader: R) -> core::result::Result::Decoder as bitcoin_consensus_encoding::Decoder>::Error>> where T: bitcoin_consensus_encoding::Decodable, R: std::io::Read +pub fn bitcoin_consensus_encoding::decode_from_read_unbuffered_with(reader: R) -> core::result::Result::Decoder as bitcoin_consensus_encoding::Decoder>::Error>> where T: bitcoin_consensus_encoding::Decodable, R: std::io::Read +pub fn bitcoin_consensus_encoding::decode_from_slice(bytes: &[u8]) -> core::result::Result::Decoder as bitcoin_consensus_encoding::Decoder>::Error> where T: bitcoin_consensus_encoding::Decodable +pub fn bitcoin_consensus_encoding::encode_to_vec(object: &T) -> alloc::vec::Vec where T: bitcoin_consensus_encoding::Encodable + ?core::marker::Sized +pub fn bitcoin_consensus_encoding::encode_to_writer(object: &T, writer: W) -> core::result::Result<(), std::io::error::Error> where T: bitcoin_consensus_encoding::Encodable + ?core::marker::Sized, W: std::io::Write +pub fn core::option::Option::advance(&mut self) -> bool +pub fn core::option::Option::current_chunk(&self) -> &[u8] +pub macro bitcoin_consensus_encoding::encoder_newtype! +pub mod bitcoin_consensus_encoding +pub struct bitcoin_consensus_encoding::ArrayDecoder +pub struct bitcoin_consensus_encoding::ArrayEncoder +pub struct bitcoin_consensus_encoding::ByteVecDecoder +pub struct bitcoin_consensus_encoding::ByteVecDecoderError(_) +pub struct bitcoin_consensus_encoding::BytesEncoder<'sl> +pub struct bitcoin_consensus_encoding::CompactSizeDecoder +pub struct bitcoin_consensus_encoding::CompactSizeDecoderError(_) +pub struct bitcoin_consensus_encoding::CompactSizeEncoder +pub struct bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::EncodableByteIter<'s, T: bitcoin_consensus_encoding::Encodable + 's> +pub struct bitcoin_consensus_encoding::Encoder2 +pub struct bitcoin_consensus_encoding::Encoder3 +pub struct bitcoin_consensus_encoding::Encoder4 +pub struct bitcoin_consensus_encoding::Encoder6 +pub struct bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +pub struct bitcoin_consensus_encoding::SliceEncoder<'e, T: bitcoin_consensus_encoding::Encodable> +pub struct bitcoin_consensus_encoding::UnexpectedEofError +pub struct bitcoin_consensus_encoding::VecDecoder +pub struct bitcoin_consensus_encoding::VecDecoderError(_) +pub trait bitcoin_consensus_encoding::Decodable +pub trait bitcoin_consensus_encoding::Decoder: core::marker::Sized +pub trait bitcoin_consensus_encoding::Encodable +pub trait bitcoin_consensus_encoding::Encoder +pub type bitcoin_consensus_encoding::ArrayDecoder::Error = bitcoin_consensus_encoding::UnexpectedEofError +pub type bitcoin_consensus_encoding::ArrayDecoder::Output = [u8; N] +pub type bitcoin_consensus_encoding::ByteVecDecoder::Error = bitcoin_consensus_encoding::ByteVecDecoderError +pub type bitcoin_consensus_encoding::ByteVecDecoder::Output = alloc::vec::Vec +pub type bitcoin_consensus_encoding::CompactSizeDecoder::Error = bitcoin_consensus_encoding::CompactSizeDecoderError +pub type bitcoin_consensus_encoding::CompactSizeDecoder::Output = u64 +pub type bitcoin_consensus_encoding::Decodable::Decoder: bitcoin_consensus_encoding::Decoder +pub type bitcoin_consensus_encoding::Decoder2::Error = bitcoin_consensus_encoding::Decoder2Error<::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder2::Output = (::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder3::Error = bitcoin_consensus_encoding::Decoder3Error<::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder3::Output = (::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder4::Error = bitcoin_consensus_encoding::Decoder4Error<::Error, ::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder4::Output = (::Output, ::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder6::Error = bitcoin_consensus_encoding::Decoder6Error<::Error, ::Error, ::Error, ::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder6::Output = (::Output, ::Output, ::Output, ::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder::Error +pub type bitcoin_consensus_encoding::Decoder::Output +pub type bitcoin_consensus_encoding::Encodable::Encoder<'s> where Self: 's: bitcoin_consensus_encoding::Encoder +pub type bitcoin_consensus_encoding::EncodableByteIter<'s, T>::Item = u8 +pub type bitcoin_consensus_encoding::VecDecoder::Error = bitcoin_consensus_encoding::VecDecoderError<<::Decoder as bitcoin_consensus_encoding::Decoder>::Error> +pub type bitcoin_consensus_encoding::VecDecoder::Output = alloc::vec::Vec diff --git a/api/consensus_encoding/alloc-only.txt b/api/consensus_encoding/alloc-only.txt new file mode 100644 index 000000000..faf0c9f12 --- /dev/null +++ b/api/consensus_encoding/alloc-only.txt @@ -0,0 +1,426 @@ +impl bitcoin_consensus_encoding::ByteVecDecoder +impl bitcoin_consensus_encoding::CompactSizeDecoder +impl bitcoin_consensus_encoding::CompactSizeEncoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::ByteVecDecoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::CompactSizeDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::BytesEncoder<'_> +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::clone::Clone for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::clone::Clone for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::clone::Clone for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::clone::Clone for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::clone::Clone for bitcoin_consensus_encoding::UnexpectedEofError +impl core::cmp::Eq for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::cmp::Eq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::convert::From for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::default::Default for bitcoin_consensus_encoding::ByteVecDecoder +impl core::default::Default for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::fmt::Debug for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::fmt::Debug for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::fmt::Debug for bitcoin_consensus_encoding::UnexpectedEofError +impl core::fmt::Display for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::fmt::Display for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::fmt::Display for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::fmt::Display for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Freeze for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Freeze for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Freeze for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Send for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Send for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Send for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Send for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Sync for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Sync for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Sync for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Unpin for bitcoin_consensus_encoding::ByteVecDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Unpin for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::marker::Unpin for bitcoin_consensus_encoding::UnexpectedEofError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ByteVecDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::UnexpectedEofError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ByteVecDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ByteVecDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::UnexpectedEofError +impl<'e, T: bitcoin_consensus_encoding::Encodable> bitcoin_consensus_encoding::SliceEncoder<'e, T> +impl<'e, T> core::marker::Freeze for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Freeze +impl<'e, T> core::marker::Send for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Send, T: core::marker::Sync +impl<'e, T> core::marker::Sync for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Sync, T: core::marker::Sync +impl<'e, T> core::marker::Unpin for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Unpin +impl<'e, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl<'e, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> bitcoin_consensus_encoding::EncodableByteIter<'s, T> +impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> core::iter::traits::iterator::Iterator for bitcoin_consensus_encoding::EncodableByteIter<'s, T> +impl<'s, T> core::marker::Freeze for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Freeze +impl<'s, T> core::marker::Send for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Send +impl<'s, T> core::marker::Sync for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Sync +impl<'s, T> core::marker::Unpin for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Unpin +impl<'s, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::panic::unwind_safe::RefUnwindSafe +impl<'s, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::panic::unwind_safe::UnwindSafe +impl<'sl> bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Freeze for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Send for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Sync for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Unpin for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder6 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder6Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display, D: core::fmt::Display, E: core::fmt::Display, F: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, C: core::marker::Freeze, F: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze, F: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Freeze, F: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, C: core::marker::Send, F: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send, D: core::marker::Send, E: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send, E: core::marker::Send, F: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Send, F: core::marker::Send, A: core::marker::Send, B: core::marker::Send, D: core::marker::Send, E: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder6Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, C: core::marker::Sync, F: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync, F: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Sync, F: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, C: core::marker::Unpin, F: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin, F: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Unpin, F: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder6 where ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder6Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder6 where C: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder6 where ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder6Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder6 where C: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder4 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder4Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display, D: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze, ::Output: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send, ::Output: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder4Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync, ::Output: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin, ::Output: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder4 where ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder4Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder4 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder4 where ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder4Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder4 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder3 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder3Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Send, A: core::marker::Send, B: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder3Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder3 where C: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder3Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder3 where C: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder3 where C: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder3Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder3 where C: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder2 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder2Error where A: core::fmt::Display, B: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Freeze, B: core::marker::Freeze, ::Output: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Send, B: core::marker::Send, ::Output: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Send, B: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Send, B: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder2Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Sync, B: core::marker::Sync, ::Output: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Unpin, B: core::marker::Unpin, ::Output: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Unpin, B: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Unpin, B: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder2 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder2Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder2 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder2 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder2Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder2 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder6 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder4 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder3 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder2 +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder6Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder4Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder3Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder2Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder6Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder4Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder3Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder2Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder6Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder4Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder3Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder2Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder6Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder4Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder3Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder2Error +impl core::clone::Clone for bitcoin_consensus_encoding::VecDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::VecDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::VecDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::VecDecoderError +impl core::convert::From for bitcoin_consensus_encoding::VecDecoderError +impl core::fmt::Display for bitcoin_consensus_encoding::VecDecoderError where Err: core::fmt::Display + core::fmt::Debug +impl core::marker::Freeze for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::VecDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::VecDecoderError where Err: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::VecDecoderError where Err: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::VecDecoderError where Err: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::VecDecoder +impl bitcoin_consensus_encoding::VecDecoder +impl core::default::Default for bitcoin_consensus_encoding::VecDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::SliceEncoder<'_, T> +impl bitcoin_consensus_encoding::Encoder for core::option::Option +impl core::marker::Freeze for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Send, T: core::marker::Send +impl core::marker::Sync for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Sync, T: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::marker::Unpin, T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::VecDecoder where ::Decoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::ArrayDecoder +impl bitcoin_consensus_encoding::ArrayEncoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::ArrayDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::ArrayEncoder +impl core::default::Default for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Send for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Send for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Sync for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ArrayEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ArrayDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ArrayEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ArrayDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ArrayEncoder +pub bitcoin_consensus_encoding::Decoder2Error::First(A) +pub bitcoin_consensus_encoding::Decoder2Error::Second(B) +pub bitcoin_consensus_encoding::Decoder3Error::First(A) +pub bitcoin_consensus_encoding::Decoder3Error::Second(B) +pub bitcoin_consensus_encoding::Decoder3Error::Third(C) +pub bitcoin_consensus_encoding::Decoder4Error::First(A) +pub bitcoin_consensus_encoding::Decoder4Error::Fourth(D) +pub bitcoin_consensus_encoding::Decoder4Error::Second(B) +pub bitcoin_consensus_encoding::Decoder4Error::Third(C) +pub bitcoin_consensus_encoding::Decoder6Error::Fifth(E) +pub bitcoin_consensus_encoding::Decoder6Error::First(A) +pub bitcoin_consensus_encoding::Decoder6Error::Fourth(D) +pub bitcoin_consensus_encoding::Decoder6Error::Second(B) +pub bitcoin_consensus_encoding::Decoder6Error::Sixth(F) +pub bitcoin_consensus_encoding::Decoder6Error::Third(C) +pub const fn bitcoin_consensus_encoding::ArrayDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::ArrayEncoder::without_length_prefix(arr: [u8; N]) -> Self +pub const fn bitcoin_consensus_encoding::ByteVecDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::BytesEncoder<'sl>::without_length_prefix(sl: &'sl [u8]) -> Self +pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::Decoder2::new(first: A, second: B) -> Self +pub const fn bitcoin_consensus_encoding::Decoder3::new(dec_1: A, dec_2: B, dec_3: C) -> Self +pub const fn bitcoin_consensus_encoding::Decoder4::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self +pub const fn bitcoin_consensus_encoding::Decoder6::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D, dec_5: E, dec_6: F) -> Self +pub const fn bitcoin_consensus_encoding::Encoder2::new(enc_1: A, enc_2: B) -> Self +pub const fn bitcoin_consensus_encoding::Encoder3::new(enc_1: A, enc_2: B, enc_3: C) -> Self +pub const fn bitcoin_consensus_encoding::Encoder4::new(enc_1: A, enc_2: B, enc_3: C, enc_4: D) -> Self +pub const fn bitcoin_consensus_encoding::Encoder6::new(enc_1: A, enc_2: B, enc_3: C, enc_4: D, enc_5: E, enc_6: F) -> Self +pub const fn bitcoin_consensus_encoding::VecDecoder::new() -> Self +pub enum bitcoin_consensus_encoding::Decoder2Error +pub enum bitcoin_consensus_encoding::Decoder3Error +pub enum bitcoin_consensus_encoding::Decoder4Error +pub enum bitcoin_consensus_encoding::Decoder6Error +pub fn bitcoin_consensus_encoding::ArrayDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::ArrayDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::ArrayDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::ArrayDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::ArrayEncoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::ArrayEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::ByteVecDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::ByteVecDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::ByteVecDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::ByteVecDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::clone(&self) -> bitcoin_consensus_encoding::ByteVecDecoderError +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::eq(&self, other: &bitcoin_consensus_encoding::ByteVecDecoderError) -> bool +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::ByteVecDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_consensus_encoding::BytesEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::BytesEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::clone(&self) -> bitcoin_consensus_encoding::CompactSizeDecoder +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::clone(&self) -> bitcoin_consensus_encoding::CompactSizeDecoderError +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::eq(&self, other: &bitcoin_consensus_encoding::CompactSizeDecoderError) -> bool +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: usize) -> Self +pub fn bitcoin_consensus_encoding::Decodable::decoder() -> Self::Decoder +pub fn bitcoin_consensus_encoding::Decoder2::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder2::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder2::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder2Error::clone(&self) -> bitcoin_consensus_encoding::Decoder2Error +pub fn bitcoin_consensus_encoding::Decoder2Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder2Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder2Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder3::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder3::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder3::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder3Error::clone(&self) -> bitcoin_consensus_encoding::Decoder3Error +pub fn bitcoin_consensus_encoding::Decoder3Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder3Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder3Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder4::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder4::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder4::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder4Error::clone(&self) -> bitcoin_consensus_encoding::Decoder4Error +pub fn bitcoin_consensus_encoding::Decoder4Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder4Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder4Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder6::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder6::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder6::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder6Error::clone(&self) -> bitcoin_consensus_encoding::Decoder6Error +pub fn bitcoin_consensus_encoding::Decoder6Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder6Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder6Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Encodable::encoder(&self) -> Self::Encoder +pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::new(encodable: &'s T) -> Self +pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::next(&mut self) -> core::option::Option +pub fn bitcoin_consensus_encoding::Encoder2::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder2::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder3::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder3::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder4::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder4::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder6::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder6::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::LengthPrefixExceedsMaxError::clone(&self) -> bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +pub fn bitcoin_consensus_encoding::LengthPrefixExceedsMaxError::eq(&self, other: &bitcoin_consensus_encoding::LengthPrefixExceedsMaxError) -> bool +pub fn bitcoin_consensus_encoding::LengthPrefixExceedsMaxError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::SliceEncoder<'_, T>::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::SliceEncoder<'_, T>::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::SliceEncoder<'e, T>::without_length_prefix(sl: &'e [T]) -> Self +pub fn bitcoin_consensus_encoding::UnexpectedEofError::clone(&self) -> bitcoin_consensus_encoding::UnexpectedEofError +pub fn bitcoin_consensus_encoding::UnexpectedEofError::eq(&self, other: &bitcoin_consensus_encoding::UnexpectedEofError) -> bool +pub fn bitcoin_consensus_encoding::UnexpectedEofError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::VecDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::VecDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::VecDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::VecDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::VecDecoderError::clone(&self) -> bitcoin_consensus_encoding::VecDecoderError +pub fn bitcoin_consensus_encoding::VecDecoderError::eq(&self, other: &bitcoin_consensus_encoding::VecDecoderError) -> bool +pub fn bitcoin_consensus_encoding::VecDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::VecDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_consensus_encoding::cast_to_usize_if_valid(n: u64) -> core::result::Result +pub fn bitcoin_consensus_encoding::decode_from_slice(bytes: &[u8]) -> core::result::Result::Decoder as bitcoin_consensus_encoding::Decoder>::Error> where T: bitcoin_consensus_encoding::Decodable +pub fn bitcoin_consensus_encoding::encode_to_vec(object: &T) -> alloc::vec::Vec where T: bitcoin_consensus_encoding::Encodable + ?core::marker::Sized +pub fn core::option::Option::advance(&mut self) -> bool +pub fn core::option::Option::current_chunk(&self) -> &[u8] +pub macro bitcoin_consensus_encoding::encoder_newtype! +pub mod bitcoin_consensus_encoding +pub struct bitcoin_consensus_encoding::ArrayDecoder +pub struct bitcoin_consensus_encoding::ArrayEncoder +pub struct bitcoin_consensus_encoding::ByteVecDecoder +pub struct bitcoin_consensus_encoding::ByteVecDecoderError(_) +pub struct bitcoin_consensus_encoding::BytesEncoder<'sl> +pub struct bitcoin_consensus_encoding::CompactSizeDecoder +pub struct bitcoin_consensus_encoding::CompactSizeDecoderError(_) +pub struct bitcoin_consensus_encoding::CompactSizeEncoder +pub struct bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::EncodableByteIter<'s, T: bitcoin_consensus_encoding::Encodable + 's> +pub struct bitcoin_consensus_encoding::Encoder2 +pub struct bitcoin_consensus_encoding::Encoder3 +pub struct bitcoin_consensus_encoding::Encoder4 +pub struct bitcoin_consensus_encoding::Encoder6 +pub struct bitcoin_consensus_encoding::LengthPrefixExceedsMaxError +pub struct bitcoin_consensus_encoding::SliceEncoder<'e, T: bitcoin_consensus_encoding::Encodable> +pub struct bitcoin_consensus_encoding::UnexpectedEofError +pub struct bitcoin_consensus_encoding::VecDecoder +pub struct bitcoin_consensus_encoding::VecDecoderError(_) +pub trait bitcoin_consensus_encoding::Decodable +pub trait bitcoin_consensus_encoding::Decoder: core::marker::Sized +pub trait bitcoin_consensus_encoding::Encodable +pub trait bitcoin_consensus_encoding::Encoder +pub type bitcoin_consensus_encoding::ArrayDecoder::Error = bitcoin_consensus_encoding::UnexpectedEofError +pub type bitcoin_consensus_encoding::ArrayDecoder::Output = [u8; N] +pub type bitcoin_consensus_encoding::ByteVecDecoder::Error = bitcoin_consensus_encoding::ByteVecDecoderError +pub type bitcoin_consensus_encoding::ByteVecDecoder::Output = alloc::vec::Vec +pub type bitcoin_consensus_encoding::CompactSizeDecoder::Error = bitcoin_consensus_encoding::CompactSizeDecoderError +pub type bitcoin_consensus_encoding::CompactSizeDecoder::Output = u64 +pub type bitcoin_consensus_encoding::Decodable::Decoder: bitcoin_consensus_encoding::Decoder +pub type bitcoin_consensus_encoding::Decoder2::Error = bitcoin_consensus_encoding::Decoder2Error<::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder2::Output = (::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder3::Error = bitcoin_consensus_encoding::Decoder3Error<::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder3::Output = (::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder4::Error = bitcoin_consensus_encoding::Decoder4Error<::Error, ::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder4::Output = (::Output, ::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder6::Error = bitcoin_consensus_encoding::Decoder6Error<::Error, ::Error, ::Error, ::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder6::Output = (::Output, ::Output, ::Output, ::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder::Error +pub type bitcoin_consensus_encoding::Decoder::Output +pub type bitcoin_consensus_encoding::Encodable::Encoder<'s> where Self: 's: bitcoin_consensus_encoding::Encoder +pub type bitcoin_consensus_encoding::EncodableByteIter<'s, T>::Item = u8 +pub type bitcoin_consensus_encoding::VecDecoder::Error = bitcoin_consensus_encoding::VecDecoderError<<::Decoder as bitcoin_consensus_encoding::Decoder>::Error> +pub type bitcoin_consensus_encoding::VecDecoder::Output = alloc::vec::Vec diff --git a/api/consensus_encoding/no-features.txt b/api/consensus_encoding/no-features.txt new file mode 100644 index 000000000..6e089c51f --- /dev/null +++ b/api/consensus_encoding/no-features.txt @@ -0,0 +1,338 @@ +impl bitcoin_consensus_encoding::CompactSizeDecoder +impl bitcoin_consensus_encoding::CompactSizeEncoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::CompactSizeDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::BytesEncoder<'_> +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::clone::Clone for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::clone::Clone for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::clone::Clone for bitcoin_consensus_encoding::UnexpectedEofError +impl core::cmp::Eq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::cmp::Eq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::cmp::PartialEq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::default::Default for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::fmt::Debug for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::fmt::Debug for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::fmt::Debug for bitcoin_consensus_encoding::UnexpectedEofError +impl core::fmt::Display for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::fmt::Display for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Freeze for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Freeze for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Send for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Send for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Sync for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Sync for bitcoin_consensus_encoding::UnexpectedEofError +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::marker::Unpin for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::marker::Unpin for bitcoin_consensus_encoding::UnexpectedEofError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::UnexpectedEofError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::CompactSizeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::UnexpectedEofError +impl<'e, T: bitcoin_consensus_encoding::Encodable> bitcoin_consensus_encoding::SliceEncoder<'e, T> +impl<'e, T> core::marker::Freeze for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Freeze +impl<'e, T> core::marker::Send for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Send, T: core::marker::Sync +impl<'e, T> core::marker::Sync for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Sync, T: core::marker::Sync +impl<'e, T> core::marker::Unpin for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::marker::Unpin +impl<'e, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::panic::unwind_safe::RefUnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl<'e, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::SliceEncoder<'e, T> where ::Encoder: core::panic::unwind_safe::UnwindSafe, T: core::panic::unwind_safe::RefUnwindSafe +impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> bitcoin_consensus_encoding::EncodableByteIter<'s, T> +impl<'s, T: bitcoin_consensus_encoding::Encodable + 's> core::iter::traits::iterator::Iterator for bitcoin_consensus_encoding::EncodableByteIter<'s, T> +impl<'s, T> core::marker::Freeze for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Freeze +impl<'s, T> core::marker::Send for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Send +impl<'s, T> core::marker::Sync for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Sync +impl<'s, T> core::marker::Unpin for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::marker::Unpin +impl<'s, T> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::panic::unwind_safe::RefUnwindSafe +impl<'s, T> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::EncodableByteIter<'s, T> where ::Encoder: core::panic::unwind_safe::UnwindSafe +impl<'sl> bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Freeze for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Send for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Sync for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::marker::Unpin for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl<'sl> core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::BytesEncoder<'sl> +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder6 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder6Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display, D: core::fmt::Display, E: core::fmt::Display, F: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, C: core::marker::Freeze, F: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze, F: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Freeze, F: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, D: core::marker::Freeze, E: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, C: core::marker::Send, F: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send, D: core::marker::Send, E: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send, E: core::marker::Send, F: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Send, F: core::marker::Send, A: core::marker::Send, B: core::marker::Send, D: core::marker::Send, E: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder6Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, C: core::marker::Sync, F: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync, F: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Sync, F: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, D: core::marker::Sync, E: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder6 where ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, C: core::marker::Unpin, F: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder6Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin, F: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder6 where C: core::marker::Unpin, F: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, D: core::marker::Unpin, E: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder6 where ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder6Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder6 where C: core::panic::unwind_safe::RefUnwindSafe, F: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, E: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder6 where ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder6Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder6 where C: core::panic::unwind_safe::UnwindSafe, F: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, E: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder4 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder4Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display, D: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze, ::Output: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze, D: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send, ::Output: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send, D: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder4Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync, ::Output: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync, D: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder4 where ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin, ::Output: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder4Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder4 where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin, D: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder4 where ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder4Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder4 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe, D: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder4 where ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder4Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder4 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe, D: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder3 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder3Error where A: core::fmt::Display, B: core::fmt::Display, C: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Freeze, ::Output: core::marker::Freeze, ::Output: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Freeze, B: core::marker::Freeze, C: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Freeze, A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Send, ::Output: core::marker::Send, ::Output: core::marker::Send, A: core::marker::Send, B: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Send, B: core::marker::Send, C: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Send, A: core::marker::Send, B: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder3Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Sync, ::Output: core::marker::Sync, ::Output: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Sync, B: core::marker::Sync, C: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Sync, A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder3 where C: core::marker::Unpin, ::Output: core::marker::Unpin, ::Output: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder3Error where A: core::marker::Unpin, B: core::marker::Unpin, C: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder3 where C: core::marker::Unpin, A: core::marker::Unpin, B: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder3 where C: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder3Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, C: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder3 where C: core::panic::unwind_safe::RefUnwindSafe, A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder3 where C: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder3Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, C: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder3 where C: core::panic::unwind_safe::UnwindSafe, A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +impl bitcoin_consensus_encoding::Encoder2 +impl core::fmt::Display for bitcoin_consensus_encoding::Decoder2Error where A: core::fmt::Display, B: core::fmt::Display +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Freeze, B: core::marker::Freeze, ::Output: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Freeze for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Freeze, B: core::marker::Freeze +impl core::marker::Send for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Send, B: core::marker::Send, ::Output: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Send, B: core::marker::Send +impl core::marker::Send for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Send, B: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_consensus_encoding::Decoder2Error +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Sync, B: core::marker::Sync, ::Output: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Sync for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Sync, B: core::marker::Sync +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder2 where A: core::marker::Unpin, B: core::marker::Unpin, ::Output: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Decoder2Error where A: core::marker::Unpin, B: core::marker::Unpin +impl core::marker::Unpin for bitcoin_consensus_encoding::Encoder2 where A: core::marker::Unpin, B: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder2 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe, ::Output: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Decoder2Error where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::Encoder2 where A: core::panic::unwind_safe::RefUnwindSafe, B: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder2 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe, ::Output: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Decoder2Error where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::Encoder2 where A: core::panic::unwind_safe::UnwindSafe, B: core::panic::unwind_safe::UnwindSafe +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder6 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder4 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder3 +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::Encoder2 +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder6Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder4Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder3Error +impl core::clone::Clone for bitcoin_consensus_encoding::Decoder2Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder6Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder4Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder3Error +impl core::cmp::Eq for bitcoin_consensus_encoding::Decoder2Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder6Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder4Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder3Error +impl core::cmp::PartialEq for bitcoin_consensus_encoding::Decoder2Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder6Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder4Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder3Error +impl core::fmt::Debug for bitcoin_consensus_encoding::Decoder2Error +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::SliceEncoder<'_, T> +impl bitcoin_consensus_encoding::Encoder for core::option::Option +impl bitcoin_consensus_encoding::ArrayDecoder +impl bitcoin_consensus_encoding::ArrayEncoder +impl bitcoin_consensus_encoding::Decoder for bitcoin_consensus_encoding::ArrayDecoder +impl bitcoin_consensus_encoding::Encoder for bitcoin_consensus_encoding::ArrayEncoder +impl core::default::Default for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Freeze for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Send for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Send for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Sync for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Sync for bitcoin_consensus_encoding::ArrayEncoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ArrayDecoder +impl core::marker::Unpin for bitcoin_consensus_encoding::ArrayEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ArrayDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_consensus_encoding::ArrayEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ArrayDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_consensus_encoding::ArrayEncoder +pub bitcoin_consensus_encoding::Decoder2Error::First(A) +pub bitcoin_consensus_encoding::Decoder2Error::Second(B) +pub bitcoin_consensus_encoding::Decoder3Error::First(A) +pub bitcoin_consensus_encoding::Decoder3Error::Second(B) +pub bitcoin_consensus_encoding::Decoder3Error::Third(C) +pub bitcoin_consensus_encoding::Decoder4Error::First(A) +pub bitcoin_consensus_encoding::Decoder4Error::Fourth(D) +pub bitcoin_consensus_encoding::Decoder4Error::Second(B) +pub bitcoin_consensus_encoding::Decoder4Error::Third(C) +pub bitcoin_consensus_encoding::Decoder6Error::Fifth(E) +pub bitcoin_consensus_encoding::Decoder6Error::First(A) +pub bitcoin_consensus_encoding::Decoder6Error::Fourth(D) +pub bitcoin_consensus_encoding::Decoder6Error::Second(B) +pub bitcoin_consensus_encoding::Decoder6Error::Sixth(F) +pub bitcoin_consensus_encoding::Decoder6Error::Third(C) +pub const fn bitcoin_consensus_encoding::ArrayDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::ArrayEncoder::without_length_prefix(arr: [u8; N]) -> Self +pub const fn bitcoin_consensus_encoding::BytesEncoder<'sl>::without_length_prefix(sl: &'sl [u8]) -> Self +pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new() -> Self +pub const fn bitcoin_consensus_encoding::Decoder2::new(first: A, second: B) -> Self +pub const fn bitcoin_consensus_encoding::Decoder3::new(dec_1: A, dec_2: B, dec_3: C) -> Self +pub const fn bitcoin_consensus_encoding::Decoder4::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self +pub const fn bitcoin_consensus_encoding::Decoder6::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D, dec_5: E, dec_6: F) -> Self +pub const fn bitcoin_consensus_encoding::Encoder2::new(enc_1: A, enc_2: B) -> Self +pub const fn bitcoin_consensus_encoding::Encoder3::new(enc_1: A, enc_2: B, enc_3: C) -> Self +pub const fn bitcoin_consensus_encoding::Encoder4::new(enc_1: A, enc_2: B, enc_3: C, enc_4: D) -> Self +pub const fn bitcoin_consensus_encoding::Encoder6::new(enc_1: A, enc_2: B, enc_3: C, enc_4: D, enc_5: E, enc_6: F) -> Self +pub enum bitcoin_consensus_encoding::Decoder2Error +pub enum bitcoin_consensus_encoding::Decoder3Error +pub enum bitcoin_consensus_encoding::Decoder4Error +pub enum bitcoin_consensus_encoding::Decoder6Error +pub fn bitcoin_consensus_encoding::ArrayDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::ArrayDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::ArrayDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::ArrayDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::ArrayEncoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::ArrayEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::BytesEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::BytesEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::clone(&self) -> bitcoin_consensus_encoding::CompactSizeDecoder +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::default() -> Self +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::CompactSizeDecoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::clone(&self) -> bitcoin_consensus_encoding::CompactSizeDecoderError +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::eq(&self, other: &bitcoin_consensus_encoding::CompactSizeDecoderError) -> bool +pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: usize) -> Self +pub fn bitcoin_consensus_encoding::Decodable::decoder() -> Self::Decoder +pub fn bitcoin_consensus_encoding::Decoder2::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder2::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder2::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder2Error::clone(&self) -> bitcoin_consensus_encoding::Decoder2Error +pub fn bitcoin_consensus_encoding::Decoder2Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder2Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder2Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder3::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder3::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder3::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder3Error::clone(&self) -> bitcoin_consensus_encoding::Decoder3Error +pub fn bitcoin_consensus_encoding::Decoder3Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder3Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder3Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder4::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder4::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder4::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder4Error::clone(&self) -> bitcoin_consensus_encoding::Decoder4Error +pub fn bitcoin_consensus_encoding::Decoder4Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder4Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder4Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder6::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder6::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder6::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Decoder6Error::clone(&self) -> bitcoin_consensus_encoding::Decoder6Error +pub fn bitcoin_consensus_encoding::Decoder6Error::eq(&self, other: &bitcoin_consensus_encoding::Decoder6Error) -> bool +pub fn bitcoin_consensus_encoding::Decoder6Error::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::Decoder::end(self) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_consensus_encoding::Decoder::read_limit(&self) -> usize +pub fn bitcoin_consensus_encoding::Encodable::encoder(&self) -> Self::Encoder +pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::new(encodable: &'s T) -> Self +pub fn bitcoin_consensus_encoding::EncodableByteIter<'s, T>::next(&mut self) -> core::option::Option +pub fn bitcoin_consensus_encoding::Encoder2::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder2::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder3::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder3::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder4::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder4::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder6::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder6::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::Encoder::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::Encoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::SliceEncoder<'_, T>::advance(&mut self) -> bool +pub fn bitcoin_consensus_encoding::SliceEncoder<'_, T>::current_chunk(&self) -> &[u8] +pub fn bitcoin_consensus_encoding::SliceEncoder<'e, T>::without_length_prefix(sl: &'e [T]) -> Self +pub fn bitcoin_consensus_encoding::UnexpectedEofError::clone(&self) -> bitcoin_consensus_encoding::UnexpectedEofError +pub fn bitcoin_consensus_encoding::UnexpectedEofError::eq(&self, other: &bitcoin_consensus_encoding::UnexpectedEofError) -> bool +pub fn bitcoin_consensus_encoding::UnexpectedEofError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_consensus_encoding::decode_from_slice(bytes: &[u8]) -> core::result::Result::Decoder as bitcoin_consensus_encoding::Decoder>::Error> where T: bitcoin_consensus_encoding::Decodable +pub fn core::option::Option::advance(&mut self) -> bool +pub fn core::option::Option::current_chunk(&self) -> &[u8] +pub macro bitcoin_consensus_encoding::encoder_newtype! +pub mod bitcoin_consensus_encoding +pub struct bitcoin_consensus_encoding::ArrayDecoder +pub struct bitcoin_consensus_encoding::ArrayEncoder +pub struct bitcoin_consensus_encoding::BytesEncoder<'sl> +pub struct bitcoin_consensus_encoding::CompactSizeDecoder +pub struct bitcoin_consensus_encoding::CompactSizeDecoderError(_) +pub struct bitcoin_consensus_encoding::CompactSizeEncoder +pub struct bitcoin_consensus_encoding::Decoder2 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder3 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder4 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::Decoder6 where A: bitcoin_consensus_encoding::Decoder, B: bitcoin_consensus_encoding::Decoder, C: bitcoin_consensus_encoding::Decoder, D: bitcoin_consensus_encoding::Decoder, E: bitcoin_consensus_encoding::Decoder, F: bitcoin_consensus_encoding::Decoder +pub struct bitcoin_consensus_encoding::EncodableByteIter<'s, T: bitcoin_consensus_encoding::Encodable + 's> +pub struct bitcoin_consensus_encoding::Encoder2 +pub struct bitcoin_consensus_encoding::Encoder3 +pub struct bitcoin_consensus_encoding::Encoder4 +pub struct bitcoin_consensus_encoding::Encoder6 +pub struct bitcoin_consensus_encoding::SliceEncoder<'e, T: bitcoin_consensus_encoding::Encodable> +pub struct bitcoin_consensus_encoding::UnexpectedEofError +pub trait bitcoin_consensus_encoding::Decodable +pub trait bitcoin_consensus_encoding::Decoder: core::marker::Sized +pub trait bitcoin_consensus_encoding::Encodable +pub trait bitcoin_consensus_encoding::Encoder +pub type bitcoin_consensus_encoding::ArrayDecoder::Error = bitcoin_consensus_encoding::UnexpectedEofError +pub type bitcoin_consensus_encoding::ArrayDecoder::Output = [u8; N] +pub type bitcoin_consensus_encoding::CompactSizeDecoder::Error = bitcoin_consensus_encoding::CompactSizeDecoderError +pub type bitcoin_consensus_encoding::CompactSizeDecoder::Output = u64 +pub type bitcoin_consensus_encoding::Decodable::Decoder: bitcoin_consensus_encoding::Decoder +pub type bitcoin_consensus_encoding::Decoder2::Error = bitcoin_consensus_encoding::Decoder2Error<::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder2::Output = (::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder3::Error = bitcoin_consensus_encoding::Decoder3Error<::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder3::Output = (::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder4::Error = bitcoin_consensus_encoding::Decoder4Error<::Error, ::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder4::Output = (::Output, ::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder6::Error = bitcoin_consensus_encoding::Decoder6Error<::Error, ::Error, ::Error, ::Error, ::Error, ::Error> +pub type bitcoin_consensus_encoding::Decoder6::Output = (::Output, ::Output, ::Output, ::Output, ::Output, ::Output) +pub type bitcoin_consensus_encoding::Decoder::Error +pub type bitcoin_consensus_encoding::Decoder::Output +pub type bitcoin_consensus_encoding::Encodable::Encoder<'s> where Self: 's: bitcoin_consensus_encoding::Encoder +pub type bitcoin_consensus_encoding::EncodableByteIter<'s, T>::Item = u8 diff --git a/api/primitives/all-features.txt b/api/primitives/all-features.txt new file mode 100644 index 000000000..bd3927650 --- /dev/null +++ b/api/primitives/all-features.txt @@ -0,0 +1,2116 @@ +#[non_exhaustive] pub enum bitcoin_primitives::block::HeaderDecoderError +#[non_exhaustive] pub enum bitcoin_primitives::block::InvalidBlockError +#[non_exhaustive] pub enum bitcoin_primitives::transaction::ParseOutPointError +#[repr(transparent)] pub struct bitcoin_primitives::script::Script(_, _) +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::BlockHash +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::TxMerkleNode +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::WitnessMerkleNode +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Block +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Header +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Version +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::pow::CompactTarget +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::OutPoint +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::Transaction +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::TxIn +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::TxOut +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::Version +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::witness::Witness +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::BlockDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::BlockHashDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::HeaderDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::VersionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::pow::CompactTargetDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::OutPointDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TransactionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxInDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxOutDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::VersionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::witness::WitnessDecoder +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::BlockHash +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::TxMerkleNode +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::WitnessMerkleNode +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Block +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Header +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Version +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::pow::CompactTarget +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::OutPoint +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::Transaction +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::TxIn +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::TxOut +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::Version +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::witness::Witness +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::BlockHashEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::HeaderEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::VersionEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::pow::CompactTargetEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::VersionEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_> +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::witness::WitnessEncoder<'_> +impl bitcoin_primitives::BlockHash +impl bitcoin_primitives::Ntxid +impl bitcoin_primitives::TxMerkleNode +impl bitcoin_primitives::Txid +impl bitcoin_primitives::WitnessCommitment +impl bitcoin_primitives::WitnessMerkleNode +impl bitcoin_primitives::Wtxid +impl bitcoin_primitives::block::Block +impl bitcoin_primitives::block::Block +impl bitcoin_primitives::block::BlockHashDecoder +impl bitcoin_primitives::block::Header +impl bitcoin_primitives::block::Validation for bitcoin_primitives::block::Checked +impl bitcoin_primitives::block::Validation for bitcoin_primitives::block::Unchecked +impl bitcoin_primitives::block::Version +impl bitcoin_primitives::block::VersionDecoder +impl bitcoin_primitives::pow::CompactTarget +impl bitcoin_primitives::pow::CompactTargetDecoder +impl bitcoin_primitives::script::RedeemScriptSizeError +impl bitcoin_primitives::script::ScriptHash +impl bitcoin_primitives::script::ScriptHashableTag for bitcoin_primitives::script::RedeemScriptTag +impl bitcoin_primitives::script::ScriptHashableTag for bitcoin_primitives::script::ScriptPubKeyTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::RedeemScriptTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::ScriptPubKeyTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::ScriptSigTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::TapScriptTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::WitnessScriptTag +impl bitcoin_primitives::script::WScriptHash +impl bitcoin_primitives::script::WitnessScriptSizeError +impl bitcoin_primitives::transaction::OutPoint +impl bitcoin_primitives::transaction::OutPointDecoder +impl bitcoin_primitives::transaction::Transaction +impl bitcoin_primitives::transaction::TransactionDecoder +impl bitcoin_primitives::transaction::TxIn +impl bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl bitcoin_primitives::transaction::Version +impl bitcoin_primitives::transaction::VersionDecoder +impl bitcoin_primitives::witness::Witness +impl bitcoin_primitives::witness::WitnessDecoder +impl core::borrow::Borrow<[u8; 20]> for bitcoin_primitives::script::ScriptHash +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::BlockHash +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Ntxid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::TxMerkleNode +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Txid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::WitnessCommitment +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::WitnessMerkleNode +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Wtxid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::script::WScriptHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::BlockHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Ntxid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::TxMerkleNode +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Txid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::WitnessCommitment +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::WitnessMerkleNode +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Wtxid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::script::ScriptHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::script::WScriptHash +impl core::clone::Clone for bitcoin_primitives::BlockHash +impl core::clone::Clone for bitcoin_primitives::Ntxid +impl core::clone::Clone for bitcoin_primitives::TxMerkleNode +impl core::clone::Clone for bitcoin_primitives::Txid +impl core::clone::Clone for bitcoin_primitives::WitnessCommitment +impl core::clone::Clone for bitcoin_primitives::WitnessMerkleNode +impl core::clone::Clone for bitcoin_primitives::Wtxid +impl core::clone::Clone for bitcoin_primitives::block::BlockDecoderError +impl core::clone::Clone for bitcoin_primitives::block::BlockHashDecoderError +impl core::clone::Clone for bitcoin_primitives::block::Checked +impl core::clone::Clone for bitcoin_primitives::block::Header +impl core::clone::Clone for bitcoin_primitives::block::HeaderDecoderError +impl core::clone::Clone for bitcoin_primitives::block::InvalidBlockError +impl core::clone::Clone for bitcoin_primitives::block::Unchecked +impl core::clone::Clone for bitcoin_primitives::block::Version +impl core::clone::Clone for bitcoin_primitives::block::VersionDecoderError +impl core::clone::Clone for bitcoin_primitives::pow::CompactTarget +impl core::clone::Clone for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::clone::Clone for bitcoin_primitives::script::RedeemScriptSizeError +impl core::clone::Clone for bitcoin_primitives::script::RedeemScriptTag +impl core::clone::Clone for bitcoin_primitives::script::ScriptBufDecoderError +impl core::clone::Clone for bitcoin_primitives::script::ScriptHash +impl core::clone::Clone for bitcoin_primitives::script::ScriptPubKeyTag +impl core::clone::Clone for bitcoin_primitives::script::ScriptSigTag +impl core::clone::Clone for bitcoin_primitives::script::TapScriptTag +impl core::clone::Clone for bitcoin_primitives::script::WScriptHash +impl core::clone::Clone for bitcoin_primitives::script::WitnessScriptSizeError +impl core::clone::Clone for bitcoin_primitives::script::WitnessScriptTag +impl core::clone::Clone for bitcoin_primitives::transaction::OutPoint +impl core::clone::Clone for bitcoin_primitives::transaction::OutPointDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::ParseOutPointError +impl core::clone::Clone for bitcoin_primitives::transaction::Transaction +impl core::clone::Clone for bitcoin_primitives::transaction::TransactionDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxIn +impl core::clone::Clone for bitcoin_primitives::transaction::TxInDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxOut +impl core::clone::Clone for bitcoin_primitives::transaction::TxOutDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::Version +impl core::clone::Clone for bitcoin_primitives::transaction::VersionDecoderError +impl core::clone::Clone for bitcoin_primitives::witness::UnexpectedEofError +impl core::clone::Clone for bitcoin_primitives::witness::Witness +impl core::clone::Clone for bitcoin_primitives::witness::WitnessDecoderError +impl core::cmp::Eq for bitcoin_primitives::BlockHash +impl core::cmp::Eq for bitcoin_primitives::Ntxid +impl core::cmp::Eq for bitcoin_primitives::TxMerkleNode +impl core::cmp::Eq for bitcoin_primitives::Txid +impl core::cmp::Eq for bitcoin_primitives::WitnessCommitment +impl core::cmp::Eq for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::Eq for bitcoin_primitives::Wtxid +impl core::cmp::Eq for bitcoin_primitives::block::BlockDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::BlockHashDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::Checked +impl core::cmp::Eq for bitcoin_primitives::block::Header +impl core::cmp::Eq for bitcoin_primitives::block::HeaderDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::InvalidBlockError +impl core::cmp::Eq for bitcoin_primitives::block::Unchecked +impl core::cmp::Eq for bitcoin_primitives::block::Version +impl core::cmp::Eq for bitcoin_primitives::block::VersionDecoderError +impl core::cmp::Eq for bitcoin_primitives::pow::CompactTarget +impl core::cmp::Eq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::cmp::Eq for bitcoin_primitives::script::RedeemScriptSizeError +impl core::cmp::Eq for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::Eq for bitcoin_primitives::script::ScriptBufDecoderError +impl core::cmp::Eq for bitcoin_primitives::script::ScriptHash +impl core::cmp::Eq for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::Eq for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::Eq for bitcoin_primitives::script::TapScriptTag +impl core::cmp::Eq for bitcoin_primitives::script::WScriptHash +impl core::cmp::Eq for bitcoin_primitives::script::WitnessScriptSizeError +impl core::cmp::Eq for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::Eq for bitcoin_primitives::transaction::OutPoint +impl core::cmp::Eq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::ParseOutPointError +impl core::cmp::Eq for bitcoin_primitives::transaction::Transaction +impl core::cmp::Eq for bitcoin_primitives::transaction::TransactionDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxIn +impl core::cmp::Eq for bitcoin_primitives::transaction::TxInDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxOut +impl core::cmp::Eq for bitcoin_primitives::transaction::TxOutDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::Version +impl core::cmp::Eq for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::Eq for bitcoin_primitives::witness::UnexpectedEofError +impl core::cmp::Eq for bitcoin_primitives::witness::Witness +impl core::cmp::Eq for bitcoin_primitives::witness::WitnessDecoderError +impl core::cmp::Ord for bitcoin_primitives::BlockHash +impl core::cmp::Ord for bitcoin_primitives::Ntxid +impl core::cmp::Ord for bitcoin_primitives::TxMerkleNode +impl core::cmp::Ord for bitcoin_primitives::Txid +impl core::cmp::Ord for bitcoin_primitives::WitnessCommitment +impl core::cmp::Ord for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::Ord for bitcoin_primitives::Wtxid +impl core::cmp::Ord for bitcoin_primitives::block::Checked +impl core::cmp::Ord for bitcoin_primitives::block::Header +impl core::cmp::Ord for bitcoin_primitives::block::Unchecked +impl core::cmp::Ord for bitcoin_primitives::block::Version +impl core::cmp::Ord for bitcoin_primitives::pow::CompactTarget +impl core::cmp::Ord for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::Ord for bitcoin_primitives::script::ScriptHash +impl core::cmp::Ord for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::Ord for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::Ord for bitcoin_primitives::script::TapScriptTag +impl core::cmp::Ord for bitcoin_primitives::script::WScriptHash +impl core::cmp::Ord for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::Ord for bitcoin_primitives::transaction::OutPoint +impl core::cmp::Ord for bitcoin_primitives::transaction::Transaction +impl core::cmp::Ord for bitcoin_primitives::transaction::TxIn +impl core::cmp::Ord for bitcoin_primitives::transaction::TxOut +impl core::cmp::Ord for bitcoin_primitives::transaction::Version +impl core::cmp::Ord for bitcoin_primitives::witness::Witness +impl core::cmp::PartialEq for bitcoin_primitives::BlockHash +impl core::cmp::PartialEq for bitcoin_primitives::Ntxid +impl core::cmp::PartialEq for bitcoin_primitives::TxMerkleNode +impl core::cmp::PartialEq for bitcoin_primitives::Txid +impl core::cmp::PartialEq for bitcoin_primitives::WitnessCommitment +impl core::cmp::PartialEq for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::PartialEq for bitcoin_primitives::Wtxid +impl core::cmp::PartialEq for bitcoin_primitives::block::BlockDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::BlockHashDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::Checked +impl core::cmp::PartialEq for bitcoin_primitives::block::Header +impl core::cmp::PartialEq for bitcoin_primitives::block::HeaderDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::InvalidBlockError +impl core::cmp::PartialEq for bitcoin_primitives::block::Unchecked +impl core::cmp::PartialEq for bitcoin_primitives::block::Version +impl core::cmp::PartialEq for bitcoin_primitives::block::VersionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::pow::CompactTarget +impl core::cmp::PartialEq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::script::RedeemScriptSizeError +impl core::cmp::PartialEq for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptBufDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptHash +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::PartialEq for bitcoin_primitives::script::TapScriptTag +impl core::cmp::PartialEq for bitcoin_primitives::script::WScriptHash +impl core::cmp::PartialEq for bitcoin_primitives::script::WitnessScriptSizeError +impl core::cmp::PartialEq for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::PartialEq for bitcoin_primitives::transaction::OutPoint +impl core::cmp::PartialEq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::ParseOutPointError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::Transaction +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TransactionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxIn +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxInDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxOut +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxOutDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::Version +impl core::cmp::PartialEq for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::witness::UnexpectedEofError +impl core::cmp::PartialEq for bitcoin_primitives::witness::Witness +impl core::cmp::PartialEq for bitcoin_primitives::witness::WitnessDecoderError +impl core::cmp::PartialOrd for bitcoin_primitives::BlockHash +impl core::cmp::PartialOrd for bitcoin_primitives::Ntxid +impl core::cmp::PartialOrd for bitcoin_primitives::TxMerkleNode +impl core::cmp::PartialOrd for bitcoin_primitives::Txid +impl core::cmp::PartialOrd for bitcoin_primitives::WitnessCommitment +impl core::cmp::PartialOrd for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::PartialOrd for bitcoin_primitives::Wtxid +impl core::cmp::PartialOrd for bitcoin_primitives::block::Checked +impl core::cmp::PartialOrd for bitcoin_primitives::block::Header +impl core::cmp::PartialOrd for bitcoin_primitives::block::Unchecked +impl core::cmp::PartialOrd for bitcoin_primitives::block::Version +impl core::cmp::PartialOrd for bitcoin_primitives::pow::CompactTarget +impl core::cmp::PartialOrd for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptHash +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::TapScriptTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::WScriptHash +impl core::cmp::PartialOrd for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::OutPoint +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::Transaction +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::TxIn +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::TxOut +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::Version +impl core::cmp::PartialOrd for bitcoin_primitives::witness::Witness +impl core::convert::AsRef<[u8; 20]> for bitcoin_primitives::script::ScriptHash +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::BlockHash +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Ntxid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::TxMerkleNode +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Txid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::WitnessCommitment +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::WitnessMerkleNode +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Wtxid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::script::WScriptHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::BlockHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Ntxid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::TxMerkleNode +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Txid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::WitnessCommitment +impl core::convert::AsRef<[u8]> for bitcoin_primitives::WitnessMerkleNode +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Wtxid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::ScriptHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::WScriptHash +impl core::convert::From<&[&[u8]]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[alloc::vec::Vec]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&bitcoin_primitives::block::Block> for bitcoin_primitives::BlockHash +impl core::convert::From<&bitcoin_primitives::block::Header> for bitcoin_primitives::BlockHash +impl core::convert::From<&bitcoin_primitives::transaction::Transaction> for bitcoin_primitives::Txid +impl core::convert::From<&bitcoin_primitives::transaction::Transaction> for bitcoin_primitives::Wtxid +impl core::convert::From> for bitcoin_primitives::witness::Witness +impl core::convert::From>> for bitcoin_primitives::witness::Witness +impl core::convert::From for bitcoin_primitives::script::ScriptBufDecoderError +impl core::convert::From for bitcoin_primitives::block::BlockHashDecoderError +impl core::convert::From for bitcoin_primitives::block::VersionDecoderError +impl core::convert::From for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::convert::From> for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From> for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::BlockHash +impl core::convert::From for bitcoin_primitives::BlockHash +impl core::convert::From for bitcoin_primitives::Txid +impl core::convert::From for bitcoin_primitives::Wtxid +impl core::convert::From for u32 +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::block::BlockDecoderError +impl core::convert::From for bitcoin_primitives::block::BlockHashDecoderError +impl core::convert::From for bitcoin_primitives::block::HeaderDecoderError +impl core::convert::From for bitcoin_primitives::block::InvalidBlockError +impl core::convert::From for bitcoin_primitives::block::VersionDecoderError +impl core::convert::From for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::convert::From for bitcoin_primitives::script::RedeemScriptSizeError +impl core::convert::From for bitcoin_primitives::script::ScriptBufDecoderError +impl core::convert::From for bitcoin_primitives::script::WitnessScriptSizeError +impl core::convert::From for bitcoin_primitives::transaction::ParseOutPointError +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxInDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxOutDecoderError +impl core::convert::From for bitcoin_primitives::transaction::VersionDecoderError +impl core::convert::From for bitcoin_primitives::witness::WitnessDecoderError +impl core::convert::TryFrom<&bitcoin_primitives::script::Script> for bitcoin_primitives::script::WScriptHash +impl core::convert::TryFrom<&bitcoin_primitives::script::ScriptBuf> for bitcoin_primitives::script::WScriptHash +impl core::convert::TryFrom> for bitcoin_primitives::script::WScriptHash +impl core::default::Default for bitcoin_primitives::block::BlockHashDecoder +impl core::default::Default for bitcoin_primitives::block::Version +impl core::default::Default for bitcoin_primitives::block::VersionDecoder +impl core::default::Default for bitcoin_primitives::pow::CompactTargetDecoder +impl core::default::Default for bitcoin_primitives::transaction::OutPointDecoder +impl core::default::Default for bitcoin_primitives::transaction::TransactionDecoder +impl core::default::Default for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::default::Default for bitcoin_primitives::transaction::VersionDecoder +impl core::default::Default for bitcoin_primitives::witness::Witness +impl core::default::Default for bitcoin_primitives::witness::WitnessDecoder +impl core::error::Error for bitcoin_primitives::block::BlockDecoderError +impl core::error::Error for bitcoin_primitives::block::BlockHashDecoderError +impl core::error::Error for bitcoin_primitives::block::HeaderDecoderError +impl core::error::Error for bitcoin_primitives::block::InvalidBlockError +impl core::error::Error for bitcoin_primitives::block::VersionDecoderError +impl core::error::Error for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::error::Error for bitcoin_primitives::script::RedeemScriptSizeError +impl core::error::Error for bitcoin_primitives::script::ScriptBufDecoderError +impl core::error::Error for bitcoin_primitives::script::WitnessScriptSizeError +impl core::error::Error for bitcoin_primitives::transaction::OutPointDecoderError +impl core::error::Error for bitcoin_primitives::transaction::ParseOutPointError +impl core::error::Error for bitcoin_primitives::transaction::TransactionDecoderError +impl core::error::Error for bitcoin_primitives::transaction::TxInDecoderError +impl core::error::Error for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::error::Error for bitcoin_primitives::transaction::TxOutDecoderError +impl core::error::Error for bitcoin_primitives::transaction::VersionDecoderError +impl core::error::Error for bitcoin_primitives::witness::UnexpectedEofError +impl core::error::Error for bitcoin_primitives::witness::WitnessDecoderError +impl core::fmt::Debug for bitcoin_primitives::BlockHash +impl core::fmt::Debug for bitcoin_primitives::Ntxid +impl core::fmt::Debug for bitcoin_primitives::TxMerkleNode +impl core::fmt::Debug for bitcoin_primitives::Txid +impl core::fmt::Debug for bitcoin_primitives::WitnessCommitment +impl core::fmt::Debug for bitcoin_primitives::WitnessMerkleNode +impl core::fmt::Debug for bitcoin_primitives::Wtxid +impl core::fmt::Debug for bitcoin_primitives::block::BlockDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::BlockHashDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::Checked +impl core::fmt::Debug for bitcoin_primitives::block::Header +impl core::fmt::Debug for bitcoin_primitives::block::HeaderDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::InvalidBlockError +impl core::fmt::Debug for bitcoin_primitives::block::Unchecked +impl core::fmt::Debug for bitcoin_primitives::block::Version +impl core::fmt::Debug for bitcoin_primitives::block::VersionDecoderError +impl core::fmt::Debug for bitcoin_primitives::pow::CompactTarget +impl core::fmt::Debug for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::fmt::Debug for bitcoin_primitives::script::RedeemScriptSizeError +impl core::fmt::Debug for bitcoin_primitives::script::ScriptBufDecoderError +impl core::fmt::Debug for bitcoin_primitives::script::ScriptHash +impl core::fmt::Debug for bitcoin_primitives::script::WScriptHash +impl core::fmt::Debug for bitcoin_primitives::script::WitnessScriptSizeError +impl core::fmt::Debug for bitcoin_primitives::transaction::OutPoint +impl core::fmt::Debug for bitcoin_primitives::transaction::OutPointDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::ParseOutPointError +impl core::fmt::Debug for bitcoin_primitives::transaction::Transaction +impl core::fmt::Debug for bitcoin_primitives::transaction::TransactionDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxIn +impl core::fmt::Debug for bitcoin_primitives::transaction::TxInDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxOut +impl core::fmt::Debug for bitcoin_primitives::transaction::TxOutDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::Version +impl core::fmt::Debug for bitcoin_primitives::transaction::VersionDecoderError +impl core::fmt::Debug for bitcoin_primitives::witness::UnexpectedEofError +impl core::fmt::Debug for bitcoin_primitives::witness::Witness +impl core::fmt::Debug for bitcoin_primitives::witness::WitnessDecoderError +impl core::fmt::Display for bitcoin_primitives::BlockHash +impl core::fmt::Display for bitcoin_primitives::Ntxid +impl core::fmt::Display for bitcoin_primitives::TxMerkleNode +impl core::fmt::Display for bitcoin_primitives::Txid +impl core::fmt::Display for bitcoin_primitives::WitnessCommitment +impl core::fmt::Display for bitcoin_primitives::WitnessMerkleNode +impl core::fmt::Display for bitcoin_primitives::Wtxid +impl core::fmt::Display for bitcoin_primitives::block::BlockDecoderError +impl core::fmt::Display for bitcoin_primitives::block::BlockHashDecoderError +impl core::fmt::Display for bitcoin_primitives::block::Header +impl core::fmt::Display for bitcoin_primitives::block::HeaderDecoderError +impl core::fmt::Display for bitcoin_primitives::block::InvalidBlockError +impl core::fmt::Display for bitcoin_primitives::block::VersionDecoderError +impl core::fmt::Display for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::fmt::Display for bitcoin_primitives::script::RedeemScriptSizeError +impl core::fmt::Display for bitcoin_primitives::script::ScriptBufDecoderError +impl core::fmt::Display for bitcoin_primitives::script::ScriptHash +impl core::fmt::Display for bitcoin_primitives::script::WScriptHash +impl core::fmt::Display for bitcoin_primitives::script::WitnessScriptSizeError +impl core::fmt::Display for bitcoin_primitives::transaction::OutPoint +impl core::fmt::Display for bitcoin_primitives::transaction::OutPointDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::ParseOutPointError +impl core::fmt::Display for bitcoin_primitives::transaction::TransactionDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxInDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxOutDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::Version +impl core::fmt::Display for bitcoin_primitives::transaction::VersionDecoderError +impl core::fmt::Display for bitcoin_primitives::witness::UnexpectedEofError +impl core::fmt::Display for bitcoin_primitives::witness::WitnessDecoderError +impl core::fmt::LowerHex for bitcoin_primitives::BlockHash +impl core::fmt::LowerHex for bitcoin_primitives::Ntxid +impl core::fmt::LowerHex for bitcoin_primitives::TxMerkleNode +impl core::fmt::LowerHex for bitcoin_primitives::Txid +impl core::fmt::LowerHex for bitcoin_primitives::WitnessCommitment +impl core::fmt::LowerHex for bitcoin_primitives::WitnessMerkleNode +impl core::fmt::LowerHex for bitcoin_primitives::Wtxid +impl core::fmt::LowerHex for bitcoin_primitives::pow::CompactTarget +impl core::fmt::LowerHex for bitcoin_primitives::script::ScriptHash +impl core::fmt::LowerHex for bitcoin_primitives::script::WScriptHash +impl core::fmt::UpperHex for bitcoin_primitives::BlockHash +impl core::fmt::UpperHex for bitcoin_primitives::Ntxid +impl core::fmt::UpperHex for bitcoin_primitives::TxMerkleNode +impl core::fmt::UpperHex for bitcoin_primitives::Txid +impl core::fmt::UpperHex for bitcoin_primitives::WitnessCommitment +impl core::fmt::UpperHex for bitcoin_primitives::WitnessMerkleNode +impl core::fmt::UpperHex for bitcoin_primitives::Wtxid +impl core::fmt::UpperHex for bitcoin_primitives::pow::CompactTarget +impl core::fmt::UpperHex for bitcoin_primitives::script::ScriptHash +impl core::fmt::UpperHex for bitcoin_primitives::script::WScriptHash +impl core::hash::Hash for bitcoin_primitives::BlockHash +impl core::hash::Hash for bitcoin_primitives::Ntxid +impl core::hash::Hash for bitcoin_primitives::TxMerkleNode +impl core::hash::Hash for bitcoin_primitives::Txid +impl core::hash::Hash for bitcoin_primitives::WitnessCommitment +impl core::hash::Hash for bitcoin_primitives::WitnessMerkleNode +impl core::hash::Hash for bitcoin_primitives::Wtxid +impl core::hash::Hash for bitcoin_primitives::block::Checked +impl core::hash::Hash for bitcoin_primitives::block::Header +impl core::hash::Hash for bitcoin_primitives::block::Unchecked +impl core::hash::Hash for bitcoin_primitives::block::Version +impl core::hash::Hash for bitcoin_primitives::pow::CompactTarget +impl core::hash::Hash for bitcoin_primitives::script::RedeemScriptTag +impl core::hash::Hash for bitcoin_primitives::script::ScriptHash +impl core::hash::Hash for bitcoin_primitives::script::ScriptPubKeyTag +impl core::hash::Hash for bitcoin_primitives::script::ScriptSigTag +impl core::hash::Hash for bitcoin_primitives::script::TapScriptTag +impl core::hash::Hash for bitcoin_primitives::script::WScriptHash +impl core::hash::Hash for bitcoin_primitives::script::WitnessScriptTag +impl core::hash::Hash for bitcoin_primitives::transaction::OutPoint +impl core::hash::Hash for bitcoin_primitives::transaction::Transaction +impl core::hash::Hash for bitcoin_primitives::transaction::TxIn +impl core::hash::Hash for bitcoin_primitives::transaction::TxOut +impl core::hash::Hash for bitcoin_primitives::transaction::Version +impl core::hash::Hash for bitcoin_primitives::witness::Witness +impl core::iter::traits::exact_size::ExactSizeIterator for bitcoin_primitives::witness::Iter<'_> +impl core::marker::Copy for bitcoin_primitives::BlockHash +impl core::marker::Copy for bitcoin_primitives::Ntxid +impl core::marker::Copy for bitcoin_primitives::TxMerkleNode +impl core::marker::Copy for bitcoin_primitives::Txid +impl core::marker::Copy for bitcoin_primitives::WitnessCommitment +impl core::marker::Copy for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Copy for bitcoin_primitives::Wtxid +impl core::marker::Copy for bitcoin_primitives::block::Header +impl core::marker::Copy for bitcoin_primitives::block::Version +impl core::marker::Copy for bitcoin_primitives::pow::CompactTarget +impl core::marker::Copy for bitcoin_primitives::script::ScriptHash +impl core::marker::Copy for bitcoin_primitives::script::WScriptHash +impl core::marker::Copy for bitcoin_primitives::transaction::OutPoint +impl core::marker::Copy for bitcoin_primitives::transaction::Version +impl core::marker::Freeze for bitcoin_primitives::BlockHash +impl core::marker::Freeze for bitcoin_primitives::Ntxid +impl core::marker::Freeze for bitcoin_primitives::TxMerkleNode +impl core::marker::Freeze for bitcoin_primitives::Txid +impl core::marker::Freeze for bitcoin_primitives::WitnessCommitment +impl core::marker::Freeze for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Freeze for bitcoin_primitives::Wtxid +impl core::marker::Freeze for bitcoin_primitives::block::BlockDecoder +impl core::marker::Freeze for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Freeze for bitcoin_primitives::block::Checked +impl core::marker::Freeze for bitcoin_primitives::block::Header +impl core::marker::Freeze for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Freeze for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Freeze for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Freeze for bitcoin_primitives::block::Unchecked +impl core::marker::Freeze for bitcoin_primitives::block::Version +impl core::marker::Freeze for bitcoin_primitives::block::VersionDecoder +impl core::marker::Freeze for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::VersionEncoder +impl core::marker::Freeze for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTarget +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Freeze for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Freeze for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Freeze for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Freeze for bitcoin_primitives::script::ScriptHash +impl core::marker::Freeze for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Freeze for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Freeze for bitcoin_primitives::script::TapScriptTag +impl core::marker::Freeze for bitcoin_primitives::script::WScriptHash +impl core::marker::Freeze for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Freeze for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPoint +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::ParseOutPointError +impl core::marker::Freeze for bitcoin_primitives::transaction::Transaction +impl core::marker::Freeze for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxIn +impl core::marker::Freeze for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxOut +impl core::marker::Freeze for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::Version +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Freeze for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Freeze for bitcoin_primitives::witness::Witness +impl core::marker::Freeze for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Freeze for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::Send for bitcoin_primitives::BlockHash +impl core::marker::Send for bitcoin_primitives::Ntxid +impl core::marker::Send for bitcoin_primitives::TxMerkleNode +impl core::marker::Send for bitcoin_primitives::Txid +impl core::marker::Send for bitcoin_primitives::WitnessCommitment +impl core::marker::Send for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Send for bitcoin_primitives::Wtxid +impl core::marker::Send for bitcoin_primitives::block::BlockDecoder +impl core::marker::Send for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Send for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Send for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Send for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Send for bitcoin_primitives::block::Checked +impl core::marker::Send for bitcoin_primitives::block::Header +impl core::marker::Send for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Send for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Send for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Send for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Send for bitcoin_primitives::block::Unchecked +impl core::marker::Send for bitcoin_primitives::block::Version +impl core::marker::Send for bitcoin_primitives::block::VersionDecoder +impl core::marker::Send for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Send for bitcoin_primitives::block::VersionEncoder +impl core::marker::Send for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Send for bitcoin_primitives::pow::CompactTarget +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Send for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Send for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Send for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Send for bitcoin_primitives::script::ScriptHash +impl core::marker::Send for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Send for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Send for bitcoin_primitives::script::TapScriptTag +impl core::marker::Send for bitcoin_primitives::script::WScriptHash +impl core::marker::Send for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Send for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Send for bitcoin_primitives::transaction::OutPoint +impl core::marker::Send for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Send for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::ParseOutPointError +impl core::marker::Send for bitcoin_primitives::transaction::Transaction +impl core::marker::Send for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxIn +impl core::marker::Send for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxOut +impl core::marker::Send for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::Version +impl core::marker::Send for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Send for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Send for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Send for bitcoin_primitives::witness::Witness +impl core::marker::Send for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Send for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::BlockHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::Ntxid +impl core::marker::StructuralPartialEq for bitcoin_primitives::TxMerkleNode +impl core::marker::StructuralPartialEq for bitcoin_primitives::Txid +impl core::marker::StructuralPartialEq for bitcoin_primitives::WitnessCommitment +impl core::marker::StructuralPartialEq for bitcoin_primitives::WitnessMerkleNode +impl core::marker::StructuralPartialEq for bitcoin_primitives::Wtxid +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::BlockDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Checked +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Header +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::InvalidBlockError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Unchecked +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Version +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::VersionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::pow::CompactTarget +impl core::marker::StructuralPartialEq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptSigTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::TapScriptTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::WScriptHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::OutPoint +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::ParseOutPointError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::Transaction +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxIn +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxOut +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::Version +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::StructuralPartialEq for bitcoin_primitives::witness::Witness +impl core::marker::StructuralPartialEq for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::Sync for bitcoin_primitives::BlockHash +impl core::marker::Sync for bitcoin_primitives::Ntxid +impl core::marker::Sync for bitcoin_primitives::TxMerkleNode +impl core::marker::Sync for bitcoin_primitives::Txid +impl core::marker::Sync for bitcoin_primitives::WitnessCommitment +impl core::marker::Sync for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Sync for bitcoin_primitives::Wtxid +impl core::marker::Sync for bitcoin_primitives::block::BlockDecoder +impl core::marker::Sync for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Sync for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Sync for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Sync for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Sync for bitcoin_primitives::block::Checked +impl core::marker::Sync for bitcoin_primitives::block::Header +impl core::marker::Sync for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Sync for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Sync for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Sync for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Sync for bitcoin_primitives::block::Unchecked +impl core::marker::Sync for bitcoin_primitives::block::Version +impl core::marker::Sync for bitcoin_primitives::block::VersionDecoder +impl core::marker::Sync for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::block::VersionEncoder +impl core::marker::Sync for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Sync for bitcoin_primitives::pow::CompactTarget +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Sync for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Sync for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Sync for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Sync for bitcoin_primitives::script::ScriptHash +impl core::marker::Sync for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Sync for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Sync for bitcoin_primitives::script::TapScriptTag +impl core::marker::Sync for bitcoin_primitives::script::WScriptHash +impl core::marker::Sync for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Sync for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Sync for bitcoin_primitives::transaction::OutPoint +impl core::marker::Sync for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::ParseOutPointError +impl core::marker::Sync for bitcoin_primitives::transaction::Transaction +impl core::marker::Sync for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxIn +impl core::marker::Sync for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxOut +impl core::marker::Sync for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::Version +impl core::marker::Sync for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Sync for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Sync for bitcoin_primitives::witness::Witness +impl core::marker::Sync for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Sync for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::Unpin for bitcoin_primitives::BlockHash +impl core::marker::Unpin for bitcoin_primitives::Ntxid +impl core::marker::Unpin for bitcoin_primitives::TxMerkleNode +impl core::marker::Unpin for bitcoin_primitives::Txid +impl core::marker::Unpin for bitcoin_primitives::WitnessCommitment +impl core::marker::Unpin for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Unpin for bitcoin_primitives::Wtxid +impl core::marker::Unpin for bitcoin_primitives::block::BlockDecoder +impl core::marker::Unpin for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Unpin for bitcoin_primitives::block::Checked +impl core::marker::Unpin for bitcoin_primitives::block::Header +impl core::marker::Unpin for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Unpin for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Unpin for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Unpin for bitcoin_primitives::block::Unchecked +impl core::marker::Unpin for bitcoin_primitives::block::Version +impl core::marker::Unpin for bitcoin_primitives::block::VersionDecoder +impl core::marker::Unpin for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::VersionEncoder +impl core::marker::Unpin for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTarget +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Unpin for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Unpin for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Unpin for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Unpin for bitcoin_primitives::script::ScriptHash +impl core::marker::Unpin for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Unpin for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Unpin for bitcoin_primitives::script::TapScriptTag +impl core::marker::Unpin for bitcoin_primitives::script::WScriptHash +impl core::marker::Unpin for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Unpin for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPoint +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::ParseOutPointError +impl core::marker::Unpin for bitcoin_primitives::transaction::Transaction +impl core::marker::Unpin for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxIn +impl core::marker::Unpin for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxOut +impl core::marker::Unpin for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::Version +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Unpin for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Unpin for bitcoin_primitives::witness::Witness +impl core::marker::Unpin for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Unpin for bitcoin_primitives::witness::WitnessDecoderError +impl core::ops::index::Index for bitcoin_primitives::witness::Witness +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::BlockHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Ntxid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::TxMerkleNode +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Txid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::WitnessCommitment +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::WitnessMerkleNode +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Wtxid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Checked +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Header +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::InvalidBlockError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Unchecked +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Version +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTarget +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::RedeemScriptSizeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::RedeemScriptTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptBufDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptPubKeyTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptSigTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::TapScriptTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::WScriptHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::WitnessScriptSizeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::WitnessScriptTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPoint +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::ParseOutPointError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::Transaction +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TransactionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TransactionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxIn +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxInDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxInDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOut +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOutDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOutDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::Version +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::UnexpectedEofError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::Witness +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::WitnessDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::WitnessDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::BlockHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Ntxid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::TxMerkleNode +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Txid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::WitnessCommitment +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::WitnessMerkleNode +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Wtxid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Checked +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Header +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::InvalidBlockError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Unchecked +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Version +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTarget +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::RedeemScriptSizeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::RedeemScriptTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptBufDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptPubKeyTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptSigTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::TapScriptTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::WScriptHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::WitnessScriptSizeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::WitnessScriptTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPoint +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::ParseOutPointError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::Transaction +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TransactionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TransactionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxIn +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxInDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxInDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOut +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOutDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOutDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::Version +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::UnexpectedEofError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::Witness +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::WitnessDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::WitnessDecoderError +impl core::str::traits::FromStr for bitcoin_primitives::BlockHash +impl core::str::traits::FromStr for bitcoin_primitives::Ntxid +impl core::str::traits::FromStr for bitcoin_primitives::TxMerkleNode +impl core::str::traits::FromStr for bitcoin_primitives::Txid +impl core::str::traits::FromStr for bitcoin_primitives::WitnessCommitment +impl core::str::traits::FromStr for bitcoin_primitives::WitnessMerkleNode +impl core::str::traits::FromStr for bitcoin_primitives::Wtxid +impl core::str::traits::FromStr for bitcoin_primitives::script::ScriptHash +impl core::str::traits::FromStr for bitcoin_primitives::script::WScriptHash +impl core::str::traits::FromStr for bitcoin_primitives::transaction::OutPoint +impl serde::ser::Serialize for bitcoin_primitives::BlockHash +impl serde::ser::Serialize for bitcoin_primitives::Ntxid +impl serde::ser::Serialize for bitcoin_primitives::TxMerkleNode +impl serde::ser::Serialize for bitcoin_primitives::Txid +impl serde::ser::Serialize for bitcoin_primitives::WitnessCommitment +impl serde::ser::Serialize for bitcoin_primitives::WitnessMerkleNode +impl serde::ser::Serialize for bitcoin_primitives::Wtxid +impl serde::ser::Serialize for bitcoin_primitives::block::Version +impl serde::ser::Serialize for bitcoin_primitives::pow::CompactTarget +impl serde::ser::Serialize for bitcoin_primitives::script::ScriptHash +impl serde::ser::Serialize for bitcoin_primitives::script::WScriptHash +impl serde::ser::Serialize for bitcoin_primitives::transaction::OutPoint +impl serde::ser::Serialize for bitcoin_primitives::transaction::Version +impl serde::ser::Serialize for bitcoin_primitives::witness::Witness +impl<'a, T> arbitrary::Arbitrary<'a> for &'a bitcoin_primitives::script::Script +impl<'a, T> arbitrary::Arbitrary<'a> for bitcoin_primitives::script::ScriptBuf +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::borrow::Cow<'a, bitcoin_primitives::script::Script> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::boxed::Box> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::rc::Rc> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::sync::Arc> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for bitcoin_primitives::script::ScriptBuf +impl<'a, T> core::convert::From>> for alloc::boxed::Box> +impl<'a, T> core::convert::From>> for bitcoin_primitives::script::ScriptBuf +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::BlockHash +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::Ntxid +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::TxMerkleNode +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::Txid +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::WitnessCommitment +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::WitnessMerkleNode +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::Wtxid +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::block::Block +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::block::Header +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::block::Version +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::script::ScriptHash +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::script::WScriptHash +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::transaction::OutPoint +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::transaction::Transaction +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::transaction::TxIn +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::transaction::TxOut +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::transaction::Version +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_primitives::witness::Witness +impl<'a> core::clone::Clone for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::iter::traits::collect::IntoIterator for &'a bitcoin_primitives::witness::Witness +impl<'a> core::iter::traits::iterator::Iterator for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Freeze for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Freeze for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::marker::Send for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Send for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::marker::Sync for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Sync for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::marker::Unpin for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Unpin for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'de, T> serde::de::Deserialize<'de> for &'de bitcoin_primitives::script::Script +impl<'de, T> serde::de::Deserialize<'de> for bitcoin_primitives::script::ScriptBuf +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::BlockHash +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::Ntxid +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::TxMerkleNode +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::Txid +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::WitnessCommitment +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::WitnessMerkleNode +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::Wtxid +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::block::Version +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::pow::CompactTarget +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::script::ScriptHash +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::script::WScriptHash +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::transaction::OutPoint +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::transaction::Version +impl<'de> serde::de::Deserialize<'de> for bitcoin_primitives::witness::Witness +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl core::default::Default for &bitcoin_primitives::script::Script +impl core::convert::TryFrom<&bitcoin_primitives::script::Script> for bitcoin_primitives::script::ScriptHash +impl core::convert::TryFrom<&bitcoin_primitives::script::ScriptBuf> for bitcoin_primitives::script::ScriptHash +impl core::convert::TryFrom> for bitcoin_primitives::script::ScriptHash +impl> core::cmp::PartialEq<&[T]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq<[T]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq for &[T] +impl> core::cmp::PartialEq for [T] +impl> core::cmp::PartialEq for alloc::boxed::Box<[T]> +impl> core::cmp::PartialEq for alloc::rc::Rc<[T]> +impl> core::cmp::PartialEq for alloc::sync::Arc<[T]> +impl> core::cmp::PartialEq for alloc::vec::Vec +impl core::clone::Clone for bitcoin_primitives::script::ScriptBuf +impl core::cmp::Eq for bitcoin_primitives::script::Script +impl core::cmp::Eq for bitcoin_primitives::script::ScriptBuf +impl core::cmp::Ord for bitcoin_primitives::script::Script +impl core::cmp::Ord for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialEq for bitcoin_primitives::script::Script +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialEq> for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialEq> for bitcoin_primitives::script::Script +impl core::cmp::PartialOrd for bitcoin_primitives::script::Script +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialOrd> for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialOrd> for bitcoin_primitives::script::Script +impl> core::iter::traits::collect::FromIterator for bitcoin_primitives::witness::Witness +impl core::hash::Hash for bitcoin_primitives::script::Script +impl core::hash::Hash for bitcoin_primitives::script::ScriptBuf +impl !core::marker::Sized for bitcoin_primitives::script::Script +impl alloc::borrow::ToOwned for bitcoin_primitives::script::Script +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::script::ScriptBuf +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::script::ScriptBufDecoder +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::script::Script +impl bitcoin_primitives::script::Script +impl bitcoin_primitives::script::ScriptBuf +impl bitcoin_primitives::script::ScriptBufDecoder +impl core::borrow::Borrow> for bitcoin_primitives::script::ScriptBuf +impl core::borrow::BorrowMut> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsMut<[u8]> for bitcoin_primitives::script::Script +impl core::convert::AsMut<[u8]> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsMut> for bitcoin_primitives::script::Script +impl core::convert::AsMut> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::Script +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsRef> for bitcoin_primitives::script::Script +impl core::convert::AsRef> for bitcoin_primitives::script::ScriptBuf +impl core::convert::From> for bitcoin_primitives::script::ScriptBuf +impl core::convert::From> for alloc::borrow::Cow<'_, bitcoin_primitives::script::Script> +impl core::convert::From> for alloc::boxed::Box> +impl core::convert::From> for alloc::vec::Vec +impl core::default::Default for bitcoin_primitives::script::ScriptBuf +impl core::default::Default for bitcoin_primitives::script::ScriptBufDecoder +impl core::fmt::Debug for bitcoin_primitives::script::Script +impl core::fmt::Debug for bitcoin_primitives::script::ScriptBuf +impl core::fmt::Display for bitcoin_primitives::script::Script +impl core::fmt::Display for bitcoin_primitives::script::ScriptBuf +impl core::fmt::LowerHex for bitcoin_primitives::script::Script +impl core::fmt::LowerHex for bitcoin_primitives::script::ScriptBuf +impl core::fmt::UpperHex for bitcoin_primitives::script::Script +impl core::fmt::UpperHex for bitcoin_primitives::script::ScriptBuf +impl core::marker::Freeze for bitcoin_primitives::script::Script +impl core::marker::Freeze for bitcoin_primitives::script::ScriptBuf +impl core::marker::Freeze for bitcoin_primitives::script::ScriptBufDecoder +impl core::marker::Send for bitcoin_primitives::script::Script where T: core::marker::Send +impl core::marker::Send for bitcoin_primitives::script::ScriptBuf where T: core::marker::Send +impl core::marker::Send for bitcoin_primitives::script::ScriptBufDecoder where T: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::Script +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptBuf +impl core::marker::Sync for bitcoin_primitives::script::Script where T: core::marker::Sync +impl core::marker::Sync for bitcoin_primitives::script::ScriptBuf where T: core::marker::Sync +impl core::marker::Sync for bitcoin_primitives::script::ScriptBufDecoder where T: core::marker::Sync +impl core::marker::Unpin for bitcoin_primitives::script::Script where T: core::marker::Unpin +impl core::marker::Unpin for bitcoin_primitives::script::ScriptBuf where T: core::marker::Unpin +impl core::marker::Unpin for bitcoin_primitives::script::ScriptBufDecoder where T: core::marker::Unpin +impl core::ops::deref::Deref for bitcoin_primitives::script::ScriptBuf +impl core::ops::deref::DerefMut for bitcoin_primitives::script::ScriptBuf +impl core::ops::index::Index<(core::ops::range::Bound, core::ops::range::Bound)> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::Script where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptBufDecoder where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::Script where T: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptBuf where T: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptBufDecoder where T: core::panic::unwind_safe::UnwindSafe +impl serde::ser::Serialize for bitcoin_primitives::script::Script +impl serde::ser::Serialize for bitcoin_primitives::script::ScriptBuf +impl bitcoin_primitives::block::Block +impl core::clone::Clone for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::clone::Clone +impl core::cmp::Eq for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::cmp::Eq +impl core::cmp::PartialEq for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::cmp::PartialEq +impl core::fmt::Debug for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::fmt::Debug +impl core::marker::Freeze for bitcoin_primitives::block::Block +impl core::marker::Send for bitcoin_primitives::block::Block +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation +impl core::marker::Sync for bitcoin_primitives::block::Block +impl core::marker::Unpin for bitcoin_primitives::block::Block +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Block where V: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Block where V: core::panic::unwind_safe::UnwindSafe +impl> core::cmp::PartialEq<&[T; N]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq<[T; N]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq for &[T; N] +impl> core::cmp::PartialEq for [T; N] +impl core::convert::From<&[&[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<[&[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<[[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[&[u8; N]]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[&[u8]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[[u8; N]]> for bitcoin_primitives::witness::Witness +impl core::convert::From<[&[u8]; N]> for bitcoin_primitives::witness::Witness +pub bitcoin_primitives::BlockHeader::bits: bitcoin_primitives::pow::CompactTarget +pub bitcoin_primitives::BlockHeader::merkle_root: bitcoin_primitives::TxMerkleNode +pub bitcoin_primitives::BlockHeader::nonce: u32 +pub bitcoin_primitives::BlockHeader::prev_blockhash: bitcoin_primitives::BlockHash +pub bitcoin_primitives::BlockHeader::time: bitcoin_units::time::encapsulate::BlockTime +pub bitcoin_primitives::BlockHeader::version: bitcoin_primitives::block::Version +pub bitcoin_primitives::OutPoint::txid: bitcoin_primitives::Txid +pub bitcoin_primitives::OutPoint::vout: u32 +pub bitcoin_primitives::Transaction::inputs: alloc::vec::Vec +pub bitcoin_primitives::Transaction::lock_time: bitcoin_units::locktime::absolute::LockTime +pub bitcoin_primitives::Transaction::outputs: alloc::vec::Vec +pub bitcoin_primitives::Transaction::version: bitcoin_primitives::transaction::Version +pub bitcoin_primitives::TxIn::previous_output: bitcoin_primitives::transaction::OutPoint +pub bitcoin_primitives::TxIn::script_sig: bitcoin_primitives::script::ScriptSigBuf +pub bitcoin_primitives::TxIn::sequence: bitcoin_units::sequence::Sequence +pub bitcoin_primitives::TxIn::witness: bitcoin_primitives::witness::Witness +pub bitcoin_primitives::TxOut::amount: bitcoin_units::amount::unsigned::encapsulate::Amount +pub bitcoin_primitives::TxOut::script_pubkey: bitcoin_primitives::script::ScriptPubKeyBuf +pub bitcoin_primitives::block::Header::bits: bitcoin_primitives::pow::CompactTarget +pub bitcoin_primitives::block::Header::merkle_root: bitcoin_primitives::TxMerkleNode +pub bitcoin_primitives::block::Header::nonce: u32 +pub bitcoin_primitives::block::Header::prev_blockhash: bitcoin_primitives::BlockHash +pub bitcoin_primitives::block::Header::time: bitcoin_units::time::encapsulate::BlockTime +pub bitcoin_primitives::block::Header::version: bitcoin_primitives::block::Version +pub bitcoin_primitives::block::HeaderDecoderError::Bits(bitcoin_primitives::pow::CompactTargetDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::MerkleRoot(bitcoin_primitives::transaction::TxMerkleNodeDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::Nonce(bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) +pub bitcoin_primitives::block::HeaderDecoderError::PrevBlockhash(bitcoin_primitives::block::BlockHashDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::Time(bitcoin_units::time::BlockTimeDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::Version(bitcoin_primitives::block::VersionDecoderError) +pub bitcoin_primitives::block::InvalidBlockError::InvalidCoinbase +pub bitcoin_primitives::block::InvalidBlockError::InvalidMerkleRoot +pub bitcoin_primitives::block::InvalidBlockError::InvalidWitnessCommitment +pub bitcoin_primitives::block::InvalidBlockError::NoTransactions +pub bitcoin_primitives::transaction::OutPoint::txid: bitcoin_primitives::Txid +pub bitcoin_primitives::transaction::OutPoint::vout: u32 +pub bitcoin_primitives::transaction::ParseOutPointError::Format +pub bitcoin_primitives::transaction::ParseOutPointError::TooLong +pub bitcoin_primitives::transaction::ParseOutPointError::Txid(hex_conservative::error::DecodeFixedLengthBytesError) +pub bitcoin_primitives::transaction::ParseOutPointError::Vout(bitcoin_units::parse_int::ParseIntError) +pub bitcoin_primitives::transaction::ParseOutPointError::VoutNotCanonical +pub bitcoin_primitives::transaction::Transaction::inputs: alloc::vec::Vec +pub bitcoin_primitives::transaction::Transaction::lock_time: bitcoin_units::locktime::absolute::LockTime +pub bitcoin_primitives::transaction::Transaction::outputs: alloc::vec::Vec +pub bitcoin_primitives::transaction::Transaction::version: bitcoin_primitives::transaction::Version +pub bitcoin_primitives::transaction::TxIn::previous_output: bitcoin_primitives::transaction::OutPoint +pub bitcoin_primitives::transaction::TxIn::script_sig: bitcoin_primitives::script::ScriptSigBuf +pub bitcoin_primitives::transaction::TxIn::sequence: bitcoin_units::sequence::Sequence +pub bitcoin_primitives::transaction::TxIn::witness: bitcoin_primitives::witness::Witness +pub bitcoin_primitives::transaction::TxOut::amount: bitcoin_units::amount::unsigned::encapsulate::Amount +pub bitcoin_primitives::transaction::TxOut::script_pubkey: bitcoin_primitives::script::ScriptPubKeyBuf +pub const bitcoin_primitives::BlockHash::GENESIS_PREVIOUS_BLOCK_HASH: Self +pub const bitcoin_primitives::BlockValidation::IS_CHECKED: bool +pub const bitcoin_primitives::Txid::COINBASE_PREVOUT: Self +pub const bitcoin_primitives::WitnessCommitment::GENESIS_PREVIOUS_BLOCK_HASH: Self +pub const bitcoin_primitives::Wtxid::COINBASE: Self +pub const bitcoin_primitives::block::Checked::IS_CHECKED: bool +pub const bitcoin_primitives::block::Header::SIZE: usize +pub const bitcoin_primitives::block::Unchecked::IS_CHECKED: bool +pub const bitcoin_primitives::block::Validation::IS_CHECKED: bool +pub const bitcoin_primitives::block::Version::NO_SOFT_FORK_SIGNALLING: Self +pub const bitcoin_primitives::block::Version::ONE: Self +pub const bitcoin_primitives::block::Version::TWO: Self +pub const bitcoin_primitives::script::MAX_REDEEM_SCRIPT_SIZE: usize +pub const bitcoin_primitives::script::MAX_WITNESS_SCRIPT_SIZE: usize +pub const bitcoin_primitives::transaction::OutPoint::COINBASE_PREVOUT: Self +pub const bitcoin_primitives::transaction::OutPoint::SIZE: usize +pub const bitcoin_primitives::transaction::Transaction::MAX_STANDARD_WEIGHT: bitcoin_units::weight::encapsulate::Weight +pub const bitcoin_primitives::transaction::TxIn::EMPTY_COINBASE: Self +pub const bitcoin_primitives::transaction::Version::ONE: Self +pub const bitcoin_primitives::transaction::Version::THREE: Self +pub const bitcoin_primitives::transaction::Version::TWO: Self +pub const fn bitcoin_primitives::BlockHash::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::BlockHash::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::BlockHash::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Ntxid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Ntxid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Ntxid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::TxMerkleNode::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::TxMerkleNode::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::TxMerkleNode::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Txid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Txid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Txid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::WitnessCommitment::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::WitnessCommitment::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::WitnessCommitment::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::WitnessMerkleNode::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::WitnessMerkleNode::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::WitnessMerkleNode::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Wtxid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Wtxid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Wtxid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::block::BlockHashDecoder::new() -> Self +pub const fn bitcoin_primitives::block::Version::from_consensus(v: i32) -> Self +pub const fn bitcoin_primitives::block::Version::to_consensus(self) -> i32 +pub const fn bitcoin_primitives::block::VersionDecoder::new() -> Self +pub const fn bitcoin_primitives::pow::CompactTarget::to_consensus(self) -> u32 +pub const fn bitcoin_primitives::pow::CompactTargetDecoder::new() -> Self +pub const fn bitcoin_primitives::script::Script::as_bytes(&self) -> &[u8] +pub const fn bitcoin_primitives::script::Script::from_bytes(bytes: &[u8]) -> &Self +pub const fn bitcoin_primitives::script::Script::is_empty(&self) -> bool +pub const fn bitcoin_primitives::script::Script::len(&self) -> usize +pub const fn bitcoin_primitives::script::Script::new() -> &'static Self +pub const fn bitcoin_primitives::script::ScriptBuf::from_bytes(bytes: alloc::vec::Vec) -> Self +pub const fn bitcoin_primitives::script::ScriptBuf::new() -> Self +pub const fn bitcoin_primitives::script::ScriptBufDecoder::new() -> Self +pub const fn bitcoin_primitives::script::ScriptHash::as_byte_array(&self) -> &[u8; 20] +pub const fn bitcoin_primitives::script::ScriptHash::from_byte_array(bytes: [u8; 20]) -> Self +pub const fn bitcoin_primitives::script::ScriptHash::to_byte_array(self) -> [u8; 20] +pub const fn bitcoin_primitives::script::WScriptHash::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::script::WScriptHash::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::script::WScriptHash::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::transaction::OutPointDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::TransactionDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::Version::is_standard(self) -> bool +pub const fn bitcoin_primitives::transaction::Version::maybe_non_standard(version: u32) -> Self +pub const fn bitcoin_primitives::transaction::Version::to_u32(self) -> u32 +pub const fn bitcoin_primitives::transaction::VersionDecoder::new() -> Self +pub const fn bitcoin_primitives::witness::Witness::len(&self) -> usize +pub const fn bitcoin_primitives::witness::Witness::new() -> Self +pub const fn bitcoin_primitives::witness::WitnessDecoder::new() -> Self +pub enum bitcoin_primitives::BlockChecked +pub enum bitcoin_primitives::BlockUnchecked +pub enum bitcoin_primitives::block::Checked +pub enum bitcoin_primitives::block::Unchecked +pub enum bitcoin_primitives::script::RedeemScriptTag +pub enum bitcoin_primitives::script::ScriptPubKeyTag +pub enum bitcoin_primitives::script::ScriptSigTag +pub enum bitcoin_primitives::script::TapScriptTag +pub enum bitcoin_primitives::script::WitnessScriptTag +pub extern crate bitcoin_primitives::hex +pub fn &'a bitcoin_primitives::script::Script::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn &'a bitcoin_primitives::witness::Witness::into_iter(self) -> Self::IntoIter +pub fn &'de bitcoin_primitives::script::Script::deserialize(deserializer: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn &[T; N]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn &[T]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn &bitcoin_primitives::script::Script::default() -> Self +pub fn [T; N]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn [T]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::borrow::Cow<'_, bitcoin_primitives::script::Script>::from(value: bitcoin_primitives::script::ScriptBuf) -> Self +pub fn alloc::borrow::Cow<'a, bitcoin_primitives::script::Script>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::boxed::Box<[T]>::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::boxed::Box>::from(v: bitcoin_primitives::script::ScriptBuf) -> Self +pub fn alloc::boxed::Box>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::boxed::Box>::from(value: alloc::borrow::Cow<'a, bitcoin_primitives::script::Script>) -> Self +pub fn alloc::rc::Rc<[T]>::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::rc::Rc>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::sync::Arc<[T]>::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::sync::Arc>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::vec::Vec::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::vec::Vec::from(v: bitcoin_primitives::script::ScriptBuf) -> Self +pub fn bitcoin_primitives::BlockHash::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::BlockHash::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::BlockHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::BlockHash::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::BlockHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::BlockHash::clone(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::BlockHash::cmp(&self, other: &bitcoin_primitives::BlockHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::BlockHash::decoder() -> Self::Decoder +pub fn bitcoin_primitives::BlockHash::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::BlockHash::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::BlockHash::eq(&self, other: &bitcoin_primitives::BlockHash) -> bool +pub fn bitcoin_primitives::BlockHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::BlockHash::from(block: &bitcoin_primitives::block::Block) -> Self +pub fn bitcoin_primitives::BlockHash::from(block: bitcoin_primitives::block::Block) -> Self +pub fn bitcoin_primitives::BlockHash::from(header: &bitcoin_primitives::block::Header) -> Self +pub fn bitcoin_primitives::BlockHash::from(header: bitcoin_primitives::block::Header) -> Self +pub fn bitcoin_primitives::BlockHash::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::BlockHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::BlockHash::partial_cmp(&self, other: &bitcoin_primitives::BlockHash) -> core::option::Option +pub fn bitcoin_primitives::BlockHash::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::Ntxid::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::Ntxid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Ntxid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Ntxid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Ntxid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Ntxid::clone(&self) -> bitcoin_primitives::Ntxid +pub fn bitcoin_primitives::Ntxid::cmp(&self, other: &bitcoin_primitives::Ntxid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Ntxid::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::Ntxid::eq(&self, other: &bitcoin_primitives::Ntxid) -> bool +pub fn bitcoin_primitives::Ntxid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Ntxid::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::Ntxid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Ntxid::partial_cmp(&self, other: &bitcoin_primitives::Ntxid) -> core::option::Option +pub fn bitcoin_primitives::Ntxid::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::TxMerkleNode::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::TxMerkleNode::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::TxMerkleNode::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::TxMerkleNode::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::TxMerkleNode::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::TxMerkleNode::calculate_root>(iter: I) -> core::option::Option +pub fn bitcoin_primitives::TxMerkleNode::clone(&self) -> bitcoin_primitives::TxMerkleNode +pub fn bitcoin_primitives::TxMerkleNode::cmp(&self, other: &bitcoin_primitives::TxMerkleNode) -> core::cmp::Ordering +pub fn bitcoin_primitives::TxMerkleNode::combine(&self, other: &Self) -> Self +pub fn bitcoin_primitives::TxMerkleNode::decoder() -> Self::Decoder +pub fn bitcoin_primitives::TxMerkleNode::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::TxMerkleNode::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::TxMerkleNode::eq(&self, other: &bitcoin_primitives::TxMerkleNode) -> bool +pub fn bitcoin_primitives::TxMerkleNode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::TxMerkleNode::from_leaf(leaf: bitcoin_primitives::Txid) -> Self +pub fn bitcoin_primitives::TxMerkleNode::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::TxMerkleNode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::TxMerkleNode::partial_cmp(&self, other: &bitcoin_primitives::TxMerkleNode) -> core::option::Option +pub fn bitcoin_primitives::TxMerkleNode::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::Txid::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::Txid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Txid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Txid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Txid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Txid::clone(&self) -> bitcoin_primitives::Txid +pub fn bitcoin_primitives::Txid::cmp(&self, other: &bitcoin_primitives::Txid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Txid::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::Txid::eq(&self, other: &bitcoin_primitives::Txid) -> bool +pub fn bitcoin_primitives::Txid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Txid::from(tx: &bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Txid::from(tx: bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Txid::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::Txid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Txid::partial_cmp(&self, other: &bitcoin_primitives::Txid) -> core::option::Option +pub fn bitcoin_primitives::Txid::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::WitnessCommitment::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::WitnessCommitment::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessCommitment::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessCommitment::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessCommitment::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessCommitment::clone(&self) -> bitcoin_primitives::WitnessCommitment +pub fn bitcoin_primitives::WitnessCommitment::cmp(&self, other: &bitcoin_primitives::WitnessCommitment) -> core::cmp::Ordering +pub fn bitcoin_primitives::WitnessCommitment::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::WitnessCommitment::eq(&self, other: &bitcoin_primitives::WitnessCommitment) -> bool +pub fn bitcoin_primitives::WitnessCommitment::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::WitnessCommitment::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::WitnessCommitment::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::WitnessCommitment::partial_cmp(&self, other: &bitcoin_primitives::WitnessCommitment) -> core::option::Option +pub fn bitcoin_primitives::WitnessCommitment::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::WitnessMerkleNode::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::WitnessMerkleNode::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessMerkleNode::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessMerkleNode::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessMerkleNode::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessMerkleNode::calculate_root>(iter: I) -> core::option::Option +pub fn bitcoin_primitives::WitnessMerkleNode::clone(&self) -> bitcoin_primitives::WitnessMerkleNode +pub fn bitcoin_primitives::WitnessMerkleNode::cmp(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> core::cmp::Ordering +pub fn bitcoin_primitives::WitnessMerkleNode::combine(&self, other: &Self) -> Self +pub fn bitcoin_primitives::WitnessMerkleNode::decoder() -> Self::Decoder +pub fn bitcoin_primitives::WitnessMerkleNode::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::WitnessMerkleNode::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::WitnessMerkleNode::eq(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> bool +pub fn bitcoin_primitives::WitnessMerkleNode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::WitnessMerkleNode::from_leaf(leaf: bitcoin_primitives::Wtxid) -> Self +pub fn bitcoin_primitives::WitnessMerkleNode::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::WitnessMerkleNode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::WitnessMerkleNode::partial_cmp(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> core::option::Option +pub fn bitcoin_primitives::WitnessMerkleNode::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::Wtxid::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::Wtxid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Wtxid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Wtxid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Wtxid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Wtxid::clone(&self) -> bitcoin_primitives::Wtxid +pub fn bitcoin_primitives::Wtxid::cmp(&self, other: &bitcoin_primitives::Wtxid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Wtxid::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::Wtxid::eq(&self, other: &bitcoin_primitives::Wtxid) -> bool +pub fn bitcoin_primitives::Wtxid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Wtxid::from(tx: &bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Wtxid::from(tx: bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Wtxid::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::Wtxid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Wtxid::partial_cmp(&self, other: &bitcoin_primitives::Wtxid) -> core::option::Option +pub fn bitcoin_primitives::Wtxid::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::block::Block::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::block::Block::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Block::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Block::block_hash(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::block::Block::clone(&self) -> bitcoin_primitives::block::Block +pub fn bitcoin_primitives::block::Block::eq(&self, other: &bitcoin_primitives::block::Block) -> bool +pub fn bitcoin_primitives::block::Block::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Block::cached_witness_root(&self) -> core::option::Option +pub fn bitcoin_primitives::block::Block::header(&self) -> &bitcoin_primitives::block::Header +pub fn bitcoin_primitives::block::Block::transactions(&self) -> &[bitcoin_primitives::transaction::Transaction] +pub fn bitcoin_primitives::block::Block::assume_checked(self, witness_root: core::option::Option) -> bitcoin_primitives::block::Block +pub fn bitcoin_primitives::block::Block::check_merkle_root(&self) -> bool +pub fn bitcoin_primitives::block::Block::check_witness_commitment(&self) -> (bool, core::option::Option) +pub fn bitcoin_primitives::block::Block::compute_witness_commitment(&self, witness_reserved_value: &[u8]) -> core::option::Option<(bitcoin_primitives::WitnessMerkleNode, bitcoin_primitives::WitnessCommitment)> +pub fn bitcoin_primitives::block::Block::into_parts(self) -> (bitcoin_primitives::block::Header, alloc::vec::Vec) +pub fn bitcoin_primitives::block::Block::new_unchecked(header: bitcoin_primitives::block::Header, transactions: alloc::vec::Vec) -> Self +pub fn bitcoin_primitives::block::Block::validate(self) -> core::result::Result, bitcoin_primitives::block::InvalidBlockError> +pub fn bitcoin_primitives::block::BlockDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::BlockDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::BlockDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::BlockDecoderError::clone(&self) -> bitcoin_primitives::block::BlockDecoderError +pub fn bitcoin_primitives::block::BlockDecoderError::eq(&self, other: &bitcoin_primitives::block::BlockDecoderError) -> bool +pub fn bitcoin_primitives::block::BlockDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::BlockDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::BlockDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::block::BlockEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::BlockEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::BlockHashDecoder::default() -> Self +pub fn bitcoin_primitives::block::BlockHashDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::BlockHashDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::BlockHashDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::BlockHashDecoderError::clone(&self) -> bitcoin_primitives::block::BlockHashDecoderError +pub fn bitcoin_primitives::block::BlockHashDecoderError::eq(&self, other: &bitcoin_primitives::block::BlockHashDecoderError) -> bool +pub fn bitcoin_primitives::block::BlockHashDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::BlockHashDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::block::BlockHashDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::BlockHashDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::block::BlockHashEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::BlockHashEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::Checked::clone(&self) -> bitcoin_primitives::block::Checked +pub fn bitcoin_primitives::block::Checked::cmp(&self, other: &bitcoin_primitives::block::Checked) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Checked::eq(&self, other: &bitcoin_primitives::block::Checked) -> bool +pub fn bitcoin_primitives::block::Checked::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Checked::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Checked::partial_cmp(&self, other: &bitcoin_primitives::block::Checked) -> core::option::Option +pub fn bitcoin_primitives::block::Header::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::block::Header::block_hash(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::block::Header::clone(&self) -> bitcoin_primitives::block::Header +pub fn bitcoin_primitives::block::Header::cmp(&self, other: &bitcoin_primitives::block::Header) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Header::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Header::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Header::eq(&self, other: &bitcoin_primitives::block::Header) -> bool +pub fn bitcoin_primitives::block::Header::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Header::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Header::partial_cmp(&self, other: &bitcoin_primitives::block::Header) -> core::option::Option +pub fn bitcoin_primitives::block::HeaderDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::HeaderDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::HeaderDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::HeaderDecoderError::clone(&self) -> bitcoin_primitives::block::HeaderDecoderError +pub fn bitcoin_primitives::block::HeaderDecoderError::eq(&self, other: &bitcoin_primitives::block::HeaderDecoderError) -> bool +pub fn bitcoin_primitives::block::HeaderDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::HeaderDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::HeaderDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::block::HeaderEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::HeaderEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::InvalidBlockError::clone(&self) -> bitcoin_primitives::block::InvalidBlockError +pub fn bitcoin_primitives::block::InvalidBlockError::eq(&self, other: &bitcoin_primitives::block::InvalidBlockError) -> bool +pub fn bitcoin_primitives::block::InvalidBlockError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::InvalidBlockError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::Unchecked::clone(&self) -> bitcoin_primitives::block::Unchecked +pub fn bitcoin_primitives::block::Unchecked::cmp(&self, other: &bitcoin_primitives::block::Unchecked) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Unchecked::eq(&self, other: &bitcoin_primitives::block::Unchecked) -> bool +pub fn bitcoin_primitives::block::Unchecked::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Unchecked::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Unchecked::partial_cmp(&self, other: &bitcoin_primitives::block::Unchecked) -> core::option::Option +pub fn bitcoin_primitives::block::Version::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::block::Version::clone(&self) -> bitcoin_primitives::block::Version +pub fn bitcoin_primitives::block::Version::cmp(&self, other: &bitcoin_primitives::block::Version) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Version::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Version::default() -> Self +pub fn bitcoin_primitives::block::Version::deserialize<__D>(__deserializer: __D) -> core::result::Result::Error> where __D: serde::de::Deserializer<'de> +pub fn bitcoin_primitives::block::Version::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Version::eq(&self, other: &bitcoin_primitives::block::Version) -> bool +pub fn bitcoin_primitives::block::Version::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Version::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Version::is_signalling_soft_fork(self, bit: u8) -> bool +pub fn bitcoin_primitives::block::Version::partial_cmp(&self, other: &bitcoin_primitives::block::Version) -> core::option::Option +pub fn bitcoin_primitives::block::Version::serialize<__S>(&self, __serializer: __S) -> core::result::Result<<__S as serde::ser::Serializer>::Ok, <__S as serde::ser::Serializer>::Error> where __S: serde::ser::Serializer +pub fn bitcoin_primitives::block::VersionDecoder::default() -> Self +pub fn bitcoin_primitives::block::VersionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::VersionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::VersionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::VersionDecoderError::clone(&self) -> bitcoin_primitives::block::VersionDecoderError +pub fn bitcoin_primitives::block::VersionDecoderError::eq(&self, other: &bitcoin_primitives::block::VersionDecoderError) -> bool +pub fn bitcoin_primitives::block::VersionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::VersionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::block::VersionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::VersionDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::block::VersionEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::VersionEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::compute_merkle_root(transactions: &[bitcoin_primitives::transaction::Transaction]) -> core::option::Option +pub fn bitcoin_primitives::block::compute_witness_root(transactions: &[bitcoin_primitives::transaction::Transaction]) -> core::option::Option +pub fn bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::pow::CompactTarget::clone(&self) -> bitcoin_primitives::pow::CompactTarget +pub fn bitcoin_primitives::pow::CompactTarget::cmp(&self, other: &bitcoin_primitives::pow::CompactTarget) -> core::cmp::Ordering +pub fn bitcoin_primitives::pow::CompactTarget::decoder() -> Self::Decoder +pub fn bitcoin_primitives::pow::CompactTarget::deserialize<__D>(__deserializer: __D) -> core::result::Result::Error> where __D: serde::de::Deserializer<'de> +pub fn bitcoin_primitives::pow::CompactTarget::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::pow::CompactTarget::eq(&self, other: &bitcoin_primitives::pow::CompactTarget) -> bool +pub fn bitcoin_primitives::pow::CompactTarget::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::pow::CompactTarget::from_consensus(bits: u32) -> Self +pub fn bitcoin_primitives::pow::CompactTarget::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::pow::CompactTarget::partial_cmp(&self, other: &bitcoin_primitives::pow::CompactTarget) -> core::option::Option +pub fn bitcoin_primitives::pow::CompactTarget::serialize<__S>(&self, __serializer: __S) -> core::result::Result<<__S as serde::ser::Serializer>::Ok, <__S as serde::ser::Serializer>::Error> where __S: serde::ser::Serializer +pub fn bitcoin_primitives::pow::CompactTarget::to_hex(self) -> alloc::string::String +pub fn bitcoin_primitives::pow::CompactTargetDecoder::default() -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::clone(&self) -> bitcoin_primitives::pow::CompactTargetDecoderError +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::eq(&self, other: &bitcoin_primitives::pow::CompactTargetDecoderError) -> bool +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::pow::CompactTargetEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::pow::CompactTargetEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::script::RedeemScriptSizeError::clone(&self) -> bitcoin_primitives::script::RedeemScriptSizeError +pub fn bitcoin_primitives::script::RedeemScriptSizeError::eq(&self, other: &bitcoin_primitives::script::RedeemScriptSizeError) -> bool +pub fn bitcoin_primitives::script::RedeemScriptSizeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::RedeemScriptSizeError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::script::RedeemScriptSizeError::invalid_size(&self) -> usize +pub fn bitcoin_primitives::script::RedeemScriptTag::clone(&self) -> bitcoin_primitives::script::RedeemScriptTag +pub fn bitcoin_primitives::script::RedeemScriptTag::cmp(&self, other: &bitcoin_primitives::script::RedeemScriptTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::RedeemScriptTag::eq(&self, other: &bitcoin_primitives::script::RedeemScriptTag) -> bool +pub fn bitcoin_primitives::script::RedeemScriptTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::RedeemScriptTag::partial_cmp(&self, other: &bitcoin_primitives::script::RedeemScriptTag) -> core::option::Option +pub fn bitcoin_primitives::script::Script::as_mut(&mut self) -> &mut Self +pub fn bitcoin_primitives::script::Script::as_mut(&mut self) -> &mut [u8] +pub fn bitcoin_primitives::script::Script::as_mut_bytes(&mut self) -> &mut [u8] +pub fn bitcoin_primitives::script::Script::as_ref(&self) -> &Self +pub fn bitcoin_primitives::script::Script::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::Script::cmp(&self, other: &bitcoin_primitives::script::Script) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::Script::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::script::Script::eq(&self, other: &bitcoin_primitives::script::Script) -> bool +pub fn bitcoin_primitives::script::Script::eq(&self, other: &bitcoin_primitives::script::ScriptBuf) -> bool +pub fn bitcoin_primitives::script::Script::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::Script::from_bytes_mut(bytes: &mut [u8]) -> &mut Self +pub fn bitcoin_primitives::script::Script::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::Script::index(&self, index: (core::ops::range::Bound, core::ops::range::Bound)) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::Range) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeFrom) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeFull) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeInclusive) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeTo) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeToInclusive) -> &Self::Output +pub fn bitcoin_primitives::script::Script::into_script_buf(self: alloc::boxed::Box) -> bitcoin_primitives::script::ScriptBuf +pub fn bitcoin_primitives::script::Script::partial_cmp(&self, other: &bitcoin_primitives::script::Script) -> core::option::Option +pub fn bitcoin_primitives::script::Script::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptBuf) -> core::option::Option +pub fn bitcoin_primitives::script::Script::serialize(&self, serializer: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_primitives::script::Script::to_bytes(&self) -> alloc::vec::Vec +pub fn bitcoin_primitives::script::Script::to_hex(&self) -> alloc::string::String +pub fn bitcoin_primitives::script::Script::to_owned(&self) -> Self::Owned +pub fn bitcoin_primitives::script::Script::to_vec(&self) -> alloc::vec::Vec +pub fn bitcoin_primitives::script::ScriptBuf::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::script::ScriptBuf::as_mut(&mut self) -> &mut [u8] +pub fn bitcoin_primitives::script::ScriptBuf::as_mut(&mut self) -> &mut bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::as_mut_script(&mut self) -> &mut bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptBuf::as_ref(&self) -> &bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::as_script(&self) -> &bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::borrow(&self) -> &bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::borrow_mut(&mut self) -> &mut bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::capacity(&self) -> usize +pub fn bitcoin_primitives::script::ScriptBuf::clone(&self) -> bitcoin_primitives::script::ScriptBuf +pub fn bitcoin_primitives::script::ScriptBuf::cmp(&self, other: &bitcoin_primitives::script::ScriptBuf) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptBuf::decoder() -> Self::Decoder +pub fn bitcoin_primitives::script::ScriptBuf::default() -> Self +pub fn bitcoin_primitives::script::ScriptBuf::deref(&self) -> &Self::Target +pub fn bitcoin_primitives::script::ScriptBuf::deref_mut(&mut self) -> &mut Self::Target +pub fn bitcoin_primitives::script::ScriptBuf::deserialize(deserializer: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_primitives::script::ScriptBuf::eq(&self, other: &bitcoin_primitives::script::Script) -> bool +pub fn bitcoin_primitives::script::ScriptBuf::eq(&self, other: &bitcoin_primitives::script::ScriptBuf) -> bool +pub fn bitcoin_primitives::script::ScriptBuf::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::ScriptBuf::from(v: alloc::vec::Vec) -> Self +pub fn bitcoin_primitives::script::ScriptBuf::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn bitcoin_primitives::script::ScriptBuf::from(value: alloc::borrow::Cow<'a, bitcoin_primitives::script::Script>) -> Self +pub fn bitcoin_primitives::script::ScriptBuf::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptBuf::into_boxed_script(self) -> alloc::boxed::Box> +pub fn bitcoin_primitives::script::ScriptBuf::into_bytes(self) -> alloc::vec::Vec +pub fn bitcoin_primitives::script::ScriptBuf::partial_cmp(&self, other: &bitcoin_primitives::script::Script) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptBuf::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptBuf) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptBuf::reserve(&mut self, additional_len: usize) +pub fn bitcoin_primitives::script::ScriptBuf::reserve_exact(&mut self, additional_len: usize) +pub fn bitcoin_primitives::script::ScriptBuf::serialize(&self, serializer: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_primitives::script::ScriptBuf::to_hex(&self) -> alloc::string::String +pub fn bitcoin_primitives::script::ScriptBuf::with_capacity(capacity: usize) -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoder::default() -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptBufDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptBufDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::script::ScriptBufDecoderError::clone(&self) -> bitcoin_primitives::script::ScriptBufDecoderError +pub fn bitcoin_primitives::script::ScriptBufDecoderError::eq(&self, other: &bitcoin_primitives::script::ScriptBufDecoderError) -> bool +pub fn bitcoin_primitives::script::ScriptBufDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::ScriptBufDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::ByteVecDecoderError) -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::script::ScriptEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::script::ScriptEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptHash::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::script::ScriptHash::as_ref(&self) -> &[u8; 20] +pub fn bitcoin_primitives::script::ScriptHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptHash::borrow(&self) -> &[u8; 20] +pub fn bitcoin_primitives::script::ScriptHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptHash::clone(&self) -> bitcoin_primitives::script::ScriptHash +pub fn bitcoin_primitives::script::ScriptHash::cmp(&self, other: &bitcoin_primitives::script::ScriptHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptHash::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::script::ScriptHash::eq(&self, other: &bitcoin_primitives::script::ScriptHash) -> bool +pub fn bitcoin_primitives::script::ScriptHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::ScriptHash::from_script(redeem_script: &bitcoin_primitives::script::Script) -> core::result::Result where T: bitcoin_primitives::script::ScriptHashableTag +pub fn bitcoin_primitives::script::ScriptHash::from_script_unchecked(script: &bitcoin_primitives::script::Script) -> Self +pub fn bitcoin_primitives::script::ScriptHash::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptHash::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptHash) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptHash::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::script::ScriptHash::try_from(redeem_script: &bitcoin_primitives::script::Script) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptHash::try_from(redeem_script: &bitcoin_primitives::script::ScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptHash::try_from(redeem_script: bitcoin_primitives::script::ScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptPubKeyTag::clone(&self) -> bitcoin_primitives::script::ScriptPubKeyTag +pub fn bitcoin_primitives::script::ScriptPubKeyTag::cmp(&self, other: &bitcoin_primitives::script::ScriptPubKeyTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptPubKeyTag::eq(&self, other: &bitcoin_primitives::script::ScriptPubKeyTag) -> bool +pub fn bitcoin_primitives::script::ScriptPubKeyTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptPubKeyTag::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptPubKeyTag) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptSigTag::clone(&self) -> bitcoin_primitives::script::ScriptSigTag +pub fn bitcoin_primitives::script::ScriptSigTag::cmp(&self, other: &bitcoin_primitives::script::ScriptSigTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptSigTag::eq(&self, other: &bitcoin_primitives::script::ScriptSigTag) -> bool +pub fn bitcoin_primitives::script::ScriptSigTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptSigTag::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptSigTag) -> core::option::Option +pub fn bitcoin_primitives::script::TapScriptTag::clone(&self) -> bitcoin_primitives::script::TapScriptTag +pub fn bitcoin_primitives::script::TapScriptTag::cmp(&self, other: &bitcoin_primitives::script::TapScriptTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::TapScriptTag::eq(&self, other: &bitcoin_primitives::script::TapScriptTag) -> bool +pub fn bitcoin_primitives::script::TapScriptTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::TapScriptTag::partial_cmp(&self, other: &bitcoin_primitives::script::TapScriptTag) -> core::option::Option +pub fn bitcoin_primitives::script::WScriptHash::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::script::WScriptHash::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::script::WScriptHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::WScriptHash::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::script::WScriptHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::script::WScriptHash::clone(&self) -> bitcoin_primitives::script::WScriptHash +pub fn bitcoin_primitives::script::WScriptHash::cmp(&self, other: &bitcoin_primitives::script::WScriptHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::WScriptHash::deserialize>(d: D) -> core::result::Result::Error> +pub fn bitcoin_primitives::script::WScriptHash::eq(&self, other: &bitcoin_primitives::script::WScriptHash) -> bool +pub fn bitcoin_primitives::script::WScriptHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::WScriptHash::from_script(witness_script: &bitcoin_primitives::script::WitnessScript) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::from_script_unchecked(script: &bitcoin_primitives::script::WitnessScript) -> Self +pub fn bitcoin_primitives::script::WScriptHash::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::WScriptHash::partial_cmp(&self, other: &bitcoin_primitives::script::WScriptHash) -> core::option::Option +pub fn bitcoin_primitives::script::WScriptHash::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_primitives::script::WScriptHash::try_from(witness_script: &bitcoin_primitives::script::WitnessScript) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::try_from(witness_script: &bitcoin_primitives::script::WitnessScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::try_from(witness_script: bitcoin_primitives::script::WitnessScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::WitnessScriptSizeError::clone(&self) -> bitcoin_primitives::script::WitnessScriptSizeError +pub fn bitcoin_primitives::script::WitnessScriptSizeError::eq(&self, other: &bitcoin_primitives::script::WitnessScriptSizeError) -> bool +pub fn bitcoin_primitives::script::WitnessScriptSizeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::WitnessScriptSizeError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::script::WitnessScriptSizeError::invalid_size(&self) -> usize +pub fn bitcoin_primitives::script::WitnessScriptTag::clone(&self) -> bitcoin_primitives::script::WitnessScriptTag +pub fn bitcoin_primitives::script::WitnessScriptTag::cmp(&self, other: &bitcoin_primitives::script::WitnessScriptTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::WitnessScriptTag::eq(&self, other: &bitcoin_primitives::script::WitnessScriptTag) -> bool +pub fn bitcoin_primitives::script::WitnessScriptTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::WitnessScriptTag::partial_cmp(&self, other: &bitcoin_primitives::script::WitnessScriptTag) -> core::option::Option +pub fn bitcoin_primitives::transaction::OutPoint::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::transaction::OutPoint::clone(&self) -> bitcoin_primitives::transaction::OutPoint +pub fn bitcoin_primitives::transaction::OutPoint::cmp(&self, other: &bitcoin_primitives::transaction::OutPoint) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::OutPoint::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::OutPoint::deserialize(deserializer: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_primitives::transaction::OutPoint::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::OutPoint::eq(&self, other: &bitcoin_primitives::transaction::OutPoint) -> bool +pub fn bitcoin_primitives::transaction::OutPoint::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::OutPoint::from_str(s: &str) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPoint::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::OutPoint::partial_cmp(&self, other: &bitcoin_primitives::transaction::OutPoint) -> core::option::Option +pub fn bitcoin_primitives::transaction::OutPoint::serialize(&self, serializer: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_primitives::transaction::OutPointDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::OutPointDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPointDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPointDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::OutPointDecoderError::clone(&self) -> bitcoin_primitives::transaction::OutPointDecoderError +pub fn bitcoin_primitives::transaction::OutPointDecoderError::eq(&self, other: &bitcoin_primitives::transaction::OutPointDecoderError) -> bool +pub fn bitcoin_primitives::transaction::OutPointDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::OutPointDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::OutPointEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::OutPointEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::ParseOutPointError::clone(&self) -> bitcoin_primitives::transaction::ParseOutPointError +pub fn bitcoin_primitives::transaction::ParseOutPointError::eq(&self, other: &bitcoin_primitives::transaction::ParseOutPointError) -> bool +pub fn bitcoin_primitives::transaction::ParseOutPointError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::ParseOutPointError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::ParseOutPointError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::Transaction::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::transaction::Transaction::clone(&self) -> bitcoin_primitives::transaction::Transaction +pub fn bitcoin_primitives::transaction::Transaction::cmp(&self, other: &Self) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::Transaction::compute_ntxid(&self) -> bitcoin_primitives::Ntxid +pub fn bitcoin_primitives::transaction::Transaction::compute_txid(&self) -> bitcoin_primitives::Txid +pub fn bitcoin_primitives::transaction::Transaction::compute_wtxid(&self) -> bitcoin_primitives::Wtxid +pub fn bitcoin_primitives::transaction::Transaction::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::Transaction::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::Transaction::eq(&self, other: &bitcoin_primitives::transaction::Transaction) -> bool +pub fn bitcoin_primitives::transaction::Transaction::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::Transaction::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::Transaction::is_coinbase(&self) -> bool +pub fn bitcoin_primitives::transaction::Transaction::partial_cmp(&self, other: &Self) -> core::option::Option +pub fn bitcoin_primitives::transaction::TransactionDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TransactionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TransactionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TransactionDecoderError::clone(&self) -> bitcoin_primitives::transaction::TransactionDecoderError +pub fn bitcoin_primitives::transaction::TransactionDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TransactionDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TransactionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::VecDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::VecDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_primitives::transaction::VersionDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_primitives::witness::WitnessDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_units::locktime::absolute::error::LockTimeDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::TransactionEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::TransactionEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::TxIn::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::transaction::TxIn::clone(&self) -> bitcoin_primitives::transaction::TxIn +pub fn bitcoin_primitives::transaction::TxIn::cmp(&self, other: &bitcoin_primitives::transaction::TxIn) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::TxIn::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::TxIn::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::TxIn::eq(&self, other: &bitcoin_primitives::transaction::TxIn) -> bool +pub fn bitcoin_primitives::transaction::TxIn::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxIn::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::TxIn::partial_cmp(&self, other: &bitcoin_primitives::transaction::TxIn) -> core::option::Option +pub fn bitcoin_primitives::transaction::TxInDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxInDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxInDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxInDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxInDecoderError +pub fn bitcoin_primitives::transaction::TxInDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxInDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxInDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxInDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TxInDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::TxInEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::TxInEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxMerkleNodeDecoderError +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxMerkleNodeDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::TxOut::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::transaction::TxOut::clone(&self) -> bitcoin_primitives::transaction::TxOut +pub fn bitcoin_primitives::transaction::TxOut::cmp(&self, other: &bitcoin_primitives::transaction::TxOut) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::TxOut::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::TxOut::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::TxOut::eq(&self, other: &bitcoin_primitives::transaction::TxOut) -> bool +pub fn bitcoin_primitives::transaction::TxOut::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxOut::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::TxOut::partial_cmp(&self, other: &bitcoin_primitives::transaction::TxOut) -> core::option::Option +pub fn bitcoin_primitives::transaction::TxOutDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxOutDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxOutDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxOutDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxOutDecoderError +pub fn bitcoin_primitives::transaction::TxOutDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxOutDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxOutDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxOutDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TxOutDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::TxOutEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::TxOutEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::Version::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::transaction::Version::clone(&self) -> bitcoin_primitives::transaction::Version +pub fn bitcoin_primitives::transaction::Version::cmp(&self, other: &bitcoin_primitives::transaction::Version) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::Version::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::Version::deserialize<__D>(__deserializer: __D) -> core::result::Result::Error> where __D: serde::de::Deserializer<'de> +pub fn bitcoin_primitives::transaction::Version::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::Version::eq(&self, other: &bitcoin_primitives::transaction::Version) -> bool +pub fn bitcoin_primitives::transaction::Version::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::Version::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::Version::partial_cmp(&self, other: &bitcoin_primitives::transaction::Version) -> core::option::Option +pub fn bitcoin_primitives::transaction::Version::serialize<__S>(&self, __serializer: __S) -> core::result::Result<<__S as serde::ser::Serializer>::Ok, <__S as serde::ser::Serializer>::Error> where __S: serde::ser::Serializer +pub fn bitcoin_primitives::transaction::VersionDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::VersionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::VersionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::VersionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::VersionDecoderError::clone(&self) -> bitcoin_primitives::transaction::VersionDecoderError +pub fn bitcoin_primitives::transaction::VersionDecoderError::eq(&self, other: &bitcoin_primitives::transaction::VersionDecoderError) -> bool +pub fn bitcoin_primitives::transaction::VersionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::VersionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::VersionDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::transaction::VersionEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::VersionEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::new(inputs: &'e [bitcoin_primitives::transaction::TxIn]) -> Self +pub fn bitcoin_primitives::witness::Iter<'a>::clone(&self) -> bitcoin_primitives::witness::Iter<'a> +pub fn bitcoin_primitives::witness::Iter<'a>::next(&mut self) -> core::option::Option +pub fn bitcoin_primitives::witness::Iter<'a>::size_hint(&self) -> (usize, core::option::Option) +pub fn bitcoin_primitives::witness::UnexpectedEofError::clone(&self) -> bitcoin_primitives::witness::UnexpectedEofError +pub fn bitcoin_primitives::witness::UnexpectedEofError::eq(&self, other: &bitcoin_primitives::witness::UnexpectedEofError) -> bool +pub fn bitcoin_primitives::witness::UnexpectedEofError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::witness::Witness::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_primitives::witness::Witness::clear(&mut self) +pub fn bitcoin_primitives::witness::Witness::clone(&self) -> bitcoin_primitives::witness::Witness +pub fn bitcoin_primitives::witness::Witness::cmp(&self, other: &bitcoin_primitives::witness::Witness) -> core::cmp::Ordering +pub fn bitcoin_primitives::witness::Witness::decoder() -> Self::Decoder +pub fn bitcoin_primitives::witness::Witness::default() -> Self +pub fn bitcoin_primitives::witness::Witness::deserialize(deserializer: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_primitives::witness::Witness::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::witness::Witness::eq(&self, other: &bitcoin_primitives::witness::Witness) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &&[T; N]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &&[T]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &[T; N]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &[T]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::boxed::Box<[T]>) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::rc::Rc<[T]>) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::sync::Arc<[T]>) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::vec::Vec) -> bool +pub fn bitcoin_primitives::witness::Witness::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::witness::Witness::from(arr: &[&[u8]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(arr: [&[u8]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[&[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[&[u8; N]]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[&[u8]]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[[u8; N]]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[alloc::vec::Vec]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: [&[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: [[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(vec: alloc::vec::Vec<&[u8]>) -> Self +pub fn bitcoin_primitives::witness::Witness::from(vec: alloc::vec::Vec>) -> Self +pub fn bitcoin_primitives::witness::Witness::from_hex(iter: I) -> core::result::Result where I: core::iter::traits::collect::IntoIterator, T: core::convert::AsRef +pub fn bitcoin_primitives::witness::Witness::from_iter>(iter: I) -> Self +pub fn bitcoin_primitives::witness::Witness::from_slice>(slice: &[T]) -> Self +pub fn bitcoin_primitives::witness::Witness::get(&self, index: usize) -> core::option::Option<&[u8]> +pub fn bitcoin_primitives::witness::Witness::get_back(&self, index: usize) -> core::option::Option<&[u8]> +pub fn bitcoin_primitives::witness::Witness::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::witness::Witness::index(&self, index: usize) -> &Self::Output +pub fn bitcoin_primitives::witness::Witness::is_empty(&self) -> bool +pub fn bitcoin_primitives::witness::Witness::iter(&self) -> bitcoin_primitives::witness::Iter<'_> +pub fn bitcoin_primitives::witness::Witness::last(&self) -> core::option::Option<&[u8]> +pub fn bitcoin_primitives::witness::Witness::partial_cmp(&self, other: &bitcoin_primitives::witness::Witness) -> core::option::Option +pub fn bitcoin_primitives::witness::Witness::push>(&mut self, new_element: T) +pub fn bitcoin_primitives::witness::Witness::serialize(&self, serializer: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_primitives::witness::Witness::size(&self) -> usize +pub fn bitcoin_primitives::witness::Witness::to_vec(&self) -> alloc::vec::Vec> +pub fn bitcoin_primitives::witness::WitnessDecoder::default() -> Self +pub fn bitcoin_primitives::witness::WitnessDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::witness::WitnessDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::witness::WitnessDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::witness::WitnessDecoderError::clone(&self) -> bitcoin_primitives::witness::WitnessDecoderError +pub fn bitcoin_primitives::witness::WitnessDecoderError::eq(&self, other: &bitcoin_primitives::witness::WitnessDecoderError) -> bool +pub fn bitcoin_primitives::witness::WitnessDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::witness::WitnessDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::witness::WitnessDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_primitives::witness::WitnessEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_primitives::witness::WitnessEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn u32::from(version: bitcoin_primitives::transaction::Version) -> Self +pub mod bitcoin_primitives +pub mod bitcoin_primitives::block +pub mod bitcoin_primitives::merkle_tree +pub mod bitcoin_primitives::pow +pub mod bitcoin_primitives::script +pub mod bitcoin_primitives::transaction +pub mod bitcoin_primitives::witness +pub struct bitcoin_primitives::Block where V: bitcoin_primitives::block::Validation +pub struct bitcoin_primitives::BlockHash(_) +pub struct bitcoin_primitives::BlockHeader +pub struct bitcoin_primitives::BlockVersion(_) +pub struct bitcoin_primitives::CompactTarget(_) +pub struct bitcoin_primitives::Ntxid(_) +pub struct bitcoin_primitives::OutPoint +pub struct bitcoin_primitives::Transaction +pub struct bitcoin_primitives::TransactionVersion(_) +pub struct bitcoin_primitives::TxIn +pub struct bitcoin_primitives::TxMerkleNode(_) +pub struct bitcoin_primitives::TxOut +pub struct bitcoin_primitives::Txid(_) +pub struct bitcoin_primitives::Witness +pub struct bitcoin_primitives::WitnessCommitment(_) +pub struct bitcoin_primitives::WitnessMerkleNode(_) +pub struct bitcoin_primitives::Wtxid(_) +pub struct bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation +pub struct bitcoin_primitives::block::BlockDecoder(_) +pub struct bitcoin_primitives::block::BlockDecoderError(_) +pub struct bitcoin_primitives::block::BlockEncoder<'e>(_) +pub struct bitcoin_primitives::block::BlockHash(_) +pub struct bitcoin_primitives::block::BlockHashDecoder(_) +pub struct bitcoin_primitives::block::BlockHashDecoderError(_) +pub struct bitcoin_primitives::block::BlockHashEncoder(_) +pub struct bitcoin_primitives::block::Header +pub struct bitcoin_primitives::block::HeaderDecoder(_) +pub struct bitcoin_primitives::block::HeaderEncoder(_) +pub struct bitcoin_primitives::block::Version(_) +pub struct bitcoin_primitives::block::VersionDecoder(_) +pub struct bitcoin_primitives::block::VersionDecoderError(_) +pub struct bitcoin_primitives::block::VersionEncoder(_) +pub struct bitcoin_primitives::block::WitnessCommitment(_) +pub struct bitcoin_primitives::merkle_tree::TxMerkleNode(_) +pub struct bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder(_) +pub struct bitcoin_primitives::merkle_tree::WitnessMerkleNode(_) +pub struct bitcoin_primitives::pow::CompactTarget(_) +pub struct bitcoin_primitives::pow::CompactTargetDecoder(_) +pub struct bitcoin_primitives::pow::CompactTargetDecoderError(_) +pub struct bitcoin_primitives::pow::CompactTargetEncoder(_) +pub struct bitcoin_primitives::script::RedeemScriptSizeError +pub struct bitcoin_primitives::script::ScriptBuf(_, _) +pub struct bitcoin_primitives::script::ScriptBufDecoder(_, _) +pub struct bitcoin_primitives::script::ScriptBufDecoderError(_) +pub struct bitcoin_primitives::script::ScriptEncoder<'e>(_) +pub struct bitcoin_primitives::script::ScriptHash(_) +pub struct bitcoin_primitives::script::WScriptHash(_) +pub struct bitcoin_primitives::script::WitnessScriptSizeError +pub struct bitcoin_primitives::transaction::BlockHashDecoder(_) +pub struct bitcoin_primitives::transaction::BlockHashDecoderError(_) +pub struct bitcoin_primitives::transaction::Ntxid(_) +pub struct bitcoin_primitives::transaction::OutPoint +pub struct bitcoin_primitives::transaction::OutPointDecoder(_) +pub struct bitcoin_primitives::transaction::OutPointDecoderError(_) +pub struct bitcoin_primitives::transaction::OutPointEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::Transaction +pub struct bitcoin_primitives::transaction::TransactionDecoder +pub struct bitcoin_primitives::transaction::TransactionDecoderError(_) +pub struct bitcoin_primitives::transaction::TransactionEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::TxIn +pub struct bitcoin_primitives::transaction::TxInDecoder(_) +pub struct bitcoin_primitives::transaction::TxInDecoderError(_) +pub struct bitcoin_primitives::transaction::TxInEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::TxMerkleNodeDecoder(_) +pub struct bitcoin_primitives::transaction::TxMerkleNodeDecoderError(_) +pub struct bitcoin_primitives::transaction::TxOut +pub struct bitcoin_primitives::transaction::TxOutDecoder(_) +pub struct bitcoin_primitives::transaction::TxOutDecoderError(_) +pub struct bitcoin_primitives::transaction::TxOutEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::Txid(_) +pub struct bitcoin_primitives::transaction::Version(_) +pub struct bitcoin_primitives::transaction::VersionDecoder(_) +pub struct bitcoin_primitives::transaction::VersionDecoderError(_) +pub struct bitcoin_primitives::transaction::VersionEncoder(_) +pub struct bitcoin_primitives::transaction::WitnessesEncoder<'e> +pub struct bitcoin_primitives::transaction::Wtxid(_) +pub struct bitcoin_primitives::witness::Iter<'a> +pub struct bitcoin_primitives::witness::UnexpectedEofError +pub struct bitcoin_primitives::witness::Witness +pub struct bitcoin_primitives::witness::WitnessDecoder +pub struct bitcoin_primitives::witness::WitnessDecoderError(_) +pub struct bitcoin_primitives::witness::WitnessEncoder<'a>(_) +pub trait bitcoin_primitives::BlockValidation: bitcoin_primitives::block::sealed::Validation + core::marker::Sync + core::marker::Send + core::marker::Sized + core::marker::Unpin +pub trait bitcoin_primitives::block::Validation: bitcoin_primitives::block::sealed::Validation + core::marker::Sync + core::marker::Send + core::marker::Sized + core::marker::Unpin +pub trait bitcoin_primitives::script::ScriptHashableTag: bitcoin_primitives::script::sealed::Sealed +pub trait bitcoin_primitives::script::Tag +pub type &'a bitcoin_primitives::witness::Witness::IntoIter = bitcoin_primitives::witness::Iter<'a> +pub type &'a bitcoin_primitives::witness::Witness::Item = &'a [u8] +pub type bitcoin_primitives::BlockHash::Decoder = bitcoin_primitives::block::BlockHashDecoder +pub type bitcoin_primitives::BlockHash::Encoder<'e> = bitcoin_primitives::block::BlockHashEncoder +pub type bitcoin_primitives::BlockHash::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::Ntxid::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::RedeemScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::RedeemScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::ScriptPubKey = bitcoin_primitives::script::Script +pub type bitcoin_primitives::ScriptPubKeyBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::ScriptSig = bitcoin_primitives::script::Script +pub type bitcoin_primitives::ScriptSigBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::TapScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::TapScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::TxMerkleNode::Decoder = bitcoin_primitives::transaction::TxMerkleNodeDecoder +pub type bitcoin_primitives::TxMerkleNode::Encoder<'e> = bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +pub type bitcoin_primitives::TxMerkleNode::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::Txid::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::WitnessCommitment::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::WitnessMerkleNode::Decoder = bitcoin_primitives::hash_types::witness_merkle_node::WitnessMerkleNodeDecoder +pub type bitcoin_primitives::WitnessMerkleNode::Encoder<'e> = bitcoin_primitives::hash_types::witness_merkle_node::WitnessMerkleNodeEncoder +pub type bitcoin_primitives::WitnessMerkleNode::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::WitnessScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::WitnessScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::Wtxid::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::block::Block::Decoder = bitcoin_primitives::block::BlockDecoder +pub type bitcoin_primitives::block::Block::Encoder<'e> where Self: 'e = bitcoin_consensus_encoding::encode::encoders::Encoder2>> +pub type bitcoin_primitives::block::BlockDecoder::Error = bitcoin_primitives::block::BlockDecoderError +pub type bitcoin_primitives::block::BlockDecoder::Output = bitcoin_primitives::block::Block +pub type bitcoin_primitives::block::BlockHashDecoder::Error = bitcoin_primitives::block::BlockHashDecoderError +pub type bitcoin_primitives::block::BlockHashDecoder::Output = bitcoin_primitives::BlockHash +pub type bitcoin_primitives::block::Header::Decoder = bitcoin_primitives::block::HeaderDecoder +pub type bitcoin_primitives::block::Header::Encoder<'e> = bitcoin_primitives::block::HeaderEncoder +pub type bitcoin_primitives::block::HeaderDecoder::Error = bitcoin_primitives::block::HeaderDecoderError +pub type bitcoin_primitives::block::HeaderDecoder::Output = bitcoin_primitives::block::Header +pub type bitcoin_primitives::block::Version::Decoder = bitcoin_primitives::block::VersionDecoder +pub type bitcoin_primitives::block::Version::Encoder<'e> = bitcoin_primitives::block::VersionEncoder +pub type bitcoin_primitives::block::VersionDecoder::Error = bitcoin_primitives::block::VersionDecoderError +pub type bitcoin_primitives::block::VersionDecoder::Output = bitcoin_primitives::block::Version +pub type bitcoin_primitives::pow::CompactTarget::Decoder = bitcoin_primitives::pow::CompactTargetDecoder +pub type bitcoin_primitives::pow::CompactTarget::Encoder<'e> = bitcoin_primitives::pow::CompactTargetEncoder +pub type bitcoin_primitives::pow::CompactTargetDecoder::Error = bitcoin_primitives::pow::CompactTargetDecoderError +pub type bitcoin_primitives::pow::CompactTargetDecoder::Output = bitcoin_primitives::pow::CompactTarget +pub type bitcoin_primitives::script::RedeemScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::RedeemScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::Script::Encoder<'a> where Self: 'a = bitcoin_primitives::script::ScriptEncoder<'a> +pub type bitcoin_primitives::script::Script::Output = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::Script::Owned = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptBuf::Decoder = bitcoin_primitives::script::ScriptBufDecoder +pub type bitcoin_primitives::script::ScriptBuf::Target = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::ScriptBufDecoder::Error = bitcoin_primitives::script::ScriptBufDecoderError +pub type bitcoin_primitives::script::ScriptBufDecoder::Output = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptHash::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::script::ScriptHash::Error = bitcoin_primitives::script::RedeemScriptSizeError +pub type bitcoin_primitives::script::ScriptPubKey = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::ScriptPubKeyBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptPubKeyBufDecoder = bitcoin_primitives::script::ScriptBufDecoder +pub type bitcoin_primitives::script::ScriptSig = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::ScriptSigBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptSigBufDecoder = bitcoin_primitives::script::ScriptBufDecoder +pub type bitcoin_primitives::script::TapScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::TapScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::WScriptHash::Err = hex_conservative::error::DecodeFixedLengthBytesError +pub type bitcoin_primitives::script::WScriptHash::Error = bitcoin_primitives::script::WitnessScriptSizeError +pub type bitcoin_primitives::script::WitnessScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::WitnessScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::transaction::OutPoint::Decoder = bitcoin_primitives::transaction::OutPointDecoder +pub type bitcoin_primitives::transaction::OutPoint::Encoder<'e> where Self: 'e = bitcoin_primitives::transaction::OutPointEncoder<'e> +pub type bitcoin_primitives::transaction::OutPoint::Err = bitcoin_primitives::transaction::ParseOutPointError +pub type bitcoin_primitives::transaction::OutPointDecoder::Error = bitcoin_primitives::transaction::OutPointDecoderError +pub type bitcoin_primitives::transaction::OutPointDecoder::Output = bitcoin_primitives::transaction::OutPoint +pub type bitcoin_primitives::transaction::Transaction::Decoder = bitcoin_primitives::transaction::TransactionDecoder +pub type bitcoin_primitives::transaction::Transaction::Encoder<'e> where Self: 'e = bitcoin_primitives::transaction::TransactionEncoder<'e> +pub type bitcoin_primitives::transaction::TransactionDecoder::Error = bitcoin_primitives::transaction::TransactionDecoderError +pub type bitcoin_primitives::transaction::TransactionDecoder::Output = bitcoin_primitives::transaction::Transaction +pub type bitcoin_primitives::transaction::TxIn::Decoder = bitcoin_primitives::transaction::TxInDecoder +pub type bitcoin_primitives::transaction::TxIn::Encoder<'e> where Self: 'e = bitcoin_consensus_encoding::encode::encoders::Encoder3, bitcoin_primitives::script::ScriptEncoder<'e>, bitcoin_units::sequence::SequenceEncoder> +pub type bitcoin_primitives::transaction::TxInDecoder::Error = bitcoin_primitives::transaction::TxInDecoderError +pub type bitcoin_primitives::transaction::TxInDecoder::Output = bitcoin_primitives::transaction::TxIn +pub type bitcoin_primitives::transaction::TxMerkleNodeDecoder::Error = bitcoin_primitives::transaction::TxMerkleNodeDecoderError +pub type bitcoin_primitives::transaction::TxMerkleNodeDecoder::Output = bitcoin_primitives::TxMerkleNode +pub type bitcoin_primitives::transaction::TxOut::Decoder = bitcoin_primitives::transaction::TxOutDecoder +pub type bitcoin_primitives::transaction::TxOut::Encoder<'e> where Self: 'e = bitcoin_consensus_encoding::encode::encoders::Encoder2> +pub type bitcoin_primitives::transaction::TxOutDecoder::Error = bitcoin_primitives::transaction::TxOutDecoderError +pub type bitcoin_primitives::transaction::TxOutDecoder::Output = bitcoin_primitives::transaction::TxOut +pub type bitcoin_primitives::transaction::Version::Decoder = bitcoin_primitives::transaction::VersionDecoder +pub type bitcoin_primitives::transaction::Version::Encoder<'e> = bitcoin_primitives::transaction::VersionEncoder +pub type bitcoin_primitives::transaction::VersionDecoder::Error = bitcoin_primitives::transaction::VersionDecoderError +pub type bitcoin_primitives::transaction::VersionDecoder::Output = bitcoin_primitives::transaction::Version +pub type bitcoin_primitives::witness::Iter<'a>::Item = &'a [u8] +pub type bitcoin_primitives::witness::Witness::Decoder = bitcoin_primitives::witness::WitnessDecoder +pub type bitcoin_primitives::witness::Witness::Encoder<'a> where Self: 'a = bitcoin_primitives::witness::WitnessEncoder<'a> +pub type bitcoin_primitives::witness::Witness::Output = [u8] +pub type bitcoin_primitives::witness::WitnessDecoder::Error = bitcoin_primitives::witness::WitnessDecoderError +pub type bitcoin_primitives::witness::WitnessDecoder::Output = bitcoin_primitives::witness::Witness +pub use bitcoin_primitives::Amount +pub use bitcoin_primitives::BlockHeight +pub use bitcoin_primitives::BlockHeightInterval +pub use bitcoin_primitives::BlockMtp +pub use bitcoin_primitives::BlockMtpInterval +pub use bitcoin_primitives::BlockTime +pub use bitcoin_primitives::BlockTimeDecoder +pub use bitcoin_primitives::BlockTimeDecoderError +pub use bitcoin_primitives::FeeRate +pub use bitcoin_primitives::NumOpResult +pub use bitcoin_primitives::Sequence +pub use bitcoin_primitives::SignedAmount +pub use bitcoin_primitives::Weight +pub use bitcoin_primitives::absolute +pub use bitcoin_primitives::amount +pub use bitcoin_primitives::block::BlockHeight +pub use bitcoin_primitives::block::BlockHeightDecoder +pub use bitcoin_primitives::block::BlockHeightDecoderError +pub use bitcoin_primitives::block::BlockHeightEncoder +pub use bitcoin_primitives::block::BlockHeightInterval +pub use bitcoin_primitives::block::BlockMtp +pub use bitcoin_primitives::block::BlockMtpInterval +pub use bitcoin_primitives::block::TooBigForRelativeHeightError +pub use bitcoin_primitives::fee_rate +pub use bitcoin_primitives::locktime +pub use bitcoin_primitives::parse_int +pub use bitcoin_primitives::relative +pub use bitcoin_primitives::result +pub use bitcoin_primitives::sequence +pub use bitcoin_primitives::time +pub use bitcoin_primitives::weight diff --git a/api/primitives/alloc-only.txt b/api/primitives/alloc-only.txt new file mode 100644 index 000000000..dc3dc482c --- /dev/null +++ b/api/primitives/alloc-only.txt @@ -0,0 +1,1890 @@ +#[non_exhaustive] pub enum bitcoin_primitives::block::HeaderDecoderError +#[non_exhaustive] pub enum bitcoin_primitives::block::InvalidBlockError +#[repr(transparent)] pub struct bitcoin_primitives::script::Script(_, _) +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::BlockHash +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::TxMerkleNode +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::WitnessMerkleNode +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Block +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Header +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Version +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::pow::CompactTarget +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::OutPoint +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::Transaction +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::TxIn +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::TxOut +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::Version +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::witness::Witness +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::BlockDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::BlockHashDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::HeaderDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::VersionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::pow::CompactTargetDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::OutPointDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TransactionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxInDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxOutDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::VersionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::witness::WitnessDecoder +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::BlockHash +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::TxMerkleNode +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::WitnessMerkleNode +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Block +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Header +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Version +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::pow::CompactTarget +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::OutPoint +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::Transaction +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::TxIn +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::TxOut +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::Version +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::witness::Witness +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::BlockHashEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::HeaderEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::VersionEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::pow::CompactTargetEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::VersionEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_> +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::witness::WitnessEncoder<'_> +impl bitcoin_primitives::BlockHash +impl bitcoin_primitives::Ntxid +impl bitcoin_primitives::TxMerkleNode +impl bitcoin_primitives::Txid +impl bitcoin_primitives::WitnessCommitment +impl bitcoin_primitives::WitnessMerkleNode +impl bitcoin_primitives::Wtxid +impl bitcoin_primitives::block::Block +impl bitcoin_primitives::block::Block +impl bitcoin_primitives::block::BlockHashDecoder +impl bitcoin_primitives::block::Header +impl bitcoin_primitives::block::Validation for bitcoin_primitives::block::Checked +impl bitcoin_primitives::block::Validation for bitcoin_primitives::block::Unchecked +impl bitcoin_primitives::block::Version +impl bitcoin_primitives::block::VersionDecoder +impl bitcoin_primitives::pow::CompactTarget +impl bitcoin_primitives::pow::CompactTargetDecoder +impl bitcoin_primitives::script::RedeemScriptSizeError +impl bitcoin_primitives::script::ScriptHash +impl bitcoin_primitives::script::ScriptHashableTag for bitcoin_primitives::script::RedeemScriptTag +impl bitcoin_primitives::script::ScriptHashableTag for bitcoin_primitives::script::ScriptPubKeyTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::RedeemScriptTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::ScriptPubKeyTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::ScriptSigTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::TapScriptTag +impl bitcoin_primitives::script::Tag for bitcoin_primitives::script::WitnessScriptTag +impl bitcoin_primitives::script::WScriptHash +impl bitcoin_primitives::script::WitnessScriptSizeError +impl bitcoin_primitives::transaction::OutPoint +impl bitcoin_primitives::transaction::OutPointDecoder +impl bitcoin_primitives::transaction::Transaction +impl bitcoin_primitives::transaction::TransactionDecoder +impl bitcoin_primitives::transaction::TxIn +impl bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl bitcoin_primitives::transaction::Version +impl bitcoin_primitives::transaction::VersionDecoder +impl bitcoin_primitives::witness::Witness +impl bitcoin_primitives::witness::WitnessDecoder +impl core::borrow::Borrow<[u8; 20]> for bitcoin_primitives::script::ScriptHash +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::BlockHash +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Ntxid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::TxMerkleNode +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Txid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::WitnessCommitment +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::WitnessMerkleNode +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Wtxid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::script::WScriptHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::BlockHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Ntxid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::TxMerkleNode +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Txid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::WitnessCommitment +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::WitnessMerkleNode +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Wtxid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::script::ScriptHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::script::WScriptHash +impl core::clone::Clone for bitcoin_primitives::BlockHash +impl core::clone::Clone for bitcoin_primitives::Ntxid +impl core::clone::Clone for bitcoin_primitives::TxMerkleNode +impl core::clone::Clone for bitcoin_primitives::Txid +impl core::clone::Clone for bitcoin_primitives::WitnessCommitment +impl core::clone::Clone for bitcoin_primitives::WitnessMerkleNode +impl core::clone::Clone for bitcoin_primitives::Wtxid +impl core::clone::Clone for bitcoin_primitives::block::BlockDecoderError +impl core::clone::Clone for bitcoin_primitives::block::BlockHashDecoderError +impl core::clone::Clone for bitcoin_primitives::block::Checked +impl core::clone::Clone for bitcoin_primitives::block::Header +impl core::clone::Clone for bitcoin_primitives::block::HeaderDecoderError +impl core::clone::Clone for bitcoin_primitives::block::InvalidBlockError +impl core::clone::Clone for bitcoin_primitives::block::Unchecked +impl core::clone::Clone for bitcoin_primitives::block::Version +impl core::clone::Clone for bitcoin_primitives::block::VersionDecoderError +impl core::clone::Clone for bitcoin_primitives::pow::CompactTarget +impl core::clone::Clone for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::clone::Clone for bitcoin_primitives::script::RedeemScriptSizeError +impl core::clone::Clone for bitcoin_primitives::script::RedeemScriptTag +impl core::clone::Clone for bitcoin_primitives::script::ScriptBufDecoderError +impl core::clone::Clone for bitcoin_primitives::script::ScriptHash +impl core::clone::Clone for bitcoin_primitives::script::ScriptPubKeyTag +impl core::clone::Clone for bitcoin_primitives::script::ScriptSigTag +impl core::clone::Clone for bitcoin_primitives::script::TapScriptTag +impl core::clone::Clone for bitcoin_primitives::script::WScriptHash +impl core::clone::Clone for bitcoin_primitives::script::WitnessScriptSizeError +impl core::clone::Clone for bitcoin_primitives::script::WitnessScriptTag +impl core::clone::Clone for bitcoin_primitives::transaction::OutPoint +impl core::clone::Clone for bitcoin_primitives::transaction::OutPointDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::Transaction +impl core::clone::Clone for bitcoin_primitives::transaction::TransactionDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxIn +impl core::clone::Clone for bitcoin_primitives::transaction::TxInDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxOut +impl core::clone::Clone for bitcoin_primitives::transaction::TxOutDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::Version +impl core::clone::Clone for bitcoin_primitives::transaction::VersionDecoderError +impl core::clone::Clone for bitcoin_primitives::witness::UnexpectedEofError +impl core::clone::Clone for bitcoin_primitives::witness::Witness +impl core::clone::Clone for bitcoin_primitives::witness::WitnessDecoderError +impl core::cmp::Eq for bitcoin_primitives::BlockHash +impl core::cmp::Eq for bitcoin_primitives::Ntxid +impl core::cmp::Eq for bitcoin_primitives::TxMerkleNode +impl core::cmp::Eq for bitcoin_primitives::Txid +impl core::cmp::Eq for bitcoin_primitives::WitnessCommitment +impl core::cmp::Eq for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::Eq for bitcoin_primitives::Wtxid +impl core::cmp::Eq for bitcoin_primitives::block::BlockDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::BlockHashDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::Checked +impl core::cmp::Eq for bitcoin_primitives::block::Header +impl core::cmp::Eq for bitcoin_primitives::block::HeaderDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::InvalidBlockError +impl core::cmp::Eq for bitcoin_primitives::block::Unchecked +impl core::cmp::Eq for bitcoin_primitives::block::Version +impl core::cmp::Eq for bitcoin_primitives::block::VersionDecoderError +impl core::cmp::Eq for bitcoin_primitives::pow::CompactTarget +impl core::cmp::Eq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::cmp::Eq for bitcoin_primitives::script::RedeemScriptSizeError +impl core::cmp::Eq for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::Eq for bitcoin_primitives::script::ScriptBufDecoderError +impl core::cmp::Eq for bitcoin_primitives::script::ScriptHash +impl core::cmp::Eq for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::Eq for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::Eq for bitcoin_primitives::script::TapScriptTag +impl core::cmp::Eq for bitcoin_primitives::script::WScriptHash +impl core::cmp::Eq for bitcoin_primitives::script::WitnessScriptSizeError +impl core::cmp::Eq for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::Eq for bitcoin_primitives::transaction::OutPoint +impl core::cmp::Eq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::Transaction +impl core::cmp::Eq for bitcoin_primitives::transaction::TransactionDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxIn +impl core::cmp::Eq for bitcoin_primitives::transaction::TxInDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxOut +impl core::cmp::Eq for bitcoin_primitives::transaction::TxOutDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::Version +impl core::cmp::Eq for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::Eq for bitcoin_primitives::witness::UnexpectedEofError +impl core::cmp::Eq for bitcoin_primitives::witness::Witness +impl core::cmp::Eq for bitcoin_primitives::witness::WitnessDecoderError +impl core::cmp::Ord for bitcoin_primitives::BlockHash +impl core::cmp::Ord for bitcoin_primitives::Ntxid +impl core::cmp::Ord for bitcoin_primitives::TxMerkleNode +impl core::cmp::Ord for bitcoin_primitives::Txid +impl core::cmp::Ord for bitcoin_primitives::WitnessCommitment +impl core::cmp::Ord for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::Ord for bitcoin_primitives::Wtxid +impl core::cmp::Ord for bitcoin_primitives::block::Checked +impl core::cmp::Ord for bitcoin_primitives::block::Header +impl core::cmp::Ord for bitcoin_primitives::block::Unchecked +impl core::cmp::Ord for bitcoin_primitives::block::Version +impl core::cmp::Ord for bitcoin_primitives::pow::CompactTarget +impl core::cmp::Ord for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::Ord for bitcoin_primitives::script::ScriptHash +impl core::cmp::Ord for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::Ord for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::Ord for bitcoin_primitives::script::TapScriptTag +impl core::cmp::Ord for bitcoin_primitives::script::WScriptHash +impl core::cmp::Ord for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::Ord for bitcoin_primitives::transaction::OutPoint +impl core::cmp::Ord for bitcoin_primitives::transaction::Transaction +impl core::cmp::Ord for bitcoin_primitives::transaction::TxIn +impl core::cmp::Ord for bitcoin_primitives::transaction::TxOut +impl core::cmp::Ord for bitcoin_primitives::transaction::Version +impl core::cmp::Ord for bitcoin_primitives::witness::Witness +impl core::cmp::PartialEq for bitcoin_primitives::BlockHash +impl core::cmp::PartialEq for bitcoin_primitives::Ntxid +impl core::cmp::PartialEq for bitcoin_primitives::TxMerkleNode +impl core::cmp::PartialEq for bitcoin_primitives::Txid +impl core::cmp::PartialEq for bitcoin_primitives::WitnessCommitment +impl core::cmp::PartialEq for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::PartialEq for bitcoin_primitives::Wtxid +impl core::cmp::PartialEq for bitcoin_primitives::block::BlockDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::BlockHashDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::Checked +impl core::cmp::PartialEq for bitcoin_primitives::block::Header +impl core::cmp::PartialEq for bitcoin_primitives::block::HeaderDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::InvalidBlockError +impl core::cmp::PartialEq for bitcoin_primitives::block::Unchecked +impl core::cmp::PartialEq for bitcoin_primitives::block::Version +impl core::cmp::PartialEq for bitcoin_primitives::block::VersionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::pow::CompactTarget +impl core::cmp::PartialEq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::script::RedeemScriptSizeError +impl core::cmp::PartialEq for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptBufDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptHash +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::PartialEq for bitcoin_primitives::script::TapScriptTag +impl core::cmp::PartialEq for bitcoin_primitives::script::WScriptHash +impl core::cmp::PartialEq for bitcoin_primitives::script::WitnessScriptSizeError +impl core::cmp::PartialEq for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::PartialEq for bitcoin_primitives::transaction::OutPoint +impl core::cmp::PartialEq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::Transaction +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TransactionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxIn +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxInDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxOut +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxOutDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::Version +impl core::cmp::PartialEq for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::witness::UnexpectedEofError +impl core::cmp::PartialEq for bitcoin_primitives::witness::Witness +impl core::cmp::PartialEq for bitcoin_primitives::witness::WitnessDecoderError +impl core::cmp::PartialOrd for bitcoin_primitives::BlockHash +impl core::cmp::PartialOrd for bitcoin_primitives::Ntxid +impl core::cmp::PartialOrd for bitcoin_primitives::TxMerkleNode +impl core::cmp::PartialOrd for bitcoin_primitives::Txid +impl core::cmp::PartialOrd for bitcoin_primitives::WitnessCommitment +impl core::cmp::PartialOrd for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::PartialOrd for bitcoin_primitives::Wtxid +impl core::cmp::PartialOrd for bitcoin_primitives::block::Checked +impl core::cmp::PartialOrd for bitcoin_primitives::block::Header +impl core::cmp::PartialOrd for bitcoin_primitives::block::Unchecked +impl core::cmp::PartialOrd for bitcoin_primitives::block::Version +impl core::cmp::PartialOrd for bitcoin_primitives::pow::CompactTarget +impl core::cmp::PartialOrd for bitcoin_primitives::script::RedeemScriptTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptHash +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptPubKeyTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptSigTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::TapScriptTag +impl core::cmp::PartialOrd for bitcoin_primitives::script::WScriptHash +impl core::cmp::PartialOrd for bitcoin_primitives::script::WitnessScriptTag +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::OutPoint +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::Transaction +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::TxIn +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::TxOut +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::Version +impl core::cmp::PartialOrd for bitcoin_primitives::witness::Witness +impl core::convert::AsRef<[u8; 20]> for bitcoin_primitives::script::ScriptHash +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::BlockHash +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Ntxid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::TxMerkleNode +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Txid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::WitnessCommitment +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::WitnessMerkleNode +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Wtxid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::script::WScriptHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::BlockHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Ntxid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::TxMerkleNode +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Txid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::WitnessCommitment +impl core::convert::AsRef<[u8]> for bitcoin_primitives::WitnessMerkleNode +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Wtxid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::ScriptHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::WScriptHash +impl core::convert::From<&[&[u8]]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[alloc::vec::Vec]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&bitcoin_primitives::block::Block> for bitcoin_primitives::BlockHash +impl core::convert::From<&bitcoin_primitives::block::Header> for bitcoin_primitives::BlockHash +impl core::convert::From<&bitcoin_primitives::transaction::Transaction> for bitcoin_primitives::Txid +impl core::convert::From<&bitcoin_primitives::transaction::Transaction> for bitcoin_primitives::Wtxid +impl core::convert::From> for bitcoin_primitives::witness::Witness +impl core::convert::From>> for bitcoin_primitives::witness::Witness +impl core::convert::From for bitcoin_primitives::script::ScriptBufDecoderError +impl core::convert::From for bitcoin_primitives::block::BlockHashDecoderError +impl core::convert::From for bitcoin_primitives::block::VersionDecoderError +impl core::convert::From for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::convert::From> for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From> for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::BlockHash +impl core::convert::From for bitcoin_primitives::BlockHash +impl core::convert::From for bitcoin_primitives::Txid +impl core::convert::From for bitcoin_primitives::Wtxid +impl core::convert::From for u32 +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::block::BlockDecoderError +impl core::convert::From for bitcoin_primitives::block::BlockHashDecoderError +impl core::convert::From for bitcoin_primitives::block::HeaderDecoderError +impl core::convert::From for bitcoin_primitives::block::InvalidBlockError +impl core::convert::From for bitcoin_primitives::block::VersionDecoderError +impl core::convert::From for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::convert::From for bitcoin_primitives::script::RedeemScriptSizeError +impl core::convert::From for bitcoin_primitives::script::ScriptBufDecoderError +impl core::convert::From for bitcoin_primitives::script::WitnessScriptSizeError +impl core::convert::From for bitcoin_primitives::transaction::TransactionDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxInDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxOutDecoderError +impl core::convert::From for bitcoin_primitives::transaction::VersionDecoderError +impl core::convert::From for bitcoin_primitives::witness::WitnessDecoderError +impl core::convert::TryFrom<&bitcoin_primitives::script::Script> for bitcoin_primitives::script::WScriptHash +impl core::convert::TryFrom<&bitcoin_primitives::script::ScriptBuf> for bitcoin_primitives::script::WScriptHash +impl core::convert::TryFrom> for bitcoin_primitives::script::WScriptHash +impl core::default::Default for bitcoin_primitives::block::BlockHashDecoder +impl core::default::Default for bitcoin_primitives::block::Version +impl core::default::Default for bitcoin_primitives::block::VersionDecoder +impl core::default::Default for bitcoin_primitives::pow::CompactTargetDecoder +impl core::default::Default for bitcoin_primitives::transaction::OutPointDecoder +impl core::default::Default for bitcoin_primitives::transaction::TransactionDecoder +impl core::default::Default for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::default::Default for bitcoin_primitives::transaction::VersionDecoder +impl core::default::Default for bitcoin_primitives::witness::Witness +impl core::default::Default for bitcoin_primitives::witness::WitnessDecoder +impl core::fmt::Debug for bitcoin_primitives::BlockHash +impl core::fmt::Debug for bitcoin_primitives::Ntxid +impl core::fmt::Debug for bitcoin_primitives::TxMerkleNode +impl core::fmt::Debug for bitcoin_primitives::Txid +impl core::fmt::Debug for bitcoin_primitives::WitnessCommitment +impl core::fmt::Debug for bitcoin_primitives::WitnessMerkleNode +impl core::fmt::Debug for bitcoin_primitives::Wtxid +impl core::fmt::Debug for bitcoin_primitives::block::BlockDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::BlockHashDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::Checked +impl core::fmt::Debug for bitcoin_primitives::block::Header +impl core::fmt::Debug for bitcoin_primitives::block::HeaderDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::InvalidBlockError +impl core::fmt::Debug for bitcoin_primitives::block::Unchecked +impl core::fmt::Debug for bitcoin_primitives::block::Version +impl core::fmt::Debug for bitcoin_primitives::block::VersionDecoderError +impl core::fmt::Debug for bitcoin_primitives::pow::CompactTarget +impl core::fmt::Debug for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::fmt::Debug for bitcoin_primitives::script::RedeemScriptSizeError +impl core::fmt::Debug for bitcoin_primitives::script::ScriptBufDecoderError +impl core::fmt::Debug for bitcoin_primitives::script::ScriptHash +impl core::fmt::Debug for bitcoin_primitives::script::WScriptHash +impl core::fmt::Debug for bitcoin_primitives::script::WitnessScriptSizeError +impl core::fmt::Debug for bitcoin_primitives::transaction::OutPoint +impl core::fmt::Debug for bitcoin_primitives::transaction::OutPointDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::Transaction +impl core::fmt::Debug for bitcoin_primitives::transaction::TransactionDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxIn +impl core::fmt::Debug for bitcoin_primitives::transaction::TxInDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxOut +impl core::fmt::Debug for bitcoin_primitives::transaction::TxOutDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::Version +impl core::fmt::Debug for bitcoin_primitives::transaction::VersionDecoderError +impl core::fmt::Debug for bitcoin_primitives::witness::UnexpectedEofError +impl core::fmt::Debug for bitcoin_primitives::witness::Witness +impl core::fmt::Debug for bitcoin_primitives::witness::WitnessDecoderError +impl core::fmt::Display for bitcoin_primitives::block::BlockDecoderError +impl core::fmt::Display for bitcoin_primitives::block::BlockHashDecoderError +impl core::fmt::Display for bitcoin_primitives::block::HeaderDecoderError +impl core::fmt::Display for bitcoin_primitives::block::InvalidBlockError +impl core::fmt::Display for bitcoin_primitives::block::VersionDecoderError +impl core::fmt::Display for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::fmt::Display for bitcoin_primitives::script::RedeemScriptSizeError +impl core::fmt::Display for bitcoin_primitives::script::ScriptBufDecoderError +impl core::fmt::Display for bitcoin_primitives::script::WitnessScriptSizeError +impl core::fmt::Display for bitcoin_primitives::transaction::OutPointDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TransactionDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxInDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxOutDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::Version +impl core::fmt::Display for bitcoin_primitives::transaction::VersionDecoderError +impl core::fmt::Display for bitcoin_primitives::witness::UnexpectedEofError +impl core::fmt::Display for bitcoin_primitives::witness::WitnessDecoderError +impl core::fmt::LowerHex for bitcoin_primitives::pow::CompactTarget +impl core::fmt::UpperHex for bitcoin_primitives::pow::CompactTarget +impl core::hash::Hash for bitcoin_primitives::BlockHash +impl core::hash::Hash for bitcoin_primitives::Ntxid +impl core::hash::Hash for bitcoin_primitives::TxMerkleNode +impl core::hash::Hash for bitcoin_primitives::Txid +impl core::hash::Hash for bitcoin_primitives::WitnessCommitment +impl core::hash::Hash for bitcoin_primitives::WitnessMerkleNode +impl core::hash::Hash for bitcoin_primitives::Wtxid +impl core::hash::Hash for bitcoin_primitives::block::Checked +impl core::hash::Hash for bitcoin_primitives::block::Header +impl core::hash::Hash for bitcoin_primitives::block::Unchecked +impl core::hash::Hash for bitcoin_primitives::block::Version +impl core::hash::Hash for bitcoin_primitives::pow::CompactTarget +impl core::hash::Hash for bitcoin_primitives::script::RedeemScriptTag +impl core::hash::Hash for bitcoin_primitives::script::ScriptHash +impl core::hash::Hash for bitcoin_primitives::script::ScriptPubKeyTag +impl core::hash::Hash for bitcoin_primitives::script::ScriptSigTag +impl core::hash::Hash for bitcoin_primitives::script::TapScriptTag +impl core::hash::Hash for bitcoin_primitives::script::WScriptHash +impl core::hash::Hash for bitcoin_primitives::script::WitnessScriptTag +impl core::hash::Hash for bitcoin_primitives::transaction::OutPoint +impl core::hash::Hash for bitcoin_primitives::transaction::Transaction +impl core::hash::Hash for bitcoin_primitives::transaction::TxIn +impl core::hash::Hash for bitcoin_primitives::transaction::TxOut +impl core::hash::Hash for bitcoin_primitives::transaction::Version +impl core::hash::Hash for bitcoin_primitives::witness::Witness +impl core::iter::traits::exact_size::ExactSizeIterator for bitcoin_primitives::witness::Iter<'_> +impl core::marker::Copy for bitcoin_primitives::BlockHash +impl core::marker::Copy for bitcoin_primitives::Ntxid +impl core::marker::Copy for bitcoin_primitives::TxMerkleNode +impl core::marker::Copy for bitcoin_primitives::Txid +impl core::marker::Copy for bitcoin_primitives::WitnessCommitment +impl core::marker::Copy for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Copy for bitcoin_primitives::Wtxid +impl core::marker::Copy for bitcoin_primitives::block::Header +impl core::marker::Copy for bitcoin_primitives::block::Version +impl core::marker::Copy for bitcoin_primitives::pow::CompactTarget +impl core::marker::Copy for bitcoin_primitives::script::ScriptHash +impl core::marker::Copy for bitcoin_primitives::script::WScriptHash +impl core::marker::Copy for bitcoin_primitives::transaction::OutPoint +impl core::marker::Copy for bitcoin_primitives::transaction::Version +impl core::marker::Freeze for bitcoin_primitives::BlockHash +impl core::marker::Freeze for bitcoin_primitives::Ntxid +impl core::marker::Freeze for bitcoin_primitives::TxMerkleNode +impl core::marker::Freeze for bitcoin_primitives::Txid +impl core::marker::Freeze for bitcoin_primitives::WitnessCommitment +impl core::marker::Freeze for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Freeze for bitcoin_primitives::Wtxid +impl core::marker::Freeze for bitcoin_primitives::block::BlockDecoder +impl core::marker::Freeze for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Freeze for bitcoin_primitives::block::Checked +impl core::marker::Freeze for bitcoin_primitives::block::Header +impl core::marker::Freeze for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Freeze for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Freeze for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Freeze for bitcoin_primitives::block::Unchecked +impl core::marker::Freeze for bitcoin_primitives::block::Version +impl core::marker::Freeze for bitcoin_primitives::block::VersionDecoder +impl core::marker::Freeze for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::VersionEncoder +impl core::marker::Freeze for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTarget +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Freeze for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Freeze for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Freeze for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Freeze for bitcoin_primitives::script::ScriptHash +impl core::marker::Freeze for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Freeze for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Freeze for bitcoin_primitives::script::TapScriptTag +impl core::marker::Freeze for bitcoin_primitives::script::WScriptHash +impl core::marker::Freeze for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Freeze for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPoint +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::Transaction +impl core::marker::Freeze for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxIn +impl core::marker::Freeze for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxOut +impl core::marker::Freeze for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::Version +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Freeze for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Freeze for bitcoin_primitives::witness::Witness +impl core::marker::Freeze for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Freeze for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::Send for bitcoin_primitives::BlockHash +impl core::marker::Send for bitcoin_primitives::Ntxid +impl core::marker::Send for bitcoin_primitives::TxMerkleNode +impl core::marker::Send for bitcoin_primitives::Txid +impl core::marker::Send for bitcoin_primitives::WitnessCommitment +impl core::marker::Send for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Send for bitcoin_primitives::Wtxid +impl core::marker::Send for bitcoin_primitives::block::BlockDecoder +impl core::marker::Send for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Send for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Send for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Send for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Send for bitcoin_primitives::block::Checked +impl core::marker::Send for bitcoin_primitives::block::Header +impl core::marker::Send for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Send for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Send for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Send for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Send for bitcoin_primitives::block::Unchecked +impl core::marker::Send for bitcoin_primitives::block::Version +impl core::marker::Send for bitcoin_primitives::block::VersionDecoder +impl core::marker::Send for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Send for bitcoin_primitives::block::VersionEncoder +impl core::marker::Send for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Send for bitcoin_primitives::pow::CompactTarget +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Send for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Send for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Send for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Send for bitcoin_primitives::script::ScriptHash +impl core::marker::Send for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Send for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Send for bitcoin_primitives::script::TapScriptTag +impl core::marker::Send for bitcoin_primitives::script::WScriptHash +impl core::marker::Send for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Send for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Send for bitcoin_primitives::transaction::OutPoint +impl core::marker::Send for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Send for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::Transaction +impl core::marker::Send for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxIn +impl core::marker::Send for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxOut +impl core::marker::Send for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::Version +impl core::marker::Send for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Send for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Send for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Send for bitcoin_primitives::witness::Witness +impl core::marker::Send for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Send for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::BlockHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::Ntxid +impl core::marker::StructuralPartialEq for bitcoin_primitives::TxMerkleNode +impl core::marker::StructuralPartialEq for bitcoin_primitives::Txid +impl core::marker::StructuralPartialEq for bitcoin_primitives::WitnessCommitment +impl core::marker::StructuralPartialEq for bitcoin_primitives::WitnessMerkleNode +impl core::marker::StructuralPartialEq for bitcoin_primitives::Wtxid +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::BlockDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Checked +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Header +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::InvalidBlockError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Unchecked +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Version +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::VersionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::pow::CompactTarget +impl core::marker::StructuralPartialEq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptSigTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::TapScriptTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::WScriptHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::OutPoint +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::Transaction +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxIn +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxOut +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::Version +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::StructuralPartialEq for bitcoin_primitives::witness::Witness +impl core::marker::StructuralPartialEq for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::Sync for bitcoin_primitives::BlockHash +impl core::marker::Sync for bitcoin_primitives::Ntxid +impl core::marker::Sync for bitcoin_primitives::TxMerkleNode +impl core::marker::Sync for bitcoin_primitives::Txid +impl core::marker::Sync for bitcoin_primitives::WitnessCommitment +impl core::marker::Sync for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Sync for bitcoin_primitives::Wtxid +impl core::marker::Sync for bitcoin_primitives::block::BlockDecoder +impl core::marker::Sync for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Sync for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Sync for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Sync for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Sync for bitcoin_primitives::block::Checked +impl core::marker::Sync for bitcoin_primitives::block::Header +impl core::marker::Sync for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Sync for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Sync for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Sync for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Sync for bitcoin_primitives::block::Unchecked +impl core::marker::Sync for bitcoin_primitives::block::Version +impl core::marker::Sync for bitcoin_primitives::block::VersionDecoder +impl core::marker::Sync for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::block::VersionEncoder +impl core::marker::Sync for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Sync for bitcoin_primitives::pow::CompactTarget +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Sync for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Sync for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Sync for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Sync for bitcoin_primitives::script::ScriptHash +impl core::marker::Sync for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Sync for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Sync for bitcoin_primitives::script::TapScriptTag +impl core::marker::Sync for bitcoin_primitives::script::WScriptHash +impl core::marker::Sync for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Sync for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Sync for bitcoin_primitives::transaction::OutPoint +impl core::marker::Sync for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::Transaction +impl core::marker::Sync for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxIn +impl core::marker::Sync for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxOut +impl core::marker::Sync for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::Version +impl core::marker::Sync for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Sync for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Sync for bitcoin_primitives::witness::Witness +impl core::marker::Sync for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Sync for bitcoin_primitives::witness::WitnessDecoderError +impl core::marker::Unpin for bitcoin_primitives::BlockHash +impl core::marker::Unpin for bitcoin_primitives::Ntxid +impl core::marker::Unpin for bitcoin_primitives::TxMerkleNode +impl core::marker::Unpin for bitcoin_primitives::Txid +impl core::marker::Unpin for bitcoin_primitives::WitnessCommitment +impl core::marker::Unpin for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Unpin for bitcoin_primitives::Wtxid +impl core::marker::Unpin for bitcoin_primitives::block::BlockDecoder +impl core::marker::Unpin for bitcoin_primitives::block::BlockDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Unpin for bitcoin_primitives::block::Checked +impl core::marker::Unpin for bitcoin_primitives::block::Header +impl core::marker::Unpin for bitcoin_primitives::block::HeaderDecoder +impl core::marker::Unpin for bitcoin_primitives::block::HeaderDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Unpin for bitcoin_primitives::block::InvalidBlockError +impl core::marker::Unpin for bitcoin_primitives::block::Unchecked +impl core::marker::Unpin for bitcoin_primitives::block::Version +impl core::marker::Unpin for bitcoin_primitives::block::VersionDecoder +impl core::marker::Unpin for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::VersionEncoder +impl core::marker::Unpin for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTarget +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Unpin for bitcoin_primitives::script::RedeemScriptSizeError +impl core::marker::Unpin for bitcoin_primitives::script::RedeemScriptTag +impl core::marker::Unpin for bitcoin_primitives::script::ScriptBufDecoderError +impl core::marker::Unpin for bitcoin_primitives::script::ScriptHash +impl core::marker::Unpin for bitcoin_primitives::script::ScriptPubKeyTag +impl core::marker::Unpin for bitcoin_primitives::script::ScriptSigTag +impl core::marker::Unpin for bitcoin_primitives::script::TapScriptTag +impl core::marker::Unpin for bitcoin_primitives::script::WScriptHash +impl core::marker::Unpin for bitcoin_primitives::script::WitnessScriptSizeError +impl core::marker::Unpin for bitcoin_primitives::script::WitnessScriptTag +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPoint +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::Transaction +impl core::marker::Unpin for bitcoin_primitives::transaction::TransactionDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TransactionDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxIn +impl core::marker::Unpin for bitcoin_primitives::transaction::TxInDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxInDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxOut +impl core::marker::Unpin for bitcoin_primitives::transaction::TxOutDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxOutDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::Version +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Unpin for bitcoin_primitives::witness::UnexpectedEofError +impl core::marker::Unpin for bitcoin_primitives::witness::Witness +impl core::marker::Unpin for bitcoin_primitives::witness::WitnessDecoder +impl core::marker::Unpin for bitcoin_primitives::witness::WitnessDecoderError +impl core::ops::index::Index for bitcoin_primitives::witness::Witness +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::BlockHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Ntxid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::TxMerkleNode +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Txid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::WitnessCommitment +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::WitnessMerkleNode +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Wtxid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Checked +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Header +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::InvalidBlockError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Unchecked +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Version +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTarget +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::RedeemScriptSizeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::RedeemScriptTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptBufDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptPubKeyTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptSigTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::TapScriptTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::WScriptHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::WitnessScriptSizeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::WitnessScriptTag +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPoint +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::Transaction +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TransactionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TransactionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxIn +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxInDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxInDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOut +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOutDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOutDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::Version +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::UnexpectedEofError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::Witness +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::WitnessDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::WitnessDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::BlockHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Ntxid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::TxMerkleNode +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Txid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::WitnessCommitment +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::WitnessMerkleNode +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Wtxid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Checked +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Header +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::InvalidBlockError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Unchecked +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Version +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTarget +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::RedeemScriptSizeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::RedeemScriptTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptBufDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptPubKeyTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptSigTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::TapScriptTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::WScriptHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::WitnessScriptSizeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::WitnessScriptTag +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPoint +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::Transaction +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TransactionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TransactionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxIn +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxInDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxInDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOut +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOutDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOutDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::Version +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::UnexpectedEofError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::Witness +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::WitnessDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::WitnessDecoderError +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::borrow::Cow<'a, bitcoin_primitives::script::Script> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::boxed::Box> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::rc::Rc> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for alloc::sync::Arc> +impl<'a, T> core::convert::From<&'a bitcoin_primitives::script::Script> for bitcoin_primitives::script::ScriptBuf +impl<'a, T> core::convert::From>> for alloc::boxed::Box> +impl<'a, T> core::convert::From>> for bitcoin_primitives::script::ScriptBuf +impl<'a> core::clone::Clone for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::iter::traits::collect::IntoIterator for &'a bitcoin_primitives::witness::Witness +impl<'a> core::iter::traits::iterator::Iterator for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Freeze for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Freeze for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::marker::Send for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Send for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::marker::Sync for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Sync for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::marker::Unpin for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::marker::Unpin for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'a> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::Iter<'a> +impl<'a> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::witness::WitnessEncoder<'a> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TransactionEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxInEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxOutEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e> +impl core::default::Default for &bitcoin_primitives::script::Script +impl core::convert::TryFrom<&bitcoin_primitives::script::Script> for bitcoin_primitives::script::ScriptHash +impl core::convert::TryFrom<&bitcoin_primitives::script::ScriptBuf> for bitcoin_primitives::script::ScriptHash +impl core::convert::TryFrom> for bitcoin_primitives::script::ScriptHash +impl> core::cmp::PartialEq<&[T]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq<[T]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq for &[T] +impl> core::cmp::PartialEq for [T] +impl> core::cmp::PartialEq for alloc::boxed::Box<[T]> +impl> core::cmp::PartialEq for alloc::rc::Rc<[T]> +impl> core::cmp::PartialEq for alloc::sync::Arc<[T]> +impl> core::cmp::PartialEq for alloc::vec::Vec +impl core::clone::Clone for bitcoin_primitives::script::ScriptBuf +impl core::cmp::Eq for bitcoin_primitives::script::Script +impl core::cmp::Eq for bitcoin_primitives::script::ScriptBuf +impl core::cmp::Ord for bitcoin_primitives::script::Script +impl core::cmp::Ord for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialEq for bitcoin_primitives::script::Script +impl core::cmp::PartialEq for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialEq> for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialEq> for bitcoin_primitives::script::Script +impl core::cmp::PartialOrd for bitcoin_primitives::script::Script +impl core::cmp::PartialOrd for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialOrd> for bitcoin_primitives::script::ScriptBuf +impl core::cmp::PartialOrd> for bitcoin_primitives::script::Script +impl> core::iter::traits::collect::FromIterator for bitcoin_primitives::witness::Witness +impl core::hash::Hash for bitcoin_primitives::script::Script +impl core::hash::Hash for bitcoin_primitives::script::ScriptBuf +impl !core::marker::Sized for bitcoin_primitives::script::Script +impl alloc::borrow::ToOwned for bitcoin_primitives::script::Script +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::script::ScriptBuf +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::script::ScriptBufDecoder +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::script::Script +impl bitcoin_primitives::script::Script +impl bitcoin_primitives::script::ScriptBuf +impl bitcoin_primitives::script::ScriptBufDecoder +impl core::borrow::Borrow> for bitcoin_primitives::script::ScriptBuf +impl core::borrow::BorrowMut> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsMut<[u8]> for bitcoin_primitives::script::Script +impl core::convert::AsMut<[u8]> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsMut> for bitcoin_primitives::script::Script +impl core::convert::AsMut> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::Script +impl core::convert::AsRef<[u8]> for bitcoin_primitives::script::ScriptBuf +impl core::convert::AsRef> for bitcoin_primitives::script::Script +impl core::convert::AsRef> for bitcoin_primitives::script::ScriptBuf +impl core::convert::From> for bitcoin_primitives::script::ScriptBuf +impl core::convert::From> for alloc::borrow::Cow<'_, bitcoin_primitives::script::Script> +impl core::convert::From> for alloc::boxed::Box> +impl core::convert::From> for alloc::vec::Vec +impl core::default::Default for bitcoin_primitives::script::ScriptBuf +impl core::default::Default for bitcoin_primitives::script::ScriptBufDecoder +impl core::fmt::Debug for bitcoin_primitives::script::Script +impl core::fmt::Debug for bitcoin_primitives::script::ScriptBuf +impl core::fmt::Display for bitcoin_primitives::script::Script +impl core::fmt::Display for bitcoin_primitives::script::ScriptBuf +impl core::marker::Freeze for bitcoin_primitives::script::Script +impl core::marker::Freeze for bitcoin_primitives::script::ScriptBuf +impl core::marker::Freeze for bitcoin_primitives::script::ScriptBufDecoder +impl core::marker::Send for bitcoin_primitives::script::Script where T: core::marker::Send +impl core::marker::Send for bitcoin_primitives::script::ScriptBuf where T: core::marker::Send +impl core::marker::Send for bitcoin_primitives::script::ScriptBufDecoder where T: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::Script +impl core::marker::StructuralPartialEq for bitcoin_primitives::script::ScriptBuf +impl core::marker::Sync for bitcoin_primitives::script::Script where T: core::marker::Sync +impl core::marker::Sync for bitcoin_primitives::script::ScriptBuf where T: core::marker::Sync +impl core::marker::Sync for bitcoin_primitives::script::ScriptBufDecoder where T: core::marker::Sync +impl core::marker::Unpin for bitcoin_primitives::script::Script where T: core::marker::Unpin +impl core::marker::Unpin for bitcoin_primitives::script::ScriptBuf where T: core::marker::Unpin +impl core::marker::Unpin for bitcoin_primitives::script::ScriptBufDecoder where T: core::marker::Unpin +impl core::ops::deref::Deref for bitcoin_primitives::script::ScriptBuf +impl core::ops::deref::DerefMut for bitcoin_primitives::script::ScriptBuf +impl core::ops::index::Index<(core::ops::range::Bound, core::ops::range::Bound)> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::ops::index::Index> for bitcoin_primitives::script::Script +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::Script where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptBuf where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::script::ScriptBufDecoder where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::Script where T: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptBuf where T: core::panic::unwind_safe::UnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::script::ScriptBufDecoder where T: core::panic::unwind_safe::UnwindSafe +impl bitcoin_primitives::block::Block +impl core::clone::Clone for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::clone::Clone +impl core::cmp::Eq for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::cmp::Eq +impl core::cmp::PartialEq for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::cmp::PartialEq +impl core::fmt::Debug for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation + core::fmt::Debug +impl core::marker::Freeze for bitcoin_primitives::block::Block +impl core::marker::Send for bitcoin_primitives::block::Block +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation +impl core::marker::Sync for bitcoin_primitives::block::Block +impl core::marker::Unpin for bitcoin_primitives::block::Block +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Block where V: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Block where V: core::panic::unwind_safe::UnwindSafe +impl> core::cmp::PartialEq<&[T; N]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq<[T; N]> for bitcoin_primitives::witness::Witness +impl> core::cmp::PartialEq for &[T; N] +impl> core::cmp::PartialEq for [T; N] +impl core::convert::From<&[&[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<[&[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<[[u8; M]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[&[u8; N]]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[&[u8]; N]> for bitcoin_primitives::witness::Witness +impl core::convert::From<&[[u8; N]]> for bitcoin_primitives::witness::Witness +impl core::convert::From<[&[u8]; N]> for bitcoin_primitives::witness::Witness +pub bitcoin_primitives::BlockHeader::bits: bitcoin_primitives::pow::CompactTarget +pub bitcoin_primitives::BlockHeader::merkle_root: bitcoin_primitives::TxMerkleNode +pub bitcoin_primitives::BlockHeader::nonce: u32 +pub bitcoin_primitives::BlockHeader::prev_blockhash: bitcoin_primitives::BlockHash +pub bitcoin_primitives::BlockHeader::time: bitcoin_units::time::encapsulate::BlockTime +pub bitcoin_primitives::BlockHeader::version: bitcoin_primitives::block::Version +pub bitcoin_primitives::OutPoint::txid: bitcoin_primitives::Txid +pub bitcoin_primitives::OutPoint::vout: u32 +pub bitcoin_primitives::Transaction::inputs: alloc::vec::Vec +pub bitcoin_primitives::Transaction::lock_time: bitcoin_units::locktime::absolute::LockTime +pub bitcoin_primitives::Transaction::outputs: alloc::vec::Vec +pub bitcoin_primitives::Transaction::version: bitcoin_primitives::transaction::Version +pub bitcoin_primitives::TxIn::previous_output: bitcoin_primitives::transaction::OutPoint +pub bitcoin_primitives::TxIn::script_sig: bitcoin_primitives::script::ScriptSigBuf +pub bitcoin_primitives::TxIn::sequence: bitcoin_units::sequence::Sequence +pub bitcoin_primitives::TxIn::witness: bitcoin_primitives::witness::Witness +pub bitcoin_primitives::TxOut::amount: bitcoin_units::amount::unsigned::encapsulate::Amount +pub bitcoin_primitives::TxOut::script_pubkey: bitcoin_primitives::script::ScriptPubKeyBuf +pub bitcoin_primitives::block::Header::bits: bitcoin_primitives::pow::CompactTarget +pub bitcoin_primitives::block::Header::merkle_root: bitcoin_primitives::TxMerkleNode +pub bitcoin_primitives::block::Header::nonce: u32 +pub bitcoin_primitives::block::Header::prev_blockhash: bitcoin_primitives::BlockHash +pub bitcoin_primitives::block::Header::time: bitcoin_units::time::encapsulate::BlockTime +pub bitcoin_primitives::block::Header::version: bitcoin_primitives::block::Version +pub bitcoin_primitives::block::HeaderDecoderError::Bits(bitcoin_primitives::pow::CompactTargetDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::MerkleRoot(bitcoin_primitives::transaction::TxMerkleNodeDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::Nonce(bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) +pub bitcoin_primitives::block::HeaderDecoderError::PrevBlockhash(bitcoin_primitives::block::BlockHashDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::Time(bitcoin_units::time::BlockTimeDecoderError) +pub bitcoin_primitives::block::HeaderDecoderError::Version(bitcoin_primitives::block::VersionDecoderError) +pub bitcoin_primitives::block::InvalidBlockError::InvalidCoinbase +pub bitcoin_primitives::block::InvalidBlockError::InvalidMerkleRoot +pub bitcoin_primitives::block::InvalidBlockError::InvalidWitnessCommitment +pub bitcoin_primitives::block::InvalidBlockError::NoTransactions +pub bitcoin_primitives::transaction::OutPoint::txid: bitcoin_primitives::Txid +pub bitcoin_primitives::transaction::OutPoint::vout: u32 +pub bitcoin_primitives::transaction::Transaction::inputs: alloc::vec::Vec +pub bitcoin_primitives::transaction::Transaction::lock_time: bitcoin_units::locktime::absolute::LockTime +pub bitcoin_primitives::transaction::Transaction::outputs: alloc::vec::Vec +pub bitcoin_primitives::transaction::Transaction::version: bitcoin_primitives::transaction::Version +pub bitcoin_primitives::transaction::TxIn::previous_output: bitcoin_primitives::transaction::OutPoint +pub bitcoin_primitives::transaction::TxIn::script_sig: bitcoin_primitives::script::ScriptSigBuf +pub bitcoin_primitives::transaction::TxIn::sequence: bitcoin_units::sequence::Sequence +pub bitcoin_primitives::transaction::TxIn::witness: bitcoin_primitives::witness::Witness +pub bitcoin_primitives::transaction::TxOut::amount: bitcoin_units::amount::unsigned::encapsulate::Amount +pub bitcoin_primitives::transaction::TxOut::script_pubkey: bitcoin_primitives::script::ScriptPubKeyBuf +pub const bitcoin_primitives::BlockHash::GENESIS_PREVIOUS_BLOCK_HASH: Self +pub const bitcoin_primitives::BlockValidation::IS_CHECKED: bool +pub const bitcoin_primitives::Txid::COINBASE_PREVOUT: Self +pub const bitcoin_primitives::WitnessCommitment::GENESIS_PREVIOUS_BLOCK_HASH: Self +pub const bitcoin_primitives::Wtxid::COINBASE: Self +pub const bitcoin_primitives::block::Checked::IS_CHECKED: bool +pub const bitcoin_primitives::block::Header::SIZE: usize +pub const bitcoin_primitives::block::Unchecked::IS_CHECKED: bool +pub const bitcoin_primitives::block::Validation::IS_CHECKED: bool +pub const bitcoin_primitives::block::Version::NO_SOFT_FORK_SIGNALLING: Self +pub const bitcoin_primitives::block::Version::ONE: Self +pub const bitcoin_primitives::block::Version::TWO: Self +pub const bitcoin_primitives::script::MAX_REDEEM_SCRIPT_SIZE: usize +pub const bitcoin_primitives::script::MAX_WITNESS_SCRIPT_SIZE: usize +pub const bitcoin_primitives::transaction::OutPoint::COINBASE_PREVOUT: Self +pub const bitcoin_primitives::transaction::OutPoint::SIZE: usize +pub const bitcoin_primitives::transaction::Transaction::MAX_STANDARD_WEIGHT: bitcoin_units::weight::encapsulate::Weight +pub const bitcoin_primitives::transaction::TxIn::EMPTY_COINBASE: Self +pub const bitcoin_primitives::transaction::Version::ONE: Self +pub const bitcoin_primitives::transaction::Version::THREE: Self +pub const bitcoin_primitives::transaction::Version::TWO: Self +pub const fn bitcoin_primitives::BlockHash::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::BlockHash::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::BlockHash::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Ntxid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Ntxid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Ntxid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::TxMerkleNode::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::TxMerkleNode::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::TxMerkleNode::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Txid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Txid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Txid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::WitnessCommitment::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::WitnessCommitment::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::WitnessCommitment::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::WitnessMerkleNode::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::WitnessMerkleNode::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::WitnessMerkleNode::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Wtxid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Wtxid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Wtxid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::block::BlockHashDecoder::new() -> Self +pub const fn bitcoin_primitives::block::Version::from_consensus(v: i32) -> Self +pub const fn bitcoin_primitives::block::Version::to_consensus(self) -> i32 +pub const fn bitcoin_primitives::block::VersionDecoder::new() -> Self +pub const fn bitcoin_primitives::pow::CompactTarget::to_consensus(self) -> u32 +pub const fn bitcoin_primitives::pow::CompactTargetDecoder::new() -> Self +pub const fn bitcoin_primitives::script::Script::as_bytes(&self) -> &[u8] +pub const fn bitcoin_primitives::script::Script::from_bytes(bytes: &[u8]) -> &Self +pub const fn bitcoin_primitives::script::Script::is_empty(&self) -> bool +pub const fn bitcoin_primitives::script::Script::len(&self) -> usize +pub const fn bitcoin_primitives::script::Script::new() -> &'static Self +pub const fn bitcoin_primitives::script::ScriptBuf::from_bytes(bytes: alloc::vec::Vec) -> Self +pub const fn bitcoin_primitives::script::ScriptBuf::new() -> Self +pub const fn bitcoin_primitives::script::ScriptBufDecoder::new() -> Self +pub const fn bitcoin_primitives::script::ScriptHash::as_byte_array(&self) -> &[u8; 20] +pub const fn bitcoin_primitives::script::ScriptHash::from_byte_array(bytes: [u8; 20]) -> Self +pub const fn bitcoin_primitives::script::ScriptHash::to_byte_array(self) -> [u8; 20] +pub const fn bitcoin_primitives::script::WScriptHash::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::script::WScriptHash::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::script::WScriptHash::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::transaction::OutPointDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::TransactionDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::Version::is_standard(self) -> bool +pub const fn bitcoin_primitives::transaction::Version::maybe_non_standard(version: u32) -> Self +pub const fn bitcoin_primitives::transaction::Version::to_u32(self) -> u32 +pub const fn bitcoin_primitives::transaction::VersionDecoder::new() -> Self +pub const fn bitcoin_primitives::witness::Witness::len(&self) -> usize +pub const fn bitcoin_primitives::witness::Witness::new() -> Self +pub const fn bitcoin_primitives::witness::WitnessDecoder::new() -> Self +pub enum bitcoin_primitives::BlockChecked +pub enum bitcoin_primitives::BlockUnchecked +pub enum bitcoin_primitives::block::Checked +pub enum bitcoin_primitives::block::Unchecked +pub enum bitcoin_primitives::script::RedeemScriptTag +pub enum bitcoin_primitives::script::ScriptPubKeyTag +pub enum bitcoin_primitives::script::ScriptSigTag +pub enum bitcoin_primitives::script::TapScriptTag +pub enum bitcoin_primitives::script::WitnessScriptTag +pub fn &'a bitcoin_primitives::witness::Witness::into_iter(self) -> Self::IntoIter +pub fn &[T; N]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn &[T]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn &bitcoin_primitives::script::Script::default() -> Self +pub fn [T; N]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn [T]::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::borrow::Cow<'_, bitcoin_primitives::script::Script>::from(value: bitcoin_primitives::script::ScriptBuf) -> Self +pub fn alloc::borrow::Cow<'a, bitcoin_primitives::script::Script>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::boxed::Box<[T]>::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::boxed::Box>::from(v: bitcoin_primitives::script::ScriptBuf) -> Self +pub fn alloc::boxed::Box>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::boxed::Box>::from(value: alloc::borrow::Cow<'a, bitcoin_primitives::script::Script>) -> Self +pub fn alloc::rc::Rc<[T]>::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::rc::Rc>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::sync::Arc<[T]>::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::sync::Arc>::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn alloc::vec::Vec::eq(&self, rhs: &bitcoin_primitives::witness::Witness) -> bool +pub fn alloc::vec::Vec::from(v: bitcoin_primitives::script::ScriptBuf) -> Self +pub fn bitcoin_primitives::BlockHash::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::BlockHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::BlockHash::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::BlockHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::BlockHash::clone(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::BlockHash::cmp(&self, other: &bitcoin_primitives::BlockHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::BlockHash::decoder() -> Self::Decoder +pub fn bitcoin_primitives::BlockHash::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::BlockHash::eq(&self, other: &bitcoin_primitives::BlockHash) -> bool +pub fn bitcoin_primitives::BlockHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::BlockHash::from(block: &bitcoin_primitives::block::Block) -> Self +pub fn bitcoin_primitives::BlockHash::from(block: bitcoin_primitives::block::Block) -> Self +pub fn bitcoin_primitives::BlockHash::from(header: &bitcoin_primitives::block::Header) -> Self +pub fn bitcoin_primitives::BlockHash::from(header: bitcoin_primitives::block::Header) -> Self +pub fn bitcoin_primitives::BlockHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::BlockHash::partial_cmp(&self, other: &bitcoin_primitives::BlockHash) -> core::option::Option +pub fn bitcoin_primitives::Ntxid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Ntxid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Ntxid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Ntxid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Ntxid::clone(&self) -> bitcoin_primitives::Ntxid +pub fn bitcoin_primitives::Ntxid::cmp(&self, other: &bitcoin_primitives::Ntxid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Ntxid::eq(&self, other: &bitcoin_primitives::Ntxid) -> bool +pub fn bitcoin_primitives::Ntxid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Ntxid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Ntxid::partial_cmp(&self, other: &bitcoin_primitives::Ntxid) -> core::option::Option +pub fn bitcoin_primitives::TxMerkleNode::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::TxMerkleNode::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::TxMerkleNode::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::TxMerkleNode::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::TxMerkleNode::calculate_root>(iter: I) -> core::option::Option +pub fn bitcoin_primitives::TxMerkleNode::clone(&self) -> bitcoin_primitives::TxMerkleNode +pub fn bitcoin_primitives::TxMerkleNode::cmp(&self, other: &bitcoin_primitives::TxMerkleNode) -> core::cmp::Ordering +pub fn bitcoin_primitives::TxMerkleNode::combine(&self, other: &Self) -> Self +pub fn bitcoin_primitives::TxMerkleNode::decoder() -> Self::Decoder +pub fn bitcoin_primitives::TxMerkleNode::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::TxMerkleNode::eq(&self, other: &bitcoin_primitives::TxMerkleNode) -> bool +pub fn bitcoin_primitives::TxMerkleNode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::TxMerkleNode::from_leaf(leaf: bitcoin_primitives::Txid) -> Self +pub fn bitcoin_primitives::TxMerkleNode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::TxMerkleNode::partial_cmp(&self, other: &bitcoin_primitives::TxMerkleNode) -> core::option::Option +pub fn bitcoin_primitives::Txid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Txid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Txid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Txid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Txid::clone(&self) -> bitcoin_primitives::Txid +pub fn bitcoin_primitives::Txid::cmp(&self, other: &bitcoin_primitives::Txid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Txid::eq(&self, other: &bitcoin_primitives::Txid) -> bool +pub fn bitcoin_primitives::Txid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Txid::from(tx: &bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Txid::from(tx: bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Txid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Txid::partial_cmp(&self, other: &bitcoin_primitives::Txid) -> core::option::Option +pub fn bitcoin_primitives::WitnessCommitment::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessCommitment::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessCommitment::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessCommitment::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessCommitment::clone(&self) -> bitcoin_primitives::WitnessCommitment +pub fn bitcoin_primitives::WitnessCommitment::cmp(&self, other: &bitcoin_primitives::WitnessCommitment) -> core::cmp::Ordering +pub fn bitcoin_primitives::WitnessCommitment::eq(&self, other: &bitcoin_primitives::WitnessCommitment) -> bool +pub fn bitcoin_primitives::WitnessCommitment::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::WitnessCommitment::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::WitnessCommitment::partial_cmp(&self, other: &bitcoin_primitives::WitnessCommitment) -> core::option::Option +pub fn bitcoin_primitives::WitnessMerkleNode::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessMerkleNode::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessMerkleNode::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessMerkleNode::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessMerkleNode::calculate_root>(iter: I) -> core::option::Option +pub fn bitcoin_primitives::WitnessMerkleNode::clone(&self) -> bitcoin_primitives::WitnessMerkleNode +pub fn bitcoin_primitives::WitnessMerkleNode::cmp(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> core::cmp::Ordering +pub fn bitcoin_primitives::WitnessMerkleNode::combine(&self, other: &Self) -> Self +pub fn bitcoin_primitives::WitnessMerkleNode::decoder() -> Self::Decoder +pub fn bitcoin_primitives::WitnessMerkleNode::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::WitnessMerkleNode::eq(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> bool +pub fn bitcoin_primitives::WitnessMerkleNode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::WitnessMerkleNode::from_leaf(leaf: bitcoin_primitives::Wtxid) -> Self +pub fn bitcoin_primitives::WitnessMerkleNode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::WitnessMerkleNode::partial_cmp(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> core::option::Option +pub fn bitcoin_primitives::Wtxid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Wtxid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Wtxid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Wtxid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Wtxid::clone(&self) -> bitcoin_primitives::Wtxid +pub fn bitcoin_primitives::Wtxid::cmp(&self, other: &bitcoin_primitives::Wtxid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Wtxid::eq(&self, other: &bitcoin_primitives::Wtxid) -> bool +pub fn bitcoin_primitives::Wtxid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Wtxid::from(tx: &bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Wtxid::from(tx: bitcoin_primitives::transaction::Transaction) -> Self +pub fn bitcoin_primitives::Wtxid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Wtxid::partial_cmp(&self, other: &bitcoin_primitives::Wtxid) -> core::option::Option +pub fn bitcoin_primitives::block::Block::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Block::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Block::block_hash(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::block::Block::clone(&self) -> bitcoin_primitives::block::Block +pub fn bitcoin_primitives::block::Block::eq(&self, other: &bitcoin_primitives::block::Block) -> bool +pub fn bitcoin_primitives::block::Block::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Block::cached_witness_root(&self) -> core::option::Option +pub fn bitcoin_primitives::block::Block::header(&self) -> &bitcoin_primitives::block::Header +pub fn bitcoin_primitives::block::Block::transactions(&self) -> &[bitcoin_primitives::transaction::Transaction] +pub fn bitcoin_primitives::block::Block::assume_checked(self, witness_root: core::option::Option) -> bitcoin_primitives::block::Block +pub fn bitcoin_primitives::block::Block::check_merkle_root(&self) -> bool +pub fn bitcoin_primitives::block::Block::check_witness_commitment(&self) -> (bool, core::option::Option) +pub fn bitcoin_primitives::block::Block::compute_witness_commitment(&self, witness_reserved_value: &[u8]) -> core::option::Option<(bitcoin_primitives::WitnessMerkleNode, bitcoin_primitives::WitnessCommitment)> +pub fn bitcoin_primitives::block::Block::into_parts(self) -> (bitcoin_primitives::block::Header, alloc::vec::Vec) +pub fn bitcoin_primitives::block::Block::new_unchecked(header: bitcoin_primitives::block::Header, transactions: alloc::vec::Vec) -> Self +pub fn bitcoin_primitives::block::Block::validate(self) -> core::result::Result, bitcoin_primitives::block::InvalidBlockError> +pub fn bitcoin_primitives::block::BlockDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::BlockDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::BlockDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::BlockDecoderError::clone(&self) -> bitcoin_primitives::block::BlockDecoderError +pub fn bitcoin_primitives::block::BlockDecoderError::eq(&self, other: &bitcoin_primitives::block::BlockDecoderError) -> bool +pub fn bitcoin_primitives::block::BlockDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::BlockDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::BlockEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::BlockEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::BlockHashDecoder::default() -> Self +pub fn bitcoin_primitives::block::BlockHashDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::BlockHashDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::BlockHashDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::BlockHashDecoderError::clone(&self) -> bitcoin_primitives::block::BlockHashDecoderError +pub fn bitcoin_primitives::block::BlockHashDecoderError::eq(&self, other: &bitcoin_primitives::block::BlockHashDecoderError) -> bool +pub fn bitcoin_primitives::block::BlockHashDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::BlockHashDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::block::BlockHashDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::BlockHashEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::BlockHashEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::Checked::clone(&self) -> bitcoin_primitives::block::Checked +pub fn bitcoin_primitives::block::Checked::cmp(&self, other: &bitcoin_primitives::block::Checked) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Checked::eq(&self, other: &bitcoin_primitives::block::Checked) -> bool +pub fn bitcoin_primitives::block::Checked::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Checked::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Checked::partial_cmp(&self, other: &bitcoin_primitives::block::Checked) -> core::option::Option +pub fn bitcoin_primitives::block::Header::block_hash(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::block::Header::clone(&self) -> bitcoin_primitives::block::Header +pub fn bitcoin_primitives::block::Header::cmp(&self, other: &bitcoin_primitives::block::Header) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Header::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Header::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Header::eq(&self, other: &bitcoin_primitives::block::Header) -> bool +pub fn bitcoin_primitives::block::Header::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Header::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Header::partial_cmp(&self, other: &bitcoin_primitives::block::Header) -> core::option::Option +pub fn bitcoin_primitives::block::HeaderDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::HeaderDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::HeaderDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::HeaderDecoderError::clone(&self) -> bitcoin_primitives::block::HeaderDecoderError +pub fn bitcoin_primitives::block::HeaderDecoderError::eq(&self, other: &bitcoin_primitives::block::HeaderDecoderError) -> bool +pub fn bitcoin_primitives::block::HeaderDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::HeaderDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::HeaderEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::HeaderEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::InvalidBlockError::clone(&self) -> bitcoin_primitives::block::InvalidBlockError +pub fn bitcoin_primitives::block::InvalidBlockError::eq(&self, other: &bitcoin_primitives::block::InvalidBlockError) -> bool +pub fn bitcoin_primitives::block::InvalidBlockError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::InvalidBlockError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::Unchecked::clone(&self) -> bitcoin_primitives::block::Unchecked +pub fn bitcoin_primitives::block::Unchecked::cmp(&self, other: &bitcoin_primitives::block::Unchecked) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Unchecked::eq(&self, other: &bitcoin_primitives::block::Unchecked) -> bool +pub fn bitcoin_primitives::block::Unchecked::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Unchecked::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Unchecked::partial_cmp(&self, other: &bitcoin_primitives::block::Unchecked) -> core::option::Option +pub fn bitcoin_primitives::block::Version::clone(&self) -> bitcoin_primitives::block::Version +pub fn bitcoin_primitives::block::Version::cmp(&self, other: &bitcoin_primitives::block::Version) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Version::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Version::default() -> Self +pub fn bitcoin_primitives::block::Version::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Version::eq(&self, other: &bitcoin_primitives::block::Version) -> bool +pub fn bitcoin_primitives::block::Version::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Version::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Version::is_signalling_soft_fork(self, bit: u8) -> bool +pub fn bitcoin_primitives::block::Version::partial_cmp(&self, other: &bitcoin_primitives::block::Version) -> core::option::Option +pub fn bitcoin_primitives::block::VersionDecoder::default() -> Self +pub fn bitcoin_primitives::block::VersionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::VersionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::VersionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::VersionDecoderError::clone(&self) -> bitcoin_primitives::block::VersionDecoderError +pub fn bitcoin_primitives::block::VersionDecoderError::eq(&self, other: &bitcoin_primitives::block::VersionDecoderError) -> bool +pub fn bitcoin_primitives::block::VersionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::VersionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::block::VersionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::VersionEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::VersionEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::compute_merkle_root(transactions: &[bitcoin_primitives::transaction::Transaction]) -> core::option::Option +pub fn bitcoin_primitives::block::compute_witness_root(transactions: &[bitcoin_primitives::transaction::Transaction]) -> core::option::Option +pub fn bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::pow::CompactTarget::clone(&self) -> bitcoin_primitives::pow::CompactTarget +pub fn bitcoin_primitives::pow::CompactTarget::cmp(&self, other: &bitcoin_primitives::pow::CompactTarget) -> core::cmp::Ordering +pub fn bitcoin_primitives::pow::CompactTarget::decoder() -> Self::Decoder +pub fn bitcoin_primitives::pow::CompactTarget::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::pow::CompactTarget::eq(&self, other: &bitcoin_primitives::pow::CompactTarget) -> bool +pub fn bitcoin_primitives::pow::CompactTarget::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::pow::CompactTarget::from_consensus(bits: u32) -> Self +pub fn bitcoin_primitives::pow::CompactTarget::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::pow::CompactTarget::partial_cmp(&self, other: &bitcoin_primitives::pow::CompactTarget) -> core::option::Option +pub fn bitcoin_primitives::pow::CompactTarget::to_hex(self) -> alloc::string::String +pub fn bitcoin_primitives::pow::CompactTargetDecoder::default() -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::clone(&self) -> bitcoin_primitives::pow::CompactTargetDecoderError +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::eq(&self, other: &bitcoin_primitives::pow::CompactTargetDecoderError) -> bool +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::pow::CompactTargetEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::pow::CompactTargetEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::script::RedeemScriptSizeError::clone(&self) -> bitcoin_primitives::script::RedeemScriptSizeError +pub fn bitcoin_primitives::script::RedeemScriptSizeError::eq(&self, other: &bitcoin_primitives::script::RedeemScriptSizeError) -> bool +pub fn bitcoin_primitives::script::RedeemScriptSizeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::RedeemScriptSizeError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::script::RedeemScriptSizeError::invalid_size(&self) -> usize +pub fn bitcoin_primitives::script::RedeemScriptTag::clone(&self) -> bitcoin_primitives::script::RedeemScriptTag +pub fn bitcoin_primitives::script::RedeemScriptTag::cmp(&self, other: &bitcoin_primitives::script::RedeemScriptTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::RedeemScriptTag::eq(&self, other: &bitcoin_primitives::script::RedeemScriptTag) -> bool +pub fn bitcoin_primitives::script::RedeemScriptTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::RedeemScriptTag::partial_cmp(&self, other: &bitcoin_primitives::script::RedeemScriptTag) -> core::option::Option +pub fn bitcoin_primitives::script::Script::as_mut(&mut self) -> &mut Self +pub fn bitcoin_primitives::script::Script::as_mut(&mut self) -> &mut [u8] +pub fn bitcoin_primitives::script::Script::as_mut_bytes(&mut self) -> &mut [u8] +pub fn bitcoin_primitives::script::Script::as_ref(&self) -> &Self +pub fn bitcoin_primitives::script::Script::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::Script::cmp(&self, other: &bitcoin_primitives::script::Script) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::Script::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::script::Script::eq(&self, other: &bitcoin_primitives::script::Script) -> bool +pub fn bitcoin_primitives::script::Script::eq(&self, other: &bitcoin_primitives::script::ScriptBuf) -> bool +pub fn bitcoin_primitives::script::Script::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::Script::from_bytes_mut(bytes: &mut [u8]) -> &mut Self +pub fn bitcoin_primitives::script::Script::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::Script::index(&self, index: (core::ops::range::Bound, core::ops::range::Bound)) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::Range) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeFrom) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeFull) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeInclusive) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeTo) -> &Self::Output +pub fn bitcoin_primitives::script::Script::index(&self, index: core::ops::range::RangeToInclusive) -> &Self::Output +pub fn bitcoin_primitives::script::Script::into_script_buf(self: alloc::boxed::Box) -> bitcoin_primitives::script::ScriptBuf +pub fn bitcoin_primitives::script::Script::partial_cmp(&self, other: &bitcoin_primitives::script::Script) -> core::option::Option +pub fn bitcoin_primitives::script::Script::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptBuf) -> core::option::Option +pub fn bitcoin_primitives::script::Script::to_bytes(&self) -> alloc::vec::Vec +pub fn bitcoin_primitives::script::Script::to_owned(&self) -> Self::Owned +pub fn bitcoin_primitives::script::Script::to_vec(&self) -> alloc::vec::Vec +pub fn bitcoin_primitives::script::ScriptBuf::as_mut(&mut self) -> &mut [u8] +pub fn bitcoin_primitives::script::ScriptBuf::as_mut(&mut self) -> &mut bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::as_mut_script(&mut self) -> &mut bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptBuf::as_ref(&self) -> &bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::as_script(&self) -> &bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::borrow(&self) -> &bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::borrow_mut(&mut self) -> &mut bitcoin_primitives::script::Script +pub fn bitcoin_primitives::script::ScriptBuf::capacity(&self) -> usize +pub fn bitcoin_primitives::script::ScriptBuf::clone(&self) -> bitcoin_primitives::script::ScriptBuf +pub fn bitcoin_primitives::script::ScriptBuf::cmp(&self, other: &bitcoin_primitives::script::ScriptBuf) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptBuf::decoder() -> Self::Decoder +pub fn bitcoin_primitives::script::ScriptBuf::default() -> Self +pub fn bitcoin_primitives::script::ScriptBuf::deref(&self) -> &Self::Target +pub fn bitcoin_primitives::script::ScriptBuf::deref_mut(&mut self) -> &mut Self::Target +pub fn bitcoin_primitives::script::ScriptBuf::eq(&self, other: &bitcoin_primitives::script::Script) -> bool +pub fn bitcoin_primitives::script::ScriptBuf::eq(&self, other: &bitcoin_primitives::script::ScriptBuf) -> bool +pub fn bitcoin_primitives::script::ScriptBuf::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::ScriptBuf::from(v: alloc::vec::Vec) -> Self +pub fn bitcoin_primitives::script::ScriptBuf::from(value: &'a bitcoin_primitives::script::Script) -> Self +pub fn bitcoin_primitives::script::ScriptBuf::from(value: alloc::borrow::Cow<'a, bitcoin_primitives::script::Script>) -> Self +pub fn bitcoin_primitives::script::ScriptBuf::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptBuf::into_boxed_script(self) -> alloc::boxed::Box> +pub fn bitcoin_primitives::script::ScriptBuf::into_bytes(self) -> alloc::vec::Vec +pub fn bitcoin_primitives::script::ScriptBuf::partial_cmp(&self, other: &bitcoin_primitives::script::Script) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptBuf::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptBuf) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptBuf::reserve(&mut self, additional_len: usize) +pub fn bitcoin_primitives::script::ScriptBuf::reserve_exact(&mut self, additional_len: usize) +pub fn bitcoin_primitives::script::ScriptBuf::with_capacity(capacity: usize) -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoder::default() -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptBufDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptBufDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::script::ScriptBufDecoderError::clone(&self) -> bitcoin_primitives::script::ScriptBufDecoderError +pub fn bitcoin_primitives::script::ScriptBufDecoderError::eq(&self, other: &bitcoin_primitives::script::ScriptBufDecoderError) -> bool +pub fn bitcoin_primitives::script::ScriptBufDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::ScriptBufDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::ByteVecDecoderError) -> Self +pub fn bitcoin_primitives::script::ScriptBufDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::script::ScriptEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::script::ScriptEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptHash::as_ref(&self) -> &[u8; 20] +pub fn bitcoin_primitives::script::ScriptHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptHash::borrow(&self) -> &[u8; 20] +pub fn bitcoin_primitives::script::ScriptHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::script::ScriptHash::clone(&self) -> bitcoin_primitives::script::ScriptHash +pub fn bitcoin_primitives::script::ScriptHash::cmp(&self, other: &bitcoin_primitives::script::ScriptHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptHash::eq(&self, other: &bitcoin_primitives::script::ScriptHash) -> bool +pub fn bitcoin_primitives::script::ScriptHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::ScriptHash::from_script(redeem_script: &bitcoin_primitives::script::Script) -> core::result::Result where T: bitcoin_primitives::script::ScriptHashableTag +pub fn bitcoin_primitives::script::ScriptHash::from_script_unchecked(script: &bitcoin_primitives::script::Script) -> Self +pub fn bitcoin_primitives::script::ScriptHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptHash::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptHash) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptHash::try_from(redeem_script: &bitcoin_primitives::script::Script) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptHash::try_from(redeem_script: &bitcoin_primitives::script::ScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptHash::try_from(redeem_script: bitcoin_primitives::script::ScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::ScriptPubKeyTag::clone(&self) -> bitcoin_primitives::script::ScriptPubKeyTag +pub fn bitcoin_primitives::script::ScriptPubKeyTag::cmp(&self, other: &bitcoin_primitives::script::ScriptPubKeyTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptPubKeyTag::eq(&self, other: &bitcoin_primitives::script::ScriptPubKeyTag) -> bool +pub fn bitcoin_primitives::script::ScriptPubKeyTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptPubKeyTag::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptPubKeyTag) -> core::option::Option +pub fn bitcoin_primitives::script::ScriptSigTag::clone(&self) -> bitcoin_primitives::script::ScriptSigTag +pub fn bitcoin_primitives::script::ScriptSigTag::cmp(&self, other: &bitcoin_primitives::script::ScriptSigTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::ScriptSigTag::eq(&self, other: &bitcoin_primitives::script::ScriptSigTag) -> bool +pub fn bitcoin_primitives::script::ScriptSigTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::ScriptSigTag::partial_cmp(&self, other: &bitcoin_primitives::script::ScriptSigTag) -> core::option::Option +pub fn bitcoin_primitives::script::TapScriptTag::clone(&self) -> bitcoin_primitives::script::TapScriptTag +pub fn bitcoin_primitives::script::TapScriptTag::cmp(&self, other: &bitcoin_primitives::script::TapScriptTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::TapScriptTag::eq(&self, other: &bitcoin_primitives::script::TapScriptTag) -> bool +pub fn bitcoin_primitives::script::TapScriptTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::TapScriptTag::partial_cmp(&self, other: &bitcoin_primitives::script::TapScriptTag) -> core::option::Option +pub fn bitcoin_primitives::script::WScriptHash::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::script::WScriptHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::script::WScriptHash::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::script::WScriptHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::script::WScriptHash::clone(&self) -> bitcoin_primitives::script::WScriptHash +pub fn bitcoin_primitives::script::WScriptHash::cmp(&self, other: &bitcoin_primitives::script::WScriptHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::WScriptHash::eq(&self, other: &bitcoin_primitives::script::WScriptHash) -> bool +pub fn bitcoin_primitives::script::WScriptHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::WScriptHash::from_script(witness_script: &bitcoin_primitives::script::WitnessScript) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::from_script_unchecked(script: &bitcoin_primitives::script::WitnessScript) -> Self +pub fn bitcoin_primitives::script::WScriptHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::WScriptHash::partial_cmp(&self, other: &bitcoin_primitives::script::WScriptHash) -> core::option::Option +pub fn bitcoin_primitives::script::WScriptHash::try_from(witness_script: &bitcoin_primitives::script::WitnessScript) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::try_from(witness_script: &bitcoin_primitives::script::WitnessScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::WScriptHash::try_from(witness_script: bitcoin_primitives::script::WitnessScriptBuf) -> core::result::Result +pub fn bitcoin_primitives::script::WitnessScriptSizeError::clone(&self) -> bitcoin_primitives::script::WitnessScriptSizeError +pub fn bitcoin_primitives::script::WitnessScriptSizeError::eq(&self, other: &bitcoin_primitives::script::WitnessScriptSizeError) -> bool +pub fn bitcoin_primitives::script::WitnessScriptSizeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::script::WitnessScriptSizeError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::script::WitnessScriptSizeError::invalid_size(&self) -> usize +pub fn bitcoin_primitives::script::WitnessScriptTag::clone(&self) -> bitcoin_primitives::script::WitnessScriptTag +pub fn bitcoin_primitives::script::WitnessScriptTag::cmp(&self, other: &bitcoin_primitives::script::WitnessScriptTag) -> core::cmp::Ordering +pub fn bitcoin_primitives::script::WitnessScriptTag::eq(&self, other: &bitcoin_primitives::script::WitnessScriptTag) -> bool +pub fn bitcoin_primitives::script::WitnessScriptTag::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::script::WitnessScriptTag::partial_cmp(&self, other: &bitcoin_primitives::script::WitnessScriptTag) -> core::option::Option +pub fn bitcoin_primitives::transaction::OutPoint::clone(&self) -> bitcoin_primitives::transaction::OutPoint +pub fn bitcoin_primitives::transaction::OutPoint::cmp(&self, other: &bitcoin_primitives::transaction::OutPoint) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::OutPoint::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::OutPoint::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::OutPoint::eq(&self, other: &bitcoin_primitives::transaction::OutPoint) -> bool +pub fn bitcoin_primitives::transaction::OutPoint::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::OutPoint::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::OutPoint::partial_cmp(&self, other: &bitcoin_primitives::transaction::OutPoint) -> core::option::Option +pub fn bitcoin_primitives::transaction::OutPointDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::OutPointDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPointDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPointDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::OutPointDecoderError::clone(&self) -> bitcoin_primitives::transaction::OutPointDecoderError +pub fn bitcoin_primitives::transaction::OutPointDecoderError::eq(&self, other: &bitcoin_primitives::transaction::OutPointDecoderError) -> bool +pub fn bitcoin_primitives::transaction::OutPointDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::OutPointEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::OutPointEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::Transaction::clone(&self) -> bitcoin_primitives::transaction::Transaction +pub fn bitcoin_primitives::transaction::Transaction::cmp(&self, other: &Self) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::Transaction::compute_ntxid(&self) -> bitcoin_primitives::Ntxid +pub fn bitcoin_primitives::transaction::Transaction::compute_txid(&self) -> bitcoin_primitives::Txid +pub fn bitcoin_primitives::transaction::Transaction::compute_wtxid(&self) -> bitcoin_primitives::Wtxid +pub fn bitcoin_primitives::transaction::Transaction::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::Transaction::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::Transaction::eq(&self, other: &bitcoin_primitives::transaction::Transaction) -> bool +pub fn bitcoin_primitives::transaction::Transaction::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::Transaction::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::Transaction::is_coinbase(&self) -> bool +pub fn bitcoin_primitives::transaction::Transaction::partial_cmp(&self, other: &Self) -> core::option::Option +pub fn bitcoin_primitives::transaction::TransactionDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TransactionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TransactionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TransactionDecoderError::clone(&self) -> bitcoin_primitives::transaction::TransactionDecoderError +pub fn bitcoin_primitives::transaction::TransactionDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TransactionDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TransactionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::VecDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::VecDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_primitives::transaction::VersionDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_primitives::witness::WitnessDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(e: bitcoin_units::locktime::absolute::error::LockTimeDecoderError) -> Self +pub fn bitcoin_primitives::transaction::TransactionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TransactionEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::TransactionEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::TxIn::clone(&self) -> bitcoin_primitives::transaction::TxIn +pub fn bitcoin_primitives::transaction::TxIn::cmp(&self, other: &bitcoin_primitives::transaction::TxIn) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::TxIn::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::TxIn::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::TxIn::eq(&self, other: &bitcoin_primitives::transaction::TxIn) -> bool +pub fn bitcoin_primitives::transaction::TxIn::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxIn::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::TxIn::partial_cmp(&self, other: &bitcoin_primitives::transaction::TxIn) -> core::option::Option +pub fn bitcoin_primitives::transaction::TxInDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxInDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxInDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxInDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxInDecoderError +pub fn bitcoin_primitives::transaction::TxInDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxInDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxInDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxInDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TxInEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::TxInEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxMerkleNodeDecoderError +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxMerkleNodeDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TxOut::clone(&self) -> bitcoin_primitives::transaction::TxOut +pub fn bitcoin_primitives::transaction::TxOut::cmp(&self, other: &bitcoin_primitives::transaction::TxOut) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::TxOut::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::TxOut::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::TxOut::eq(&self, other: &bitcoin_primitives::transaction::TxOut) -> bool +pub fn bitcoin_primitives::transaction::TxOut::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxOut::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::TxOut::partial_cmp(&self, other: &bitcoin_primitives::transaction::TxOut) -> core::option::Option +pub fn bitcoin_primitives::transaction::TxOutDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxOutDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxOutDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxOutDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxOutDecoderError +pub fn bitcoin_primitives::transaction::TxOutDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxOutDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxOutDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxOutDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::TxOutEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::TxOutEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::Version::clone(&self) -> bitcoin_primitives::transaction::Version +pub fn bitcoin_primitives::transaction::Version::cmp(&self, other: &bitcoin_primitives::transaction::Version) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::Version::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::Version::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::Version::eq(&self, other: &bitcoin_primitives::transaction::Version) -> bool +pub fn bitcoin_primitives::transaction::Version::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::Version::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::Version::partial_cmp(&self, other: &bitcoin_primitives::transaction::Version) -> core::option::Option +pub fn bitcoin_primitives::transaction::VersionDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::VersionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::VersionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::VersionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::VersionDecoderError::clone(&self) -> bitcoin_primitives::transaction::VersionDecoderError +pub fn bitcoin_primitives::transaction::VersionDecoderError::eq(&self, other: &bitcoin_primitives::transaction::VersionDecoderError) -> bool +pub fn bitcoin_primitives::transaction::VersionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::VersionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::VersionEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::VersionEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::new(inputs: &'e [bitcoin_primitives::transaction::TxIn]) -> Self +pub fn bitcoin_primitives::witness::Iter<'a>::clone(&self) -> bitcoin_primitives::witness::Iter<'a> +pub fn bitcoin_primitives::witness::Iter<'a>::next(&mut self) -> core::option::Option +pub fn bitcoin_primitives::witness::Iter<'a>::size_hint(&self) -> (usize, core::option::Option) +pub fn bitcoin_primitives::witness::UnexpectedEofError::clone(&self) -> bitcoin_primitives::witness::UnexpectedEofError +pub fn bitcoin_primitives::witness::UnexpectedEofError::eq(&self, other: &bitcoin_primitives::witness::UnexpectedEofError) -> bool +pub fn bitcoin_primitives::witness::UnexpectedEofError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::witness::Witness::clear(&mut self) +pub fn bitcoin_primitives::witness::Witness::clone(&self) -> bitcoin_primitives::witness::Witness +pub fn bitcoin_primitives::witness::Witness::cmp(&self, other: &bitcoin_primitives::witness::Witness) -> core::cmp::Ordering +pub fn bitcoin_primitives::witness::Witness::decoder() -> Self::Decoder +pub fn bitcoin_primitives::witness::Witness::default() -> Self +pub fn bitcoin_primitives::witness::Witness::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::witness::Witness::eq(&self, other: &bitcoin_primitives::witness::Witness) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &&[T; N]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &&[T]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &[T; N]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &[T]) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::boxed::Box<[T]>) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::rc::Rc<[T]>) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::sync::Arc<[T]>) -> bool +pub fn bitcoin_primitives::witness::Witness::eq(&self, rhs: &alloc::vec::Vec) -> bool +pub fn bitcoin_primitives::witness::Witness::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::witness::Witness::from(arr: &[&[u8]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(arr: [&[u8]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[&[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[&[u8; N]]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[&[u8]]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[[u8; N]]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: &[alloc::vec::Vec]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: [&[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(slice: [[u8; M]; N]) -> Self +pub fn bitcoin_primitives::witness::Witness::from(vec: alloc::vec::Vec<&[u8]>) -> Self +pub fn bitcoin_primitives::witness::Witness::from(vec: alloc::vec::Vec>) -> Self +pub fn bitcoin_primitives::witness::Witness::from_iter>(iter: I) -> Self +pub fn bitcoin_primitives::witness::Witness::from_slice>(slice: &[T]) -> Self +pub fn bitcoin_primitives::witness::Witness::get(&self, index: usize) -> core::option::Option<&[u8]> +pub fn bitcoin_primitives::witness::Witness::get_back(&self, index: usize) -> core::option::Option<&[u8]> +pub fn bitcoin_primitives::witness::Witness::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::witness::Witness::index(&self, index: usize) -> &Self::Output +pub fn bitcoin_primitives::witness::Witness::is_empty(&self) -> bool +pub fn bitcoin_primitives::witness::Witness::iter(&self) -> bitcoin_primitives::witness::Iter<'_> +pub fn bitcoin_primitives::witness::Witness::last(&self) -> core::option::Option<&[u8]> +pub fn bitcoin_primitives::witness::Witness::partial_cmp(&self, other: &bitcoin_primitives::witness::Witness) -> core::option::Option +pub fn bitcoin_primitives::witness::Witness::push>(&mut self, new_element: T) +pub fn bitcoin_primitives::witness::Witness::size(&self) -> usize +pub fn bitcoin_primitives::witness::Witness::to_vec(&self) -> alloc::vec::Vec> +pub fn bitcoin_primitives::witness::WitnessDecoder::default() -> Self +pub fn bitcoin_primitives::witness::WitnessDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::witness::WitnessDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::witness::WitnessDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::witness::WitnessDecoderError::clone(&self) -> bitcoin_primitives::witness::WitnessDecoderError +pub fn bitcoin_primitives::witness::WitnessDecoderError::eq(&self, other: &bitcoin_primitives::witness::WitnessDecoderError) -> bool +pub fn bitcoin_primitives::witness::WitnessDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::witness::WitnessDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::witness::WitnessEncoder<'_>::advance(&mut self) -> bool +pub fn bitcoin_primitives::witness::WitnessEncoder<'_>::current_chunk(&self) -> &[u8] +pub fn u32::from(version: bitcoin_primitives::transaction::Version) -> Self +pub mod bitcoin_primitives +pub mod bitcoin_primitives::block +pub mod bitcoin_primitives::merkle_tree +pub mod bitcoin_primitives::pow +pub mod bitcoin_primitives::script +pub mod bitcoin_primitives::transaction +pub mod bitcoin_primitives::witness +pub struct bitcoin_primitives::Block where V: bitcoin_primitives::block::Validation +pub struct bitcoin_primitives::BlockHash(_) +pub struct bitcoin_primitives::BlockHeader +pub struct bitcoin_primitives::BlockVersion(_) +pub struct bitcoin_primitives::CompactTarget(_) +pub struct bitcoin_primitives::Ntxid(_) +pub struct bitcoin_primitives::OutPoint +pub struct bitcoin_primitives::Transaction +pub struct bitcoin_primitives::TransactionVersion(_) +pub struct bitcoin_primitives::TxIn +pub struct bitcoin_primitives::TxMerkleNode(_) +pub struct bitcoin_primitives::TxOut +pub struct bitcoin_primitives::Txid(_) +pub struct bitcoin_primitives::Witness +pub struct bitcoin_primitives::WitnessCommitment(_) +pub struct bitcoin_primitives::WitnessMerkleNode(_) +pub struct bitcoin_primitives::Wtxid(_) +pub struct bitcoin_primitives::block::Block where V: bitcoin_primitives::block::Validation +pub struct bitcoin_primitives::block::BlockDecoder(_) +pub struct bitcoin_primitives::block::BlockDecoderError(_) +pub struct bitcoin_primitives::block::BlockEncoder<'e>(_) +pub struct bitcoin_primitives::block::BlockHash(_) +pub struct bitcoin_primitives::block::BlockHashDecoder(_) +pub struct bitcoin_primitives::block::BlockHashDecoderError(_) +pub struct bitcoin_primitives::block::BlockHashEncoder(_) +pub struct bitcoin_primitives::block::Header +pub struct bitcoin_primitives::block::HeaderDecoder(_) +pub struct bitcoin_primitives::block::HeaderEncoder(_) +pub struct bitcoin_primitives::block::Version(_) +pub struct bitcoin_primitives::block::VersionDecoder(_) +pub struct bitcoin_primitives::block::VersionDecoderError(_) +pub struct bitcoin_primitives::block::VersionEncoder(_) +pub struct bitcoin_primitives::block::WitnessCommitment(_) +pub struct bitcoin_primitives::merkle_tree::TxMerkleNode(_) +pub struct bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder(_) +pub struct bitcoin_primitives::merkle_tree::WitnessMerkleNode(_) +pub struct bitcoin_primitives::pow::CompactTarget(_) +pub struct bitcoin_primitives::pow::CompactTargetDecoder(_) +pub struct bitcoin_primitives::pow::CompactTargetDecoderError(_) +pub struct bitcoin_primitives::pow::CompactTargetEncoder(_) +pub struct bitcoin_primitives::script::RedeemScriptSizeError +pub struct bitcoin_primitives::script::ScriptBuf(_, _) +pub struct bitcoin_primitives::script::ScriptBufDecoder(_, _) +pub struct bitcoin_primitives::script::ScriptBufDecoderError(_) +pub struct bitcoin_primitives::script::ScriptEncoder<'e>(_) +pub struct bitcoin_primitives::script::ScriptHash(_) +pub struct bitcoin_primitives::script::WScriptHash(_) +pub struct bitcoin_primitives::script::WitnessScriptSizeError +pub struct bitcoin_primitives::transaction::BlockHashDecoder(_) +pub struct bitcoin_primitives::transaction::BlockHashDecoderError(_) +pub struct bitcoin_primitives::transaction::Ntxid(_) +pub struct bitcoin_primitives::transaction::OutPoint +pub struct bitcoin_primitives::transaction::OutPointDecoder(_) +pub struct bitcoin_primitives::transaction::OutPointDecoderError(_) +pub struct bitcoin_primitives::transaction::OutPointEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::Transaction +pub struct bitcoin_primitives::transaction::TransactionDecoder +pub struct bitcoin_primitives::transaction::TransactionDecoderError(_) +pub struct bitcoin_primitives::transaction::TransactionEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::TxIn +pub struct bitcoin_primitives::transaction::TxInDecoder(_) +pub struct bitcoin_primitives::transaction::TxInDecoderError(_) +pub struct bitcoin_primitives::transaction::TxInEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::TxMerkleNodeDecoder(_) +pub struct bitcoin_primitives::transaction::TxMerkleNodeDecoderError(_) +pub struct bitcoin_primitives::transaction::TxOut +pub struct bitcoin_primitives::transaction::TxOutDecoder(_) +pub struct bitcoin_primitives::transaction::TxOutDecoderError(_) +pub struct bitcoin_primitives::transaction::TxOutEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::Txid(_) +pub struct bitcoin_primitives::transaction::Version(_) +pub struct bitcoin_primitives::transaction::VersionDecoder(_) +pub struct bitcoin_primitives::transaction::VersionDecoderError(_) +pub struct bitcoin_primitives::transaction::VersionEncoder(_) +pub struct bitcoin_primitives::transaction::WitnessesEncoder<'e> +pub struct bitcoin_primitives::transaction::Wtxid(_) +pub struct bitcoin_primitives::witness::Iter<'a> +pub struct bitcoin_primitives::witness::UnexpectedEofError +pub struct bitcoin_primitives::witness::Witness +pub struct bitcoin_primitives::witness::WitnessDecoder +pub struct bitcoin_primitives::witness::WitnessDecoderError(_) +pub struct bitcoin_primitives::witness::WitnessEncoder<'a>(_) +pub trait bitcoin_primitives::BlockValidation: bitcoin_primitives::block::sealed::Validation + core::marker::Sync + core::marker::Send + core::marker::Sized + core::marker::Unpin +pub trait bitcoin_primitives::block::Validation: bitcoin_primitives::block::sealed::Validation + core::marker::Sync + core::marker::Send + core::marker::Sized + core::marker::Unpin +pub trait bitcoin_primitives::script::ScriptHashableTag: bitcoin_primitives::script::sealed::Sealed +pub trait bitcoin_primitives::script::Tag +pub type &'a bitcoin_primitives::witness::Witness::IntoIter = bitcoin_primitives::witness::Iter<'a> +pub type &'a bitcoin_primitives::witness::Witness::Item = &'a [u8] +pub type bitcoin_primitives::BlockHash::Decoder = bitcoin_primitives::block::BlockHashDecoder +pub type bitcoin_primitives::BlockHash::Encoder<'e> = bitcoin_primitives::block::BlockHashEncoder +pub type bitcoin_primitives::RedeemScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::RedeemScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::ScriptPubKey = bitcoin_primitives::script::Script +pub type bitcoin_primitives::ScriptPubKeyBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::ScriptSig = bitcoin_primitives::script::Script +pub type bitcoin_primitives::ScriptSigBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::TapScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::TapScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::TxMerkleNode::Decoder = bitcoin_primitives::transaction::TxMerkleNodeDecoder +pub type bitcoin_primitives::TxMerkleNode::Encoder<'e> = bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +pub type bitcoin_primitives::WitnessMerkleNode::Decoder = bitcoin_primitives::hash_types::witness_merkle_node::WitnessMerkleNodeDecoder +pub type bitcoin_primitives::WitnessMerkleNode::Encoder<'e> = bitcoin_primitives::hash_types::witness_merkle_node::WitnessMerkleNodeEncoder +pub type bitcoin_primitives::WitnessScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::WitnessScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::block::Block::Decoder = bitcoin_primitives::block::BlockDecoder +pub type bitcoin_primitives::block::Block::Encoder<'e> where Self: 'e = bitcoin_consensus_encoding::encode::encoders::Encoder2>> +pub type bitcoin_primitives::block::BlockDecoder::Error = bitcoin_primitives::block::BlockDecoderError +pub type bitcoin_primitives::block::BlockDecoder::Output = bitcoin_primitives::block::Block +pub type bitcoin_primitives::block::BlockHashDecoder::Error = bitcoin_primitives::block::BlockHashDecoderError +pub type bitcoin_primitives::block::BlockHashDecoder::Output = bitcoin_primitives::BlockHash +pub type bitcoin_primitives::block::Header::Decoder = bitcoin_primitives::block::HeaderDecoder +pub type bitcoin_primitives::block::Header::Encoder<'e> = bitcoin_primitives::block::HeaderEncoder +pub type bitcoin_primitives::block::HeaderDecoder::Error = bitcoin_primitives::block::HeaderDecoderError +pub type bitcoin_primitives::block::HeaderDecoder::Output = bitcoin_primitives::block::Header +pub type bitcoin_primitives::block::Version::Decoder = bitcoin_primitives::block::VersionDecoder +pub type bitcoin_primitives::block::Version::Encoder<'e> = bitcoin_primitives::block::VersionEncoder +pub type bitcoin_primitives::block::VersionDecoder::Error = bitcoin_primitives::block::VersionDecoderError +pub type bitcoin_primitives::block::VersionDecoder::Output = bitcoin_primitives::block::Version +pub type bitcoin_primitives::pow::CompactTarget::Decoder = bitcoin_primitives::pow::CompactTargetDecoder +pub type bitcoin_primitives::pow::CompactTarget::Encoder<'e> = bitcoin_primitives::pow::CompactTargetEncoder +pub type bitcoin_primitives::pow::CompactTargetDecoder::Error = bitcoin_primitives::pow::CompactTargetDecoderError +pub type bitcoin_primitives::pow::CompactTargetDecoder::Output = bitcoin_primitives::pow::CompactTarget +pub type bitcoin_primitives::script::RedeemScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::RedeemScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::Script::Encoder<'a> where Self: 'a = bitcoin_primitives::script::ScriptEncoder<'a> +pub type bitcoin_primitives::script::Script::Output = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::Script::Owned = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptBuf::Decoder = bitcoin_primitives::script::ScriptBufDecoder +pub type bitcoin_primitives::script::ScriptBuf::Target = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::ScriptBufDecoder::Error = bitcoin_primitives::script::ScriptBufDecoderError +pub type bitcoin_primitives::script::ScriptBufDecoder::Output = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptHash::Error = bitcoin_primitives::script::RedeemScriptSizeError +pub type bitcoin_primitives::script::ScriptPubKey = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::ScriptPubKeyBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptPubKeyBufDecoder = bitcoin_primitives::script::ScriptBufDecoder +pub type bitcoin_primitives::script::ScriptSig = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::ScriptSigBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::ScriptSigBufDecoder = bitcoin_primitives::script::ScriptBufDecoder +pub type bitcoin_primitives::script::TapScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::TapScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::script::WScriptHash::Error = bitcoin_primitives::script::WitnessScriptSizeError +pub type bitcoin_primitives::script::WitnessScript = bitcoin_primitives::script::Script +pub type bitcoin_primitives::script::WitnessScriptBuf = bitcoin_primitives::script::ScriptBuf +pub type bitcoin_primitives::transaction::OutPoint::Decoder = bitcoin_primitives::transaction::OutPointDecoder +pub type bitcoin_primitives::transaction::OutPoint::Encoder<'e> where Self: 'e = bitcoin_primitives::transaction::OutPointEncoder<'e> +pub type bitcoin_primitives::transaction::OutPointDecoder::Error = bitcoin_primitives::transaction::OutPointDecoderError +pub type bitcoin_primitives::transaction::OutPointDecoder::Output = bitcoin_primitives::transaction::OutPoint +pub type bitcoin_primitives::transaction::Transaction::Decoder = bitcoin_primitives::transaction::TransactionDecoder +pub type bitcoin_primitives::transaction::Transaction::Encoder<'e> where Self: 'e = bitcoin_primitives::transaction::TransactionEncoder<'e> +pub type bitcoin_primitives::transaction::TransactionDecoder::Error = bitcoin_primitives::transaction::TransactionDecoderError +pub type bitcoin_primitives::transaction::TransactionDecoder::Output = bitcoin_primitives::transaction::Transaction +pub type bitcoin_primitives::transaction::TxIn::Decoder = bitcoin_primitives::transaction::TxInDecoder +pub type bitcoin_primitives::transaction::TxIn::Encoder<'e> where Self: 'e = bitcoin_consensus_encoding::encode::encoders::Encoder3, bitcoin_primitives::script::ScriptEncoder<'e>, bitcoin_units::sequence::SequenceEncoder> +pub type bitcoin_primitives::transaction::TxInDecoder::Error = bitcoin_primitives::transaction::TxInDecoderError +pub type bitcoin_primitives::transaction::TxInDecoder::Output = bitcoin_primitives::transaction::TxIn +pub type bitcoin_primitives::transaction::TxMerkleNodeDecoder::Error = bitcoin_primitives::transaction::TxMerkleNodeDecoderError +pub type bitcoin_primitives::transaction::TxMerkleNodeDecoder::Output = bitcoin_primitives::TxMerkleNode +pub type bitcoin_primitives::transaction::TxOut::Decoder = bitcoin_primitives::transaction::TxOutDecoder +pub type bitcoin_primitives::transaction::TxOut::Encoder<'e> where Self: 'e = bitcoin_consensus_encoding::encode::encoders::Encoder2> +pub type bitcoin_primitives::transaction::TxOutDecoder::Error = bitcoin_primitives::transaction::TxOutDecoderError +pub type bitcoin_primitives::transaction::TxOutDecoder::Output = bitcoin_primitives::transaction::TxOut +pub type bitcoin_primitives::transaction::Version::Decoder = bitcoin_primitives::transaction::VersionDecoder +pub type bitcoin_primitives::transaction::Version::Encoder<'e> = bitcoin_primitives::transaction::VersionEncoder +pub type bitcoin_primitives::transaction::VersionDecoder::Error = bitcoin_primitives::transaction::VersionDecoderError +pub type bitcoin_primitives::transaction::VersionDecoder::Output = bitcoin_primitives::transaction::Version +pub type bitcoin_primitives::witness::Iter<'a>::Item = &'a [u8] +pub type bitcoin_primitives::witness::Witness::Decoder = bitcoin_primitives::witness::WitnessDecoder +pub type bitcoin_primitives::witness::Witness::Encoder<'a> where Self: 'a = bitcoin_primitives::witness::WitnessEncoder<'a> +pub type bitcoin_primitives::witness::Witness::Output = [u8] +pub type bitcoin_primitives::witness::WitnessDecoder::Error = bitcoin_primitives::witness::WitnessDecoderError +pub type bitcoin_primitives::witness::WitnessDecoder::Output = bitcoin_primitives::witness::Witness +pub use bitcoin_primitives::Amount +pub use bitcoin_primitives::BlockHeight +pub use bitcoin_primitives::BlockHeightInterval +pub use bitcoin_primitives::BlockMtp +pub use bitcoin_primitives::BlockMtpInterval +pub use bitcoin_primitives::BlockTime +pub use bitcoin_primitives::BlockTimeDecoder +pub use bitcoin_primitives::BlockTimeDecoderError +pub use bitcoin_primitives::FeeRate +pub use bitcoin_primitives::NumOpResult +pub use bitcoin_primitives::Sequence +pub use bitcoin_primitives::SignedAmount +pub use bitcoin_primitives::Weight +pub use bitcoin_primitives::absolute +pub use bitcoin_primitives::amount +pub use bitcoin_primitives::block::BlockHeight +pub use bitcoin_primitives::block::BlockHeightDecoder +pub use bitcoin_primitives::block::BlockHeightDecoderError +pub use bitcoin_primitives::block::BlockHeightEncoder +pub use bitcoin_primitives::block::BlockHeightInterval +pub use bitcoin_primitives::block::BlockMtp +pub use bitcoin_primitives::block::BlockMtpInterval +pub use bitcoin_primitives::block::TooBigForRelativeHeightError +pub use bitcoin_primitives::fee_rate +pub use bitcoin_primitives::locktime +pub use bitcoin_primitives::parse_int +pub use bitcoin_primitives::relative +pub use bitcoin_primitives::result +pub use bitcoin_primitives::sequence +pub use bitcoin_primitives::time +pub use bitcoin_primitives::weight diff --git a/api/primitives/no-features.txt b/api/primitives/no-features.txt new file mode 100644 index 000000000..9a8113810 --- /dev/null +++ b/api/primitives/no-features.txt @@ -0,0 +1,789 @@ +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::BlockHash +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::TxMerkleNode +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::WitnessMerkleNode +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::block::Version +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::pow::CompactTarget +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::OutPoint +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_primitives::transaction::Version +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::BlockHashDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::block::VersionDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::pow::CompactTargetDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::OutPointDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_primitives::transaction::VersionDecoder +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::BlockHash +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::TxMerkleNode +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::WitnessMerkleNode +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Header +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::block::Version +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::pow::CompactTarget +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::OutPoint +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_primitives::transaction::Version +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::BlockHashEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::HeaderEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::block::VersionEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::pow::CompactTargetEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::VersionEncoder +impl bitcoin_primitives::BlockHash +impl bitcoin_primitives::Ntxid +impl bitcoin_primitives::TxMerkleNode +impl bitcoin_primitives::Txid +impl bitcoin_primitives::WitnessCommitment +impl bitcoin_primitives::WitnessMerkleNode +impl bitcoin_primitives::Wtxid +impl bitcoin_primitives::block::BlockHashDecoder +impl bitcoin_primitives::block::Header +impl bitcoin_primitives::block::Version +impl bitcoin_primitives::block::VersionDecoder +impl bitcoin_primitives::pow::CompactTarget +impl bitcoin_primitives::pow::CompactTargetDecoder +impl bitcoin_primitives::transaction::OutPoint +impl bitcoin_primitives::transaction::OutPointDecoder +impl bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl bitcoin_primitives::transaction::Version +impl bitcoin_primitives::transaction::VersionDecoder +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::BlockHash +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Ntxid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::TxMerkleNode +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Txid +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::WitnessCommitment +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::WitnessMerkleNode +impl core::borrow::Borrow<[u8; 32]> for bitcoin_primitives::Wtxid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::BlockHash +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Ntxid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::TxMerkleNode +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Txid +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::WitnessCommitment +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::WitnessMerkleNode +impl core::borrow::Borrow<[u8]> for bitcoin_primitives::Wtxid +impl core::clone::Clone for bitcoin_primitives::BlockHash +impl core::clone::Clone for bitcoin_primitives::Ntxid +impl core::clone::Clone for bitcoin_primitives::TxMerkleNode +impl core::clone::Clone for bitcoin_primitives::Txid +impl core::clone::Clone for bitcoin_primitives::WitnessCommitment +impl core::clone::Clone for bitcoin_primitives::WitnessMerkleNode +impl core::clone::Clone for bitcoin_primitives::Wtxid +impl core::clone::Clone for bitcoin_primitives::block::BlockHashDecoderError +impl core::clone::Clone for bitcoin_primitives::block::Header +impl core::clone::Clone for bitcoin_primitives::block::Version +impl core::clone::Clone for bitcoin_primitives::block::VersionDecoderError +impl core::clone::Clone for bitcoin_primitives::pow::CompactTarget +impl core::clone::Clone for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::OutPoint +impl core::clone::Clone for bitcoin_primitives::transaction::OutPointDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::clone::Clone for bitcoin_primitives::transaction::Version +impl core::clone::Clone for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::Eq for bitcoin_primitives::BlockHash +impl core::cmp::Eq for bitcoin_primitives::Ntxid +impl core::cmp::Eq for bitcoin_primitives::TxMerkleNode +impl core::cmp::Eq for bitcoin_primitives::Txid +impl core::cmp::Eq for bitcoin_primitives::WitnessCommitment +impl core::cmp::Eq for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::Eq for bitcoin_primitives::Wtxid +impl core::cmp::Eq for bitcoin_primitives::block::BlockHashDecoderError +impl core::cmp::Eq for bitcoin_primitives::block::Header +impl core::cmp::Eq for bitcoin_primitives::block::Version +impl core::cmp::Eq for bitcoin_primitives::block::VersionDecoderError +impl core::cmp::Eq for bitcoin_primitives::pow::CompactTarget +impl core::cmp::Eq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::OutPoint +impl core::cmp::Eq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::cmp::Eq for bitcoin_primitives::transaction::Version +impl core::cmp::Eq for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::Ord for bitcoin_primitives::BlockHash +impl core::cmp::Ord for bitcoin_primitives::Ntxid +impl core::cmp::Ord for bitcoin_primitives::TxMerkleNode +impl core::cmp::Ord for bitcoin_primitives::Txid +impl core::cmp::Ord for bitcoin_primitives::WitnessCommitment +impl core::cmp::Ord for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::Ord for bitcoin_primitives::Wtxid +impl core::cmp::Ord for bitcoin_primitives::block::Header +impl core::cmp::Ord for bitcoin_primitives::block::Version +impl core::cmp::Ord for bitcoin_primitives::pow::CompactTarget +impl core::cmp::Ord for bitcoin_primitives::transaction::OutPoint +impl core::cmp::Ord for bitcoin_primitives::transaction::Version +impl core::cmp::PartialEq for bitcoin_primitives::BlockHash +impl core::cmp::PartialEq for bitcoin_primitives::Ntxid +impl core::cmp::PartialEq for bitcoin_primitives::TxMerkleNode +impl core::cmp::PartialEq for bitcoin_primitives::Txid +impl core::cmp::PartialEq for bitcoin_primitives::WitnessCommitment +impl core::cmp::PartialEq for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::PartialEq for bitcoin_primitives::Wtxid +impl core::cmp::PartialEq for bitcoin_primitives::block::BlockHashDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::block::Header +impl core::cmp::PartialEq for bitcoin_primitives::block::Version +impl core::cmp::PartialEq for bitcoin_primitives::block::VersionDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::pow::CompactTarget +impl core::cmp::PartialEq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::OutPoint +impl core::cmp::PartialEq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::cmp::PartialEq for bitcoin_primitives::transaction::Version +impl core::cmp::PartialEq for bitcoin_primitives::transaction::VersionDecoderError +impl core::cmp::PartialOrd for bitcoin_primitives::BlockHash +impl core::cmp::PartialOrd for bitcoin_primitives::Ntxid +impl core::cmp::PartialOrd for bitcoin_primitives::TxMerkleNode +impl core::cmp::PartialOrd for bitcoin_primitives::Txid +impl core::cmp::PartialOrd for bitcoin_primitives::WitnessCommitment +impl core::cmp::PartialOrd for bitcoin_primitives::WitnessMerkleNode +impl core::cmp::PartialOrd for bitcoin_primitives::Wtxid +impl core::cmp::PartialOrd for bitcoin_primitives::block::Header +impl core::cmp::PartialOrd for bitcoin_primitives::block::Version +impl core::cmp::PartialOrd for bitcoin_primitives::pow::CompactTarget +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::OutPoint +impl core::cmp::PartialOrd for bitcoin_primitives::transaction::Version +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::BlockHash +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Ntxid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::TxMerkleNode +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Txid +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::WitnessCommitment +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::WitnessMerkleNode +impl core::convert::AsRef<[u8; 32]> for bitcoin_primitives::Wtxid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::BlockHash +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Ntxid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::TxMerkleNode +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Txid +impl core::convert::AsRef<[u8]> for bitcoin_primitives::WitnessCommitment +impl core::convert::AsRef<[u8]> for bitcoin_primitives::WitnessMerkleNode +impl core::convert::AsRef<[u8]> for bitcoin_primitives::Wtxid +impl core::convert::From<&bitcoin_primitives::block::Header> for bitcoin_primitives::BlockHash +impl core::convert::From for bitcoin_primitives::block::BlockHashDecoderError +impl core::convert::From for bitcoin_primitives::block::VersionDecoderError +impl core::convert::From for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::convert::From for bitcoin_primitives::BlockHash +impl core::convert::From for u32 +impl core::convert::From for bitcoin_primitives::block::BlockHashDecoderError +impl core::convert::From for bitcoin_primitives::block::VersionDecoderError +impl core::convert::From for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::convert::From for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::convert::From for bitcoin_primitives::transaction::VersionDecoderError +impl core::default::Default for bitcoin_primitives::block::BlockHashDecoder +impl core::default::Default for bitcoin_primitives::block::Version +impl core::default::Default for bitcoin_primitives::block::VersionDecoder +impl core::default::Default for bitcoin_primitives::pow::CompactTargetDecoder +impl core::default::Default for bitcoin_primitives::transaction::OutPointDecoder +impl core::default::Default for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::default::Default for bitcoin_primitives::transaction::VersionDecoder +impl core::fmt::Debug for bitcoin_primitives::BlockHash +impl core::fmt::Debug for bitcoin_primitives::Ntxid +impl core::fmt::Debug for bitcoin_primitives::TxMerkleNode +impl core::fmt::Debug for bitcoin_primitives::Txid +impl core::fmt::Debug for bitcoin_primitives::WitnessCommitment +impl core::fmt::Debug for bitcoin_primitives::WitnessMerkleNode +impl core::fmt::Debug for bitcoin_primitives::Wtxid +impl core::fmt::Debug for bitcoin_primitives::block::BlockHashDecoderError +impl core::fmt::Debug for bitcoin_primitives::block::Header +impl core::fmt::Debug for bitcoin_primitives::block::Version +impl core::fmt::Debug for bitcoin_primitives::block::VersionDecoderError +impl core::fmt::Debug for bitcoin_primitives::pow::CompactTarget +impl core::fmt::Debug for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::OutPoint +impl core::fmt::Debug for bitcoin_primitives::transaction::OutPointDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::fmt::Debug for bitcoin_primitives::transaction::Version +impl core::fmt::Debug for bitcoin_primitives::transaction::VersionDecoderError +impl core::fmt::Display for bitcoin_primitives::block::BlockHashDecoderError +impl core::fmt::Display for bitcoin_primitives::block::VersionDecoderError +impl core::fmt::Display for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::OutPointDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::fmt::Display for bitcoin_primitives::transaction::Version +impl core::fmt::Display for bitcoin_primitives::transaction::VersionDecoderError +impl core::fmt::LowerHex for bitcoin_primitives::pow::CompactTarget +impl core::fmt::UpperHex for bitcoin_primitives::pow::CompactTarget +impl core::hash::Hash for bitcoin_primitives::BlockHash +impl core::hash::Hash for bitcoin_primitives::Ntxid +impl core::hash::Hash for bitcoin_primitives::TxMerkleNode +impl core::hash::Hash for bitcoin_primitives::Txid +impl core::hash::Hash for bitcoin_primitives::WitnessCommitment +impl core::hash::Hash for bitcoin_primitives::WitnessMerkleNode +impl core::hash::Hash for bitcoin_primitives::Wtxid +impl core::hash::Hash for bitcoin_primitives::block::Header +impl core::hash::Hash for bitcoin_primitives::block::Version +impl core::hash::Hash for bitcoin_primitives::pow::CompactTarget +impl core::hash::Hash for bitcoin_primitives::transaction::OutPoint +impl core::hash::Hash for bitcoin_primitives::transaction::Version +impl core::marker::Copy for bitcoin_primitives::BlockHash +impl core::marker::Copy for bitcoin_primitives::Ntxid +impl core::marker::Copy for bitcoin_primitives::TxMerkleNode +impl core::marker::Copy for bitcoin_primitives::Txid +impl core::marker::Copy for bitcoin_primitives::WitnessCommitment +impl core::marker::Copy for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Copy for bitcoin_primitives::Wtxid +impl core::marker::Copy for bitcoin_primitives::block::Header +impl core::marker::Copy for bitcoin_primitives::block::Version +impl core::marker::Copy for bitcoin_primitives::pow::CompactTarget +impl core::marker::Copy for bitcoin_primitives::transaction::OutPoint +impl core::marker::Copy for bitcoin_primitives::transaction::Version +impl core::marker::Freeze for bitcoin_primitives::BlockHash +impl core::marker::Freeze for bitcoin_primitives::Ntxid +impl core::marker::Freeze for bitcoin_primitives::TxMerkleNode +impl core::marker::Freeze for bitcoin_primitives::Txid +impl core::marker::Freeze for bitcoin_primitives::WitnessCommitment +impl core::marker::Freeze for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Freeze for bitcoin_primitives::Wtxid +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Freeze for bitcoin_primitives::block::Header +impl core::marker::Freeze for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Freeze for bitcoin_primitives::block::Version +impl core::marker::Freeze for bitcoin_primitives::block::VersionDecoder +impl core::marker::Freeze for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Freeze for bitcoin_primitives::block::VersionEncoder +impl core::marker::Freeze for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTarget +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Freeze for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPoint +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::Version +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Freeze for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Send for bitcoin_primitives::BlockHash +impl core::marker::Send for bitcoin_primitives::Ntxid +impl core::marker::Send for bitcoin_primitives::TxMerkleNode +impl core::marker::Send for bitcoin_primitives::Txid +impl core::marker::Send for bitcoin_primitives::WitnessCommitment +impl core::marker::Send for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Send for bitcoin_primitives::Wtxid +impl core::marker::Send for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Send for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Send for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Send for bitcoin_primitives::block::Header +impl core::marker::Send for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Send for bitcoin_primitives::block::Version +impl core::marker::Send for bitcoin_primitives::block::VersionDecoder +impl core::marker::Send for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Send for bitcoin_primitives::block::VersionEncoder +impl core::marker::Send for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Send for bitcoin_primitives::pow::CompactTarget +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Send for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Send for bitcoin_primitives::transaction::OutPoint +impl core::marker::Send for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Send for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Send for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::Version +impl core::marker::Send for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Send for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Send for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::StructuralPartialEq for bitcoin_primitives::BlockHash +impl core::marker::StructuralPartialEq for bitcoin_primitives::Ntxid +impl core::marker::StructuralPartialEq for bitcoin_primitives::TxMerkleNode +impl core::marker::StructuralPartialEq for bitcoin_primitives::Txid +impl core::marker::StructuralPartialEq for bitcoin_primitives::WitnessCommitment +impl core::marker::StructuralPartialEq for bitcoin_primitives::WitnessMerkleNode +impl core::marker::StructuralPartialEq for bitcoin_primitives::Wtxid +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Header +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::Version +impl core::marker::StructuralPartialEq for bitcoin_primitives::block::VersionDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::pow::CompactTarget +impl core::marker::StructuralPartialEq for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::OutPoint +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::Version +impl core::marker::StructuralPartialEq for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::BlockHash +impl core::marker::Sync for bitcoin_primitives::Ntxid +impl core::marker::Sync for bitcoin_primitives::TxMerkleNode +impl core::marker::Sync for bitcoin_primitives::Txid +impl core::marker::Sync for bitcoin_primitives::WitnessCommitment +impl core::marker::Sync for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Sync for bitcoin_primitives::Wtxid +impl core::marker::Sync for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Sync for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Sync for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Sync for bitcoin_primitives::block::Header +impl core::marker::Sync for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Sync for bitcoin_primitives::block::Version +impl core::marker::Sync for bitcoin_primitives::block::VersionDecoder +impl core::marker::Sync for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::block::VersionEncoder +impl core::marker::Sync for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Sync for bitcoin_primitives::pow::CompactTarget +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Sync for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Sync for bitcoin_primitives::transaction::OutPoint +impl core::marker::Sync for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::Version +impl core::marker::Sync for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Sync for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Sync for bitcoin_primitives::transaction::VersionEncoder +impl core::marker::Unpin for bitcoin_primitives::BlockHash +impl core::marker::Unpin for bitcoin_primitives::Ntxid +impl core::marker::Unpin for bitcoin_primitives::TxMerkleNode +impl core::marker::Unpin for bitcoin_primitives::Txid +impl core::marker::Unpin for bitcoin_primitives::WitnessCommitment +impl core::marker::Unpin for bitcoin_primitives::WitnessMerkleNode +impl core::marker::Unpin for bitcoin_primitives::Wtxid +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashDecoder +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::BlockHashEncoder +impl core::marker::Unpin for bitcoin_primitives::block::Header +impl core::marker::Unpin for bitcoin_primitives::block::HeaderEncoder +impl core::marker::Unpin for bitcoin_primitives::block::Version +impl core::marker::Unpin for bitcoin_primitives::block::VersionDecoder +impl core::marker::Unpin for bitcoin_primitives::block::VersionDecoderError +impl core::marker::Unpin for bitcoin_primitives::block::VersionEncoder +impl core::marker::Unpin for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTarget +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetDecoder +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::marker::Unpin for bitcoin_primitives::pow::CompactTargetEncoder +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPoint +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPointDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::OutPointDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::Version +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionDecoder +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionDecoderError +impl core::marker::Unpin for bitcoin_primitives::transaction::VersionEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::BlockHash +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Ntxid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::TxMerkleNode +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Txid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::WitnessCommitment +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::WitnessMerkleNode +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::Wtxid +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::BlockHashEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Header +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::HeaderEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::Version +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::block::VersionEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTarget +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::pow::CompactTargetEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPoint +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::Version +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::VersionEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::BlockHash +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Ntxid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::TxMerkleNode +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Txid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::WitnessCommitment +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::WitnessMerkleNode +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::Wtxid +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::BlockHashEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Header +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::HeaderEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::Version +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::block::VersionEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTarget +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::pow::CompactTargetEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPoint +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::TxMerkleNodeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::Version +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::VersionEncoder +impl<'e> bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Send for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Sync for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::OutPointEncoder<'e> +impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::OutPointEncoder<'e> +pub bitcoin_primitives::BlockHeader::bits: bitcoin_primitives::pow::CompactTarget +pub bitcoin_primitives::BlockHeader::merkle_root: bitcoin_primitives::TxMerkleNode +pub bitcoin_primitives::BlockHeader::nonce: u32 +pub bitcoin_primitives::BlockHeader::prev_blockhash: bitcoin_primitives::BlockHash +pub bitcoin_primitives::BlockHeader::time: bitcoin_units::time::encapsulate::BlockTime +pub bitcoin_primitives::BlockHeader::version: bitcoin_primitives::block::Version +pub bitcoin_primitives::OutPoint::txid: bitcoin_primitives::Txid +pub bitcoin_primitives::OutPoint::vout: u32 +pub bitcoin_primitives::block::Header::bits: bitcoin_primitives::pow::CompactTarget +pub bitcoin_primitives::block::Header::merkle_root: bitcoin_primitives::TxMerkleNode +pub bitcoin_primitives::block::Header::nonce: u32 +pub bitcoin_primitives::block::Header::prev_blockhash: bitcoin_primitives::BlockHash +pub bitcoin_primitives::block::Header::time: bitcoin_units::time::encapsulate::BlockTime +pub bitcoin_primitives::block::Header::version: bitcoin_primitives::block::Version +pub bitcoin_primitives::transaction::OutPoint::txid: bitcoin_primitives::Txid +pub bitcoin_primitives::transaction::OutPoint::vout: u32 +pub const bitcoin_primitives::BlockHash::GENESIS_PREVIOUS_BLOCK_HASH: Self +pub const bitcoin_primitives::Txid::COINBASE_PREVOUT: Self +pub const bitcoin_primitives::WitnessCommitment::GENESIS_PREVIOUS_BLOCK_HASH: Self +pub const bitcoin_primitives::Wtxid::COINBASE: Self +pub const bitcoin_primitives::block::Header::SIZE: usize +pub const bitcoin_primitives::block::Version::NO_SOFT_FORK_SIGNALLING: Self +pub const bitcoin_primitives::block::Version::ONE: Self +pub const bitcoin_primitives::block::Version::TWO: Self +pub const bitcoin_primitives::transaction::OutPoint::COINBASE_PREVOUT: Self +pub const bitcoin_primitives::transaction::OutPoint::SIZE: usize +pub const bitcoin_primitives::transaction::Version::ONE: Self +pub const bitcoin_primitives::transaction::Version::THREE: Self +pub const bitcoin_primitives::transaction::Version::TWO: Self +pub const fn bitcoin_primitives::BlockHash::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::BlockHash::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::BlockHash::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Ntxid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Ntxid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Ntxid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::TxMerkleNode::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::TxMerkleNode::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::TxMerkleNode::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Txid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Txid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Txid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::WitnessCommitment::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::WitnessCommitment::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::WitnessCommitment::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::WitnessMerkleNode::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::WitnessMerkleNode::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::WitnessMerkleNode::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::Wtxid::as_byte_array(&self) -> &[u8; 32] +pub const fn bitcoin_primitives::Wtxid::from_byte_array(bytes: [u8; 32]) -> Self +pub const fn bitcoin_primitives::Wtxid::to_byte_array(self) -> [u8; 32] +pub const fn bitcoin_primitives::block::BlockHashDecoder::new() -> Self +pub const fn bitcoin_primitives::block::Version::from_consensus(v: i32) -> Self +pub const fn bitcoin_primitives::block::Version::to_consensus(self) -> i32 +pub const fn bitcoin_primitives::block::VersionDecoder::new() -> Self +pub const fn bitcoin_primitives::pow::CompactTarget::to_consensus(self) -> u32 +pub const fn bitcoin_primitives::pow::CompactTargetDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::OutPointDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::new() -> Self +pub const fn bitcoin_primitives::transaction::Version::is_standard(self) -> bool +pub const fn bitcoin_primitives::transaction::Version::maybe_non_standard(version: u32) -> Self +pub const fn bitcoin_primitives::transaction::Version::to_u32(self) -> u32 +pub const fn bitcoin_primitives::transaction::VersionDecoder::new() -> Self +pub fn bitcoin_primitives::BlockHash::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::BlockHash::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::BlockHash::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::BlockHash::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::BlockHash::clone(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::BlockHash::cmp(&self, other: &bitcoin_primitives::BlockHash) -> core::cmp::Ordering +pub fn bitcoin_primitives::BlockHash::decoder() -> Self::Decoder +pub fn bitcoin_primitives::BlockHash::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::BlockHash::eq(&self, other: &bitcoin_primitives::BlockHash) -> bool +pub fn bitcoin_primitives::BlockHash::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::BlockHash::from(header: &bitcoin_primitives::block::Header) -> Self +pub fn bitcoin_primitives::BlockHash::from(header: bitcoin_primitives::block::Header) -> Self +pub fn bitcoin_primitives::BlockHash::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::BlockHash::partial_cmp(&self, other: &bitcoin_primitives::BlockHash) -> core::option::Option +pub fn bitcoin_primitives::Ntxid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Ntxid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Ntxid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Ntxid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Ntxid::clone(&self) -> bitcoin_primitives::Ntxid +pub fn bitcoin_primitives::Ntxid::cmp(&self, other: &bitcoin_primitives::Ntxid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Ntxid::eq(&self, other: &bitcoin_primitives::Ntxid) -> bool +pub fn bitcoin_primitives::Ntxid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Ntxid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Ntxid::partial_cmp(&self, other: &bitcoin_primitives::Ntxid) -> core::option::Option +pub fn bitcoin_primitives::TxMerkleNode::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::TxMerkleNode::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::TxMerkleNode::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::TxMerkleNode::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::TxMerkleNode::calculate_root>(iter: I) -> core::option::Option +pub fn bitcoin_primitives::TxMerkleNode::clone(&self) -> bitcoin_primitives::TxMerkleNode +pub fn bitcoin_primitives::TxMerkleNode::cmp(&self, other: &bitcoin_primitives::TxMerkleNode) -> core::cmp::Ordering +pub fn bitcoin_primitives::TxMerkleNode::combine(&self, other: &Self) -> Self +pub fn bitcoin_primitives::TxMerkleNode::decoder() -> Self::Decoder +pub fn bitcoin_primitives::TxMerkleNode::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::TxMerkleNode::eq(&self, other: &bitcoin_primitives::TxMerkleNode) -> bool +pub fn bitcoin_primitives::TxMerkleNode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::TxMerkleNode::from_leaf(leaf: bitcoin_primitives::Txid) -> Self +pub fn bitcoin_primitives::TxMerkleNode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::TxMerkleNode::partial_cmp(&self, other: &bitcoin_primitives::TxMerkleNode) -> core::option::Option +pub fn bitcoin_primitives::Txid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Txid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Txid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Txid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Txid::clone(&self) -> bitcoin_primitives::Txid +pub fn bitcoin_primitives::Txid::cmp(&self, other: &bitcoin_primitives::Txid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Txid::eq(&self, other: &bitcoin_primitives::Txid) -> bool +pub fn bitcoin_primitives::Txid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Txid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Txid::partial_cmp(&self, other: &bitcoin_primitives::Txid) -> core::option::Option +pub fn bitcoin_primitives::WitnessCommitment::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessCommitment::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessCommitment::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessCommitment::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessCommitment::clone(&self) -> bitcoin_primitives::WitnessCommitment +pub fn bitcoin_primitives::WitnessCommitment::cmp(&self, other: &bitcoin_primitives::WitnessCommitment) -> core::cmp::Ordering +pub fn bitcoin_primitives::WitnessCommitment::eq(&self, other: &bitcoin_primitives::WitnessCommitment) -> bool +pub fn bitcoin_primitives::WitnessCommitment::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::WitnessCommitment::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::WitnessCommitment::partial_cmp(&self, other: &bitcoin_primitives::WitnessCommitment) -> core::option::Option +pub fn bitcoin_primitives::WitnessMerkleNode::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessMerkleNode::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessMerkleNode::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::WitnessMerkleNode::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::WitnessMerkleNode::calculate_root>(iter: I) -> core::option::Option +pub fn bitcoin_primitives::WitnessMerkleNode::clone(&self) -> bitcoin_primitives::WitnessMerkleNode +pub fn bitcoin_primitives::WitnessMerkleNode::cmp(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> core::cmp::Ordering +pub fn bitcoin_primitives::WitnessMerkleNode::combine(&self, other: &Self) -> Self +pub fn bitcoin_primitives::WitnessMerkleNode::decoder() -> Self::Decoder +pub fn bitcoin_primitives::WitnessMerkleNode::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::WitnessMerkleNode::eq(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> bool +pub fn bitcoin_primitives::WitnessMerkleNode::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::WitnessMerkleNode::from_leaf(leaf: bitcoin_primitives::Wtxid) -> Self +pub fn bitcoin_primitives::WitnessMerkleNode::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::WitnessMerkleNode::partial_cmp(&self, other: &bitcoin_primitives::WitnessMerkleNode) -> core::option::Option +pub fn bitcoin_primitives::Wtxid::as_ref(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Wtxid::as_ref(&self) -> &[u8] +pub fn bitcoin_primitives::Wtxid::borrow(&self) -> &[u8; 32] +pub fn bitcoin_primitives::Wtxid::borrow(&self) -> &[u8] +pub fn bitcoin_primitives::Wtxid::clone(&self) -> bitcoin_primitives::Wtxid +pub fn bitcoin_primitives::Wtxid::cmp(&self, other: &bitcoin_primitives::Wtxid) -> core::cmp::Ordering +pub fn bitcoin_primitives::Wtxid::eq(&self, other: &bitcoin_primitives::Wtxid) -> bool +pub fn bitcoin_primitives::Wtxid::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::Wtxid::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::Wtxid::partial_cmp(&self, other: &bitcoin_primitives::Wtxid) -> core::option::Option +pub fn bitcoin_primitives::block::BlockHashDecoder::default() -> Self +pub fn bitcoin_primitives::block::BlockHashDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::BlockHashDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::BlockHashDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::BlockHashDecoderError::clone(&self) -> bitcoin_primitives::block::BlockHashDecoderError +pub fn bitcoin_primitives::block::BlockHashDecoderError::eq(&self, other: &bitcoin_primitives::block::BlockHashDecoderError) -> bool +pub fn bitcoin_primitives::block::BlockHashDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::BlockHashDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::block::BlockHashDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::BlockHashEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::BlockHashEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::Header::block_hash(&self) -> bitcoin_primitives::BlockHash +pub fn bitcoin_primitives::block::Header::clone(&self) -> bitcoin_primitives::block::Header +pub fn bitcoin_primitives::block::Header::cmp(&self, other: &bitcoin_primitives::block::Header) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Header::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Header::eq(&self, other: &bitcoin_primitives::block::Header) -> bool +pub fn bitcoin_primitives::block::Header::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Header::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Header::partial_cmp(&self, other: &bitcoin_primitives::block::Header) -> core::option::Option +pub fn bitcoin_primitives::block::HeaderEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::HeaderEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::block::Version::clone(&self) -> bitcoin_primitives::block::Version +pub fn bitcoin_primitives::block::Version::cmp(&self, other: &bitcoin_primitives::block::Version) -> core::cmp::Ordering +pub fn bitcoin_primitives::block::Version::decoder() -> Self::Decoder +pub fn bitcoin_primitives::block::Version::default() -> Self +pub fn bitcoin_primitives::block::Version::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::block::Version::eq(&self, other: &bitcoin_primitives::block::Version) -> bool +pub fn bitcoin_primitives::block::Version::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::Version::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::block::Version::is_signalling_soft_fork(self, bit: u8) -> bool +pub fn bitcoin_primitives::block::Version::partial_cmp(&self, other: &bitcoin_primitives::block::Version) -> core::option::Option +pub fn bitcoin_primitives::block::VersionDecoder::default() -> Self +pub fn bitcoin_primitives::block::VersionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::block::VersionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::block::VersionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::block::VersionDecoderError::clone(&self) -> bitcoin_primitives::block::VersionDecoderError +pub fn bitcoin_primitives::block::VersionDecoderError::eq(&self, other: &bitcoin_primitives::block::VersionDecoderError) -> bool +pub fn bitcoin_primitives::block::VersionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::block::VersionDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::block::VersionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::block::VersionEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::block::VersionEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::pow::CompactTarget::clone(&self) -> bitcoin_primitives::pow::CompactTarget +pub fn bitcoin_primitives::pow::CompactTarget::cmp(&self, other: &bitcoin_primitives::pow::CompactTarget) -> core::cmp::Ordering +pub fn bitcoin_primitives::pow::CompactTarget::decoder() -> Self::Decoder +pub fn bitcoin_primitives::pow::CompactTarget::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::pow::CompactTarget::eq(&self, other: &bitcoin_primitives::pow::CompactTarget) -> bool +pub fn bitcoin_primitives::pow::CompactTarget::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::pow::CompactTarget::from_consensus(bits: u32) -> Self +pub fn bitcoin_primitives::pow::CompactTarget::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::pow::CompactTarget::partial_cmp(&self, other: &bitcoin_primitives::pow::CompactTarget) -> core::option::Option +pub fn bitcoin_primitives::pow::CompactTargetDecoder::default() -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::clone(&self) -> bitcoin_primitives::pow::CompactTargetDecoderError +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::eq(&self, other: &bitcoin_primitives::pow::CompactTargetDecoderError) -> bool +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::pow::CompactTargetDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::pow::CompactTargetEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::pow::CompactTargetEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::OutPoint::clone(&self) -> bitcoin_primitives::transaction::OutPoint +pub fn bitcoin_primitives::transaction::OutPoint::cmp(&self, other: &bitcoin_primitives::transaction::OutPoint) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::OutPoint::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::OutPoint::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::OutPoint::eq(&self, other: &bitcoin_primitives::transaction::OutPoint) -> bool +pub fn bitcoin_primitives::transaction::OutPoint::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::OutPoint::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::OutPoint::partial_cmp(&self, other: &bitcoin_primitives::transaction::OutPoint) -> core::option::Option +pub fn bitcoin_primitives::transaction::OutPointDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::OutPointDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPointDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::OutPointDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::OutPointDecoderError::clone(&self) -> bitcoin_primitives::transaction::OutPointDecoderError +pub fn bitcoin_primitives::transaction::OutPointDecoderError::eq(&self, other: &bitcoin_primitives::transaction::OutPointDecoderError) -> bool +pub fn bitcoin_primitives::transaction::OutPointDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::OutPointEncoder<'e>::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::OutPointEncoder<'e>::current_chunk(&self) -> &[u8] +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::clone(&self) -> bitcoin_primitives::transaction::TxMerkleNodeDecoderError +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::eq(&self, other: &bitcoin_primitives::transaction::TxMerkleNodeDecoderError) -> bool +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::from(e: bitcoin_consensus_encoding::decode::decoders::UnexpectedEofError) -> Self +pub fn bitcoin_primitives::transaction::TxMerkleNodeDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::Version::clone(&self) -> bitcoin_primitives::transaction::Version +pub fn bitcoin_primitives::transaction::Version::cmp(&self, other: &bitcoin_primitives::transaction::Version) -> core::cmp::Ordering +pub fn bitcoin_primitives::transaction::Version::decoder() -> Self::Decoder +pub fn bitcoin_primitives::transaction::Version::encoder(&self) -> Self::Encoder +pub fn bitcoin_primitives::transaction::Version::eq(&self, other: &bitcoin_primitives::transaction::Version) -> bool +pub fn bitcoin_primitives::transaction::Version::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::Version::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_primitives::transaction::Version::partial_cmp(&self, other: &bitcoin_primitives::transaction::Version) -> core::option::Option +pub fn bitcoin_primitives::transaction::VersionDecoder::default() -> Self +pub fn bitcoin_primitives::transaction::VersionDecoder::end(self) -> core::result::Result +pub fn bitcoin_primitives::transaction::VersionDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_primitives::transaction::VersionDecoder::read_limit(&self) -> usize +pub fn bitcoin_primitives::transaction::VersionDecoderError::clone(&self) -> bitcoin_primitives::transaction::VersionDecoderError +pub fn bitcoin_primitives::transaction::VersionDecoderError::eq(&self, other: &bitcoin_primitives::transaction::VersionDecoderError) -> bool +pub fn bitcoin_primitives::transaction::VersionDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_primitives::transaction::VersionDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_primitives::transaction::VersionEncoder::advance(&mut self) -> bool +pub fn bitcoin_primitives::transaction::VersionEncoder::current_chunk(&self) -> &[u8] +pub fn u32::from(version: bitcoin_primitives::transaction::Version) -> Self +pub mod bitcoin_primitives +pub mod bitcoin_primitives::block +pub mod bitcoin_primitives::merkle_tree +pub mod bitcoin_primitives::pow +pub mod bitcoin_primitives::transaction +pub struct bitcoin_primitives::BlockHash(_) +pub struct bitcoin_primitives::BlockHeader +pub struct bitcoin_primitives::BlockVersion(_) +pub struct bitcoin_primitives::CompactTarget(_) +pub struct bitcoin_primitives::Ntxid(_) +pub struct bitcoin_primitives::OutPoint +pub struct bitcoin_primitives::TransactionVersion(_) +pub struct bitcoin_primitives::TxMerkleNode(_) +pub struct bitcoin_primitives::Txid(_) +pub struct bitcoin_primitives::WitnessCommitment(_) +pub struct bitcoin_primitives::WitnessMerkleNode(_) +pub struct bitcoin_primitives::Wtxid(_) +pub struct bitcoin_primitives::block::BlockHash(_) +pub struct bitcoin_primitives::block::BlockHashDecoder(_) +pub struct bitcoin_primitives::block::BlockHashDecoderError(_) +pub struct bitcoin_primitives::block::BlockHashEncoder(_) +pub struct bitcoin_primitives::block::Header +pub struct bitcoin_primitives::block::HeaderEncoder(_) +pub struct bitcoin_primitives::block::Version(_) +pub struct bitcoin_primitives::block::VersionDecoder(_) +pub struct bitcoin_primitives::block::VersionDecoderError(_) +pub struct bitcoin_primitives::block::VersionEncoder(_) +pub struct bitcoin_primitives::block::WitnessCommitment(_) +pub struct bitcoin_primitives::merkle_tree::TxMerkleNode(_) +pub struct bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder(_) +pub struct bitcoin_primitives::merkle_tree::WitnessMerkleNode(_) +pub struct bitcoin_primitives::pow::CompactTarget(_) +pub struct bitcoin_primitives::pow::CompactTargetDecoder(_) +pub struct bitcoin_primitives::pow::CompactTargetDecoderError(_) +pub struct bitcoin_primitives::pow::CompactTargetEncoder(_) +pub struct bitcoin_primitives::transaction::BlockHashDecoder(_) +pub struct bitcoin_primitives::transaction::BlockHashDecoderError(_) +pub struct bitcoin_primitives::transaction::Ntxid(_) +pub struct bitcoin_primitives::transaction::OutPoint +pub struct bitcoin_primitives::transaction::OutPointDecoder(_) +pub struct bitcoin_primitives::transaction::OutPointDecoderError(_) +pub struct bitcoin_primitives::transaction::OutPointEncoder<'e>(_) +pub struct bitcoin_primitives::transaction::TxMerkleNodeDecoder(_) +pub struct bitcoin_primitives::transaction::TxMerkleNodeDecoderError(_) +pub struct bitcoin_primitives::transaction::Txid(_) +pub struct bitcoin_primitives::transaction::Version(_) +pub struct bitcoin_primitives::transaction::VersionDecoder(_) +pub struct bitcoin_primitives::transaction::VersionDecoderError(_) +pub struct bitcoin_primitives::transaction::VersionEncoder(_) +pub struct bitcoin_primitives::transaction::Wtxid(_) +pub type bitcoin_primitives::BlockHash::Decoder = bitcoin_primitives::block::BlockHashDecoder +pub type bitcoin_primitives::BlockHash::Encoder<'e> = bitcoin_primitives::block::BlockHashEncoder +pub type bitcoin_primitives::TxMerkleNode::Decoder = bitcoin_primitives::transaction::TxMerkleNodeDecoder +pub type bitcoin_primitives::TxMerkleNode::Encoder<'e> = bitcoin_primitives::merkle_tree::TxMerkleNodeEncoder +pub type bitcoin_primitives::WitnessMerkleNode::Decoder = bitcoin_primitives::hash_types::witness_merkle_node::WitnessMerkleNodeDecoder +pub type bitcoin_primitives::WitnessMerkleNode::Encoder<'e> = bitcoin_primitives::hash_types::witness_merkle_node::WitnessMerkleNodeEncoder +pub type bitcoin_primitives::block::BlockHashDecoder::Error = bitcoin_primitives::block::BlockHashDecoderError +pub type bitcoin_primitives::block::BlockHashDecoder::Output = bitcoin_primitives::BlockHash +pub type bitcoin_primitives::block::Header::Encoder<'e> = bitcoin_primitives::block::HeaderEncoder +pub type bitcoin_primitives::block::Version::Decoder = bitcoin_primitives::block::VersionDecoder +pub type bitcoin_primitives::block::Version::Encoder<'e> = bitcoin_primitives::block::VersionEncoder +pub type bitcoin_primitives::block::VersionDecoder::Error = bitcoin_primitives::block::VersionDecoderError +pub type bitcoin_primitives::block::VersionDecoder::Output = bitcoin_primitives::block::Version +pub type bitcoin_primitives::pow::CompactTarget::Decoder = bitcoin_primitives::pow::CompactTargetDecoder +pub type bitcoin_primitives::pow::CompactTarget::Encoder<'e> = bitcoin_primitives::pow::CompactTargetEncoder +pub type bitcoin_primitives::pow::CompactTargetDecoder::Error = bitcoin_primitives::pow::CompactTargetDecoderError +pub type bitcoin_primitives::pow::CompactTargetDecoder::Output = bitcoin_primitives::pow::CompactTarget +pub type bitcoin_primitives::transaction::OutPoint::Decoder = bitcoin_primitives::transaction::OutPointDecoder +pub type bitcoin_primitives::transaction::OutPoint::Encoder<'e> where Self: 'e = bitcoin_primitives::transaction::OutPointEncoder<'e> +pub type bitcoin_primitives::transaction::OutPointDecoder::Error = bitcoin_primitives::transaction::OutPointDecoderError +pub type bitcoin_primitives::transaction::OutPointDecoder::Output = bitcoin_primitives::transaction::OutPoint +pub type bitcoin_primitives::transaction::TxMerkleNodeDecoder::Error = bitcoin_primitives::transaction::TxMerkleNodeDecoderError +pub type bitcoin_primitives::transaction::TxMerkleNodeDecoder::Output = bitcoin_primitives::TxMerkleNode +pub type bitcoin_primitives::transaction::Version::Decoder = bitcoin_primitives::transaction::VersionDecoder +pub type bitcoin_primitives::transaction::Version::Encoder<'e> = bitcoin_primitives::transaction::VersionEncoder +pub type bitcoin_primitives::transaction::VersionDecoder::Error = bitcoin_primitives::transaction::VersionDecoderError +pub type bitcoin_primitives::transaction::VersionDecoder::Output = bitcoin_primitives::transaction::Version +pub use bitcoin_primitives::Amount +pub use bitcoin_primitives::BlockHeight +pub use bitcoin_primitives::BlockHeightInterval +pub use bitcoin_primitives::BlockMtp +pub use bitcoin_primitives::BlockMtpInterval +pub use bitcoin_primitives::BlockTime +pub use bitcoin_primitives::BlockTimeDecoder +pub use bitcoin_primitives::BlockTimeDecoderError +pub use bitcoin_primitives::FeeRate +pub use bitcoin_primitives::NumOpResult +pub use bitcoin_primitives::Sequence +pub use bitcoin_primitives::SignedAmount +pub use bitcoin_primitives::Weight +pub use bitcoin_primitives::absolute +pub use bitcoin_primitives::amount +pub use bitcoin_primitives::block::BlockHeight +pub use bitcoin_primitives::block::BlockHeightDecoder +pub use bitcoin_primitives::block::BlockHeightDecoderError +pub use bitcoin_primitives::block::BlockHeightEncoder +pub use bitcoin_primitives::block::BlockHeightInterval +pub use bitcoin_primitives::block::BlockMtp +pub use bitcoin_primitives::block::BlockMtpInterval +pub use bitcoin_primitives::block::TooBigForRelativeHeightError +pub use bitcoin_primitives::fee_rate +pub use bitcoin_primitives::locktime +pub use bitcoin_primitives::parse_int +pub use bitcoin_primitives::relative +pub use bitcoin_primitives::result +pub use bitcoin_primitives::sequence +pub use bitcoin_primitives::time +pub use bitcoin_primitives::weight diff --git a/api/units/all-features.txt b/api/units/all-features.txt new file mode 100644 index 000000000..50fc84ca6 --- /dev/null +++ b/api/units/all-features.txt @@ -0,0 +1,2865 @@ +#[non_exhaustive] pub enum bitcoin_units::amount::Denomination +#[non_exhaustive] pub enum bitcoin_units::amount::ParseDenominationError +#[non_exhaustive] pub enum bitcoin_units::amount::error::ParseDenominationError +#[non_exhaustive] pub enum bitcoin_units::result::MathOp +#[non_exhaustive] pub struct bitcoin_units::absolute::ConversionError +#[non_exhaustive] pub struct bitcoin_units::absolute::error::ConversionError +#[non_exhaustive] pub struct bitcoin_units::amount::error::MissingDenominationError +#[non_exhaustive] pub struct bitcoin_units::amount::error::PossiblyConfusingDenominationError(_) +#[non_exhaustive] pub struct bitcoin_units::amount::error::UnknownDenominationError(_) +#[non_exhaustive] pub struct bitcoin_units::fee_rate::serde::OverflowError +#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::ConversionError +#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::error::ConversionError +#[non_exhaustive] pub struct bitcoin_units::parse_int::ParseIntError +#[non_exhaustive] pub struct bitcoin_units::result::NumOpError(_) +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_units::Amount +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_units::BlockTime +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_units::block::BlockHeight +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_units::locktime::absolute::LockTime +impl bitcoin_consensus_encoding::decode::Decodable for bitcoin_units::sequence::Sequence +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_units::amount::AmountDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_units::block::BlockHeightDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_units::locktime::absolute::LockTimeDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_units::sequence::SequenceDecoder +impl bitcoin_consensus_encoding::decode::Decoder for bitcoin_units::time::BlockTimeDecoder +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_units::Amount +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_units::BlockTime +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_units::block::BlockHeight +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_units::locktime::absolute::LockTime +impl bitcoin_consensus_encoding::encode::Encodable for bitcoin_units::sequence::Sequence +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_units::amount::AmountEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_units::block::BlockHeightEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_units::locktime::absolute::LockTimeEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_units::sequence::SequenceEncoder +impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_units::time::BlockTimeEncoder +impl bitcoin_units::Amount +impl bitcoin_units::BlockTime +impl bitcoin_units::FeeRate +impl bitcoin_units::SignedAmount +impl bitcoin_units::Weight +impl bitcoin_units::amount::AmountDecoder +impl bitcoin_units::amount::Denomination +impl bitcoin_units::amount::Display +impl bitcoin_units::amount::error::OutOfRangeError +impl bitcoin_units::block::BlockHeight +impl bitcoin_units::block::BlockHeightDecoder +impl bitcoin_units::block::BlockHeightInterval +impl bitcoin_units::block::BlockMtp +impl bitcoin_units::block::BlockMtpInterval +impl bitcoin_units::locktime::absolute::Height +impl bitcoin_units::locktime::absolute::LockTime +impl bitcoin_units::locktime::absolute::LockTimeDecoder +impl bitcoin_units::locktime::absolute::MedianTimePast +impl bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl bitcoin_units::locktime::relative::LockTime +impl bitcoin_units::locktime::relative::NumberOf512Seconds +impl bitcoin_units::locktime::relative::NumberOfBlocks +impl bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl bitcoin_units::parse_int::Integer for i128 +impl bitcoin_units::parse_int::Integer for i16 +impl bitcoin_units::parse_int::Integer for i32 +impl bitcoin_units::parse_int::Integer for i64 +impl bitcoin_units::parse_int::Integer for i8 +impl bitcoin_units::parse_int::Integer for u128 +impl bitcoin_units::parse_int::Integer for u16 +impl bitcoin_units::parse_int::Integer for u32 +impl bitcoin_units::parse_int::Integer for u64 +impl bitcoin_units::parse_int::Integer for u8 +impl bitcoin_units::result::MathOp +impl bitcoin_units::result::NumOpError +impl bitcoin_units::sequence::Sequence +impl bitcoin_units::sequence::SequenceDecoder +impl bitcoin_units::time::BlockTimeDecoder +impl core::clone::Clone for bitcoin_units::Amount +impl core::clone::Clone for bitcoin_units::BlockTime +impl core::clone::Clone for bitcoin_units::FeeRate +impl core::clone::Clone for bitcoin_units::SignedAmount +impl core::clone::Clone for bitcoin_units::Weight +impl core::clone::Clone for bitcoin_units::amount::Denomination +impl core::clone::Clone for bitcoin_units::amount::Display +impl core::clone::Clone for bitcoin_units::amount::error::AmountDecoderError +impl core::clone::Clone for bitcoin_units::amount::error::BadPositionError +impl core::clone::Clone for bitcoin_units::amount::error::InputTooLargeError +impl core::clone::Clone for bitcoin_units::amount::error::InvalidCharacterError +impl core::clone::Clone for bitcoin_units::amount::error::MissingDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::MissingDigitsError +impl core::clone::Clone for bitcoin_units::amount::error::OutOfRangeError +impl core::clone::Clone for bitcoin_units::amount::error::ParseAmountError +impl core::clone::Clone for bitcoin_units::amount::error::ParseDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::ParseError +impl core::clone::Clone for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::TooPreciseError +impl core::clone::Clone for bitcoin_units::amount::error::UnknownDenominationError +impl core::clone::Clone for bitcoin_units::block::BlockHeight +impl core::clone::Clone for bitcoin_units::block::BlockHeightDecoderError +impl core::clone::Clone for bitcoin_units::block::BlockHeightInterval +impl core::clone::Clone for bitcoin_units::block::BlockMtp +impl core::clone::Clone for bitcoin_units::block::BlockMtpInterval +impl core::clone::Clone for bitcoin_units::block::TooBigForRelativeHeightError +impl core::clone::Clone for bitcoin_units::fee_rate::serde::OverflowError +impl core::clone::Clone for bitcoin_units::locktime::absolute::Height +impl core::clone::Clone for bitcoin_units::locktime::absolute::LockTime +impl core::clone::Clone for bitcoin_units::locktime::absolute::MedianTimePast +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ConversionError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::LockTime +impl core::clone::Clone for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::clone::Clone for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::clone::Clone for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::clone::Clone for bitcoin_units::parse_int::ParseIntError +impl core::clone::Clone for bitcoin_units::parse_int::PrefixedHexError +impl core::clone::Clone for bitcoin_units::parse_int::UnprefixedHexError +impl core::clone::Clone for bitcoin_units::result::MathOp +impl core::clone::Clone for bitcoin_units::result::NumOpError +impl core::clone::Clone for bitcoin_units::sequence::Sequence +impl core::clone::Clone for bitcoin_units::sequence::SequenceDecoderError +impl core::clone::Clone for bitcoin_units::time::BlockTimeDecoderError +impl core::cmp::Eq for bitcoin_units::Amount +impl core::cmp::Eq for bitcoin_units::BlockTime +impl core::cmp::Eq for bitcoin_units::FeeRate +impl core::cmp::Eq for bitcoin_units::SignedAmount +impl core::cmp::Eq for bitcoin_units::Weight +impl core::cmp::Eq for bitcoin_units::amount::Denomination +impl core::cmp::Eq for bitcoin_units::amount::error::AmountDecoderError +impl core::cmp::Eq for bitcoin_units::amount::error::BadPositionError +impl core::cmp::Eq for bitcoin_units::amount::error::InputTooLargeError +impl core::cmp::Eq for bitcoin_units::amount::error::InvalidCharacterError +impl core::cmp::Eq for bitcoin_units::amount::error::MissingDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::MissingDigitsError +impl core::cmp::Eq for bitcoin_units::amount::error::OutOfRangeError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseAmountError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseError +impl core::cmp::Eq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::TooPreciseError +impl core::cmp::Eq for bitcoin_units::amount::error::UnknownDenominationError +impl core::cmp::Eq for bitcoin_units::block::BlockHeight +impl core::cmp::Eq for bitcoin_units::block::BlockHeightDecoderError +impl core::cmp::Eq for bitcoin_units::block::BlockHeightInterval +impl core::cmp::Eq for bitcoin_units::block::BlockMtp +impl core::cmp::Eq for bitcoin_units::block::BlockMtpInterval +impl core::cmp::Eq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::cmp::Eq for bitcoin_units::fee_rate::serde::OverflowError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::Height +impl core::cmp::Eq for bitcoin_units::locktime::absolute::LockTime +impl core::cmp::Eq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::LockTime +impl core::cmp::Eq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::Eq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::cmp::Eq for bitcoin_units::parse_int::ParseIntError +impl core::cmp::Eq for bitcoin_units::parse_int::PrefixedHexError +impl core::cmp::Eq for bitcoin_units::parse_int::UnprefixedHexError +impl core::cmp::Eq for bitcoin_units::result::MathOp +impl core::cmp::Eq for bitcoin_units::result::NumOpError +impl core::cmp::Eq for bitcoin_units::sequence::Sequence +impl core::cmp::Eq for bitcoin_units::sequence::SequenceDecoderError +impl core::cmp::Eq for bitcoin_units::time::BlockTimeDecoderError +impl core::cmp::Ord for bitcoin_units::Amount +impl core::cmp::Ord for bitcoin_units::BlockTime +impl core::cmp::Ord for bitcoin_units::FeeRate +impl core::cmp::Ord for bitcoin_units::SignedAmount +impl core::cmp::Ord for bitcoin_units::Weight +impl core::cmp::Ord for bitcoin_units::block::BlockHeight +impl core::cmp::Ord for bitcoin_units::block::BlockHeightInterval +impl core::cmp::Ord for bitcoin_units::block::BlockMtp +impl core::cmp::Ord for bitcoin_units::block::BlockMtpInterval +impl core::cmp::Ord for bitcoin_units::locktime::absolute::Height +impl core::cmp::Ord for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::Ord for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::Ord for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::Ord for bitcoin_units::sequence::Sequence +impl core::cmp::PartialEq for bitcoin_units::Amount +impl core::cmp::PartialEq for bitcoin_units::BlockTime +impl core::cmp::PartialEq for bitcoin_units::FeeRate +impl core::cmp::PartialEq for bitcoin_units::SignedAmount +impl core::cmp::PartialEq for bitcoin_units::Weight +impl core::cmp::PartialEq for bitcoin_units::amount::Denomination +impl core::cmp::PartialEq for bitcoin_units::amount::error::AmountDecoderError +impl core::cmp::PartialEq for bitcoin_units::amount::error::BadPositionError +impl core::cmp::PartialEq for bitcoin_units::amount::error::InputTooLargeError +impl core::cmp::PartialEq for bitcoin_units::amount::error::InvalidCharacterError +impl core::cmp::PartialEq for bitcoin_units::amount::error::MissingDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::MissingDigitsError +impl core::cmp::PartialEq for bitcoin_units::amount::error::OutOfRangeError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseAmountError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseError +impl core::cmp::PartialEq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::TooPreciseError +impl core::cmp::PartialEq for bitcoin_units::amount::error::UnknownDenominationError +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeight +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeightDecoderError +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeightInterval +impl core::cmp::PartialEq for bitcoin_units::block::BlockMtp +impl core::cmp::PartialEq for bitcoin_units::block::BlockMtpInterval +impl core::cmp::PartialEq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::cmp::PartialEq for bitcoin_units::fee_rate::serde::OverflowError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::Height +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::LockTime +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::LockTime +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::cmp::PartialEq for bitcoin_units::parse_int::ParseIntError +impl core::cmp::PartialEq for bitcoin_units::parse_int::PrefixedHexError +impl core::cmp::PartialEq for bitcoin_units::parse_int::UnprefixedHexError +impl core::cmp::PartialEq for bitcoin_units::result::MathOp +impl core::cmp::PartialEq for bitcoin_units::result::NumOpError +impl core::cmp::PartialEq for bitcoin_units::sequence::Sequence +impl core::cmp::PartialEq for bitcoin_units::sequence::SequenceDecoderError +impl core::cmp::PartialEq for bitcoin_units::time::BlockTimeDecoderError +impl core::cmp::PartialOrd for bitcoin_units::Amount +impl core::cmp::PartialOrd for bitcoin_units::BlockTime +impl core::cmp::PartialOrd for bitcoin_units::FeeRate +impl core::cmp::PartialOrd for bitcoin_units::SignedAmount +impl core::cmp::PartialOrd for bitcoin_units::Weight +impl core::cmp::PartialOrd for bitcoin_units::block::BlockHeight +impl core::cmp::PartialOrd for bitcoin_units::block::BlockHeightInterval +impl core::cmp::PartialOrd for bitcoin_units::block::BlockMtp +impl core::cmp::PartialOrd for bitcoin_units::block::BlockMtpInterval +impl core::cmp::PartialOrd for bitcoin_units::locktime::absolute::Height +impl core::cmp::PartialOrd for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::PartialOrd for bitcoin_units::sequence::Sequence +impl core::convert::AsRef for bitcoin_units::parse_int::ParseIntError +impl core::convert::From<&bitcoin_units::Amount> for bitcoin_units::result::NumOpResult +impl core::convert::From<&bitcoin_units::SignedAmount> for bitcoin_units::result::NumOpResult +impl core::convert::From for bitcoin_units::SignedAmount +impl core::convert::From for bitcoin_units::result::NumOpResult +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::result::NumOpResult +impl core::convert::From for u64 +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::block::BlockHeight +impl core::convert::From for bitcoin_units::locktime::absolute::LockTime +impl core::convert::From for bitcoin_units::block::BlockMtp +impl core::convert::From for bitcoin_units::locktime::absolute::LockTime +impl core::convert::From for bitcoin_units::sequence::Sequence +impl core::convert::From for bitcoin_units::block::BlockMtpInterval +impl core::convert::From for bitcoin_units::locktime::relative::LockTime +impl core::convert::From for bitcoin_units::block::BlockHeightInterval +impl core::convert::From for bitcoin_units::locktime::relative::LockTime +impl core::convert::From for bitcoin_units::parse_int::PrefixedHexError +impl core::convert::From for bitcoin_units::parse_int::UnprefixedHexError +impl core::convert::From for core::num::error::ParseIntError +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::amount::error::AmountDecoderError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseDenominationError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::block::BlockHeightDecoderError +impl core::convert::From for bitcoin_units::fee_rate::serde::OverflowError +impl core::convert::From for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::convert::From for bitcoin_units::parse_int::PrefixedHexError +impl core::convert::From for bitcoin_units::parse_int::UnprefixedHexError +impl core::convert::From for bitcoin_units::sequence::SequenceDecoderError +impl core::convert::From for bitcoin_units::time::BlockTimeDecoderError +impl core::convert::From for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::From for bitcoin_units::BlockTime +impl core::convert::From for bitcoin_units::block::BlockHeight +impl core::convert::From for bitcoin_units::block::BlockHeightInterval +impl core::convert::From for bitcoin_units::block::BlockMtp +impl core::convert::From for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom<&str> for bitcoin_units::Weight +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom<&str> for bitcoin_units::sequence::Sequence +impl core::convert::TryFrom> for bitcoin_units::Weight +impl core::convert::TryFrom> for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom> for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom> for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom> for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom> for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom> for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom> for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom> for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom> for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom> for bitcoin_units::sequence::Sequence +impl core::convert::TryFrom for bitcoin_units::Weight +impl core::convert::TryFrom for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom for bitcoin_units::sequence::Sequence +impl core::convert::TryFrom for bitcoin_units::Amount +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom for bitcoin_units::locktime::relative::LockTime +impl core::default::Default for bitcoin_units::Amount +impl core::default::Default for bitcoin_units::SignedAmount +impl core::default::Default for bitcoin_units::amount::AmountDecoder +impl core::default::Default for bitcoin_units::block::BlockHeightDecoder +impl core::default::Default for bitcoin_units::block::BlockHeightInterval +impl core::default::Default for bitcoin_units::block::BlockMtpInterval +impl core::default::Default for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::default::Default for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::default::Default for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::default::Default for bitcoin_units::sequence::Sequence +impl core::default::Default for bitcoin_units::sequence::SequenceDecoder +impl core::default::Default for bitcoin_units::time::BlockTimeDecoder +impl core::error::Error for bitcoin_units::amount::error::AmountDecoderError +impl core::error::Error for bitcoin_units::amount::error::BadPositionError +impl core::error::Error for bitcoin_units::amount::error::InputTooLargeError +impl core::error::Error for bitcoin_units::amount::error::InvalidCharacterError +impl core::error::Error for bitcoin_units::amount::error::MissingDigitsError +impl core::error::Error for bitcoin_units::amount::error::OutOfRangeError +impl core::error::Error for bitcoin_units::amount::error::ParseAmountError +impl core::error::Error for bitcoin_units::amount::error::ParseDenominationError +impl core::error::Error for bitcoin_units::amount::error::ParseError +impl core::error::Error for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::error::Error for bitcoin_units::amount::error::TooPreciseError +impl core::error::Error for bitcoin_units::amount::error::UnknownDenominationError +impl core::error::Error for bitcoin_units::block::BlockHeightDecoderError +impl core::error::Error for bitcoin_units::block::TooBigForRelativeHeightError +impl core::error::Error for bitcoin_units::fee_rate::serde::OverflowError +impl core::error::Error for bitcoin_units::locktime::absolute::error::ConversionError +impl core::error::Error for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::error::Error for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::error::Error for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::error::Error for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::error::Error for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::error::Error for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::error::Error for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::error::Error for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::error::Error for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::error::Error for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::error::Error for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::error::Error for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::error::Error for bitcoin_units::parse_int::ParseIntError +impl core::error::Error for bitcoin_units::parse_int::PrefixedHexError +impl core::error::Error for bitcoin_units::parse_int::UnprefixedHexError +impl core::error::Error for bitcoin_units::result::NumOpError +impl core::error::Error for bitcoin_units::sequence::SequenceDecoderError +impl core::error::Error for bitcoin_units::time::BlockTimeDecoderError +impl core::fmt::Debug for bitcoin_units::Amount +impl core::fmt::Debug for bitcoin_units::BlockTime +impl core::fmt::Debug for bitcoin_units::FeeRate +impl core::fmt::Debug for bitcoin_units::SignedAmount +impl core::fmt::Debug for bitcoin_units::Weight +impl core::fmt::Debug for bitcoin_units::amount::Denomination +impl core::fmt::Debug for bitcoin_units::amount::Display +impl core::fmt::Debug for bitcoin_units::amount::error::AmountDecoderError +impl core::fmt::Debug for bitcoin_units::amount::error::BadPositionError +impl core::fmt::Debug for bitcoin_units::amount::error::InputTooLargeError +impl core::fmt::Debug for bitcoin_units::amount::error::InvalidCharacterError +impl core::fmt::Debug for bitcoin_units::amount::error::MissingDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::MissingDigitsError +impl core::fmt::Debug for bitcoin_units::amount::error::OutOfRangeError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseAmountError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseError +impl core::fmt::Debug for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::TooPreciseError +impl core::fmt::Debug for bitcoin_units::amount::error::UnknownDenominationError +impl core::fmt::Debug for bitcoin_units::block::BlockHeight +impl core::fmt::Debug for bitcoin_units::block::BlockHeightDecoderError +impl core::fmt::Debug for bitcoin_units::block::BlockHeightInterval +impl core::fmt::Debug for bitcoin_units::block::BlockMtp +impl core::fmt::Debug for bitcoin_units::block::BlockMtpInterval +impl core::fmt::Debug for bitcoin_units::block::TooBigForRelativeHeightError +impl core::fmt::Debug for bitcoin_units::fee_rate::serde::OverflowError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::Height +impl core::fmt::Debug for bitcoin_units::locktime::absolute::LockTime +impl core::fmt::Debug for bitcoin_units::locktime::absolute::MedianTimePast +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ConversionError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::LockTime +impl core::fmt::Debug for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::fmt::Debug for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::fmt::Debug for bitcoin_units::parse_int::ParseIntError +impl core::fmt::Debug for bitcoin_units::parse_int::PrefixedHexError +impl core::fmt::Debug for bitcoin_units::parse_int::UnprefixedHexError +impl core::fmt::Debug for bitcoin_units::result::MathOp +impl core::fmt::Debug for bitcoin_units::result::NumOpError +impl core::fmt::Debug for bitcoin_units::sequence::Sequence +impl core::fmt::Debug for bitcoin_units::sequence::SequenceDecoderError +impl core::fmt::Debug for bitcoin_units::time::BlockTimeDecoderError +impl core::fmt::Display for bitcoin_units::Amount +impl core::fmt::Display for bitcoin_units::SignedAmount +impl core::fmt::Display for bitcoin_units::Weight +impl core::fmt::Display for bitcoin_units::amount::Denomination +impl core::fmt::Display for bitcoin_units::amount::Display +impl core::fmt::Display for bitcoin_units::amount::error::AmountDecoderError +impl core::fmt::Display for bitcoin_units::amount::error::BadPositionError +impl core::fmt::Display for bitcoin_units::amount::error::InputTooLargeError +impl core::fmt::Display for bitcoin_units::amount::error::InvalidCharacterError +impl core::fmt::Display for bitcoin_units::amount::error::MissingDigitsError +impl core::fmt::Display for bitcoin_units::amount::error::OutOfRangeError +impl core::fmt::Display for bitcoin_units::amount::error::ParseAmountError +impl core::fmt::Display for bitcoin_units::amount::error::ParseDenominationError +impl core::fmt::Display for bitcoin_units::amount::error::ParseError +impl core::fmt::Display for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::fmt::Display for bitcoin_units::amount::error::TooPreciseError +impl core::fmt::Display for bitcoin_units::amount::error::UnknownDenominationError +impl core::fmt::Display for bitcoin_units::block::BlockHeight +impl core::fmt::Display for bitcoin_units::block::BlockHeightDecoderError +impl core::fmt::Display for bitcoin_units::block::BlockHeightInterval +impl core::fmt::Display for bitcoin_units::block::BlockMtp +impl core::fmt::Display for bitcoin_units::block::BlockMtpInterval +impl core::fmt::Display for bitcoin_units::block::TooBigForRelativeHeightError +impl core::fmt::Display for bitcoin_units::fee_rate::serde::OverflowError +impl core::fmt::Display for bitcoin_units::locktime::absolute::Height +impl core::fmt::Display for bitcoin_units::locktime::absolute::LockTime +impl core::fmt::Display for bitcoin_units::locktime::absolute::MedianTimePast +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ConversionError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::LockTime +impl core::fmt::Display for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::fmt::Display for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::fmt::Display for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::fmt::Display for bitcoin_units::parse_int::ParseIntError +impl core::fmt::Display for bitcoin_units::parse_int::PrefixedHexError +impl core::fmt::Display for bitcoin_units::parse_int::UnprefixedHexError +impl core::fmt::Display for bitcoin_units::result::MathOp +impl core::fmt::Display for bitcoin_units::result::NumOpError +impl core::fmt::Display for bitcoin_units::sequence::Sequence +impl core::fmt::Display for bitcoin_units::sequence::SequenceDecoderError +impl core::fmt::Display for bitcoin_units::time::BlockTimeDecoderError +impl core::fmt::LowerHex for bitcoin_units::sequence::Sequence +impl core::fmt::UpperHex for bitcoin_units::sequence::Sequence +impl core::hash::Hash for bitcoin_units::Amount +impl core::hash::Hash for bitcoin_units::BlockTime +impl core::hash::Hash for bitcoin_units::FeeRate +impl core::hash::Hash for bitcoin_units::SignedAmount +impl core::hash::Hash for bitcoin_units::Weight +impl core::hash::Hash for bitcoin_units::amount::Denomination +impl core::hash::Hash for bitcoin_units::block::BlockHeight +impl core::hash::Hash for bitcoin_units::block::BlockHeightInterval +impl core::hash::Hash for bitcoin_units::block::BlockMtp +impl core::hash::Hash for bitcoin_units::block::BlockMtpInterval +impl core::hash::Hash for bitcoin_units::locktime::absolute::Height +impl core::hash::Hash for bitcoin_units::locktime::absolute::LockTime +impl core::hash::Hash for bitcoin_units::locktime::absolute::MedianTimePast +impl core::hash::Hash for bitcoin_units::locktime::relative::LockTime +impl core::hash::Hash for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::hash::Hash for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::hash::Hash for bitcoin_units::sequence::Sequence +impl core::iter::traits::accum::Sum for bitcoin_units::FeeRate +impl core::iter::traits::accum::Sum for bitcoin_units::Weight +impl core::iter::traits::accum::Sum for bitcoin_units::block::BlockHeightInterval +impl core::iter::traits::accum::Sum for bitcoin_units::block::BlockMtpInterval +impl core::iter::traits::accum::Sum for bitcoin_units::result::NumOpResult +impl core::iter::traits::accum::Sum for bitcoin_units::result::NumOpResult +impl core::marker::Copy for bitcoin_units::Amount +impl core::marker::Copy for bitcoin_units::BlockTime +impl core::marker::Copy for bitcoin_units::FeeRate +impl core::marker::Copy for bitcoin_units::SignedAmount +impl core::marker::Copy for bitcoin_units::Weight +impl core::marker::Copy for bitcoin_units::amount::Denomination +impl core::marker::Copy for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Copy for bitcoin_units::block::BlockHeight +impl core::marker::Copy for bitcoin_units::block::BlockHeightInterval +impl core::marker::Copy for bitcoin_units::block::BlockMtp +impl core::marker::Copy for bitcoin_units::block::BlockMtpInterval +impl core::marker::Copy for bitcoin_units::locktime::absolute::Height +impl core::marker::Copy for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Copy for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Copy for bitcoin_units::locktime::relative::LockTime +impl core::marker::Copy for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Copy for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Copy for bitcoin_units::result::MathOp +impl core::marker::Copy for bitcoin_units::result::NumOpError +impl core::marker::Copy for bitcoin_units::sequence::Sequence +impl core::marker::Freeze for bitcoin_units::Amount +impl core::marker::Freeze for bitcoin_units::BlockTime +impl core::marker::Freeze for bitcoin_units::FeeRate +impl core::marker::Freeze for bitcoin_units::SignedAmount +impl core::marker::Freeze for bitcoin_units::Weight +impl core::marker::Freeze for bitcoin_units::amount::AmountDecoder +impl core::marker::Freeze for bitcoin_units::amount::AmountEncoder +impl core::marker::Freeze for bitcoin_units::amount::Denomination +impl core::marker::Freeze for bitcoin_units::amount::Display +impl core::marker::Freeze for bitcoin_units::amount::error::AmountDecoderError +impl core::marker::Freeze for bitcoin_units::amount::error::BadPositionError +impl core::marker::Freeze for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Freeze for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Freeze for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Freeze for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseError +impl core::marker::Freeze for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Freeze for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Freeze for bitcoin_units::block::BlockHeight +impl core::marker::Freeze for bitcoin_units::block::BlockHeightDecoder +impl core::marker::Freeze for bitcoin_units::block::BlockHeightDecoderError +impl core::marker::Freeze for bitcoin_units::block::BlockHeightEncoder +impl core::marker::Freeze for bitcoin_units::block::BlockHeightInterval +impl core::marker::Freeze for bitcoin_units::block::BlockMtp +impl core::marker::Freeze for bitcoin_units::block::BlockMtpInterval +impl core::marker::Freeze for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Freeze for bitcoin_units::fee_rate::serde::OverflowError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::Height +impl core::marker::Freeze for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Freeze for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::marker::Freeze for bitcoin_units::locktime::absolute::LockTimeEncoder +impl core::marker::Freeze for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::LockTime +impl core::marker::Freeze for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Freeze for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Freeze for bitcoin_units::parse_int::ParseIntError +impl core::marker::Freeze for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Freeze for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Freeze for bitcoin_units::result::MathOp +impl core::marker::Freeze for bitcoin_units::result::NumOpError +impl core::marker::Freeze for bitcoin_units::sequence::Sequence +impl core::marker::Freeze for bitcoin_units::sequence::SequenceDecoder +impl core::marker::Freeze for bitcoin_units::sequence::SequenceDecoderError +impl core::marker::Freeze for bitcoin_units::sequence::SequenceEncoder +impl core::marker::Freeze for bitcoin_units::time::BlockTimeDecoder +impl core::marker::Freeze for bitcoin_units::time::BlockTimeDecoderError +impl core::marker::Freeze for bitcoin_units::time::BlockTimeEncoder +impl core::marker::Send for bitcoin_units::Amount +impl core::marker::Send for bitcoin_units::BlockTime +impl core::marker::Send for bitcoin_units::FeeRate +impl core::marker::Send for bitcoin_units::SignedAmount +impl core::marker::Send for bitcoin_units::Weight +impl core::marker::Send for bitcoin_units::amount::AmountDecoder +impl core::marker::Send for bitcoin_units::amount::AmountEncoder +impl core::marker::Send for bitcoin_units::amount::Denomination +impl core::marker::Send for bitcoin_units::amount::Display +impl core::marker::Send for bitcoin_units::amount::error::AmountDecoderError +impl core::marker::Send for bitcoin_units::amount::error::BadPositionError +impl core::marker::Send for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Send for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Send for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Send for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Send for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Send for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Send for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Send for bitcoin_units::amount::error::ParseError +impl core::marker::Send for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Send for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Send for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Send for bitcoin_units::block::BlockHeight +impl core::marker::Send for bitcoin_units::block::BlockHeightDecoder +impl core::marker::Send for bitcoin_units::block::BlockHeightDecoderError +impl core::marker::Send for bitcoin_units::block::BlockHeightEncoder +impl core::marker::Send for bitcoin_units::block::BlockHeightInterval +impl core::marker::Send for bitcoin_units::block::BlockMtp +impl core::marker::Send for bitcoin_units::block::BlockMtpInterval +impl core::marker::Send for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Send for bitcoin_units::fee_rate::serde::OverflowError +impl core::marker::Send for bitcoin_units::locktime::absolute::Height +impl core::marker::Send for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Send for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::marker::Send for bitcoin_units::locktime::absolute::LockTimeEncoder +impl core::marker::Send for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::LockTime +impl core::marker::Send for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Send for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Send for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Send for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Send for bitcoin_units::parse_int::ParseIntError +impl core::marker::Send for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Send for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Send for bitcoin_units::result::MathOp +impl core::marker::Send for bitcoin_units::result::NumOpError +impl core::marker::Send for bitcoin_units::sequence::Sequence +impl core::marker::Send for bitcoin_units::sequence::SequenceDecoder +impl core::marker::Send for bitcoin_units::sequence::SequenceDecoderError +impl core::marker::Send for bitcoin_units::sequence::SequenceEncoder +impl core::marker::Send for bitcoin_units::time::BlockTimeDecoder +impl core::marker::Send for bitcoin_units::time::BlockTimeDecoderError +impl core::marker::Send for bitcoin_units::time::BlockTimeEncoder +impl core::marker::StructuralPartialEq for bitcoin_units::Amount +impl core::marker::StructuralPartialEq for bitcoin_units::BlockTime +impl core::marker::StructuralPartialEq for bitcoin_units::FeeRate +impl core::marker::StructuralPartialEq for bitcoin_units::SignedAmount +impl core::marker::StructuralPartialEq for bitcoin_units::Weight +impl core::marker::StructuralPartialEq for bitcoin_units::amount::Denomination +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::AmountDecoderError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::BadPositionError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseAmountError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::TooPreciseError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeight +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeightDecoderError +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeightInterval +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockMtp +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockMtpInterval +impl core::marker::StructuralPartialEq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::fee_rate::serde::OverflowError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::Height +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::LockTime +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::LockTime +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::ParseIntError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::StructuralPartialEq for bitcoin_units::result::MathOp +impl core::marker::StructuralPartialEq for bitcoin_units::result::NumOpError +impl core::marker::StructuralPartialEq for bitcoin_units::sequence::Sequence +impl core::marker::StructuralPartialEq for bitcoin_units::sequence::SequenceDecoderError +impl core::marker::StructuralPartialEq for bitcoin_units::time::BlockTimeDecoderError +impl core::marker::Sync for bitcoin_units::Amount +impl core::marker::Sync for bitcoin_units::BlockTime +impl core::marker::Sync for bitcoin_units::FeeRate +impl core::marker::Sync for bitcoin_units::SignedAmount +impl core::marker::Sync for bitcoin_units::Weight +impl core::marker::Sync for bitcoin_units::amount::AmountDecoder +impl core::marker::Sync for bitcoin_units::amount::AmountEncoder +impl core::marker::Sync for bitcoin_units::amount::Denomination +impl core::marker::Sync for bitcoin_units::amount::Display +impl core::marker::Sync for bitcoin_units::amount::error::AmountDecoderError +impl core::marker::Sync for bitcoin_units::amount::error::BadPositionError +impl core::marker::Sync for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Sync for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Sync for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Sync for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Sync for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Sync for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::ParseError +impl core::marker::Sync for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Sync for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Sync for bitcoin_units::block::BlockHeight +impl core::marker::Sync for bitcoin_units::block::BlockHeightDecoder +impl core::marker::Sync for bitcoin_units::block::BlockHeightDecoderError +impl core::marker::Sync for bitcoin_units::block::BlockHeightEncoder +impl core::marker::Sync for bitcoin_units::block::BlockHeightInterval +impl core::marker::Sync for bitcoin_units::block::BlockMtp +impl core::marker::Sync for bitcoin_units::block::BlockMtpInterval +impl core::marker::Sync for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Sync for bitcoin_units::fee_rate::serde::OverflowError +impl core::marker::Sync for bitcoin_units::locktime::absolute::Height +impl core::marker::Sync for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Sync for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::marker::Sync for bitcoin_units::locktime::absolute::LockTimeEncoder +impl core::marker::Sync for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::LockTime +impl core::marker::Sync for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Sync for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Sync for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Sync for bitcoin_units::parse_int::ParseIntError +impl core::marker::Sync for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Sync for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Sync for bitcoin_units::result::MathOp +impl core::marker::Sync for bitcoin_units::result::NumOpError +impl core::marker::Sync for bitcoin_units::sequence::Sequence +impl core::marker::Sync for bitcoin_units::sequence::SequenceDecoder +impl core::marker::Sync for bitcoin_units::sequence::SequenceDecoderError +impl core::marker::Sync for bitcoin_units::sequence::SequenceEncoder +impl core::marker::Sync for bitcoin_units::time::BlockTimeDecoder +impl core::marker::Sync for bitcoin_units::time::BlockTimeDecoderError +impl core::marker::Sync for bitcoin_units::time::BlockTimeEncoder +impl core::marker::Unpin for bitcoin_units::Amount +impl core::marker::Unpin for bitcoin_units::BlockTime +impl core::marker::Unpin for bitcoin_units::FeeRate +impl core::marker::Unpin for bitcoin_units::SignedAmount +impl core::marker::Unpin for bitcoin_units::Weight +impl core::marker::Unpin for bitcoin_units::amount::AmountDecoder +impl core::marker::Unpin for bitcoin_units::amount::AmountEncoder +impl core::marker::Unpin for bitcoin_units::amount::Denomination +impl core::marker::Unpin for bitcoin_units::amount::Display +impl core::marker::Unpin for bitcoin_units::amount::error::AmountDecoderError +impl core::marker::Unpin for bitcoin_units::amount::error::BadPositionError +impl core::marker::Unpin for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Unpin for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Unpin for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Unpin for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseError +impl core::marker::Unpin for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Unpin for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Unpin for bitcoin_units::block::BlockHeight +impl core::marker::Unpin for bitcoin_units::block::BlockHeightDecoder +impl core::marker::Unpin for bitcoin_units::block::BlockHeightDecoderError +impl core::marker::Unpin for bitcoin_units::block::BlockHeightEncoder +impl core::marker::Unpin for bitcoin_units::block::BlockHeightInterval +impl core::marker::Unpin for bitcoin_units::block::BlockMtp +impl core::marker::Unpin for bitcoin_units::block::BlockMtpInterval +impl core::marker::Unpin for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Unpin for bitcoin_units::fee_rate::serde::OverflowError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::Height +impl core::marker::Unpin for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Unpin for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::marker::Unpin for bitcoin_units::locktime::absolute::LockTimeEncoder +impl core::marker::Unpin for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::LockTime +impl core::marker::Unpin for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Unpin for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Unpin for bitcoin_units::parse_int::ParseIntError +impl core::marker::Unpin for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Unpin for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Unpin for bitcoin_units::result::MathOp +impl core::marker::Unpin for bitcoin_units::result::NumOpError +impl core::marker::Unpin for bitcoin_units::sequence::Sequence +impl core::marker::Unpin for bitcoin_units::sequence::SequenceDecoder +impl core::marker::Unpin for bitcoin_units::sequence::SequenceDecoderError +impl core::marker::Unpin for bitcoin_units::sequence::SequenceEncoder +impl core::marker::Unpin for bitcoin_units::time::BlockTimeDecoder +impl core::marker::Unpin for bitcoin_units::time::BlockTimeDecoderError +impl core::marker::Unpin for bitcoin_units::time::BlockTimeEncoder +impl core::ops::arith::Add for bitcoin_units::Amount +impl core::ops::arith::Add for bitcoin_units::FeeRate +impl core::ops::arith::Add for bitcoin_units::SignedAmount +impl core::ops::arith::Add for bitcoin_units::Weight +impl core::ops::arith::Add for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Add<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::Add<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Add<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Add<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Add<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Add<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::SignedAmount +impl core::ops::arith::Add for &bitcoin_units::Amount +impl core::ops::arith::Add for &bitcoin_units::FeeRate +impl core::ops::arith::Add for &bitcoin_units::SignedAmount +impl core::ops::arith::Add for &bitcoin_units::Weight +impl core::ops::arith::Add for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Add for &bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockHeight +impl core::ops::arith::Add for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Add for &bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockMtp +impl core::ops::arith::Add> for &bitcoin_units::Amount +impl core::ops::arith::Add> for bitcoin_units::Amount +impl core::ops::arith::Add> for &bitcoin_units::SignedAmount +impl core::ops::arith::Add> for bitcoin_units::SignedAmount +impl core::ops::arith::AddAssign for bitcoin_units::FeeRate +impl core::ops::arith::AddAssign for bitcoin_units::Weight +impl core::ops::arith::AddAssign for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::AddAssign for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::AddAssign<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::AddAssign<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::AddAssign<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::SignedAmount +impl core::ops::arith::Div for bitcoin_units::Weight +impl core::ops::arith::Div<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::FeeRate> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::FeeRate> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::Amount +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::FeeRate +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::Weight +impl core::ops::arith::Div<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&u64> for bitcoin_units::Amount +impl core::ops::arith::Div<&u64> for bitcoin_units::Weight +impl core::ops::arith::Div<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::SignedAmount +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::SignedAmount +impl core::ops::arith::Div> for bitcoin_units::SignedAmount +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::FeeRate +impl core::ops::arith::Div> for &bitcoin_units::Weight +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::FeeRate +impl core::ops::arith::Div> for bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::SignedAmount +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::SignedAmount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::Weight +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign for bitcoin_units::Weight +impl core::ops::arith::DivAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::Amount> for u64 +impl core::ops::arith::Mul<&bitcoin_units::FeeRate> for bitcoin_units::Weight +impl core::ops::arith::Mul<&bitcoin_units::FeeRate> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::SignedAmount> for i64 +impl core::ops::arith::Mul<&bitcoin_units::Weight> for bitcoin_units::FeeRate +impl core::ops::arith::Mul<&bitcoin_units::Weight> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::Weight> for u64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for u64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::Weight +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for i64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::FeeRate +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Mul<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&u64> for bitcoin_units::Amount +impl core::ops::arith::Mul<&u64> for bitcoin_units::Weight +impl core::ops::arith::Mul<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &u64 +impl core::ops::arith::Mul for u64 +impl core::ops::arith::Mul for &bitcoin_units::Weight +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::Weight +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &i64 +impl core::ops::arith::Mul for i64 +impl core::ops::arith::Mul for &bitcoin_units::FeeRate +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &u64 +impl core::ops::arith::Mul for bitcoin_units::FeeRate +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for u64 +impl core::ops::arith::Mul> for &u64 +impl core::ops::arith::Mul> for u64 +impl core::ops::arith::Mul> for &bitcoin_units::Weight +impl core::ops::arith::Mul> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for bitcoin_units::Weight +impl core::ops::arith::Mul> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for &i64 +impl core::ops::arith::Mul> for i64 +impl core::ops::arith::Mul> for &bitcoin_units::FeeRate +impl core::ops::arith::Mul> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for bitcoin_units::FeeRate +impl core::ops::arith::Mul> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &bitcoin_units::SignedAmount +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::SignedAmount +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &bitcoin_units::Amount +impl core::ops::arith::Mul for &bitcoin_units::Weight +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::Amount +impl core::ops::arith::Mul for bitcoin_units::Weight +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign for bitcoin_units::Weight +impl core::ops::arith::MulAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Neg for bitcoin_units::SignedAmount +impl core::ops::arith::Rem for bitcoin_units::Weight +impl core::ops::arith::Rem<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Rem<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Rem<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem<&u64> for bitcoin_units::Amount +impl core::ops::arith::Rem<&u64> for bitcoin_units::Weight +impl core::ops::arith::Rem<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for &bitcoin_units::Weight +impl core::ops::arith::Rem for &bitcoin_units::SignedAmount +impl core::ops::arith::Rem for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for bitcoin_units::SignedAmount +impl core::ops::arith::Rem for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for &bitcoin_units::Amount +impl core::ops::arith::Rem for &bitcoin_units::Weight +impl core::ops::arith::Rem for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for bitcoin_units::Amount +impl core::ops::arith::Rem for bitcoin_units::Weight +impl core::ops::arith::Rem for bitcoin_units::result::NumOpResult +impl core::ops::arith::RemAssign for bitcoin_units::Weight +impl core::ops::arith::Sub for bitcoin_units::Amount +impl core::ops::arith::Sub for bitcoin_units::FeeRate +impl core::ops::arith::Sub for bitcoin_units::SignedAmount +impl core::ops::arith::Sub for bitcoin_units::Weight +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Sub<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::Sub<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Sub<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeight> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtp> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::SignedAmount +impl core::ops::arith::Sub for &bitcoin_units::Amount +impl core::ops::arith::Sub for &bitcoin_units::FeeRate +impl core::ops::arith::Sub for &bitcoin_units::SignedAmount +impl core::ops::arith::Sub for &bitcoin_units::Weight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub> for &bitcoin_units::Amount +impl core::ops::arith::Sub> for bitcoin_units::Amount +impl core::ops::arith::Sub> for &bitcoin_units::SignedAmount +impl core::ops::arith::Sub> for bitcoin_units::SignedAmount +impl core::ops::arith::SubAssign for bitcoin_units::FeeRate +impl core::ops::arith::SubAssign for bitcoin_units::Weight +impl core::ops::arith::SubAssign for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::SubAssign for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::SubAssign<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::SubAssign<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::SubAssign<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::Amount +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::BlockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::FeeRate +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::SignedAmount +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::Weight +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::AmountDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::AmountEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::Denomination +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::Display +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::AmountDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::BadPositionError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::InputTooLargeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::InvalidCharacterError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::MissingDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::MissingDigitsError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::OutOfRangeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseAmountError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::TooPreciseError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::UnknownDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeight +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeightDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeightDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeightEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeightInterval +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockMtp +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockMtpInterval +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::TooBigForRelativeHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::fee_rate::serde::OverflowError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::Height +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::LockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::LockTimeEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::MedianTimePast +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ConversionError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::LockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::ParseIntError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::PrefixedHexError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::UnprefixedHexError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::MathOp +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::NumOpError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::sequence::Sequence +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::sequence::SequenceDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::sequence::SequenceDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::sequence::SequenceEncoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::time::BlockTimeDecoder +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::time::BlockTimeDecoderError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::time::BlockTimeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::Amount +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::BlockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::FeeRate +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::SignedAmount +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::Weight +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::AmountDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::AmountEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::Denomination +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::Display +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::AmountDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::BadPositionError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::InputTooLargeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::InvalidCharacterError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::MissingDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::MissingDigitsError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::OutOfRangeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseAmountError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::TooPreciseError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::UnknownDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeight +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeightDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeightDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeightEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeightInterval +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockMtp +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockMtpInterval +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::TooBigForRelativeHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::fee_rate::serde::OverflowError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::Height +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::LockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::LockTimeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::LockTimeEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::MedianTimePast +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ConversionError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::LockTimeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::LockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::ParseIntError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::PrefixedHexError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::UnprefixedHexError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::MathOp +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::NumOpError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::sequence::Sequence +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::sequence::SequenceDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::sequence::SequenceDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::sequence::SequenceEncoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::time::BlockTimeDecoder +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::time::BlockTimeDecoderError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::time::BlockTimeEncoder +impl core::str::traits::FromStr for bitcoin_units::Amount +impl core::str::traits::FromStr for bitcoin_units::SignedAmount +impl core::str::traits::FromStr for bitcoin_units::Weight +impl core::str::traits::FromStr for bitcoin_units::amount::Denomination +impl core::str::traits::FromStr for bitcoin_units::block::BlockHeight +impl core::str::traits::FromStr for bitcoin_units::block::BlockHeightInterval +impl core::str::traits::FromStr for bitcoin_units::block::BlockMtp +impl core::str::traits::FromStr for bitcoin_units::block::BlockMtpInterval +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::Height +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::LockTime +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::MedianTimePast +impl core::str::traits::FromStr for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::str::traits::FromStr for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::str::traits::FromStr for bitcoin_units::sequence::Sequence +impl serde::ser::Serialize for bitcoin_units::BlockTime +impl serde::ser::Serialize for bitcoin_units::Weight +impl serde::ser::Serialize for bitcoin_units::block::BlockHeight +impl serde::ser::Serialize for bitcoin_units::block::BlockHeightInterval +impl serde::ser::Serialize for bitcoin_units::block::BlockMtp +impl serde::ser::Serialize for bitcoin_units::block::BlockMtpInterval +impl serde::ser::Serialize for bitcoin_units::locktime::absolute::LockTime +impl serde::ser::Serialize for bitcoin_units::locktime::relative::LockTime +impl serde::ser::Serialize for bitcoin_units::sequence::Sequence +impl<'a, T: arbitrary::Arbitrary<'a>> arbitrary::Arbitrary<'a> for bitcoin_units::result::NumOpResult +impl<'a, T> core::ops::arith::Add<&'a T> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl<'a, T> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl<'a, T> core::ops::arith::Sub<&'a T> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl<'a, T> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::Amount +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::BlockTime +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::FeeRate +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::SignedAmount +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::Weight +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::amount::Denomination +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::block::BlockHeight +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::block::BlockHeightInterval +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::block::BlockMtp +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::block::BlockMtpInterval +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::absolute::Height +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::absolute::LockTime +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::absolute::MedianTimePast +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::relative::NumberOf512Seconds +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::locktime::relative::NumberOfBlocks +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::result::MathOp +impl<'a> arbitrary::Arbitrary<'a> for bitcoin_units::sequence::Sequence +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::Weight> for bitcoin_units::Weight +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Add<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::FeeRate> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Add<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeightInterval +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtpInterval +impl<'a> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::FeeRate> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::FeeRate> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Amount> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::FeeRate> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::FeeRate> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::SignedAmount> for &i64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &i64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Mul<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Rem<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Rem<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Rem<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::FeeRate> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeight> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeightInterval +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtp> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtpInterval +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::SignedAmount +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::BlockTime +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::Weight +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::block::BlockHeight +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::block::BlockHeightInterval +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::block::BlockMtp +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::block::BlockMtpInterval +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::locktime::absolute::LockTime +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::locktime::relative::LockTime +impl<'de> serde::de::Deserialize<'de> for bitcoin_units::sequence::Sequence +impl core::clone::Clone for bitcoin_units::result::NumOpResult +impl core::cmp::Eq for bitcoin_units::result::NumOpResult +impl core::cmp::PartialEq for bitcoin_units::result::NumOpResult +impl bitcoin_units::result::NumOpResult +impl core::fmt::Debug for bitcoin_units::result::NumOpResult +impl core::marker::Copy for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl bitcoin_units::result::NumOpResult +impl core::marker::Freeze for bitcoin_units::result::NumOpResult where T: core::marker::Freeze +impl core::marker::Send for bitcoin_units::result::NumOpResult where T: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_units::result::NumOpResult +impl core::marker::Sync for bitcoin_units::result::NumOpResult where T: core::marker::Sync +impl core::marker::Unpin for bitcoin_units::result::NumOpResult where T: core::marker::Unpin +impl core::ops::arith::Add for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Add<&T> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Add for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Sub for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub<&T> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::NumOpResult where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::NumOpResult where T: core::panic::unwind_safe::UnwindSafe +pub bitcoin_units::NumOpResult::Error(bitcoin_units::result::NumOpError) +pub bitcoin_units::NumOpResult::Valid(T) +pub bitcoin_units::absolute::LockTime::Blocks(bitcoin_units::locktime::absolute::Height) +pub bitcoin_units::absolute::LockTime::Seconds(bitcoin_units::locktime::absolute::MedianTimePast) +pub bitcoin_units::amount::Denomination::Bit +pub bitcoin_units::amount::Denomination::Bitcoin +pub bitcoin_units::amount::Denomination::CentiBitcoin +pub bitcoin_units::amount::Denomination::MicroBitcoin +pub bitcoin_units::amount::Denomination::MilliBitcoin +pub bitcoin_units::amount::Denomination::Satoshi +pub bitcoin_units::amount::ParseDenominationError::PossiblyConfusing(bitcoin_units::amount::error::PossiblyConfusingDenominationError) +pub bitcoin_units::amount::ParseDenominationError::Unknown(bitcoin_units::amount::error::UnknownDenominationError) +pub bitcoin_units::amount::error::ParseDenominationError::PossiblyConfusing(bitcoin_units::amount::error::PossiblyConfusingDenominationError) +pub bitcoin_units::amount::error::ParseDenominationError::Unknown(bitcoin_units::amount::error::UnknownDenominationError) +pub bitcoin_units::locktime::absolute::LockTime::Blocks(bitcoin_units::locktime::absolute::Height) +pub bitcoin_units::locktime::absolute::LockTime::Seconds(bitcoin_units::locktime::absolute::MedianTimePast) +pub bitcoin_units::locktime::relative::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::LockTime::Blocks(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::LockTime::Time(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::LockTime::Blocks(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::LockTime::Time(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::error::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::error::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::error::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::error::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::error::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::error::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::result::MathOp::Add +pub bitcoin_units::result::MathOp::Div +pub bitcoin_units::result::MathOp::Mul +pub bitcoin_units::result::MathOp::Neg +pub bitcoin_units::result::MathOp::Rem +pub bitcoin_units::result::MathOp::Sub +pub bitcoin_units::result::NumOpResult::Error(bitcoin_units::result::NumOpError) +pub bitcoin_units::result::NumOpResult::Valid(T) +pub const bitcoin_units::Amount::FIFTY_BTC: Self +pub const bitcoin_units::Amount::MAX: Self +pub const bitcoin_units::Amount::MAX_MONEY: Self +pub const bitcoin_units::Amount::MIN: Self +pub const bitcoin_units::Amount::ONE_BTC: Self +pub const bitcoin_units::Amount::ONE_SAT: Self +pub const bitcoin_units::Amount::SIZE: usize +pub const bitcoin_units::Amount::ZERO: Self +pub const bitcoin_units::FeeRate::BROADCAST_MIN: Self +pub const bitcoin_units::FeeRate::DUST: Self +pub const bitcoin_units::FeeRate::MAX: Self +pub const bitcoin_units::FeeRate::MIN: Self +pub const bitcoin_units::FeeRate::ZERO: Self +pub const bitcoin_units::SignedAmount::FIFTY_BTC: Self +pub const bitcoin_units::SignedAmount::MAX: Self +pub const bitcoin_units::SignedAmount::MAX_MONEY: Self +pub const bitcoin_units::SignedAmount::MIN: Self +pub const bitcoin_units::SignedAmount::ONE_BTC: Self +pub const bitcoin_units::SignedAmount::ONE_SAT: Self +pub const bitcoin_units::SignedAmount::ZERO: Self +pub const bitcoin_units::Weight::MAX: Self +pub const bitcoin_units::Weight::MAX_BLOCK: Self +pub const bitcoin_units::Weight::MIN: Self +pub const bitcoin_units::Weight::MIN_TRANSACTION: Self +pub const bitcoin_units::Weight::WITNESS_SCALE_FACTOR: u64 +pub const bitcoin_units::Weight::ZERO: Self +pub const bitcoin_units::absolute::LOCK_TIME_THRESHOLD: u32 +pub const bitcoin_units::amount::Denomination::BTC: Self +pub const bitcoin_units::amount::Denomination::SAT: Self +pub const bitcoin_units::block::BlockHeight::MAX: Self +pub const bitcoin_units::block::BlockHeight::MIN: Self +pub const bitcoin_units::block::BlockHeight::ZERO: Self +pub const bitcoin_units::block::BlockHeightInterval::MAX: Self +pub const bitcoin_units::block::BlockHeightInterval::MIN: Self +pub const bitcoin_units::block::BlockHeightInterval::ZERO: Self +pub const bitcoin_units::block::BlockMtp::MAX: Self +pub const bitcoin_units::block::BlockMtp::MIN: Self +pub const bitcoin_units::block::BlockMtp::ZERO: Self +pub const bitcoin_units::block::BlockMtpInterval::MAX: Self +pub const bitcoin_units::block::BlockMtpInterval::MIN: Self +pub const bitcoin_units::block::BlockMtpInterval::ZERO: Self +pub const bitcoin_units::locktime::absolute::Height::MAX: Self +pub const bitcoin_units::locktime::absolute::Height::MIN: Self +pub const bitcoin_units::locktime::absolute::Height::ZERO: Self +pub const bitcoin_units::locktime::absolute::LOCK_TIME_THRESHOLD: u32 +pub const bitcoin_units::locktime::absolute::LockTime::SIZE: usize +pub const bitcoin_units::locktime::absolute::LockTime::ZERO: Self +pub const bitcoin_units::locktime::absolute::MedianTimePast::MAX: Self +pub const bitcoin_units::locktime::absolute::MedianTimePast::MIN: Self +pub const bitcoin_units::locktime::relative::LockTime::SIZE: usize +pub const bitcoin_units::locktime::relative::LockTime::ZERO: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::MAX: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::MIN: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::ZERO: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::MAX: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::MIN: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::ZERO: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_LOCKTIME_AND_RBF: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_LOCKTIME_NO_RBF: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_RBF_NO_LOCKTIME: Self +pub const bitcoin_units::sequence::Sequence::FINAL: Self +pub const bitcoin_units::sequence::Sequence::MAX: Self +pub const bitcoin_units::sequence::Sequence::SIZE: usize +pub const bitcoin_units::sequence::Sequence::ZERO: Self +pub const bitcoin_units::weight::WITNESS_SCALE_FACTOR: usize +pub const fn bitcoin_units::Amount::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_rem(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Amount::div_by_fee_rate_ceil(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_fee_rate_floor(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_weight_ceil(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_weight_floor(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::from_btc_u16(whole_bitcoin: u16) -> Self +pub const fn bitcoin_units::Amount::from_sat(satoshi: u64) -> core::result::Result +pub const fn bitcoin_units::Amount::from_sat_u32(satoshi: u32) -> Self +pub const fn bitcoin_units::Amount::to_sat(self) -> u64 +pub const fn bitcoin_units::BlockTime::from_u32(t: u32) -> Self +pub const fn bitcoin_units::BlockTime::to_u32(self) -> u32 +pub const fn bitcoin_units::FeeRate::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::FeeRate::from_per_kvb(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_per_kwu(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_per_vb(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_sat_per_kvb(sat_kvb: u32) -> Self +pub const fn bitcoin_units::FeeRate::from_sat_per_kwu(sat_kwu: u32) -> Self +pub const fn bitcoin_units::FeeRate::from_sat_per_vb(sat_vb: u32) -> Self +pub const fn bitcoin_units::FeeRate::mul_by_weight(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::to_fee(self, weight: bitcoin_units::Weight) -> bitcoin_units::Amount +pub const fn bitcoin_units::FeeRate::to_sat_per_kvb_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kvb_floor(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kwu_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kwu_floor(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_vb_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_vb_floor(self) -> u64 +pub const fn bitcoin_units::SignedAmount::abs(self) -> Self +pub const fn bitcoin_units::SignedAmount::checked_abs(self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_div(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_mul(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_rem(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::from_btc_i16(whole_bitcoin: i16) -> Self +pub const fn bitcoin_units::SignedAmount::from_sat(satoshi: i64) -> core::result::Result +pub const fn bitcoin_units::SignedAmount::from_sat_i32(satoshi: i32) -> Self +pub const fn bitcoin_units::SignedAmount::to_sat(self) -> i64 +pub const fn bitcoin_units::Weight::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Weight::from_kwu(wu: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::from_non_witness_data_size(non_witness_size: u64) -> Self +pub const fn bitcoin_units::Weight::from_vb(vb: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::from_vb_unchecked(vb: u64) -> Self +pub const fn bitcoin_units::Weight::from_vb_unwrap(vb: u64) -> Self +pub const fn bitcoin_units::Weight::from_witness_data_size(witness_size: u64) -> Self +pub const fn bitcoin_units::Weight::from_wu(wu: u64) -> Self +pub const fn bitcoin_units::Weight::mul_by_fee_rate(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Weight::to_kwu_ceil(self) -> u64 +pub const fn bitcoin_units::Weight::to_kwu_floor(self) -> u64 +pub const fn bitcoin_units::Weight::to_vbytes_ceil(self) -> u64 +pub const fn bitcoin_units::Weight::to_vbytes_floor(self) -> u64 +pub const fn bitcoin_units::Weight::to_wu(self) -> u64 +pub const fn bitcoin_units::absolute::is_block_height(n: u32) -> bool +pub const fn bitcoin_units::absolute::is_block_time(n: u32) -> bool +pub const fn bitcoin_units::amount::AmountDecoder::new() -> Self +pub const fn bitcoin_units::block::BlockHeight::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockHeight::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockHeightDecoder::new() -> Self +pub const fn bitcoin_units::block::BlockHeightInterval::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockHeightInterval::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockMtp::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockMtp::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockMtpInterval::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockMtpInterval::to_relative_mtp_interval_ceil(self) -> core::result::Result +pub const fn bitcoin_units::block::BlockMtpInterval::to_relative_mtp_interval_floor(self) -> core::result::Result +pub const fn bitcoin_units::block::BlockMtpInterval::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::Height::from_u32(n: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::absolute::Height::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::LockTime::is_block_height(self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTime::is_block_time(self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTime::is_same_unit(self, other: Self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTimeDecoder::new() -> Self +pub const fn bitcoin_units::locktime::absolute::MedianTimePast::from_u32(n: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::absolute::MedianTimePast::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::is_block_height(n: u32) -> bool +pub const fn bitcoin_units::locktime::absolute::is_block_time(n: u32) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::from_512_second_intervals(intervals: u16) -> Self +pub const fn bitcoin_units::locktime::relative::LockTime::from_height(n: u16) -> Self +pub const fn bitcoin_units::locktime::relative::LockTime::from_seconds_ceil(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::LockTime::from_seconds_floor(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::LockTime::is_block_height(self) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::is_block_time(self) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::is_same_unit(self, other: Self) -> bool +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_512_second_intervals(intervals: u16) -> Self +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_seconds_ceil(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_seconds_floor(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_512_second_intervals(self) -> u16 +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_seconds(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::from_height(blocks: u16) -> Self +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::to_height(self) -> u16 +pub const fn bitcoin_units::sequence::Sequence::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::sequence::SequenceDecoder::new() -> Self +pub const fn bitcoin_units::time::BlockTimeDecoder::new() -> Self +pub enum bitcoin_units::NumOpResult +pub enum bitcoin_units::absolute::LockTime +pub enum bitcoin_units::locktime::absolute::LockTime +pub enum bitcoin_units::locktime::relative::IsSatisfiedByError +pub enum bitcoin_units::locktime::relative::IsSatisfiedByHeightError +pub enum bitcoin_units::locktime::relative::IsSatisfiedByTimeError +pub enum bitcoin_units::locktime::relative::LockTime +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByError +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +pub enum bitcoin_units::relative::IsSatisfiedByError +pub enum bitcoin_units::relative::IsSatisfiedByHeightError +pub enum bitcoin_units::relative::IsSatisfiedByTimeError +pub enum bitcoin_units::relative::LockTime +pub enum bitcoin_units::relative::error::IsSatisfiedByError +pub enum bitcoin_units::relative::error::IsSatisfiedByHeightError +pub enum bitcoin_units::relative::error::IsSatisfiedByTimeError +pub enum bitcoin_units::result::NumOpResult +pub fn &bitcoin_units::Amount::add(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::add(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::add(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::FeeRate::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::sub(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::sub(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &core::num::nonzero::NonZeroI64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: core::num::nonzero::NonZeroI64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::mul(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::mul(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::rem(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::rem(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::add(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::add(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::sub(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::sub(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtp) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtp) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: &T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: &T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &i64::mul(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &i64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &i64::mul(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &i64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::Amount::clone(&self) -> bitcoin_units::Amount +pub fn bitcoin_units::Amount::cmp(&self, other: &bitcoin_units::Amount) -> core::cmp::Ordering +pub fn bitcoin_units::Amount::decoder() -> Self::Decoder +pub fn bitcoin_units::Amount::default() -> Self +pub fn bitcoin_units::Amount::display_dynamic(self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::Amount::display_in(self, denomination: bitcoin_units::amount::Denomination) -> bitcoin_units::amount::Display +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Amount::encoder(&self) -> Self::Encoder +pub fn bitcoin_units::Amount::eq(&self, other: &bitcoin_units::Amount) -> bool +pub fn bitcoin_units::Amount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::Amount::from_btc(btc: f64) -> core::result::Result +pub fn bitcoin_units::Amount::from_float_in(value: f64, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::Amount::from_int_btc>(whole_bitcoin: T) -> Self +pub fn bitcoin_units::Amount::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::Amount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::Amount::from_str_with_denomination(s: &str) -> core::result::Result +pub fn bitcoin_units::Amount::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::Amount::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Amount::partial_cmp(&self, other: &bitcoin_units::Amount) -> core::option::Option +pub fn bitcoin_units::Amount::rem(self, modulus: u64) -> Self::Output +pub fn bitcoin_units::Amount::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::signed_sub(self, rhs: Self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::to_btc(self) -> f64 +pub fn bitcoin_units::Amount::to_float_in(self, denom: bitcoin_units::amount::Denomination) -> f64 +pub fn bitcoin_units::Amount::to_signed(self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::Amount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::Amount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::Amount::try_from(value: bitcoin_units::SignedAmount) -> core::result::Result +pub fn bitcoin_units::BlockTime::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::BlockTime::clone(&self) -> bitcoin_units::BlockTime +pub fn bitcoin_units::BlockTime::cmp(&self, other: &bitcoin_units::BlockTime) -> core::cmp::Ordering +pub fn bitcoin_units::BlockTime::decoder() -> Self::Decoder +pub fn bitcoin_units::BlockTime::deserialize(d: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::BlockTime::encoder(&self) -> Self::Encoder +pub fn bitcoin_units::BlockTime::eq(&self, other: &bitcoin_units::BlockTime) -> bool +pub fn bitcoin_units::BlockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::BlockTime::from(t: u32) -> Self +pub fn bitcoin_units::BlockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::BlockTime::partial_cmp(&self, other: &bitcoin_units::BlockTime) -> core::option::Option +pub fn bitcoin_units::BlockTime::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::FeeRate::add(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::add(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::add_assign(&mut self, rhs: &bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::add_assign(&mut self, rhs: bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::FeeRate::clone(&self) -> bitcoin_units::FeeRate +pub fn bitcoin_units::FeeRate::cmp(&self, other: &bitcoin_units::FeeRate) -> core::cmp::Ordering +pub fn bitcoin_units::FeeRate::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::FeeRate::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::FeeRate::eq(&self, other: &bitcoin_units::FeeRate) -> bool +pub fn bitcoin_units::FeeRate::fee_vb(self, vb: u64) -> core::option::Option +pub fn bitcoin_units::FeeRate::fee_wu(self, weight: bitcoin_units::Weight) -> core::option::Option +pub fn bitcoin_units::FeeRate::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::FeeRate::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::FeeRate::partial_cmp(&self, other: &bitcoin_units::FeeRate) -> core::option::Option +pub fn bitcoin_units::FeeRate::sub(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::sub(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::sub_assign(&mut self, rhs: &bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::sub_assign(&mut self, rhs: bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::FeeRate::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::SignedAmount::clone(&self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::SignedAmount::cmp(&self, other: &bitcoin_units::SignedAmount) -> core::cmp::Ordering +pub fn bitcoin_units::SignedAmount::default() -> Self +pub fn bitcoin_units::SignedAmount::display_dynamic(self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::SignedAmount::display_in(self, denomination: bitcoin_units::amount::Denomination) -> bitcoin_units::amount::Display +pub fn bitcoin_units::SignedAmount::div(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: &core::num::nonzero::NonZeroI64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: core::num::nonzero::NonZeroI64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::eq(&self, other: &bitcoin_units::SignedAmount) -> bool +pub fn bitcoin_units::SignedAmount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::SignedAmount::from(value: bitcoin_units::Amount) -> Self +pub fn bitcoin_units::SignedAmount::from_btc(btc: f64) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_float_in(value: f64, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_int_btc>(whole_bitcoin: T) -> Self +pub fn bitcoin_units::SignedAmount::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_str_with_denomination(s: &str) -> core::result::Result +pub fn bitcoin_units::SignedAmount::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::SignedAmount::is_negative(self) -> bool +pub fn bitcoin_units::SignedAmount::is_positive(self) -> bool +pub fn bitcoin_units::SignedAmount::mul(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::mul(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::neg(self) -> Self::Output +pub fn bitcoin_units::SignedAmount::partial_cmp(&self, other: &bitcoin_units::SignedAmount) -> core::option::Option +pub fn bitcoin_units::SignedAmount::positive_sub(self, rhs: Self) -> core::option::Option +pub fn bitcoin_units::SignedAmount::rem(self, modulus: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::rem(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::signum(self) -> i64 +pub fn bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::to_btc(self) -> f64 +pub fn bitcoin_units::SignedAmount::to_float_in(self, denom: bitcoin_units::amount::Denomination) -> f64 +pub fn bitcoin_units::SignedAmount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::SignedAmount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::SignedAmount::to_unsigned(self) -> core::result::Result +pub fn bitcoin_units::SignedAmount::unsigned_abs(self) -> bitcoin_units::Amount +pub fn bitcoin_units::Weight::add(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::add(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::add_assign(&mut self, rhs: &bitcoin_units::Weight) +pub fn bitcoin_units::Weight::add_assign(&mut self, rhs: bitcoin_units::Weight) +pub fn bitcoin_units::Weight::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::Weight::clone(&self) -> bitcoin_units::Weight +pub fn bitcoin_units::Weight::cmp(&self, other: &bitcoin_units::Weight) -> core::cmp::Ordering +pub fn bitcoin_units::Weight::deserialize(d: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::Weight::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::div_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::eq(&self, other: &bitcoin_units::Weight) -> bool +pub fn bitcoin_units::Weight::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::Weight::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::Weight::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::mul_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::partial_cmp(&self, other: &bitcoin_units::Weight) -> core::option::Option +pub fn bitcoin_units::Weight::rem(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::rem_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::Weight::sub(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::sub(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::sub_assign(&mut self, rhs: &bitcoin_units::Weight) +pub fn bitcoin_units::Weight::sub_assign(&mut self, rhs: bitcoin_units::Weight) +pub fn bitcoin_units::Weight::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::Weight::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::Weight::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::Weight::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::Weight::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::amount::AmountDecoder::default() -> Self +pub fn bitcoin_units::amount::AmountDecoder::end(self) -> core::result::Result +pub fn bitcoin_units::amount::AmountDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_units::amount::AmountDecoder::read_limit(&self) -> usize +pub fn bitcoin_units::amount::AmountEncoder::advance(&mut self) -> bool +pub fn bitcoin_units::amount::AmountEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_units::amount::Denomination::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::amount::Denomination::clone(&self) -> bitcoin_units::amount::Denomination +pub fn bitcoin_units::amount::Denomination::eq(&self, other: &bitcoin_units::amount::Denomination) -> bool +pub fn bitcoin_units::amount::Denomination::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::Denomination::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::amount::Denomination::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::amount::Display::clone(&self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::amount::Display::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::Display::show_denomination(self) -> Self +pub fn bitcoin_units::amount::error::AmountDecoderError::clone(&self) -> bitcoin_units::amount::error::AmountDecoderError +pub fn bitcoin_units::amount::error::AmountDecoderError::eq(&self, other: &bitcoin_units::amount::error::AmountDecoderError) -> bool +pub fn bitcoin_units::amount::error::AmountDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::AmountDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::AmountDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::amount::error::BadPositionError::clone(&self) -> bitcoin_units::amount::error::BadPositionError +pub fn bitcoin_units::amount::error::BadPositionError::eq(&self, other: &bitcoin_units::amount::error::BadPositionError) -> bool +pub fn bitcoin_units::amount::error::BadPositionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::InputTooLargeError::clone(&self) -> bitcoin_units::amount::error::InputTooLargeError +pub fn bitcoin_units::amount::error::InputTooLargeError::eq(&self, other: &bitcoin_units::amount::error::InputTooLargeError) -> bool +pub fn bitcoin_units::amount::error::InputTooLargeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::InvalidCharacterError::clone(&self) -> bitcoin_units::amount::error::InvalidCharacterError +pub fn bitcoin_units::amount::error::InvalidCharacterError::eq(&self, other: &bitcoin_units::amount::error::InvalidCharacterError) -> bool +pub fn bitcoin_units::amount::error::InvalidCharacterError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::MissingDenominationError::clone(&self) -> bitcoin_units::amount::error::MissingDenominationError +pub fn bitcoin_units::amount::error::MissingDenominationError::eq(&self, other: &bitcoin_units::amount::error::MissingDenominationError) -> bool +pub fn bitcoin_units::amount::error::MissingDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::MissingDigitsError::clone(&self) -> bitcoin_units::amount::error::MissingDigitsError +pub fn bitcoin_units::amount::error::MissingDigitsError::eq(&self, other: &bitcoin_units::amount::error::MissingDigitsError) -> bool +pub fn bitcoin_units::amount::error::MissingDigitsError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::OutOfRangeError::clone(&self) -> bitcoin_units::amount::error::OutOfRangeError +pub fn bitcoin_units::amount::error::OutOfRangeError::eq(&self, other: &bitcoin_units::amount::error::OutOfRangeError) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::OutOfRangeError::is_above_max(self) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::is_below_min(self) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::valid_range(self) -> (i64, u64) +pub fn bitcoin_units::amount::error::ParseAmountError::clone(&self) -> bitcoin_units::amount::error::ParseAmountError +pub fn bitcoin_units::amount::error::ParseAmountError::eq(&self, other: &bitcoin_units::amount::error::ParseAmountError) -> bool +pub fn bitcoin_units::amount::error::ParseAmountError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseAmountError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::BadPositionError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::InputTooLargeError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::InvalidCharacterError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::MissingDigitsError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::OutOfRangeError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::TooPreciseError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::amount::error::ParseDenominationError::clone(&self) -> bitcoin_units::amount::error::ParseDenominationError +pub fn bitcoin_units::amount::error::ParseDenominationError::eq(&self, other: &bitcoin_units::amount::error::ParseDenominationError) -> bool +pub fn bitcoin_units::amount::error::ParseDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseDenominationError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseDenominationError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::amount::error::ParseError::clone(&self) -> bitcoin_units::amount::error::ParseError +pub fn bitcoin_units::amount::error::ParseError::eq(&self, other: &bitcoin_units::amount::error::ParseError) -> bool +pub fn bitcoin_units::amount::error::ParseError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::BadPositionError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::InputTooLargeError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::InvalidCharacterError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::MissingDigitsError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::OutOfRangeError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::ParseAmountError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::ParseDenominationError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::TooPreciseError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::clone(&self) -> bitcoin_units::amount::error::PossiblyConfusingDenominationError +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::eq(&self, other: &bitcoin_units::amount::error::PossiblyConfusingDenominationError) -> bool +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::amount::error::TooPreciseError::clone(&self) -> bitcoin_units::amount::error::TooPreciseError +pub fn bitcoin_units::amount::error::TooPreciseError::eq(&self, other: &bitcoin_units::amount::error::TooPreciseError) -> bool +pub fn bitcoin_units::amount::error::TooPreciseError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::UnknownDenominationError::clone(&self) -> bitcoin_units::amount::error::UnknownDenominationError +pub fn bitcoin_units::amount::error::UnknownDenominationError::eq(&self, other: &bitcoin_units::amount::error::UnknownDenominationError) -> bool +pub fn bitcoin_units::amount::error::UnknownDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::UnknownDenominationError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::amount::serde::as_btc::deserialize<'d, A, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result::Error> where A: core::convert::TryFrom, >::Error: core::fmt::Display +pub fn bitcoin_units::amount::serde::as_btc::opt::deserialize<'d, A, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result, ::Error> where A: core::convert::TryFrom, >::Error: core::fmt::Display +pub fn bitcoin_units::amount::serde::as_btc::opt::serialize(a: &core::option::Option, s: S) -> core::result::Result<::Ok, ::Error> where A: core::convert::Into + core::marker::Copy +pub fn bitcoin_units::amount::serde::as_btc::serialize(a: &A, s: S) -> core::result::Result<::Ok, ::Error> where A: core::convert::Into + core::marker::Copy +pub fn bitcoin_units::amount::serde::as_sat::deserialize<'d, A, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result::Error> where A: core::convert::TryFrom, >::Error: core::fmt::Display +pub fn bitcoin_units::amount::serde::as_sat::opt::deserialize<'d, A, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result, ::Error> where A: core::convert::TryFrom, >::Error: core::fmt::Display +pub fn bitcoin_units::amount::serde::as_sat::opt::serialize(a: &core::option::Option, s: S) -> core::result::Result<::Ok, ::Error> where A: core::convert::Into + core::marker::Copy +pub fn bitcoin_units::amount::serde::as_sat::serialize(a: &A, s: S) -> core::result::Result<::Ok, ::Error> where A: core::convert::Into + core::marker::Copy +pub fn bitcoin_units::amount::serde::as_str::deserialize<'d, A, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result::Error> where A: core::convert::TryFrom, >::Error: core::fmt::Display +pub fn bitcoin_units::amount::serde::as_str::opt::deserialize<'d, A, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result, ::Error> where A: core::convert::TryFrom, >::Error: core::fmt::Display +pub fn bitcoin_units::amount::serde::as_str::opt::serialize(a: &core::option::Option, s: S) -> core::result::Result<::Ok, ::Error> where A: core::convert::Into + core::marker::Copy +pub fn bitcoin_units::amount::serde::as_str::serialize(a: &A, s: S) -> core::result::Result<::Ok, ::Error> where A: core::convert::Into + core::marker::Copy +pub fn bitcoin_units::block::BlockHeight::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::block::BlockHeight::checked_add(self, other: bitcoin_units::block::BlockHeightInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::clone(&self) -> bitcoin_units::block::BlockHeight +pub fn bitcoin_units::block::BlockHeight::cmp(&self, other: &bitcoin_units::block::BlockHeight) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockHeight::decoder() -> Self::Decoder +pub fn bitcoin_units::block::BlockHeight::deserialize(d: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::block::BlockHeight::encoder(&self) -> Self::Encoder +pub fn bitcoin_units::block::BlockHeight::eq(&self, other: &bitcoin_units::block::BlockHeight) -> bool +pub fn bitcoin_units::block::BlockHeight::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeight::from(h: bitcoin_units::locktime::absolute::Height) -> Self +pub fn bitcoin_units::block::BlockHeight::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockHeight::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockHeight::partial_cmp(&self, other: &bitcoin_units::block::BlockHeight) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeight) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeight) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightDecoder::default() -> Self +pub fn bitcoin_units::block::BlockHeightDecoder::end(self) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightDecoder::read_limit(&self) -> usize +pub fn bitcoin_units::block::BlockHeightDecoderError::clone(&self) -> bitcoin_units::block::BlockHeightDecoderError +pub fn bitcoin_units::block::BlockHeightDecoderError::eq(&self, other: &bitcoin_units::block::BlockHeightDecoderError) -> bool +pub fn bitcoin_units::block::BlockHeightDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeightDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::block::BlockHeightDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::block::BlockHeightEncoder::advance(&mut self) -> bool +pub fn bitcoin_units::block::BlockHeightEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_units::block::BlockHeightInterval::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::add_assign(&mut self, rhs: &bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::add_assign(&mut self, rhs: bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::block::BlockHeightInterval::checked_add(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::clone(&self) -> bitcoin_units::block::BlockHeightInterval +pub fn bitcoin_units::block::BlockHeightInterval::cmp(&self, other: &bitcoin_units::block::BlockHeightInterval) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockHeightInterval::default() -> bitcoin_units::block::BlockHeightInterval +pub fn bitcoin_units::block::BlockHeightInterval::deserialize(d: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::block::BlockHeightInterval::eq(&self, other: &bitcoin_units::block::BlockHeightInterval) -> bool +pub fn bitcoin_units::block::BlockHeightInterval::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeightInterval::from(h: bitcoin_units::locktime::relative::NumberOfBlocks) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockHeightInterval::partial_cmp(&self, other: &bitcoin_units::block::BlockHeightInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::block::BlockHeightInterval::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::sub_assign(&mut self, rhs: &bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::sub_assign(&mut self, rhs: bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::sum>(iter: I) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::block::BlockMtp::checked_add(self, other: bitcoin_units::block::BlockMtpInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::clone(&self) -> bitcoin_units::block::BlockMtp +pub fn bitcoin_units::block::BlockMtp::cmp(&self, other: &bitcoin_units::block::BlockMtp) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockMtp::deserialize(d: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::block::BlockMtp::eq(&self, other: &bitcoin_units::block::BlockMtp) -> bool +pub fn bitcoin_units::block::BlockMtp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockMtp::from(h: bitcoin_units::locktime::absolute::MedianTimePast) -> Self +pub fn bitcoin_units::block::BlockMtp::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockMtp::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockMtp::new(timestamps: [bitcoin_units::BlockTime; 11]) -> Self +pub fn bitcoin_units::block::BlockMtp::partial_cmp(&self, other: &bitcoin_units::block::BlockMtp) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtp) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtp) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::add_assign(&mut self, rhs: &bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::add_assign(&mut self, rhs: bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::block::BlockMtpInterval::checked_add(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::clone(&self) -> bitcoin_units::block::BlockMtpInterval +pub fn bitcoin_units::block::BlockMtpInterval::cmp(&self, other: &bitcoin_units::block::BlockMtpInterval) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockMtpInterval::default() -> bitcoin_units::block::BlockMtpInterval +pub fn bitcoin_units::block::BlockMtpInterval::deserialize(d: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::block::BlockMtpInterval::eq(&self, other: &bitcoin_units::block::BlockMtpInterval) -> bool +pub fn bitcoin_units::block::BlockMtpInterval::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockMtpInterval::from(h: bitcoin_units::locktime::relative::NumberOf512Seconds) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockMtpInterval::partial_cmp(&self, other: &bitcoin_units::block::BlockMtpInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::serialize(&self, s: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::block::BlockMtpInterval::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::sub_assign(&mut self, rhs: &bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::sub_assign(&mut self, rhs: bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::sum>(iter: I) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::TooBigForRelativeHeightError::clone(&self) -> bitcoin_units::block::TooBigForRelativeHeightError +pub fn bitcoin_units::block::TooBigForRelativeHeightError::eq(&self, other: &bitcoin_units::block::TooBigForRelativeHeightError) -> bool +pub fn bitcoin_units::block::TooBigForRelativeHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::fee_rate::serde::OverflowError::clone(&self) -> bitcoin_units::fee_rate::serde::OverflowError +pub fn bitcoin_units::fee_rate::serde::OverflowError::eq(&self, other: &bitcoin_units::fee_rate::serde::OverflowError) -> bool +pub fn bitcoin_units::fee_rate::serde::OverflowError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::fee_rate::serde::OverflowError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu_floor::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu_floor::opt::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu_floor::opt::serialize(f: &core::option::Option, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu_floor::serialize(f: &bitcoin_units::FeeRate, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt::serialize(f: &core::option::Option, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::serialize(f: &bitcoin_units::FeeRate, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt::serialize(f: &core::option::Option, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::serialize(f: &bitcoin_units::FeeRate, s: S) -> core::result::Result<::Ok, ::Error> +pub fn bitcoin_units::locktime::absolute::Height::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::locktime::absolute::Height::clone(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::Height::cmp(&self, other: &bitcoin_units::locktime::absolute::Height) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::absolute::Height::eq(&self, other: &bitcoin_units::locktime::absolute::Height) -> bool +pub fn bitcoin_units::locktime::absolute::Height::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::Height::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::Height::is_satisfied_by(self, height: Self) -> bool +pub fn bitcoin_units::locktime::absolute::Height::partial_cmp(&self, other: &bitcoin_units::locktime::absolute::Height) -> core::option::Option +pub fn bitcoin_units::locktime::absolute::Height::try_from(h: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::locktime::absolute::LockTime::clone(&self) -> bitcoin_units::locktime::absolute::LockTime +pub fn bitcoin_units::locktime::absolute::LockTime::decoder() -> Self::Decoder +pub fn bitcoin_units::locktime::absolute::LockTime::deserialize(deserializer: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::locktime::absolute::LockTime::encoder(&self) -> Self::Encoder +pub fn bitcoin_units::locktime::absolute::LockTime::eq(&self, other: &bitcoin_units::locktime::absolute::LockTime) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from(h: bitcoin_units::locktime::absolute::Height) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from(t: bitcoin_units::locktime::absolute::MedianTimePast) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from_consensus(n: u32) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from_height(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_mtp(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_unprefixed_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::LockTime::is_implied_by(self, other: Self) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by(self, height: bitcoin_units::locktime::absolute::Height, mtp: bitcoin_units::locktime::absolute::MedianTimePast) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by_height(self, height: bitcoin_units::locktime::absolute::Height) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by_time(self, mtp: bitcoin_units::locktime::absolute::MedianTimePast) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::serialize(&self, serializer: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::locktime::absolute::LockTime::to_consensus_u32(self) -> u32 +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTimeDecoder::default() -> Self +pub fn bitcoin_units::locktime::absolute::LockTimeDecoder::end(self) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTimeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTimeDecoder::read_limit(&self) -> usize +pub fn bitcoin_units::locktime::absolute::LockTimeEncoder::advance(&mut self) -> bool +pub fn bitcoin_units::locktime::absolute::LockTimeEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_units::locktime::absolute::MedianTimePast::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::clone(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::MedianTimePast::cmp(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::absolute::MedianTimePast::eq(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> bool +pub fn bitcoin_units::locktime::absolute::MedianTimePast::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::MedianTimePast::is_satisfied_by(self, time: Self) -> bool +pub fn bitcoin_units::locktime::absolute::MedianTimePast::new(timestamps: [bitcoin_units::BlockTime; 11]) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::partial_cmp(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> core::option::Option +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(h: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::error::ConversionError::clone(&self) -> bitcoin_units::locktime::absolute::error::ConversionError +pub fn bitcoin_units::locktime::absolute::error::ConversionError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ConversionError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ConversionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::ConversionError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::clone(&self) -> bitcoin_units::locktime::absolute::error::IncompatibleHeightError +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::eq(&self, other: &bitcoin_units::locktime::absolute::error::IncompatibleHeightError) -> bool +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::incompatible(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::lock(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::clone(&self) -> bitcoin_units::locktime::absolute::error::IncompatibleTimeError +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::IncompatibleTimeError) -> bool +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::incompatible(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::lock(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::error::LockTimeDecoderError::clone(&self) -> bitcoin_units::locktime::absolute::error::LockTimeDecoderError +pub fn bitcoin_units::locktime::absolute::error::LockTimeDecoderError::eq(&self, other: &bitcoin_units::locktime::absolute::error::LockTimeDecoderError) -> bool +pub fn bitcoin_units::locktime::absolute::error::LockTimeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::LockTimeDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::locktime::absolute::error::LockTimeDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::clone(&self) -> bitcoin_units::locktime::absolute::error::ParseHeightError +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseHeightError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::clone(&self) -> bitcoin_units::locktime::absolute::error::ParseTimeError +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseTimeError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::relative::LockTime::clone(&self) -> bitcoin_units::locktime::relative::LockTime +pub fn bitcoin_units::locktime::relative::LockTime::deserialize(deserializer: D) -> core::result::Result::Error> where D: serde::de::Deserializer<'de> +pub fn bitcoin_units::locktime::relative::LockTime::eq(&self, other: &bitcoin_units::locktime::relative::LockTime) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::LockTime::from(h: bitcoin_units::locktime::relative::NumberOfBlocks) -> Self +pub fn bitcoin_units::locktime::relative::LockTime::from(t: bitcoin_units::locktime::relative::NumberOf512Seconds) -> Self +pub fn bitcoin_units::locktime::relative::LockTime::from_consensus(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::from_sequence(n: bitcoin_units::sequence::Sequence) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::LockTime::is_implied_by(self, other: Self) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::is_implied_by_sequence(self, other: bitcoin_units::sequence::Sequence) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by(self, chain_tip_height: bitcoin_units::block::BlockHeight, chain_tip_mtp: bitcoin_units::block::BlockMtp, utxo_mined_at_height: bitcoin_units::block::BlockHeight, utxo_mined_at_mtp: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by_height(self, chain_tip: bitcoin_units::block::BlockHeight, utxo_mined_at: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by_time(self, chain_tip: bitcoin_units::block::BlockMtp, utxo_mined_at: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::serialize(&self, serializer: S) -> core::result::Result<::Ok, ::Error> where S: serde::ser::Serializer +pub fn bitcoin_units::locktime::relative::LockTime::to_consensus_u32(self) -> u32 +pub fn bitcoin_units::locktime::relative::LockTime::to_sequence(self) -> bitcoin_units::sequence::Sequence +pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::clone(&self) -> bitcoin_units::locktime::relative::NumberOf512Seconds +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::cmp(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::default() -> bitcoin_units::locktime::relative::NumberOf512Seconds +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::eq(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> bool +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::is_satisfied_by(self, chain_tip: bitcoin_units::block::BlockMtp, utxo_mined_at: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::partial_cmp(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> core::option::Option +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::clone(&self) -> bitcoin_units::locktime::relative::NumberOfBlocks +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::cmp(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::default() -> bitcoin_units::locktime::relative::NumberOfBlocks +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::eq(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> bool +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::from(value: u16) -> Self +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::is_satisfied_by(self, chain_tip: bitcoin_units::block::BlockHeight, utxo_mined_at: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::partial_cmp(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> core::option::Option +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(h: bitcoin_units::block::BlockHeightInterval) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::DisabledLockTimeError +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::disabled_locktime_value(&self) -> u32 +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::DisabledLockTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::clone(&self) -> bitcoin_units::locktime::relative::error::InvalidHeightError +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::eq(&self, other: &bitcoin_units::locktime::relative::error::InvalidHeightError) -> bool +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::InvalidTimeError +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::InvalidTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::clone(&self) -> bitcoin_units::locktime::relative::error::TimeOverflowError +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::eq(&self, other: &bitcoin_units::locktime::relative::error::TimeOverflowError) -> bool +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::ParseIntError::as_ref(&self) -> &core::num::error::ParseIntError +pub fn bitcoin_units::parse_int::ParseIntError::clone(&self) -> bitcoin_units::parse_int::ParseIntError +pub fn bitcoin_units::parse_int::ParseIntError::eq(&self, other: &bitcoin_units::parse_int::ParseIntError) -> bool +pub fn bitcoin_units::parse_int::ParseIntError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::ParseIntError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::parse_int::PrefixedHexError::clone(&self) -> bitcoin_units::parse_int::PrefixedHexError +pub fn bitcoin_units::parse_int::PrefixedHexError::eq(&self, other: &bitcoin_units::parse_int::PrefixedHexError) -> bool +pub fn bitcoin_units::parse_int::PrefixedHexError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::PrefixedHexError::from(e: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn bitcoin_units::parse_int::PrefixedHexError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::parse_int::PrefixedHexError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::parse_int::UnprefixedHexError::clone(&self) -> bitcoin_units::parse_int::UnprefixedHexError +pub fn bitcoin_units::parse_int::UnprefixedHexError::eq(&self, other: &bitcoin_units::parse_int::UnprefixedHexError) -> bool +pub fn bitcoin_units::parse_int::UnprefixedHexError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::UnprefixedHexError::from(e: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn bitcoin_units::parse_int::UnprefixedHexError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::parse_int::UnprefixedHexError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::parse_int::hex_check_unprefixed(s: &str) -> core::result::Result<&str, bitcoin_units::parse_int::UnprefixedHexError> +pub fn bitcoin_units::parse_int::hex_remove_prefix(s: &str) -> core::result::Result<&str, bitcoin_units::parse_int::PrefixedHexError> +pub fn bitcoin_units::parse_int::hex_u128(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_prefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_unchecked(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_unprefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_prefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_unchecked(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_unprefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_box(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_string(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::result::MathOp::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::result::MathOp::clone(&self) -> bitcoin_units::result::MathOp +pub fn bitcoin_units::result::MathOp::eq(&self, other: &bitcoin_units::result::MathOp) -> bool +pub fn bitcoin_units::result::MathOp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::MathOp::is_addition(self) -> bool +pub fn bitcoin_units::result::MathOp::is_div_by_zero(self) -> bool +pub fn bitcoin_units::result::MathOp::is_multiplication(self) -> bool +pub fn bitcoin_units::result::MathOp::is_negation(self) -> bool +pub fn bitcoin_units::result::MathOp::is_overflow(self) -> bool +pub fn bitcoin_units::result::MathOp::is_subtraction(self) -> bool +pub fn bitcoin_units::result::NumOpError::clone(&self) -> bitcoin_units::result::NumOpError +pub fn bitcoin_units::result::NumOpError::eq(&self, other: &bitcoin_units::result::NumOpError) -> bool +pub fn bitcoin_units::result::NumOpError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::NumOpError::is_div_by_zero(self) -> bool +pub fn bitcoin_units::result::NumOpError::is_overflow(self) -> bool +pub fn bitcoin_units::result::NumOpError::operation(self) -> bitcoin_units::result::MathOp +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: &T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: Self) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: T) +pub fn bitcoin_units::result::NumOpResult::and_then(self, op: F) -> Self where F: core::ops::function::FnOnce(T) -> Self +pub fn bitcoin_units::result::NumOpResult::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::result::NumOpResult::clone(&self) -> bitcoin_units::result::NumOpResult +pub fn bitcoin_units::result::NumOpResult::eq(&self, other: &bitcoin_units::result::NumOpResult) -> bool +pub fn bitcoin_units::result::NumOpResult::expect(self, msg: &str) -> T +pub fn bitcoin_units::result::NumOpResult::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::NumOpResult::into_result(self) -> core::result::Result +pub fn bitcoin_units::result::NumOpResult::is_error(&self) -> bool +pub fn bitcoin_units::result::NumOpResult::is_valid(&self) -> bool +pub fn bitcoin_units::result::NumOpResult::map U>(self, op: F) -> bitcoin_units::result::NumOpResult +pub fn bitcoin_units::result::NumOpResult::ok(self) -> core::option::Option +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: &T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: Self) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: T) +pub fn bitcoin_units::result::NumOpResult::unwrap(self) -> T +pub fn bitcoin_units::result::NumOpResult::unwrap_err(self) -> bitcoin_units::result::NumOpError +pub fn bitcoin_units::result::NumOpResult::unwrap_or(self, default: T) -> T +pub fn bitcoin_units::result::NumOpResult::unwrap_or_else(self, f: F) -> T where F: core::ops::function::FnOnce() -> T +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: bitcoin_units::Amount) +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: &u64) +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: u64) +pub fn bitcoin_units::result::NumOpResult::from(a: &bitcoin_units::Amount) -> Self +pub fn bitcoin_units::result::NumOpResult::from(a: bitcoin_units::Amount) -> Self +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: &u64) +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: u64) +pub fn bitcoin_units::result::NumOpResult::rem(self, modulus: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: bitcoin_units::Amount) +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: bitcoin_units::SignedAmount) +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: &i64) +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: i64) +pub fn bitcoin_units::result::NumOpResult::from(a: &bitcoin_units::SignedAmount) -> Self +pub fn bitcoin_units::result::NumOpResult::from(a: bitcoin_units::SignedAmount) -> Self +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: &i64) +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: i64) +pub fn bitcoin_units::result::NumOpResult::rem(self, modulus: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::rem(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: bitcoin_units::SignedAmount) +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::sequence::Sequence::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result +pub fn bitcoin_units::sequence::Sequence::clone(&self) -> bitcoin_units::sequence::Sequence +pub fn bitcoin_units::sequence::Sequence::cmp(&self, other: &bitcoin_units::sequence::Sequence) -> core::cmp::Ordering +pub fn bitcoin_units::sequence::Sequence::decoder() -> Self::Decoder +pub fn bitcoin_units::sequence::Sequence::default() -> Self +pub fn bitcoin_units::sequence::Sequence::deserialize<__D>(__deserializer: __D) -> core::result::Result::Error> where __D: serde::de::Deserializer<'de> +pub fn bitcoin_units::sequence::Sequence::enables_absolute_lock_time(self) -> bool +pub fn bitcoin_units::sequence::Sequence::encoder(&self) -> Self::Encoder +pub fn bitcoin_units::sequence::Sequence::eq(&self, other: &bitcoin_units::sequence::Sequence) -> bool +pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::sequence::Sequence::from(lt: bitcoin_units::locktime::relative::LockTime) -> Self +pub fn bitcoin_units::sequence::Sequence::from_512_second_intervals(intervals: u16) -> Self +pub fn bitcoin_units::sequence::Sequence::from_consensus(n: u32) -> Self +pub fn bitcoin_units::sequence::Sequence::from_height(height: u16) -> Self +pub fn bitcoin_units::sequence::Sequence::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_seconds_ceil(seconds: u32) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_seconds_floor(seconds: u32) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_unprefixed_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::sequence::Sequence::is_final(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_height_locked(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_rbf(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_relative_lock_time(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_time_locked(self) -> bool +pub fn bitcoin_units::sequence::Sequence::partial_cmp(&self, other: &bitcoin_units::sequence::Sequence) -> core::option::Option +pub fn bitcoin_units::sequence::Sequence::serialize<__S>(&self, __serializer: __S) -> core::result::Result<<__S as serde::ser::Serializer>::Ok, <__S as serde::ser::Serializer>::Error> where __S: serde::ser::Serializer +pub fn bitcoin_units::sequence::Sequence::to_hex(self) -> alloc::string::String +pub fn bitcoin_units::sequence::Sequence::to_relative_lock_time(self) -> core::option::Option +pub fn bitcoin_units::sequence::Sequence::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::sequence::SequenceDecoder::default() -> Self +pub fn bitcoin_units::sequence::SequenceDecoder::end(self) -> core::result::Result +pub fn bitcoin_units::sequence::SequenceDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_units::sequence::SequenceDecoder::read_limit(&self) -> usize +pub fn bitcoin_units::sequence::SequenceDecoderError::clone(&self) -> bitcoin_units::sequence::SequenceDecoderError +pub fn bitcoin_units::sequence::SequenceDecoderError::eq(&self, other: &bitcoin_units::sequence::SequenceDecoderError) -> bool +pub fn bitcoin_units::sequence::SequenceDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::sequence::SequenceDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::sequence::SequenceDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::sequence::SequenceEncoder::advance(&mut self) -> bool +pub fn bitcoin_units::sequence::SequenceEncoder::current_chunk(&self) -> &[u8] +pub fn bitcoin_units::time::BlockTimeDecoder::default() -> Self +pub fn bitcoin_units::time::BlockTimeDecoder::end(self) -> core::result::Result +pub fn bitcoin_units::time::BlockTimeDecoder::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result +pub fn bitcoin_units::time::BlockTimeDecoder::read_limit(&self) -> usize +pub fn bitcoin_units::time::BlockTimeDecoderError::clone(&self) -> bitcoin_units::time::BlockTimeDecoderError +pub fn bitcoin_units::time::BlockTimeDecoderError::eq(&self, other: &bitcoin_units::time::BlockTimeDecoderError) -> bool +pub fn bitcoin_units::time::BlockTimeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::time::BlockTimeDecoderError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::time::BlockTimeDecoderError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +pub fn bitcoin_units::time::BlockTimeEncoder::advance(&mut self) -> bool +pub fn bitcoin_units::time::BlockTimeEncoder::current_chunk(&self) -> &[u8] +pub fn core::num::error::ParseIntError::from(value: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn i64::mul(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn i64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn i64::mul(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn i64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn u32::from(height: bitcoin_units::block::BlockHeight) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockHeightInterval) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockMtp) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockMtpInterval) -> Self +pub fn u32::from(sequence: bitcoin_units::sequence::Sequence) -> Self +pub fn u32::from(t: bitcoin_units::BlockTime) -> Self +pub fn u64::from(value: bitcoin_units::Weight) -> Self +pub fn u64::mul(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn u64::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn u64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub mod bitcoin_units +pub mod bitcoin_units::absolute +pub mod bitcoin_units::absolute::error +pub mod bitcoin_units::amount +pub mod bitcoin_units::amount::error +pub mod bitcoin_units::amount::serde +pub mod bitcoin_units::amount::serde::as_btc +pub mod bitcoin_units::amount::serde::as_btc::opt +pub mod bitcoin_units::amount::serde::as_sat +pub mod bitcoin_units::amount::serde::as_sat::opt +pub mod bitcoin_units::amount::serde::as_str +pub mod bitcoin_units::amount::serde::as_str::opt +pub mod bitcoin_units::block +pub mod bitcoin_units::fee_rate +pub mod bitcoin_units::fee_rate::serde +pub mod bitcoin_units::fee_rate::serde::as_sat_per_kwu_floor +pub mod bitcoin_units::fee_rate::serde::as_sat_per_kwu_floor::opt +pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil +pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt +pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_floor +pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt +pub mod bitcoin_units::locktime +pub mod bitcoin_units::locktime::absolute +pub mod bitcoin_units::locktime::absolute::error +pub mod bitcoin_units::locktime::relative +pub mod bitcoin_units::locktime::relative::error +pub mod bitcoin_units::parse_int +pub mod bitcoin_units::relative +pub mod bitcoin_units::relative::error +pub mod bitcoin_units::result +pub mod bitcoin_units::sequence +pub mod bitcoin_units::time +pub mod bitcoin_units::weight +pub struct bitcoin_units::Amount(_) +pub struct bitcoin_units::BlockHeight(_) +pub struct bitcoin_units::BlockHeightInterval(_) +pub struct bitcoin_units::BlockMtp(_) +pub struct bitcoin_units::BlockMtpInterval(_) +pub struct bitcoin_units::BlockTime(_) +pub struct bitcoin_units::FeeRate(_) +pub struct bitcoin_units::Sequence(pub u32) +pub struct bitcoin_units::SignedAmount(_) +pub struct bitcoin_units::Weight(_) +pub struct bitcoin_units::absolute::Height(_) +pub struct bitcoin_units::absolute::IncompatibleHeightError +pub struct bitcoin_units::absolute::IncompatibleTimeError +pub struct bitcoin_units::absolute::LockTimeDecoder(_) +pub struct bitcoin_units::absolute::LockTimeDecoderError(_) +pub struct bitcoin_units::absolute::LockTimeEncoder(_) +pub struct bitcoin_units::absolute::MedianTimePast(_) +pub struct bitcoin_units::absolute::ParseHeightError(_) +pub struct bitcoin_units::absolute::ParseTimeError(_) +pub struct bitcoin_units::absolute::error::IncompatibleHeightError +pub struct bitcoin_units::absolute::error::IncompatibleTimeError +pub struct bitcoin_units::absolute::error::LockTimeDecoderError(_) +pub struct bitcoin_units::absolute::error::ParseHeightError(_) +pub struct bitcoin_units::absolute::error::ParseTimeError(_) +pub struct bitcoin_units::amount::Amount(_) +pub struct bitcoin_units::amount::AmountDecoder(_) +pub struct bitcoin_units::amount::AmountDecoderError(_) +pub struct bitcoin_units::amount::AmountEncoder(_) +pub struct bitcoin_units::amount::Display +pub struct bitcoin_units::amount::OutOfRangeError +pub struct bitcoin_units::amount::ParseAmountError(_) +pub struct bitcoin_units::amount::ParseError(_) +pub struct bitcoin_units::amount::SignedAmount(_) +pub struct bitcoin_units::amount::error::AmountDecoderError(_) +pub struct bitcoin_units::amount::error::BadPositionError +pub struct bitcoin_units::amount::error::InputTooLargeError +pub struct bitcoin_units::amount::error::InvalidCharacterError +pub struct bitcoin_units::amount::error::MissingDigitsError +pub struct bitcoin_units::amount::error::OutOfRangeError +pub struct bitcoin_units::amount::error::ParseAmountError(_) +pub struct bitcoin_units::amount::error::ParseError(_) +pub struct bitcoin_units::amount::error::TooPreciseError +pub struct bitcoin_units::block::BlockHeight(_) +pub struct bitcoin_units::block::BlockHeightDecoder(_) +pub struct bitcoin_units::block::BlockHeightDecoderError(_) +pub struct bitcoin_units::block::BlockHeightEncoder(_) +pub struct bitcoin_units::block::BlockHeightInterval(_) +pub struct bitcoin_units::block::BlockMtp(_) +pub struct bitcoin_units::block::BlockMtpInterval(_) +pub struct bitcoin_units::block::TooBigForRelativeHeightError(_) +pub struct bitcoin_units::fee_rate::FeeRate(_) +pub struct bitcoin_units::locktime::absolute::Height(_) +pub struct bitcoin_units::locktime::absolute::IncompatibleHeightError +pub struct bitcoin_units::locktime::absolute::IncompatibleTimeError +pub struct bitcoin_units::locktime::absolute::LockTimeDecoder(_) +pub struct bitcoin_units::locktime::absolute::LockTimeDecoderError(_) +pub struct bitcoin_units::locktime::absolute::LockTimeEncoder(_) +pub struct bitcoin_units::locktime::absolute::MedianTimePast(_) +pub struct bitcoin_units::locktime::absolute::ParseHeightError(_) +pub struct bitcoin_units::locktime::absolute::ParseTimeError(_) +pub struct bitcoin_units::locktime::absolute::error::IncompatibleHeightError +pub struct bitcoin_units::locktime::absolute::error::IncompatibleTimeError +pub struct bitcoin_units::locktime::absolute::error::LockTimeDecoderError(_) +pub struct bitcoin_units::locktime::absolute::error::ParseHeightError(_) +pub struct bitcoin_units::locktime::absolute::error::ParseTimeError(_) +pub struct bitcoin_units::locktime::relative::DisabledLockTimeError(_) +pub struct bitcoin_units::locktime::relative::InvalidHeightError +pub struct bitcoin_units::locktime::relative::InvalidTimeError +pub struct bitcoin_units::locktime::relative::NumberOf512Seconds(_) +pub struct bitcoin_units::locktime::relative::NumberOfBlocks(_) +pub struct bitcoin_units::locktime::relative::TimeOverflowError +pub struct bitcoin_units::locktime::relative::error::DisabledLockTimeError(_) +pub struct bitcoin_units::locktime::relative::error::InvalidHeightError +pub struct bitcoin_units::locktime::relative::error::InvalidTimeError +pub struct bitcoin_units::locktime::relative::error::TimeOverflowError +pub struct bitcoin_units::parse_int::PrefixedHexError(_) +pub struct bitcoin_units::parse_int::UnprefixedHexError(_) +pub struct bitcoin_units::relative::DisabledLockTimeError(_) +pub struct bitcoin_units::relative::InvalidHeightError +pub struct bitcoin_units::relative::InvalidTimeError +pub struct bitcoin_units::relative::NumberOf512Seconds(_) +pub struct bitcoin_units::relative::NumberOfBlocks(_) +pub struct bitcoin_units::relative::TimeOverflowError +pub struct bitcoin_units::relative::error::DisabledLockTimeError(_) +pub struct bitcoin_units::relative::error::InvalidHeightError +pub struct bitcoin_units::relative::error::InvalidTimeError +pub struct bitcoin_units::relative::error::TimeOverflowError +pub struct bitcoin_units::sequence::Sequence(pub u32) +pub struct bitcoin_units::sequence::SequenceDecoder(_) +pub struct bitcoin_units::sequence::SequenceDecoderError(_) +pub struct bitcoin_units::sequence::SequenceEncoder(_) +pub struct bitcoin_units::time::BlockTime(_) +pub struct bitcoin_units::time::BlockTimeDecoder(_) +pub struct bitcoin_units::time::BlockTimeDecoderError(_) +pub struct bitcoin_units::time::BlockTimeEncoder(_) +pub struct bitcoin_units::weight::Weight(_) +pub trait bitcoin_units::parse_int::Integer: core::str::traits::FromStr + core::convert::TryFrom + core::marker::Sized + bitcoin_units::parse_int::sealed::Sealed +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::FeeRate::Output = ::Output +pub type &bitcoin_units::FeeRate::Output = >>::Output +pub type &bitcoin_units::FeeRate::Output = >::Output +pub type &bitcoin_units::FeeRate::Output = >>::Output +pub type &bitcoin_units::FeeRate::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = >>::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = >>::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::block::BlockHeight::Output = >::Output +pub type &bitcoin_units::block::BlockHeight::Output = >::Output +pub type &bitcoin_units::block::BlockHeight::Output = ::Output +pub type &bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type &bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type &bitcoin_units::block::BlockMtp::Output = >::Output +pub type &bitcoin_units::block::BlockMtp::Output = >::Output +pub type &bitcoin_units::block::BlockMtp::Output = ::Output +pub type &bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type &bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type &i64::Output = >::Output +pub type &i64::Output = >>::Output +pub type &u64::Output = >::Output +pub type &u64::Output = >::Output +pub type &u64::Output = >>::Output +pub type bitcoin_units::Amount::Decoder = bitcoin_units::amount::AmountDecoder +pub type bitcoin_units::Amount::Encoder<'e> = bitcoin_units::amount::AmountEncoder +pub type bitcoin_units::Amount::Err = bitcoin_units::amount::error::ParseError +pub type bitcoin_units::Amount::Error = bitcoin_units::amount::error::OutOfRangeError +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = bitcoin_units::Amount +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::BlockTime::Decoder = bitcoin_units::time::BlockTimeDecoder +pub type bitcoin_units::BlockTime::Encoder<'e> = bitcoin_units::time::BlockTimeEncoder +pub type bitcoin_units::FeeRate::Output = ::Output +pub type bitcoin_units::FeeRate::Output = >>::Output +pub type bitcoin_units::FeeRate::Output = >::Output +pub type bitcoin_units::FeeRate::Output = >>::Output +pub type bitcoin_units::FeeRate::Output = ::Output +pub type bitcoin_units::FeeRate::Output = bitcoin_units::FeeRate +pub type bitcoin_units::FeeRate::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::SignedAmount::Err = bitcoin_units::amount::error::ParseError +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::SignedAmount +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Weight::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::Weight::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = >>::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = >>::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = bitcoin_units::Weight +pub type bitcoin_units::Weight::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Weight::Output = u64 +pub type bitcoin_units::amount::AmountDecoder::Error = bitcoin_units::amount::error::AmountDecoderError +pub type bitcoin_units::amount::AmountDecoder::Output = bitcoin_units::Amount +pub type bitcoin_units::amount::Denomination::Err = bitcoin_units::amount::error::ParseDenominationError +pub type bitcoin_units::block::BlockHeight::Decoder = bitcoin_units::block::BlockHeightDecoder +pub type bitcoin_units::block::BlockHeight::Encoder<'e> = bitcoin_units::block::BlockHeightEncoder +pub type bitcoin_units::block::BlockHeight::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeight::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeight::Output = >::Output +pub type bitcoin_units::block::BlockHeight::Output = >::Output +pub type bitcoin_units::block::BlockHeight::Output = ::Output +pub type bitcoin_units::block::BlockHeight::Output = bitcoin_units::block::BlockHeight +pub type bitcoin_units::block::BlockHeight::Output = bitcoin_units::block::BlockHeightInterval +pub type bitcoin_units::block::BlockHeightDecoder::Error = bitcoin_units::block::BlockHeightDecoderError +pub type bitcoin_units::block::BlockHeightDecoder::Output = bitcoin_units::block::BlockHeight +pub type bitcoin_units::block::BlockHeightInterval::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeightInterval::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type bitcoin_units::block::BlockHeightInterval::Output = bitcoin_units::block::BlockHeightInterval +pub type bitcoin_units::block::BlockMtp::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtp::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtp::Output = >::Output +pub type bitcoin_units::block::BlockMtp::Output = >::Output +pub type bitcoin_units::block::BlockMtp::Output = ::Output +pub type bitcoin_units::block::BlockMtp::Output = bitcoin_units::block::BlockMtp +pub type bitcoin_units::block::BlockMtp::Output = bitcoin_units::block::BlockMtpInterval +pub type bitcoin_units::block::BlockMtpInterval::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtpInterval::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type bitcoin_units::block::BlockMtpInterval::Output = bitcoin_units::block::BlockMtpInterval +pub type bitcoin_units::locktime::absolute::Height::Err = bitcoin_units::locktime::absolute::error::ParseHeightError +pub type bitcoin_units::locktime::absolute::Height::Error = bitcoin_units::locktime::absolute::error::ConversionError +pub type bitcoin_units::locktime::absolute::Height::Error = bitcoin_units::locktime::absolute::error::ParseHeightError +pub type bitcoin_units::locktime::absolute::LockTime::Decoder = bitcoin_units::locktime::absolute::LockTimeDecoder +pub type bitcoin_units::locktime::absolute::LockTime::Encoder<'e> = bitcoin_units::locktime::absolute::LockTimeEncoder +pub type bitcoin_units::locktime::absolute::LockTime::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::absolute::LockTime::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::absolute::LockTimeDecoder::Error = bitcoin_units::locktime::absolute::error::LockTimeDecoderError +pub type bitcoin_units::locktime::absolute::LockTimeDecoder::Output = bitcoin_units::locktime::absolute::LockTime +pub type bitcoin_units::locktime::absolute::MedianTimePast::Err = bitcoin_units::locktime::absolute::error::ParseTimeError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Error = bitcoin_units::locktime::absolute::error::ConversionError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Error = bitcoin_units::locktime::absolute::error::ParseTimeError +pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError +pub type bitcoin_units::locktime::relative::NumberOf512Seconds::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOf512Seconds::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Error = bitcoin_units::block::TooBigForRelativeHeightError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::sequence::Sequence::Decoder = bitcoin_units::sequence::SequenceDecoder +pub type bitcoin_units::sequence::Sequence::Encoder<'e> = bitcoin_units::sequence::SequenceEncoder +pub type bitcoin_units::sequence::Sequence::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::sequence::Sequence::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::sequence::SequenceDecoder::Error = bitcoin_units::sequence::SequenceDecoderError +pub type bitcoin_units::sequence::SequenceDecoder::Output = bitcoin_units::sequence::Sequence +pub type bitcoin_units::time::BlockTimeDecoder::Error = bitcoin_units::time::BlockTimeDecoderError +pub type bitcoin_units::time::BlockTimeDecoder::Output = bitcoin_units::BlockTime +pub type i64::Output = >::Output +pub type i64::Output = >>::Output +pub type i64::Output = bitcoin_units::result::NumOpResult +pub type u64::Output = >::Output +pub type u64::Output = >::Output +pub type u64::Output = >>::Output +pub type u64::Output = bitcoin_units::Weight +pub type u64::Output = bitcoin_units::result::NumOpResult diff --git a/api/units/alloc-only.txt b/api/units/alloc-only.txt new file mode 100644 index 000000000..eeb4cec3b --- /dev/null +++ b/api/units/alloc-only.txt @@ -0,0 +1,2423 @@ +#[non_exhaustive] pub enum bitcoin_units::amount::Denomination +#[non_exhaustive] pub enum bitcoin_units::amount::ParseDenominationError +#[non_exhaustive] pub enum bitcoin_units::amount::error::ParseDenominationError +#[non_exhaustive] pub enum bitcoin_units::result::MathOp +#[non_exhaustive] pub struct bitcoin_units::absolute::ConversionError +#[non_exhaustive] pub struct bitcoin_units::absolute::error::ConversionError +#[non_exhaustive] pub struct bitcoin_units::amount::error::MissingDenominationError +#[non_exhaustive] pub struct bitcoin_units::amount::error::PossiblyConfusingDenominationError(_) +#[non_exhaustive] pub struct bitcoin_units::amount::error::UnknownDenominationError(_) +#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::ConversionError +#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::error::ConversionError +#[non_exhaustive] pub struct bitcoin_units::parse_int::ParseIntError +#[non_exhaustive] pub struct bitcoin_units::result::NumOpError(_) +impl bitcoin_units::Amount +impl bitcoin_units::BlockTime +impl bitcoin_units::FeeRate +impl bitcoin_units::SignedAmount +impl bitcoin_units::Weight +impl bitcoin_units::amount::Denomination +impl bitcoin_units::amount::Display +impl bitcoin_units::amount::error::OutOfRangeError +impl bitcoin_units::block::BlockHeight +impl bitcoin_units::block::BlockHeightInterval +impl bitcoin_units::block::BlockMtp +impl bitcoin_units::block::BlockMtpInterval +impl bitcoin_units::locktime::absolute::Height +impl bitcoin_units::locktime::absolute::LockTime +impl bitcoin_units::locktime::absolute::MedianTimePast +impl bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl bitcoin_units::locktime::relative::LockTime +impl bitcoin_units::locktime::relative::NumberOf512Seconds +impl bitcoin_units::locktime::relative::NumberOfBlocks +impl bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl bitcoin_units::parse_int::Integer for i128 +impl bitcoin_units::parse_int::Integer for i16 +impl bitcoin_units::parse_int::Integer for i32 +impl bitcoin_units::parse_int::Integer for i64 +impl bitcoin_units::parse_int::Integer for i8 +impl bitcoin_units::parse_int::Integer for u128 +impl bitcoin_units::parse_int::Integer for u16 +impl bitcoin_units::parse_int::Integer for u32 +impl bitcoin_units::parse_int::Integer for u64 +impl bitcoin_units::parse_int::Integer for u8 +impl bitcoin_units::result::MathOp +impl bitcoin_units::result::NumOpError +impl bitcoin_units::sequence::Sequence +impl core::clone::Clone for bitcoin_units::Amount +impl core::clone::Clone for bitcoin_units::BlockTime +impl core::clone::Clone for bitcoin_units::FeeRate +impl core::clone::Clone for bitcoin_units::SignedAmount +impl core::clone::Clone for bitcoin_units::Weight +impl core::clone::Clone for bitcoin_units::amount::Denomination +impl core::clone::Clone for bitcoin_units::amount::Display +impl core::clone::Clone for bitcoin_units::amount::error::BadPositionError +impl core::clone::Clone for bitcoin_units::amount::error::InputTooLargeError +impl core::clone::Clone for bitcoin_units::amount::error::InvalidCharacterError +impl core::clone::Clone for bitcoin_units::amount::error::MissingDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::MissingDigitsError +impl core::clone::Clone for bitcoin_units::amount::error::OutOfRangeError +impl core::clone::Clone for bitcoin_units::amount::error::ParseAmountError +impl core::clone::Clone for bitcoin_units::amount::error::ParseDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::ParseError +impl core::clone::Clone for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::TooPreciseError +impl core::clone::Clone for bitcoin_units::amount::error::UnknownDenominationError +impl core::clone::Clone for bitcoin_units::block::BlockHeight +impl core::clone::Clone for bitcoin_units::block::BlockHeightInterval +impl core::clone::Clone for bitcoin_units::block::BlockMtp +impl core::clone::Clone for bitcoin_units::block::BlockMtpInterval +impl core::clone::Clone for bitcoin_units::block::TooBigForRelativeHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::Height +impl core::clone::Clone for bitcoin_units::locktime::absolute::LockTime +impl core::clone::Clone for bitcoin_units::locktime::absolute::MedianTimePast +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ConversionError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::LockTime +impl core::clone::Clone for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::clone::Clone for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::clone::Clone for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::clone::Clone for bitcoin_units::parse_int::ParseIntError +impl core::clone::Clone for bitcoin_units::parse_int::PrefixedHexError +impl core::clone::Clone for bitcoin_units::parse_int::UnprefixedHexError +impl core::clone::Clone for bitcoin_units::result::MathOp +impl core::clone::Clone for bitcoin_units::result::NumOpError +impl core::clone::Clone for bitcoin_units::sequence::Sequence +impl core::cmp::Eq for bitcoin_units::Amount +impl core::cmp::Eq for bitcoin_units::BlockTime +impl core::cmp::Eq for bitcoin_units::FeeRate +impl core::cmp::Eq for bitcoin_units::SignedAmount +impl core::cmp::Eq for bitcoin_units::Weight +impl core::cmp::Eq for bitcoin_units::amount::Denomination +impl core::cmp::Eq for bitcoin_units::amount::error::BadPositionError +impl core::cmp::Eq for bitcoin_units::amount::error::InputTooLargeError +impl core::cmp::Eq for bitcoin_units::amount::error::InvalidCharacterError +impl core::cmp::Eq for bitcoin_units::amount::error::MissingDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::MissingDigitsError +impl core::cmp::Eq for bitcoin_units::amount::error::OutOfRangeError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseAmountError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseError +impl core::cmp::Eq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::TooPreciseError +impl core::cmp::Eq for bitcoin_units::amount::error::UnknownDenominationError +impl core::cmp::Eq for bitcoin_units::block::BlockHeight +impl core::cmp::Eq for bitcoin_units::block::BlockHeightInterval +impl core::cmp::Eq for bitcoin_units::block::BlockMtp +impl core::cmp::Eq for bitcoin_units::block::BlockMtpInterval +impl core::cmp::Eq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::Height +impl core::cmp::Eq for bitcoin_units::locktime::absolute::LockTime +impl core::cmp::Eq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::LockTime +impl core::cmp::Eq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::Eq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::cmp::Eq for bitcoin_units::parse_int::ParseIntError +impl core::cmp::Eq for bitcoin_units::parse_int::PrefixedHexError +impl core::cmp::Eq for bitcoin_units::parse_int::UnprefixedHexError +impl core::cmp::Eq for bitcoin_units::result::MathOp +impl core::cmp::Eq for bitcoin_units::result::NumOpError +impl core::cmp::Eq for bitcoin_units::sequence::Sequence +impl core::cmp::Ord for bitcoin_units::Amount +impl core::cmp::Ord for bitcoin_units::BlockTime +impl core::cmp::Ord for bitcoin_units::FeeRate +impl core::cmp::Ord for bitcoin_units::SignedAmount +impl core::cmp::Ord for bitcoin_units::Weight +impl core::cmp::Ord for bitcoin_units::block::BlockHeight +impl core::cmp::Ord for bitcoin_units::block::BlockHeightInterval +impl core::cmp::Ord for bitcoin_units::block::BlockMtp +impl core::cmp::Ord for bitcoin_units::block::BlockMtpInterval +impl core::cmp::Ord for bitcoin_units::locktime::absolute::Height +impl core::cmp::Ord for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::Ord for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::Ord for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::Ord for bitcoin_units::sequence::Sequence +impl core::cmp::PartialEq for bitcoin_units::Amount +impl core::cmp::PartialEq for bitcoin_units::BlockTime +impl core::cmp::PartialEq for bitcoin_units::FeeRate +impl core::cmp::PartialEq for bitcoin_units::SignedAmount +impl core::cmp::PartialEq for bitcoin_units::Weight +impl core::cmp::PartialEq for bitcoin_units::amount::Denomination +impl core::cmp::PartialEq for bitcoin_units::amount::error::BadPositionError +impl core::cmp::PartialEq for bitcoin_units::amount::error::InputTooLargeError +impl core::cmp::PartialEq for bitcoin_units::amount::error::InvalidCharacterError +impl core::cmp::PartialEq for bitcoin_units::amount::error::MissingDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::MissingDigitsError +impl core::cmp::PartialEq for bitcoin_units::amount::error::OutOfRangeError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseAmountError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseError +impl core::cmp::PartialEq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::TooPreciseError +impl core::cmp::PartialEq for bitcoin_units::amount::error::UnknownDenominationError +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeight +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeightInterval +impl core::cmp::PartialEq for bitcoin_units::block::BlockMtp +impl core::cmp::PartialEq for bitcoin_units::block::BlockMtpInterval +impl core::cmp::PartialEq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::Height +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::LockTime +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::LockTime +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::cmp::PartialEq for bitcoin_units::parse_int::ParseIntError +impl core::cmp::PartialEq for bitcoin_units::parse_int::PrefixedHexError +impl core::cmp::PartialEq for bitcoin_units::parse_int::UnprefixedHexError +impl core::cmp::PartialEq for bitcoin_units::result::MathOp +impl core::cmp::PartialEq for bitcoin_units::result::NumOpError +impl core::cmp::PartialEq for bitcoin_units::sequence::Sequence +impl core::cmp::PartialOrd for bitcoin_units::Amount +impl core::cmp::PartialOrd for bitcoin_units::BlockTime +impl core::cmp::PartialOrd for bitcoin_units::FeeRate +impl core::cmp::PartialOrd for bitcoin_units::SignedAmount +impl core::cmp::PartialOrd for bitcoin_units::Weight +impl core::cmp::PartialOrd for bitcoin_units::block::BlockHeight +impl core::cmp::PartialOrd for bitcoin_units::block::BlockHeightInterval +impl core::cmp::PartialOrd for bitcoin_units::block::BlockMtp +impl core::cmp::PartialOrd for bitcoin_units::block::BlockMtpInterval +impl core::cmp::PartialOrd for bitcoin_units::locktime::absolute::Height +impl core::cmp::PartialOrd for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::PartialOrd for bitcoin_units::sequence::Sequence +impl core::convert::AsRef for bitcoin_units::parse_int::ParseIntError +impl core::convert::From<&bitcoin_units::Amount> for bitcoin_units::result::NumOpResult +impl core::convert::From<&bitcoin_units::SignedAmount> for bitcoin_units::result::NumOpResult +impl core::convert::From for bitcoin_units::SignedAmount +impl core::convert::From for bitcoin_units::result::NumOpResult +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::result::NumOpResult +impl core::convert::From for u64 +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::block::BlockHeight +impl core::convert::From for bitcoin_units::locktime::absolute::LockTime +impl core::convert::From for bitcoin_units::block::BlockMtp +impl core::convert::From for bitcoin_units::locktime::absolute::LockTime +impl core::convert::From for bitcoin_units::sequence::Sequence +impl core::convert::From for bitcoin_units::block::BlockMtpInterval +impl core::convert::From for bitcoin_units::locktime::relative::LockTime +impl core::convert::From for bitcoin_units::block::BlockHeightInterval +impl core::convert::From for bitcoin_units::locktime::relative::LockTime +impl core::convert::From for bitcoin_units::parse_int::PrefixedHexError +impl core::convert::From for bitcoin_units::parse_int::UnprefixedHexError +impl core::convert::From for core::num::error::ParseIntError +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseDenominationError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::parse_int::PrefixedHexError +impl core::convert::From for bitcoin_units::parse_int::UnprefixedHexError +impl core::convert::From for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::From for bitcoin_units::BlockTime +impl core::convert::From for bitcoin_units::block::BlockHeight +impl core::convert::From for bitcoin_units::block::BlockHeightInterval +impl core::convert::From for bitcoin_units::block::BlockMtp +impl core::convert::From for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom<&str> for bitcoin_units::Weight +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom<&str> for bitcoin_units::sequence::Sequence +impl core::convert::TryFrom> for bitcoin_units::Weight +impl core::convert::TryFrom> for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom> for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom> for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom> for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom> for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom> for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom> for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom> for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom> for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom> for bitcoin_units::sequence::Sequence +impl core::convert::TryFrom for bitcoin_units::Weight +impl core::convert::TryFrom for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom for bitcoin_units::sequence::Sequence +impl core::convert::TryFrom for bitcoin_units::Amount +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom for bitcoin_units::locktime::relative::LockTime +impl core::default::Default for bitcoin_units::Amount +impl core::default::Default for bitcoin_units::SignedAmount +impl core::default::Default for bitcoin_units::block::BlockHeightInterval +impl core::default::Default for bitcoin_units::block::BlockMtpInterval +impl core::default::Default for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::default::Default for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::default::Default for bitcoin_units::sequence::Sequence +impl core::fmt::Debug for bitcoin_units::Amount +impl core::fmt::Debug for bitcoin_units::BlockTime +impl core::fmt::Debug for bitcoin_units::FeeRate +impl core::fmt::Debug for bitcoin_units::SignedAmount +impl core::fmt::Debug for bitcoin_units::Weight +impl core::fmt::Debug for bitcoin_units::amount::Denomination +impl core::fmt::Debug for bitcoin_units::amount::Display +impl core::fmt::Debug for bitcoin_units::amount::error::BadPositionError +impl core::fmt::Debug for bitcoin_units::amount::error::InputTooLargeError +impl core::fmt::Debug for bitcoin_units::amount::error::InvalidCharacterError +impl core::fmt::Debug for bitcoin_units::amount::error::MissingDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::MissingDigitsError +impl core::fmt::Debug for bitcoin_units::amount::error::OutOfRangeError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseAmountError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseError +impl core::fmt::Debug for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::TooPreciseError +impl core::fmt::Debug for bitcoin_units::amount::error::UnknownDenominationError +impl core::fmt::Debug for bitcoin_units::block::BlockHeight +impl core::fmt::Debug for bitcoin_units::block::BlockHeightInterval +impl core::fmt::Debug for bitcoin_units::block::BlockMtp +impl core::fmt::Debug for bitcoin_units::block::BlockMtpInterval +impl core::fmt::Debug for bitcoin_units::block::TooBigForRelativeHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::Height +impl core::fmt::Debug for bitcoin_units::locktime::absolute::LockTime +impl core::fmt::Debug for bitcoin_units::locktime::absolute::MedianTimePast +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ConversionError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::LockTime +impl core::fmt::Debug for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::fmt::Debug for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::fmt::Debug for bitcoin_units::parse_int::ParseIntError +impl core::fmt::Debug for bitcoin_units::parse_int::PrefixedHexError +impl core::fmt::Debug for bitcoin_units::parse_int::UnprefixedHexError +impl core::fmt::Debug for bitcoin_units::result::MathOp +impl core::fmt::Debug for bitcoin_units::result::NumOpError +impl core::fmt::Debug for bitcoin_units::sequence::Sequence +impl core::fmt::Display for bitcoin_units::Amount +impl core::fmt::Display for bitcoin_units::SignedAmount +impl core::fmt::Display for bitcoin_units::Weight +impl core::fmt::Display for bitcoin_units::amount::Denomination +impl core::fmt::Display for bitcoin_units::amount::Display +impl core::fmt::Display for bitcoin_units::amount::error::BadPositionError +impl core::fmt::Display for bitcoin_units::amount::error::InputTooLargeError +impl core::fmt::Display for bitcoin_units::amount::error::InvalidCharacterError +impl core::fmt::Display for bitcoin_units::amount::error::MissingDigitsError +impl core::fmt::Display for bitcoin_units::amount::error::OutOfRangeError +impl core::fmt::Display for bitcoin_units::amount::error::ParseAmountError +impl core::fmt::Display for bitcoin_units::amount::error::ParseDenominationError +impl core::fmt::Display for bitcoin_units::amount::error::ParseError +impl core::fmt::Display for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::fmt::Display for bitcoin_units::amount::error::TooPreciseError +impl core::fmt::Display for bitcoin_units::amount::error::UnknownDenominationError +impl core::fmt::Display for bitcoin_units::block::BlockHeight +impl core::fmt::Display for bitcoin_units::block::BlockHeightInterval +impl core::fmt::Display for bitcoin_units::block::BlockMtp +impl core::fmt::Display for bitcoin_units::block::BlockMtpInterval +impl core::fmt::Display for bitcoin_units::block::TooBigForRelativeHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::Height +impl core::fmt::Display for bitcoin_units::locktime::absolute::LockTime +impl core::fmt::Display for bitcoin_units::locktime::absolute::MedianTimePast +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ConversionError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::LockTime +impl core::fmt::Display for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::fmt::Display for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::fmt::Display for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::fmt::Display for bitcoin_units::parse_int::ParseIntError +impl core::fmt::Display for bitcoin_units::parse_int::PrefixedHexError +impl core::fmt::Display for bitcoin_units::parse_int::UnprefixedHexError +impl core::fmt::Display for bitcoin_units::result::MathOp +impl core::fmt::Display for bitcoin_units::result::NumOpError +impl core::fmt::Display for bitcoin_units::sequence::Sequence +impl core::fmt::LowerHex for bitcoin_units::sequence::Sequence +impl core::fmt::UpperHex for bitcoin_units::sequence::Sequence +impl core::hash::Hash for bitcoin_units::Amount +impl core::hash::Hash for bitcoin_units::BlockTime +impl core::hash::Hash for bitcoin_units::FeeRate +impl core::hash::Hash for bitcoin_units::SignedAmount +impl core::hash::Hash for bitcoin_units::Weight +impl core::hash::Hash for bitcoin_units::amount::Denomination +impl core::hash::Hash for bitcoin_units::block::BlockHeight +impl core::hash::Hash for bitcoin_units::block::BlockHeightInterval +impl core::hash::Hash for bitcoin_units::block::BlockMtp +impl core::hash::Hash for bitcoin_units::block::BlockMtpInterval +impl core::hash::Hash for bitcoin_units::locktime::absolute::Height +impl core::hash::Hash for bitcoin_units::locktime::absolute::LockTime +impl core::hash::Hash for bitcoin_units::locktime::absolute::MedianTimePast +impl core::hash::Hash for bitcoin_units::locktime::relative::LockTime +impl core::hash::Hash for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::hash::Hash for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::hash::Hash for bitcoin_units::sequence::Sequence +impl core::iter::traits::accum::Sum for bitcoin_units::FeeRate +impl core::iter::traits::accum::Sum for bitcoin_units::Weight +impl core::iter::traits::accum::Sum for bitcoin_units::block::BlockHeightInterval +impl core::iter::traits::accum::Sum for bitcoin_units::block::BlockMtpInterval +impl core::iter::traits::accum::Sum for bitcoin_units::result::NumOpResult +impl core::iter::traits::accum::Sum for bitcoin_units::result::NumOpResult +impl core::marker::Copy for bitcoin_units::Amount +impl core::marker::Copy for bitcoin_units::BlockTime +impl core::marker::Copy for bitcoin_units::FeeRate +impl core::marker::Copy for bitcoin_units::SignedAmount +impl core::marker::Copy for bitcoin_units::Weight +impl core::marker::Copy for bitcoin_units::amount::Denomination +impl core::marker::Copy for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Copy for bitcoin_units::block::BlockHeight +impl core::marker::Copy for bitcoin_units::block::BlockHeightInterval +impl core::marker::Copy for bitcoin_units::block::BlockMtp +impl core::marker::Copy for bitcoin_units::block::BlockMtpInterval +impl core::marker::Copy for bitcoin_units::locktime::absolute::Height +impl core::marker::Copy for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Copy for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Copy for bitcoin_units::locktime::relative::LockTime +impl core::marker::Copy for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Copy for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Copy for bitcoin_units::result::MathOp +impl core::marker::Copy for bitcoin_units::result::NumOpError +impl core::marker::Copy for bitcoin_units::sequence::Sequence +impl core::marker::Freeze for bitcoin_units::Amount +impl core::marker::Freeze for bitcoin_units::BlockTime +impl core::marker::Freeze for bitcoin_units::FeeRate +impl core::marker::Freeze for bitcoin_units::SignedAmount +impl core::marker::Freeze for bitcoin_units::Weight +impl core::marker::Freeze for bitcoin_units::amount::Denomination +impl core::marker::Freeze for bitcoin_units::amount::Display +impl core::marker::Freeze for bitcoin_units::amount::error::BadPositionError +impl core::marker::Freeze for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Freeze for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Freeze for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Freeze for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseError +impl core::marker::Freeze for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Freeze for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Freeze for bitcoin_units::block::BlockHeight +impl core::marker::Freeze for bitcoin_units::block::BlockHeightInterval +impl core::marker::Freeze for bitcoin_units::block::BlockMtp +impl core::marker::Freeze for bitcoin_units::block::BlockMtpInterval +impl core::marker::Freeze for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::Height +impl core::marker::Freeze for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Freeze for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::LockTime +impl core::marker::Freeze for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Freeze for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Freeze for bitcoin_units::parse_int::ParseIntError +impl core::marker::Freeze for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Freeze for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Freeze for bitcoin_units::result::MathOp +impl core::marker::Freeze for bitcoin_units::result::NumOpError +impl core::marker::Freeze for bitcoin_units::sequence::Sequence +impl core::marker::Send for bitcoin_units::Amount +impl core::marker::Send for bitcoin_units::BlockTime +impl core::marker::Send for bitcoin_units::FeeRate +impl core::marker::Send for bitcoin_units::SignedAmount +impl core::marker::Send for bitcoin_units::Weight +impl core::marker::Send for bitcoin_units::amount::Denomination +impl core::marker::Send for bitcoin_units::amount::Display +impl core::marker::Send for bitcoin_units::amount::error::BadPositionError +impl core::marker::Send for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Send for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Send for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Send for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Send for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Send for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Send for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Send for bitcoin_units::amount::error::ParseError +impl core::marker::Send for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Send for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Send for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Send for bitcoin_units::block::BlockHeight +impl core::marker::Send for bitcoin_units::block::BlockHeightInterval +impl core::marker::Send for bitcoin_units::block::BlockMtp +impl core::marker::Send for bitcoin_units::block::BlockMtpInterval +impl core::marker::Send for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::Height +impl core::marker::Send for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Send for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::LockTime +impl core::marker::Send for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Send for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Send for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Send for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Send for bitcoin_units::parse_int::ParseIntError +impl core::marker::Send for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Send for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Send for bitcoin_units::result::MathOp +impl core::marker::Send for bitcoin_units::result::NumOpError +impl core::marker::Send for bitcoin_units::sequence::Sequence +impl core::marker::StructuralPartialEq for bitcoin_units::Amount +impl core::marker::StructuralPartialEq for bitcoin_units::BlockTime +impl core::marker::StructuralPartialEq for bitcoin_units::FeeRate +impl core::marker::StructuralPartialEq for bitcoin_units::SignedAmount +impl core::marker::StructuralPartialEq for bitcoin_units::Weight +impl core::marker::StructuralPartialEq for bitcoin_units::amount::Denomination +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::BadPositionError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseAmountError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::TooPreciseError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeight +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeightInterval +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockMtp +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockMtpInterval +impl core::marker::StructuralPartialEq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::Height +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::LockTime +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::LockTime +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::ParseIntError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::StructuralPartialEq for bitcoin_units::result::MathOp +impl core::marker::StructuralPartialEq for bitcoin_units::result::NumOpError +impl core::marker::StructuralPartialEq for bitcoin_units::sequence::Sequence +impl core::marker::Sync for bitcoin_units::Amount +impl core::marker::Sync for bitcoin_units::BlockTime +impl core::marker::Sync for bitcoin_units::FeeRate +impl core::marker::Sync for bitcoin_units::SignedAmount +impl core::marker::Sync for bitcoin_units::Weight +impl core::marker::Sync for bitcoin_units::amount::Denomination +impl core::marker::Sync for bitcoin_units::amount::Display +impl core::marker::Sync for bitcoin_units::amount::error::BadPositionError +impl core::marker::Sync for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Sync for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Sync for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Sync for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Sync for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Sync for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::ParseError +impl core::marker::Sync for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Sync for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Sync for bitcoin_units::block::BlockHeight +impl core::marker::Sync for bitcoin_units::block::BlockHeightInterval +impl core::marker::Sync for bitcoin_units::block::BlockMtp +impl core::marker::Sync for bitcoin_units::block::BlockMtpInterval +impl core::marker::Sync for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::Height +impl core::marker::Sync for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Sync for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::LockTime +impl core::marker::Sync for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Sync for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Sync for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Sync for bitcoin_units::parse_int::ParseIntError +impl core::marker::Sync for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Sync for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Sync for bitcoin_units::result::MathOp +impl core::marker::Sync for bitcoin_units::result::NumOpError +impl core::marker::Sync for bitcoin_units::sequence::Sequence +impl core::marker::Unpin for bitcoin_units::Amount +impl core::marker::Unpin for bitcoin_units::BlockTime +impl core::marker::Unpin for bitcoin_units::FeeRate +impl core::marker::Unpin for bitcoin_units::SignedAmount +impl core::marker::Unpin for bitcoin_units::Weight +impl core::marker::Unpin for bitcoin_units::amount::Denomination +impl core::marker::Unpin for bitcoin_units::amount::Display +impl core::marker::Unpin for bitcoin_units::amount::error::BadPositionError +impl core::marker::Unpin for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Unpin for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Unpin for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Unpin for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseError +impl core::marker::Unpin for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Unpin for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Unpin for bitcoin_units::block::BlockHeight +impl core::marker::Unpin for bitcoin_units::block::BlockHeightInterval +impl core::marker::Unpin for bitcoin_units::block::BlockMtp +impl core::marker::Unpin for bitcoin_units::block::BlockMtpInterval +impl core::marker::Unpin for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::Height +impl core::marker::Unpin for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Unpin for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::LockTime +impl core::marker::Unpin for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Unpin for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Unpin for bitcoin_units::parse_int::ParseIntError +impl core::marker::Unpin for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Unpin for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Unpin for bitcoin_units::result::MathOp +impl core::marker::Unpin for bitcoin_units::result::NumOpError +impl core::marker::Unpin for bitcoin_units::sequence::Sequence +impl core::ops::arith::Add for bitcoin_units::Amount +impl core::ops::arith::Add for bitcoin_units::FeeRate +impl core::ops::arith::Add for bitcoin_units::SignedAmount +impl core::ops::arith::Add for bitcoin_units::Weight +impl core::ops::arith::Add for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Add<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::Add<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Add<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Add<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Add<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Add<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::SignedAmount +impl core::ops::arith::Add for &bitcoin_units::Amount +impl core::ops::arith::Add for &bitcoin_units::FeeRate +impl core::ops::arith::Add for &bitcoin_units::SignedAmount +impl core::ops::arith::Add for &bitcoin_units::Weight +impl core::ops::arith::Add for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Add for &bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockHeight +impl core::ops::arith::Add for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Add for &bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockMtp +impl core::ops::arith::Add> for &bitcoin_units::Amount +impl core::ops::arith::Add> for bitcoin_units::Amount +impl core::ops::arith::Add> for &bitcoin_units::SignedAmount +impl core::ops::arith::Add> for bitcoin_units::SignedAmount +impl core::ops::arith::AddAssign for bitcoin_units::FeeRate +impl core::ops::arith::AddAssign for bitcoin_units::Weight +impl core::ops::arith::AddAssign for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::AddAssign for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::AddAssign<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::AddAssign<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::AddAssign<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::SignedAmount +impl core::ops::arith::Div for bitcoin_units::Weight +impl core::ops::arith::Div<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::FeeRate> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::FeeRate> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::Amount +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::FeeRate +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::Weight +impl core::ops::arith::Div<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&u64> for bitcoin_units::Amount +impl core::ops::arith::Div<&u64> for bitcoin_units::Weight +impl core::ops::arith::Div<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::SignedAmount +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::SignedAmount +impl core::ops::arith::Div> for bitcoin_units::SignedAmount +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::FeeRate +impl core::ops::arith::Div> for &bitcoin_units::Weight +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::FeeRate +impl core::ops::arith::Div> for bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::SignedAmount +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::SignedAmount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::Weight +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign for bitcoin_units::Weight +impl core::ops::arith::DivAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::Amount> for u64 +impl core::ops::arith::Mul<&bitcoin_units::FeeRate> for bitcoin_units::Weight +impl core::ops::arith::Mul<&bitcoin_units::FeeRate> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::SignedAmount> for i64 +impl core::ops::arith::Mul<&bitcoin_units::Weight> for bitcoin_units::FeeRate +impl core::ops::arith::Mul<&bitcoin_units::Weight> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::Weight> for u64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for u64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::Weight +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for i64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::FeeRate +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Mul<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&u64> for bitcoin_units::Amount +impl core::ops::arith::Mul<&u64> for bitcoin_units::Weight +impl core::ops::arith::Mul<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &u64 +impl core::ops::arith::Mul for u64 +impl core::ops::arith::Mul for &bitcoin_units::Weight +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::Weight +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &i64 +impl core::ops::arith::Mul for i64 +impl core::ops::arith::Mul for &bitcoin_units::FeeRate +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &u64 +impl core::ops::arith::Mul for bitcoin_units::FeeRate +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for u64 +impl core::ops::arith::Mul> for &u64 +impl core::ops::arith::Mul> for u64 +impl core::ops::arith::Mul> for &bitcoin_units::Weight +impl core::ops::arith::Mul> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for bitcoin_units::Weight +impl core::ops::arith::Mul> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for &i64 +impl core::ops::arith::Mul> for i64 +impl core::ops::arith::Mul> for &bitcoin_units::FeeRate +impl core::ops::arith::Mul> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for bitcoin_units::FeeRate +impl core::ops::arith::Mul> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &bitcoin_units::SignedAmount +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::SignedAmount +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &bitcoin_units::Amount +impl core::ops::arith::Mul for &bitcoin_units::Weight +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::Amount +impl core::ops::arith::Mul for bitcoin_units::Weight +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign for bitcoin_units::Weight +impl core::ops::arith::MulAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Neg for bitcoin_units::SignedAmount +impl core::ops::arith::Rem for bitcoin_units::Weight +impl core::ops::arith::Rem<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Rem<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Rem<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem<&u64> for bitcoin_units::Amount +impl core::ops::arith::Rem<&u64> for bitcoin_units::Weight +impl core::ops::arith::Rem<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for &bitcoin_units::Weight +impl core::ops::arith::Rem for &bitcoin_units::SignedAmount +impl core::ops::arith::Rem for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for bitcoin_units::SignedAmount +impl core::ops::arith::Rem for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for &bitcoin_units::Amount +impl core::ops::arith::Rem for &bitcoin_units::Weight +impl core::ops::arith::Rem for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for bitcoin_units::Amount +impl core::ops::arith::Rem for bitcoin_units::Weight +impl core::ops::arith::Rem for bitcoin_units::result::NumOpResult +impl core::ops::arith::RemAssign for bitcoin_units::Weight +impl core::ops::arith::Sub for bitcoin_units::Amount +impl core::ops::arith::Sub for bitcoin_units::FeeRate +impl core::ops::arith::Sub for bitcoin_units::SignedAmount +impl core::ops::arith::Sub for bitcoin_units::Weight +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Sub<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::Sub<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Sub<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeight> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtp> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::SignedAmount +impl core::ops::arith::Sub for &bitcoin_units::Amount +impl core::ops::arith::Sub for &bitcoin_units::FeeRate +impl core::ops::arith::Sub for &bitcoin_units::SignedAmount +impl core::ops::arith::Sub for &bitcoin_units::Weight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub> for &bitcoin_units::Amount +impl core::ops::arith::Sub> for bitcoin_units::Amount +impl core::ops::arith::Sub> for &bitcoin_units::SignedAmount +impl core::ops::arith::Sub> for bitcoin_units::SignedAmount +impl core::ops::arith::SubAssign for bitcoin_units::FeeRate +impl core::ops::arith::SubAssign for bitcoin_units::Weight +impl core::ops::arith::SubAssign for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::SubAssign for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::SubAssign<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::SubAssign<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::SubAssign<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::Amount +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::BlockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::FeeRate +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::SignedAmount +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::Weight +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::Denomination +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::Display +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::BadPositionError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::InputTooLargeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::InvalidCharacterError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::MissingDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::MissingDigitsError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::OutOfRangeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseAmountError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::TooPreciseError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::UnknownDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeight +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeightInterval +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockMtp +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockMtpInterval +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::TooBigForRelativeHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::Height +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::LockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::MedianTimePast +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ConversionError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::LockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::ParseIntError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::PrefixedHexError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::UnprefixedHexError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::MathOp +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::NumOpError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::sequence::Sequence +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::Amount +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::BlockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::FeeRate +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::SignedAmount +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::Weight +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::Denomination +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::Display +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::BadPositionError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::InputTooLargeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::InvalidCharacterError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::MissingDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::MissingDigitsError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::OutOfRangeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseAmountError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::TooPreciseError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::UnknownDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeight +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeightInterval +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockMtp +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockMtpInterval +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::TooBigForRelativeHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::Height +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::LockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::MedianTimePast +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ConversionError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::LockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::ParseIntError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::PrefixedHexError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::UnprefixedHexError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::MathOp +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::NumOpError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::sequence::Sequence +impl core::str::traits::FromStr for bitcoin_units::Amount +impl core::str::traits::FromStr for bitcoin_units::SignedAmount +impl core::str::traits::FromStr for bitcoin_units::Weight +impl core::str::traits::FromStr for bitcoin_units::amount::Denomination +impl core::str::traits::FromStr for bitcoin_units::block::BlockHeight +impl core::str::traits::FromStr for bitcoin_units::block::BlockHeightInterval +impl core::str::traits::FromStr for bitcoin_units::block::BlockMtp +impl core::str::traits::FromStr for bitcoin_units::block::BlockMtpInterval +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::Height +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::LockTime +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::MedianTimePast +impl core::str::traits::FromStr for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::str::traits::FromStr for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::str::traits::FromStr for bitcoin_units::sequence::Sequence +impl<'a, T> core::ops::arith::Add<&'a T> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl<'a, T> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl<'a, T> core::ops::arith::Sub<&'a T> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl<'a, T> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::Weight> for bitcoin_units::Weight +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Add<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::FeeRate> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Add<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeightInterval +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtpInterval +impl<'a> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::FeeRate> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::FeeRate> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Amount> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::FeeRate> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::FeeRate> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::SignedAmount> for &i64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &i64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Mul<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Rem<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Rem<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Rem<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::FeeRate> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeight> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeightInterval +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtp> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtpInterval +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::SignedAmount +impl core::clone::Clone for bitcoin_units::result::NumOpResult +impl core::cmp::Eq for bitcoin_units::result::NumOpResult +impl core::cmp::PartialEq for bitcoin_units::result::NumOpResult +impl bitcoin_units::result::NumOpResult +impl core::fmt::Debug for bitcoin_units::result::NumOpResult +impl core::marker::Copy for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl bitcoin_units::result::NumOpResult +impl core::marker::Freeze for bitcoin_units::result::NumOpResult where T: core::marker::Freeze +impl core::marker::Send for bitcoin_units::result::NumOpResult where T: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_units::result::NumOpResult +impl core::marker::Sync for bitcoin_units::result::NumOpResult where T: core::marker::Sync +impl core::marker::Unpin for bitcoin_units::result::NumOpResult where T: core::marker::Unpin +impl core::ops::arith::Add for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Add<&T> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Add for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Sub for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub<&T> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::NumOpResult where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::NumOpResult where T: core::panic::unwind_safe::UnwindSafe +pub bitcoin_units::NumOpResult::Error(bitcoin_units::result::NumOpError) +pub bitcoin_units::NumOpResult::Valid(T) +pub bitcoin_units::absolute::LockTime::Blocks(bitcoin_units::locktime::absolute::Height) +pub bitcoin_units::absolute::LockTime::Seconds(bitcoin_units::locktime::absolute::MedianTimePast) +pub bitcoin_units::amount::Denomination::Bit +pub bitcoin_units::amount::Denomination::Bitcoin +pub bitcoin_units::amount::Denomination::CentiBitcoin +pub bitcoin_units::amount::Denomination::MicroBitcoin +pub bitcoin_units::amount::Denomination::MilliBitcoin +pub bitcoin_units::amount::Denomination::Satoshi +pub bitcoin_units::amount::ParseDenominationError::PossiblyConfusing(bitcoin_units::amount::error::PossiblyConfusingDenominationError) +pub bitcoin_units::amount::ParseDenominationError::Unknown(bitcoin_units::amount::error::UnknownDenominationError) +pub bitcoin_units::amount::error::ParseDenominationError::PossiblyConfusing(bitcoin_units::amount::error::PossiblyConfusingDenominationError) +pub bitcoin_units::amount::error::ParseDenominationError::Unknown(bitcoin_units::amount::error::UnknownDenominationError) +pub bitcoin_units::locktime::absolute::LockTime::Blocks(bitcoin_units::locktime::absolute::Height) +pub bitcoin_units::locktime::absolute::LockTime::Seconds(bitcoin_units::locktime::absolute::MedianTimePast) +pub bitcoin_units::locktime::relative::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::LockTime::Blocks(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::LockTime::Time(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::LockTime::Blocks(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::LockTime::Time(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::error::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::error::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::error::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::error::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::error::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::error::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::result::MathOp::Add +pub bitcoin_units::result::MathOp::Div +pub bitcoin_units::result::MathOp::Mul +pub bitcoin_units::result::MathOp::Neg +pub bitcoin_units::result::MathOp::Rem +pub bitcoin_units::result::MathOp::Sub +pub bitcoin_units::result::NumOpResult::Error(bitcoin_units::result::NumOpError) +pub bitcoin_units::result::NumOpResult::Valid(T) +pub const bitcoin_units::Amount::FIFTY_BTC: Self +pub const bitcoin_units::Amount::MAX: Self +pub const bitcoin_units::Amount::MAX_MONEY: Self +pub const bitcoin_units::Amount::MIN: Self +pub const bitcoin_units::Amount::ONE_BTC: Self +pub const bitcoin_units::Amount::ONE_SAT: Self +pub const bitcoin_units::Amount::SIZE: usize +pub const bitcoin_units::Amount::ZERO: Self +pub const bitcoin_units::FeeRate::BROADCAST_MIN: Self +pub const bitcoin_units::FeeRate::DUST: Self +pub const bitcoin_units::FeeRate::MAX: Self +pub const bitcoin_units::FeeRate::MIN: Self +pub const bitcoin_units::FeeRate::ZERO: Self +pub const bitcoin_units::SignedAmount::FIFTY_BTC: Self +pub const bitcoin_units::SignedAmount::MAX: Self +pub const bitcoin_units::SignedAmount::MAX_MONEY: Self +pub const bitcoin_units::SignedAmount::MIN: Self +pub const bitcoin_units::SignedAmount::ONE_BTC: Self +pub const bitcoin_units::SignedAmount::ONE_SAT: Self +pub const bitcoin_units::SignedAmount::ZERO: Self +pub const bitcoin_units::Weight::MAX: Self +pub const bitcoin_units::Weight::MAX_BLOCK: Self +pub const bitcoin_units::Weight::MIN: Self +pub const bitcoin_units::Weight::MIN_TRANSACTION: Self +pub const bitcoin_units::Weight::WITNESS_SCALE_FACTOR: u64 +pub const bitcoin_units::Weight::ZERO: Self +pub const bitcoin_units::absolute::LOCK_TIME_THRESHOLD: u32 +pub const bitcoin_units::amount::Denomination::BTC: Self +pub const bitcoin_units::amount::Denomination::SAT: Self +pub const bitcoin_units::block::BlockHeight::MAX: Self +pub const bitcoin_units::block::BlockHeight::MIN: Self +pub const bitcoin_units::block::BlockHeight::ZERO: Self +pub const bitcoin_units::block::BlockHeightInterval::MAX: Self +pub const bitcoin_units::block::BlockHeightInterval::MIN: Self +pub const bitcoin_units::block::BlockHeightInterval::ZERO: Self +pub const bitcoin_units::block::BlockMtp::MAX: Self +pub const bitcoin_units::block::BlockMtp::MIN: Self +pub const bitcoin_units::block::BlockMtp::ZERO: Self +pub const bitcoin_units::block::BlockMtpInterval::MAX: Self +pub const bitcoin_units::block::BlockMtpInterval::MIN: Self +pub const bitcoin_units::block::BlockMtpInterval::ZERO: Self +pub const bitcoin_units::locktime::absolute::Height::MAX: Self +pub const bitcoin_units::locktime::absolute::Height::MIN: Self +pub const bitcoin_units::locktime::absolute::Height::ZERO: Self +pub const bitcoin_units::locktime::absolute::LOCK_TIME_THRESHOLD: u32 +pub const bitcoin_units::locktime::absolute::LockTime::SIZE: usize +pub const bitcoin_units::locktime::absolute::LockTime::ZERO: Self +pub const bitcoin_units::locktime::absolute::MedianTimePast::MAX: Self +pub const bitcoin_units::locktime::absolute::MedianTimePast::MIN: Self +pub const bitcoin_units::locktime::relative::LockTime::SIZE: usize +pub const bitcoin_units::locktime::relative::LockTime::ZERO: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::MAX: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::MIN: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::ZERO: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::MAX: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::MIN: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::ZERO: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_LOCKTIME_AND_RBF: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_LOCKTIME_NO_RBF: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_RBF_NO_LOCKTIME: Self +pub const bitcoin_units::sequence::Sequence::FINAL: Self +pub const bitcoin_units::sequence::Sequence::MAX: Self +pub const bitcoin_units::sequence::Sequence::SIZE: usize +pub const bitcoin_units::sequence::Sequence::ZERO: Self +pub const bitcoin_units::weight::WITNESS_SCALE_FACTOR: usize +pub const fn bitcoin_units::Amount::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_rem(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Amount::div_by_fee_rate_ceil(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_fee_rate_floor(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_weight_ceil(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_weight_floor(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::from_btc_u16(whole_bitcoin: u16) -> Self +pub const fn bitcoin_units::Amount::from_sat(satoshi: u64) -> core::result::Result +pub const fn bitcoin_units::Amount::from_sat_u32(satoshi: u32) -> Self +pub const fn bitcoin_units::Amount::to_sat(self) -> u64 +pub const fn bitcoin_units::BlockTime::from_u32(t: u32) -> Self +pub const fn bitcoin_units::BlockTime::to_u32(self) -> u32 +pub const fn bitcoin_units::FeeRate::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::FeeRate::from_per_kvb(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_per_kwu(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_per_vb(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_sat_per_kvb(sat_kvb: u32) -> Self +pub const fn bitcoin_units::FeeRate::from_sat_per_kwu(sat_kwu: u32) -> Self +pub const fn bitcoin_units::FeeRate::from_sat_per_vb(sat_vb: u32) -> Self +pub const fn bitcoin_units::FeeRate::mul_by_weight(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::to_fee(self, weight: bitcoin_units::Weight) -> bitcoin_units::Amount +pub const fn bitcoin_units::FeeRate::to_sat_per_kvb_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kvb_floor(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kwu_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kwu_floor(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_vb_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_vb_floor(self) -> u64 +pub const fn bitcoin_units::SignedAmount::abs(self) -> Self +pub const fn bitcoin_units::SignedAmount::checked_abs(self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_div(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_mul(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_rem(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::from_btc_i16(whole_bitcoin: i16) -> Self +pub const fn bitcoin_units::SignedAmount::from_sat(satoshi: i64) -> core::result::Result +pub const fn bitcoin_units::SignedAmount::from_sat_i32(satoshi: i32) -> Self +pub const fn bitcoin_units::SignedAmount::to_sat(self) -> i64 +pub const fn bitcoin_units::Weight::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Weight::from_kwu(wu: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::from_non_witness_data_size(non_witness_size: u64) -> Self +pub const fn bitcoin_units::Weight::from_vb(vb: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::from_vb_unchecked(vb: u64) -> Self +pub const fn bitcoin_units::Weight::from_vb_unwrap(vb: u64) -> Self +pub const fn bitcoin_units::Weight::from_witness_data_size(witness_size: u64) -> Self +pub const fn bitcoin_units::Weight::from_wu(wu: u64) -> Self +pub const fn bitcoin_units::Weight::mul_by_fee_rate(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Weight::to_kwu_ceil(self) -> u64 +pub const fn bitcoin_units::Weight::to_kwu_floor(self) -> u64 +pub const fn bitcoin_units::Weight::to_vbytes_ceil(self) -> u64 +pub const fn bitcoin_units::Weight::to_vbytes_floor(self) -> u64 +pub const fn bitcoin_units::Weight::to_wu(self) -> u64 +pub const fn bitcoin_units::absolute::is_block_height(n: u32) -> bool +pub const fn bitcoin_units::absolute::is_block_time(n: u32) -> bool +pub const fn bitcoin_units::block::BlockHeight::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockHeight::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockHeightInterval::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockHeightInterval::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockMtp::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockMtp::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockMtpInterval::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockMtpInterval::to_relative_mtp_interval_ceil(self) -> core::result::Result +pub const fn bitcoin_units::block::BlockMtpInterval::to_relative_mtp_interval_floor(self) -> core::result::Result +pub const fn bitcoin_units::block::BlockMtpInterval::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::Height::from_u32(n: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::absolute::Height::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::LockTime::is_block_height(self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTime::is_block_time(self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTime::is_same_unit(self, other: Self) -> bool +pub const fn bitcoin_units::locktime::absolute::MedianTimePast::from_u32(n: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::absolute::MedianTimePast::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::is_block_height(n: u32) -> bool +pub const fn bitcoin_units::locktime::absolute::is_block_time(n: u32) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::from_512_second_intervals(intervals: u16) -> Self +pub const fn bitcoin_units::locktime::relative::LockTime::from_height(n: u16) -> Self +pub const fn bitcoin_units::locktime::relative::LockTime::from_seconds_ceil(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::LockTime::from_seconds_floor(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::LockTime::is_block_height(self) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::is_block_time(self) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::is_same_unit(self, other: Self) -> bool +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_512_second_intervals(intervals: u16) -> Self +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_seconds_ceil(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_seconds_floor(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_512_second_intervals(self) -> u16 +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_seconds(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::from_height(blocks: u16) -> Self +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::to_height(self) -> u16 +pub const fn bitcoin_units::sequence::Sequence::to_consensus_u32(self) -> u32 +pub enum bitcoin_units::NumOpResult +pub enum bitcoin_units::absolute::LockTime +pub enum bitcoin_units::locktime::absolute::LockTime +pub enum bitcoin_units::locktime::relative::IsSatisfiedByError +pub enum bitcoin_units::locktime::relative::IsSatisfiedByHeightError +pub enum bitcoin_units::locktime::relative::IsSatisfiedByTimeError +pub enum bitcoin_units::locktime::relative::LockTime +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByError +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +pub enum bitcoin_units::relative::IsSatisfiedByError +pub enum bitcoin_units::relative::IsSatisfiedByHeightError +pub enum bitcoin_units::relative::IsSatisfiedByTimeError +pub enum bitcoin_units::relative::LockTime +pub enum bitcoin_units::relative::error::IsSatisfiedByError +pub enum bitcoin_units::relative::error::IsSatisfiedByHeightError +pub enum bitcoin_units::relative::error::IsSatisfiedByTimeError +pub enum bitcoin_units::result::NumOpResult +pub fn &bitcoin_units::Amount::add(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::add(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::add(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::FeeRate::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::sub(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::sub(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &core::num::nonzero::NonZeroI64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: core::num::nonzero::NonZeroI64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::mul(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::mul(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::rem(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::rem(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::add(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::add(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::sub(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::sub(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtp) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtp) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: &T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: &T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &i64::mul(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &i64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &i64::mul(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &i64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::clone(&self) -> bitcoin_units::Amount +pub fn bitcoin_units::Amount::cmp(&self, other: &bitcoin_units::Amount) -> core::cmp::Ordering +pub fn bitcoin_units::Amount::default() -> Self +pub fn bitcoin_units::Amount::display_dynamic(self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::Amount::display_in(self, denomination: bitcoin_units::amount::Denomination) -> bitcoin_units::amount::Display +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Amount::eq(&self, other: &bitcoin_units::Amount) -> bool +pub fn bitcoin_units::Amount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::Amount::from_btc(btc: f64) -> core::result::Result +pub fn bitcoin_units::Amount::from_float_in(value: f64, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::Amount::from_int_btc>(whole_bitcoin: T) -> Self +pub fn bitcoin_units::Amount::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::Amount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::Amount::from_str_with_denomination(s: &str) -> core::result::Result +pub fn bitcoin_units::Amount::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::Amount::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Amount::partial_cmp(&self, other: &bitcoin_units::Amount) -> core::option::Option +pub fn bitcoin_units::Amount::rem(self, modulus: u64) -> Self::Output +pub fn bitcoin_units::Amount::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::signed_sub(self, rhs: Self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::to_btc(self) -> f64 +pub fn bitcoin_units::Amount::to_float_in(self, denom: bitcoin_units::amount::Denomination) -> f64 +pub fn bitcoin_units::Amount::to_signed(self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::Amount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::Amount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::Amount::try_from(value: bitcoin_units::SignedAmount) -> core::result::Result +pub fn bitcoin_units::BlockTime::clone(&self) -> bitcoin_units::BlockTime +pub fn bitcoin_units::BlockTime::cmp(&self, other: &bitcoin_units::BlockTime) -> core::cmp::Ordering +pub fn bitcoin_units::BlockTime::eq(&self, other: &bitcoin_units::BlockTime) -> bool +pub fn bitcoin_units::BlockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::BlockTime::from(t: u32) -> Self +pub fn bitcoin_units::BlockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::BlockTime::partial_cmp(&self, other: &bitcoin_units::BlockTime) -> core::option::Option +pub fn bitcoin_units::FeeRate::add(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::add(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::add_assign(&mut self, rhs: &bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::add_assign(&mut self, rhs: bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::clone(&self) -> bitcoin_units::FeeRate +pub fn bitcoin_units::FeeRate::cmp(&self, other: &bitcoin_units::FeeRate) -> core::cmp::Ordering +pub fn bitcoin_units::FeeRate::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::FeeRate::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::FeeRate::eq(&self, other: &bitcoin_units::FeeRate) -> bool +pub fn bitcoin_units::FeeRate::fee_vb(self, vb: u64) -> core::option::Option +pub fn bitcoin_units::FeeRate::fee_wu(self, weight: bitcoin_units::Weight) -> core::option::Option +pub fn bitcoin_units::FeeRate::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::FeeRate::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::FeeRate::partial_cmp(&self, other: &bitcoin_units::FeeRate) -> core::option::Option +pub fn bitcoin_units::FeeRate::sub(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::sub(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::sub_assign(&mut self, rhs: &bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::sub_assign(&mut self, rhs: bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::FeeRate::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::clone(&self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::SignedAmount::cmp(&self, other: &bitcoin_units::SignedAmount) -> core::cmp::Ordering +pub fn bitcoin_units::SignedAmount::default() -> Self +pub fn bitcoin_units::SignedAmount::display_dynamic(self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::SignedAmount::display_in(self, denomination: bitcoin_units::amount::Denomination) -> bitcoin_units::amount::Display +pub fn bitcoin_units::SignedAmount::div(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: &core::num::nonzero::NonZeroI64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: core::num::nonzero::NonZeroI64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::eq(&self, other: &bitcoin_units::SignedAmount) -> bool +pub fn bitcoin_units::SignedAmount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::SignedAmount::from(value: bitcoin_units::Amount) -> Self +pub fn bitcoin_units::SignedAmount::from_btc(btc: f64) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_float_in(value: f64, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_int_btc>(whole_bitcoin: T) -> Self +pub fn bitcoin_units::SignedAmount::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_str_with_denomination(s: &str) -> core::result::Result +pub fn bitcoin_units::SignedAmount::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::SignedAmount::is_negative(self) -> bool +pub fn bitcoin_units::SignedAmount::is_positive(self) -> bool +pub fn bitcoin_units::SignedAmount::mul(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::mul(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::neg(self) -> Self::Output +pub fn bitcoin_units::SignedAmount::partial_cmp(&self, other: &bitcoin_units::SignedAmount) -> core::option::Option +pub fn bitcoin_units::SignedAmount::positive_sub(self, rhs: Self) -> core::option::Option +pub fn bitcoin_units::SignedAmount::rem(self, modulus: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::rem(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::signum(self) -> i64 +pub fn bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::to_btc(self) -> f64 +pub fn bitcoin_units::SignedAmount::to_float_in(self, denom: bitcoin_units::amount::Denomination) -> f64 +pub fn bitcoin_units::SignedAmount::to_string_in(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::SignedAmount::to_string_with_denomination(self, denom: bitcoin_units::amount::Denomination) -> alloc::string::String +pub fn bitcoin_units::SignedAmount::to_unsigned(self) -> core::result::Result +pub fn bitcoin_units::SignedAmount::unsigned_abs(self) -> bitcoin_units::Amount +pub fn bitcoin_units::Weight::add(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::add(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::add_assign(&mut self, rhs: &bitcoin_units::Weight) +pub fn bitcoin_units::Weight::add_assign(&mut self, rhs: bitcoin_units::Weight) +pub fn bitcoin_units::Weight::clone(&self) -> bitcoin_units::Weight +pub fn bitcoin_units::Weight::cmp(&self, other: &bitcoin_units::Weight) -> core::cmp::Ordering +pub fn bitcoin_units::Weight::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::div_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::eq(&self, other: &bitcoin_units::Weight) -> bool +pub fn bitcoin_units::Weight::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::Weight::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::Weight::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::mul_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::partial_cmp(&self, other: &bitcoin_units::Weight) -> core::option::Option +pub fn bitcoin_units::Weight::rem(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::rem_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::sub(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::sub(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::sub_assign(&mut self, rhs: &bitcoin_units::Weight) +pub fn bitcoin_units::Weight::sub_assign(&mut self, rhs: bitcoin_units::Weight) +pub fn bitcoin_units::Weight::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::Weight::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::Weight::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::Weight::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::Weight::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::amount::Denomination::clone(&self) -> bitcoin_units::amount::Denomination +pub fn bitcoin_units::amount::Denomination::eq(&self, other: &bitcoin_units::amount::Denomination) -> bool +pub fn bitcoin_units::amount::Denomination::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::Denomination::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::amount::Denomination::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::amount::Display::clone(&self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::amount::Display::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::Display::show_denomination(self) -> Self +pub fn bitcoin_units::amount::error::BadPositionError::clone(&self) -> bitcoin_units::amount::error::BadPositionError +pub fn bitcoin_units::amount::error::BadPositionError::eq(&self, other: &bitcoin_units::amount::error::BadPositionError) -> bool +pub fn bitcoin_units::amount::error::BadPositionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::InputTooLargeError::clone(&self) -> bitcoin_units::amount::error::InputTooLargeError +pub fn bitcoin_units::amount::error::InputTooLargeError::eq(&self, other: &bitcoin_units::amount::error::InputTooLargeError) -> bool +pub fn bitcoin_units::amount::error::InputTooLargeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::InvalidCharacterError::clone(&self) -> bitcoin_units::amount::error::InvalidCharacterError +pub fn bitcoin_units::amount::error::InvalidCharacterError::eq(&self, other: &bitcoin_units::amount::error::InvalidCharacterError) -> bool +pub fn bitcoin_units::amount::error::InvalidCharacterError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::MissingDenominationError::clone(&self) -> bitcoin_units::amount::error::MissingDenominationError +pub fn bitcoin_units::amount::error::MissingDenominationError::eq(&self, other: &bitcoin_units::amount::error::MissingDenominationError) -> bool +pub fn bitcoin_units::amount::error::MissingDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::MissingDigitsError::clone(&self) -> bitcoin_units::amount::error::MissingDigitsError +pub fn bitcoin_units::amount::error::MissingDigitsError::eq(&self, other: &bitcoin_units::amount::error::MissingDigitsError) -> bool +pub fn bitcoin_units::amount::error::MissingDigitsError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::OutOfRangeError::clone(&self) -> bitcoin_units::amount::error::OutOfRangeError +pub fn bitcoin_units::amount::error::OutOfRangeError::eq(&self, other: &bitcoin_units::amount::error::OutOfRangeError) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::OutOfRangeError::is_above_max(self) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::is_below_min(self) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::valid_range(self) -> (i64, u64) +pub fn bitcoin_units::amount::error::ParseAmountError::clone(&self) -> bitcoin_units::amount::error::ParseAmountError +pub fn bitcoin_units::amount::error::ParseAmountError::eq(&self, other: &bitcoin_units::amount::error::ParseAmountError) -> bool +pub fn bitcoin_units::amount::error::ParseAmountError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseAmountError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::BadPositionError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::InputTooLargeError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::InvalidCharacterError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::MissingDigitsError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::OutOfRangeError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::TooPreciseError) -> Self +pub fn bitcoin_units::amount::error::ParseDenominationError::clone(&self) -> bitcoin_units::amount::error::ParseDenominationError +pub fn bitcoin_units::amount::error::ParseDenominationError::eq(&self, other: &bitcoin_units::amount::error::ParseDenominationError) -> bool +pub fn bitcoin_units::amount::error::ParseDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseDenominationError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseError::clone(&self) -> bitcoin_units::amount::error::ParseError +pub fn bitcoin_units::amount::error::ParseError::eq(&self, other: &bitcoin_units::amount::error::ParseError) -> bool +pub fn bitcoin_units::amount::error::ParseError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::BadPositionError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::InputTooLargeError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::InvalidCharacterError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::MissingDigitsError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::OutOfRangeError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::ParseAmountError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::ParseDenominationError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::TooPreciseError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::clone(&self) -> bitcoin_units::amount::error::PossiblyConfusingDenominationError +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::eq(&self, other: &bitcoin_units::amount::error::PossiblyConfusingDenominationError) -> bool +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::TooPreciseError::clone(&self) -> bitcoin_units::amount::error::TooPreciseError +pub fn bitcoin_units::amount::error::TooPreciseError::eq(&self, other: &bitcoin_units::amount::error::TooPreciseError) -> bool +pub fn bitcoin_units::amount::error::TooPreciseError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::UnknownDenominationError::clone(&self) -> bitcoin_units::amount::error::UnknownDenominationError +pub fn bitcoin_units::amount::error::UnknownDenominationError::eq(&self, other: &bitcoin_units::amount::error::UnknownDenominationError) -> bool +pub fn bitcoin_units::amount::error::UnknownDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeight::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::checked_add(self, other: bitcoin_units::block::BlockHeightInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::clone(&self) -> bitcoin_units::block::BlockHeight +pub fn bitcoin_units::block::BlockHeight::cmp(&self, other: &bitcoin_units::block::BlockHeight) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockHeight::eq(&self, other: &bitcoin_units::block::BlockHeight) -> bool +pub fn bitcoin_units::block::BlockHeight::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeight::from(h: bitcoin_units::locktime::absolute::Height) -> Self +pub fn bitcoin_units::block::BlockHeight::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockHeight::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockHeight::partial_cmp(&self, other: &bitcoin_units::block::BlockHeight) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeight) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeight) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::add_assign(&mut self, rhs: &bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::add_assign(&mut self, rhs: bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::checked_add(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::clone(&self) -> bitcoin_units::block::BlockHeightInterval +pub fn bitcoin_units::block::BlockHeightInterval::cmp(&self, other: &bitcoin_units::block::BlockHeightInterval) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockHeightInterval::default() -> bitcoin_units::block::BlockHeightInterval +pub fn bitcoin_units::block::BlockHeightInterval::eq(&self, other: &bitcoin_units::block::BlockHeightInterval) -> bool +pub fn bitcoin_units::block::BlockHeightInterval::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeightInterval::from(h: bitcoin_units::locktime::relative::NumberOfBlocks) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockHeightInterval::partial_cmp(&self, other: &bitcoin_units::block::BlockHeightInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::sub_assign(&mut self, rhs: &bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::sub_assign(&mut self, rhs: bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::sum>(iter: I) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::checked_add(self, other: bitcoin_units::block::BlockMtpInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::clone(&self) -> bitcoin_units::block::BlockMtp +pub fn bitcoin_units::block::BlockMtp::cmp(&self, other: &bitcoin_units::block::BlockMtp) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockMtp::eq(&self, other: &bitcoin_units::block::BlockMtp) -> bool +pub fn bitcoin_units::block::BlockMtp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockMtp::from(h: bitcoin_units::locktime::absolute::MedianTimePast) -> Self +pub fn bitcoin_units::block::BlockMtp::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockMtp::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockMtp::new(timestamps: [bitcoin_units::BlockTime; 11]) -> Self +pub fn bitcoin_units::block::BlockMtp::partial_cmp(&self, other: &bitcoin_units::block::BlockMtp) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtp) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtp) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::add_assign(&mut self, rhs: &bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::add_assign(&mut self, rhs: bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::checked_add(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::clone(&self) -> bitcoin_units::block::BlockMtpInterval +pub fn bitcoin_units::block::BlockMtpInterval::cmp(&self, other: &bitcoin_units::block::BlockMtpInterval) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockMtpInterval::default() -> bitcoin_units::block::BlockMtpInterval +pub fn bitcoin_units::block::BlockMtpInterval::eq(&self, other: &bitcoin_units::block::BlockMtpInterval) -> bool +pub fn bitcoin_units::block::BlockMtpInterval::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockMtpInterval::from(h: bitcoin_units::locktime::relative::NumberOf512Seconds) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockMtpInterval::partial_cmp(&self, other: &bitcoin_units::block::BlockMtpInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::sub_assign(&mut self, rhs: &bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::sub_assign(&mut self, rhs: bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::sum>(iter: I) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::block::TooBigForRelativeHeightError::clone(&self) -> bitcoin_units::block::TooBigForRelativeHeightError +pub fn bitcoin_units::block::TooBigForRelativeHeightError::eq(&self, other: &bitcoin_units::block::TooBigForRelativeHeightError) -> bool +pub fn bitcoin_units::block::TooBigForRelativeHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::Height::clone(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::Height::cmp(&self, other: &bitcoin_units::locktime::absolute::Height) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::absolute::Height::eq(&self, other: &bitcoin_units::locktime::absolute::Height) -> bool +pub fn bitcoin_units::locktime::absolute::Height::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::Height::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::Height::is_satisfied_by(self, height: Self) -> bool +pub fn bitcoin_units::locktime::absolute::Height::partial_cmp(&self, other: &bitcoin_units::locktime::absolute::Height) -> core::option::Option +pub fn bitcoin_units::locktime::absolute::Height::try_from(h: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::clone(&self) -> bitcoin_units::locktime::absolute::LockTime +pub fn bitcoin_units::locktime::absolute::LockTime::eq(&self, other: &bitcoin_units::locktime::absolute::LockTime) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from(h: bitcoin_units::locktime::absolute::Height) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from(t: bitcoin_units::locktime::absolute::MedianTimePast) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from_consensus(n: u32) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from_height(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_mtp(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_unprefixed_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::LockTime::is_implied_by(self, other: Self) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by(self, height: bitcoin_units::locktime::absolute::Height, mtp: bitcoin_units::locktime::absolute::MedianTimePast) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by_height(self, height: bitcoin_units::locktime::absolute::Height) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by_time(self, mtp: bitcoin_units::locktime::absolute::MedianTimePast) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::to_consensus_u32(self) -> u32 +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::clone(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::MedianTimePast::cmp(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::absolute::MedianTimePast::eq(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> bool +pub fn bitcoin_units::locktime::absolute::MedianTimePast::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::MedianTimePast::is_satisfied_by(self, time: Self) -> bool +pub fn bitcoin_units::locktime::absolute::MedianTimePast::new(timestamps: [bitcoin_units::BlockTime; 11]) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::partial_cmp(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> core::option::Option +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(h: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::error::ConversionError::clone(&self) -> bitcoin_units::locktime::absolute::error::ConversionError +pub fn bitcoin_units::locktime::absolute::error::ConversionError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ConversionError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ConversionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::clone(&self) -> bitcoin_units::locktime::absolute::error::IncompatibleHeightError +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::eq(&self, other: &bitcoin_units::locktime::absolute::error::IncompatibleHeightError) -> bool +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::incompatible(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::lock(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::clone(&self) -> bitcoin_units::locktime::absolute::error::IncompatibleTimeError +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::IncompatibleTimeError) -> bool +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::incompatible(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::lock(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::clone(&self) -> bitcoin_units::locktime::absolute::error::ParseHeightError +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseHeightError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::clone(&self) -> bitcoin_units::locktime::absolute::error::ParseTimeError +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseTimeError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::LockTime::clone(&self) -> bitcoin_units::locktime::relative::LockTime +pub fn bitcoin_units::locktime::relative::LockTime::eq(&self, other: &bitcoin_units::locktime::relative::LockTime) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::LockTime::from(h: bitcoin_units::locktime::relative::NumberOfBlocks) -> Self +pub fn bitcoin_units::locktime::relative::LockTime::from(t: bitcoin_units::locktime::relative::NumberOf512Seconds) -> Self +pub fn bitcoin_units::locktime::relative::LockTime::from_consensus(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::from_sequence(n: bitcoin_units::sequence::Sequence) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::LockTime::is_implied_by(self, other: Self) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::is_implied_by_sequence(self, other: bitcoin_units::sequence::Sequence) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by(self, chain_tip_height: bitcoin_units::block::BlockHeight, chain_tip_mtp: bitcoin_units::block::BlockMtp, utxo_mined_at_height: bitcoin_units::block::BlockHeight, utxo_mined_at_mtp: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by_height(self, chain_tip: bitcoin_units::block::BlockHeight, utxo_mined_at: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by_time(self, chain_tip: bitcoin_units::block::BlockMtp, utxo_mined_at: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::to_consensus_u32(self) -> u32 +pub fn bitcoin_units::locktime::relative::LockTime::to_sequence(self) -> bitcoin_units::sequence::Sequence +pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::clone(&self) -> bitcoin_units::locktime::relative::NumberOf512Seconds +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::cmp(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::default() -> bitcoin_units::locktime::relative::NumberOf512Seconds +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::eq(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> bool +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::is_satisfied_by(self, chain_tip: bitcoin_units::block::BlockMtp, utxo_mined_at: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::partial_cmp(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> core::option::Option +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::clone(&self) -> bitcoin_units::locktime::relative::NumberOfBlocks +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::cmp(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::default() -> bitcoin_units::locktime::relative::NumberOfBlocks +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::eq(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> bool +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::from(value: u16) -> Self +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::is_satisfied_by(self, chain_tip: bitcoin_units::block::BlockHeight, utxo_mined_at: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::partial_cmp(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> core::option::Option +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(h: bitcoin_units::block::BlockHeightInterval) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::DisabledLockTimeError +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::disabled_locktime_value(&self) -> u32 +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::DisabledLockTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::clone(&self) -> bitcoin_units::locktime::relative::error::InvalidHeightError +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::eq(&self, other: &bitcoin_units::locktime::relative::error::InvalidHeightError) -> bool +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::InvalidTimeError +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::InvalidTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::clone(&self) -> bitcoin_units::locktime::relative::error::TimeOverflowError +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::eq(&self, other: &bitcoin_units::locktime::relative::error::TimeOverflowError) -> bool +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::ParseIntError::as_ref(&self) -> &core::num::error::ParseIntError +pub fn bitcoin_units::parse_int::ParseIntError::clone(&self) -> bitcoin_units::parse_int::ParseIntError +pub fn bitcoin_units::parse_int::ParseIntError::eq(&self, other: &bitcoin_units::parse_int::ParseIntError) -> bool +pub fn bitcoin_units::parse_int::ParseIntError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::PrefixedHexError::clone(&self) -> bitcoin_units::parse_int::PrefixedHexError +pub fn bitcoin_units::parse_int::PrefixedHexError::eq(&self, other: &bitcoin_units::parse_int::PrefixedHexError) -> bool +pub fn bitcoin_units::parse_int::PrefixedHexError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::PrefixedHexError::from(e: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn bitcoin_units::parse_int::PrefixedHexError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::parse_int::UnprefixedHexError::clone(&self) -> bitcoin_units::parse_int::UnprefixedHexError +pub fn bitcoin_units::parse_int::UnprefixedHexError::eq(&self, other: &bitcoin_units::parse_int::UnprefixedHexError) -> bool +pub fn bitcoin_units::parse_int::UnprefixedHexError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::UnprefixedHexError::from(e: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn bitcoin_units::parse_int::UnprefixedHexError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::parse_int::hex_check_unprefixed(s: &str) -> core::result::Result<&str, bitcoin_units::parse_int::UnprefixedHexError> +pub fn bitcoin_units::parse_int::hex_remove_prefix(s: &str) -> core::result::Result<&str, bitcoin_units::parse_int::PrefixedHexError> +pub fn bitcoin_units::parse_int::hex_u128(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_prefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_unchecked(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_unprefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_prefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_unchecked(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_unprefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_box(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_string(s: alloc::string::String) -> core::result::Result +pub fn bitcoin_units::result::MathOp::clone(&self) -> bitcoin_units::result::MathOp +pub fn bitcoin_units::result::MathOp::eq(&self, other: &bitcoin_units::result::MathOp) -> bool +pub fn bitcoin_units::result::MathOp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::MathOp::is_addition(self) -> bool +pub fn bitcoin_units::result::MathOp::is_div_by_zero(self) -> bool +pub fn bitcoin_units::result::MathOp::is_multiplication(self) -> bool +pub fn bitcoin_units::result::MathOp::is_negation(self) -> bool +pub fn bitcoin_units::result::MathOp::is_overflow(self) -> bool +pub fn bitcoin_units::result::MathOp::is_subtraction(self) -> bool +pub fn bitcoin_units::result::NumOpError::clone(&self) -> bitcoin_units::result::NumOpError +pub fn bitcoin_units::result::NumOpError::eq(&self, other: &bitcoin_units::result::NumOpError) -> bool +pub fn bitcoin_units::result::NumOpError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::NumOpError::is_div_by_zero(self) -> bool +pub fn bitcoin_units::result::NumOpError::is_overflow(self) -> bool +pub fn bitcoin_units::result::NumOpError::operation(self) -> bitcoin_units::result::MathOp +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: &T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: Self) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: T) +pub fn bitcoin_units::result::NumOpResult::and_then(self, op: F) -> Self where F: core::ops::function::FnOnce(T) -> Self +pub fn bitcoin_units::result::NumOpResult::clone(&self) -> bitcoin_units::result::NumOpResult +pub fn bitcoin_units::result::NumOpResult::eq(&self, other: &bitcoin_units::result::NumOpResult) -> bool +pub fn bitcoin_units::result::NumOpResult::expect(self, msg: &str) -> T +pub fn bitcoin_units::result::NumOpResult::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::NumOpResult::into_result(self) -> core::result::Result +pub fn bitcoin_units::result::NumOpResult::is_error(&self) -> bool +pub fn bitcoin_units::result::NumOpResult::is_valid(&self) -> bool +pub fn bitcoin_units::result::NumOpResult::map U>(self, op: F) -> bitcoin_units::result::NumOpResult +pub fn bitcoin_units::result::NumOpResult::ok(self) -> core::option::Option +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: &T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: Self) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: T) +pub fn bitcoin_units::result::NumOpResult::unwrap(self) -> T +pub fn bitcoin_units::result::NumOpResult::unwrap_err(self) -> bitcoin_units::result::NumOpError +pub fn bitcoin_units::result::NumOpResult::unwrap_or(self, default: T) -> T +pub fn bitcoin_units::result::NumOpResult::unwrap_or_else(self, f: F) -> T where F: core::ops::function::FnOnce() -> T +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: bitcoin_units::Amount) +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: &u64) +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: u64) +pub fn bitcoin_units::result::NumOpResult::from(a: &bitcoin_units::Amount) -> Self +pub fn bitcoin_units::result::NumOpResult::from(a: bitcoin_units::Amount) -> Self +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: &u64) +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: u64) +pub fn bitcoin_units::result::NumOpResult::rem(self, modulus: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: bitcoin_units::Amount) +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: bitcoin_units::SignedAmount) +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: &i64) +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: i64) +pub fn bitcoin_units::result::NumOpResult::from(a: &bitcoin_units::SignedAmount) -> Self +pub fn bitcoin_units::result::NumOpResult::from(a: bitcoin_units::SignedAmount) -> Self +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: &i64) +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: i64) +pub fn bitcoin_units::result::NumOpResult::rem(self, modulus: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::rem(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: bitcoin_units::SignedAmount) +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::sequence::Sequence::clone(&self) -> bitcoin_units::sequence::Sequence +pub fn bitcoin_units::sequence::Sequence::cmp(&self, other: &bitcoin_units::sequence::Sequence) -> core::cmp::Ordering +pub fn bitcoin_units::sequence::Sequence::default() -> Self +pub fn bitcoin_units::sequence::Sequence::enables_absolute_lock_time(self) -> bool +pub fn bitcoin_units::sequence::Sequence::eq(&self, other: &bitcoin_units::sequence::Sequence) -> bool +pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::sequence::Sequence::from(lt: bitcoin_units::locktime::relative::LockTime) -> Self +pub fn bitcoin_units::sequence::Sequence::from_512_second_intervals(intervals: u16) -> Self +pub fn bitcoin_units::sequence::Sequence::from_consensus(n: u32) -> Self +pub fn bitcoin_units::sequence::Sequence::from_height(height: u16) -> Self +pub fn bitcoin_units::sequence::Sequence::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_seconds_ceil(seconds: u32) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_seconds_floor(seconds: u32) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_unprefixed_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::sequence::Sequence::is_final(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_height_locked(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_rbf(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_relative_lock_time(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_time_locked(self) -> bool +pub fn bitcoin_units::sequence::Sequence::partial_cmp(&self, other: &bitcoin_units::sequence::Sequence) -> core::option::Option +pub fn bitcoin_units::sequence::Sequence::to_hex(self) -> alloc::string::String +pub fn bitcoin_units::sequence::Sequence::to_relative_lock_time(self) -> core::option::Option +pub fn bitcoin_units::sequence::Sequence::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::try_from(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::try_from(s: alloc::string::String) -> core::result::Result +pub fn core::num::error::ParseIntError::from(value: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn i64::mul(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn i64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn i64::mul(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn i64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn u32::from(height: bitcoin_units::block::BlockHeight) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockHeightInterval) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockMtp) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockMtpInterval) -> Self +pub fn u32::from(sequence: bitcoin_units::sequence::Sequence) -> Self +pub fn u32::from(t: bitcoin_units::BlockTime) -> Self +pub fn u64::from(value: bitcoin_units::Weight) -> Self +pub fn u64::mul(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn u64::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn u64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub mod bitcoin_units +pub mod bitcoin_units::absolute +pub mod bitcoin_units::absolute::error +pub mod bitcoin_units::amount +pub mod bitcoin_units::amount::error +pub mod bitcoin_units::block +pub mod bitcoin_units::fee_rate +pub mod bitcoin_units::locktime +pub mod bitcoin_units::locktime::absolute +pub mod bitcoin_units::locktime::absolute::error +pub mod bitcoin_units::locktime::relative +pub mod bitcoin_units::locktime::relative::error +pub mod bitcoin_units::parse_int +pub mod bitcoin_units::relative +pub mod bitcoin_units::relative::error +pub mod bitcoin_units::result +pub mod bitcoin_units::sequence +pub mod bitcoin_units::time +pub mod bitcoin_units::weight +pub struct bitcoin_units::Amount(_) +pub struct bitcoin_units::BlockHeight(_) +pub struct bitcoin_units::BlockHeightInterval(_) +pub struct bitcoin_units::BlockMtp(_) +pub struct bitcoin_units::BlockMtpInterval(_) +pub struct bitcoin_units::BlockTime(_) +pub struct bitcoin_units::FeeRate(_) +pub struct bitcoin_units::Sequence(pub u32) +pub struct bitcoin_units::SignedAmount(_) +pub struct bitcoin_units::Weight(_) +pub struct bitcoin_units::absolute::Height(_) +pub struct bitcoin_units::absolute::IncompatibleHeightError +pub struct bitcoin_units::absolute::IncompatibleTimeError +pub struct bitcoin_units::absolute::MedianTimePast(_) +pub struct bitcoin_units::absolute::ParseHeightError(_) +pub struct bitcoin_units::absolute::ParseTimeError(_) +pub struct bitcoin_units::absolute::error::IncompatibleHeightError +pub struct bitcoin_units::absolute::error::IncompatibleTimeError +pub struct bitcoin_units::absolute::error::ParseHeightError(_) +pub struct bitcoin_units::absolute::error::ParseTimeError(_) +pub struct bitcoin_units::amount::Amount(_) +pub struct bitcoin_units::amount::Display +pub struct bitcoin_units::amount::OutOfRangeError +pub struct bitcoin_units::amount::ParseAmountError(_) +pub struct bitcoin_units::amount::ParseError(_) +pub struct bitcoin_units::amount::SignedAmount(_) +pub struct bitcoin_units::amount::error::BadPositionError +pub struct bitcoin_units::amount::error::InputTooLargeError +pub struct bitcoin_units::amount::error::InvalidCharacterError +pub struct bitcoin_units::amount::error::MissingDigitsError +pub struct bitcoin_units::amount::error::OutOfRangeError +pub struct bitcoin_units::amount::error::ParseAmountError(_) +pub struct bitcoin_units::amount::error::ParseError(_) +pub struct bitcoin_units::amount::error::TooPreciseError +pub struct bitcoin_units::block::BlockHeight(_) +pub struct bitcoin_units::block::BlockHeightInterval(_) +pub struct bitcoin_units::block::BlockMtp(_) +pub struct bitcoin_units::block::BlockMtpInterval(_) +pub struct bitcoin_units::block::TooBigForRelativeHeightError(_) +pub struct bitcoin_units::fee_rate::FeeRate(_) +pub struct bitcoin_units::locktime::absolute::Height(_) +pub struct bitcoin_units::locktime::absolute::IncompatibleHeightError +pub struct bitcoin_units::locktime::absolute::IncompatibleTimeError +pub struct bitcoin_units::locktime::absolute::MedianTimePast(_) +pub struct bitcoin_units::locktime::absolute::ParseHeightError(_) +pub struct bitcoin_units::locktime::absolute::ParseTimeError(_) +pub struct bitcoin_units::locktime::absolute::error::IncompatibleHeightError +pub struct bitcoin_units::locktime::absolute::error::IncompatibleTimeError +pub struct bitcoin_units::locktime::absolute::error::ParseHeightError(_) +pub struct bitcoin_units::locktime::absolute::error::ParseTimeError(_) +pub struct bitcoin_units::locktime::relative::DisabledLockTimeError(_) +pub struct bitcoin_units::locktime::relative::InvalidHeightError +pub struct bitcoin_units::locktime::relative::InvalidTimeError +pub struct bitcoin_units::locktime::relative::NumberOf512Seconds(_) +pub struct bitcoin_units::locktime::relative::NumberOfBlocks(_) +pub struct bitcoin_units::locktime::relative::TimeOverflowError +pub struct bitcoin_units::locktime::relative::error::DisabledLockTimeError(_) +pub struct bitcoin_units::locktime::relative::error::InvalidHeightError +pub struct bitcoin_units::locktime::relative::error::InvalidTimeError +pub struct bitcoin_units::locktime::relative::error::TimeOverflowError +pub struct bitcoin_units::parse_int::PrefixedHexError(_) +pub struct bitcoin_units::parse_int::UnprefixedHexError(_) +pub struct bitcoin_units::relative::DisabledLockTimeError(_) +pub struct bitcoin_units::relative::InvalidHeightError +pub struct bitcoin_units::relative::InvalidTimeError +pub struct bitcoin_units::relative::NumberOf512Seconds(_) +pub struct bitcoin_units::relative::NumberOfBlocks(_) +pub struct bitcoin_units::relative::TimeOverflowError +pub struct bitcoin_units::relative::error::DisabledLockTimeError(_) +pub struct bitcoin_units::relative::error::InvalidHeightError +pub struct bitcoin_units::relative::error::InvalidTimeError +pub struct bitcoin_units::relative::error::TimeOverflowError +pub struct bitcoin_units::sequence::Sequence(pub u32) +pub struct bitcoin_units::time::BlockTime(_) +pub struct bitcoin_units::weight::Weight(_) +pub trait bitcoin_units::parse_int::Integer: core::str::traits::FromStr + core::convert::TryFrom + core::marker::Sized + bitcoin_units::parse_int::sealed::Sealed +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::FeeRate::Output = ::Output +pub type &bitcoin_units::FeeRate::Output = >>::Output +pub type &bitcoin_units::FeeRate::Output = >::Output +pub type &bitcoin_units::FeeRate::Output = >>::Output +pub type &bitcoin_units::FeeRate::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = >>::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = >>::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::block::BlockHeight::Output = >::Output +pub type &bitcoin_units::block::BlockHeight::Output = >::Output +pub type &bitcoin_units::block::BlockHeight::Output = ::Output +pub type &bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type &bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type &bitcoin_units::block::BlockMtp::Output = >::Output +pub type &bitcoin_units::block::BlockMtp::Output = >::Output +pub type &bitcoin_units::block::BlockMtp::Output = ::Output +pub type &bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type &bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type &i64::Output = >::Output +pub type &i64::Output = >>::Output +pub type &u64::Output = >::Output +pub type &u64::Output = >::Output +pub type &u64::Output = >>::Output +pub type bitcoin_units::Amount::Err = bitcoin_units::amount::error::ParseError +pub type bitcoin_units::Amount::Error = bitcoin_units::amount::error::OutOfRangeError +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = bitcoin_units::Amount +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::FeeRate::Output = ::Output +pub type bitcoin_units::FeeRate::Output = >>::Output +pub type bitcoin_units::FeeRate::Output = >::Output +pub type bitcoin_units::FeeRate::Output = >>::Output +pub type bitcoin_units::FeeRate::Output = ::Output +pub type bitcoin_units::FeeRate::Output = bitcoin_units::FeeRate +pub type bitcoin_units::FeeRate::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::SignedAmount::Err = bitcoin_units::amount::error::ParseError +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::SignedAmount +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Weight::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::Weight::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = >>::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = >>::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = bitcoin_units::Weight +pub type bitcoin_units::Weight::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Weight::Output = u64 +pub type bitcoin_units::amount::Denomination::Err = bitcoin_units::amount::error::ParseDenominationError +pub type bitcoin_units::block::BlockHeight::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeight::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeight::Output = >::Output +pub type bitcoin_units::block::BlockHeight::Output = >::Output +pub type bitcoin_units::block::BlockHeight::Output = ::Output +pub type bitcoin_units::block::BlockHeight::Output = bitcoin_units::block::BlockHeight +pub type bitcoin_units::block::BlockHeight::Output = bitcoin_units::block::BlockHeightInterval +pub type bitcoin_units::block::BlockHeightInterval::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeightInterval::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type bitcoin_units::block::BlockHeightInterval::Output = bitcoin_units::block::BlockHeightInterval +pub type bitcoin_units::block::BlockMtp::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtp::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtp::Output = >::Output +pub type bitcoin_units::block::BlockMtp::Output = >::Output +pub type bitcoin_units::block::BlockMtp::Output = ::Output +pub type bitcoin_units::block::BlockMtp::Output = bitcoin_units::block::BlockMtp +pub type bitcoin_units::block::BlockMtp::Output = bitcoin_units::block::BlockMtpInterval +pub type bitcoin_units::block::BlockMtpInterval::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtpInterval::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type bitcoin_units::block::BlockMtpInterval::Output = bitcoin_units::block::BlockMtpInterval +pub type bitcoin_units::locktime::absolute::Height::Err = bitcoin_units::locktime::absolute::error::ParseHeightError +pub type bitcoin_units::locktime::absolute::Height::Error = bitcoin_units::locktime::absolute::error::ConversionError +pub type bitcoin_units::locktime::absolute::Height::Error = bitcoin_units::locktime::absolute::error::ParseHeightError +pub type bitcoin_units::locktime::absolute::LockTime::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::absolute::LockTime::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Err = bitcoin_units::locktime::absolute::error::ParseTimeError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Error = bitcoin_units::locktime::absolute::error::ConversionError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Error = bitcoin_units::locktime::absolute::error::ParseTimeError +pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError +pub type bitcoin_units::locktime::relative::NumberOf512Seconds::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOf512Seconds::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Error = bitcoin_units::block::TooBigForRelativeHeightError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::sequence::Sequence::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::sequence::Sequence::Error = bitcoin_units::parse_int::ParseIntError +pub type i64::Output = >::Output +pub type i64::Output = >>::Output +pub type i64::Output = bitcoin_units::result::NumOpResult +pub type u64::Output = >::Output +pub type u64::Output = >::Output +pub type u64::Output = >>::Output +pub type u64::Output = bitcoin_units::Weight +pub type u64::Output = bitcoin_units::result::NumOpResult diff --git a/api/units/no-features.txt b/api/units/no-features.txt new file mode 100644 index 000000000..8c0c21e5f --- /dev/null +++ b/api/units/no-features.txt @@ -0,0 +1,2358 @@ +#[non_exhaustive] pub enum bitcoin_units::amount::Denomination +#[non_exhaustive] pub enum bitcoin_units::amount::ParseDenominationError +#[non_exhaustive] pub enum bitcoin_units::amount::error::ParseDenominationError +#[non_exhaustive] pub enum bitcoin_units::result::MathOp +#[non_exhaustive] pub struct bitcoin_units::absolute::ConversionError +#[non_exhaustive] pub struct bitcoin_units::absolute::error::ConversionError +#[non_exhaustive] pub struct bitcoin_units::amount::error::MissingDenominationError +#[non_exhaustive] pub struct bitcoin_units::amount::error::PossiblyConfusingDenominationError(_) +#[non_exhaustive] pub struct bitcoin_units::amount::error::UnknownDenominationError(_) +#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::ConversionError +#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::error::ConversionError +#[non_exhaustive] pub struct bitcoin_units::parse_int::ParseIntError +#[non_exhaustive] pub struct bitcoin_units::result::NumOpError(_) +impl bitcoin_units::Amount +impl bitcoin_units::BlockTime +impl bitcoin_units::FeeRate +impl bitcoin_units::SignedAmount +impl bitcoin_units::Weight +impl bitcoin_units::amount::Denomination +impl bitcoin_units::amount::Display +impl bitcoin_units::amount::error::OutOfRangeError +impl bitcoin_units::block::BlockHeight +impl bitcoin_units::block::BlockHeightInterval +impl bitcoin_units::block::BlockMtp +impl bitcoin_units::block::BlockMtpInterval +impl bitcoin_units::locktime::absolute::Height +impl bitcoin_units::locktime::absolute::LockTime +impl bitcoin_units::locktime::absolute::MedianTimePast +impl bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl bitcoin_units::locktime::relative::LockTime +impl bitcoin_units::locktime::relative::NumberOf512Seconds +impl bitcoin_units::locktime::relative::NumberOfBlocks +impl bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl bitcoin_units::parse_int::Integer for i128 +impl bitcoin_units::parse_int::Integer for i16 +impl bitcoin_units::parse_int::Integer for i32 +impl bitcoin_units::parse_int::Integer for i64 +impl bitcoin_units::parse_int::Integer for i8 +impl bitcoin_units::parse_int::Integer for u128 +impl bitcoin_units::parse_int::Integer for u16 +impl bitcoin_units::parse_int::Integer for u32 +impl bitcoin_units::parse_int::Integer for u64 +impl bitcoin_units::parse_int::Integer for u8 +impl bitcoin_units::result::MathOp +impl bitcoin_units::result::NumOpError +impl bitcoin_units::sequence::Sequence +impl core::clone::Clone for bitcoin_units::Amount +impl core::clone::Clone for bitcoin_units::BlockTime +impl core::clone::Clone for bitcoin_units::FeeRate +impl core::clone::Clone for bitcoin_units::SignedAmount +impl core::clone::Clone for bitcoin_units::Weight +impl core::clone::Clone for bitcoin_units::amount::Denomination +impl core::clone::Clone for bitcoin_units::amount::Display +impl core::clone::Clone for bitcoin_units::amount::error::BadPositionError +impl core::clone::Clone for bitcoin_units::amount::error::InputTooLargeError +impl core::clone::Clone for bitcoin_units::amount::error::InvalidCharacterError +impl core::clone::Clone for bitcoin_units::amount::error::MissingDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::MissingDigitsError +impl core::clone::Clone for bitcoin_units::amount::error::OutOfRangeError +impl core::clone::Clone for bitcoin_units::amount::error::ParseAmountError +impl core::clone::Clone for bitcoin_units::amount::error::ParseDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::ParseError +impl core::clone::Clone for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::clone::Clone for bitcoin_units::amount::error::TooPreciseError +impl core::clone::Clone for bitcoin_units::amount::error::UnknownDenominationError +impl core::clone::Clone for bitcoin_units::block::BlockHeight +impl core::clone::Clone for bitcoin_units::block::BlockHeightInterval +impl core::clone::Clone for bitcoin_units::block::BlockMtp +impl core::clone::Clone for bitcoin_units::block::BlockMtpInterval +impl core::clone::Clone for bitcoin_units::block::TooBigForRelativeHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::Height +impl core::clone::Clone for bitcoin_units::locktime::absolute::LockTime +impl core::clone::Clone for bitcoin_units::locktime::absolute::MedianTimePast +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ConversionError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::clone::Clone for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::LockTime +impl core::clone::Clone for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::clone::Clone for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::clone::Clone for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::clone::Clone for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::clone::Clone for bitcoin_units::parse_int::ParseIntError +impl core::clone::Clone for bitcoin_units::parse_int::PrefixedHexError +impl core::clone::Clone for bitcoin_units::parse_int::UnprefixedHexError +impl core::clone::Clone for bitcoin_units::result::MathOp +impl core::clone::Clone for bitcoin_units::result::NumOpError +impl core::clone::Clone for bitcoin_units::sequence::Sequence +impl core::cmp::Eq for bitcoin_units::Amount +impl core::cmp::Eq for bitcoin_units::BlockTime +impl core::cmp::Eq for bitcoin_units::FeeRate +impl core::cmp::Eq for bitcoin_units::SignedAmount +impl core::cmp::Eq for bitcoin_units::Weight +impl core::cmp::Eq for bitcoin_units::amount::Denomination +impl core::cmp::Eq for bitcoin_units::amount::error::BadPositionError +impl core::cmp::Eq for bitcoin_units::amount::error::InputTooLargeError +impl core::cmp::Eq for bitcoin_units::amount::error::InvalidCharacterError +impl core::cmp::Eq for bitcoin_units::amount::error::MissingDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::MissingDigitsError +impl core::cmp::Eq for bitcoin_units::amount::error::OutOfRangeError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseAmountError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::ParseError +impl core::cmp::Eq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::cmp::Eq for bitcoin_units::amount::error::TooPreciseError +impl core::cmp::Eq for bitcoin_units::amount::error::UnknownDenominationError +impl core::cmp::Eq for bitcoin_units::block::BlockHeight +impl core::cmp::Eq for bitcoin_units::block::BlockHeightInterval +impl core::cmp::Eq for bitcoin_units::block::BlockMtp +impl core::cmp::Eq for bitcoin_units::block::BlockMtpInterval +impl core::cmp::Eq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::Height +impl core::cmp::Eq for bitcoin_units::locktime::absolute::LockTime +impl core::cmp::Eq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::cmp::Eq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::LockTime +impl core::cmp::Eq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::Eq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::cmp::Eq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::cmp::Eq for bitcoin_units::parse_int::ParseIntError +impl core::cmp::Eq for bitcoin_units::parse_int::PrefixedHexError +impl core::cmp::Eq for bitcoin_units::parse_int::UnprefixedHexError +impl core::cmp::Eq for bitcoin_units::result::MathOp +impl core::cmp::Eq for bitcoin_units::result::NumOpError +impl core::cmp::Eq for bitcoin_units::sequence::Sequence +impl core::cmp::Ord for bitcoin_units::Amount +impl core::cmp::Ord for bitcoin_units::BlockTime +impl core::cmp::Ord for bitcoin_units::FeeRate +impl core::cmp::Ord for bitcoin_units::SignedAmount +impl core::cmp::Ord for bitcoin_units::Weight +impl core::cmp::Ord for bitcoin_units::block::BlockHeight +impl core::cmp::Ord for bitcoin_units::block::BlockHeightInterval +impl core::cmp::Ord for bitcoin_units::block::BlockMtp +impl core::cmp::Ord for bitcoin_units::block::BlockMtpInterval +impl core::cmp::Ord for bitcoin_units::locktime::absolute::Height +impl core::cmp::Ord for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::Ord for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::Ord for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::Ord for bitcoin_units::sequence::Sequence +impl core::cmp::PartialEq for bitcoin_units::Amount +impl core::cmp::PartialEq for bitcoin_units::BlockTime +impl core::cmp::PartialEq for bitcoin_units::FeeRate +impl core::cmp::PartialEq for bitcoin_units::SignedAmount +impl core::cmp::PartialEq for bitcoin_units::Weight +impl core::cmp::PartialEq for bitcoin_units::amount::Denomination +impl core::cmp::PartialEq for bitcoin_units::amount::error::BadPositionError +impl core::cmp::PartialEq for bitcoin_units::amount::error::InputTooLargeError +impl core::cmp::PartialEq for bitcoin_units::amount::error::InvalidCharacterError +impl core::cmp::PartialEq for bitcoin_units::amount::error::MissingDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::MissingDigitsError +impl core::cmp::PartialEq for bitcoin_units::amount::error::OutOfRangeError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseAmountError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::ParseError +impl core::cmp::PartialEq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::cmp::PartialEq for bitcoin_units::amount::error::TooPreciseError +impl core::cmp::PartialEq for bitcoin_units::amount::error::UnknownDenominationError +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeight +impl core::cmp::PartialEq for bitcoin_units::block::BlockHeightInterval +impl core::cmp::PartialEq for bitcoin_units::block::BlockMtp +impl core::cmp::PartialEq for bitcoin_units::block::BlockMtpInterval +impl core::cmp::PartialEq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::Height +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::LockTime +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::LockTime +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::cmp::PartialEq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::cmp::PartialEq for bitcoin_units::parse_int::ParseIntError +impl core::cmp::PartialEq for bitcoin_units::parse_int::PrefixedHexError +impl core::cmp::PartialEq for bitcoin_units::parse_int::UnprefixedHexError +impl core::cmp::PartialEq for bitcoin_units::result::MathOp +impl core::cmp::PartialEq for bitcoin_units::result::NumOpError +impl core::cmp::PartialEq for bitcoin_units::sequence::Sequence +impl core::cmp::PartialOrd for bitcoin_units::Amount +impl core::cmp::PartialOrd for bitcoin_units::BlockTime +impl core::cmp::PartialOrd for bitcoin_units::FeeRate +impl core::cmp::PartialOrd for bitcoin_units::SignedAmount +impl core::cmp::PartialOrd for bitcoin_units::Weight +impl core::cmp::PartialOrd for bitcoin_units::block::BlockHeight +impl core::cmp::PartialOrd for bitcoin_units::block::BlockHeightInterval +impl core::cmp::PartialOrd for bitcoin_units::block::BlockMtp +impl core::cmp::PartialOrd for bitcoin_units::block::BlockMtpInterval +impl core::cmp::PartialOrd for bitcoin_units::locktime::absolute::Height +impl core::cmp::PartialOrd for bitcoin_units::locktime::absolute::MedianTimePast +impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::cmp::PartialOrd for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::cmp::PartialOrd for bitcoin_units::sequence::Sequence +impl core::convert::AsRef for bitcoin_units::parse_int::ParseIntError +impl core::convert::From<&bitcoin_units::Amount> for bitcoin_units::result::NumOpResult +impl core::convert::From<&bitcoin_units::SignedAmount> for bitcoin_units::result::NumOpResult +impl core::convert::From for bitcoin_units::SignedAmount +impl core::convert::From for bitcoin_units::result::NumOpResult +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::result::NumOpResult +impl core::convert::From for u64 +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::block::BlockHeight +impl core::convert::From for bitcoin_units::locktime::absolute::LockTime +impl core::convert::From for bitcoin_units::block::BlockMtp +impl core::convert::From for bitcoin_units::locktime::absolute::LockTime +impl core::convert::From for bitcoin_units::sequence::Sequence +impl core::convert::From for bitcoin_units::block::BlockMtpInterval +impl core::convert::From for bitcoin_units::locktime::relative::LockTime +impl core::convert::From for bitcoin_units::block::BlockHeightInterval +impl core::convert::From for bitcoin_units::locktime::relative::LockTime +impl core::convert::From for bitcoin_units::parse_int::PrefixedHexError +impl core::convert::From for bitcoin_units::parse_int::UnprefixedHexError +impl core::convert::From for core::num::error::ParseIntError +impl core::convert::From for u32 +impl core::convert::From for bitcoin_units::amount::error::ParseAmountError +impl core::convert::From for bitcoin_units::amount::error::ParseDenominationError +impl core::convert::From for bitcoin_units::amount::error::ParseError +impl core::convert::From for bitcoin_units::parse_int::PrefixedHexError +impl core::convert::From for bitcoin_units::parse_int::UnprefixedHexError +impl core::convert::From for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::From for bitcoin_units::BlockTime +impl core::convert::From for bitcoin_units::block::BlockHeight +impl core::convert::From for bitcoin_units::block::BlockHeightInterval +impl core::convert::From for bitcoin_units::block::BlockMtp +impl core::convert::From for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom<&str> for bitcoin_units::Weight +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockHeight +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockHeightInterval +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockMtp +impl core::convert::TryFrom<&str> for bitcoin_units::block::BlockMtpInterval +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::LockTime +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::convert::TryFrom<&str> for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom for bitcoin_units::Amount +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::Height +impl core::convert::TryFrom for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::convert::TryFrom for bitcoin_units::locktime::absolute::MedianTimePast +impl core::convert::TryFrom for bitcoin_units::locktime::relative::LockTime +impl core::default::Default for bitcoin_units::Amount +impl core::default::Default for bitcoin_units::SignedAmount +impl core::default::Default for bitcoin_units::block::BlockHeightInterval +impl core::default::Default for bitcoin_units::block::BlockMtpInterval +impl core::default::Default for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::default::Default for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::default::Default for bitcoin_units::sequence::Sequence +impl core::fmt::Debug for bitcoin_units::Amount +impl core::fmt::Debug for bitcoin_units::BlockTime +impl core::fmt::Debug for bitcoin_units::FeeRate +impl core::fmt::Debug for bitcoin_units::SignedAmount +impl core::fmt::Debug for bitcoin_units::Weight +impl core::fmt::Debug for bitcoin_units::amount::Denomination +impl core::fmt::Debug for bitcoin_units::amount::Display +impl core::fmt::Debug for bitcoin_units::amount::error::BadPositionError +impl core::fmt::Debug for bitcoin_units::amount::error::InputTooLargeError +impl core::fmt::Debug for bitcoin_units::amount::error::InvalidCharacterError +impl core::fmt::Debug for bitcoin_units::amount::error::MissingDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::MissingDigitsError +impl core::fmt::Debug for bitcoin_units::amount::error::OutOfRangeError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseAmountError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::ParseError +impl core::fmt::Debug for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::fmt::Debug for bitcoin_units::amount::error::TooPreciseError +impl core::fmt::Debug for bitcoin_units::amount::error::UnknownDenominationError +impl core::fmt::Debug for bitcoin_units::block::BlockHeight +impl core::fmt::Debug for bitcoin_units::block::BlockHeightInterval +impl core::fmt::Debug for bitcoin_units::block::BlockMtp +impl core::fmt::Debug for bitcoin_units::block::BlockMtpInterval +impl core::fmt::Debug for bitcoin_units::block::TooBigForRelativeHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::Height +impl core::fmt::Debug for bitcoin_units::locktime::absolute::LockTime +impl core::fmt::Debug for bitcoin_units::locktime::absolute::MedianTimePast +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ConversionError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::fmt::Debug for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::LockTime +impl core::fmt::Debug for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::fmt::Debug for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::fmt::Debug for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::fmt::Debug for bitcoin_units::parse_int::ParseIntError +impl core::fmt::Debug for bitcoin_units::parse_int::PrefixedHexError +impl core::fmt::Debug for bitcoin_units::parse_int::UnprefixedHexError +impl core::fmt::Debug for bitcoin_units::result::MathOp +impl core::fmt::Debug for bitcoin_units::result::NumOpError +impl core::fmt::Debug for bitcoin_units::sequence::Sequence +impl core::fmt::Display for bitcoin_units::Amount +impl core::fmt::Display for bitcoin_units::SignedAmount +impl core::fmt::Display for bitcoin_units::Weight +impl core::fmt::Display for bitcoin_units::amount::Denomination +impl core::fmt::Display for bitcoin_units::amount::Display +impl core::fmt::Display for bitcoin_units::amount::error::BadPositionError +impl core::fmt::Display for bitcoin_units::amount::error::InputTooLargeError +impl core::fmt::Display for bitcoin_units::amount::error::InvalidCharacterError +impl core::fmt::Display for bitcoin_units::amount::error::MissingDigitsError +impl core::fmt::Display for bitcoin_units::amount::error::OutOfRangeError +impl core::fmt::Display for bitcoin_units::amount::error::ParseAmountError +impl core::fmt::Display for bitcoin_units::amount::error::ParseDenominationError +impl core::fmt::Display for bitcoin_units::amount::error::ParseError +impl core::fmt::Display for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::fmt::Display for bitcoin_units::amount::error::TooPreciseError +impl core::fmt::Display for bitcoin_units::amount::error::UnknownDenominationError +impl core::fmt::Display for bitcoin_units::block::BlockHeight +impl core::fmt::Display for bitcoin_units::block::BlockHeightInterval +impl core::fmt::Display for bitcoin_units::block::BlockMtp +impl core::fmt::Display for bitcoin_units::block::BlockMtpInterval +impl core::fmt::Display for bitcoin_units::block::TooBigForRelativeHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::Height +impl core::fmt::Display for bitcoin_units::locktime::absolute::LockTime +impl core::fmt::Display for bitcoin_units::locktime::absolute::MedianTimePast +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ConversionError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::fmt::Display for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::LockTime +impl core::fmt::Display for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::fmt::Display for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::fmt::Display for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::fmt::Display for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::fmt::Display for bitcoin_units::parse_int::ParseIntError +impl core::fmt::Display for bitcoin_units::parse_int::PrefixedHexError +impl core::fmt::Display for bitcoin_units::parse_int::UnprefixedHexError +impl core::fmt::Display for bitcoin_units::result::MathOp +impl core::fmt::Display for bitcoin_units::result::NumOpError +impl core::fmt::Display for bitcoin_units::sequence::Sequence +impl core::fmt::LowerHex for bitcoin_units::sequence::Sequence +impl core::fmt::UpperHex for bitcoin_units::sequence::Sequence +impl core::hash::Hash for bitcoin_units::Amount +impl core::hash::Hash for bitcoin_units::BlockTime +impl core::hash::Hash for bitcoin_units::FeeRate +impl core::hash::Hash for bitcoin_units::SignedAmount +impl core::hash::Hash for bitcoin_units::Weight +impl core::hash::Hash for bitcoin_units::amount::Denomination +impl core::hash::Hash for bitcoin_units::block::BlockHeight +impl core::hash::Hash for bitcoin_units::block::BlockHeightInterval +impl core::hash::Hash for bitcoin_units::block::BlockMtp +impl core::hash::Hash for bitcoin_units::block::BlockMtpInterval +impl core::hash::Hash for bitcoin_units::locktime::absolute::Height +impl core::hash::Hash for bitcoin_units::locktime::absolute::LockTime +impl core::hash::Hash for bitcoin_units::locktime::absolute::MedianTimePast +impl core::hash::Hash for bitcoin_units::locktime::relative::LockTime +impl core::hash::Hash for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::hash::Hash for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::hash::Hash for bitcoin_units::sequence::Sequence +impl core::iter::traits::accum::Sum for bitcoin_units::FeeRate +impl core::iter::traits::accum::Sum for bitcoin_units::Weight +impl core::iter::traits::accum::Sum for bitcoin_units::block::BlockHeightInterval +impl core::iter::traits::accum::Sum for bitcoin_units::block::BlockMtpInterval +impl core::iter::traits::accum::Sum for bitcoin_units::result::NumOpResult +impl core::iter::traits::accum::Sum for bitcoin_units::result::NumOpResult +impl core::marker::Copy for bitcoin_units::Amount +impl core::marker::Copy for bitcoin_units::BlockTime +impl core::marker::Copy for bitcoin_units::FeeRate +impl core::marker::Copy for bitcoin_units::SignedAmount +impl core::marker::Copy for bitcoin_units::Weight +impl core::marker::Copy for bitcoin_units::amount::Denomination +impl core::marker::Copy for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Copy for bitcoin_units::block::BlockHeight +impl core::marker::Copy for bitcoin_units::block::BlockHeightInterval +impl core::marker::Copy for bitcoin_units::block::BlockMtp +impl core::marker::Copy for bitcoin_units::block::BlockMtpInterval +impl core::marker::Copy for bitcoin_units::locktime::absolute::Height +impl core::marker::Copy for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Copy for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Copy for bitcoin_units::locktime::relative::LockTime +impl core::marker::Copy for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Copy for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Copy for bitcoin_units::result::MathOp +impl core::marker::Copy for bitcoin_units::result::NumOpError +impl core::marker::Copy for bitcoin_units::sequence::Sequence +impl core::marker::Freeze for bitcoin_units::Amount +impl core::marker::Freeze for bitcoin_units::BlockTime +impl core::marker::Freeze for bitcoin_units::FeeRate +impl core::marker::Freeze for bitcoin_units::SignedAmount +impl core::marker::Freeze for bitcoin_units::Weight +impl core::marker::Freeze for bitcoin_units::amount::Denomination +impl core::marker::Freeze for bitcoin_units::amount::Display +impl core::marker::Freeze for bitcoin_units::amount::error::BadPositionError +impl core::marker::Freeze for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Freeze for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Freeze for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Freeze for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::ParseError +impl core::marker::Freeze for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Freeze for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Freeze for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Freeze for bitcoin_units::block::BlockHeight +impl core::marker::Freeze for bitcoin_units::block::BlockHeightInterval +impl core::marker::Freeze for bitcoin_units::block::BlockMtp +impl core::marker::Freeze for bitcoin_units::block::BlockMtpInterval +impl core::marker::Freeze for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::Height +impl core::marker::Freeze for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Freeze for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Freeze for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::LockTime +impl core::marker::Freeze for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Freeze for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Freeze for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Freeze for bitcoin_units::parse_int::ParseIntError +impl core::marker::Freeze for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Freeze for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Freeze for bitcoin_units::result::MathOp +impl core::marker::Freeze for bitcoin_units::result::NumOpError +impl core::marker::Freeze for bitcoin_units::sequence::Sequence +impl core::marker::Send for bitcoin_units::Amount +impl core::marker::Send for bitcoin_units::BlockTime +impl core::marker::Send for bitcoin_units::FeeRate +impl core::marker::Send for bitcoin_units::SignedAmount +impl core::marker::Send for bitcoin_units::Weight +impl core::marker::Send for bitcoin_units::amount::Denomination +impl core::marker::Send for bitcoin_units::amount::Display +impl core::marker::Send for bitcoin_units::amount::error::BadPositionError +impl core::marker::Send for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Send for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Send for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Send for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Send for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Send for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Send for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Send for bitcoin_units::amount::error::ParseError +impl core::marker::Send for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Send for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Send for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Send for bitcoin_units::block::BlockHeight +impl core::marker::Send for bitcoin_units::block::BlockHeightInterval +impl core::marker::Send for bitcoin_units::block::BlockMtp +impl core::marker::Send for bitcoin_units::block::BlockMtpInterval +impl core::marker::Send for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::Height +impl core::marker::Send for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Send for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Send for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::LockTime +impl core::marker::Send for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Send for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Send for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Send for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Send for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Send for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Send for bitcoin_units::parse_int::ParseIntError +impl core::marker::Send for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Send for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Send for bitcoin_units::result::MathOp +impl core::marker::Send for bitcoin_units::result::NumOpError +impl core::marker::Send for bitcoin_units::sequence::Sequence +impl core::marker::StructuralPartialEq for bitcoin_units::Amount +impl core::marker::StructuralPartialEq for bitcoin_units::BlockTime +impl core::marker::StructuralPartialEq for bitcoin_units::FeeRate +impl core::marker::StructuralPartialEq for bitcoin_units::SignedAmount +impl core::marker::StructuralPartialEq for bitcoin_units::Weight +impl core::marker::StructuralPartialEq for bitcoin_units::amount::Denomination +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::BadPositionError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseAmountError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::ParseError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::TooPreciseError +impl core::marker::StructuralPartialEq for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeight +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeightInterval +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockMtp +impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockMtpInterval +impl core::marker::StructuralPartialEq for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::Height +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::LockTime +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::LockTime +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::StructuralPartialEq for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::ParseIntError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::StructuralPartialEq for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::StructuralPartialEq for bitcoin_units::result::MathOp +impl core::marker::StructuralPartialEq for bitcoin_units::result::NumOpError +impl core::marker::StructuralPartialEq for bitcoin_units::sequence::Sequence +impl core::marker::Sync for bitcoin_units::Amount +impl core::marker::Sync for bitcoin_units::BlockTime +impl core::marker::Sync for bitcoin_units::FeeRate +impl core::marker::Sync for bitcoin_units::SignedAmount +impl core::marker::Sync for bitcoin_units::Weight +impl core::marker::Sync for bitcoin_units::amount::Denomination +impl core::marker::Sync for bitcoin_units::amount::Display +impl core::marker::Sync for bitcoin_units::amount::error::BadPositionError +impl core::marker::Sync for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Sync for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Sync for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Sync for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Sync for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Sync for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::ParseError +impl core::marker::Sync for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Sync for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Sync for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Sync for bitcoin_units::block::BlockHeight +impl core::marker::Sync for bitcoin_units::block::BlockHeightInterval +impl core::marker::Sync for bitcoin_units::block::BlockMtp +impl core::marker::Sync for bitcoin_units::block::BlockMtpInterval +impl core::marker::Sync for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::Height +impl core::marker::Sync for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Sync for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Sync for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::LockTime +impl core::marker::Sync for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Sync for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Sync for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Sync for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Sync for bitcoin_units::parse_int::ParseIntError +impl core::marker::Sync for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Sync for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Sync for bitcoin_units::result::MathOp +impl core::marker::Sync for bitcoin_units::result::NumOpError +impl core::marker::Sync for bitcoin_units::sequence::Sequence +impl core::marker::Unpin for bitcoin_units::Amount +impl core::marker::Unpin for bitcoin_units::BlockTime +impl core::marker::Unpin for bitcoin_units::FeeRate +impl core::marker::Unpin for bitcoin_units::SignedAmount +impl core::marker::Unpin for bitcoin_units::Weight +impl core::marker::Unpin for bitcoin_units::amount::Denomination +impl core::marker::Unpin for bitcoin_units::amount::Display +impl core::marker::Unpin for bitcoin_units::amount::error::BadPositionError +impl core::marker::Unpin for bitcoin_units::amount::error::InputTooLargeError +impl core::marker::Unpin for bitcoin_units::amount::error::InvalidCharacterError +impl core::marker::Unpin for bitcoin_units::amount::error::MissingDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::MissingDigitsError +impl core::marker::Unpin for bitcoin_units::amount::error::OutOfRangeError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseAmountError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::ParseError +impl core::marker::Unpin for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::marker::Unpin for bitcoin_units::amount::error::TooPreciseError +impl core::marker::Unpin for bitcoin_units::amount::error::UnknownDenominationError +impl core::marker::Unpin for bitcoin_units::block::BlockHeight +impl core::marker::Unpin for bitcoin_units::block::BlockHeightInterval +impl core::marker::Unpin for bitcoin_units::block::BlockMtp +impl core::marker::Unpin for bitcoin_units::block::BlockMtpInterval +impl core::marker::Unpin for bitcoin_units::block::TooBigForRelativeHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::Height +impl core::marker::Unpin for bitcoin_units::locktime::absolute::LockTime +impl core::marker::Unpin for bitcoin_units::locktime::absolute::MedianTimePast +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ConversionError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::marker::Unpin for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::LockTime +impl core::marker::Unpin for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::marker::Unpin for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::marker::Unpin for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::marker::Unpin for bitcoin_units::parse_int::ParseIntError +impl core::marker::Unpin for bitcoin_units::parse_int::PrefixedHexError +impl core::marker::Unpin for bitcoin_units::parse_int::UnprefixedHexError +impl core::marker::Unpin for bitcoin_units::result::MathOp +impl core::marker::Unpin for bitcoin_units::result::NumOpError +impl core::marker::Unpin for bitcoin_units::sequence::Sequence +impl core::ops::arith::Add for bitcoin_units::Amount +impl core::ops::arith::Add for bitcoin_units::FeeRate +impl core::ops::arith::Add for bitcoin_units::SignedAmount +impl core::ops::arith::Add for bitcoin_units::Weight +impl core::ops::arith::Add for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Add<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::Add<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Add<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Add<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Add<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Add<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::SignedAmount +impl core::ops::arith::Add for &bitcoin_units::Amount +impl core::ops::arith::Add for &bitcoin_units::FeeRate +impl core::ops::arith::Add for &bitcoin_units::SignedAmount +impl core::ops::arith::Add for &bitcoin_units::Weight +impl core::ops::arith::Add for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Add for &bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockHeight +impl core::ops::arith::Add for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Add for &bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Add for bitcoin_units::block::BlockMtp +impl core::ops::arith::Add> for &bitcoin_units::Amount +impl core::ops::arith::Add> for bitcoin_units::Amount +impl core::ops::arith::Add> for &bitcoin_units::SignedAmount +impl core::ops::arith::Add> for bitcoin_units::SignedAmount +impl core::ops::arith::AddAssign for bitcoin_units::FeeRate +impl core::ops::arith::AddAssign for bitcoin_units::Weight +impl core::ops::arith::AddAssign for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::AddAssign for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::AddAssign<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::AddAssign<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::AddAssign<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::SignedAmount +impl core::ops::arith::Div for bitcoin_units::Weight +impl core::ops::arith::Div<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::FeeRate> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::FeeRate> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Div<&bitcoin_units::Weight> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Div<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::Amount +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::FeeRate +impl core::ops::arith::Div<&core::num::nonzero::NonZero> for bitcoin_units::Weight +impl core::ops::arith::Div<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Div<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div<&u64> for bitcoin_units::Amount +impl core::ops::arith::Div<&u64> for bitcoin_units::Weight +impl core::ops::arith::Div<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::SignedAmount +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div> for &bitcoin_units::SignedAmount +impl core::ops::arith::Div> for bitcoin_units::SignedAmount +impl core::ops::arith::Div> for &bitcoin_units::Amount +impl core::ops::arith::Div> for &bitcoin_units::FeeRate +impl core::ops::arith::Div> for &bitcoin_units::Weight +impl core::ops::arith::Div> for bitcoin_units::Amount +impl core::ops::arith::Div> for bitcoin_units::FeeRate +impl core::ops::arith::Div> for bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::SignedAmount +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::SignedAmount +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for &bitcoin_units::Amount +impl core::ops::arith::Div for &bitcoin_units::Weight +impl core::ops::arith::Div for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Div for bitcoin_units::Amount +impl core::ops::arith::Div for bitcoin_units::Weight +impl core::ops::arith::Div for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::DivAssign for bitcoin_units::Weight +impl core::ops::arith::DivAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::Amount> for u64 +impl core::ops::arith::Mul<&bitcoin_units::FeeRate> for bitcoin_units::Weight +impl core::ops::arith::Mul<&bitcoin_units::FeeRate> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::SignedAmount> for i64 +impl core::ops::arith::Mul<&bitcoin_units::Weight> for bitcoin_units::FeeRate +impl core::ops::arith::Mul<&bitcoin_units::Weight> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::Weight> for u64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for u64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::Weight +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for i64 +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::FeeRate +impl core::ops::arith::Mul<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Mul<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul<&u64> for bitcoin_units::Amount +impl core::ops::arith::Mul<&u64> for bitcoin_units::Weight +impl core::ops::arith::Mul<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &u64 +impl core::ops::arith::Mul for u64 +impl core::ops::arith::Mul for &bitcoin_units::Weight +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::Weight +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &i64 +impl core::ops::arith::Mul for i64 +impl core::ops::arith::Mul for &bitcoin_units::FeeRate +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &u64 +impl core::ops::arith::Mul for bitcoin_units::FeeRate +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for u64 +impl core::ops::arith::Mul> for &u64 +impl core::ops::arith::Mul> for u64 +impl core::ops::arith::Mul> for &bitcoin_units::Weight +impl core::ops::arith::Mul> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for bitcoin_units::Weight +impl core::ops::arith::Mul> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for &i64 +impl core::ops::arith::Mul> for i64 +impl core::ops::arith::Mul> for &bitcoin_units::FeeRate +impl core::ops::arith::Mul> for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul> for bitcoin_units::FeeRate +impl core::ops::arith::Mul> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &bitcoin_units::SignedAmount +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::SignedAmount +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for &bitcoin_units::Amount +impl core::ops::arith::Mul for &bitcoin_units::Weight +impl core::ops::arith::Mul for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Mul for bitcoin_units::Amount +impl core::ops::arith::Mul for bitcoin_units::Weight +impl core::ops::arith::Mul for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::MulAssign for bitcoin_units::Weight +impl core::ops::arith::MulAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::Neg for bitcoin_units::SignedAmount +impl core::ops::arith::Rem for bitcoin_units::Weight +impl core::ops::arith::Rem<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Rem<&i64> for bitcoin_units::SignedAmount +impl core::ops::arith::Rem<&i64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem<&u64> for bitcoin_units::Amount +impl core::ops::arith::Rem<&u64> for bitcoin_units::Weight +impl core::ops::arith::Rem<&u64> for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for &bitcoin_units::Weight +impl core::ops::arith::Rem for &bitcoin_units::SignedAmount +impl core::ops::arith::Rem for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for bitcoin_units::SignedAmount +impl core::ops::arith::Rem for bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for &bitcoin_units::Amount +impl core::ops::arith::Rem for &bitcoin_units::Weight +impl core::ops::arith::Rem for &bitcoin_units::result::NumOpResult +impl core::ops::arith::Rem for bitcoin_units::Amount +impl core::ops::arith::Rem for bitcoin_units::Weight +impl core::ops::arith::Rem for bitcoin_units::result::NumOpResult +impl core::ops::arith::RemAssign for bitcoin_units::Weight +impl core::ops::arith::Sub for bitcoin_units::Amount +impl core::ops::arith::Sub for bitcoin_units::FeeRate +impl core::ops::arith::Sub for bitcoin_units::SignedAmount +impl core::ops::arith::Sub for bitcoin_units::Weight +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub<&bitcoin_units::Amount> for bitcoin_units::Amount +impl core::ops::arith::Sub<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::Sub<&bitcoin_units::SignedAmount> for bitcoin_units::SignedAmount +impl core::ops::arith::Sub<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeight> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtp> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::Amount +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::SignedAmount +impl core::ops::arith::Sub for &bitcoin_units::Amount +impl core::ops::arith::Sub for &bitcoin_units::FeeRate +impl core::ops::arith::Sub for &bitcoin_units::SignedAmount +impl core::ops::arith::Sub for &bitcoin_units::Weight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockHeight +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub for &bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::Sub for bitcoin_units::block::BlockMtp +impl core::ops::arith::Sub> for &bitcoin_units::Amount +impl core::ops::arith::Sub> for bitcoin_units::Amount +impl core::ops::arith::Sub> for &bitcoin_units::SignedAmount +impl core::ops::arith::Sub> for bitcoin_units::SignedAmount +impl core::ops::arith::SubAssign for bitcoin_units::FeeRate +impl core::ops::arith::SubAssign for bitcoin_units::Weight +impl core::ops::arith::SubAssign for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::SubAssign for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign<&bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl core::ops::arith::SubAssign<&bitcoin_units::Weight> for bitcoin_units::Weight +impl core::ops::arith::SubAssign<&bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl core::ops::arith::SubAssign<&bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::Amount +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::BlockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::FeeRate +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::SignedAmount +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::Weight +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::Denomination +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::Display +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::BadPositionError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::InputTooLargeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::InvalidCharacterError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::MissingDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::MissingDigitsError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::OutOfRangeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseAmountError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::ParseError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::TooPreciseError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::amount::error::UnknownDenominationError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeight +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeightInterval +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockMtp +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockMtpInterval +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::TooBigForRelativeHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::Height +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::LockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::MedianTimePast +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ConversionError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::LockTime +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::ParseIntError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::PrefixedHexError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::parse_int::UnprefixedHexError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::MathOp +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::NumOpError +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::sequence::Sequence +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::Amount +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::BlockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::FeeRate +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::SignedAmount +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::Weight +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::Denomination +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::Display +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::BadPositionError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::InputTooLargeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::InvalidCharacterError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::MissingDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::MissingDigitsError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::OutOfRangeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseAmountError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::ParseError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::PossiblyConfusingDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::TooPreciseError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::amount::error::UnknownDenominationError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeight +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeightInterval +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockMtp +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockMtpInterval +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::TooBigForRelativeHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::Height +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::LockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::MedianTimePast +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ConversionError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::IncompatibleTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ParseHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::error::ParseTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::LockTime +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::NumberOfBlocks +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::DisabledLockTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::InvalidHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::InvalidTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::relative::error::TimeOverflowError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::ParseIntError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::PrefixedHexError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::parse_int::UnprefixedHexError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::MathOp +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::NumOpError +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::sequence::Sequence +impl core::str::traits::FromStr for bitcoin_units::Amount +impl core::str::traits::FromStr for bitcoin_units::SignedAmount +impl core::str::traits::FromStr for bitcoin_units::Weight +impl core::str::traits::FromStr for bitcoin_units::amount::Denomination +impl core::str::traits::FromStr for bitcoin_units::block::BlockHeight +impl core::str::traits::FromStr for bitcoin_units::block::BlockHeightInterval +impl core::str::traits::FromStr for bitcoin_units::block::BlockMtp +impl core::str::traits::FromStr for bitcoin_units::block::BlockMtpInterval +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::Height +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::LockTime +impl core::str::traits::FromStr for bitcoin_units::locktime::absolute::MedianTimePast +impl core::str::traits::FromStr for bitcoin_units::locktime::relative::NumberOf512Seconds +impl core::str::traits::FromStr for bitcoin_units::locktime::relative::NumberOfBlocks +impl<'a, T> core::ops::arith::Add<&'a T> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl<'a, T> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl<'a, T> core::ops::arith::Sub<&'a T> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl<'a, T> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::FeeRate> for bitcoin_units::FeeRate +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::Weight> for bitcoin_units::Weight +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::block::BlockHeightInterval> for bitcoin_units::block::BlockHeightInterval +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::block::BlockMtpInterval> for bitcoin_units::block::BlockMtpInterval +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl<'a> core::iter::traits::accum::Sum<&'a bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Add<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::FeeRate> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Add<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeightInterval +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Add<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtpInterval +impl<'a> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Add<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::FeeRate> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::FeeRate> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a bitcoin_units::Weight> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Div<&'a core::num::nonzero::NonZero> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Div<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Div<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Amount> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::FeeRate> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::FeeRate> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::SignedAmount> for &i64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::Weight> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &u64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &i64 +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Mul<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Mul<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Mul<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Rem<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Rem<&'a i64> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Rem<&'a i64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Rem<&'a u64> for &bitcoin_units::result::NumOpResult +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::Amount> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::FeeRate> for &bitcoin_units::FeeRate +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::SignedAmount> for &bitcoin_units::SignedAmount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::Weight> for &bitcoin_units::Weight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeight> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeight +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockHeightInterval> for &bitcoin_units::block::BlockHeightInterval +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtp> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtp +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::block::BlockMtpInterval> for &bitcoin_units::block::BlockMtpInterval +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::Amount +impl<'a> core::ops::arith::Sub<&'a bitcoin_units::result::NumOpResult> for &bitcoin_units::SignedAmount +impl core::clone::Clone for bitcoin_units::result::NumOpResult +impl core::cmp::Eq for bitcoin_units::result::NumOpResult +impl core::cmp::PartialEq for bitcoin_units::result::NumOpResult +impl bitcoin_units::result::NumOpResult +impl core::fmt::Debug for bitcoin_units::result::NumOpResult +impl core::marker::Copy for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::AddAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl core::ops::arith::SubAssign for bitcoin_units::result::NumOpResult +impl bitcoin_units::result::NumOpResult +impl core::marker::Freeze for bitcoin_units::result::NumOpResult where T: core::marker::Freeze +impl core::marker::Send for bitcoin_units::result::NumOpResult where T: core::marker::Send +impl core::marker::StructuralPartialEq for bitcoin_units::result::NumOpResult +impl core::marker::Sync for bitcoin_units::result::NumOpResult where T: core::marker::Sync +impl core::marker::Unpin for bitcoin_units::result::NumOpResult where T: core::marker::Unpin +impl core::ops::arith::Add for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Add<&T> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Add for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add, Output = bitcoin_units::result::NumOpResult> +impl core::ops::arith::Add> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Add> +impl core::ops::arith::Sub for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub<&T> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub<&bitcoin_units::result::NumOpResult> for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub for bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::ops::arith::Sub> for &bitcoin_units::result::NumOpResult where T: core::marker::Copy + core::ops::arith::Sub> +impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::result::NumOpResult where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::result::NumOpResult where T: core::panic::unwind_safe::UnwindSafe +pub bitcoin_units::NumOpResult::Error(bitcoin_units::result::NumOpError) +pub bitcoin_units::NumOpResult::Valid(T) +pub bitcoin_units::absolute::LockTime::Blocks(bitcoin_units::locktime::absolute::Height) +pub bitcoin_units::absolute::LockTime::Seconds(bitcoin_units::locktime::absolute::MedianTimePast) +pub bitcoin_units::amount::Denomination::Bit +pub bitcoin_units::amount::Denomination::Bitcoin +pub bitcoin_units::amount::Denomination::CentiBitcoin +pub bitcoin_units::amount::Denomination::MicroBitcoin +pub bitcoin_units::amount::Denomination::MilliBitcoin +pub bitcoin_units::amount::Denomination::Satoshi +pub bitcoin_units::amount::ParseDenominationError::PossiblyConfusing(bitcoin_units::amount::error::PossiblyConfusingDenominationError) +pub bitcoin_units::amount::ParseDenominationError::Unknown(bitcoin_units::amount::error::UnknownDenominationError) +pub bitcoin_units::amount::error::ParseDenominationError::PossiblyConfusing(bitcoin_units::amount::error::PossiblyConfusingDenominationError) +pub bitcoin_units::amount::error::ParseDenominationError::Unknown(bitcoin_units::amount::error::UnknownDenominationError) +pub bitcoin_units::locktime::absolute::LockTime::Blocks(bitcoin_units::locktime::absolute::Height) +pub bitcoin_units::locktime::absolute::LockTime::Seconds(bitcoin_units::locktime::absolute::MedianTimePast) +pub bitcoin_units::locktime::relative::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::LockTime::Blocks(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::LockTime::Time(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::LockTime::Blocks(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::LockTime::Time(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::error::IsSatisfiedByError::Blocks(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::error::IsSatisfiedByError::Time(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::relative::error::IsSatisfiedByHeightError::Incompatible(bitcoin_units::locktime::relative::NumberOf512Seconds) +pub bitcoin_units::relative::error::IsSatisfiedByHeightError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidHeightError) +pub bitcoin_units::relative::error::IsSatisfiedByTimeError::Incompatible(bitcoin_units::locktime::relative::NumberOfBlocks) +pub bitcoin_units::relative::error::IsSatisfiedByTimeError::Satisfaction(bitcoin_units::locktime::relative::error::InvalidTimeError) +pub bitcoin_units::result::MathOp::Add +pub bitcoin_units::result::MathOp::Div +pub bitcoin_units::result::MathOp::Mul +pub bitcoin_units::result::MathOp::Neg +pub bitcoin_units::result::MathOp::Rem +pub bitcoin_units::result::MathOp::Sub +pub bitcoin_units::result::NumOpResult::Error(bitcoin_units::result::NumOpError) +pub bitcoin_units::result::NumOpResult::Valid(T) +pub const bitcoin_units::Amount::FIFTY_BTC: Self +pub const bitcoin_units::Amount::MAX: Self +pub const bitcoin_units::Amount::MAX_MONEY: Self +pub const bitcoin_units::Amount::MIN: Self +pub const bitcoin_units::Amount::ONE_BTC: Self +pub const bitcoin_units::Amount::ONE_SAT: Self +pub const bitcoin_units::Amount::SIZE: usize +pub const bitcoin_units::Amount::ZERO: Self +pub const bitcoin_units::FeeRate::BROADCAST_MIN: Self +pub const bitcoin_units::FeeRate::DUST: Self +pub const bitcoin_units::FeeRate::MAX: Self +pub const bitcoin_units::FeeRate::MIN: Self +pub const bitcoin_units::FeeRate::ZERO: Self +pub const bitcoin_units::SignedAmount::FIFTY_BTC: Self +pub const bitcoin_units::SignedAmount::MAX: Self +pub const bitcoin_units::SignedAmount::MAX_MONEY: Self +pub const bitcoin_units::SignedAmount::MIN: Self +pub const bitcoin_units::SignedAmount::ONE_BTC: Self +pub const bitcoin_units::SignedAmount::ONE_SAT: Self +pub const bitcoin_units::SignedAmount::ZERO: Self +pub const bitcoin_units::Weight::MAX: Self +pub const bitcoin_units::Weight::MAX_BLOCK: Self +pub const bitcoin_units::Weight::MIN: Self +pub const bitcoin_units::Weight::MIN_TRANSACTION: Self +pub const bitcoin_units::Weight::WITNESS_SCALE_FACTOR: u64 +pub const bitcoin_units::Weight::ZERO: Self +pub const bitcoin_units::absolute::LOCK_TIME_THRESHOLD: u32 +pub const bitcoin_units::amount::Denomination::BTC: Self +pub const bitcoin_units::amount::Denomination::SAT: Self +pub const bitcoin_units::block::BlockHeight::MAX: Self +pub const bitcoin_units::block::BlockHeight::MIN: Self +pub const bitcoin_units::block::BlockHeight::ZERO: Self +pub const bitcoin_units::block::BlockHeightInterval::MAX: Self +pub const bitcoin_units::block::BlockHeightInterval::MIN: Self +pub const bitcoin_units::block::BlockHeightInterval::ZERO: Self +pub const bitcoin_units::block::BlockMtp::MAX: Self +pub const bitcoin_units::block::BlockMtp::MIN: Self +pub const bitcoin_units::block::BlockMtp::ZERO: Self +pub const bitcoin_units::block::BlockMtpInterval::MAX: Self +pub const bitcoin_units::block::BlockMtpInterval::MIN: Self +pub const bitcoin_units::block::BlockMtpInterval::ZERO: Self +pub const bitcoin_units::locktime::absolute::Height::MAX: Self +pub const bitcoin_units::locktime::absolute::Height::MIN: Self +pub const bitcoin_units::locktime::absolute::Height::ZERO: Self +pub const bitcoin_units::locktime::absolute::LOCK_TIME_THRESHOLD: u32 +pub const bitcoin_units::locktime::absolute::LockTime::SIZE: usize +pub const bitcoin_units::locktime::absolute::LockTime::ZERO: Self +pub const bitcoin_units::locktime::absolute::MedianTimePast::MAX: Self +pub const bitcoin_units::locktime::absolute::MedianTimePast::MIN: Self +pub const bitcoin_units::locktime::relative::LockTime::SIZE: usize +pub const bitcoin_units::locktime::relative::LockTime::ZERO: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::MAX: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::MIN: Self +pub const bitcoin_units::locktime::relative::NumberOf512Seconds::ZERO: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::MAX: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::MIN: Self +pub const bitcoin_units::locktime::relative::NumberOfBlocks::ZERO: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_LOCKTIME_AND_RBF: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_LOCKTIME_NO_RBF: Self +pub const bitcoin_units::sequence::Sequence::ENABLE_RBF_NO_LOCKTIME: Self +pub const bitcoin_units::sequence::Sequence::FINAL: Self +pub const bitcoin_units::sequence::Sequence::MAX: Self +pub const bitcoin_units::sequence::Sequence::SIZE: usize +pub const bitcoin_units::sequence::Sequence::ZERO: Self +pub const bitcoin_units::weight::WITNESS_SCALE_FACTOR: usize +pub const fn bitcoin_units::Amount::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_rem(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Amount::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Amount::div_by_fee_rate_ceil(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_fee_rate_floor(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_weight_ceil(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::div_by_weight_floor(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Amount::from_btc_u16(whole_bitcoin: u16) -> Self +pub const fn bitcoin_units::Amount::from_sat(satoshi: u64) -> core::result::Result +pub const fn bitcoin_units::Amount::from_sat_u32(satoshi: u32) -> Self +pub const fn bitcoin_units::Amount::to_sat(self) -> u64 +pub const fn bitcoin_units::BlockTime::from_u32(t: u32) -> Self +pub const fn bitcoin_units::BlockTime::to_u32(self) -> u32 +pub const fn bitcoin_units::FeeRate::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::FeeRate::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::FeeRate::from_per_kvb(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_per_kwu(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_per_vb(rate: bitcoin_units::Amount) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::from_sat_per_kvb(sat_kvb: u32) -> Self +pub const fn bitcoin_units::FeeRate::from_sat_per_kwu(sat_kwu: u32) -> Self +pub const fn bitcoin_units::FeeRate::from_sat_per_vb(sat_vb: u32) -> Self +pub const fn bitcoin_units::FeeRate::mul_by_weight(self, weight: bitcoin_units::Weight) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::FeeRate::to_fee(self, weight: bitcoin_units::Weight) -> bitcoin_units::Amount +pub const fn bitcoin_units::FeeRate::to_sat_per_kvb_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kvb_floor(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kwu_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_kwu_floor(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_vb_ceil(self) -> u64 +pub const fn bitcoin_units::FeeRate::to_sat_per_vb_floor(self) -> u64 +pub const fn bitcoin_units::SignedAmount::abs(self) -> Self +pub const fn bitcoin_units::SignedAmount::checked_abs(self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_div(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_mul(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_rem(self, rhs: i64) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::SignedAmount::from_btc_i16(whole_bitcoin: i16) -> Self +pub const fn bitcoin_units::SignedAmount::from_sat(satoshi: i64) -> core::result::Result +pub const fn bitcoin_units::SignedAmount::from_sat_i32(satoshi: i32) -> Self +pub const fn bitcoin_units::SignedAmount::to_sat(self) -> i64 +pub const fn bitcoin_units::Weight::checked_add(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_div(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_mul(self, rhs: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::checked_sub(self, rhs: Self) -> core::option::Option +pub const fn bitcoin_units::Weight::from_kwu(wu: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::from_non_witness_data_size(non_witness_size: u64) -> Self +pub const fn bitcoin_units::Weight::from_vb(vb: u64) -> core::option::Option +pub const fn bitcoin_units::Weight::from_vb_unchecked(vb: u64) -> Self +pub const fn bitcoin_units::Weight::from_vb_unwrap(vb: u64) -> Self +pub const fn bitcoin_units::Weight::from_witness_data_size(witness_size: u64) -> Self +pub const fn bitcoin_units::Weight::from_wu(wu: u64) -> Self +pub const fn bitcoin_units::Weight::mul_by_fee_rate(self, fee_rate: bitcoin_units::FeeRate) -> bitcoin_units::result::NumOpResult +pub const fn bitcoin_units::Weight::to_kwu_ceil(self) -> u64 +pub const fn bitcoin_units::Weight::to_kwu_floor(self) -> u64 +pub const fn bitcoin_units::Weight::to_vbytes_ceil(self) -> u64 +pub const fn bitcoin_units::Weight::to_vbytes_floor(self) -> u64 +pub const fn bitcoin_units::Weight::to_wu(self) -> u64 +pub const fn bitcoin_units::absolute::is_block_height(n: u32) -> bool +pub const fn bitcoin_units::absolute::is_block_time(n: u32) -> bool +pub const fn bitcoin_units::block::BlockHeight::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockHeight::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockHeightInterval::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockHeightInterval::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockMtp::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockMtp::to_u32(self) -> u32 +pub const fn bitcoin_units::block::BlockMtpInterval::from_u32(inner: u32) -> Self +pub const fn bitcoin_units::block::BlockMtpInterval::to_relative_mtp_interval_ceil(self) -> core::result::Result +pub const fn bitcoin_units::block::BlockMtpInterval::to_relative_mtp_interval_floor(self) -> core::result::Result +pub const fn bitcoin_units::block::BlockMtpInterval::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::Height::from_u32(n: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::absolute::Height::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::LockTime::is_block_height(self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTime::is_block_time(self) -> bool +pub const fn bitcoin_units::locktime::absolute::LockTime::is_same_unit(self, other: Self) -> bool +pub const fn bitcoin_units::locktime::absolute::MedianTimePast::from_u32(n: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::absolute::MedianTimePast::to_u32(self) -> u32 +pub const fn bitcoin_units::locktime::absolute::is_block_height(n: u32) -> bool +pub const fn bitcoin_units::locktime::absolute::is_block_time(n: u32) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::from_512_second_intervals(intervals: u16) -> Self +pub const fn bitcoin_units::locktime::relative::LockTime::from_height(n: u16) -> Self +pub const fn bitcoin_units::locktime::relative::LockTime::from_seconds_ceil(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::LockTime::from_seconds_floor(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::LockTime::is_block_height(self) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::is_block_time(self) -> bool +pub const fn bitcoin_units::locktime::relative::LockTime::is_same_unit(self, other: Self) -> bool +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_512_second_intervals(intervals: u16) -> Self +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_seconds_ceil(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_seconds_floor(seconds: u32) -> core::result::Result +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_512_second_intervals(self) -> u16 +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOf512Seconds::to_seconds(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::from_height(blocks: u16) -> Self +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::to_consensus_u32(self) -> u32 +pub const fn bitcoin_units::locktime::relative::NumberOfBlocks::to_height(self) -> u16 +pub const fn bitcoin_units::sequence::Sequence::to_consensus_u32(self) -> u32 +pub enum bitcoin_units::NumOpResult +pub enum bitcoin_units::absolute::LockTime +pub enum bitcoin_units::locktime::absolute::LockTime +pub enum bitcoin_units::locktime::relative::IsSatisfiedByError +pub enum bitcoin_units::locktime::relative::IsSatisfiedByHeightError +pub enum bitcoin_units::locktime::relative::IsSatisfiedByTimeError +pub enum bitcoin_units::locktime::relative::LockTime +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByError +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +pub enum bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +pub enum bitcoin_units::relative::IsSatisfiedByError +pub enum bitcoin_units::relative::IsSatisfiedByHeightError +pub enum bitcoin_units::relative::IsSatisfiedByTimeError +pub enum bitcoin_units::relative::LockTime +pub enum bitcoin_units::relative::error::IsSatisfiedByError +pub enum bitcoin_units::relative::error::IsSatisfiedByHeightError +pub enum bitcoin_units::relative::error::IsSatisfiedByTimeError +pub enum bitcoin_units::result::NumOpResult +pub fn &bitcoin_units::Amount::add(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Amount::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Amount::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &bitcoin_units::Amount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::add(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::add(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::FeeRate::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::FeeRate::sub(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::FeeRate::sub(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &core::num::nonzero::NonZeroI64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: core::num::nonzero::NonZeroI64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::mul(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::mul(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::rem(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::rem(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::add(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::add(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn &bitcoin_units::Weight::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::Weight::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::Weight::sub(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::Weight::sub(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeight) -> Self::Output +pub fn &bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockHeightInterval::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtp) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtp) -> Self::Output +pub fn &bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::block::BlockMtpInterval::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: &T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: &T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: T) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: &u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: u64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::div(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: &i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::rem(self, rhs: i64) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn &bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &i64::mul(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn &i64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &i64::mul(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn &i64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn &u64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn &u64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::clone(&self) -> bitcoin_units::Amount +pub fn bitcoin_units::Amount::cmp(&self, other: &bitcoin_units::Amount) -> core::cmp::Ordering +pub fn bitcoin_units::Amount::default() -> Self +pub fn bitcoin_units::Amount::display_dynamic(self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::Amount::display_in(self, denomination: bitcoin_units::amount::Denomination) -> bitcoin_units::amount::Display +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Amount::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Amount::eq(&self, other: &bitcoin_units::Amount) -> bool +pub fn bitcoin_units::Amount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::Amount::from_int_btc>(whole_bitcoin: T) -> Self +pub fn bitcoin_units::Amount::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::Amount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::Amount::from_str_with_denomination(s: &str) -> core::result::Result +pub fn bitcoin_units::Amount::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::Amount::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Amount::partial_cmp(&self, other: &bitcoin_units::Amount) -> core::option::Option +pub fn bitcoin_units::Amount::rem(self, modulus: u64) -> Self::Output +pub fn bitcoin_units::Amount::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Amount::signed_sub(self, rhs: Self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn bitcoin_units::Amount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Amount::to_signed(self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::Amount::try_from(value: bitcoin_units::SignedAmount) -> core::result::Result +pub fn bitcoin_units::BlockTime::clone(&self) -> bitcoin_units::BlockTime +pub fn bitcoin_units::BlockTime::cmp(&self, other: &bitcoin_units::BlockTime) -> core::cmp::Ordering +pub fn bitcoin_units::BlockTime::eq(&self, other: &bitcoin_units::BlockTime) -> bool +pub fn bitcoin_units::BlockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::BlockTime::from(t: u32) -> Self +pub fn bitcoin_units::BlockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::BlockTime::partial_cmp(&self, other: &bitcoin_units::BlockTime) -> core::option::Option +pub fn bitcoin_units::FeeRate::add(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::add(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::add_assign(&mut self, rhs: &bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::add_assign(&mut self, rhs: bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::clone(&self) -> bitcoin_units::FeeRate +pub fn bitcoin_units::FeeRate::cmp(&self, other: &bitcoin_units::FeeRate) -> core::cmp::Ordering +pub fn bitcoin_units::FeeRate::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::FeeRate::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::FeeRate::eq(&self, other: &bitcoin_units::FeeRate) -> bool +pub fn bitcoin_units::FeeRate::fee_vb(self, vb: u64) -> core::option::Option +pub fn bitcoin_units::FeeRate::fee_wu(self, weight: bitcoin_units::Weight) -> core::option::Option +pub fn bitcoin_units::FeeRate::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::FeeRate::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::FeeRate::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::FeeRate::partial_cmp(&self, other: &bitcoin_units::FeeRate) -> core::option::Option +pub fn bitcoin_units::FeeRate::sub(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::sub(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::FeeRate::sub_assign(&mut self, rhs: &bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::sub_assign(&mut self, rhs: bitcoin_units::FeeRate) +pub fn bitcoin_units::FeeRate::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::FeeRate::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::add(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::clone(&self) -> bitcoin_units::SignedAmount +pub fn bitcoin_units::SignedAmount::cmp(&self, other: &bitcoin_units::SignedAmount) -> core::cmp::Ordering +pub fn bitcoin_units::SignedAmount::default() -> Self +pub fn bitcoin_units::SignedAmount::display_dynamic(self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::SignedAmount::display_in(self, denomination: bitcoin_units::amount::Denomination) -> bitcoin_units::amount::Display +pub fn bitcoin_units::SignedAmount::div(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: &core::num::nonzero::NonZeroI64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: core::num::nonzero::NonZeroI64) -> Self::Output +pub fn bitcoin_units::SignedAmount::div(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::eq(&self, other: &bitcoin_units::SignedAmount) -> bool +pub fn bitcoin_units::SignedAmount::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::SignedAmount::from(value: bitcoin_units::Amount) -> Self +pub fn bitcoin_units::SignedAmount::from_int_btc>(whole_bitcoin: T) -> Self +pub fn bitcoin_units::SignedAmount::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_str_in(s: &str, denom: bitcoin_units::amount::Denomination) -> core::result::Result +pub fn bitcoin_units::SignedAmount::from_str_with_denomination(s: &str) -> core::result::Result +pub fn bitcoin_units::SignedAmount::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::SignedAmount::is_negative(self) -> bool +pub fn bitcoin_units::SignedAmount::is_positive(self) -> bool +pub fn bitcoin_units::SignedAmount::mul(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::mul(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::neg(self) -> Self::Output +pub fn bitcoin_units::SignedAmount::partial_cmp(&self, other: &bitcoin_units::SignedAmount) -> core::option::Option +pub fn bitcoin_units::SignedAmount::positive_sub(self, rhs: Self) -> core::option::Option +pub fn bitcoin_units::SignedAmount::rem(self, modulus: i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::rem(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::SignedAmount::signum(self) -> i64 +pub fn bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn bitcoin_units::SignedAmount::sub(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::SignedAmount::to_unsigned(self) -> core::result::Result +pub fn bitcoin_units::SignedAmount::unsigned_abs(self) -> bitcoin_units::Amount +pub fn bitcoin_units::Weight::add(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::add(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::add_assign(&mut self, rhs: &bitcoin_units::Weight) +pub fn bitcoin_units::Weight::add_assign(&mut self, rhs: bitcoin_units::Weight) +pub fn bitcoin_units::Weight::clone(&self) -> bitcoin_units::Weight +pub fn bitcoin_units::Weight::cmp(&self, other: &bitcoin_units::Weight) -> core::cmp::Ordering +pub fn bitcoin_units::Weight::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: &core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: core::num::nonzero::NonZeroU64) -> Self::Output +pub fn bitcoin_units::Weight::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::div_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::eq(&self, other: &bitcoin_units::Weight) -> bool +pub fn bitcoin_units::Weight::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::Weight::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::Weight::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::Weight::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::mul_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::partial_cmp(&self, other: &bitcoin_units::Weight) -> core::option::Option +pub fn bitcoin_units::Weight::rem(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::rem(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::Weight::rem_assign(&mut self, rhs: u64) +pub fn bitcoin_units::Weight::sub(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::sub(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::Weight::sub_assign(&mut self, rhs: &bitcoin_units::Weight) +pub fn bitcoin_units::Weight::sub_assign(&mut self, rhs: bitcoin_units::Weight) +pub fn bitcoin_units::Weight::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::Weight::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::Weight::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::amount::Denomination::clone(&self) -> bitcoin_units::amount::Denomination +pub fn bitcoin_units::amount::Denomination::eq(&self, other: &bitcoin_units::amount::Denomination) -> bool +pub fn bitcoin_units::amount::Denomination::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::Denomination::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::amount::Denomination::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::amount::Display::clone(&self) -> bitcoin_units::amount::Display +pub fn bitcoin_units::amount::Display::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::Display::show_denomination(self) -> Self +pub fn bitcoin_units::amount::error::BadPositionError::clone(&self) -> bitcoin_units::amount::error::BadPositionError +pub fn bitcoin_units::amount::error::BadPositionError::eq(&self, other: &bitcoin_units::amount::error::BadPositionError) -> bool +pub fn bitcoin_units::amount::error::BadPositionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::InputTooLargeError::clone(&self) -> bitcoin_units::amount::error::InputTooLargeError +pub fn bitcoin_units::amount::error::InputTooLargeError::eq(&self, other: &bitcoin_units::amount::error::InputTooLargeError) -> bool +pub fn bitcoin_units::amount::error::InputTooLargeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::InvalidCharacterError::clone(&self) -> bitcoin_units::amount::error::InvalidCharacterError +pub fn bitcoin_units::amount::error::InvalidCharacterError::eq(&self, other: &bitcoin_units::amount::error::InvalidCharacterError) -> bool +pub fn bitcoin_units::amount::error::InvalidCharacterError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::MissingDenominationError::clone(&self) -> bitcoin_units::amount::error::MissingDenominationError +pub fn bitcoin_units::amount::error::MissingDenominationError::eq(&self, other: &bitcoin_units::amount::error::MissingDenominationError) -> bool +pub fn bitcoin_units::amount::error::MissingDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::MissingDigitsError::clone(&self) -> bitcoin_units::amount::error::MissingDigitsError +pub fn bitcoin_units::amount::error::MissingDigitsError::eq(&self, other: &bitcoin_units::amount::error::MissingDigitsError) -> bool +pub fn bitcoin_units::amount::error::MissingDigitsError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::OutOfRangeError::clone(&self) -> bitcoin_units::amount::error::OutOfRangeError +pub fn bitcoin_units::amount::error::OutOfRangeError::eq(&self, other: &bitcoin_units::amount::error::OutOfRangeError) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::OutOfRangeError::is_above_max(self) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::is_below_min(self) -> bool +pub fn bitcoin_units::amount::error::OutOfRangeError::valid_range(self) -> (i64, u64) +pub fn bitcoin_units::amount::error::ParseAmountError::clone(&self) -> bitcoin_units::amount::error::ParseAmountError +pub fn bitcoin_units::amount::error::ParseAmountError::eq(&self, other: &bitcoin_units::amount::error::ParseAmountError) -> bool +pub fn bitcoin_units::amount::error::ParseAmountError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseAmountError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::BadPositionError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::InputTooLargeError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::InvalidCharacterError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::MissingDigitsError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::OutOfRangeError) -> Self +pub fn bitcoin_units::amount::error::ParseAmountError::from(value: bitcoin_units::amount::error::TooPreciseError) -> Self +pub fn bitcoin_units::amount::error::ParseDenominationError::clone(&self) -> bitcoin_units::amount::error::ParseDenominationError +pub fn bitcoin_units::amount::error::ParseDenominationError::eq(&self, other: &bitcoin_units::amount::error::ParseDenominationError) -> bool +pub fn bitcoin_units::amount::error::ParseDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseDenominationError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::ParseError::clone(&self) -> bitcoin_units::amount::error::ParseError +pub fn bitcoin_units::amount::error::ParseError::eq(&self, other: &bitcoin_units::amount::error::ParseError) -> bool +pub fn bitcoin_units::amount::error::ParseError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::BadPositionError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::InputTooLargeError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::InvalidCharacterError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::MissingDigitsError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::OutOfRangeError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::ParseAmountError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::ParseDenominationError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(e: bitcoin_units::amount::error::TooPreciseError) -> Self +pub fn bitcoin_units::amount::error::ParseError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::clone(&self) -> bitcoin_units::amount::error::PossiblyConfusingDenominationError +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::eq(&self, other: &bitcoin_units::amount::error::PossiblyConfusingDenominationError) -> bool +pub fn bitcoin_units::amount::error::PossiblyConfusingDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::TooPreciseError::clone(&self) -> bitcoin_units::amount::error::TooPreciseError +pub fn bitcoin_units::amount::error::TooPreciseError::eq(&self, other: &bitcoin_units::amount::error::TooPreciseError) -> bool +pub fn bitcoin_units::amount::error::TooPreciseError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::amount::error::UnknownDenominationError::clone(&self) -> bitcoin_units::amount::error::UnknownDenominationError +pub fn bitcoin_units::amount::error::UnknownDenominationError::eq(&self, other: &bitcoin_units::amount::error::UnknownDenominationError) -> bool +pub fn bitcoin_units::amount::error::UnknownDenominationError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeight::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::checked_add(self, other: bitcoin_units::block::BlockHeightInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::clone(&self) -> bitcoin_units::block::BlockHeight +pub fn bitcoin_units::block::BlockHeight::cmp(&self, other: &bitcoin_units::block::BlockHeight) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockHeight::eq(&self, other: &bitcoin_units::block::BlockHeight) -> bool +pub fn bitcoin_units::block::BlockHeight::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeight::from(h: bitcoin_units::locktime::absolute::Height) -> Self +pub fn bitcoin_units::block::BlockHeight::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockHeight::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeight::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockHeight::partial_cmp(&self, other: &bitcoin_units::block::BlockHeight) -> core::option::Option +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeight) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeight) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeight::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::add(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::add(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::add_assign(&mut self, rhs: &bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::add_assign(&mut self, rhs: bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::checked_add(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::clone(&self) -> bitcoin_units::block::BlockHeightInterval +pub fn bitcoin_units::block::BlockHeightInterval::cmp(&self, other: &bitcoin_units::block::BlockHeightInterval) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockHeightInterval::default() -> bitcoin_units::block::BlockHeightInterval +pub fn bitcoin_units::block::BlockHeightInterval::eq(&self, other: &bitcoin_units::block::BlockHeightInterval) -> bool +pub fn bitcoin_units::block::BlockHeightInterval::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockHeightInterval::from(h: bitcoin_units::locktime::relative::NumberOfBlocks) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockHeightInterval::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockHeightInterval::partial_cmp(&self, other: &bitcoin_units::block::BlockHeightInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockHeightInterval::sub(self, rhs: &bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::sub(self, rhs: bitcoin_units::block::BlockHeightInterval) -> Self::Output +pub fn bitcoin_units::block::BlockHeightInterval::sub_assign(&mut self, rhs: &bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::sub_assign(&mut self, rhs: bitcoin_units::block::BlockHeightInterval) +pub fn bitcoin_units::block::BlockHeightInterval::sum>(iter: I) -> Self +pub fn bitcoin_units::block::BlockHeightInterval::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::block::BlockHeightInterval::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::checked_add(self, other: bitcoin_units::block::BlockMtpInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::clone(&self) -> bitcoin_units::block::BlockMtp +pub fn bitcoin_units::block::BlockMtp::cmp(&self, other: &bitcoin_units::block::BlockMtp) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockMtp::eq(&self, other: &bitcoin_units::block::BlockMtp) -> bool +pub fn bitcoin_units::block::BlockMtp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockMtp::from(h: bitcoin_units::locktime::absolute::MedianTimePast) -> Self +pub fn bitcoin_units::block::BlockMtp::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockMtp::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtp::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockMtp::new(timestamps: [bitcoin_units::BlockTime; 11]) -> Self +pub fn bitcoin_units::block::BlockMtp::partial_cmp(&self, other: &bitcoin_units::block::BlockMtp) -> core::option::Option +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtp) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtp) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtp::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::add(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::add(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::add_assign(&mut self, rhs: &bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::add_assign(&mut self, rhs: bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::checked_add(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::checked_sub(self, other: Self) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::clone(&self) -> bitcoin_units::block::BlockMtpInterval +pub fn bitcoin_units::block::BlockMtpInterval::cmp(&self, other: &bitcoin_units::block::BlockMtpInterval) -> core::cmp::Ordering +pub fn bitcoin_units::block::BlockMtpInterval::default() -> bitcoin_units::block::BlockMtpInterval +pub fn bitcoin_units::block::BlockMtpInterval::eq(&self, other: &bitcoin_units::block::BlockMtpInterval) -> bool +pub fn bitcoin_units::block::BlockMtpInterval::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::block::BlockMtpInterval::from(h: bitcoin_units::locktime::relative::NumberOf512Seconds) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::from(inner: u32) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::block::BlockMtpInterval::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::block::BlockMtpInterval::partial_cmp(&self, other: &bitcoin_units::block::BlockMtpInterval) -> core::option::Option +pub fn bitcoin_units::block::BlockMtpInterval::sub(self, rhs: &bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::sub(self, rhs: bitcoin_units::block::BlockMtpInterval) -> Self::Output +pub fn bitcoin_units::block::BlockMtpInterval::sub_assign(&mut self, rhs: &bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::sub_assign(&mut self, rhs: bitcoin_units::block::BlockMtpInterval) +pub fn bitcoin_units::block::BlockMtpInterval::sum>(iter: I) -> Self +pub fn bitcoin_units::block::BlockMtpInterval::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::block::BlockMtpInterval::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::block::TooBigForRelativeHeightError::clone(&self) -> bitcoin_units::block::TooBigForRelativeHeightError +pub fn bitcoin_units::block::TooBigForRelativeHeightError::eq(&self, other: &bitcoin_units::block::TooBigForRelativeHeightError) -> bool +pub fn bitcoin_units::block::TooBigForRelativeHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::Height::clone(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::Height::cmp(&self, other: &bitcoin_units::locktime::absolute::Height) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::absolute::Height::eq(&self, other: &bitcoin_units::locktime::absolute::Height) -> bool +pub fn bitcoin_units::locktime::absolute::Height::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::Height::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::Height::is_satisfied_by(self, height: Self) -> bool +pub fn bitcoin_units::locktime::absolute::Height::partial_cmp(&self, other: &bitcoin_units::locktime::absolute::Height) -> core::option::Option +pub fn bitcoin_units::locktime::absolute::Height::try_from(h: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::Height::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::clone(&self) -> bitcoin_units::locktime::absolute::LockTime +pub fn bitcoin_units::locktime::absolute::LockTime::eq(&self, other: &bitcoin_units::locktime::absolute::LockTime) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from(h: bitcoin_units::locktime::absolute::Height) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from(t: bitcoin_units::locktime::absolute::MedianTimePast) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from_consensus(n: u32) -> Self +pub fn bitcoin_units::locktime::absolute::LockTime::from_height(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_mtp(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::from_unprefixed_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::LockTime::is_implied_by(self, other: Self) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by(self, height: bitcoin_units::locktime::absolute::Height, mtp: bitcoin_units::locktime::absolute::MedianTimePast) -> bool +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by_height(self, height: bitcoin_units::locktime::absolute::Height) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::is_satisfied_by_time(self, mtp: bitcoin_units::locktime::absolute::MedianTimePast) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::LockTime::to_consensus_u32(self) -> u32 +pub fn bitcoin_units::locktime::absolute::LockTime::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::clone(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::MedianTimePast::cmp(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::absolute::MedianTimePast::eq(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> bool +pub fn bitcoin_units::locktime::absolute::MedianTimePast::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::absolute::MedianTimePast::is_satisfied_by(self, time: Self) -> bool +pub fn bitcoin_units::locktime::absolute::MedianTimePast::new(timestamps: [bitcoin_units::BlockTime; 11]) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::partial_cmp(&self, other: &bitcoin_units::locktime::absolute::MedianTimePast) -> core::option::Option +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(h: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::MedianTimePast::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::absolute::error::ConversionError::clone(&self) -> bitcoin_units::locktime::absolute::error::ConversionError +pub fn bitcoin_units::locktime::absolute::error::ConversionError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ConversionError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ConversionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::clone(&self) -> bitcoin_units::locktime::absolute::error::IncompatibleHeightError +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::eq(&self, other: &bitcoin_units::locktime::absolute::error::IncompatibleHeightError) -> bool +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::incompatible(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::error::IncompatibleHeightError::lock(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::clone(&self) -> bitcoin_units::locktime::absolute::error::IncompatibleTimeError +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::IncompatibleTimeError) -> bool +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::incompatible(&self) -> bitcoin_units::locktime::absolute::MedianTimePast +pub fn bitcoin_units::locktime::absolute::error::IncompatibleTimeError::lock(&self) -> bitcoin_units::locktime::absolute::Height +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::clone(&self) -> bitcoin_units::locktime::absolute::error::ParseHeightError +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseHeightError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ParseHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::clone(&self) -> bitcoin_units::locktime::absolute::error::ParseTimeError +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::eq(&self, other: &bitcoin_units::locktime::absolute::error::ParseTimeError) -> bool +pub fn bitcoin_units::locktime::absolute::error::ParseTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::LockTime::clone(&self) -> bitcoin_units::locktime::relative::LockTime +pub fn bitcoin_units::locktime::relative::LockTime::eq(&self, other: &bitcoin_units::locktime::relative::LockTime) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::LockTime::from(h: bitcoin_units::locktime::relative::NumberOfBlocks) -> Self +pub fn bitcoin_units::locktime::relative::LockTime::from(t: bitcoin_units::locktime::relative::NumberOf512Seconds) -> Self +pub fn bitcoin_units::locktime::relative::LockTime::from_consensus(n: u32) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::from_sequence(n: bitcoin_units::sequence::Sequence) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::LockTime::is_implied_by(self, other: Self) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::is_implied_by_sequence(self, other: bitcoin_units::sequence::Sequence) -> bool +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by(self, chain_tip_height: bitcoin_units::block::BlockHeight, chain_tip_mtp: bitcoin_units::block::BlockMtp, utxo_mined_at_height: bitcoin_units::block::BlockHeight, utxo_mined_at_mtp: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by_height(self, chain_tip: bitcoin_units::block::BlockHeight, utxo_mined_at: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::is_satisfied_by_time(self, chain_tip: bitcoin_units::block::BlockMtp, utxo_mined_at: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::LockTime::to_consensus_u32(self) -> u32 +pub fn bitcoin_units::locktime::relative::LockTime::to_sequence(self) -> bitcoin_units::sequence::Sequence +pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::clone(&self) -> bitcoin_units::locktime::relative::NumberOf512Seconds +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::cmp(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::default() -> bitcoin_units::locktime::relative::NumberOf512Seconds +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::eq(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> bool +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::is_satisfied_by(self, chain_tip: bitcoin_units::block::BlockMtp, utxo_mined_at: bitcoin_units::block::BlockMtp) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::partial_cmp(&self, other: &bitcoin_units::locktime::relative::NumberOf512Seconds) -> core::option::Option +pub fn bitcoin_units::locktime::relative::NumberOf512Seconds::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::clone(&self) -> bitcoin_units::locktime::relative::NumberOfBlocks +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::cmp(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> core::cmp::Ordering +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::default() -> bitcoin_units::locktime::relative::NumberOfBlocks +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::eq(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> bool +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::from(value: u16) -> Self +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::is_satisfied_by(self, chain_tip: bitcoin_units::block::BlockHeight, utxo_mined_at: bitcoin_units::block::BlockHeight) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::partial_cmp(&self, other: &bitcoin_units::locktime::relative::NumberOfBlocks) -> core::option::Option +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(h: bitcoin_units::block::BlockHeightInterval) -> core::result::Result +pub fn bitcoin_units::locktime::relative::NumberOfBlocks::try_from(s: &str) -> core::result::Result +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::DisabledLockTimeError +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::disabled_locktime_value(&self) -> u32 +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::DisabledLockTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::DisabledLockTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::clone(&self) -> bitcoin_units::locktime::relative::error::InvalidHeightError +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::eq(&self, other: &bitcoin_units::locktime::relative::error::InvalidHeightError) -> bool +pub fn bitcoin_units::locktime::relative::error::InvalidHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::InvalidTimeError +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::InvalidTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::InvalidTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByHeightError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::clone(&self) -> bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::eq(&self, other: &bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError) -> bool +pub fn bitcoin_units::locktime::relative::error::IsSatisfiedByTimeError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::clone(&self) -> bitcoin_units::locktime::relative::error::TimeOverflowError +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::eq(&self, other: &bitcoin_units::locktime::relative::error::TimeOverflowError) -> bool +pub fn bitcoin_units::locktime::relative::error::TimeOverflowError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::ParseIntError::as_ref(&self) -> &core::num::error::ParseIntError +pub fn bitcoin_units::parse_int::ParseIntError::clone(&self) -> bitcoin_units::parse_int::ParseIntError +pub fn bitcoin_units::parse_int::ParseIntError::eq(&self, other: &bitcoin_units::parse_int::ParseIntError) -> bool +pub fn bitcoin_units::parse_int::ParseIntError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::PrefixedHexError::clone(&self) -> bitcoin_units::parse_int::PrefixedHexError +pub fn bitcoin_units::parse_int::PrefixedHexError::eq(&self, other: &bitcoin_units::parse_int::PrefixedHexError) -> bool +pub fn bitcoin_units::parse_int::PrefixedHexError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::PrefixedHexError::from(e: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn bitcoin_units::parse_int::PrefixedHexError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::parse_int::UnprefixedHexError::clone(&self) -> bitcoin_units::parse_int::UnprefixedHexError +pub fn bitcoin_units::parse_int::UnprefixedHexError::eq(&self, other: &bitcoin_units::parse_int::UnprefixedHexError) -> bool +pub fn bitcoin_units::parse_int::UnprefixedHexError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::parse_int::UnprefixedHexError::from(e: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn bitcoin_units::parse_int::UnprefixedHexError::from(never: core::convert::Infallible) -> Self +pub fn bitcoin_units::parse_int::hex_check_unprefixed(s: &str) -> core::result::Result<&str, bitcoin_units::parse_int::UnprefixedHexError> +pub fn bitcoin_units::parse_int::hex_remove_prefix(s: &str) -> core::result::Result<&str, bitcoin_units::parse_int::PrefixedHexError> +pub fn bitcoin_units::parse_int::hex_u128(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_prefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_unchecked(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u128_unprefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_prefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_unchecked(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::hex_u32_unprefixed(s: &str) -> core::result::Result +pub fn bitcoin_units::parse_int::int_from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::result::MathOp::clone(&self) -> bitcoin_units::result::MathOp +pub fn bitcoin_units::result::MathOp::eq(&self, other: &bitcoin_units::result::MathOp) -> bool +pub fn bitcoin_units::result::MathOp::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::MathOp::is_addition(self) -> bool +pub fn bitcoin_units::result::MathOp::is_div_by_zero(self) -> bool +pub fn bitcoin_units::result::MathOp::is_multiplication(self) -> bool +pub fn bitcoin_units::result::MathOp::is_negation(self) -> bool +pub fn bitcoin_units::result::MathOp::is_overflow(self) -> bool +pub fn bitcoin_units::result::MathOp::is_subtraction(self) -> bool +pub fn bitcoin_units::result::NumOpError::clone(&self) -> bitcoin_units::result::NumOpError +pub fn bitcoin_units::result::NumOpError::eq(&self, other: &bitcoin_units::result::NumOpError) -> bool +pub fn bitcoin_units::result::NumOpError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::NumOpError::is_div_by_zero(self) -> bool +pub fn bitcoin_units::result::NumOpError::is_overflow(self) -> bool +pub fn bitcoin_units::result::NumOpError::operation(self) -> bitcoin_units::result::MathOp +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: &T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: Self) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add(self, rhs: T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: T) +pub fn bitcoin_units::result::NumOpResult::and_then(self, op: F) -> Self where F: core::ops::function::FnOnce(T) -> Self +pub fn bitcoin_units::result::NumOpResult::clone(&self) -> bitcoin_units::result::NumOpResult +pub fn bitcoin_units::result::NumOpResult::eq(&self, other: &bitcoin_units::result::NumOpResult) -> bool +pub fn bitcoin_units::result::NumOpResult::expect(self, msg: &str) -> T +pub fn bitcoin_units::result::NumOpResult::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::result::NumOpResult::into_result(self) -> core::result::Result +pub fn bitcoin_units::result::NumOpResult::is_error(&self) -> bool +pub fn bitcoin_units::result::NumOpResult::is_valid(&self) -> bool +pub fn bitcoin_units::result::NumOpResult::map U>(self, op: F) -> bitcoin_units::result::NumOpResult +pub fn bitcoin_units::result::NumOpResult::ok(self) -> core::option::Option +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: &T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: Self) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub(self, rhs: T) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: T) +pub fn bitcoin_units::result::NumOpResult::unwrap(self) -> T +pub fn bitcoin_units::result::NumOpResult::unwrap_err(self) -> bitcoin_units::result::NumOpError +pub fn bitcoin_units::result::NumOpResult::unwrap_or(self, default: T) -> T +pub fn bitcoin_units::result::NumOpResult::unwrap_or_else(self, f: F) -> T where F: core::ops::function::FnOnce() -> T +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: bitcoin_units::Amount) +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: &u64) +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: u64) +pub fn bitcoin_units::result::NumOpResult::from(a: &bitcoin_units::Amount) -> Self +pub fn bitcoin_units::result::NumOpResult::from(a: bitcoin_units::Amount) -> Self +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: &u64) +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: u64) +pub fn bitcoin_units::result::NumOpResult::rem(self, modulus: u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::rem(self, rhs: &u64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: bitcoin_units::Amount) +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::add_assign(&mut self, rhs: bitcoin_units::SignedAmount) +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: &i64) +pub fn bitcoin_units::result::NumOpResult::div_assign(&mut self, rhs: i64) +pub fn bitcoin_units::result::NumOpResult::from(a: &bitcoin_units::SignedAmount) -> Self +pub fn bitcoin_units::result::NumOpResult::from(a: bitcoin_units::SignedAmount) -> Self +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: &i64) +pub fn bitcoin_units::result::NumOpResult::mul_assign(&mut self, rhs: i64) +pub fn bitcoin_units::result::NumOpResult::rem(self, modulus: i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::rem(self, rhs: &i64) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: Self) +pub fn bitcoin_units::result::NumOpResult::sub_assign(&mut self, rhs: bitcoin_units::SignedAmount) +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::sum(iter: I) -> Self where I: core::iter::traits::iterator::Iterator +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::FeeRate) -> Self::Output +pub fn bitcoin_units::result::NumOpResult::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn bitcoin_units::sequence::Sequence::clone(&self) -> bitcoin_units::sequence::Sequence +pub fn bitcoin_units::sequence::Sequence::cmp(&self, other: &bitcoin_units::sequence::Sequence) -> core::cmp::Ordering +pub fn bitcoin_units::sequence::Sequence::default() -> Self +pub fn bitcoin_units::sequence::Sequence::enables_absolute_lock_time(self) -> bool +pub fn bitcoin_units::sequence::Sequence::eq(&self, other: &bitcoin_units::sequence::Sequence) -> bool +pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn bitcoin_units::sequence::Sequence::from(lt: bitcoin_units::locktime::relative::LockTime) -> Self +pub fn bitcoin_units::sequence::Sequence::from_512_second_intervals(intervals: u16) -> Self +pub fn bitcoin_units::sequence::Sequence::from_consensus(n: u32) -> Self +pub fn bitcoin_units::sequence::Sequence::from_height(height: u16) -> Self +pub fn bitcoin_units::sequence::Sequence::from_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_seconds_ceil(seconds: u32) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_seconds_floor(seconds: u32) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::from_unprefixed_hex(s: &str) -> core::result::Result +pub fn bitcoin_units::sequence::Sequence::hash<__H: core::hash::Hasher>(&self, state: &mut __H) +pub fn bitcoin_units::sequence::Sequence::is_final(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_height_locked(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_rbf(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_relative_lock_time(self) -> bool +pub fn bitcoin_units::sequence::Sequence::is_time_locked(self) -> bool +pub fn bitcoin_units::sequence::Sequence::partial_cmp(&self, other: &bitcoin_units::sequence::Sequence) -> core::option::Option +pub fn bitcoin_units::sequence::Sequence::to_relative_lock_time(self) -> core::option::Option +pub fn core::num::error::ParseIntError::from(value: bitcoin_units::parse_int::ParseIntError) -> Self +pub fn i64::mul(self, rhs: &bitcoin_units::SignedAmount) -> Self::Output +pub fn i64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn i64::mul(self, rhs: bitcoin_units::SignedAmount) -> Self::Output +pub fn i64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub fn u32::from(height: bitcoin_units::block::BlockHeight) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockHeightInterval) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockMtp) -> Self +pub fn u32::from(height: bitcoin_units::block::BlockMtpInterval) -> Self +pub fn u32::from(sequence: bitcoin_units::sequence::Sequence) -> Self +pub fn u32::from(t: bitcoin_units::BlockTime) -> Self +pub fn u64::from(value: bitcoin_units::Weight) -> Self +pub fn u64::mul(self, rhs: &bitcoin_units::Amount) -> Self::Output +pub fn u64::mul(self, rhs: &bitcoin_units::Weight) -> Self::Output +pub fn u64::mul(self, rhs: &bitcoin_units::result::NumOpResult) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::Amount) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::Weight) -> Self::Output +pub fn u64::mul(self, rhs: bitcoin_units::result::NumOpResult) -> Self::Output +pub mod bitcoin_units +pub mod bitcoin_units::absolute +pub mod bitcoin_units::absolute::error +pub mod bitcoin_units::amount +pub mod bitcoin_units::amount::error +pub mod bitcoin_units::block +pub mod bitcoin_units::fee_rate +pub mod bitcoin_units::locktime +pub mod bitcoin_units::locktime::absolute +pub mod bitcoin_units::locktime::absolute::error +pub mod bitcoin_units::locktime::relative +pub mod bitcoin_units::locktime::relative::error +pub mod bitcoin_units::parse_int +pub mod bitcoin_units::relative +pub mod bitcoin_units::relative::error +pub mod bitcoin_units::result +pub mod bitcoin_units::sequence +pub mod bitcoin_units::time +pub mod bitcoin_units::weight +pub struct bitcoin_units::Amount(_) +pub struct bitcoin_units::BlockHeight(_) +pub struct bitcoin_units::BlockHeightInterval(_) +pub struct bitcoin_units::BlockMtp(_) +pub struct bitcoin_units::BlockMtpInterval(_) +pub struct bitcoin_units::BlockTime(_) +pub struct bitcoin_units::FeeRate(_) +pub struct bitcoin_units::Sequence(pub u32) +pub struct bitcoin_units::SignedAmount(_) +pub struct bitcoin_units::Weight(_) +pub struct bitcoin_units::absolute::Height(_) +pub struct bitcoin_units::absolute::IncompatibleHeightError +pub struct bitcoin_units::absolute::IncompatibleTimeError +pub struct bitcoin_units::absolute::MedianTimePast(_) +pub struct bitcoin_units::absolute::ParseHeightError(_) +pub struct bitcoin_units::absolute::ParseTimeError(_) +pub struct bitcoin_units::absolute::error::IncompatibleHeightError +pub struct bitcoin_units::absolute::error::IncompatibleTimeError +pub struct bitcoin_units::absolute::error::ParseHeightError(_) +pub struct bitcoin_units::absolute::error::ParseTimeError(_) +pub struct bitcoin_units::amount::Amount(_) +pub struct bitcoin_units::amount::Display +pub struct bitcoin_units::amount::OutOfRangeError +pub struct bitcoin_units::amount::ParseAmountError(_) +pub struct bitcoin_units::amount::ParseError(_) +pub struct bitcoin_units::amount::SignedAmount(_) +pub struct bitcoin_units::amount::error::BadPositionError +pub struct bitcoin_units::amount::error::InputTooLargeError +pub struct bitcoin_units::amount::error::InvalidCharacterError +pub struct bitcoin_units::amount::error::MissingDigitsError +pub struct bitcoin_units::amount::error::OutOfRangeError +pub struct bitcoin_units::amount::error::ParseAmountError(_) +pub struct bitcoin_units::amount::error::ParseError(_) +pub struct bitcoin_units::amount::error::TooPreciseError +pub struct bitcoin_units::block::BlockHeight(_) +pub struct bitcoin_units::block::BlockHeightInterval(_) +pub struct bitcoin_units::block::BlockMtp(_) +pub struct bitcoin_units::block::BlockMtpInterval(_) +pub struct bitcoin_units::block::TooBigForRelativeHeightError(_) +pub struct bitcoin_units::fee_rate::FeeRate(_) +pub struct bitcoin_units::locktime::absolute::Height(_) +pub struct bitcoin_units::locktime::absolute::IncompatibleHeightError +pub struct bitcoin_units::locktime::absolute::IncompatibleTimeError +pub struct bitcoin_units::locktime::absolute::MedianTimePast(_) +pub struct bitcoin_units::locktime::absolute::ParseHeightError(_) +pub struct bitcoin_units::locktime::absolute::ParseTimeError(_) +pub struct bitcoin_units::locktime::absolute::error::IncompatibleHeightError +pub struct bitcoin_units::locktime::absolute::error::IncompatibleTimeError +pub struct bitcoin_units::locktime::absolute::error::ParseHeightError(_) +pub struct bitcoin_units::locktime::absolute::error::ParseTimeError(_) +pub struct bitcoin_units::locktime::relative::DisabledLockTimeError(_) +pub struct bitcoin_units::locktime::relative::InvalidHeightError +pub struct bitcoin_units::locktime::relative::InvalidTimeError +pub struct bitcoin_units::locktime::relative::NumberOf512Seconds(_) +pub struct bitcoin_units::locktime::relative::NumberOfBlocks(_) +pub struct bitcoin_units::locktime::relative::TimeOverflowError +pub struct bitcoin_units::locktime::relative::error::DisabledLockTimeError(_) +pub struct bitcoin_units::locktime::relative::error::InvalidHeightError +pub struct bitcoin_units::locktime::relative::error::InvalidTimeError +pub struct bitcoin_units::locktime::relative::error::TimeOverflowError +pub struct bitcoin_units::parse_int::PrefixedHexError(_) +pub struct bitcoin_units::parse_int::UnprefixedHexError(_) +pub struct bitcoin_units::relative::DisabledLockTimeError(_) +pub struct bitcoin_units::relative::InvalidHeightError +pub struct bitcoin_units::relative::InvalidTimeError +pub struct bitcoin_units::relative::NumberOf512Seconds(_) +pub struct bitcoin_units::relative::NumberOfBlocks(_) +pub struct bitcoin_units::relative::TimeOverflowError +pub struct bitcoin_units::relative::error::DisabledLockTimeError(_) +pub struct bitcoin_units::relative::error::InvalidHeightError +pub struct bitcoin_units::relative::error::InvalidTimeError +pub struct bitcoin_units::relative::error::TimeOverflowError +pub struct bitcoin_units::sequence::Sequence(pub u32) +pub struct bitcoin_units::time::BlockTime(_) +pub struct bitcoin_units::weight::Weight(_) +pub trait bitcoin_units::parse_int::Integer: core::str::traits::FromStr + core::convert::TryFrom + core::marker::Sized + bitcoin_units::parse_int::sealed::Sealed +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >::Output +pub type &bitcoin_units::Amount::Output = >>::Output +pub type &bitcoin_units::Amount::Output = ::Output +pub type &bitcoin_units::FeeRate::Output = ::Output +pub type &bitcoin_units::FeeRate::Output = >>::Output +pub type &bitcoin_units::FeeRate::Output = >::Output +pub type &bitcoin_units::FeeRate::Output = >>::Output +pub type &bitcoin_units::FeeRate::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = >::Output +pub type &bitcoin_units::SignedAmount::Output = >>::Output +pub type &bitcoin_units::SignedAmount::Output = ::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = >>::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = >>::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = >::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::Weight::Output = ::Output +pub type &bitcoin_units::block::BlockHeight::Output = >::Output +pub type &bitcoin_units::block::BlockHeight::Output = >::Output +pub type &bitcoin_units::block::BlockHeight::Output = ::Output +pub type &bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type &bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type &bitcoin_units::block::BlockMtp::Output = >::Output +pub type &bitcoin_units::block::BlockMtp::Output = >::Output +pub type &bitcoin_units::block::BlockMtp::Output = ::Output +pub type &bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type &bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type &bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type &i64::Output = >::Output +pub type &i64::Output = >>::Output +pub type &u64::Output = >::Output +pub type &u64::Output = >::Output +pub type &u64::Output = >>::Output +pub type bitcoin_units::Amount::Err = bitcoin_units::amount::error::ParseError +pub type bitcoin_units::Amount::Error = bitcoin_units::amount::error::OutOfRangeError +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >::Output +pub type bitcoin_units::Amount::Output = >>::Output +pub type bitcoin_units::Amount::Output = ::Output +pub type bitcoin_units::Amount::Output = bitcoin_units::Amount +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Amount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::FeeRate::Output = ::Output +pub type bitcoin_units::FeeRate::Output = >>::Output +pub type bitcoin_units::FeeRate::Output = >::Output +pub type bitcoin_units::FeeRate::Output = >>::Output +pub type bitcoin_units::FeeRate::Output = ::Output +pub type bitcoin_units::FeeRate::Output = bitcoin_units::FeeRate +pub type bitcoin_units::FeeRate::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::SignedAmount::Err = bitcoin_units::amount::error::ParseError +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = >::Output +pub type bitcoin_units::SignedAmount::Output = >>::Output +pub type bitcoin_units::SignedAmount::Output = ::Output +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::SignedAmount +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::SignedAmount::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Weight::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::Weight::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = >>::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = >>::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = >::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = ::Output +pub type bitcoin_units::Weight::Output = bitcoin_units::Weight +pub type bitcoin_units::Weight::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::Weight::Output = u64 +pub type bitcoin_units::amount::Denomination::Err = bitcoin_units::amount::error::ParseDenominationError +pub type bitcoin_units::block::BlockHeight::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeight::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeight::Output = >::Output +pub type bitcoin_units::block::BlockHeight::Output = >::Output +pub type bitcoin_units::block::BlockHeight::Output = ::Output +pub type bitcoin_units::block::BlockHeight::Output = bitcoin_units::block::BlockHeight +pub type bitcoin_units::block::BlockHeight::Output = bitcoin_units::block::BlockHeightInterval +pub type bitcoin_units::block::BlockHeightInterval::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeightInterval::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type bitcoin_units::block::BlockHeightInterval::Output = ::Output +pub type bitcoin_units::block::BlockHeightInterval::Output = bitcoin_units::block::BlockHeightInterval +pub type bitcoin_units::block::BlockMtp::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtp::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtp::Output = >::Output +pub type bitcoin_units::block::BlockMtp::Output = >::Output +pub type bitcoin_units::block::BlockMtp::Output = ::Output +pub type bitcoin_units::block::BlockMtp::Output = bitcoin_units::block::BlockMtp +pub type bitcoin_units::block::BlockMtp::Output = bitcoin_units::block::BlockMtpInterval +pub type bitcoin_units::block::BlockMtpInterval::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtpInterval::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type bitcoin_units::block::BlockMtpInterval::Output = ::Output +pub type bitcoin_units::block::BlockMtpInterval::Output = bitcoin_units::block::BlockMtpInterval +pub type bitcoin_units::locktime::absolute::Height::Err = bitcoin_units::locktime::absolute::error::ParseHeightError +pub type bitcoin_units::locktime::absolute::Height::Error = bitcoin_units::locktime::absolute::error::ConversionError +pub type bitcoin_units::locktime::absolute::Height::Error = bitcoin_units::locktime::absolute::error::ParseHeightError +pub type bitcoin_units::locktime::absolute::LockTime::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::absolute::LockTime::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Err = bitcoin_units::locktime::absolute::error::ParseTimeError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Error = bitcoin_units::locktime::absolute::error::ConversionError +pub type bitcoin_units::locktime::absolute::MedianTimePast::Error = bitcoin_units::locktime::absolute::error::ParseTimeError +pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError +pub type bitcoin_units::locktime::relative::NumberOf512Seconds::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOf512Seconds::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Err = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Error = bitcoin_units::block::TooBigForRelativeHeightError +pub type bitcoin_units::locktime::relative::NumberOfBlocks::Error = bitcoin_units::parse_int::ParseIntError +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Add>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Sub>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Div>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Rem>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>::Output +pub type bitcoin_units::result::NumOpResult::Output = as core::ops::arith::Mul>>::Output +pub type bitcoin_units::result::NumOpResult::Output = bitcoin_units::result::NumOpResult +pub type i64::Output = >::Output +pub type i64::Output = >>::Output +pub type i64::Output = bitcoin_units::result::NumOpResult +pub type u64::Output = >::Output +pub type u64::Output = >::Output +pub type u64::Output = >>::Output +pub type u64::Output = bitcoin_units::Weight +pub type u64::Output = bitcoin_units::result::NumOpResult diff --git a/base58/CHANGELOG.md b/base58/CHANGELOG.md new file mode 100644 index 000000000..9bd3876aa --- /dev/null +++ b/base58/CHANGELOG.md @@ -0,0 +1,13 @@ +# 0.2.0 - 2024-12-10 + +- Bump MSRV to `1.63` [#3100](https://github.com/rust-bitcoin/rust-bitcoin/pull/3100) +- Optimize `base58` on small inputs [#3002](https://github.com/rust-bitcoin/rust-bitcoin/pull/3002) +- Add `alloc` feature [#2996](https://github.com/rust-bitcoin/rust-bitcoin/pull/2996) +- Remove zeroed vector by pushing front [#3227](https://github.com/rust-bitcoin/rust-bitcoin/pull/3227) +- Close all errors [#3533](https://github.com/rust-bitcoin/rust-bitcoin/pull/3533) +- Bump `hex-conservative` to `0.3.0` [#3543](https://github.com/rust-bitcoin/rust-bitcoin/pull/3543) + +# 0.1.0 - 2024-03-14 + +Initial release of the `base58ck` crate. This crate was cut out of +`rust-bitcoin` and cleaned up for release as a separate crate. diff --git a/base58/Cargo.toml b/base58/Cargo.toml new file mode 100644 index 000000000..a87ec8907 --- /dev/null +++ b/base58/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "base58ck" +version = "0.2.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin/" +description = "Bitcoin base58 encoding with checksum." +categories = ["cryptography::cryptocurrencies", "encoding"] +keywords = ["bitcoin", "base58", "encode", "decode", "checksum"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc", "hashes/std", "internals/std"] +alloc = ["hashes/alloc", "internals/alloc"] + +[dependencies] +hashes = { package = "bitcoin_hashes", path = "../hashes", default-features = false } +internals = { package = "bitcoin-internals", path = "../internals" } + +[dev-dependencies] +hex_lit = "0.1.1" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(bench)', 'cfg(fuzzing)', 'cfg(kani)' ] } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/base58/README.md b/base58/README.md new file mode 100644 index 000000000..34b576db7 --- /dev/null +++ b/base58/README.md @@ -0,0 +1,21 @@ +# Bitcoin base58 encoding + +This crate provides encoding and decoding of base58 strings as defined by the Bitcoin ecosystem +including the checksum. + +There are a bunch of crates on crates.io that implement base58 encoding and decoding. The more +obviously named ones differ from this crate because: + +1. [bitcoin-base58](https://crates.io/crates/bitcoin-base58) is transpiled from the C++ code in + Bitcoin Core as part of a large long-term transpilation project, whereas this crate is a pure + Rust implementation intended to be production-ready and to provide an Rust-idiomatic API. + +2. [base58](https://crates.io/crates/base58) implements parsing but does not validate checksums (see + `base58check`). It may be appropriate in cases where performance is more important than safety. + Appears unmaintained. + +3. [base58check](https://crates.io/crates/base58check) Adds checksum to the `base58` crate and + depends on [sha2](https://crates.io/crates/sha2/0.8.2) for hashing. Appears unmaintained. + +This crate uses [bitcoin_hashes](https://crates.io/crates/bitcoin_hashes) when hashing to calculate +the checksum. diff --git a/base58/contrib/extra_lints.sh b/base58/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/base58/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/base58/contrib/test_vars.sh b/base58/contrib/test_vars.sh new file mode 100644 index 000000000..92dc09406 --- /dev/null +++ b/base58/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc" + +# Run these examples. +EXAMPLES="" diff --git a/base58/src/error.rs b/base58/src/error.rs new file mode 100644 index 000000000..2ec8f5be5 --- /dev/null +++ b/base58/src/error.rs @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Error code for the `base58` crate. + +use core::convert::Infallible; +use core::fmt; + +use internals::write_err; + +/// An error occurred during base58 decoding (with checksum). +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error(pub(super) ErrorInner); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) enum ErrorInner { + /// Invalid character while decoding. + Decode(InvalidCharacterError), + /// Checksum was not correct. + IncorrectChecksum(IncorrectChecksumError), + /// Checked data was too short. + TooShort(TooShortError), +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for ErrorInner { + fn from(never: Infallible) -> Self { match never {} } +} + +impl Error { + /// Returns the invalid base58 character, if encountered. + pub fn invalid_character(&self) -> Option { + match self.0 { + ErrorInner::Decode(ref e) => Some(e.invalid_character()), + _ => None, + } + } + + /// Returns the incorrect checksum along with the expected checksum, if encountered. + pub fn incorrect_checksum(&self) -> Option<(u32, u32)> { + match self.0 { + ErrorInner::IncorrectChecksum(ref e) => Some((e.incorrect, e.expected)), + _ => None, + } + } + + /// Returns the invalid base58 string length (require at least 4 bytes for checksum), if encountered. + pub fn invalid_length(&self) -> Option { + match self.0 { + ErrorInner::TooShort(ref e) => Some(e.length), + _ => None, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ErrorInner::*; + + match self.0 { + Decode(ref e) => write_err!(f, "decode"; e), + IncorrectChecksum(ref e) => write_err!(f, "incorrect checksum"; e), + TooShort(ref e) => write_err!(f, "too short"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use ErrorInner::*; + + match self.0 { + Decode(ref e) => Some(e), + IncorrectChecksum(ref e) => Some(e), + TooShort(ref e) => Some(e), + } + } +} + +impl From for Error { + fn from(e: InvalidCharacterError) -> Self { Self(ErrorInner::Decode(e)) } +} + +impl From for Error { + fn from(e: IncorrectChecksumError) -> Self { Self(ErrorInner::IncorrectChecksum(e)) } +} + +impl From for Error { + fn from(e: TooShortError) -> Self { Self(ErrorInner::TooShort(e)) } +} + +/// Checksum was not correct. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) struct IncorrectChecksumError { + /// The incorrect checksum. + pub(super) incorrect: u32, + /// The expected checksum. + pub(super) expected: u32, +} + +impl From for IncorrectChecksumError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for IncorrectChecksumError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "base58 checksum {:#x} does not match expected {:#x}", + self.incorrect, self.expected + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for IncorrectChecksumError {} + +/// The decoded base58 data was too short (require at least 4 bytes for checksum). +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) struct TooShortError { + /// The length of the decoded data. + pub(super) length: usize, +} +impl From for TooShortError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for TooShortError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "base58 decoded data was not long enough, must be at least 4 byte: {}", + self.length + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TooShortError {} + +/// Found an invalid ASCII byte while decoding base58 string. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidCharacterError(pub(super) InvalidCharacterErrorInner); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub(super) struct InvalidCharacterErrorInner { + pub(super) invalid: u8, +} + +impl From for InvalidCharacterError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for InvalidCharacterErrorInner { + fn from(never: Infallible) -> Self { match never {} } +} + +impl InvalidCharacterError { + pub(super) fn new(invalid: u8) -> Self { Self(InvalidCharacterErrorInner { invalid }) } + + /// Returns the invalid base58 character. + pub fn invalid_character(&self) -> u8 { self.0.invalid } +} + +impl fmt::Display for InvalidCharacterError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid base58 character {:#x}", self.0.invalid) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidCharacterError {} diff --git a/base58/src/lib.rs b/base58/src/lib.rs new file mode 100644 index 000000000..85debd871 --- /dev/null +++ b/base58/src/lib.rs @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin base58 encoding and decoding. +//! +//! This crate can be used in a no-std environment but requires an allocator. + +// NB: This crate is empty if `alloc` is not enabled. +#![cfg(feature = "alloc")] +#![no_std] +// Experimental features we need. +#![cfg_attr(bench, feature(test))] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Instead of littering the codebase for non-fuzzing and bench code just globally allow. +#![cfg_attr(fuzzing, allow(dead_code, unused_imports))] +#![cfg_attr(bench, allow(dead_code, unused_imports))] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::incompatible_msrv)] // Has FPs and we're testing it which is more reliable anyway. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +extern crate alloc; + +#[cfg(bench)] +extern crate test; + +#[cfg(feature = "std")] +extern crate std; + +static BASE58_CHARS: &[u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +pub mod error; + +#[cfg(not(feature = "std"))] +pub use alloc::{string::String, vec::Vec}; +use core::fmt; +#[cfg(feature = "std")] +pub use std::{string::String, vec::Vec}; + +use hashes::sha256d; +use internals::array::ArrayExt; +use internals::array_vec::ArrayVec; +#[allow(unused)] // MSRV polyfill +use internals::slice::SliceExt; + +use crate::error::{IncorrectChecksumError, TooShortError}; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::error::{Error, InvalidCharacterError}; + +#[rustfmt::skip] +static BASE58_DIGITS: [Option; 128] = [ + None, None, None, None, None, None, None, None, // 0-7 + None, None, None, None, None, None, None, None, // 8-15 + None, None, None, None, None, None, None, None, // 16-23 + None, None, None, None, None, None, None, None, // 24-31 + None, None, None, None, None, None, None, None, // 32-39 + None, None, None, None, None, None, None, None, // 40-47 + None, Some(0), Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), // 48-55 + Some(7), Some(8), None, None, None, None, None, None, // 56-63 + None, Some(9), Some(10), Some(11), Some(12), Some(13), Some(14), Some(15), // 64-71 + Some(16), None, Some(17), Some(18), Some(19), Some(20), Some(21), None, // 72-79 + Some(22), Some(23), Some(24), Some(25), Some(26), Some(27), Some(28), Some(29), // 80-87 + Some(30), Some(31), Some(32), None, None, None, None, None, // 88-95 + None, Some(33), Some(34), Some(35), Some(36), Some(37), Some(38), Some(39), // 96-103 + Some(40), Some(41), Some(42), Some(43), None, Some(44), Some(45), Some(46), // 104-111 + Some(47), Some(48), Some(49), Some(50), Some(51), Some(52), Some(53), Some(54), // 112-119 + Some(55), Some(56), Some(57), None, None, None, None, None, // 120-127 +]; + +/// Decodes a base58-encoded string into a byte vector. +pub fn decode(data: &str) -> Result, InvalidCharacterError> { + // 11/15 is just over log_256(58) + let mut scratch = Vec::with_capacity(1 + data.len() * 11 / 15); + // Build in base 256 + for d58 in data.bytes() { + // Compute "X = X * 58 + next_digit" in base 256 + if usize::from(d58) >= BASE58_DIGITS.len() { + return Err(InvalidCharacterError::new(d58)); + } + let mut carry = match BASE58_DIGITS[usize::from(d58)] { + Some(d58) => u32::from(d58), + None => { + return Err(InvalidCharacterError::new(d58)); + } + }; + if scratch.is_empty() { + for _ in 0..scratch.capacity() { + scratch.push(carry as u8); + carry /= 256; + } + } else { + for d256 in scratch.iter_mut() { + carry += u32::from(*d256) * 58; + *d256 = carry as u8; // cast loses data intentionally + carry /= 256; + } + } + assert_eq!(carry, 0); + } + + // Copy leading zeroes directly + let mut ret: Vec = data.bytes().take_while(|&x| x == BASE58_CHARS[0]).map(|_| 0).collect(); + // Copy rest of string + ret.extend(scratch.into_iter().rev().skip_while(|&x| x == 0)); + Ok(ret) +} + +/// Decodes a base58check-encoded string into a byte vector verifying the checksum. +pub fn decode_check(data: &str) -> Result, Error> { + let mut ret: Vec = decode(data)?; + let (remaining, &data_check) = + ret.split_last_chunk::<4>().ok_or(TooShortError { length: ret.len() })?; + + let hash_check = *sha256d::Hash::hash(remaining).as_byte_array().sub_array::<0, 4>(); + + let expected = u32::from_le_bytes(hash_check); + let actual = u32::from_le_bytes(data_check); + + if actual != expected { + return Err(IncorrectChecksumError { incorrect: actual, expected }.into()); + } + + ret.truncate(remaining.len()); + Ok(ret) +} + +const SHORT_OPT_BUFFER_LEN: usize = 128; + +/// Encodes `data` as a base58 string (see also `base58::encode_check()`). +pub fn encode(data: &[u8]) -> String { + let reserve_len = encoded_reserve_len(data.len()); + let mut res = String::with_capacity(reserve_len); + if reserve_len <= SHORT_OPT_BUFFER_LEN { + format_iter( + &mut res, + data.iter().copied(), + &mut ArrayVec::::new(), + ) + } else { + format_iter(&mut res, data.iter().copied(), &mut Vec::with_capacity(reserve_len)) + } + .expect("string doesn't error"); + res +} + +/// Encodes `data` as a base58 string including the checksum. +/// +/// The checksum is the first four bytes of the sha256d of the data, concatenated onto the end. +pub fn encode_check(data: &[u8]) -> String { + let mut res = String::with_capacity(encoded_check_reserve_len(data.len())); + encode_check_to_writer(&mut res, data).expect("string doesn't fail"); + res +} + +/// Encodes a slice as base58, including the checksum, into a formatter. +/// +/// The checksum is the first four bytes of the sha256d of the data, concatenated onto the end. +pub fn encode_check_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt::Result { + encode_check_to_writer(fmt, data) +} + +fn encode_check_to_writer(fmt: &mut impl fmt::Write, data: &[u8]) -> fmt::Result { + let checksum = sha256d::Hash::hash(data); + let iter = data.iter().cloned().chain(checksum.as_byte_array()[0..4].iter().cloned()); + let reserve_len = encoded_check_reserve_len(data.len()); + if reserve_len <= SHORT_OPT_BUFFER_LEN { + format_iter(fmt, iter, &mut ArrayVec::::new()) + } else { + format_iter(fmt, iter, &mut Vec::with_capacity(reserve_len)) + } +} + +/// Returns the length to reserve when encoding base58 without checksum +const fn encoded_reserve_len(unencoded_len: usize) -> usize { + // log2(256) / log2(58) ~ 1.37 = 137 / 100 + unencoded_len * 137 / 100 +} + +/// Returns the length to reserve when encoding base58 with checksum +const fn encoded_check_reserve_len(unencoded_len: usize) -> usize { + encoded_reserve_len(unencoded_len + 4) +} + +trait Buffer: Sized { + fn push(&mut self, val: u8); + fn slice(&self) -> &[u8]; + fn slice_mut(&mut self) -> &mut [u8]; +} + +impl Buffer for Vec { + fn push(&mut self, val: u8) { Self::push(self, val) } + + fn slice(&self) -> &[u8] { self } + + fn slice_mut(&mut self) -> &mut [u8] { self } +} + +impl Buffer for ArrayVec { + fn push(&mut self, val: u8) { Self::push(self, val) } + + fn slice(&self) -> &[u8] { self.as_slice() } + + fn slice_mut(&mut self) -> &mut [u8] { self.as_mut_slice() } +} + +fn format_iter(writer: &mut W, data: I, buf: &mut impl Buffer) -> Result<(), fmt::Error> +where + I: Iterator + Clone, + W: fmt::Write, +{ + let mut leading_zero_count = 0; + let mut leading_zeroes = true; + // Build string in little endian with 0-58 in place of characters... + for d256 in data { + let mut carry = u32::from(d256); + if leading_zeroes && carry == 0 { + leading_zero_count += 1; + } else { + leading_zeroes = false; + } + + for ch in buf.slice_mut() { + let new_ch = u32::from(*ch) * 256 + carry; + *ch = (new_ch % 58) as u8; // cast loses data intentionally + carry = new_ch / 58; + } + + while carry > 0 { + buf.push((carry % 58) as u8); // cast loses data intentionally + carry /= 58; + } + } + + // ... then reverse it and convert to chars + for _ in 0..leading_zero_count { + buf.push(0); + } + + for ch in buf.slice().iter().rev() { + writer.write_char(char::from(BASE58_CHARS[usize::from(*ch)]))?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use alloc::vec; + + use hex_lit::hex; + + use super::*; + + #[test] + fn base58_encode() { + // Basics + assert_eq!(&encode(&[0][..]), "1"); + assert_eq!(&encode(&[1][..]), "2"); + assert_eq!(&encode(&[58][..]), "21"); + assert_eq!(&encode(&[13, 36][..]), "211"); + + // Leading zeroes + assert_eq!(&encode(&[0, 13, 36][..]), "1211"); + assert_eq!(&encode(&[0, 0, 0, 0, 13, 36][..]), "1111211"); + + // Long input (>128 bytes => has to use heap) + let res = encode( + "BitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBit\ + coinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoinBitcoin" + .as_bytes(), + ); + let exp = + "ZqC5ZdfpZRi7fjA8hbhX5pEE96MdH9hEaC1YouxscPtbJF16qVWksHWR4wwvx7MotFcs2ChbJqK8KJ9X\ + wZznwWn1JFDhhTmGo9v6GjAVikzCsBWZehu7bm22xL8b5zBR5AsBygYRwbFJsNwNkjpyFuDKwmsUTKvkULCvucPJrN5\ + QUdxpGakhqkZFL7RU4yT"; + assert_eq!(&res, exp); + + // Addresses + let addr = hex!("00f8917303bfa8ef24f292e8fa1419b20460ba064d"); + assert_eq!(&encode_check(&addr[..]), "1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH"); + } + + #[test] + fn base58_decode() { + // Basics + assert_eq!(decode("1").ok(), Some(vec![0u8])); + assert_eq!(decode("2").ok(), Some(vec![1u8])); + assert_eq!(decode("21").ok(), Some(vec![58u8])); + assert_eq!(decode("211").ok(), Some(vec![13u8, 36])); + + // Leading zeroes + assert_eq!(decode("1211").ok(), Some(vec![0u8, 13, 36])); + assert_eq!(decode("111211").ok(), Some(vec![0u8, 0, 0, 13, 36])); + + // Addresses + assert_eq!( + decode_check("1PfJpZsjreyVrqeoAfabrRwwjQyoSQMmHH").ok().unwrap().as_slice(), + hex!("00f8917303bfa8ef24f292e8fa1419b20460ba064d") + ); + // Non Base58 char. + assert_eq!(decode("¢").unwrap_err(), InvalidCharacterError::new(194)); + } + + #[test] + fn base58_roundtrip() { + let s = "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs"; + let v: Vec = decode_check(s).unwrap(); + assert_eq!(encode_check(&v[..]), s); + assert_eq!(decode_check(&encode_check(&v[..])).ok(), Some(v)); + + // Check that empty slice passes roundtrip. + assert_eq!(decode_check(&encode_check(&[])), Ok(vec![])); + // Check that `len > 4` is enforced. + assert_eq!(decode_check(&encode(&[1, 2, 3])), Err(TooShortError { length: 3 }.into())); + } +} + +#[cfg(bench)] +mod benches { + use test::{black_box, Bencher}; + + #[bench] + pub fn bench_encode_check_50(bh: &mut Bencher) { + let data: alloc::vec::Vec<_> = (0u8..50).collect(); + + bh.iter(|| { + let r = super::encode_check(&data); + black_box(&r); + }); + } + + #[bench] + pub fn bench_encode_check_xpub(bh: &mut Bencher) { + let data: alloc::vec::Vec<_> = (0u8..78).collect(); // length of xpub + + bh.iter(|| { + let r = super::encode_check(&data); + black_box(&r); + }); + } +} diff --git a/benches/Cargo.toml b/benches/Cargo.toml new file mode 100644 index 000000000..4836e2b80 --- /dev/null +++ b/benches/Cargo.toml @@ -0,0 +1,99 @@ +[package] +name = "bitcoin-benches" +version = "0.1.0" +license = "CC0-1.0" +description = "Criterion benchmarks for rust-bitcoin" +edition = "2021" + +[dependencies] +bitcoin = { path = "../bitcoin", default-features = false, features = ["std"] } +bitcoin_hashes = { path = "../hashes" } +chacha20-poly1305 = { path = "../chacha20_poly1305" } + +criterion = "0.7" +hex_lit = "0.1.1" + +[lints.clippy] +use_self = "warn" + +[[bench]] +name = "block" +path = "bitcoin/block.rs" +harness = false + +[[bench]] +name = "transaction" +path = "bitcoin/transaction.rs" +harness = false + +[[bench]] +name = "witness" +path = "bitcoin/witness.rs" +harness = false + + +[[bench]] +name = "chacha20poly1305" +path = "chacha20_poly1305/chacha20poly1305.rs" +harness = false + +[[bench]] +name = "chacha20" +path = "chacha20_poly1305/chacha20.rs" +harness = false + + +[[bench]] +name = "cmp" +path = "hashes/cmp.rs" +harness = false + +[[bench]] +name = "hash160" +path = "hashes/hash160.rs" +harness = false + +[[bench]] +name = "hmac" +path = "hashes/hmac.rs" +harness = false + +[[bench]] +name = "ripemd160" +path = "hashes/ripemd160.rs" +harness = false + +[[bench]] +name = "sha1" +path = "hashes/sha1.rs" +harness = false + +[[bench]] +name = "sha3_256" +path = "hashes/sha3_256.rs" +harness = false + +[[bench]] +name = "sha256" +path = "hashes/sha256.rs" +harness = false + +[[bench]] +name = "sha384" +path = "hashes/sha384.rs" +harness = false + +[[bench]] +name = "sha512_256" +path = "hashes/sha512_256.rs" +harness = false + +[[bench]] +name = "sha512" +path = "hashes/sha512.rs" +harness = false + +[[bench]] +name = "siphash24" +path = "hashes/siphash24.rs" +harness = false diff --git a/benches/README.md b/benches/README.md new file mode 100644 index 000000000..c4fa673be --- /dev/null +++ b/benches/README.md @@ -0,0 +1,77 @@ +# Rust Bitcoin Benchmarks + +Criterion based benchmarks for `rust-bitcoin`. + +## Minimum Supported Rust Version (MSRV) + +This crate’s MSRV is determined by its Criterion dependency. It currently requires **Rust 1.81**. +This higher MSRV applies only to the benches crate and does not affect other crates in this repository. + +## Running the benchmarks + +Examples below are run from within the crates folder `benches/`, if running from the repo root pass in `--manifest-path benches/Cargo.toml`. + +Run all benchmarks in this crate: + +```bash +cargo bench +``` + +Run a specific benchmark target: + +```bash +cargo bench --bench block +``` + +Pass options through to Criterion (see [More information](#more-information) for details): + +```bash +# Save current results as a baseline named "before-change" +cargo bench -- --save-baseline before-change + +# Compare to the saved baseline +cargo bench -- --baseline before-change +``` + +View reports: + +- Criterion writes detailed html reports that are linked to in `target/criterion/report/index.html`. + +## Adding a new benchmark + +1. Create a new Rust file for your benchmark in the subfolder for the crate e.g. `benches/bitcoin/base58.rs`. +2. Add it in `benches/Cargo.toml` including the path, with `harness = false`: + +```toml +[[bench]] +name = "base58" +path = "bitcoin/base58.rs" +harness = false +``` + +3. Criterion code template: + +```rust +use criterion::{criterion_group, criterion_main, Criterion}; + +fn bench_new_bench(c: &mut Criterion) { + c.bench_function("new_bench", |b| { + b.iter(|| { + // Benchmark code + }) + }); +} + +criterion_group!(benches, bench_new_bench); +criterion_main!(benches); +``` + +## More information + +- Criterion Book: +- Criterion GitHub: + +## Licensing + +The code in this project is licensed under the [Creative Commons CC0 1.0 Universal license](../LICENSE). +We use the [SPDX license list](https://spdx.org/licenses/) and [SPDX IDs](https://spdx.dev/ids/). diff --git a/benches/bitcoin/block.rs b/benches/bitcoin/block.rs new file mode 100644 index 000000000..6ac155c70 --- /dev/null +++ b/benches/bitcoin/block.rs @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::time::Duration; +use std::hint::black_box; + +use bitcoin::blockdata::block::Block; +use bitcoin::consensus::{deserialize, Decodable, Encodable}; +use bitcoin::io::sink; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_block(c: &mut Criterion) { + let raw_block = include_bytes!("../../bitcoin/tests/data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw"); + assert_eq!(raw_block.len(), 1_381_836); + let block: Block = deserialize(&raw_block[..]).unwrap(); + + let mut g = c.benchmark_group("block"); + g.throughput(Throughput::Bytes(raw_block.len() as u64)); + g.measurement_time(Duration::from_secs(10)).warm_up_time(Duration::from_secs(3)); + + g.bench_function(BenchmarkId::new("stream_reader", "big"), |b| { + let big_block = black_box(raw_block.as_ref()); + b.iter(|| { + let mut reader = big_block; + let blk = Block::consensus_decode(&mut reader).unwrap(); + black_box(blk); + }); + }); + + g.bench_function(BenchmarkId::new("serialize", "big"), |b| { + let mut data = Vec::with_capacity(raw_block.len()); + b.iter(|| { + let result = block.consensus_encode(&mut data); + black_box(&result); + data.clear(); + }); + }); + + g.bench_function(BenchmarkId::new("serialize_logic", "big"), |b| { + b.iter(|| { + let size = block.consensus_encode(&mut sink()); + let _ = black_box(size); + }); + }); + + g.bench_function(BenchmarkId::new("deserialize", "big"), |b| { + b.iter(|| { + let blk: Block = deserialize(&raw_block[..]).unwrap(); + black_box(blk); + }); + }); + + g.finish(); +} + +criterion_group!(benches, bench_block); +criterion_main!(benches); diff --git a/benches/bitcoin/transaction.rs b/benches/bitcoin/transaction.rs new file mode 100644 index 000000000..ab8101faa --- /dev/null +++ b/benches/bitcoin/transaction.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin::blockdata::transaction::Transaction; +use bitcoin::blockdata::transaction::TransactionExt as _; // for total_size() +use bitcoin::consensus::{encode, Encodable}; +use bitcoin::io::sink; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; + +const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; + +fn bench_tx(c: &mut Criterion) { + let mut g = c.benchmark_group("transaction"); + + g.bench_function(BenchmarkId::new("size", "some"), |b| { + let mut tx: Transaction = encode::deserialize_hex(SOME_TX).unwrap(); + b.iter(|| { + black_box(black_box(&mut tx).total_size()); + }); + }); + + g.bench_function(BenchmarkId::new("serialize", "some"), |b| { + let tx: Transaction = encode::deserialize_hex(SOME_TX).unwrap(); + let mut data = Vec::with_capacity(SOME_TX.len() / 2); + b.iter(|| { + let result = tx.consensus_encode(&mut data); + black_box(&result); + data.clear(); + }); + }); + + g.bench_function(BenchmarkId::new("serialize_logic", "some"), |b| { + let tx: Transaction = encode::deserialize_hex(SOME_TX).unwrap(); + b.iter(|| { + let size = tx.consensus_encode(&mut sink()); + let _ = black_box(size); + }); + }); + + g.bench_function(BenchmarkId::new("deserialize", "raw_bytes"), |b| { + let raw_tx = hex_lit::hex!(SOME_TX); + b.iter(|| { + let tx: Transaction = encode::deserialize(&raw_tx).unwrap(); + black_box(tx); + }); + }); + + g.bench_function(BenchmarkId::new("deserialize_hex", "string"), |b| { + b.iter(|| { + let tx: Transaction = encode::deserialize_hex(SOME_TX).unwrap(); + black_box(tx); + }); + }); + + g.finish(); +} + +criterion_group!(benches, bench_tx); +criterion_main!(benches); diff --git a/benches/bitcoin/witness.rs b/benches/bitcoin/witness.rs new file mode 100644 index 000000000..22adf16f6 --- /dev/null +++ b/benches/bitcoin/witness.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin::blockdata::witness::Witness; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; + +fn bench_witness(c: &mut Criterion) { + let mut g = c.benchmark_group("witness"); + + g.bench_function(BenchmarkId::new("to_vec", "big"), |b| { + let raw_witness = [[1u8]; 5]; + let witness = Witness::from_slice(&raw_witness); + b.iter(|| { + black_box(witness.to_vec()); + }); + }); + + g.bench_function(BenchmarkId::new("to_vec", "small"), |b| { + let raw_witness = vec![vec![1u8]; 3]; + let witness = Witness::from_slice(&raw_witness); + b.iter(|| { + black_box(witness.to_vec()); + }); + }); + + g.finish(); +} + +criterion_group!(benches, bench_witness); +criterion_main!(benches); diff --git a/benches/chacha20_poly1305/chacha20.rs b/benches/chacha20_poly1305/chacha20.rs new file mode 100644 index 000000000..958592950 --- /dev/null +++ b/benches/chacha20_poly1305/chacha20.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use std::time::Duration; + +use chacha20_poly1305::{chacha20::ChaCha20, Key, Nonce}; + +fn bench_chacha20(c: &mut Criterion) { + let mut g = c.benchmark_group("chacha20"); + g.measurement_time(Duration::from_secs(5)).warm_up_time(Duration::from_secs(2)); + + for &size in &[10usize, 1024, 65536] { + let key = Key::new([0u8; 32]); + let nonce = Nonce::new([0u8; 12]); + let count = 1u32; + let mut cipher = ChaCha20::new(key, nonce, count); + let mut buf = vec![0u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("apply_keystream", size), |b| { + b.iter(|| { + cipher.apply_keystream(black_box(&mut buf)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_chacha20); +criterion_main!(benches); diff --git a/benches/chacha20_poly1305/chacha20poly1305.rs b/benches/chacha20_poly1305/chacha20poly1305.rs new file mode 100644 index 000000000..7719734b3 --- /dev/null +++ b/benches/chacha20_poly1305/chacha20poly1305.rs @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use std::time::Duration; + +use chacha20_poly1305::{ChaCha20Poly1305, Key, Nonce}; + +fn bench_chacha20poly1305(c: &mut Criterion) { + let mut g = c.benchmark_group("chacha20poly1305"); + g.measurement_time(Duration::from_secs(5)).warm_up_time(Duration::from_secs(2)); + + for &size in &[128usize, 1024, 16 * 1024, 64 * 1024] { + let key = Key::new([0u8; 32]); + let nonce = Nonce::new([0u8; 12]); + + let pt = vec![0u8; size]; + let aad: &[u8] = b"dummy_aad"; + + g.throughput(Throughput::Bytes(size as u64)); + + g.bench_function(BenchmarkId::new("encrypt_no_aad", size), |b| { + b.iter(|| { + let mut buf = pt.clone(); + let cipher = ChaCha20Poly1305::new(key, nonce); + let tag = cipher.encrypt(black_box(&mut buf), None); + black_box(tag); + }); + }); + + g.bench_function(BenchmarkId::new("encrypt_with_aad", size), |b| { + b.iter(|| { + let mut buf = pt.clone(); + let cipher = ChaCha20Poly1305::new(key, nonce); + let tag = cipher.encrypt(black_box(&mut buf), Some(aad)); + black_box(tag); + }); + }); + + let mut ct = pt.clone(); + let tag = ChaCha20Poly1305::new(key, nonce).encrypt(&mut ct, Some(aad)); + + g.bench_function(BenchmarkId::new("decrypt_ok", size), |b| { + b.iter(|| { + let mut buf = ct.clone(); + let cipher = ChaCha20Poly1305::new(key, nonce); + let res = cipher.decrypt(black_box(&mut buf), tag, Some(aad)); + res.unwrap(); + black_box(()); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_chacha20poly1305); +criterion_main!(benches); diff --git a/benches/hashes/cmp.rs b/benches/hashes/cmp.rs new file mode 100644 index 000000000..13695c323 --- /dev/null +++ b/benches/hashes/cmp.rs @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha256, sha512}; +use bitcoin_hashes::cmp::fixed_time_eq; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; + +fn bench_cmp(c: &mut Criterion) { + let mut g = c.benchmark_group("cmp"); + + // 32-byte comparisons + let a32 = sha256::Hash::hash(&[0; 1]); + let b32eq = sha256::Hash::hash(&[0; 1]); + let b32ne = sha256::Hash::hash(&[1; 1]); + + g.bench_function(BenchmarkId::new("ct_eq", 32), |b| { + b.iter(|| fixed_time_eq(black_box(a32.as_byte_array()), black_box(b32eq.as_byte_array()))); + }); + g.bench_function(BenchmarkId::new("slice_eq", 32), |b| { + b.iter(|| black_box(a32.as_byte_array() == b32eq.as_byte_array())); + }); + g.bench_function(BenchmarkId::new("ct_ne", 32), |b| { + b.iter(|| fixed_time_eq(black_box(a32.as_byte_array()), black_box(b32ne.as_byte_array()))); + }); + g.bench_function(BenchmarkId::new("slice_ne", 32), |b| { + b.iter(|| black_box(a32.as_byte_array() == b32ne.as_byte_array())); + }); + + // 64-byte comparisons + let a64 = sha512::Hash::hash(&[0; 1]); + let b64eq = sha512::Hash::hash(&[0; 1]); + let b64ne = sha512::Hash::hash(&[1; 1]); + + g.bench_function(BenchmarkId::new("ct_eq", 64), |b| { + b.iter(|| fixed_time_eq(black_box(a64.as_byte_array()), black_box(b64eq.as_byte_array()))); + }); + g.bench_function(BenchmarkId::new("slice_eq", 64), |b| { + b.iter(|| black_box(a64.as_byte_array() == b64eq.as_byte_array())); + }); + g.bench_function(BenchmarkId::new("ct_ne", 64), |b| { + b.iter(|| fixed_time_eq(black_box(a64.as_byte_array()), black_box(b64ne.as_byte_array()))); + }); + g.bench_function(BenchmarkId::new("slice_ne", 64), |b| { + b.iter(|| black_box(a64.as_byte_array() == b64ne.as_byte_array())); + }); + + g.finish(); +} + +criterion_group!(benches, bench_cmp); +criterion_main!(benches); diff --git a/benches/hashes/hash160.rs b/benches/hashes/hash160.rs new file mode 100644 index 000000000..452fd454d --- /dev/null +++ b/benches/hashes/hash160.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{hash160, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_hash160(c: &mut Criterion) { + let mut g = c.benchmark_group("hash160"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = hash160::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_hash160); +criterion_main!(benches); diff --git a/benches/hashes/hmac.rs b/benches/hashes/hmac.rs new file mode 100644 index 000000000..adc90e515 --- /dev/null +++ b/benches/hashes/hmac.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha256, HashEngine as _, HmacEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_hmac(c: &mut Criterion) { + let mut g = c.benchmark_group("hmac_sha256"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = HmacEngine::::new(&[]); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_hmac); +criterion_main!(benches); diff --git a/benches/hashes/ripemd160.rs b/benches/hashes/ripemd160.rs new file mode 100644 index 000000000..b786e77af --- /dev/null +++ b/benches/hashes/ripemd160.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{ripemd160, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_ripemd160(c: &mut Criterion) { + let mut g = c.benchmark_group("ripemd160"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = ripemd160::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_ripemd160); +criterion_main!(benches); diff --git a/benches/hashes/sha1.rs b/benches/hashes/sha1.rs new file mode 100644 index 000000000..a63773f59 --- /dev/null +++ b/benches/hashes/sha1.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha1, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_sha1(c: &mut Criterion) { + let mut g = c.benchmark_group("sha1"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = sha1::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_sha1); +criterion_main!(benches); diff --git a/benches/hashes/sha256.rs b/benches/hashes/sha256.rs new file mode 100644 index 000000000..a8f2d1046 --- /dev/null +++ b/benches/hashes/sha256.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha256, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_sha256(c: &mut Criterion) { + let mut g = c.benchmark_group("sha256"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = sha256::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_sha256); +criterion_main!(benches); diff --git a/benches/hashes/sha384.rs b/benches/hashes/sha384.rs new file mode 100644 index 000000000..77004ccf2 --- /dev/null +++ b/benches/hashes/sha384.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha384, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_sha384(c: &mut Criterion) { + let mut g = c.benchmark_group("sha384"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = sha384::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_sha384); +criterion_main!(benches); diff --git a/benches/hashes/sha3_256.rs b/benches/hashes/sha3_256.rs new file mode 100644 index 000000000..2d4e1087d --- /dev/null +++ b/benches/hashes/sha3_256.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha3_256, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_sha3_256(c: &mut Criterion) { + let mut g = c.benchmark_group("sha3_256"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = sha3_256::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_sha3_256); +criterion_main!(benches); diff --git a/benches/hashes/sha512.rs b/benches/hashes/sha512.rs new file mode 100644 index 000000000..c72d9e61c --- /dev/null +++ b/benches/hashes/sha512.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha512, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_sha512(c: &mut Criterion) { + let mut g = c.benchmark_group("sha512"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = sha512::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_sha512); +criterion_main!(benches); diff --git a/benches/hashes/sha512_256.rs b/benches/hashes/sha512_256.rs new file mode 100644 index 000000000..c4cc075d5 --- /dev/null +++ b/benches/hashes/sha512_256.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{sha512_256, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_sha512_256(c: &mut Criterion) { + let mut g = c.benchmark_group("sha512_256"); + + for &size in &[10usize, 1024, 65536] { + let mut engine = sha512_256::Hash::engine(); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + g.finish(); +} + +criterion_group!(benches, bench_sha512_256); +criterion_main!(benches); diff --git a/benches/hashes/siphash24.rs b/benches/hashes/siphash24.rs new file mode 100644 index 000000000..f25d6d664 --- /dev/null +++ b/benches/hashes/siphash24.rs @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: CC0-1.0 + +use std::hint::black_box; + +use bitcoin_hashes::{siphash24, HashEngine}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; + +fn bench_siphash24(c: &mut Criterion) { + let mut g = c.benchmark_group("siphash24"); + + for &size in &[1024usize, 65536] { + let mut engine = siphash24::HashEngine::with_keys(0, 0); + let bytes = vec![1u8; size]; + g.throughput(Throughput::Bytes(size as u64)); + g.bench_function(BenchmarkId::new("engine_input", size), |b| { + b.iter(|| { + engine.input(black_box(&bytes)); + }); + }); + } + + // Hash-with-keys and to_u64 variants + let k0 = 0x_07_06_05_04_03_02_01_00; + let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; + let bytes = vec![1u8; 1024]; + g.throughput(Throughput::Bytes(bytes.len() as u64)); + g.bench_function("hash_with_keys/1k", |b| { + b.iter(|| { + let _ = siphash24::Hash::hash_with_keys(k0, k1, black_box(&bytes)); + }); + }); + g.bench_function("hash_to_u64_with_keys/1k", |b| { + b.iter(|| { + let _ = siphash24::Hash::hash_to_u64_with_keys(k0, k1, black_box(&bytes)); + }); + }); + + g.finish(); +} + +criterion_group!(benches, bench_siphash24); +criterion_main!(benches); diff --git a/bip158/CHANGELOG.md b/bip158/CHANGELOG.md new file mode 100644 index 000000000..bf34213b9 --- /dev/null +++ b/bip158/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.1.0 - 2025-12-09 + +* Initial release of the `github.com/rust-bitcoin/rust-bitcoin/bip158` crate as `bip158`. diff --git a/bip158/Cargo.toml b/bip158/Cargo.toml new file mode 100644 index 000000000..b0ac9c2cd --- /dev/null +++ b/bip158/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "bitcoin-bip158" +version = "0.0.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +description = "Golomb-rice coded filters for set membership query." +categories = ["cryptography::cryptocurrencies"] +keywords = ["bitcoin", "peer-to-peer", "cryptography"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[dependencies] + +[dev-dependencies] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/bip158/README.md b/bip158/README.md new file mode 100644 index 000000000..547ee29d2 --- /dev/null +++ b/bip158/README.md @@ -0,0 +1,3 @@ +# BIP-158 + +Implementation of [BIP-158](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki) golomb coded block filters for private light client set membership query. diff --git a/bip158/contrib/extra_lints.sh b/bip158/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/bip158/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/bip158/contrib/test_vars.sh b/bip158/contrib/test_vars.sh new file mode 100644 index 000000000..88e2d26e1 --- /dev/null +++ b/bip158/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="" + +# Run these examples. +EXAMPLES="" diff --git a/bip158/src/lib.rs b/bip158/src/lib.rs new file mode 100644 index 000000000..fb22c034e --- /dev/null +++ b/bip158/src/lib.rs @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! # Rust Bitcoin BIP-158 implementation. + +// Experimental features we need. +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Pedantic lints that we enforce. +#![warn(clippy::return_self_not_must_use)] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)`instead of enforcing `format!("{x}")` diff --git a/bitcoin/CHANGELOG.md b/bitcoin/CHANGELOG.md new file mode 100644 index 000000000..64722ec9c --- /dev/null +++ b/bitcoin/CHANGELOG.md @@ -0,0 +1,849 @@ +# 0.33.0-beta.0 - 2025-11-03 + +This series of beta releases is meant for two things: + +1. To allow testing of the upcoming `bitcoin v0.33.0`. Its been a long + time since we released and there is a lot in this. + +2. To allow testing of the `1.0.0` RC releases of: + + - `bitcoin-primitives` + - `bitcoin-units` + - `bitcoin-consensus-encoding` + +`cargo` can be surprising when there is a `-` in the version number +(see discussion on [#5229](https://github.com/rust-bitcoin/rust-bitcoin/discussions/5229)). + +We do not currently intend on releasing `bitcoin 0.33.0` until the `1.0` releases above are done. + +For changes to our dependencies included in this release see: + +- `bitcoin_hashes 0.17`: [changelog](https://github.com/rust-bitcoin/rust-bitcoin/blob/master/hashes/CHANGELOG.md) +- `hex-conservative 1.0.0`: [changelog](https://github.com/rust-bitcoin/hex-conservative/blob/1.x/CHANGELOG.md) +- `hex-conservative 0.3`: [changelog](https://github.com/rust-bitcoin/hex-conservative/blob/master/CHANGELOG.md) +- `bitcoin-io 0.2`: [changelog](https://github.com/rust-bitcoin/rust-bitcoin/blob/master/io/CHANGELOG.md) +- `bitcoin-primitives: 1.0.0-rc`: [changelog](https://github.com/rust-bitcoin/rust-bitcoin/blob/master/primitives/CHANGELOG.md) +- `bitcoin-units 1.0.0-rc`: [changelog](https://github.com/rust-bitcoin/rust-bitcoin/blob/master/units/CHANGELOG.md) +- `bitcoin-consensus-encoding 1.0.0-rc` [changelog](https://github.com/rust-bitcoin/rust-bitcoin/blob/master/consensus_encoding/CHANGELOG.md) + +## Worthy on note + +This release introduces an upper limit on the `Amount` type. + +- Remove `Amount::MAX` and replace it with the value in `MAX_MONEY` [#3691](https://github.com/rust-bitcoin/rust-bitcoin/issues/3691) +- Prepare to enforce `MAX_MONEY` invariant [#4164](https://github.com/rust-bitcoin/rust-bitcoin/pull/4164) +- Enforce `MAX_MONEY` invariant in amount types [#4157](https://github.com/rust-bitcoin/rust-bitcoin/pull/4157) +- Use `MAX_MONEY` in serde regression test [#3950](https://github.com/rust-bitcoin/rust-bitcoin/pull/3950) + +The `serde` serialization for `Psbt` has changed. + +- BREAKING: Change `Psbt` serde implementations [#4496](https://github.com/rust-bitcoin/rust-bitcoin/pull/4496) + +## Changes + +- Deprecate unchecked `amount` ops [#3759](https://github.com/rust-bitcoin/rust-bitcoin/pull/3759) +- Change parameter type used for whole bitcoin amounts [#3744](https://github.com/rust-bitcoin/rust-bitcoin/pull/3744) +- Add `Weight::to_kwu_ceil` [#3740](https://github.com/rust-bitcoin/rust-bitcoin/pull/3740) +- Remove `Weight::from_wu_usize` function [#3738](https://github.com/rust-bitcoin/rust-bitcoin/pull/3738) +- Move script hash types to `primitives` [#3734](https://github.com/rust-bitcoin/rust-bitcoin/pull/3734) +- units: Unify and flesh out ops impls [#3728](https://github.com/rust-bitcoin/rust-bitcoin/pull/3728) +- units: Seal the `Integer` trait [#3724](https://github.com/rust-bitcoin/rust-bitcoin/pull/3724) +- base58ck: Bump version to `0.2.0` [#3717](https://github.com/rust-bitcoin/rust-bitcoin/pull/3717) +- Explicitly define `Ord` for `NodeInfo` [#3699](https://github.com/rust-bitcoin/rust-bitcoin/pull/3699) +- Change `Amount::MAX` from `u64::MAX` to `Amount::MAX_MONEY` [#3693](https://github.com/rust-bitcoin/rust-bitcoin/pull/3693) +- Fix psbt fuzz crash [#3667](https://github.com/rust-bitcoin/rust-bitcoin/pull/3667) +- Update `from_next_work_required` to take an `i64` for timespan [#3660](https://github.com/rust-bitcoin/rust-bitcoin/pull/3660) +- Account for data pushing opcodes in `is_standard_op_return` [#3643](https://github.com/rust-bitcoin/rust-bitcoin/pull/3643) +- Add p2wpkh address creation example [#3642](https://github.com/rust-bitcoin/rust-bitcoin/pull/3642) +- Add `Address::into_unchecked` [#3640](https://github.com/rust-bitcoin/rust-bitcoin/pull/3640) +- Mark `checked_` functions as const [#3636](https://github.com/rust-bitcoin/rust-bitcoin/pull/3636) +- Mark functions const in `fee_rate` [#3627](https://github.com/rust-bitcoin/rust-bitcoin/pull/3627) +- Mark functions const [#3608](https://github.com/rust-bitcoin/rust-bitcoin/pull/3608) +- Add constructor to `FeeRate` [#3604](https://github.com/rust-bitcoin/rust-bitcoin/pull/3604) +- Fix bug in witness stack getters [#3601](https://github.com/rust-bitcoin/rust-bitcoin/pull/3601) +- Split `checked_div_by_weight` into floor and ceiling version [#3587](https://github.com/rust-bitcoin/rust-bitcoin/pull/3587) +- script: remove `unsafe` marker from slice-to-script conversions [#3569](https://github.com/rust-bitcoin/rust-bitcoin/pull/3569) +- io: Bump version to `0.1.3` [#3566](https://github.com/rust-bitcoin/rust-bitcoin/pull/3566) +- Re-export `block::Header` as `BlockHeader` [#3562](https://github.com/rust-bitcoin/rust-bitcoin/pull/3562) +- Bump `hex-conservative` to `0.3.0` [#3543](https://github.com/rust-bitcoin/rust-bitcoin/pull/3543) +- Re-organise the `amount` module [#3541](https://github.com/rust-bitcoin/rust-bitcoin/pull/3541) +- Improve the `amount` module [#3539](https://github.com/rust-bitcoin/rust-bitcoin/pull/3539) +- base58: Close all errors [#3533](https://github.com/rust-bitcoin/rust-bitcoin/pull/3533) +- psbt: Fix bug in `Subtype` consensus_encode [#3519](https://github.com/rust-bitcoin/rust-bitcoin/pull/3519) +- Explicitly re-export stuff from crates down the stack [#3497](https://github.com/rust-bitcoin/rust-bitcoin/pull/3497) +- Expose `units::amount::ParseError` [#3496](https://github.com/rust-bitcoin/rust-bitcoin/pull/3496) +- Make `Amount::to_sat and SignedAmount::to_sat` const [#3493](https://github.com/rust-bitcoin/rust-bitcoin/pull/3493) +- Decode an address string based on prefix [#3481](https://github.com/rust-bitcoin/rust-bitcoin/pull/3481) +- Replace `ENABLE_RBF_NO_LOCKTIME` with `ENABLE_LOCKTIME_AND_RBF` [#3459](https://github.com/rust-bitcoin/rust-bitcoin/pull/3459) +- Add version three variant to transaction version [#3450](https://github.com/rust-bitcoin/rust-bitcoin/pull/3450) +- Input weight prediction helpers for nested P2WPKH [#3443](https://github.com/rust-bitcoin/rust-bitcoin/pull/3443) +- Clarify sequence constant name and add `FINAL` [#3439](https://github.com/rust-bitcoin/rust-bitcoin/pull/3439) +- Add checked div by weight to amount [#3430](https://github.com/rust-bitcoin/rust-bitcoin/pull/3430) +- Rename `Midstate::into_parts` to `Midstate::to_parts` since it derives `Copy` [#3429](https://github.com/rust-bitcoin/rust-bitcoin/pull/3429) +- Const locktime constructors [#3421](https://github.com/rust-bitcoin/rust-bitcoin/pull/3421) +- Fix script number overflow check for `push_int` [#3392](https://github.com/rust-bitcoin/rust-bitcoin/pull/3392) +- transaction: Remove `Default` implementations [#3386](https://github.com/rust-bitcoin/rust-bitcoin/pull/3386) +- Add `FeeRate` addition and subtraction traits [#3381](https://github.com/rust-bitcoin/rust-bitcoin/pull/3381) +- Add `Xpriv::to_xpub` and improve related method names [#3358](https://github.com/rust-bitcoin/rust-bitcoin/pull/3358) +- Support `impl AsRef<[u8]>` in `signed_msg_hash` [#3357](https://github.com/rust-bitcoin/rust-bitcoin/pull/3357) +- Fix `GetKey` for sets (plus some related changes) [#3356](https://github.com/rust-bitcoin/rust-bitcoin/pull/3356) +- Add a condition for parsing zero from string when not denominated [#3346](https://github.com/rust-bitcoin/rust-bitcoin/pull/3346) +- Add basic `miri` checks [#3328](https://github.com/rust-bitcoin/rust-bitcoin/pull/3328) +- Add coinbase associated consts [#3308](https://github.com/rust-bitcoin/rust-bitcoin/pull/3308) +- Fix bug in `ArrayVec::extend_from_slice` [#3272](https://github.com/rust-bitcoin/rust-bitcoin/pull/3272) +- Change `T::from_str(s)` to `s.parse::()` in examples, docs and tests [#3262](https://github.com/rust-bitcoin/rust-bitcoin/pull/3262) +- Add `Arbitrary` to `Weight` [#3257](https://github.com/rust-bitcoin/rust-bitcoin/pull/3257) +- Bump `units` version [#3248](https://github.com/rust-bitcoin/rust-bitcoin/pull/3248) +- Rename key field in Key to key_data [#3048](https://github.com/rust-bitcoin/rust-bitcoin/pull/3048) +- Optimize `base58` on small inputs [#3002](https://github.com/rust-bitcoin/rust-bitcoin/pull/3002) +- Add `TxIdentifier` trait [#2987](https://github.com/rust-bitcoin/rust-bitcoin/pull/2987) +- Fix `Amount` decimals handling [#2951](https://github.com/rust-bitcoin/rust-bitcoin/pull/2951) +- `OP_RETURN` standardness check [#2949](https://github.com/rust-bitcoin/rust-bitcoin/pull/2949) +- Support Testnet4 Network [#2945](https://github.com/rust-bitcoin/rust-bitcoin/pull/2945) +- Remove `VarInt` and use `ReadExt` and `WriteExt` trait methods instead [#2931](https://github.com/rust-bitcoin/rust-bitcoin/pull/2931) +- bip32: Add `From<&'a [#u32]>` for `DerivationPath` [#2909](https://github.com/rust-bitcoin/rust-bitcoin/pull/2909) +- psbt: Encode keytype as a compact size unsigned integer [#2906](https://github.com/rust-bitcoin/rust-bitcoin/pull/2906) +- Pass sigs and associated types by value [#2899](https://github.com/rust-bitcoin/rust-bitcoin/pull/2899) +- Re-export `UnprefixedHexError` in the bitcoin crate root [#2895](https://github.com/rust-bitcoin/rust-bitcoin/pull/2895) +- taproot: Split errors up [#2886](https://github.com/rust-bitcoin/rust-bitcoin/pull/2886) +- Remove usage of `blockdata` from paths [#2885](https://github.com/rust-bitcoin/rust-bitcoin/pull/2885) +- Update `PushBytes::read_scriptint(x)` to `x.read_scriptint()` [#2872](https://github.com/rust-bitcoin/rust-bitcoin/pull/2872) +- Remove `Denomination::MilliSatoshi` [#2870](https://github.com/rust-bitcoin/rust-bitcoin/pull/2870) +- Pass keys by value [#2868](https://github.com/rust-bitcoin/rust-bitcoin/pull/2868) +- Clarify the meaning of `Height` & `Time` based locktime [#2858](https://github.com/rust-bitcoin/rust-bitcoin/pull/2858) +- Add API for extracting the inner payload of `RawNetworkMessage` [#2839](https://github.com/rust-bitcoin/rust-bitcoin/pull/2839) +- Update `bitcoinconsensus` version to `0.106.0+26` [#2833](https://github.com/rust-bitcoin/rust-bitcoin/pull/2833) +- Make `difficulty_float` general to all networks [#2816](https://github.com/rust-bitcoin/rust-bitcoin/pull/2816) +- Add const modifier to `Magic::from_bytes` [#2815](https://github.com/rust-bitcoin/rust-bitcoin/pull/2815) +- Add an `AddressData` type [#2808](https://github.com/rust-bitcoin/rust-bitcoin/pull/2808) +- Make `Address:p2sh_from_hash` public [#2795](https://github.com/rust-bitcoin/rust-bitcoin/pull/2795) +- Enable getting the witness program from an address [#2796](https://github.com/rust-bitcoin/rust-bitcoin/pull/2796) +- Enforce script size limit when hashing scripts [#2794](https://github.com/rust-bitcoin/rust-bitcoin/pull/2794) +- Deprecate `to_vec` in favour of `to_bytes` [#2768](https://github.com/rust-bitcoin/rust-bitcoin/pull/2768) +- Flesh out hex unit parsing API [#2765](https://github.com/rust-bitcoin/rust-bitcoin/pull/2765) +- Bench `base58` encoding and remove `SmallVec` to improve perf [#2759](https://github.com/rust-bitcoin/rust-bitcoin/pull/2759) +- Add difficulty adjustment calculation [#2740](https://github.com/rust-bitcoin/rust-bitcoin/pull/2740) +- Upgrade `base64` dependency [#2721](https://github.com/rust-bitcoin/rust-bitcoin/pull/2721) +- Some additional inspectors on `Script` and `Witness` [#2646](https://github.com/rust-bitcoin/rust-bitcoin/pull/2646) + +## Upgrade notes + +- `MAX_SCRIPT_ELEMENT_SIZE` was removed in [#2794](https://github.com/rust-bitcoin/rust-bitcoin/pull/2794) + you may want to use `MAX_REDEEM_SCRIPT_SIZE` or perhaps `MAX_STACK_ELEMENT_SIZE` (see `bitcoin/src/blockdata/constants`). +- `ecdsa::Error` was replaced by `ecdsa::DecodeError` and `ecdsa::ParseSignatureError` + (returned by `ecdsa::Signature::from_slice` and `from_str` respectively). +- `script::read_scriptint` was move to be a method on `PushBytes`. +- You can likely just remove the `hashes::Hash` trait import. +- Change `OutPoint::default()` to `OutPoint::COINBASE_PREVOUT` if appropriate. +- Change `TxIn::default()` to `TxIn::EMPTY_COINBASE` if appropriate. +- Change `to_raw_hash()` to `to_byte_array()`. +- `bitcoin::error::UnprefixedHexError` moved to `bitcoin::parse::UnprefixedHexError`. + +# 0.32.7 - 2025-07-30 + +- Backport - Use `_u32` in `FeeRate` constructor instead of `_unchecked` [#4552](https://github.com/rust-bitcoin/rust-bitcoin/pull/4552) +- Backport - Add support for pay to anchor outputs [#4691](https://github.com/rust-bitcoin/rust-bitcoin/pull/4691) +- Backport - Remove `non_exhaustive` from `Network` [#4658](https://github.com/rust-bitcoin/rust-bitcoin/pull/4658) + +# 0.32.6 - 2025-05-06 + +- Backport - Fix `is_invalid_use_of_sighash_single()` incompatibility with Bitcoin Core [#4122](https://github.com/rust-bitcoin/rust-bitcoin/pull/4122) +- Backport - Backport witness fixes [#4101](https://github.com/rust-bitcoin/rust-bitcoin/pull/4101) +- Backport - bip32: Return error when attempting to derive past maximum depth [#4434](https://github.com/rust-bitcoin/rust-bitcoin/pull/4434) +- Backport - Add `XOnlyPublicKey` support for PSBT key retrieval and improve Taproot signing [#4443](https://github.com/rust-bitcoin/rust-bitcoin/pull/4443) +- Backport - Add methods to retrieve inner types [#4450](https://github.com/rust-bitcoin/rust-bitcoin/pull/4450) + +# 0.32.5 - 2024-11-27 + +- Backport - Re-export `bech32` crate [#3662](https://github.com/rust-bitcoin/rust-bitcoin/pull/3662) +- Backport - Add API for extracting the inner payload of `RawNetworkMessage` [#3523](https://github.com/rust-bitcoin/rust-bitcoin/pull/3523) +- Backport - Fix bug in witness stack getters [#3626](https://github.com/rust-bitcoin/rust-bitcoin/pull/3626) +- Backport - address: Add `Address::into_unchecked` [#3655](https://github.com/rust-bitcoin/rust-bitcoin/pull/3655) + +# 0.32.4 - 2024-10-24 + +- Bound decode methods on `Read`, rather than `BufRead` [#3173](https://github.com/rust-bitcoin/rust-bitcoin/pull/3173) +- Backport - Some additional inspectors on `Script` and `Witness` [#2646](https://github.com/rust-bitcoin/rust-bitcoin/pull/2646) +- Backport - Add difficulty adjustment calculation [#3494](https://github.com/rust-bitcoin/rust-bitcoin/pull/3494) +- Backport - Add testnet 4 support [#3453](https://github.com/rust-bitcoin/rust-bitcoin/pull/3453) +- Backport - CI: Copy main workflow from master [#3418](https://github.com/rust-bitcoin/rust-bitcoin/pull/3418) + +# 0.32.3 - 2024-09-27 + +- Backport BIP-0032 alias' without typo [#3252](https://github.com/rust-bitcoin/rust-bitcoin/pull/3252) + +# 0.32.2 - 2024-06-07 + +- Fix a bug when parsing 256-bit numeric types [#2837](https://github.com/rust-bitcoin/rust-bitcoin/pull/2837) + +# 0.32.1 - 2024-05-29 + +Fix things we broke/removed from the `Address` API in the last release. + +- Enable getting the witness program from an address [#2804](https://github.com/rust-bitcoin/rust-bitcoin/pull/2804) +- Make `Address:p2sh_from_hash` public [#2806](https://github.com/rust-bitcoin/rust-bitcoin/pull/2806) +- Add an `AddressData` type [#2810](https://github.com/rust-bitcoin/rust-bitcoin/pull/2810) + +If you are looking for the `address::Payload` type we removed in `v0.32.0` then the `AddressData` type +might be what you are after. + +# 0.32.0 - 2024-04-23 + +- Bump MSRV to Rust 1.56.1 [#2188](https://github.com/rust-bitcoin/rust-bitcoin/pull/2188) +- Remove "no-std" feature [#2233](https://github.com/rust-bitcoin/rust-bitcoin/pull/2233) +- Enforce displaying `Amount` with trailing zeros [#2604](https://github.com/rust-bitcoin/rust-bitcoin/pull/2604) + +## Things you will almost certainly hit when upgrading + +- Rename `Signature` field names [#2338](https://github.com/rust-bitcoin/rust-bitcoin/pull/2338) + - `sig` becomes `signature` + - `hash_ty` becomes `sighash_type` +- Rename `txid` to `compute_txid` [#2366](https://github.com/rust-bitcoin/rust-bitcoin/pull/2366) +- In hardcoded BIP-0032 derivation paths: Remove `m/` prefix requirement [#2451](https://github.com/rust-bitcoin/rust-bitcoin/pull/2451) + +## Crate smashing + +This release we continued our effort to split up the library into +smaller crates AKA crate smashing. + +- Release new `bitcoin-units` crate [docs](https://docs.rs/bitcoin-units/0.1.1/bitcoin_units/) +- Release new `base58ck` crate [docs](https://docs.rs/base58ck/0.1.0/base58ck/) +- Release new `bitcoin-io` crate [docs](https://docs.rs/bitcoin-io/0.1.2/bitcoin_io/) + +## Bug fixes + +- Fix `FeeRate::checked_mul_by_weight` [#2182](https://github.com/rust-bitcoin/rust-bitcoin/pull/2182) +- Use network when calculating difficulty [#2168](https://github.com/rust-bitcoin/rust-bitcoin/pull/2168) +- Fix `InputWeightPrediction::P2WPKH_MAX` constant DER sig length [#2213](https://github.com/rust-bitcoin/rust-bitcoin/pull/2213) +- Fix CJDNS marker byte check [#2546](https://github.com/rust-bitcoin/rust-bitcoin/pull/2546) +- Add resource limit check during deserialization of Merkle block [#2607](https://github.com/rust-bitcoin/rust-bitcoin/pull/2607) + +## Changes to and involving the `Network` type + +In release 0.31.0 we managed to annoy a lot of people by the addition of `non_exhaustive` to the +`Network` type. After much discussion, and in an effort to cater to multiple camps, we did a bunch +of changes this release. To sum up, "network" is ill defined and it means different things to +different devs/software. Your software should probably have some custom handling of whatever +"network" means to you. + +In particular consider having some type that implements `AsRef`, we have attempted to + replace `Network` in much of the API ([#2541](https://github.com/rust-bitcoin/rust-bitcoin/pull/2541)). + +- Add `NetworkKind` [#2232](https://github.com/rust-bitcoin/rust-bitcoin/pull/2232) +- Reduce usage of `Network` in the public API [#2541](https://github.com/rust-bitcoin/rust-bitcoin/pull/2541) +- Remove `Network` from `AddressInner` [#1832](https://github.com/rust-bitcoin/rust-bitcoin/pull/1832) +- Add consts to `Params` for individual networks [#2396](https://github.com/rust-bitcoin/rust-bitcoin/pull/2396) +- Add `params()` method to `Network` [#2172](https://github.com/rust-bitcoin/rust-bitcoin/pull/2172) +- Use `KnowHrp`` instead of `Network` [#2387](https://github.com/rust-bitcoin/rust-bitcoin/pull/2387) +- Add check to max difficulty transition threshold [#2337](https://github.com/rust-bitcoin/rust-bitcoin/pull/2337) + +## Other API additions + +- Add `CompressedPublicKey` [#2277](https://github.com/rust-bitcoin/rust-bitcoin/pull/2277) +- Add a `consensus::deserialize_hex` function [#2039](https://github.com/rust-bitcoin/rust-bitcoin/pull/2039) +- Add `Witness::p2tr_key_spend` function [#2097](https://github.com/rust-bitcoin/rust-bitcoin/pull/2097) +- Add `taproot::SerializedSignature` [#2156](https://github.com/rust-bitcoin/rust-bitcoin/pull/2156) +- Add input weight predictions for p2pkh outputs [#2185](https://github.com/rust-bitcoin/rust-bitcoin/pull/2185) +- Add `Weight::from_vb_weight function` function (added in [#2206](https://github.com/rust-bitcoin/rust-bitcoin/pull/2206), + renamed in [#2228](https://github.com/rust-bitcoin/rust-bitcoin/pull/2228) +- Implement `LowerHex` and `UpperHex` for `CompactTarget` [#2221](https://github.com/rust-bitcoin/rust-bitcoin/pull/2221) +- Add conversions from TXIDs to Merkle nodes [#2227](https://github.com/rust-bitcoin/rust-bitcoin/pull/2227) +- Add `transaction::effective_value()` function [#2230](https://github.com/rust-bitcoin/rust-bitcoin/pull/2230) +- Improve `LockTime`s and related types: + - Improve relative locktime API [#2549](https://github.com/rust-bitcoin/rust-bitcoin/pull/2549) + - Implement `ordered::ArbitraryOrd` for absolute and relative locktimes, introducing the "ordered" feature: + - [#2581](https://github.com/rust-bitcoin/rust-bitcoin/pull/2581) + - [#2248](https://github.com/rust-bitcoin/rust-bitcoin/pull/2248) +- Add and use custom `ArrayVec` + - [#2287](https://github.com/rust-bitcoin/rust-bitcoin/pull/2287) + - [#2286](https://github.com/rust-bitcoin/rust-bitcoin/pull/2286) + - [#2310](https://github.com/rust-bitcoin/rust-bitcoin/pull/2310) +- Add the implementation of `Display` for `transaction::Version` [#2309](https://github.com/rust-bitcoin/rust-bitcoin/pull/2309) +- Add functionality to serialize signatures to a writer [#2392](https://github.com/rust-bitcoin/rust-bitcoin/pull/2392) +- Add unchecked integer operations to `Amount` and `SignedAmount` (add, sum etc.) [#2436](https://github.com/rust-bitcoin/rust-bitcoin/pull/2436) +- Add methods `p2wpkh_script_code` to `Script` and `ScriptBuf` [#2445](https://github.com/rust-bitcoin/rust-bitcoin/pull/2445) +- Improve API for signing Taproot inputs in PSBTs [#2458](https://github.com/rust-bitcoin/rust-bitcoin/pull/2458) +- Add `TapNodeHash` getter method on `TapTree` and `NodeInfo` [#2467](https://github.com/rust-bitcoin/rust-bitcoin/pull/2467) +- Add hex parsing to pow types [#2514](https://github.com/rust-bitcoin/rust-bitcoin/pull/2514) +- Implement `From` for errors [#2516](https://github.com/rust-bitcoin/rust-bitcoin/pull/2516) +- Add ServiceFlags::P2P_V2 [#2555](https://github.com/rust-bitcoin/rust-bitcoin/pull/2555) + +## Other API breaking changes + +- Require `io::BufRead` instead of `io::Read` in consensus decode trait [#2240](https://github.com/rust-bitcoin/rust-bitcoin/pull/2240) +- Make `Payload` and `AddressEncoding` private [#1979](https://github.com/rust-bitcoin/rust-bitcoin/pull/1979) +- Remove `bech32` from the public API [#2381](https://github.com/rust-bitcoin/rust-bitcoin/pull/2381) +- Make from_hex inherent for byte-like types [#2491](https://github.com/rust-bitcoin/rust-bitcoin/pull/2491) +- Remove the FromHexStr trait [#2492](https://github.com/rust-bitcoin/rust-bitcoin/pull/2492) + +## Error handling + +- Split `Prevouts` errors out into specific error types [#2042](https://github.com/rust-bitcoin/rust-bitcoin/pull/2042) +- Improve error handling in the `sighash` module [#2329](https://github.com/rust-bitcoin/rust-bitcoin/pull/2329) +- Improve lock time errors [#2417](https://github.com/rust-bitcoin/rust-bitcoin/pull/2417) +- Split relative locktime error up [#2433](https://github.com/rust-bitcoin/rust-bitcoin/pull/2433) +- Improve `amount` module errors [#2487](https://github.com/rust-bitcoin/rust-bitcoin/pull/2487) +- Add the `FromScriptError` for handling errors in address [#2497](https://github.com/rust-bitcoin/rust-bitcoin/pull/2497) +- Add `NetworkValidationError` [#2508](https://github.com/rust-bitcoin/rust-bitcoin/pull/2508) but don't return it [#2610](https://github.com/rust-bitcoin/rust-bitcoin/pull/2610) +- Improve leaf errors ("leaf" means not enum with nested error type) [#2530](https://github.com/rust-bitcoin/rust-bitcoin/pull/2530) + +# 0.31.1 - 2024-01-09 + +- Fix bug in `FeeRate::checked_mul_by_weight` [#2128](https://github.com/rust-bitcoin/rust-bitcoin/pull/2182) +- Add BIP-0032 types remove in 0.31 back in and mark as deprecated [#2258](https://github.com/rust-bitcoin/rust-bitcoin/pull/2258) + +# 0.31.0 - 2023-10-18 + +- Bump MSRV to Rust 1.48.0 [#1729](https://github.com/rust-bitcoin/rust-bitcoin/pull/1729) +- Add new example code for signature verification [#1776](https://github.com/rust-bitcoin/rust-bitcoin/pull/1776) +- Manually implement `Debug` on `Witness` [#1913](https://github.com/rust-bitcoin/rust-bitcoin/pull/1913) +- Use new bech32 API [#1951](https://github.com/rust-bitcoin/rust-bitcoin/pull/1951) and [#2117](https://github.com/rust-bitcoin/rust-bitcoin/pull/2117) +- Upgrade to `secp256k1 v0.28.0` [#2098](https://github.com/rust-bitcoin/rust-bitcoin/pull/2098) +- Upgrade to `base64 v0.21.3` [#2032](https://github.com/rust-bitcoin/rust-bitcoin/pull/2032) + +- API Improvements: + - Add kilo weight unit conversion [#1735](https://github.com/rust-bitcoin/rust-bitcoin/pull/1735) + - Add `ChainHash::from_genesis_block_hash`[#1753](https://github.com/rust-bitcoin/rust-bitcoin/pull/1753) + - Add implementation of `PartialEq` trait for `Address` [#1757](https://github.com/rust-bitcoin/rust-bitcoin/pull/1757) + - Add unsafe address type conversions [#1765](https://github.com/rust-bitcoin/rust-bitcoin/pull/1765) + - Add `Inventory::network_hash()` method [#515](https://github.com/rust-bitcoin/rust-bitcoin/pull/515) + - Implement `serde::Serialize` for `Address` [#1785](https://github.com/rust-bitcoin/rust-bitcoin/pull/1785) + - Expose valid (min, max) difficulty transition thresholds [#1820](https://github.com/rust-bitcoin/rust-bitcoin/pull/1820) + - Add functionality to generate `PrivateKey` [#1837](https://github.com/rust-bitcoin/rust-bitcoin/pull/1837) + - Allow parsing sub-sat denominations with decimal points [#1768](https://github.com/rust-bitcoin/rust-bitcoin/pull/1768) + - Fix associated constants of `InputWeightPrediction` [#1835](https://github.com/rust-bitcoin/rust-bitcoin/pull/1835) + - Add `FeeRate::checked_mul_by_weight` [#1864](https://github.com/rust-bitcoin/rust-bitcoin/pull/1864) + - Use `Amount` type for the `TxOut` value field [#1811](https://github.com/rust-bitcoin/rust-bitcoin/pull/1811) + - Add support for alloc-free parse errors [#1297](https://github.com/rust-bitcoin/rust-bitcoin/pull/1297) + - Add `Amount::from_int_btc` [#1870](https://github.com/rust-bitcoin/rust-bitcoin/pull/1870) + - Make `ckd_priv` function private and impl `AsRef` for `ChildNumber` [#1882](https://github.com/rust-bitcoin/rust-bitcoin/pull/1882) + - Use `hex_lit::hex` in benches (also backported to v0.30.1) [#1941](https://github.com/rust-bitcoin/rust-bitcoin/pull/1941) + - Add a verify function to `PublicKey` [#1911](https://github.com/rust-bitcoin/rust-bitcoin/pull/1911) + - Add method `Script::count_sigops` [#1890](https://github.com/rust-bitcoin/rust-bitcoin/pull/1890) + - Implement `From for XOnlyPublicKey` [#1901](https://github.com/rust-bitcoin/rust-bitcoin/pull/1901) + - Implement `From for bitcoin::PublicKey` [#1949](https://github.com/rust-bitcoin/rust-bitcoin/pull/1949) + - Add `DerivationPath::to_u32_vec` [#1946](https://github.com/rust-bitcoin/rust-bitcoin/pull/1946) + - Use `Target` as type for `pow_limit` [#2107](https://github.com/rust-bitcoin/rust-bitcoin/pull/2107) + - Add `Witness::p2wpkh` constructor [#2084](https://github.com/rust-bitcoin/rust-bitcoin/pull/2084) + - Make `Instruction` be able to read the script number [#2081](https://github.com/rust-bitcoin/rust-bitcoin/pull/2081) + - Add `Script::is_mulitsig` [#2078](https://github.com/rust-bitcoin/rust-bitcoin/pull/2078) + - Count sigops for `Transaction` [#2073](https://github.com/rust-bitcoin/rust-bitcoin/pull/2073) + - Add `Psbt` fee checks [#2064](https://github.com/rust-bitcoin/rust-bitcoin/pull/2064) + - Add version bytes consts [#2020](https://github.com/rust-bitcoin/rust-bitcoin/pull/2020) + - Add `transaction::Version` data type [#2006](https://github.com/rust-bitcoin/rust-bitcoin/pull/2006) + +- Moves, Removes, and renames: + - Move witness types to the script module [#1846](https://github.com/rust-bitcoin/rust-bitcoin/pull/1846) + - Remove reexport of `psbt::Prevouts` [#1872](https://github.com/rust-bitcoin/rust-bitcoin/pull/1872) + - Rename `Transaction::is_coin_base` to `is_coinbase` [#1796](https://github.com/rust-bitcoin/rust-bitcoin/pull/1796) + - Rename `TaprootSpendInfo::as_script_map` to `script_map` [#1897](https://github.com/rust-bitcoin/rust-bitcoin/pull/1897) + - Rename `Script::empty` to `Script::new` [#1925](https://github.com/rust-bitcoin/rust-bitcoin/pull/1925) + - Rename `PartiallySignedTransaction` to `Psbt` [#1938](https://github.com/rust-bitcoin/rust-bitcoin/pull/1938) + - Rename `XpubIdenifier` to `XKeyIdentifier` [#2021](https://github.com/rust-bitcoin/rust-bitcoin/pull/2021) + - Rename `ExtendedPubKey` to `Xpub` [#2019](https://github.com/rust-bitcoin/rust-bitcoin/pull/2019) + - Rename `ExtendedPrivKey` to `Xpriv` [#2019](https://github.com/rust-bitcoin/rust-bitcoin/pull/2019) + - Remove `_v0` from various function names (eg, `new_v0_p2wpkh`) [#1994](https://github.com/rust-bitcoin/rust-bitcoin/pull/1994) + - Remove `SighashCache::segwit_signature_hash` (add `p2wpkh_signature_hash` and `p2wsh_signature_hash`) [#1995](https://github.com/rust-bitcoin/rust-bitcoin/pull/1995) + - Reexport all the hash types from the crate root [#1998](https://github.com/rust-bitcoin/rust-bitcoin/pull/1998) + - Rename `opcodes::All` to `Opcode` [#1995](https://github.com/rust-bitcoin/rust-bitcoin/pull/1995) + - Removed `TxOut::default()`, the same logic now exists as `TxOut::NULL` [#1811](https://github.com/rust-bitcoin/rust-bitcoin/pull/1811) and [#1838](https://github.com/rust-bitcoin/rust-bitcoin/pull/1838) + +- Error handling improvements: + - Improve `hashes::Error` [#1873](https://github.com/rust-bitcoin/rust-bitcoin/pull/1873) + - Add `ValidationError` [#1874](https://github.com/rust-bitcoin/rust-bitcoin/pull/1874) + - Improve `crypto::taproot` error type [#1895](https://github.com/rust-bitcoin/rust-bitcoin/pull/1895) + - Audit error types code base wide [#2101](https://github.com/rust-bitcoin/rust-bitcoin/pull/2101) + +# 0.30.2 - 2023-11-16 + +- Expose valid (min, max) difficulty transition thresholds [#1820](Expose valid (min, max) difficulty transition thresholds) + +# 0.30.1 - 2023-07-16 + +- Fix compilation when [`RUSTFLAGS=--cfg=bench` is set](https://github.com/rust-bitcoin/rust-bitcoin/pull/1943) + +# 0.30 - 2023-03-21 "The First Crate-Smashing Release" + +We now have a website for crates that live under the `rust-bitcoin` GitHub organization: https://rust-bitcoin.org/ + +This release is big, to help users upgrade we wrote a blog post, please see https://rust-bitcoin.org/blog/release-0.30.0/ + +- [Import `bitcoin_hashes`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1284) into this repository. + +- Update dependencies we control + - Depend on the new private crate `bitcoin-private` + - Depend on the new `bitcoin_hashes` v0.12 + - Depend on the new `secp256k1` v0.27 + +- We moved a lot of modules around, specifically we move basically everything out of `util`. + +- API improvements: + - [Use marker type to enforce validation of `Address`'s network](https://github.com/rust-bitcoin/rust-bitcoin/pull/1489) + - [New `Witness` features](https://github.com/rust-bitcoin/rust-bitcoin/pull/1323) + - [`Witness` API improvements](https://github.com/rust-bitcoin/rust-bitcoin/pull/1380) + - Renamed `Script` to `ScriptBuf` and [added a new unsized type](https://github.com/rust-bitcoin/rust-bitcoin/pull/1155) `Script` + - [Add `tapscript_leaf_hash()` to `Script`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1485) + - [Unify `TapLeafHash` and `TapBranchHash` into `TapNodeHash` while tree construction](https://github.com/rust-bitcoin/rust-bitcoin/pull/1479) + - [Add `Script::builder` convenience function](https://github.com/rust-bitcoin/rust-bitcoin/pull/1312) + - [Implement `PartiallySignedTransaction::fee`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1338) + - [Implement `Script::p2pk_public_key(&self) -> Option`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1412) + - [Add `log2` to `Work`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1437) + - [Add weight utilities to `TxIn` and `TxOut`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1467) + - [Add conversions for `TweakedKeyPair` -> `TweakedPublicKey`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1583) + - [Add `From
` for `ScriptBuf`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1592) + - [Rename `from_slice` methods to `decode`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1621) + - [Add methods for pushing locktimes to scripts](https://github.com/rust-bitcoin/rust-bitcoin/pull/1629) + - [Create Address::matches_script_pubkey method](https://github.com/rust-bitcoin/rust-bitcoin/pull/1663) + - [Add API method `absolute::LockTime::is_satisfied_by_lock`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1258) + - [Add `FromHexStr`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1400) for parsing strings with and without `0x` prefix + - [Add CentiBitcoin to denominations](https://github.com/rust-bitcoin/rust-bitcoin/pull/1715) + - [Add `difficulty_float` method for `block::Header`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1720) + +- Various sighash code moves, and type improvements: + - [Improve `SighashCache` API](https://github.com/rust-bitcoin/rust-bitcoin/pull/1625) + - [Do not export unusual hash types at crate root](https://github.com/rust-bitcoin/rust-bitcoin/pull/1617) + - [Move sighash types around](https://github.com/rust-bitcoin/rust-bitcoin/pull/1597) + - [Try to fix up sighash export mess](https://github.com/rust-bitcoin/rust-bitcoin/pull/1277) + +- New types: + - `ScriptBuf` ([Implement unsized `Script`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1155). + - [Network `Magic`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1288) + - [Add `Weight` and `FeeRate` newtypes](https://github.com/rust-bitcoin/rust-bitcoin/pull/1627) + - [Add `Target` and `Work` types](https://github.com/rust-bitcoin/rust-bitcoin/pull/1197) + - [Add `relative::LockTime` type](https://github.com/rust-bitcoin/rust-bitcoin/pull/1196) + +- Removed types/traits: + - [Remove `ToHex`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1531) + - [Remove code deprecated in v0.28](https://github.com/rust-bitcoin/rust-bitcoin/pull/1276) + - Remove `PackedLockTime`, [replace with richer `LockTime` everywhere](https://github.com/rust-bitcoin/rust-bitcoin/pull/1330) + Be aware that `LockTime` does not have an `Ord` implementation, so users who need a + total ordering on locktimes will be forced to wrap this type. In `Transaction`, which + contains a `LockTime` but is `Ord`, we have manually sorted the locktimes based on + their consensus encoding. This ordering is somewhat arbitrary -- there is no total + ordering on locktimes since they may be measured in either blocks or seconds. + - [Removed `FromHex` implementation](https://github.com/rust-bitcoin/rust-bitcoin/pull/1565) from + all types except `Vec` and arrays, replace where appropriate with `FromStr`. + +- Performance improvements: + - [Remove needless allocation from BIP-0158 encoding](https://github.com/rust-bitcoin/rust-bitcoin/pull/1146) + - [Implement fast hex encoding](https://github.com/rust-bitcoin/rust-bitcoin/pull/1268) (usage added in a [later PR](https://github.com/rust-bitcoin/rust-bitcoin/pull/1476)) + +- Testing improvements: + - Started using [kani](https://github.com/model-checking/kani) + - Started using [mutagen](https://github.com/llogiq/mutagen) + +# 0.29 - 2022-07-20 "Edition 2018 Release" + +As promised, this is our quick release to bring on edition 2018 by increasing our MSRV to Rust +1.41.1 [#983](https://github.com/rust-bitcoin/rust-bitcoin/pull/983) + +This work saw a bunch of new language features become available to us. At the +same time we were able to start using `rustfmt`. We also started linting as part +of CI. + +## Breaking changes + +There are numerous breaking changes in this release related to the new language features but also +other improvements such as more newtypes added. Note that not all changes cause compilation failure! +For example, [`Witness` serialization was changed](https://github.com/rust-bitcoin/rust-bitcoin/pull/1068) +to support human-readable formats. + +[Detailed list of breaking changes](https://github.com/rust-bitcoin/rust-bitcoin/pulls?q=is%3Apr+label%3A%22API+break%22+is%3Aclosed+milestone%3A0.29.0+) + +## Highlights + +- Added support for BIP 152 [#1088](https://github.com/rust-bitcoin/rust-bitcoin/pull/1088) +- Edition 2018 improvements + - Implement `TryFrom` [#1007](https://github.com/rust-bitcoin/rust-bitcoin/pull/1007) + - Add `non_exhaustive` to all error enums [#1026](https://github.com/rust-bitcoin/rust-bitcoin/pull/1026) + - Various other improvements, see [tracking issue](https://github.com/rust-bitcoin/rust-bitcoin/issues/510) for more information. +- Enable `clippy` on CI [#1061](https://github.com/rust-bitcoin/rust-bitcoin/pull/1061) +- Taproot improvements + [#950](https://github.com/rust-bitcoin/rust-bitcoin/pull/950) [#936](https://github.com/rust-bitcoin/rust-bitcoin/pull/936) +- serde improvements/changes + [#1006](https://github.com/rust-bitcoin/rust-bitcoin/pull/1006) [#905](https://github.com/rust-bitcoin/rust-bitcoin/pull/905) + [#1071](https://github.com/rust-bitcoin/rust-bitcoin/pull/1071) [] +- Performance improvements + [#1033](https://github.com/rust-bitcoin/rust-bitcoin/pull/1033) [#996](https://github.com/rust-bitcoin/rust-bitcoin/pull/996) + [#1053](https://github.com/rust-bitcoin/rust-bitcoin/pull/1053) [#1023](https://github.com/rust-bitcoin/rust-bitcoin/pull/1023) +- PSBT improvements + [#853](https://github.com/rust-bitcoin/rust-bitcoin/pull/853) [#951](https://github.com/rust-bitcoin/rust-bitcoin/pull/951) + [#940](https://github.com/rust-bitcoin/rust-bitcoin/pull/940) +- Script improvements + [#1021](https://github.com/rust-bitcoin/rust-bitcoin/pull/1021) [#954](https://github.com/rust-bitcoin/rust-bitcoin/pull/954) +- New types that may be of interest + - `Sequence`, transaction sequence number [#1093](https://github.com/rust-bitcoin/rust-bitcoin/pull/1093) + - `ChainHash`, as used in Lightning [#878](https://github.com/rust-bitcoin/rust-bitcoin/pull/878) + - `LockTime`, transaction nLockTime [#994](https://github.com/rust-bitcoin/rust-bitcoin/pull/994) +- Improve pubkey sorting: [#1084](https://github.com/rust-bitcoin/rust-bitcoin/pull/1084) +- Introduce `rustfmt` [#1040](https://github.com/rust-bitcoin/rust-bitcoin/pull/1040) +- Dependencies + - Upgrade to use `bitcoinconsensus` v0.20.2-0.5.0 [#1165](https://github.com/rust-bitcoin/rust-bitcoin/pull/1165) + - Upgrade to use `secp256k1` v0.24.0 [#1110](https://github.com/rust-bitcoin/rust-bitcoin/pull/1110) + - Upgrade to use `bech32` v0.9.0 [#1131](https://github.com/rust-bitcoin/rust-bitcoin/pull/1131) + - Remove `base64-compat` in favour of `base64` [#993](https://github.com/rust-bitcoin/rust-bitcoin/pull/993) + - Do not pin transitive `ryu` dependency [#1013](https://github.com/rust-bitcoin/rust-bitcoin/pull/1013) +- Take `Writer`/`Reader` by `&mut` in consensus en/decoding [#1035](https://github.com/rust-bitcoin/rust-bitcoin/pull/1035) +- Consume `self` in conversion methods named `to_*` instead of borrowing [#1161](https://github.com/rust-bitcoin/rust-bitcoin/pull/1161) + +# 0.28.2 - 2022-11-01 + +Backported a set of changes from 0.29 which may cause some specific +transactions and/or blocks to fail to deserialize. No known such transactions +exist on any public blockchain. + +# 0.28 - 2022-04-20 "The Taproot Release" + +At nearly nine months, this is our longest release cycle ever, and thanks +to a huge increase in the number of active contributors this year and last, +it is also **by far** our largest release ever, at 148 PRs merged from 23 +different contributors. Our primary goal in this release was to introduce +support for Taproot and its associated data structures: addresses, taptrees, +sighashes, PSBT fields, and more. As it turned out, these changes required +(or at least, incentivized) changing a lot of our APIs, causing a significant +increase in scope. + +We have more big changes coming down the pike. 2022 is going to be a big +year for `rust-bitcoin`, which we know is exciting for us but disruptive to +downstream users who ultimately want the library to just work. Our hope is +that by 2023 we will have eliminated large amounts of technical debt, +modernized our APIs to meet current Rust conventions, and clarified the scope +of the individual crates in this ecosystem while still providing the essential +functionality needed by our downstream users, especially wallet projects. + +We will also develop a plan to make our releases more predictable and manageable, +likely by having scheduled releases with limited scope. We would like to reach +a point where we no longer have frequent breaking releases, but right now we +are nowhere close. + +Upcoming changes will include +- A quick new release which updates our MRSV from 1.29 to 1.41 and does little else +- Updating our codebase to take advantage of the new MSRV, especially regarding +nostd and wasm support +- A comprehensive rethinking and flattening of our public-facing APIs +- Richer support for PSBT, Script, and BIP-0340/Schnorr signatures + +With so many changes since 0.27, we cannot list every PR. Here are the highlights: + +- Remove dangerous `fuzztarget` cargo feature [#634](https://github.com/rust-bitcoin/rust-bitcoin/pull/634) +- Improve serde serialization for `Script` [#596](https://github.com/rust-bitcoin/rust-bitcoin/pull/596) +- Documentation improvements [#623](https://github.com/rust-bitcoin/rust-bitcoin/pull/623) [#633](https://github.com/rust-bitcoin/rust-bitcoin/pull/633) [#663](https://github.com/rust-bitcoin/rust-bitcoin/pull/663) [#689](https://github.com/rust-bitcoin/rust-bitcoin/pull/689) [#704](https://github.com/rust-bitcoin/rust-bitcoin/pull/704) [#744](https://github.com/rust-bitcoin/rust-bitcoin/pull/744) [#852](https://github.com/rust-bitcoin/rust-bitcoin/pull/852) [#869](https://github.com/rust-bitcoin/rust-bitcoin/pull/869) [#865](https://github.com/rust-bitcoin/rust-bitcoin/pull/865) [#864](https://github.com/rust-bitcoin/rust-bitcoin/pull/864) [#858](https://github.com/rust-bitcoin/rust-bitcoin/pull/858) [#806](https://github.com/rust-bitcoin/rust-bitcoin/pull/806) [#877](https://github.com/rust-bitcoin/rust-bitcoin/pull/877) [#912](https://github.com/rust-bitcoin/rust-bitcoin/pull/912) [#923](https://github.com/rust-bitcoin/rust-bitcoin/pull/923) +- Introduce `WitnessVersion` type [#617](https://github.com/rust-bitcoin/rust-bitcoin/pull/617) +- Improve error types and API [#625](https://github.com/rust-bitcoin/rust-bitcoin/pull/625) +- Implement `Block.get_strippedsize()` and `Transaction.get_vsize()` [#626](https://github.com/rust-bitcoin/rust-bitcoin/pull/626) +- Add Bloom filter network messages [#580](https://github.com/rust-bitcoin/rust-bitcoin/pull/580) +- **Taproot:** add signature hash support [#628](https://github.com/rust-bitcoin/rust-bitcoin/pull/628) [#702](https://github.com/rust-bitcoin/rust-bitcoin/pull/702) [#722](https://github.com/rust-bitcoin/rust-bitcoin/pull/722) [#835](https://github.com/rust-bitcoin/rust-bitcoin/pull/835) [#903](https://github.com/rust-bitcoin/rust-bitcoin/pull/903) [#796](https://github.com/rust-bitcoin/rust-bitcoin/pull/796) +- **Taproot:** add new Script opcodes [#644](https://github.com/rust-bitcoin/rust-bitcoin/pull/644) [#721](https://github.com/rust-bitcoin/rust-bitcoin/pull/721) [#868](https://github.com/rust-bitcoin/rust-bitcoin/pull/868) [#920](https://github.com/rust-bitcoin/rust-bitcoin/pull/920) +- **Taproot:** add bech32m support, addresses and new key types [#563](https://github.com/rust-bitcoin/rust-bitcoin/pull/563) [#691](https://github.com/rust-bitcoin/rust-bitcoin/pull/691) [#697](https://github.com/rust-bitcoin/rust-bitcoin/pull/697) [#728](https://github.com/rust-bitcoin/rust-bitcoin/pull/728) [#696](https://github.com/rust-bitcoin/rust-bitcoin/pull/696) [#757](https://github.com/rust-bitcoin/rust-bitcoin/pull/757) +- **Taproot:** add taptree data structures [#677](https://github.com/rust-bitcoin/rust-bitcoin/pull/677) [#703](https://github.com/rust-bitcoin/rust-bitcoin/pull/703) [#701](https://github.com/rust-bitcoin/rust-bitcoin/pull/701) [#718](https://github.com/rust-bitcoin/rust-bitcoin/pull/718) [#845](https://github.com/rust-bitcoin/rust-bitcoin/pull/845) [#901](https://github.com/rust-bitcoin/rust-bitcoin/pull/901) [#910](https://github.com/rust-bitcoin/rust-bitcoin/pull/910) [#909](https://github.com/rust-bitcoin/rust-bitcoin/pull/909) [#914](https://github.com/rust-bitcoin/rust-bitcoin/pull/914) +- no-std improvements [#637](https://github.com/rust-bitcoin/rust-bitcoin/pull/637) +- PSBT improvements, including Taproot [#654](https://github.com/rust-bitcoin/rust-bitcoin/pull/654) [#681](https://github.com/rust-bitcoin/rust-bitcoin/pull/681) [#669](https://github.com/rust-bitcoin/rust-bitcoin/pull/669) [#774](https://github.com/rust-bitcoin/rust-bitcoin/pull/774) [#779](https://github.com/rust-bitcoin/rust-bitcoin/pull/779) [#752](https://github.com/rust-bitcoin/rust-bitcoin/pull/752) [#776](https://github.com/rust-bitcoin/rust-bitcoin/pull/776) [#790](https://github.com/rust-bitcoin/rust-bitcoin/pull/790) [#836](https://github.com/rust-bitcoin/rust-bitcoin/pull/836) [#847](https://github.com/rust-bitcoin/rust-bitcoin/pull/847) [#842](https://github.com/rust-bitcoin/rust-bitcoin/pull/842) +- serde improvements [#672](https://github.com/rust-bitcoin/rust-bitcoin/pull/672) +- Update rust-secp256k1 dependency [#694](https://github.com/rust-bitcoin/rust-bitcoin/pull/694) [#755](https://github.com/rust-bitcoin/rust-bitcoin/pull/755) [#875](https://github.com/rust-bitcoin/rust-bitcoin/pull/875) +- Change BIP32 to use rust-secp256k1 keys rather than rust-bitcoin ones (no compressedness flag) [#590](https://github.com/rust-bitcoin/rust-bitcoin/pull/590) [#591](https://github.com/rust-bitcoin/rust-bitcoin/pull/591) +- Rename inner key field in `PrivateKey` and `PublicKey` [#762](https://github.com/rust-bitcoin/rust-bitcoin/pull/762) +- Address and denomination related changes [#768](https://github.com/rust-bitcoin/rust-bitcoin/pull/768) [#784](https://github.com/rust-bitcoin/rust-bitcoin/pull/784) +- Don't allow hybrid EC keys [#829](https://github.com/rust-bitcoin/rust-bitcoin/pull/829) +- Change erroneous behavior for `SIGHASH_SINGLE` bug [#860](https://github.com/rust-bitcoin/rust-bitcoin/pull/860) [#897](https://github.com/rust-bitcoin/rust-bitcoin/pull/897) +- Delete the deprecated `contracthash` module [#871](https://github.com/rust-bitcoin/rust-bitcoin/pull/871); this functionality will migrate to ElementsProject/rust-elements +- Remove compilation-breaking feature-gating of enum variants" [#881](https://github.com/rust-bitcoin/rust-bitcoin/pull/881) + +Additionally we made several minor API changes (renaming methods, etc.) to improve +compliance with modern Rust conventions. Where possible we left the existing methods +in place, marked as deprecated. + +# 0.27 - 2021-07-21 + +- [Bigendian fixes and CI test](https://github.com/rust-bitcoin/rust-bitcoin/pull/627) +- [no_std support, keeping MSRV](https://github.com/rust-bitcoin/rust-bitcoin/pull/603) +- [Bech32m adoption](https://github.com/rust-bitcoin/rust-bitcoin/pull/601) +- [Use Amount type for dust value calculation](https://github.com/rust-bitcoin/rust-bitcoin/pull/616) +- [Errors enum improvements](https://github.com/rust-bitcoin/rust-bitcoin/pull/521) +- [std -> core](https://github.com/rust-bitcoin/rust-bitcoin/pull/614) + +# 0.26.2 - 2021-06-08 + +- [Fix `Display` impl of `ChildNumber`](https://github.com/rust-bitcoin/rust-bitcoin/pull/611) + +The previous release changed the behavior of `Display` for `ChildNumber`, assuming that any correct usage would not be +affected. [Issue 608](https://github.com/rust-bitcoin/rust-bitcoin/issues/608) goes into the details of why this isn't +the case and how we broke both `rust-miniscript` and BDK. + +# 0.26.1 - 2021-06-06 (yanked, see explanation above) + +- [Change Amount Debug impl to BTC with 8 decimals](https://github.com/rust-bitcoin/rust-bitcoin/pull/414) +- [Make uint types (un)serializable](https://github.com/rust-bitcoin/rust-bitcoin/pull/511) +- Add [more derives for key::Error](https://github.com/rust-bitcoin/rust-bitcoin/pull/551) +- [Fix optional amount serialization](https://github.com/rust-bitcoin/rust-bitcoin/pull/552) +- Add [PSBT base64 (de)serialization with Display & FromStr](https://github.com/rust-bitcoin/rust-bitcoin/pull/557) +- Add [non-API breaking derives for error & transaction types](https://github.com/rust-bitcoin/rust-bitcoin/pull/558) +- [Fix error derives](https://github.com/rust-bitcoin/rust-bitcoin/pull/559) +- [Add function to check RBF-ness of transactions](https://github.com/rust-bitcoin/rust-bitcoin/pull/565) +- [Add Script:dust_value() to get minimum output value for a spk](https://github.com/rust-bitcoin/rust-bitcoin/pull/566) +- [Improving bip32 ChildNumber display implementation](https://github.com/rust-bitcoin/rust-bitcoin/pull/567) +- [Make Script::fmt_asm a static method and add Script::str_asm ](https://github.com/rust-bitcoin/rust-bitcoin/pull/569) +- [Return BlockHash from BlockHeader::validate_pow](https://github.com/rust-bitcoin/rust-bitcoin/pull/572) +- [Add a method to error on non-standard hashtypes](https://github.com/rust-bitcoin/rust-bitcoin/pull/573) +- [Include proprietary key in deserialized PSBT](https://github.com/rust-bitcoin/rust-bitcoin/pull/577) +- [Fix Script::dust_value()'s calculation for non-P2*PKH script_pubkeys](https://github.com/rust-bitcoin/rust-bitcoin/pull/579) +- Add [Address to optimized QR string](https://github.com/rust-bitcoin/rust-bitcoin/pull/581) conversion +- [Correct Transaction struct encode_signing_data_to doc comment](https://github.com/rust-bitcoin/rust-bitcoin/pull/582) +- Fixing [CI if base image's apt db is outdated](https://github.com/rust-bitcoin/rust-bitcoin/pull/583) +- [Introduce some policy constants from Bitcoin Core](https://github.com/rust-bitcoin/rust-bitcoin/pull/584) +- [Fix warnings for sighashtype](https://github.com/rust-bitcoin/rust-bitcoin/pull/586) +- [Introduction of Schnorr keys](https://github.com/rust-bitcoin/rust-bitcoin/pull/589) +- Adding [constructors for compressed and uncompressed ECDSA keys](https://github.com/rust-bitcoin/rust-bitcoin/pull/592) +- [Count bytes read in encoding](https://github.com/rust-bitcoin/rust-bitcoin/pull/594) +- [Add verify_with_flags to Script and Transaction](https://github.com/rust-bitcoin/rust-bitcoin/pull/598) +- [Fixes documentation intra-links and enforce it](https://github.com/rust-bitcoin/rust-bitcoin/pull/600) +- [Fixing hashes core dependency and fuzz feature](https://github.com/rust-bitcoin/rust-bitcoin/pull/602) + +# 0.26.0 - 2020-12-21 + +- Add [signet support](https://github.com/rust-bitcoin/rust-bitcoin/pull/291) +- Add [wtxidrelay message and `WTx` inv type](https://github.com/rust-bitcoin/rust-bitcoin/pull/446) for BIP 339 +- Add [addrv2 support](https://github.com/rust-bitcoin/rust-bitcoin/pull/449) +- Distinguish [`FilterHeader` and `FilterHash`](https://github.com/rust-bitcoin/rust-bitcoin/pull/454) +- Add [hash preimage fields](https://github.com/rust-bitcoin/rust-bitcoin/pull/478) to PSBT +- Detect [write errors for `PublicKey::write_into`](https://github.com/rust-bitcoin/rust-bitcoin/pull/507) +- impl `Ord` and `PartialOrd` [for `Inventory`](https://github.com/rust-bitcoin/rust-bitcoin/pull/517) +- Add [binary encoding for BIP32 xkeys](https://github.com/rust-bitcoin/rust-bitcoin/pull/470) +- Add [Taproot Tagged Hashes](https://github.com/rust-bitcoin/rust-bitcoin/pull/259) +- Add [`message::MAX_INV_SIZE` constant](https://github.com/rust-bitcoin/rust-bitcoin/pull/516) +- impl [`ToSocketAddrs` for network addresses](https://github.com/rust-bitcoin/rust-bitcoin/pull/514) +- Add [new global fields to PSBT](https://github.com/rust-bitcoin/rust-bitcoin/pull/499) +- [Serde serialization of PSBT data](https://github.com/rust-bitcoin/rust-bitcoin/pull/497) +- [Make `Inventory` and `NetworkMessage` enums exhaustive](https://github.com/rust-bitcoin/rust-bitcoin/pull/496) +- [Add PSBT proprietary keys](https://github.com/rust-bitcoin/rust-bitcoin/pull/471) +- [Add `PublicKey::read_from` method symmetric with `write_to`](https://github.com/rust-bitcoin/rust-bitcoin/pull/542) +- [Bump rust-secp to 0.20, turn off `recovery` feature by default](https://github.com/rust-bitcoin/rust-bitcoin/pull/545) +- [Change return value of `consensus_encode` to `io::Error`](https://github.com/rust-bitcoin/rust-bitcoin/pull/494) + +# 0.25.1 - 2020-10-26 + +- Remove an incorrect `debug_assert` that can cause a panic when running using + the dev profile. + +# 0.25.1 - 2020-10-07 + +- [Expose methods on `Script`](https://github.com/rust-bitcoin/rust-bitcoin/pull/387) to generate various scriptpubkeys +- [Expose all cargo features of secp256k1](https://github.com/rust-bitcoin/rust-bitcoin/pull/486) +- Allow directly creating [various hash newtypes](https://github.com/rust-bitcoin/rust-bitcoin/pull/388) +- Add methods to `Block` [to get the coinbase tx and BIP34 height commitment](https://github.com/rust-bitcoin/rust-bitcoin/pull/444) +- [Add `extend` method](https://github.com/rust-bitcoin/rust-bitcoin/pull/459) to bip32::DerivationPath +- [Alias `(Fingerprint, DerivationPath)` as `KeySource`](https://github.com/rust-bitcoin/rust-bitcoin/pull/480) +- [Add serde implementation for PSBT data structs](https://github.com/rust-bitcoin/rust-bitcoin/pull/497) +- [Add FromStr/Display implementation for SigHashType](https://github.com/rust-bitcoin/rust-bitcoin/pull/497/commits/a4a7035a947998c8d0d69dab206e97253fd8e048) +- Expose [the raw sighash message](https://github.com/rust-bitcoin/rust-bitcoin/pull/485) from sighash computations +- Add [support for signmessage/verifymessage style message signatures](https://github.com/rust-bitcoin/rust-bitcoin/pull/413) + +# 0.25.0 - 2020-09-10 + +- **Bump MSRV to 1.29.0** + +# 0.24.0 - 2020-09-10 + +- [Remove](https://github.com/rust-bitcoin/rust-bitcoin/pull/385) the `BitcoinHash` trait +- [Introduce `SigHashCache` structure](https://github.com/rust-bitcoin/rust-bitcoin/pull/390) to replace `SighashComponents` and support all sighash modes +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/416) `Transaction::get_size` method +- [Export](https://github.com/rust-bitcoin/rust-bitcoin/pull/412) `util::amount::Denomination` +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/417) `Block::get_size` and `Block::get_weight` methods +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/415) `MerkleBlock::from_header_txids` +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/429) `BlockHeader::u256_from_compact_target` +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/448) `feefilter` network message +- [Cleanup/replace](https://github.com/rust-bitcoin/rust-bitcoin/pull/397) `Script::Instructions` iterator API +- [Disallow uncompressed pubkeys in witness address generation](https://github.com/rust-bitcoin/rust-bitcoin/pull/428) +- [Deprecate](https://github.com/rust-bitcoin/rust-bitcoin/pull/451) `util::contracthash` module +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/435) modulo division operation for `Uint128` and `Uint256` +- [Add](https://github.com/rust-bitcoin/rust-bitcoin/pull/436) `slice_to_u64_be` endian conversion method + +# 0.23.0 - 2020-01-07 + +- Update `secp256k1` dependency to `0.17.1`. +- Update `bitcoinconsensus` dependency to `0.19.0-1`. +- Update `bech32` dependency to `0.7.2`. + +# 0.22.0 - 2020-01-07 + +- Add `ServiceFlags` type. +- Add `NetworkMessage::command`. +- Add `key::Error`. +- Add newtypes for specific hashes: + - `Txid` + - `Wtxid` + - `BlockHash` + - `SigHash` + - `PubkeyHash` + - `ScriptHash` + - `WPubkeyHash` + - `WScriptHash` + - `TxMerkleNode` + - `WitnessMerkleNode` + - `WitnessCommitment` + - `XpubIdentifier` + - `FilterHash` +- Refactor `CommandString`. +- Refactor `Reject` message. +- Rename `RejectReason` enum variants. +- Refactor `encode::Error`. +- Implement `Default` for `TxIn`. +- Implement `std::hash::Hash` for `Inventory`. +- Implement `Copy` for `InvType` enum. +- Use `psbt::Error` in `PartiallySignedTransaction::from_unsigned_tx`. +- Drop message decode max length to 4_000_000. +- Drop `hex` and `byteorder` dependencies. + +# 0.21.0 - 2019-10-02 + +* Add [serde to `BlockHeader` and `Block`](https://github.com/rust-bitcoin/rust-bitcoin/pull/321) +* [Clean up `StreamReader` API](https://github.com/rust-bitcoin/rust-bitcoin/pull/318) (breaking change) +* Add [reject message](https://github.com/rust-bitcoin/rust-bitcoin/pull/323) to p2p messages + +# 0.20.0 - 2019-08-23 + +* Update `secp256k1` 0.15 and `bitcoinconsensus` 0.17 + +# 0.19.0 - 2019-08-16 + +* Add `Amount` and `SignedAmount` types. +* Add BIP-0158 support with `BlockFilter` and related types. +* Add `util::misc::signed_msg_hash()` for signing messages. +* Add `MerkleBlock` and `PartialMerkleTree` types. +* bip32: Support serde serialization for types and add some utility methods: + * `ChildNumber::increment` + * `DerivationPath::children_from` + * `DerivationPath::normal_children` + * `DerivationPath::hardened_children` +* Add `blockdata::script::Builder::push_verify` to verify-ify an opcode. +* Add `sendheaders` network message. +* Add `OutPoint::new()` method and JSON-serialize as `:`. +* Refactor `Address` type: + * Now supports segwit addresses with version >0. + * Add `Address::from_script` constructor. + * Add `Address::address_type` inspector. + * Parsing now returns an `address::Error` instead of `encode::Error`. + * Removed `bitcoin_bech32` dependency for bech32 payloads. +* bip143: Rename `witness_script` to `script_code` +* Rename `BlockHeader::spv_validate` to `validate_pow` +* Rename `OP_NOP2` and `OP_NOP3` to `OP_CLTV` and `OP_CSV` +* psbt: Use `BTreeMap` instead of `HashMap` to ensure serialization roundtrips. +* Drop `Decimal` type. +* Drop `LoneHeaders` type. +* Replace `strason` dependency with (optional) `serde_json`. +* Export the `bitcoin_hashes` and `secp256k1` dependent crates. +* Updated `bitcoin_hashes` dependency to v0.7. +* Removed `rand` and `serde_test` dependencies. +* Internal improvements to consensus encoding logic. + +# 0.18.0 - 2019-03-21 + +* Update `bitcoin-bech32` version to 0.9 +* add `to_bytes` method for `util::key` types +* add serde impls for `util::key` types +* contracthash: minor cleanups, use `util::key` types instead of `secp256k1` types + +# 0.17.1 - 2019-03-04 + +* Add some trait impls to `PublicKey` for miniscript interoperability + +# 0.17.0 - 2019-02-28 - ``The PSBT Release'' + +* **Update minimum rustc version to 1.22**. +* [Replace `rust-crypto` with `bitcoin_hashes`; refactor hash types](https://github.com/rust-bitcoin/rust-bitcoin/pull/215) +* [Remove `Address::p2pk`](https://github.com/rust-bitcoin/rust-bitcoin/pull/222/) +* Remove misleading blanket `MerkleRoot` implementation; [it is now only defined for `Block`](https://github.com/rust-bitcoin/rust-bitcoin/pull/218) +* [Add BIP157](https://github.com/rust-bitcoin/rust-bitcoin/pull/215) (client-side block filtering messages) +* Allow network messages [to be deserialized even across multiple packets](https://github.com/rust-bitcoin/rust-bitcoin/pull/231) +* [Replace all key types](https://github.com/rust-bitcoin/rust-bitcoin/pull/183) to better match abstractions needed for PSBT +* [Clean up BIP32](https://github.com/rust-bitcoin/rust-bitcoin/pull/233) in preparation for PSBT; [use new native key types rather than `secp256k1` ones](https://github.com/rust-bitcoin/rust-bitcoin/pull/238/) +* Remove [apparently-used `Option` serialization](https://github.com/rust-bitcoin/rust-bitcoin/pull/236#event-2158116421) code +* Finally merge [PSBT](https://github.com/rust-bitcoin/rust-bitcoin/pull/103) after nearly nine months + +# 0.16.0 - 2019-01-15 + +* Reorganize opcode types to eliminate unsafe code +* Un-expose some macros that were unintentionally exported +* Update rust-secp256k1 dependency to 0.12 +* Remove `util::iter::Pair` type which does not belong in this library +* Minor bugfixes and optimizations + +# 0.15.1 - 2018-11-08 + +* [Detect p2pk addresses with compressed keys](https://github.com/rust-bitcoin/rust-bitcoin/pull/189) + +# 0.15.0 - 2018-11-03 + +* [Significant API overhaul](https://github.com/rust-bitcoin/rust-bitcoin/pull/156): + * Remove `nu_select` macro and low-level networking support + * Move `network::consensus_params` to `consensus::params` + * Move many other things into `consensus::params` + * Move `BitcoinHash` from `network::serialize` to `util::hash`; remove impl for `Vec` + * Rename/restructure error types + * Rename `Consensus{De,En}coder` to `consensus::{De,En}coder` + * Replace `Raw{De,En}coder` with blanket impls of `consensus::{De,En}coder` on `io::Read` and `io::Write` + * make `serialize` and `serialize_hex` infallible +* Make 0-input transaction de/serialization [always use segwit](https://github.com/rust-bitcoin/rust-bitcoin/pull/153) +* Implement `FromStr` and `Display` for many more types + +# 0.14.2 - 2018-09-11 + +* Add serde support for `Address` + +# 0.14.1 - 2018-08-28 + +* Reject non-compact `VarInt`s on various types +* Expose many types at the top level of the crate +* Add `Ord`, `PartialOrd` impls for `Script` + +# 0.14.0 - 2018-08-22 + +* Add [regtest network](https://github.com/rust-bitcoin/rust-bitcoin/pull/84) to `Network` enum +* Add [`Script::is_op_return()`](https://github.com/rust-bitcoin/rust-bitcoin/pull/101/) which is more specific than + `Script::is_provably_unspendable()` +* Update to bech32 0.8.0; [add Regtest bech32 address support](https://github.com/rust-bitcoin/rust-bitcoin/pull/110) +* [Replace rustc-serialize dependency with hex](https://github.com/rust-bitcoin/rust-bitcoin/pull/107) as a stopgap + toward eliminating any extra dependencies for this; clean up the many independent hex encoders and decoders + throughout the codebase. +* [Add conversions between `ChildNumber` and `u32`](https://github.com/rust-bitcoin/rust-bitcoin/pull/126); make + representation non-public; fix documentation +* [Add several derivation convenience](https://github.com/rust-bitcoin/rust-bitcoin/pull/129) to `bip32` extended keys +* Make `deserialize::deserialize()` [enforce no trailing bytes](https://github.com/rust-bitcoin/rust-bitcoin/pull/129) +* Replace `TxOutRef` with `OutPoint`; use it in `TxIn` struct. +* Use modern `as_` `to_` `into_` conventions for array-wrapping types; impl `Display` rather than `ToString` for most types +* Change `script::Instructions` iterator [to allow rejecting non-minimal pushes](https://github.com/rust-bitcoin/rust-bitcoin/pull/136); + fix bug where errors would iterate forever. +* Overhaul `util::Error`; introduce `serialize::Error` [and use it for `SimpleDecoder` and `SimpleEncoder` rather + than parameterizing these over their error type](https://github.com/rust-bitcoin/rust-bitcoin/pull/137). +* Overhaul `UDecimal` and `Decimal` serialization and parsing [and fix many lingering parsing bugs](https://github.com/rust-bitcoin/rust-bitcoin/pull/142) +* [Update to serde 1.0 and strason 0.4](https://github.com/rust-bitcoin/rust-bitcoin/pull/125) +* Update to secp256k1 0.11.0 +* Many, many documentation and test improvements. + +# 0.13.1 + +* Add `Display` trait to uints, `FromStr` trait to `Network` enum +* Add witness inv types to inv enum, constants for Bitcoin regtest network, `is_coin_base` accessor for tx inputs +* Expose `merkleroot(Vec)` + +# 0.13 + +* Move witnesses inside the `TxIn` structure +* Add `Transaction::get_weight()` +* Update bip143 `sighash_all` API to be more ergonomic + +# 0.12 + +* The in-memory blockchain was moved into a dedicated project rust-bitcoin-chain. +* Removed old script interpreter +* A new optional feature "bitcoinconsensus" lets this library use Bitcoin Core's native +script verifier, wrapped into Rust by the rust-bitcoinconsensus project. +See `Transaction::verify` and `Script::verify` methods. +* Replaced Base58 traits with `encode_slice`, `check_encode_slice`, from and `from_check` functions in the base58 module. +* Un-reversed the Debug output for Sha256dHash +* Add bech32 support +* Support segwit address types + +### 0.11 + +* Remove `num` dependency at Matt's request; agree this is obnoxious to require all +downstream users to also have a `num` dependency just so they can use `Uint256::from_u64`. diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml new file mode 100644 index 000000000..e94d6720c --- /dev/null +++ b/bitcoin/Cargo.toml @@ -0,0 +1,107 @@ +[package] +name = "bitcoin" +version = "0.33.0-beta.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin/" +documentation = "https://docs.rs/bitcoin/" +description = "General purpose library for using and interoperating with Bitcoin." +categories = ["cryptography::cryptocurrencies"] +keywords = [ "crypto", "bitcoin" ] +readme = "../README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +# If you change features or optional dependencies in any way please update the "# Cargo features" section in lib.rs as well. +[features] +default = [ "std", "secp-recovery" ] +std = ["base58/std", "bech32/std", "encoding/std", "hashes/std", "hex/std", "internals/std", "io/std", "primitives/std", "secp256k1/std", "units/std", "base64?/std", "bitcoinconsensus?/std"] +rand = ["secp256k1/rand"] +serde = ["base64", "dep:serde", "hashes/serde", "internals/serde", "primitives/serde", "secp256k1/serde", "units/serde"] +secp-global-context = ["secp256k1/global-context"] +secp-lowmemory = ["secp256k1/lowmemory"] +secp-recovery = ["secp256k1/recovery"] +arbitrary = ["dep:arbitrary", "units/arbitrary", "primitives/arbitrary"] + +[dependencies] +base58 = { package = "base58ck", path = "../base58", version = "0.2.0", default-features = false, features = ["alloc"] } +bech32 = { version = "0.11.0", default-features = false, features = ["alloc"] } +hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.18.0", default-features = false, features = ["alloc", "hex"] } +encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "=1.0.0-rc.2", default-features = false, features = ["alloc"] } +hex = { package = "hex-conservative", version = "0.3.0", default-features = false, features = ["alloc"] } +internals = { package = "bitcoin-internals", path = "../internals", version = "0.4.2", features = ["alloc", "hex"] } +io = { package = "bitcoin-io", path = "../io", version = "0.3.0", default-features = false, features = ["alloc", "hashes"] } +primitives = { package = "bitcoin-primitives", path = "../primitives", version = "=1.0.0-rc.1", default-features = false, features = ["alloc", "hex"] } +secp256k1 = { version = "0.32.0-beta.2", default-features = false, features = ["alloc"] } +units = { package = "bitcoin-units", path = "../units", version = "=1.0.0-rc.3", default-features = false, features = ["alloc"] } + +arbitrary = { version = "1.4.1", optional = true } +base64 = { version = "0.22.0", optional = true, default-features = false, features = ["alloc"] } +# `bitcoinconsensus` version includes metadata which indicates the version of Core. Use `cargo tree` to see it. +bitcoinconsensus = { version = "0.106.0", default-features = false, optional = true } +serde = { version = "1.0.195", default-features = false, features = [ "derive", "alloc" ], optional = true } + +[dev-dependencies] +internals = { package = "bitcoin-internals", path = "../internals", features = ["test-serde"] } +serde_json = "1.0.68" +serde_test = "1.0.19" +bincode = "1.3.1" +hex_lit = "0.1.1" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[[example]] +name = "bip32" + +[[example]] +name = "ecdsa-psbt" +required-features = ["std", "bitcoinconsensus"] + +[[example]] +name = "ecdsa-psbt-simple" +required-features = ["rand", "std"] + +[[example]] +name = "create-p2wpkh-address" +required-features = ["rand", "std"] + +[[example]] +name = "sign-tx-segwit-v0" +required-features = ["rand", "std"] + +[[example]] +name = "sign-tx-taproot" +required-features = ["rand", "std"] + +[[example]] +name = "taproot-psbt" +required-features = ["rand", "std", "bitcoinconsensus"] + +[[example]] +name = "taproot-psbt-simple" +required-features = ["rand", "std"] + +[[example]] +name = "sighash" + +[[example]] +name = "io" +required-features = ["std"] + +[[example]] +name = "script" +required-features = ["std"] + +[[example]] +name = "serde" +required-features = ["std", "serde"] + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(fuzzing)', 'cfg(kani)'] } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/bitcoin/contrib/act/event.json b/bitcoin/contrib/act/event.json new file mode 100644 index 000000000..43c2f0ebf --- /dev/null +++ b/bitcoin/contrib/act/event.json @@ -0,0 +1,3 @@ +{ + "act": true +} diff --git a/bitcoin/contrib/extra_lints.sh b/bitcoin/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/bitcoin/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/bitcoin/contrib/extra_tests.sh b/bitcoin/contrib/extra_tests.sh new file mode 100755 index 000000000..d4c785c61 --- /dev/null +++ b/bitcoin/contrib/extra_tests.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -ex + +cargo run --locked --example bip32 7934c09359b234e076b9fa5a1abfd38e3dc2a9939745b7cc3c22a48d831d14bd +cargo run --locked --no-default-features --example bip32 7934c09359b234e076b9fa5a1abfd38e3dc2a9939745b7cc3c22a48d831d14bd diff --git a/bitcoin/contrib/test_vars.sh b/bitcoin/contrib/test_vars.sh new file mode 100644 index 000000000..6b2d09e8d --- /dev/null +++ b/bitcoin/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="rand serde secp-recovery bitcoinconsensus base64 arbitrary" + +# Test all these features without "std" or "alloc" enabled. +FEATURES_WITHOUT_STD="rand serde secp-recovery bitcoinconsensus base64 arbitrary" + +# Run these examples. +EXAMPLES="ecdsa-psbt:std,bitcoinconsensus sign-tx-segwit-v0:rand,std sign-tx-taproot:rand,std taproot-psbt:bitcoinconsensus,rand,std sighash:std serde:std,serde" diff --git a/bitcoin/embedded/Cargo.toml b/bitcoin/embedded/Cargo.toml new file mode 100644 index 000000000..fdf2c69f6 --- /dev/null +++ b/bitcoin/embedded/Cargo.toml @@ -0,0 +1,33 @@ +[package] +authors = ["Riccardo Casatta ", "Dev Random "] +edition = "2021" +readme = "README.md" +name = "embedded" +version = "0.1.0" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[dependencies] +cortex-m-rt = "0.6.10" +cortex-m-semihosting = "0.3.3" +alloc-cortex-m = "0.4.1" +bitcoin = { path="../", default-features = false, features = ["secp-lowmemory"] } + +[lints.clippy] +use_self = "warn" + +[[bin]] +name = "embedded" +test = false +bench = false + +[profile.release] +codegen-units = 1 # better optimizations +debug = true # symbols are nice and they don't increase the size on Flash +lto = true # better optimizations + + +[patch.crates-io.bitcoin_hashes] +path = "../../hashes" diff --git a/bitcoin/embedded/README.md b/bitcoin/embedded/README.md new file mode 100644 index 000000000..e27f8dc76 --- /dev/null +++ b/bitcoin/embedded/README.md @@ -0,0 +1,33 @@ +# Running + +To run the embedded test, first prepare your environment: + +```shell +sudo ./scripts/install-deps +rustup +nightly target add thumbv7m-none-eabi +``` + +Then: + +```shell +source ./scripts/env.sh && cargo +nightly run --target thumbv7m-none-eabi +``` + +Output should be something like: + +```text +heap size 262144 +Seed WIF: L1HKVVLHXiUhecWnwFYF6L3shkf1E12HUmuZTESvBXUdx3yqVP1D +Address: bc1qpx9t9pzzl4qsydmhyt6ctrxxjd4ep549np9993 +``` + +Note that this heap size is required because of the amount of stack used by libsecp256k1 when initializing a context. + +## Cleanup + +After sourcing `scripts/env.sh` and _before_ building again using another target +you'll want to unset `RUSTFLAGS` otherwise you'll get linker errors. + +```shell +unset RUSTFLAGS +``` diff --git a/bitcoin/embedded/memory.x b/bitcoin/embedded/memory.x new file mode 100644 index 000000000..a07f29cff --- /dev/null +++ b/bitcoin/embedded/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 512K + RAM : ORIGIN = 0x20000000, LENGTH = 512K +} diff --git a/bitcoin/embedded/scripts/env.sh b/bitcoin/embedded/scripts/env.sh new file mode 100644 index 000000000..798c4af83 --- /dev/null +++ b/bitcoin/embedded/scripts/env.sh @@ -0,0 +1,4 @@ +# we don't want shebangs in env.sh, disable shellcheck warning +# shellcheck disable=SC2148 +export RUSTFLAGS="-C link-arg=-Tlink.x" +export CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER="qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -nographic -semihosting-config enable=on,target=native -kernel" diff --git a/bitcoin/embedded/scripts/install-deps b/bitcoin/embedded/scripts/install-deps new file mode 100755 index 000000000..49cf20442 --- /dev/null +++ b/bitcoin/embedded/scripts/install-deps @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +apt install gcc-arm-none-eabi qemu-system-arm gdb-multiarch diff --git a/bitcoin/embedded/src/main.rs b/bitcoin/embedded/src/main.rs new file mode 100644 index 000000000..97d971183 --- /dev/null +++ b/bitcoin/embedded/src/main.rs @@ -0,0 +1,54 @@ +#![feature(alloc_error_handler)] +#![feature(panic_info_message)] +#![no_std] +#![no_main] + +extern crate alloc; +extern crate bitcoin; + +use alloc::string::ToString; +use core::panic::PanicInfo; + +use alloc_cortex_m::CortexMHeap; +// use panic_halt as _; +use bitcoin::{Address, Network, PrivateKey}; +use cortex_m_rt::entry; +use cortex_m_semihosting::{debug, hprintln}; + +// this is the allocator the application will use +#[global_allocator] +static ALLOCATOR: CortexMHeap = CortexMHeap::empty(); + +const HEAP_SIZE: usize = 1024 * 256; // 256 KB + +#[entry] +fn main() -> ! { + hprintln!("heap size {}", HEAP_SIZE).unwrap(); + + unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) } + + // Load a private key + let raw = "L1HKVVLHXiUhecWnwFYF6L3shkf1E12HUmuZTESvBXUdx3yqVP1D"; + let pk = PrivateKey::from_wif(raw).unwrap(); + hprintln!("Seed WIF: {}", pk).unwrap(); + + // Derive address + let pubkey = pk.public_key().try_into().unwrap(); + let address = Address::p2wpkh(pubkey, Network::Bitcoin); + hprintln!("Address: {}", address).unwrap(); + + assert_eq!(address.to_string(), "bc1qpx9t9pzzl4qsydmhyt6ctrxxjd4ep549np9993"); + // exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state + debug::exit(debug::EXIT_SUCCESS); + + loop {} +} + +#[inline(never)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + hprintln!("panic {:?}", info.message()).unwrap(); + debug::exit(debug::EXIT_FAILURE); + loop {} +} diff --git a/bitcoin/examples/bip32.rs b/bitcoin/examples/bip32.rs new file mode 100644 index 000000000..886a03032 --- /dev/null +++ b/bitcoin/examples/bip32.rs @@ -0,0 +1,45 @@ +use std::{env, process}; + +use bitcoin::address::{Address, KnownHrp}; +use bitcoin::bip32::{ChildNumber, DerivationPath, Xpriv, Xpub}; +use bitcoin::hex::FromHex; +use bitcoin::{CompressedPublicKey, NetworkKind}; + +fn main() { + // This example derives root xprv from a 32-byte seed, + // derives the child xprv with path m/84h/0h/0h, + // prints out corresponding xpub, + // calculates and prints out the first receiving SegWit address. + // Run this example with cargo and seed(hex-encoded) argument: + // cargo run --example bip32 7934c09359b234e076b9fa5a1abfd38e3dc2a9939745b7cc3c22a48d831d14bd + + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("not enough arguments. usage: {} ", &args[0]); + process::exit(1); + } + + let seed_hex = &args[1]; + println!("Seed: {seed_hex}"); + println!("Using mainnet network"); + + let seed = Vec::from_hex(seed_hex).unwrap(); + + // calculate root key from seed + let root = Xpriv::new_master(NetworkKind::Main, &seed); + println!("Root key: {root}"); + + // derive child xpub + let path = "84h/0h/0h".parse::().unwrap(); + let child = root.derive_xpriv(&path).expect("only deriving three steps"); + println!("Child at {path}: {child}"); + let xpub = Xpub::from_xpriv(&child); + println!("Public key at {path}: {xpub}"); + + // generate first receiving address at m/0/0 + // manually creating indexes this time + let zero = ChildNumber::ZERO_NORMAL; + let public_key = xpub.derive_xpub([zero, zero]).unwrap().public_key; + let address = Address::p2wpkh(CompressedPublicKey(public_key), KnownHrp::Mainnet); + println!("First receiving address: {address}"); +} diff --git a/bitcoin/examples/create-p2wpkh-address.rs b/bitcoin/examples/create-p2wpkh-address.rs new file mode 100644 index 000000000..d1a327590 --- /dev/null +++ b/bitcoin/examples/create-p2wpkh-address.rs @@ -0,0 +1,21 @@ +use bitcoin::secp256k1::rand; +use bitcoin::{Address, CompressedPublicKey, Network, PrivateKey}; + +/// Generate a P2WPKH (pay-to-witness-public-key-hash) address and print it +/// along with the associated private key needed to transact. +fn main() { + // Generate secp256k1 public and private key pair. + let (secret_key, public_key) = secp256k1::generate_keypair(&mut rand::rng()); + + // Create a Bitcoin private key to be used on the Bitcoin mainnet. + let private_key = PrivateKey::new(secret_key, Network::Bitcoin); + + // Create a compressed Bitcoin public key from the secp256k1 public key. + let public_key = CompressedPublicKey(public_key); + + // Create a Bitcoin P2WPKH address. + let address = Address::p2wpkh(public_key, Network::Bitcoin); + + println!("Private Key: {private_key}"); + println!("Address: {address}"); +} diff --git a/bitcoin/examples/ecdsa-psbt-simple.rs b/bitcoin/examples/ecdsa-psbt-simple.rs new file mode 100644 index 000000000..ab2341d09 --- /dev/null +++ b/bitcoin/examples/ecdsa-psbt-simple.rs @@ -0,0 +1,246 @@ +//! Implements a simple multi-input PSBT signing example +//! +//! The purpose of this section is to construct a PSBT that +//! spends multiple inputs and signs it. +//! We'll cover the following +//! [BIP 174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) +//! roles: +//! +//! - **Creator**: Creates a PSBT with multiple inputs and outputs. +//! - **Updater**: Adds Witness and SegWit V0 data to the PSBT. +//! - **Signer**: Signs the PSBT. +//! - **Finalizer**: Finalizes the PSBT. +//! +//! The example will focus on spending two SegWit V0 inputs: +//! +//! 1. 20,000,000 satoshi UTXO, the first receiving ("external") address. +//! 1. 10,000,000 satoshi UTXO, the first change ("internal") address. +//! +//! We'll be sending this to two outputs: +//! +//! 1. 25,000,000 satoshis to a receivers' address. +//! 1. 4,990,000 satoshis back to us as change. +//! +//! The miner's fee will be 10,000 satoshis. +use std::collections::BTreeMap; + +use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, IntoDerivationPath, Xpriv, Xpub}; +use bitcoin::ext::*; +use bitcoin::key::WPubkeyHash; +use bitcoin::locktime::absolute; +use bitcoin::psbt::Input; +use bitcoin::{ + consensus, transaction, Address, Amount, EcdsaSighashType, Network, OutPoint, Psbt, + RedeemScriptBuf, ScriptPubKeyBuf, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Txid, + Witness, +}; + +// The master xpriv, from which we derive the keys we control. +const XPRIV: &str = "xprv9tuogRdb5YTgcL3P8Waj7REqDuQx4sXcodQaWTtEVFEp6yRKh1CjrWfXChnhgHeLDuXxo2auDZegMiVMGGxwxcrb2PmiGyCngLxvLeGsZRq"; + +// The derivation path for the keys we control. +// This follows the BIP 84 derivation path for Bitcoin. +const BIP84_DERIVATION_PATH: &str = "m/84'/0'/0'"; + +// The master fingerprint of the master xpriv. +const MASTER_FINGERPRINT: &str = "9680603f"; + +// The dummy UTXO amounts we are spending. +const DUMMY_UTXO_AMOUNT_INPUT_1: Amount = Amount::from_sat_u32(20_000_000); +const DUMMY_UTXO_AMOUNT_INPUT_2: Amount = Amount::from_sat_u32(10_000_000); + +// The amounts we are sending to someone, and receiving back as change. +const SPEND_AMOUNT: Amount = Amount::from_sat_u32(25_000_000); +const CHANGE_AMOUNT: Amount = Amount::from_sat_u32(4_990_000); // 10_000 sat fee. + +// Derive the external address xpriv. +fn get_external_address_xpriv( + master_xpriv: Xpriv, + index: u32, +) -> Xpriv { + let derivation_path = + BIP84_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); + let child_xpriv = + master_xpriv.derive_xpriv(&derivation_path).expect("only deriving three steps"); + let external_index = ChildNumber::ZERO_NORMAL; + let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); + + child_xpriv.derive_xpriv([external_index, idx]).expect("only deriving two more steps") +} + +// Derive the internal address xpriv. +fn get_internal_address_xpriv( + master_xpriv: Xpriv, + index: u32, +) -> Xpriv { + let derivation_path = + BIP84_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); + let child_xpriv = + master_xpriv.derive_xpriv(&derivation_path).expect("only deriving three steps"); + let internal_index = ChildNumber::ONE_NORMAL; + let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); + + child_xpriv.derive_xpriv([internal_index, idx]).expect("only deriving two more steps") +} + +// The address to send to. +fn receivers_address() -> Address { + "bc1q7cyrfmck2ffu2ud3rn5l5a8yv6f0chkp0zpemf" + .parse::>() + .expect("a valid address") + .require_network(Network::Bitcoin) + .expect("valid address for mainnet") +} + +// The dummy unspent transaction outputs that we control. +fn dummy_unspent_transaction_outputs() -> Vec<(OutPoint, TxOut)> { + let script_pubkey_1 = "bc1qrwuu3ydv0jfza4a0ehtfd03m9l4vw3fy0hfm50" + .parse::>() + .expect("a valid address") + .require_network(Network::Bitcoin) + .expect("valid address for mainnet") + .script_pubkey(); + + let out_point_1 = OutPoint { + txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value. + vout: 0, + }; + + let utxo_1 = TxOut { amount: DUMMY_UTXO_AMOUNT_INPUT_1, script_pubkey: script_pubkey_1 }; + + let script_pubkey_2 = "bc1qy7swwpejlw7a2rp774pa8rymh8tw3xvd2x2xkd" + .parse::>() + .expect("a valid address") + .require_network(Network::Bitcoin) + .expect("valid address for mainnet") + .script_pubkey(); + + let out_point_2 = OutPoint { + txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value. + vout: 1, + }; + + let utxo_2 = TxOut { amount: DUMMY_UTXO_AMOUNT_INPUT_2, script_pubkey: script_pubkey_2 }; + vec![(out_point_1, utxo_1), (out_point_2, utxo_2)] +} + +fn main() { + // Get the individual xprivs we control. In a real application these would come from a stored secret. + let master_xpriv = XPRIV.parse::().expect("valid xpriv"); + let xpriv_input_1 = get_external_address_xpriv(master_xpriv, 0); + let xpriv_input_2 = get_internal_address_xpriv(master_xpriv, 0); + let xpriv_change = get_internal_address_xpriv(master_xpriv, 1); + + // Get the PKs + let pk_input_1 = Xpub::from_xpriv(&xpriv_input_1).to_public_key(); + let pk_input_2 = Xpub::from_xpriv(&xpriv_input_2).to_public_key(); + let pk_inputs = [pk_input_1, pk_input_2]; + let pk_change = Xpub::from_xpriv(&xpriv_change).to_public_key(); + + // Get the Witness Public Key Hashes (WPKHs) + let wpkhs: Vec = pk_inputs.iter().map(|pk| pk.wpubkey_hash()).collect(); + + // Get the unspent outputs that are locked to the key above that we control. + // In a real application these would come from the chain. + let utxos: Vec = + dummy_unspent_transaction_outputs().into_iter().map(|(_, utxo)| utxo).collect(); + + // Get the addresses to send to. + let address = receivers_address(); + + // The inputs for the transaction we are constructing. + let inputs: Vec = dummy_unspent_transaction_outputs() + .into_iter() + .map(|(outpoint, _)| TxIn { + previous_output: outpoint, + script_sig: ScriptSigBuf::default(), + sequence: Sequence::ENABLE_LOCKTIME_AND_RBF, + witness: Witness::default(), + }) + .collect(); + + // The spend output is locked to a key controlled by the receiver. + let spend = TxOut { amount: SPEND_AMOUNT, script_pubkey: address.script_pubkey() }; + + // The change output is locked to a key controlled by us. + let change = TxOut { + amount: CHANGE_AMOUNT, + script_pubkey: ScriptPubKeyBuf::new_p2wpkh(pk_change.wpubkey_hash()), // Change comes back to us. + }; + + // The transaction we want to sign and broadcast. + let unsigned_tx = Transaction { + version: transaction::Version::TWO, // Post BIP 68. + lock_time: absolute::LockTime::ZERO, // Ignore the locktime. + inputs, // Input is 0-indexed. + outputs: vec![spend, change], // Outputs, order does not matter. + }; + + // Now we'll start the PSBT workflow. + // Step 1: Creator role; that creates, + // and add inputs and outputs to the PSBT. + let mut psbt = Psbt::from_unsigned_tx(unsigned_tx).expect("could not create PSBT"); + + // Step 2:Updater role; that adds additional + // information to the PSBT. + let ty = EcdsaSighashType::All.into(); + let derivation_paths = [ + "m/84'/0'/0'/0/0".parse::().expect("valid derivation path"), + "m/84'/0'/0'/1/0".parse::().expect("valid derivation path"), + ]; + let mut bip32_derivations = Vec::new(); + for (idx, pk) in pk_inputs.iter().enumerate() { + let mut map = BTreeMap::new(); + let fingerprint = MASTER_FINGERPRINT.parse::().expect("valid fingerprint"); + map.insert(pk.0, (fingerprint, derivation_paths[idx].clone())); + bip32_derivations.push(map); + } + psbt.inputs = vec![ + Input { + witness_utxo: Some(utxos[0].clone()), + redeem_script: Some(RedeemScriptBuf::new_p2wpkh(wpkhs[0])), + bip32_derivation: bip32_derivations[0].clone(), + sighash_type: Some(ty), + ..Default::default() + }, + Input { + witness_utxo: Some(utxos[1].clone()), + redeem_script: Some(RedeemScriptBuf::new_p2wpkh(wpkhs[1])), + bip32_derivation: bip32_derivations[1].clone(), + sighash_type: Some(ty), + ..Default::default() + }, + ]; + + // Step 3: Signer role; that signs the PSBT. + psbt.sign(&master_xpriv).expect("valid signature"); + + // Step 4: Finalizer role; that finalizes the PSBT. + println!("PSBT Inputs: {:#?}", psbt.inputs); + let final_script_witness: Vec = psbt + .inputs + .iter() + .enumerate() + .map(|(idx, input)| { + let (_, sig) = input.partial_sigs.iter().next().expect("we have one sig"); + Witness::p2wpkh(*sig, pk_inputs[idx].0) + }) + .collect(); + psbt.inputs.iter_mut().enumerate().for_each(|(idx, input)| { + // Clear all the data fields as per the spec. + input.final_script_witness = Some(final_script_witness[idx].clone()); + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + }); + + // BOOM! Transaction signed and ready to broadcast. + let signed_tx = psbt.extract_tx().expect("valid transaction"); + let serialized_signed_tx = consensus::encode::serialize_hex(&signed_tx); + println!("Transaction Details: {signed_tx:#?}"); + // check with: + // bitcoin-cli decoderawtransaction true + println!("Raw Transaction: {serialized_signed_tx}"); +} diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs new file mode 100644 index 000000000..393c0adaf --- /dev/null +++ b/bitcoin/examples/ecdsa-psbt.rs @@ -0,0 +1,287 @@ +//! Implements an example PSBT workflow. +//! +//! The workflow we simulate is that of a setup using a watch-only online wallet (contains only +//! public keys) and a cold-storage signing wallet (contains the private keys). +//! +//! You can verify the workflow using `bitcoind` and `bitcoin-cli`. +//! +//! # Example Setup +//! +//! 1. Start Bitcoin Core in Regtest mode, for example: +//! +//! `bitcoind -regtest -server -daemon -fallbackfee=0.0002 -rpcuser=admin -rpcpassword=pass -rpcallowip=127.0.0.1/0 -rpcbind=127.0.0.1 -blockfilterindex=1 -peerblockfilters=1` +//! +//! 2. Define a shell alias to `bitcoin-cli`, for example: +//! +//! `alias bt=bitcoin-cli -rpcuser=admin -rpcpassword=pass -rpcport=18443` +//! +//! 3. Create (or load) a default wallet, for example: +//! +//! `bt createwallet ` +//! +//! 4. Mine some blocks, for example: +//! +//! `bt generatetoaddress 110 $(bt getnewaddress)` +//! +//! 5. Get the details for a UTXO to fund the PSBT with: +//! +//! `bt listunspent` +//! + +use std::collections::BTreeMap; +use std::fmt; + +use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, IntoDerivationPath, Xpriv, Xpub}; +use bitcoin::consensus::encode; +use bitcoin::ext::*; +use bitcoin::locktime::absolute; +use bitcoin::psbt::{self, Input, Psbt, PsbtSighashType}; +use bitcoin::{ + transaction, Address, Amount, CompressedPublicKey, Network, OutPoint, RedeemScriptBuf, + ScriptPubKeyBuf, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Witness, +}; + +type Result = std::result::Result; + +// Get this from the output of `bt dumpwallet `. +const EXTENDED_MASTER_PRIVATE_KEY: &str = "tprv8ZgxMBicQKsPeSHZFZWT8zxie2dXWcwemnTkf4grVzMvP2UABUxqbPTCHzZ4ztwhBghpfFw27sJqEgW6y1ZTZcfvCUdtXE1L6qMF7TBdbqQ"; + +// Set these with valid data from output of step 5 above. Please note, input utxo must be a p2wpkh. +const INPUT_UTXO_TXID: &str = "295f06639cde6039bf0c3dbf4827f0e3f2b2c2b476408e2f9af731a8d7a9c7fb"; +const INPUT_UTXO_VOUT: u32 = 0; +const INPUT_UTXO_SCRIPT_PUBKEY: &str = "00149891eeb8891b3e80a2a1ade180f143add23bf5de"; +const INPUT_UTXO_AMOUNT: &str = "50 BTC"; +// Get this from the descriptor, +// "wpkh([97f17dca/0'/0'/0']02749483607dafb30c66bd93ece4474be65745ce538c2d70e8e246f17e7a4e0c0c)#m9n56cx0". +const INPUT_UTXO_DERIVATION_PATH: &str = "0h/0h/0h"; + +// Grab an address to receive on: `bt generatenewaddress` (obviously contrived but works as an example). +const RECEIVE_ADDRESS: &str = "bcrt1qcmnpjjjw78yhyjrxtql6lk7pzpujs3h244p7ae"; // The address to receive the coins we send. + +// These should be correct if the UTXO above should is for 50 BTC. +const OUTPUT_AMOUNT_BTC: &str = "1 BTC"; +const CHANGE_AMOUNT_BTC: &str = "48.99999 BTC"; // 1000 sat transaction fee. + +const NETWORK: Network = Network::Regtest; + +fn main() -> Result<()> { + let (offline, fingerprint, account_0_xpub, input_xpub) = + ColdStorage::new(EXTENDED_MASTER_PRIVATE_KEY)?; + + let online = WatchOnly::new(account_0_xpub, input_xpub, fingerprint); + + let created = online.create_psbt()?; + let updated = online.update_psbt(created)?; + + let signed = offline.sign_psbt(updated)?; + + let finalized = online.finalize_psbt(signed)?; + + // You can use `bt sendrawtransaction` to broadcast the extracted transaction. + let tx = finalized.extract_tx_unchecked_fee_rate(); + tx.verify(|_| Some(previous_output())).expect("failed to verify transaction"); + + let hex = encode::serialize_hex(&tx); + println!("You should now be able to broadcast the following transaction: \n\n{hex}"); + + Ok(()) +} + +// We cache the pubkeys for convenience because it requires a secp256k1 context to convert the private key. +/// An example of an offline signer i.e., a cold-storage device. +struct ColdStorage { + /// The master extended private key. + master_xpriv: Xpriv, + /// The master extended public key. + master_xpub: Xpub, +} + +/// The data exported from an offline wallet to enable creation of a watch-only online wallet. +/// (wallet, fingerprint, account_0_xpub, input_utxo_xpub) +type ExportData = (ColdStorage, Fingerprint, Xpub, Xpub); + +impl ColdStorage { + /// Constructs a new `ColdStorage` signer. + /// + /// # Returns + /// + /// The newly created signer along with the data needed to configure a watch-only wallet. + fn new(xpriv: &str) -> Result { + let master_xpriv = xpriv.parse::()?; + let master_xpub = Xpub::from_xpriv(&master_xpriv); + + // Hardened children require secret data to derive. + + let path = "84h/0h/0h".into_derivation_path()?; + let account_0_xpriv = + master_xpriv.derive_xpriv(&path).expect("derivation path is short"); + let account_0_xpub = Xpub::from_xpriv(&account_0_xpriv); + + let path = INPUT_UTXO_DERIVATION_PATH.into_derivation_path()?; + let input_xpriv = master_xpriv.derive_xpriv(&path).expect("derivation path is short"); + let input_xpub = Xpub::from_xpriv(&input_xpriv); + + let wallet = Self { master_xpriv, master_xpub }; + let fingerprint = wallet.master_fingerprint(); + + Ok((wallet, fingerprint, account_0_xpub, input_xpub)) + } + + /// Returns the fingerprint for the master extended public key. + fn master_fingerprint(&self) -> Fingerprint { self.master_xpub.fingerprint() } + + /// Signs `psbt` with this signer. + fn sign_psbt( + &self, + mut psbt: Psbt, + ) -> Result { + match psbt.sign(&self.master_xpriv) { + Ok(keys) => assert_eq!(keys.len(), 1), + Err((_, e)) => { + let e = e.get(&0).expect("at least one error"); + return Err(e.clone().into()); + } + }; + Ok(psbt) + } +} + +/// An example of a watch-only online wallet. +struct WatchOnly { + /// The xpub for account 0 derived from derivation path "m/84h/0h/0h". + account_0_xpub: Xpub, + /// The xpub derived from `INPUT_UTXO_DERIVATION_PATH`. + input_xpub: Xpub, + /// The master extended pubkey fingerprint. + master_fingerprint: Fingerprint, +} + +impl WatchOnly { + /// Constructs a new watch-only wallet. + /// + /// A watch-only wallet would typically be online and connected to the Bitcoin network. We + /// 'import' into the wallet the `account_0_xpub` and `master_fingerprint`. + /// + /// The reason for importing the `input_xpub` is so one can use bitcoind to grab a valid input + /// to verify the workflow presented in this file. + fn new(account_0_xpub: Xpub, input_xpub: Xpub, master_fingerprint: Fingerprint) -> Self { + Self { account_0_xpub, input_xpub, master_fingerprint } + } + + /// Creates the PSBT, in BIP-0174 parlance this is the 'Creator'. + fn create_psbt(&self) -> Result { + let to_address = + RECEIVE_ADDRESS.parse::>()?.require_network(Network::Regtest)?; + let to_amount = OUTPUT_AMOUNT_BTC.parse::()?; + + let (_, change_address, _) = self.change_address()?; + let change_amount = CHANGE_AMOUNT_BTC.parse::()?; + + let tx = Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { txid: INPUT_UTXO_TXID.parse()?, vout: INPUT_UTXO_VOUT }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::MAX, // Disable LockTime and RBF. + witness: Witness::default(), + }], + outputs: vec![ + TxOut { amount: to_amount, script_pubkey: to_address.script_pubkey() }, + TxOut { amount: change_amount, script_pubkey: change_address.script_pubkey() }, + ], + }; + + let psbt = Psbt::from_unsigned_tx(tx)?; + + Ok(psbt) + } + + /// Updates the PSBT, in BIP-0174 parlance this is the 'Updater'. + fn update_psbt(&self, mut psbt: Psbt) -> Result { + let mut input = Input { witness_utxo: Some(previous_output()), ..Default::default() }; + + let pk = self.input_xpub.to_public_key(); + let wpkh = pk.wpubkey_hash(); + + let redeem_script = RedeemScriptBuf::new_p2wpkh(wpkh); + input.redeem_script = Some(redeem_script); + + let fingerprint = self.master_fingerprint; + let path = input_derivation_path()?; + let mut map = BTreeMap::new(); + map.insert(pk.0, (fingerprint, path)); + input.bip32_derivation = map; + + let ty = "SIGHASH_ALL".parse::()?; + input.sighash_type = Some(ty); + + psbt.inputs = vec![input]; + + Ok(psbt) + } + + /// Finalizes the PSBT, in BIP-0174 parlance this is the 'Finalizer'. + /// This is just an example. For a production-ready PSBT Finalizer, use [rust-miniscript](https://docs.rs/miniscript/latest/miniscript/psbt/trait.PsbtExt.html#tymethod.finalize) + fn finalize_psbt(&self, mut psbt: Psbt) -> Result { + if psbt.inputs.is_empty() { + return Err(psbt::SignError::MissingInputUtxo.into()); + } + + let sigs: Vec<_> = psbt.inputs[0].partial_sigs.values().collect(); + let mut script_witness: Witness = Witness::new(); + script_witness.push(sigs[0].serialize()); + script_witness.push(self.input_xpub.to_public_key().to_bytes()); + + psbt.inputs[0].final_script_witness = Some(script_witness); + + // Clear all the data fields as per the spec. + psbt.inputs[0].partial_sigs = BTreeMap::new(); + psbt.inputs[0].sighash_type = None; + psbt.inputs[0].redeem_script = None; + psbt.inputs[0].witness_script = None; + psbt.inputs[0].bip32_derivation = BTreeMap::new(); + + Ok(psbt) + } + + /// Returns data for the first change address (standard BIP-0084 derivation path + /// "m/84h/0h/0h/1/0"). A real wallet would have access to the chain so could determine if an + /// address has been used or not. We ignore this detail and just re-use the first change address + /// without loss of generality. + fn change_address( + &self, + ) -> Result<(CompressedPublicKey, Address, DerivationPath)> { + let path = [ChildNumber::ONE_NORMAL, ChildNumber::ZERO_NORMAL]; + let derived = self.account_0_xpub.derive_xpub(path)?; + + let pk = derived.to_public_key(); + let addr = Address::p2wpkh(pk, NETWORK); + let path = path.into_derivation_path()?; + + Ok((pk, addr, path)) + } +} + +fn input_derivation_path() -> Result { + let path = INPUT_UTXO_DERIVATION_PATH.into_derivation_path()?; + Ok(path) +} + +fn previous_output() -> TxOut { + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(INPUT_UTXO_SCRIPT_PUBKEY) + .expect("failed to parse input utxo scriptPubkey"); + let amount = INPUT_UTXO_AMOUNT.parse::().expect("failed to parse input utxo amount"); + + TxOut { amount, script_pubkey } +} + +struct Error(Box); + +impl From for Error { + fn from(e: T) -> Self { Self(Box::new(e)) } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } +} diff --git a/bitcoin/examples/io.rs b/bitcoin/examples/io.rs new file mode 100644 index 000000000..1cabb4f41 --- /dev/null +++ b/bitcoin/examples/io.rs @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Demonstrate reading and writing `rust-bitcoin` objects. +//! +//! The `std::io` module is not exposed in `no-std` Rust so building `no-std` applications which +//! require reading and writing objects via standard traits is not generally possible. To support +//! this we provide the `bitcoin_io` crate which provides `io::Read`, `io::BufRead`, and +//! `io::Write`. This module demonstrates its usage. + +use bitcoin::consensus::{Decodable, Encodable as _}; +use bitcoin::{OutPoint, Txid}; + +fn main() { + // Encode/Decode a `rust-bitcoin` type to/from a stdlib type. + encode_decode_from_stdlib_type(); + + // Encode to a custom type by implementing `bitcoin_io` traits. + encode_to_custom_type(); + + // Encode to a foreign custom type by using the `bitcoin_io::FromStd` wrapper. + encode_using_wrapper(); +} + +/// Encodes/Decodes a `rust-bitcoin` type to/from a stdlib type. +/// +/// The consensus encoding and decoding traits are generic over `bitcoin_io::Write` and +/// `bitcoin_io::Read`. However for various stdlib types we implement our traits so _most_ things +/// should just work. +fn encode_decode_from_stdlib_type() { + let data = dummy_utxo(); + + // A type that implements `std::io::Write`. + let mut v = Vec::new(); + + // Under the hood we implement our `io` traits for a bunch of stdlib types so this just works. + let _bytes_written = data.consensus_encode(&mut v).expect("failed to encode to writer"); + + // Slices implement `std::io::Read`. + let mut reader = v.as_ref(); + + let _: OutPoint = + Decodable::consensus_decode(&mut reader).expect("failed to decode from reader"); +} + +/// Encodes to a custom type by implementing the `bitcoin_io::Write` trait. +/// +/// To use the `Encodable` (and `Decodable`) traits you can implement the `bitcoin_io` traits. +fn encode_to_custom_type() { + /// A byte counter - counts how many bytes were written to it. + struct WriteCounter { + count: usize, + } + + /// This `io` is `bitcoin_io` - see `Cargo.toml` usage of `io = { package = "bitcoin-io" }`. + impl io::Write for WriteCounter { + fn write(&mut self, buf: &[u8]) -> Result { + let written = buf.len(); + self.count += written; + Ok(written) + } + fn write_all(&mut self, buf: &[u8]) -> Result<(), io::Error> { + self.count += buf.len(); + Ok(()) + } + fn flush(&mut self) -> Result<(), io::Error> { Ok(()) } + } + + let data = dummy_utxo(); + + let mut counter = WriteCounter { count: 0 }; + let bytes_written = data.consensus_encode(&mut counter).expect("failed to encode to writer"); + assert_eq!(bytes_written, 36); // 32 bytes for txid + 4 bytes for vout. +} + +/// Encodes to a custom type by using the `bitcoin_io::bridge` module. +/// +/// If you have a type that you don't control that implements `std::io::Write` you can still encode +/// to it by way of the `io::FromStd` wrapper. +fn encode_using_wrapper() { + use pretend_this_is_some_other_crate::WriteCounter; + + let data = dummy_utxo(); + + // This will not build because `WriteCounter` does not implement `bitcoin_io::Write`. + // + // let mut counter = WriteCounter::new(); + // let bytes_written = data.consensus_encode(&mut counter)?; + + let mut counter = io::FromStd::new(WriteCounter::new()); + let bytes_written = data.consensus_encode(&mut counter).expect("failed to encode to writer"); + assert_eq!(bytes_written, 36); // 32 bytes for txid + 4 bytes for vout. + assert_eq!(bytes_written, counter.get_ref().written()); + + // Take back ownership of the `WriteCounter`. + let _ = counter.into_inner(); +} + +mod pretend_this_is_some_other_crate { + /// A byte counter - counts how many bytes were written to it. + pub struct WriteCounter { + count: usize, + } + + impl WriteCounter { + /// Constructs a new `WriteCounter`. + pub fn new() -> Self { Self { count: 0 } } + + /// Returns the number of bytes written to this counter. + pub fn written(&self) -> usize { self.count } + } + + impl std::io::Write for WriteCounter { + fn write(&mut self, buf: &[u8]) -> Result { + let written = buf.len(); + self.count += written; + Ok(written) + } + fn write_all(&mut self, buf: &[u8]) -> Result<(), std::io::Error> { + self.count += buf.len(); + Ok(()) + } + fn flush(&mut self) -> Result<(), std::io::Error> { Ok(()) } + } +} + +/// Constructs a dummy UTXO that is just to represent some `rust-bitcoin` type that implements the +/// [`consensus::Encodable`] and [`consensus::Decodable`] traits. +fn dummy_utxo() -> OutPoint { + let txid = Txid::from_byte_array([0xFF; 32]); // Arbitrary invalid dummy value. + OutPoint { txid, vout: 1 } +} diff --git a/bitcoin/examples/script.rs b/bitcoin/examples/script.rs new file mode 100644 index 000000000..25585e051 --- /dev/null +++ b/bitcoin/examples/script.rs @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Demonstrates the API for parsing and formatting Bitcoin scripts. +//! +//! Bitcoin script is conceptually a vector of bytes. As such it is consensus encoded with a compact +//! size encoded length prefix. See [CompactSize]. +//! +//! [`CompactSize`]: + +use bitcoin::consensus::encode; +use bitcoin::key::WPubkeyHash; +use bitcoin::script::{self, ScriptBufExt as _, ScriptExt as _}; +use bitcoin::WitnessScriptBuf; + +fn main() { + let pk = "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb".parse::().unwrap(); + + // TL;DR Use `to_hex_string_prefixed` and `from_hex_prefixed`. + let script_code = script::p2wpkh_script_code(pk); + let hex = script_code.to_hex_string_prefixed(); + let decoded = WitnessScriptBuf::from_hex_prefixed(&hex).unwrap(); + assert_eq!(decoded, script_code); + + // Or if you prefer: `to_hex_string_no_length_prefix` and `from_hex_no_length_prefix`. + let script_code = script::p2wpkh_script_code(pk); + let hex = script_code.to_hex_string_no_length_prefix(); + let decoded = WitnessScriptBuf::from_hex_no_length_prefix(&hex).unwrap(); + assert_eq!(decoded, script_code); + + // Writes the script as human-readable eg, OP_DUP OP_HASH160 OP_PUSHBYTES_20 ... + println!("human-readable script: {script_code}"); + + // We do not implement parsing scripts from human-readable format. + // let decoded = s.parse::().unwrap(); + + // This is not equivalent to consensus encoding i.e., does not include the length prefix. + let hex_lower_hex_trait = format!("{script_code:x}"); + println!("hex created using `LowerHex`: {hex_lower_hex_trait}"); + + // The `deserialize_hex` function requires the length prefix. + assert!(encode::deserialize_hex::(&hex_lower_hex_trait).is_err()); + // And so does `from_hex_prefixed`. + assert!(WitnessScriptBuf::from_hex_prefixed(&hex_lower_hex_trait).is_err()); + // But we provide an explicit constructor that does not. + assert_eq!( + WitnessScriptBuf::from_hex_no_length_prefix(&hex_lower_hex_trait).unwrap(), + script_code + ); + + // This is consensus encoding i.e., includes the length prefix. + let hex_inherent = script_code.to_hex_string_prefixed(); // Defined in `ScriptExt`. + println!("hex created using inherent `to_hex_string_prefixed`: {hex_inherent}"); + + // The inverse of `to_hex_string_prefixed` is `from_hex_prefixed`. + let decoded = WitnessScriptBuf::from_hex_prefixed(&hex_inherent).unwrap(); // Defined in `ScriptBufExt`. + assert_eq!(decoded, script_code); + // We can also parse the output of `to_hex_string_prefixed` using `deserialize_hex`. + let decoded = encode::deserialize_hex::(&hex_inherent).unwrap(); + assert_eq!(decoded, script_code); + + // We also support encode/decode using `consensus::encode` functions. + let encoded = encode::serialize_hex(&script_code); + println!("hex created using consensus::encode::serialize_hex: {encoded}"); + + let decoded: WitnessScriptBuf = encode::deserialize_hex(&encoded).unwrap(); + assert_eq!(decoded, script_code); + + // And we can mix these two calls because both include the length prefix. + let encoded = encode::serialize_hex(&script_code); + let decoded = WitnessScriptBuf::from_hex_prefixed(&encoded).unwrap(); + assert_eq!(decoded, script_code); + + // Encode/decode using a byte vector. + let encoded = encode::serialize(&script_code); + assert_eq!(&encoded[1..], script_code.as_bytes()); // Shows that prefix is the first byte. + let decoded: WitnessScriptBuf = encode::deserialize(&encoded).unwrap(); + assert_eq!(decoded, script_code); + + // to/from bytes excludes the prefix, these are not encoding/decoding functions so this is sane. + let bytes = script_code.to_vec(); + let got = WitnessScriptBuf::from_bytes(bytes); + assert_eq!(got, script_code); +} diff --git a/bitcoin/examples/serde.rs b/bitcoin/examples/serde.rs new file mode 100644 index 000000000..a40f65f43 --- /dev/null +++ b/bitcoin/examples/serde.rs @@ -0,0 +1,59 @@ +//! Serializing with `serde` and `consensus::{Encodable, Decodable}` +//! +//! All types that implement consensus encoding traits can be serde de/serialized. +//! For integer types that can have multiple units we typically provide a few different modules. + +use bitcoin::block::{Header, Version}; +use bitcoin::consensus::serde::Hex; +use bitcoin::consensus::{self}; +use bitcoin::{ + amount, fee_rate, Amount, BlockHash, BlockTime, CompactTarget, FeeRate, TxMerkleNode, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Foo { + /// Consensus encoded into hex is often the best option. + #[serde(with = "consensus::serde::With::")] + header: Header, + + /// This works but it's little-endian which may be hard to read. + /// + /// Integer wrapper types are more readable if they explicitly use a unit. + #[serde(with = "consensus::serde::With::")] + this: Amount, + + /// `Amount` can use sats or bitcoin (`as_btc`). + #[serde(with = "amount::serde::as_sat")] + that: Amount, + + /// `FeeRate` can use kilo weight units or virtual bytes, both floor and ceil. + #[serde(with = "fee_rate::serde::as_sat_per_kwu_floor")] + fee_rate: FeeRate, +} + +fn main() { + let f = Foo { + header: dummy_header(), + this: Amount::ONE_SAT, + that: Amount::ONE_BTC, + fee_rate: FeeRate::DUST, + }; + + let s = serde_json::to_string(&f).unwrap(); + println!("{s}"); + + let deser = serde_json::from_str::(&s).unwrap(); + assert_eq!(deser, f); +} + +fn dummy_header() -> Header { + Header { + version: Version::ONE, + prev_blockhash: BlockHash::from_byte_array([0x99; 32]), + merkle_root: TxMerkleNode::from_byte_array([0x77; 32]), + time: BlockTime::from(2), + bits: CompactTarget::from_consensus(3), + nonce: 4, + } +} diff --git a/bitcoin/examples/sighash.rs b/bitcoin/examples/sighash.rs new file mode 100644 index 000000000..1440cbbfe --- /dev/null +++ b/bitcoin/examples/sighash.rs @@ -0,0 +1,198 @@ +use bitcoin::ext::*; +use bitcoin::{ + consensus, ecdsa, sighash, Amount, CompressedPublicKey, ScriptPubKey, ScriptPubKeyBuf, + Transaction, WitnessScript, +}; +use hex_lit::hex; + +//These are real blockchain transactions examples of computing sighash for: +// - P2WPKH +// - P2MS 2of3 +// - P2SH 2of2 multisig +// - P2WSH 2of2 multisig + +//run with: cargo run --example sighash + +/// Computes SegWit sighash for a transaction input that spends a p2wpkh output with "witness_v0_keyhash" scriptPubKey.type +/// +/// # Parameters +/// +/// * `raw_tx` - the spending tx hex +/// * `inp_idx` - the spending tx input index +/// * `amount` - the ref tx output amount. +fn compute_sighash_p2wpkh(raw_tx: &[u8], inp_idx: usize, amount: Amount) { + let tx: Transaction = consensus::deserialize(raw_tx).unwrap(); + let inp = &tx.inputs[inp_idx]; + let witness = &inp.witness; + println!("Witness: {witness:?}"); + + // BIP-0141: The witness must consist of exactly 2 items (≤ 520 bytes each). The first one a + // signature, and the second one a public key. + assert_eq!(witness.len(), 2); + let sig_bytes = witness.get(0).unwrap(); + let pk_bytes = witness.get(1).unwrap(); + + let sig = ecdsa::Signature::from_slice(sig_bytes).expect("failed to parse sig"); + + //BIP-0143: "The item 5 : For P2WPKH witness program, the scriptCode is 0x1976a914{20-byte-pubkey-hash}88ac" + //this is nothing but a standard P2PKH script OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG: + let pk = CompressedPublicKey::from_slice(pk_bytes).expect("failed to parse pubkey"); + let wpkh = pk.wpubkey_hash(); + println!("Script pubkey hash: {wpkh:x}"); + let spk = ScriptPubKeyBuf::new_p2wpkh(wpkh); + + let mut cache = sighash::SighashCache::new(&tx); + let sighash = cache + .p2wpkh_signature_hash(inp_idx, &spk, amount, sig.sighash_type) + .expect("failed to compute sighash"); + println!("SegWit p2wpkh sighash: {sighash:x}"); + let msg = secp256k1::Message::from(sighash); + println!("Message is {msg:x}"); + pk.verify(msg, sig).unwrap() +} + +/// Computes sighash for a legacy multisig transaction input that spends either a p2sh or a p2ms output. +/// +/// # Parameters +/// +/// * `raw_tx` - the spending tx hex +/// * `inp_idx` - the spending tx input index +/// * `script_pubkey_bytes_opt` - the Option with scriptPubKey bytes. If None, it's p2sh case, i.e., reftx output's scriptPubKey.type is "scripthash". In this case scriptPubkey is extracted from the spending transaction's scriptSig. If Some(), it's p2ms case, i.e., reftx output's scriptPubKey.type is "multisig", and the scriptPubkey is supplied from the referenced output. +fn compute_sighash_legacy(raw_tx: &[u8], inp_idx: usize, script_pubkey_bytes_opt: Option<&[u8]>) { + let tx: Transaction = consensus::deserialize(raw_tx).unwrap(); + let inp = &tx.inputs[inp_idx]; + let script_sig = &inp.script_sig; + println!("scriptSig is: {script_sig}"); + let cache = sighash::SighashCache::new(&tx); + //In the P2SH case we get scriptPubKey from scriptSig of the spending input. + //The scriptSig that corresponds to an M of N multisig should be: PUSHBYTES_0 PUSHBYTES_K0 ... PUSHBYTES_Km PUSHBYTES_X + //Here we assume that we have an M of N multisig scriptPubKey. + let mut instructions: Vec<_> = script_sig.instructions().collect(); + let script_pubkey_p2sh; + let script_pubkey_bytes = match script_pubkey_bytes_opt { + //In the P2MS case, the scriptPubKey is in the referenced output, passed into this function + Some(bytes) => bytes, + //In the P2SH case, the scriptPubKey is the last scriptSig PushBytes instruction + None => { + script_pubkey_p2sh = instructions.pop().unwrap().unwrap(); + script_pubkey_p2sh.push_bytes().unwrap().as_bytes() + } + }; + let script_code = ScriptPubKey::from_bytes(script_pubkey_bytes); + let pushbytes_0 = instructions.remove(0).unwrap(); + assert!( + pushbytes_0.push_bytes().unwrap().as_bytes().is_empty(), + "first in ScriptSig must be PUSHBYTES_0 got {pushbytes_0:?}" + ); + + //All other scriptSig instructions must be signatures + for instr in instructions { + let sig = ecdsa::Signature::from_slice(instr.unwrap().push_bytes().unwrap().as_bytes()) + .expect("failed to parse sig"); + let sighash = cache + .legacy_signature_hash(inp_idx, script_code, sig.sighash_type.to_u32()) + .expect("failed to compute sighash"); + println!("Legacy sighash: {:x} (sighash flag {})", sighash, sig.sighash_type); + } +} + +/// Computes sighash for a SegWit multisig transaction input that spends a p2wsh output with "witness_v0_scripthash" scriptPubKey.type +/// +/// # Parameters +/// +/// * `raw_tx` - the spending tx hex +/// * `inp_idx` - the spending tx input index +/// * `amount` - the ref tx output amount. +fn compute_sighash_p2wsh(raw_tx: &[u8], inp_idx: usize, amount: Amount) { + let tx: Transaction = consensus::deserialize(raw_tx).unwrap(); + let inp = &tx.inputs[inp_idx]; + let witness = &inp.witness; + println!("witness {witness:?}"); + + //last element is called witnessScript according to BIP-0141. It supersedes scriptPubKey. + let witness_script_bytes: &[u8] = witness.last().expect("out of bounds"); + let witness_script = WitnessScript::from_bytes(witness_script_bytes); + let mut cache = sighash::SighashCache::new(&tx); + + //in an M of N multisig, the witness elements from 1 (0-based) to M-2 are signatures (with sighash flags as the last byte) + for n in 1..=witness.len() - 2 { + let sig_bytes = witness.get(n).expect("out of bounds"); + let sig = ecdsa::Signature::from_slice(sig_bytes).expect("failed to parse sig"); + let sig_len = sig_bytes.len() - 1; //last byte is EcdsaSighashType sighash flag + //ECDSA signature in DER format lengths are between 70 and 72 bytes + assert!((70..=72).contains(&sig_len), "signature length {sig_len} out of bounds"); + //here we assume that all sighash_flags are the same. Can they be different? + let sighash = cache + .p2wsh_signature_hash(inp_idx, witness_script, amount, sig.sighash_type) + .expect("failed to compute sighash"); + println!("SegWit p2wsh sighash: {:x} ({})", sighash, sig.sighash_type); + } +} + +fn main() { + sighash_p2wpkh(); + sighash_p2ms_multisig_2x3(); + sighash_p2sh_multisig_2x2(); + sighash_p2wsh_multisig_2x2(); +} + +/// Example showing how to verify the signature for spending a p2wpkh transaction. +fn sighash_p2wpkh() { + //Spending transaction: + //bitcoin-cli getrawtransaction 663becacc6368150a46725e404ccdfa34d1fffbececa784c31f0a7849b4dad08 3 + let raw_tx = hex!("020000000001015ce1d4ffc716022f83cc0d557e6dad0500eeff9e9623bde014bdc09c5b672d750000000000fdffffff025fb7460b000000001600142cf4c1dc0352e0658971ca62a7457a1cd8c3389c4ce3a2000000000016001433f57fe374c6ceab61c8639128c038ac2a8c8db60247304402203cb50efb5c4a9aa7fd369ab6f4b226db99f44f9c610b5b50bc42f343a6aa401302201af791542eee6c1b11705e8895cc5adc36458910dc91aadcafb76a6478a29b9f01210242e811e66fd17e9a6e4ef772766c668d6e0595ca1d7f0583148bc460b575fbfdf0df0b00"); + + //vin:0 + let inp_idx = 0; + //output amount from the referenced vout:0 from the referenced tx: + //bitcoin-cli getrawtransaction 752d675b9cc0bd14e0bd23969effee0005ad6d7e550dcc832f0216c7ffd4e15c 3 + let ref_out_amount = Amount::from_sat_u32(200000000); + + println!("\nsighash_p2wpkh:"); + compute_sighash_p2wpkh(&raw_tx, inp_idx, ref_out_amount); +} + +fn sighash_p2sh_multisig_2x2() { + //Spending transaction: + //bitcoin-cli getrawtransaction 214646c4b563cd8c788754ec94468ab71602f5ed07d5e976a2b0e41a413bcc0e 3 + //after decoding ScriptSig from the input:0, its last ASM element is the scriptpubkey: + //bitcoin-cli decodescript 5221032d7306898e980c66aefdfb6b377eaf71597c449bf9ce741a3380c5646354f6de2103e8c742e1f283ef810c1cd0c8875e5c2998a05fc5b23c30160d3d33add7af565752ae + //its ASM is 2 of 2 multisig: 2 032d7306898e980c66aefdfb6b377eaf71597c449bf9ce741a3380c5646354f6de 03e8c742e1f283ef810c1cd0c8875e5c2998a05fc5b23c30160d3d33add7af5657 2 OP_CHECKMULTISIG + let raw_tx = hex!("0100000001d611ad58b2f5bc0db7d15dfde4f497d6482d1b4a1e8c462ef077d4d32b3dae7901000000da0047304402203b17b4f64fa7299e8a85a688bda3cb1394b80262598bbdffd71dab1d7f266098022019cc20dc20eae417374609cb9ca22b28261511150ed69d39664b9d3b1bcb3d1201483045022100cfff9c400abb4ce5f247bd1c582cf54ec841719b0d39550b714c3c793fb4347b02201427a961a7f32aba4eeb1b71b080ea8712705e77323b747c03c8f5dbdda1025a01475221032d7306898e980c66aefdfb6b377eaf71597c449bf9ce741a3380c5646354f6de2103e8c742e1f283ef810c1cd0c8875e5c2998a05fc5b23c30160d3d33add7af565752aeffffffff020ed000000000000016001477800cff52bd58133b895622fd1220d9e2b47a79cd0902000000000017a914da55145ca5c56ba01f1b0b98d896425aa4b0f4468700000000"); + let inp_idx = 0; + + println!("\nsighash_p2sh_multisig_2x2:"); + compute_sighash_legacy(&raw_tx, inp_idx, None); +} + +fn sighash_p2wsh_multisig_2x2() { + //The spending transaction is + //bitcoin-cli getrawtransaction 2bb157363e7a62d70b92082a9b2c9bb6f329154f816b8d239bd58c35c789a96a 3 + //input 0 (the only input) + //ScriptPubkey from its Witness data is: + //bitcoin-cli decodescript 52210289da5da9d3700156db2d01e6362491733f6c886971791deda74b4e9d707190b2210323c437f30384498be79df2990ce5a8de00844e768c0ccce914335b6c26adea7352ae + //its ASM is 2 0289da5da9d3700156db2d01e6362491733f6c886971791deda74b4e9d707190b2 0323c437f30384498be79df2990ce5a8de00844e768c0ccce914335b6c26adea73 2 OP_CHECKMULTISIG + let raw_tx = hex!("010000000001011b9eb4122976fad8f809ee4cea8ac8d1c5b6b8e0d0f9f93327a5d78c9a3945280000000000ffffffff02ba3e0d00000000002200201c3b09401aaa7c9709d118a75d301bdb2180fb68b2e9b3ade8ad4ff7281780cfa586010000000000220020a41d0d894799879ca1bd88c1c3f1c2fd4b1592821cc3c5bfd5be5238b904b09f040047304402201c7563e876d67b5702aea5726cd202bf92d0b1dc52c4acd03435d6073e630bac022032b64b70d7fba0cb8be30b882ea06c5f8ec7288d113459dd5d3e294214e2c96201483045022100f532f7e3b8fd01a0edc86de4870db4e04858964d0a609df81deb99d9581e6c2e02206d9e9b6ab661176be8194faded62f518cdc6ee74dba919e0f35d77cff81f38e5014752210289da5da9d3700156db2d01e6362491733f6c886971791deda74b4e9d707190b2210323c437f30384498be79df2990ce5a8de00844e768c0ccce914335b6c26adea7352ae00000000"); + //For the witness transaction sighash computation, we need its referenced output's amount from the original transaction: + //bitcoin-cli getrawtransaction 2845399a8cd7a52733f9f9d0e0b8b6c5d1c88aea4cee09f8d8fa762912b49e1b 3 + //we need vout 0 amount: + let ref_out_amount = Amount::from_sat_u32(968240); + + println!("\nsighash_p2wsh_multisig_2x2:"); + compute_sighash_p2wsh(&raw_tx, 0, ref_out_amount); +} + +fn sighash_p2ms_multisig_2x3() { + //Spending tx: + //bitcoin-cli getrawtransaction 949591ad468cef5c41656c0a502d9500671ee421fadb590fbc6373000039b693 3 + //Inp 0 scriptSig has 2 sigs + let raw_tx = hex!("010000000110a5fee9786a9d2d72c25525e52dd70cbd9035d5152fac83b62d3aa7e2301d58000000009300483045022100af204ef91b8dba5884df50f87219ccef22014c21dd05aa44470d4ed800b7f6e40220428fe058684db1bb2bfb6061bff67048592c574effc217f0d150daedcf36787601483045022100e8547aa2c2a2761a5a28806d3ae0d1bbf0aeff782f9081dfea67b86cacb321340220771a166929469c34959daf726a2ac0c253f9aff391e58a3c7cb46d8b7e0fdc4801ffffffff0180a21900000000001976a914971802edf585cdbc4e57017d6e5142515c1e502888ac00000000"); + //Original transaction: + //bitcoin-cli getrawtransaction 581d30e2a73a2db683ac2f15d53590bd0cd72de52555c2722d9d6a78e9fea510 3 + //Out 0 scriptPubKey.type “multisig†has 3 uncompressed pubkeys + let reftx_script_pubkey_bytes = hex!("524104d81fd577272bbe73308c93009eec5dc9fc319fc1ee2e7066e17220a5d47a18314578be2faea34b9f1f8ca078f8621acd4bc22897b03daa422b9bf56646b342a24104ec3afff0b2b66e8152e9018fe3be3fc92b30bf886b3487a525997d00fd9da2d012dce5d5275854adc3106572a5d1e12d4211b228429f5a7b2f7ba92eb0475bb14104b49b496684b02855bc32f5daefa2e2e406db4418f3b86bca5195600951c7d918cdbe5e6d3736ec2abf2dd7610995c3086976b2c0c7b4e459d10b34a316d5a5e753ae"); + let inp_idx = 0; + + println!("\nsighash_p2ms_multisig_2x3:"); + compute_sighash_legacy(&raw_tx, inp_idx, Some(&reftx_script_pubkey_bytes)); +} diff --git a/bitcoin/examples/sign-tx-segwit-v0.rs b/bitcoin/examples/sign-tx-segwit-v0.rs new file mode 100644 index 000000000..5f64df68a --- /dev/null +++ b/bitcoin/examples/sign-tx-segwit-v0.rs @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Demonstrate creating a transaction that spends to and from p2wpkh outputs. + +use bitcoin::ext::*; +use bitcoin::key::WPubkeyHash; +use bitcoin::locktime::absolute; +use bitcoin::secp256k1::{rand, Message, SecretKey}; +use bitcoin::sighash::{EcdsaSighashType, SighashCache}; +use bitcoin::{ + transaction, Address, Amount, Network, OutPoint, ScriptPubKeyBuf, ScriptSigBuf, Sequence, + Transaction, TxIn, TxOut, Txid, Witness, +}; + +const DUMMY_UTXO_AMOUNT: Amount = Amount::from_sat_u32(20_000_000); +const SPEND_AMOUNT: Amount = Amount::from_sat_u32(5_000_000); +const CHANGE_AMOUNT: Amount = Amount::from_sat_u32(14_999_000); // 1000 sat fee. + +fn main() { + // Get a secret key we control and the pubkeyhash of the associated pubkey. + // In a real application these would come from a stored secret. + let (sk, wpkh) = senders_keys(); + + // Get an address to send to. + let address = receivers_address(); + + // Get an unspent output that is locked to the key above that we control. + // In a real application these would come from the chain. + let (dummy_out_point, dummy_utxo) = dummy_unspent_transaction_output(wpkh); + + // The input for the transaction we are constructing. + let input = TxIn { + previous_output: dummy_out_point, // The dummy output we are spending. + script_sig: ScriptSigBuf::default(), // For a p2wpkh script_sig is empty. + sequence: Sequence::ENABLE_LOCKTIME_AND_RBF, + witness: Witness::default(), // Filled in after signing. + }; + + // The spend output is locked to a key controlled by the receiver. + let spend = TxOut { amount: SPEND_AMOUNT, script_pubkey: address.script_pubkey() }; + + // The change output is locked to a key controlled by us. + let change = TxOut { + amount: CHANGE_AMOUNT, + script_pubkey: ScriptPubKeyBuf::new_p2wpkh(wpkh), // Change comes back to us. + }; + + // The transaction we want to sign and broadcast. + let mut unsigned_tx = Transaction { + version: transaction::Version::TWO, // Post BIP-0068. + lock_time: absolute::LockTime::ZERO, // Ignore the locktime. + inputs: vec![input], // Input goes into index 0. + outputs: vec![spend, change], // Outputs, order does not matter. + }; + let input_index = 0; + + // Get the sighash to sign. + let sighash_type = EcdsaSighashType::All; + let mut sighasher = SighashCache::new(&mut unsigned_tx); + let sighash = sighasher + .p2wpkh_signature_hash( + input_index, + &dummy_utxo.script_pubkey, + DUMMY_UTXO_AMOUNT, + sighash_type, + ) + .expect("failed to create sighash"); + + // Sign the sighash using the secp256k1 library (exported by rust-bitcoin). + let msg = Message::from(sighash); + let signature = secp256k1::ecdsa::sign(msg, &sk); + + // Update the witness stack. + let signature = bitcoin::ecdsa::Signature { signature, sighash_type }; + let pk = sk.public_key(); + *sighasher.witness_mut(input_index).unwrap() = Witness::p2wpkh(signature, pk); + + // Get the signed transaction. + let tx = sighasher.into_transaction(); + + // BOOM! Transaction signed and ready to broadcast. + println!("{tx:#?}"); +} + +/// An example of keys controlled by the transaction sender. +/// +/// In a real application these would be actual secrets. +fn senders_keys() -> (SecretKey, WPubkeyHash) { + let sk = SecretKey::new(&mut rand::rng()); + let pk = bitcoin::PublicKey::new(sk.public_key()); + let wpkh = pk.wpubkey_hash().expect("key is compressed"); + + (sk, wpkh) +} + +/// A dummy address for the receiver. +/// +/// We lock the spend output to the key associated with this address. +/// +/// (FWIW this is a random mainnet address from block 80219.) +fn receivers_address() -> Address { + "bc1q7cyrfmck2ffu2ud3rn5l5a8yv6f0chkp0zpemf" + .parse::>() + .expect("a valid address") + .require_network(Network::Bitcoin) + .expect("valid address for mainnet") +} + +/// Constructs a new p2wpkh output locked to the key associated with `wpkh`. +/// +/// An utxo is described by the `OutPoint` (txid and index within the transaction that it was +/// created). Using the out point one can get the transaction by `txid` and using the `vout` get the +/// transaction amount and script pubkey (`TxOut`) of the utxo. +/// +/// This output is locked to keys that we control, in a real application this would be a valid +/// output taken from a transaction that appears in the chain. +fn dummy_unspent_transaction_output(wpkh: WPubkeyHash) -> (OutPoint, TxOut) { + let script_pubkey = ScriptPubKeyBuf::new_p2wpkh(wpkh); + + let out_point = OutPoint { + txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value. + vout: 0, + }; + + let utxo = TxOut { amount: DUMMY_UTXO_AMOUNT, script_pubkey }; + + (out_point, utxo) +} diff --git a/bitcoin/examples/sign-tx-taproot.rs b/bitcoin/examples/sign-tx-taproot.rs new file mode 100644 index 000000000..a1554966e --- /dev/null +++ b/bitcoin/examples/sign-tx-taproot.rs @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Demonstrate creating a transaction that spends to and from p2tr outputs. + +use bitcoin::ext::*; +use bitcoin::key::{Keypair, TapTweak, TweakedKeypair, UntweakedPublicKey}; +use bitcoin::locktime::absolute; +use bitcoin::secp256k1::{rand, SecretKey}; +use bitcoin::sighash::{Prevouts, SighashCache, TapSighashType}; +use bitcoin::{ + transaction, Address, Amount, Network, OutPoint, ScriptPubKeyBuf, ScriptSigBuf, Sequence, + Transaction, TxIn, TxOut, Txid, Witness, +}; + +const DUMMY_UTXO_AMOUNT: Amount = Amount::from_sat_u32(20_000_000); +const SPEND_AMOUNT: Amount = Amount::from_sat_u32(5_000_000); +const CHANGE_AMOUNT: Amount = Amount::from_sat_u32(14_999_000); // 1000 sat fee. + +fn main() { + // Get a keypair we control. In a real application these would come from a stored secret. + let keypair = senders_keys(); + let (internal_key, _parity) = keypair.x_only_public_key(); + + // Get an unspent output that is locked to the key above that we control. + // In a real application these would come from the chain. + let (dummy_out_point, dummy_utxo) = dummy_unspent_transaction_output(internal_key); + + // Get an address to send to. + let address = receivers_address(); + + // The input for the transaction we are constructing. + let input = TxIn { + previous_output: dummy_out_point, // The dummy output we are spending. + script_sig: ScriptSigBuf::default(), // For a p2tr script_sig is empty. + sequence: Sequence::ENABLE_LOCKTIME_AND_RBF, + witness: Witness::default(), // Filled in after signing. + }; + + // The spend output is locked to a key controlled by the receiver. + let spend = TxOut { amount: SPEND_AMOUNT, script_pubkey: address.script_pubkey() }; + + // The change output is locked to a key controlled by us. + let change = TxOut { + amount: CHANGE_AMOUNT, + script_pubkey: ScriptPubKeyBuf::new_p2tr(internal_key, None), // Change comes back to us. + }; + + // The transaction we want to sign and broadcast. + let mut unsigned_tx = Transaction { + version: transaction::Version::TWO, // Post BIP-0068. + lock_time: absolute::LockTime::ZERO, // Ignore the locktime. + inputs: vec![input], // Input goes into index 0. + outputs: vec![spend, change], // Outputs, order does not matter. + }; + let input_index = 0; + + // Get the sighash to sign. + + let sighash_type = TapSighashType::Default; + let prevouts = vec![dummy_utxo]; + let prevouts = Prevouts::All(&prevouts); + + let mut sighasher = SighashCache::new(&mut unsigned_tx); + let sighash = sighasher + .taproot_key_spend_signature_hash(input_index, &prevouts, sighash_type) + .expect("failed to construct sighash"); + + // Sign the sighash using the secp256k1 library (exported by rust-bitcoin). + let tweaked: TweakedKeypair = keypair.tap_tweak(None); + let signature = secp256k1::schnorr::sign(&sighash.to_byte_array(), tweaked.as_keypair()); + + // Update the witness stack. + let signature = bitcoin::taproot::Signature { signature, sighash_type }; + *sighasher.witness_mut(input_index).unwrap() = Witness::p2tr_key_spend(&signature); + + // Get the signed transaction. + let tx = sighasher.into_transaction(); + + // BOOM! Transaction signed and ready to broadcast. + println!("{tx:#?}"); +} + +/// An example of keys controlled by the transaction sender. +/// +/// In a real application these would be actual secrets. +fn senders_keys() -> Keypair { + let sk = SecretKey::new(&mut rand::rng()); + Keypair::from_secret_key(&sk) +} + +/// A dummy address for the receiver. +/// +/// We lock the spend output to the key associated with this address. +/// +/// (FWIW this is an arbitrary mainnet address from block 805222.) +fn receivers_address() -> Address { + "bc1p0dq0tzg2r780hldthn5mrznmpxsxc0jux5f20fwj0z3wqxxk6fpqm7q0va" + .parse::>() + .expect("a valid address") + .require_network(Network::Bitcoin) + .expect("valid address for mainnet") +} + +/// Constructs a new p2tr output locked to the key associated with `internal_key`. +/// +/// An utxo is described by the `OutPoint` (txid and index within the transaction that it was +/// created). Using the out point one can get the transaction by `txid` and using the `vout` get the +/// transaction amount and script pubkey (`TxOut`) of the utxo. +/// +/// This output is locked to keys that we control, in a real application this would be a valid +/// output taken from a transaction that appears in the chain. +fn dummy_unspent_transaction_output>( + internal_key: K, +) -> (OutPoint, TxOut) { + let internal_key = internal_key.into(); + let script_pubkey = ScriptPubKeyBuf::new_p2tr(internal_key, None); + + let out_point = OutPoint { + txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value. + vout: 0, + }; + + let utxo = TxOut { amount: DUMMY_UTXO_AMOUNT, script_pubkey }; + + (out_point, utxo) +} diff --git a/bitcoin/examples/taproot-psbt-simple.rs b/bitcoin/examples/taproot-psbt-simple.rs new file mode 100644 index 000000000..9ab4bfe45 --- /dev/null +++ b/bitcoin/examples/taproot-psbt-simple.rs @@ -0,0 +1,247 @@ +//! Implements a simple multi-input PSBT signing example +//! +//! The purpose of this section is to construct a PSBT that spends multiple inputs and signs it. +//! We'll cover the following [BIP 174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) +//! roles: +//! +//! - **Creator**: Creates a PSBT with multiple inputs and outputs. +//! - **Updater**: Adds Witness and Taproot data to the PSBT. +//! - **Signer**: Signs the PSBT. +//! - **Finalizer**: Finalizes the PSBT. +//! +//! The example will focus on spending two Taproot inputs: +//! +//! 1. 20,000,000 satoshi UTXO, the first receiving ("external") address. +//! 1. 10,000,000 satoshi UTXO, the first change ("internal") address. +//! +//! We'll be sending this to two outputs: +//! +//! 1. 25,000,000 satoshis to a receivers' address. +//! 1. 4,990,000 satoshis back to us as change. +//! +//! The miner's fee will be 10,000 satoshis. +use std::collections::BTreeMap; + +use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, IntoDerivationPath, Xpriv, Xpub}; +use bitcoin::ext::*; +use bitcoin::key::UntweakedPublicKey; +use bitcoin::locktime::absolute; +use bitcoin::psbt::Input; +use bitcoin::{ + consensus, transaction, Address, Amount, Network, OutPoint, Psbt, ScriptPubKeyBuf, + ScriptSigBuf, Sequence, TapLeafHash, TapSighashType, Transaction, TxIn, TxOut, Txid, Witness, + XOnlyPublicKey, +}; + +// The master xpriv, from which we derive the keys we control. +const XPRIV: &str = "xprv9tuogRdb5YTgcL3P8Waj7REqDuQx4sXcodQaWTtEVFEp6yRKh1CjrWfXChnhgHeLDuXxo2auDZegMiVMGGxwxcrb2PmiGyCngLxvLeGsZRq"; + +// The derivation path for the keys we control. +// This follows the BIP 86 derivation path for Bitcoin. +const BIP86_DERIVATION_PATH: &str = "m/86'/0'/0'"; + +// The master fingerprint of the master xpriv. +const MASTER_FINGERPRINT: &str = "9680603f"; + +// The dummy UTXO amounts we are spending. +const DUMMY_UTXO_AMOUNT_INPUT_1: Amount = Amount::from_sat_u32(20_000_000); +const DUMMY_UTXO_AMOUNT_INPUT_2: Amount = Amount::from_sat_u32(10_000_000); + +// The amounts we are sending to someone, and receiving back as change. +const SPEND_AMOUNT: Amount = Amount::from_sat_u32(25_000_000); +const CHANGE_AMOUNT: Amount = Amount::from_sat_u32(4_990_000); // 10_000 sat fee. + +// Derive the external address xpriv. +fn get_external_address_xpriv( + master_xpriv: Xpriv, + index: u32, +) -> Xpriv { + let derivation_path = + BIP86_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); + let child_xpriv = + master_xpriv.derive_xpriv(&derivation_path).expect("only deriving three steps"); + let external_index = ChildNumber::ZERO_NORMAL; + let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); + + child_xpriv.derive_xpriv([external_index, idx]).expect("only deriving two more steps") +} + +// Derive the internal address xpriv. +fn get_internal_address_xpriv( + master_xpriv: Xpriv, + index: u32, +) -> Xpriv { + let derivation_path = + BIP86_DERIVATION_PATH.into_derivation_path().expect("valid derivation path"); + let child_xpriv = + master_xpriv.derive_xpriv(&derivation_path).expect("only deriving three steps"); + let internal_index = ChildNumber::ONE_NORMAL; + let idx = ChildNumber::from_normal_idx(index).expect("valid index number"); + + child_xpriv.derive_xpriv([internal_index, idx]).expect("only deriving two more steps") +} + +// Get the Taproot Key Origin. +fn get_tap_key_origin + std::cmp::Ord>( + x_only_key: K, + master_fingerprint: Fingerprint, + path: DerivationPath, +) -> BTreeMap, (Fingerprint, DerivationPath))> { + let x_only_key = x_only_key.into(); + let mut map = BTreeMap::new(); + map.insert(x_only_key, (vec![], (master_fingerprint, path))); + map +} + +// The address to send to. +fn receivers_address() -> Address { + "bc1p0dq0tzg2r780hldthn5mrznmpxsxc0jux5f20fwj0z3wqxxk6fpqm7q0va" + .parse::>() + .expect("a valid address") + .require_network(Network::Bitcoin) + .expect("valid address for mainnet") +} + +// The dummy unspent transaction outputs that we control. +fn dummy_unspent_transaction_outputs() -> Vec<(OutPoint, TxOut)> { + let script_pubkey_1 = "bc1p80lanj0xee8q667aqcnn0xchlykllfsz3gu5skfv9vjsytaujmdqtv52vu" + .parse::>() + .unwrap() + .require_network(Network::Bitcoin) + .unwrap() + .script_pubkey(); + + let out_point_1 = OutPoint { + txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value. + vout: 0, + }; + + let utxo_1 = TxOut { amount: DUMMY_UTXO_AMOUNT_INPUT_1, script_pubkey: script_pubkey_1 }; + + let script_pubkey_2 = "bc1pfd0jmmdnp278vppcw68tkkmquxtq50xchy7f6wdmjtjm7fgsr8dszdcqce" + .parse::>() + .unwrap() + .require_network(Network::Bitcoin) + .unwrap() + .script_pubkey(); + + let out_point_2 = OutPoint { + txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value. + vout: 1, + }; + + let utxo_2 = TxOut { amount: DUMMY_UTXO_AMOUNT_INPUT_2, script_pubkey: script_pubkey_2 }; + vec![(out_point_1, utxo_1), (out_point_2, utxo_2)] +} + +fn main() { + // Get the individual xprivs we control. In a real application these would come from a stored secret. + let master_xpriv = XPRIV.parse::().expect("valid xpriv"); + let xpriv_input_1 = get_external_address_xpriv(master_xpriv, 0); + let xpriv_input_2 = get_internal_address_xpriv(master_xpriv, 0); + let xpriv_change = get_internal_address_xpriv(master_xpriv, 1); + + // Get the PKs + let (pk_input_1, _) = Xpub::from_xpriv(&xpriv_input_1).public_key.x_only_public_key(); + let (pk_input_2, _) = Xpub::from_xpriv(&xpriv_input_2).public_key.x_only_public_key(); + let (pk_change, _) = Xpub::from_xpriv(&xpriv_change).public_key.x_only_public_key(); + + // Get the Tap Key Origins + // Map of tap root X-only keys to origin info and leaf hashes contained in it. + let origin_input_1 = get_tap_key_origin( + pk_input_1, + MASTER_FINGERPRINT.parse::().unwrap(), + "m/86'/0'/0'/0/0".parse::().unwrap(), + ); + let origin_input_2 = get_tap_key_origin( + pk_input_2, + MASTER_FINGERPRINT.parse::().unwrap(), + "m/86'/0'/0'/1/0".parse::().unwrap(), + ); + let origins = [origin_input_1, origin_input_2]; + + // Get the unspent outputs that are locked to the key above that we control. + // In a real application these would come from the chain. + let utxos: Vec = + dummy_unspent_transaction_outputs().into_iter().map(|(_, utxo)| utxo).collect(); + + // Get the addresses to send to. + let address = receivers_address(); + + // The inputs for the transaction we are constructing. + let inputs: Vec = dummy_unspent_transaction_outputs() + .into_iter() + .map(|(outpoint, _)| TxIn { + previous_output: outpoint, + script_sig: ScriptSigBuf::default(), + sequence: Sequence::ENABLE_LOCKTIME_AND_RBF, + witness: Witness::default(), + }) + .collect(); + + // The spend output is locked to a key controlled by the receiver. + let spend = TxOut { amount: SPEND_AMOUNT, script_pubkey: address.script_pubkey() }; + + // The change output is locked to a key controlled by us. + let change = TxOut { + amount: CHANGE_AMOUNT, + script_pubkey: ScriptPubKeyBuf::new_p2tr(pk_change, None), // Change comes back to us. + }; + + // The transaction we want to sign and broadcast. + let unsigned_tx = Transaction { + version: transaction::Version::TWO, // Post BIP 68. + lock_time: absolute::LockTime::ZERO, // Ignore the locktime. + inputs, // Input is 0-indexed. + outputs: vec![spend, change], // Outputs, order does not matter. + }; + + // Now we'll start the PSBT workflow. + // Step 1: Creator role; that creates, + // and add inputs and outputs to the PSBT. + let mut psbt = Psbt::from_unsigned_tx(unsigned_tx).expect("could not create PSBT"); + + // Step 2:Updater role; that adds additional + // information to the PSBT. + let ty = TapSighashType::All.into(); + psbt.inputs = vec![ + Input { + witness_utxo: Some(utxos[0].clone()), + tap_key_origins: origins[0].clone(), + tap_internal_key: Some(pk_input_1.into()), + sighash_type: Some(ty), + ..Default::default() + }, + Input { + witness_utxo: Some(utxos[1].clone()), + tap_key_origins: origins[1].clone(), + tap_internal_key: Some(pk_input_2.into()), + sighash_type: Some(ty), + ..Default::default() + }, + ]; + + // Step 3: Signer role; that signs the PSBT. + psbt.sign(&master_xpriv).expect("valid signature"); + + // Step 4: Finalizer role; that finalizes the PSBT. + psbt.inputs.iter_mut().for_each(|input| { + let script_witness = Witness::p2tr_key_spend(&input.tap_key_sig.unwrap()); + input.final_script_witness = Some(script_witness); + + // Clear all the data fields as per the spec. + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + }); + + // BOOM! Transaction signed and ready to broadcast. + let signed_tx = psbt.extract_tx().expect("valid transaction"); + let serialized_signed_tx = consensus::encode::serialize_hex(&signed_tx); + println!("Transaction Details: {signed_tx:#?}"); + // check with: + // bitcoin-cli decoderawtransaction true + println!("Raw Transaction: {serialized_signed_tx}"); +} diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs new file mode 100644 index 000000000..f10be9509 --- /dev/null +++ b/bitcoin/examples/taproot-psbt.rs @@ -0,0 +1,751 @@ +//! Example of Taproot PSBT workflow + +// We use the alias `alias bt='bitcoin-cli -regtest'` for brevity. + +// Step 0 - Wipe the `regtest` data directory to start from a clean slate. + +// Step 1 - Run `bitcoind -regtest -daemon` to start the daemon. Bitcoin Core 23.0+ is required. + +// Step 2 - +// 2.1) Run `bt -named createwallet wallet_name=benefactor blank=true` to create a blank wallet with the name "benefactor" +// 2.2) Run `bt -named createwallet wallet_name=beneficiary blank=true` to create a blank wallet with the name "beneficiary" +// 2.3) Create the two aliases: +// alias bt-benefactor='bitcoin-cli -regtest -rpcwallet=benefactor' +// alias bt-beneficiary='bitcoin-cli -regtest -rpcwallet=beneficiary' +// +// 2.4) Import the example descriptors: +// bt-benefactor importdescriptors '[ +// { "desc": "tr(tprv8ZgxMBicQKsPd4arFr7sKjSnKFDVMR2JHw9Y8L9nXN4kiok4u28LpHijEudH3mMYoL4pM5UL9Bgdz2M4Cy8EzfErmU9m86ZTw6hCzvFeTg7/86\'/1\'/0\'/1/*)#jzyeered", "active": true, "timestamp": "now", "internal": true }, +// { "desc": "tr(tprv8ZgxMBicQKsPd4arFr7sKjSnKFDVMR2JHw9Y8L9nXN4kiok4u28LpHijEudH3mMYoL4pM5UL9Bgdz2M4Cy8EzfErmU9m86ZTw6hCzvFeTg7/86\'/1\'/0\'/0/*)#rkpcykf4", "active": true, "timestamp": "now" } +// ]' +// bt-beneficiary importdescriptors '[ +// { "desc": "tr(tprv8ZgxMBicQKsPe72C5c3cugP8b7AzEuNjP4NSC17Dkpqk5kaAmsL6FHwPsVxPpURVqbNwdLAbNqi8Cvdq6nycDwYdKHDjDRYcsMzfshimAUq/86\'/1\'/0\'/1/*)#w4ehwx46", "active": true, "timestamp": "now", "internal": true }, +// { "desc": "tr(tprv8ZgxMBicQKsPe72C5c3cugP8b7AzEuNjP4NSC17Dkpqk5kaAmsL6FHwPsVxPpURVqbNwdLAbNqi8Cvdq6nycDwYdKHDjDRYcsMzfshimAUq/86\'/1\'/0\'/0/*)#lpuknn9z", "active": true, "timestamp": "now" } +// ]' +// +// The xpriv and derivation path from the imported descriptors +const BENEFACTOR_XPRIV_STR: &str = "tprv8ZgxMBicQKsPd4arFr7sKjSnKFDVMR2JHw9Y8L9nXN4kiok4u28LpHijEudH3mMYoL4pM5UL9Bgdz2M4Cy8EzfErmU9m86ZTw6hCzvFeTg7"; +const BENEFICIARY_XPRIV_STR: &str = "tprv8ZgxMBicQKsPe72C5c3cugP8b7AzEuNjP4NSC17Dkpqk5kaAmsL6FHwPsVxPpURVqbNwdLAbNqi8Cvdq6nycDwYdKHDjDRYcsMzfshimAUq"; +const BIP86_DERIVATION_PATH: &str = "m/86'/1'/0'/0/0"; + +// Step 3 - +// Run `bt generatetoaddress 103 $(bt-benefactor getnewaddress '' bech32m)` to generate 103 new blocks +// with block reward being sent to a newly created P2TR address in the `benefactor` wallet. +// This will leave us with 3 mature UTXOs that can be spent. Each will be used in a different example below. + +// Step 4 - Run `bt-benefactor listunspent` to display our three spendable UTXOs. Check that everything is the same as below +// - otherwise modify it. The txids should be deterministic on regtest: + +const UTXO_SCRIPT_PUBKEY: &str = + "5120be27fa8b1f5278faf82cab8da23e8761f8f9bd5d5ebebbb37e0e12a70d92dd16"; +const UTXO_PUBKEY: &str = "a6ac32163539c16b6b5dbbca01b725b8e8acaa5f821ba42c80e7940062140d19"; +const UTXO_MASTER_FINGERPRINT: &str = "e61b318f"; +const ABSOLUTE_FEES: Amount = Amount::from_sat_u32(1_000); + +// UTXO_1 will be used for spending example 1 +const UTXO_1: P2trUtxo = P2trUtxo { + txid: "a85d89b4666fed622281d3589474aa1f87971b54bd5d9c1899ed2e8e0447cc06", + vout: 0, + script_pubkey: UTXO_SCRIPT_PUBKEY, + pubkey: UTXO_PUBKEY, + master_fingerprint: UTXO_MASTER_FINGERPRINT, + amount: Amount::FIFTY_BTC, + derivation_path: BIP86_DERIVATION_PATH, +}; + +// UTXO_2 will be used for spending example 2 +const UTXO_2: P2trUtxo = P2trUtxo { + txid: "6f1c1df5862a67f4b6d1cde9a87e3c441b483ba6a140fbec2815f03aa3a5309d", + vout: 0, + script_pubkey: UTXO_SCRIPT_PUBKEY, + pubkey: UTXO_PUBKEY, + master_fingerprint: UTXO_MASTER_FINGERPRINT, + amount: Amount::FIFTY_BTC, + derivation_path: BIP86_DERIVATION_PATH, +}; + +// UTXO_3 will be used for spending example 3 +const UTXO_3: P2trUtxo = P2trUtxo { + txid: "9795fed5aedca219244a396dfd7bce55c851274418383c3ab43530e3f74e5dcc", + vout: 0, + script_pubkey: UTXO_SCRIPT_PUBKEY, + pubkey: UTXO_PUBKEY, + master_fingerprint: UTXO_MASTER_FINGERPRINT, + amount: Amount::FIFTY_BTC, + derivation_path: BIP86_DERIVATION_PATH, +}; + +use std::collections::BTreeMap; + +use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpriv, Xpub}; +use bitcoin::consensus::encode; +use bitcoin::ext::*; +use bitcoin::key::{TapTweak, XOnlyPublicKey}; +use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP}; +use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType}; +use bitcoin::sighash::{self, SighashCache, TapSighash, TapSighashType}; +use bitcoin::taproot::{self, LeafVersion, TapLeafHash, TaprootBuilder, TaprootSpendInfo}; +use bitcoin::{ + absolute, script, transaction, Address, Amount, Network, OutPoint, ScriptPubKeyBuf, + ScriptSigBuf, TapScriptBuf, Transaction, TxIn, TxOut, Witness, +}; + +fn main() -> Result<(), Box> { + println!("\n----------------"); + println!("\nSTART EXAMPLE 1 - P2TR with a BIP-0086 commitment, signed with internal key\n"); + + // Just some addresses for outputs from our wallets. Not really important. + let to_address = "bcrt1p0p3rvwww0v9znrclp00uneq8ytre9kj922v8fxhnezm3mgsmn9usdxaefc" + .parse::>()? + .require_network(Network::Regtest)?; + let change_address = "bcrt1pz449kexzydh2kaypatup5ultru3ej284t6eguhnkn6wkhswt0l7q3a7j76" + .parse::>()? + .require_network(Network::Regtest)?; + let amount_to_send = Amount::ONE_BTC; + let change_amount = UTXO_1 + .amount + .checked_sub(amount_to_send) + .and_then(|x| x.checked_sub(ABSOLUTE_FEES)) + .ok_or("fees more than input amount!")?; + + let tx_hex_string = encode::serialize_hex(&generate_bip86_key_spend_tx( + // The master extended private key from the descriptor in step 4 + BENEFACTOR_XPRIV_STR.parse::()?, + // Set these fields with valid data for the UTXO from step 5 above + UTXO_1, + vec![ + TxOut { amount: amount_to_send, script_pubkey: to_address.script_pubkey() }, + TxOut { amount: change_amount, script_pubkey: change_address.script_pubkey() }, + ], + )?); + println!( + "\nYou should now be able to broadcast the following transaction: \n\n{tx_hex_string}" + ); + + println!("\nEND EXAMPLE 1\n"); + println!("----------------\n"); + + println!("START EXAMPLE 2 - Script path spending of inheritance UTXO\n"); + + { + let beneficiary = BeneficiaryWallet::new(BENEFICIARY_XPRIV_STR.parse::()?)?; + + let mut benefactor = BenefactorWallet::new( + BENEFACTOR_XPRIV_STR.parse::()?, + beneficiary.master_xpub(), + )?; + let (tx, psbt) = benefactor.create_inheritance_funding_tx( + absolute::LockTime::from_height(1000).unwrap(), + UTXO_2, + )?; + let tx_hex = encode::serialize_hex(&tx); + + println!("Inheritance funding tx hex:\n\n{tx_hex}"); + // You can now broadcast the transaction hex: + // bt sendrawtransaction ... + // + // And mine a block to confirm the transaction: + // bt generatetoaddress 1 $(bt-benefactor getnewaddress '' 'bech32m') + + let spending_tx = beneficiary.spend_inheritance( + psbt, + absolute::LockTime::from_height(1000).unwrap(), + to_address, + )?; + let spending_tx_hex = encode::serialize_hex(&spending_tx); + println!("\nInheritance spending tx hex:\n\n{spending_tx_hex}"); + // If you try to broadcast now, the transaction will be rejected as it is timelocked. + // First mine 900 blocks so we're sure we are over the 1000 block locktime: + // bt generatetoaddress 900 $(bt-benefactor getnewaddress '' 'bech32m') + // Then broadcast the transaction with `bt sendrawtransaction ...` + } + + println!("\nEND EXAMPLE 2\n"); + println!("----------------\n"); + + println!("START EXAMPLE 3 - Key path spending of inheritance UTXO\n"); + + { + let beneficiary = BeneficiaryWallet::new(BENEFICIARY_XPRIV_STR.parse::()?)?; + + let mut benefactor = BenefactorWallet::new( + BENEFACTOR_XPRIV_STR.parse::()?, + beneficiary.master_xpub(), + )?; + let (tx, _) = benefactor.create_inheritance_funding_tx( + absolute::LockTime::from_height(2000).unwrap(), + UTXO_3, + )?; + let tx_hex = encode::serialize_hex(&tx); + + println!("Inheritance funding tx hex:\n\n{tx_hex}"); + // You can now broadcast the transaction hex: + // bt sendrawtransaction ... + // + // And mine a block to confirm the transaction: + // bt generatetoaddress 1 $(bt-benefactor getnewaddress '' 'bech32m') + + // At some point we may want to extend the locktime further into the future for the beneficiary. + // We can do this by "refreshing" the inheritance transaction as the benefactor. This effectively + // spends the inheritance transaction via the key path of the Taproot output, and is not encumbered + // by the timelock so we can spend it immediately. We set up a new output similar to the first with + // a locktime that is 'locktime_delta' blocks greater. + let (tx, _) = benefactor.refresh_tx(1000)?; + let tx_hex = encode::serialize_hex(&tx); + + println!("\nRefreshed inheritance tx hex:\n\n{tx_hex}\n"); + + println!("\nEND EXAMPLE 3\n"); + println!("----------------\n"); + } + + Ok(()) +} + +struct P2trUtxo<'a> { + txid: &'a str, + vout: u32, + script_pubkey: &'a str, + pubkey: &'a str, + master_fingerprint: &'a str, + amount: Amount, + derivation_path: &'a str, +} + +#[allow(clippy::single_element_loop)] +fn generate_bip86_key_spend_tx( + master_xpriv: Xpriv, + input_utxo: P2trUtxo, + outputs: Vec, +) -> Result> { + let from_amount = input_utxo.amount; + let input_pubkey = input_utxo.pubkey.parse::()?; + + // CREATOR + UPDATER + let tx1 = Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { txid: input_utxo.txid.parse()?, vout: input_utxo.vout }, + script_sig: ScriptSigBuf::new(), + sequence: bitcoin::Sequence(0xFFFFFFFF), // Ignore nSequence. + witness: Witness::default(), + }], + outputs, + }; + let mut psbt = Psbt::from_unsigned_tx(tx1)?; + + let mut origins = BTreeMap::new(); + origins.insert( + input_pubkey, + ( + vec![], + ( + input_utxo.master_fingerprint.parse::()?, + input_utxo.derivation_path.parse::()?, + ), + ), + ); + + let mut input = Input { + witness_utxo: { + let script_pubkey = + ScriptPubKeyBuf::from_hex_no_length_prefix(input_utxo.script_pubkey) + .expect("failed to parse input utxo scriptPubkey"); + Some(TxOut { amount: from_amount, script_pubkey }) + }, + tap_key_origins: origins, + ..Default::default() + }; + let ty = "SIGHASH_ALL".parse::()?; + input.sighash_type = Some(ty); + input.tap_internal_key = Some(input_pubkey); + psbt.inputs = vec![input]; + + // The `Prevouts::All` array is used to create the sighash to sign for each input in the + // `psbt.inputs` array, as such it must be the same length and in the same order as the inputs. + let mut input_txouts = Vec::::new(); + for input in [&input_utxo].iter() { + input_txouts.push(TxOut { + amount: input.amount, + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(input.script_pubkey)?, + }); + } + + // SIGNER + let unsigned_tx = psbt.unsigned_tx.clone(); + psbt.inputs.iter_mut().enumerate().try_for_each::<_, Result<(), Box>>( + |(vout, input)| { + let sighash_type = input + .sighash_type + .and_then(|psbt_sighash_type| psbt_sighash_type.taproot_hash_ty().ok()) + .unwrap_or(TapSighashType::All); + let hash = SighashCache::new(&unsigned_tx).taproot_key_spend_signature_hash( + vout, + &sighash::Prevouts::All(input_txouts.as_slice()), + sighash_type, + )?; + + let (_, (_, derivation_path)) = input + .tap_key_origins + .get(&input.tap_internal_key.ok_or("internal key missing in PSBT")?) + .ok_or("missing Taproot key origin")?; + + let secret_key = + master_xpriv.derive_xpriv(derivation_path)?.to_private_key().inner; + sign_psbt_taproot( + secret_key, + input.tap_internal_key.unwrap(), + None, + input, + hash, + sighash_type, + ); + + Ok(()) + }, + )?; + + // FINALIZER + psbt.inputs.iter_mut().for_each(|input| { + let mut script_witness: Witness = Witness::new(); + script_witness.push(input.tap_key_sig.unwrap().to_vec()); + input.final_script_witness = Some(script_witness); + + // Clear all the data fields as per the spec. + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + }); + + // EXTRACTOR + let tx = psbt.extract_tx_unchecked_fee_rate(); + tx.verify(|_| { + Some(TxOut { + amount: from_amount, + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(input_utxo.script_pubkey) + .unwrap(), + }) + }) + .expect("failed to verify transaction"); + + Ok(tx) +} + +/// A wallet that allows creating and spending from an inheritance directly via the key path for purposes +/// of refreshing the inheritance timelock or changing other spending conditions. +struct BenefactorWallet { + master_xpriv: Xpriv, + beneficiary_xpub: Xpub, + current_spend_info: Option, + next_psbt: Option, + next: ChildNumber, +} + +impl BenefactorWallet { + fn new( + master_xpriv: Xpriv, + beneficiary_xpub: Xpub, + ) -> Result> { + Ok(Self { + master_xpriv, + beneficiary_xpub, + current_spend_info: None, + next_psbt: None, + next: ChildNumber::ZERO_NORMAL, + }) + } + + fn time_lock_script( + locktime: absolute::LockTime, + beneficiary_key: XOnlyPublicKey, + ) -> TapScriptBuf { + script::Builder::new() + .push_lock_time(locktime) + .push_opcode(OP_CLTV) + .push_opcode(OP_DROP) + .push_x_only_key(beneficiary_key) + .push_opcode(OP_CHECKSIG) + .into_script() + } + + fn create_inheritance_funding_tx( + &mut self, + lock_time: absolute::LockTime, + input_utxo: P2trUtxo, + ) -> Result<(Transaction, Psbt), Box> { + if let ChildNumber::Normal { index } = self.next { + if index > 0 && self.current_spend_info.is_some() { + return Err( + "transaction already exists, use refresh_tx to refresh the timelock".into() + ); + } + } + // We use some other derivation path in this example for our inheritance protocol. The important thing is to ensure + // that we use an unhardened path so we can make use of xpubs. + let derivation_path = format!("101/1/0/0/{}", self.next).parse::()?; + let internal_keypair = self + .master_xpriv + .derive_xpriv(&derivation_path) + .expect("derivation path is short") + .to_keypair(); + let beneficiary_key = + self.beneficiary_xpub.derive_xpub(&derivation_path)?.to_x_only_public_key(); + + // Build up the leaf script and combine with internal key into a Taproot commitment + let script = Self::time_lock_script(lock_time, beneficiary_key); + let leaf_hash = script.tapscript_leaf_hash(); + + let taproot_spend_info = TaprootBuilder::new() + .add_leaf(0, script.clone())? + .finalize(internal_keypair.x_only_public_key().0) + .expect("should be finalizable"); + self.current_spend_info = Some(taproot_spend_info.clone()); + let script_pubkey = ScriptPubKeyBuf::new_p2tr( + taproot_spend_info.internal_key(), + taproot_spend_info.merkle_root(), + ); + let amount = (input_utxo.amount - ABSOLUTE_FEES) + .expect("ABSOLUTE_FEES must be set below input amount"); + + // Spend a normal BIP-0086-like output as an input in our inheritance funding transaction + let tx = generate_bip86_key_spend_tx( + self.master_xpriv, + input_utxo, + vec![TxOut { script_pubkey: script_pubkey.clone(), amount }], + )?; + + // CREATOR + UPDATER + let next_tx = Transaction { + version: transaction::Version::TWO, + lock_time, + inputs: vec![TxIn { + previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 }, + script_sig: ScriptSigBuf::new(), + sequence: bitcoin::Sequence(0xFFFFFFFD), // enable locktime and opt-in RBF + witness: Witness::default(), + }], + outputs: vec![], + }; + let mut next_psbt = Psbt::from_unsigned_tx(next_tx)?; + let mut origins = BTreeMap::new(); + origins.insert( + beneficiary_key, + (vec![leaf_hash], (self.beneficiary_xpub.fingerprint(), derivation_path.clone())), + ); + origins.insert( + internal_keypair.x_only_public_key().0.into(), + (vec![], (self.master_xpriv.fingerprint(), derivation_path)), + ); + let ty = "SIGHASH_ALL".parse::()?; + let mut tap_scripts = BTreeMap::new(); + tap_scripts.insert( + taproot_spend_info.control_block(&(script.clone(), LeafVersion::TapScript)).unwrap(), + (script, LeafVersion::TapScript), + ); + + let input = Input { + witness_utxo: { Some(TxOut { amount, script_pubkey }) }, + tap_key_origins: origins, + tap_merkle_root: taproot_spend_info.merkle_root(), + sighash_type: Some(ty), + tap_internal_key: Some(internal_keypair.x_only_public_key().0.into()), + tap_scripts, + ..Default::default() + }; + + next_psbt.inputs = vec![input]; + self.next_psbt = Some(next_psbt.clone()); + + self.next.increment()?; + Ok((tx, next_psbt)) + } + + fn refresh_tx( + &mut self, + lock_time_delta: u32, + ) -> Result<(Transaction, Psbt), Box> { + if let Some(ref spend_info) = self.current_spend_info.clone() { + let mut psbt = self.next_psbt.clone().expect("should have next_psbt"); + let input = &mut psbt.inputs[0]; + let input_amount = input.witness_utxo.as_ref().unwrap().amount; + let output_amount = (input_amount - ABSOLUTE_FEES).into_result()?; + + // We use some other derivation path in this example for our inheritance protocol. The important thing is to ensure + // that we use an unhardened path so we can make use of xpubs. + let new_derivation_path = + format!("101/1/0/0/{}", self.next).parse::()?; + let new_internal_keypair = self + .master_xpriv + .derive_xpriv(&new_derivation_path) + .expect("derivation path is short") + .to_keypair(); + let beneficiary_key = self + .beneficiary_xpub + .derive_xpub(&new_derivation_path)? + .to_x_only_public_key(); + + // Build up the leaf script and combine with internal key into a Taproot commitment + let lock_time = absolute::LockTime::from_height( + psbt.unsigned_tx.lock_time.to_consensus_u32() + lock_time_delta, + ) + .unwrap(); + let script = Self::time_lock_script(lock_time, beneficiary_key); + let leaf_hash = script.tapscript_leaf_hash(); + + let taproot_spend_info = TaprootBuilder::new() + .add_leaf(0, script.clone())? + .finalize(new_internal_keypair.x_only_public_key().0) + .expect("should be finalizable"); + self.current_spend_info = Some(taproot_spend_info.clone()); + let prevout_script_pubkey = input.witness_utxo.as_ref().unwrap().script_pubkey.clone(); + let output_script_pubkey = ScriptPubKeyBuf::new_p2tr( + taproot_spend_info.internal_key(), + taproot_spend_info.merkle_root(), + ); + + psbt.unsigned_tx.outputs = + vec![TxOut { script_pubkey: output_script_pubkey.clone(), amount: output_amount }]; + psbt.outputs = vec![Output::default()]; + psbt.unsigned_tx.lock_time = absolute::LockTime::ZERO; + + let sighash_type = input + .sighash_type + .and_then(|psbt_sighash_type| psbt_sighash_type.taproot_hash_ty().ok()) + .unwrap_or(TapSighashType::All); + let hash = SighashCache::new(&psbt.unsigned_tx).taproot_key_spend_signature_hash( + 0, + &sighash::Prevouts::All(&[TxOut { + amount: input_amount, + script_pubkey: prevout_script_pubkey, + }]), + sighash_type, + )?; + + { + let (_, (_, derivation_path)) = input + .tap_key_origins + .get(&input.tap_internal_key.ok_or("internal key missing in PSBT")?) + .ok_or("missing Taproot key origin")?; + let secret_key = self + .master_xpriv + .derive_xpriv(derivation_path) + .expect("derivation path is short") + .to_private_key() + .inner; + sign_psbt_taproot( + secret_key, + spend_info.internal_key(), + None, + input, + hash, + sighash_type, + ); + } + + // FINALIZER + psbt.inputs.iter_mut().for_each(|input| { + let mut script_witness: Witness = Witness::new(); + script_witness.push(input.tap_key_sig.unwrap().to_vec()); + input.final_script_witness = Some(script_witness); + + // Clear all the data fields as per the spec. + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + }); + + // EXTRACTOR + let tx = psbt.extract_tx_unchecked_fee_rate(); + tx.verify(|_| { + Some(TxOut { amount: input_amount, script_pubkey: output_script_pubkey.clone() }) + }) + .expect("failed to verify transaction"); + + let next_tx = Transaction { + version: transaction::Version::TWO, + lock_time, + inputs: vec![TxIn { + previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 }, + script_sig: ScriptSigBuf::new(), + sequence: bitcoin::Sequence(0xFFFFFFFD), // enable locktime and opt-in RBF + witness: Witness::default(), + }], + outputs: vec![], + }; + let mut next_psbt = Psbt::from_unsigned_tx(next_tx)?; + let mut origins = BTreeMap::new(); + origins.insert( + beneficiary_key, + (vec![leaf_hash], (self.beneficiary_xpub.fingerprint(), new_derivation_path)), + ); + let ty = "SIGHASH_ALL".parse::()?; + let mut tap_scripts = BTreeMap::new(); + tap_scripts.insert( + taproot_spend_info + .control_block(&(script.clone(), LeafVersion::TapScript)) + .unwrap(), + (script, LeafVersion::TapScript), + ); + + let input = Input { + witness_utxo: { + let script_pubkey = output_script_pubkey; + let amount = output_amount; + + Some(TxOut { amount, script_pubkey }) + }, + tap_key_origins: origins, + tap_merkle_root: taproot_spend_info.merkle_root(), + sighash_type: Some(ty), + tap_internal_key: Some(new_internal_keypair.x_only_public_key().0.into()), + tap_scripts, + ..Default::default() + }; + + next_psbt.inputs = vec![input]; + self.next_psbt = Some(next_psbt.clone()); + + self.next.increment()?; + Ok((tx, next_psbt)) + } else { + Err("no current_spend_info available. Create an inheritance tx first.".into()) + } + } +} + +/// A wallet that allows spending from an inheritance locked to a P2TR UTXO via a script path +/// after some expiry using CLTV. +struct BeneficiaryWallet { + master_xpriv: Xpriv, +} + +impl BeneficiaryWallet { + fn new(master_xpriv: Xpriv) -> Result> { + Ok(Self { master_xpriv }) + } + + fn master_xpub(&self) -> Xpub { Xpub::from_xpriv(&self.master_xpriv) } + + fn spend_inheritance( + &self, + mut psbt: Psbt, + lock_time: absolute::LockTime, + to_address: Address, + ) -> Result> { + let input_amount = psbt.inputs[0].witness_utxo.as_ref().unwrap().amount; + let input_script_pubkey = + psbt.inputs[0].witness_utxo.as_ref().unwrap().script_pubkey.clone(); + psbt.unsigned_tx.lock_time = lock_time; + psbt.unsigned_tx.outputs = vec![TxOut { + script_pubkey: to_address.script_pubkey(), + amount: (input_amount - ABSOLUTE_FEES) + .expect("ABSOLUTE_FEES must be set below input amount"), + }]; + psbt.outputs = vec![Output::default()]; + let unsigned_tx = psbt.unsigned_tx.clone(); + + // SIGNER + for (x_only_pubkey, (leaf_hashes, (_, derivation_path))) in + &psbt.inputs[0].tap_key_origins.clone() + { + let secret_key = + self.master_xpriv.derive_xpriv(derivation_path)?.to_private_key().inner; + for lh in leaf_hashes { + let sighash_type = TapSighashType::All; + let hash = SighashCache::new(&unsigned_tx).taproot_script_spend_signature_hash( + 0, + &sighash::Prevouts::All(&[TxOut { + amount: input_amount, + script_pubkey: input_script_pubkey.clone(), + }]), + *lh, + sighash_type, + )?; + sign_psbt_taproot( + secret_key, + *x_only_pubkey, + Some(*lh), + &mut psbt.inputs[0], + hash, + sighash_type, + ); + } + } + + // FINALIZER + psbt.inputs.iter_mut().for_each(|input| { + let mut script_witness: Witness = Witness::new(); + for (_, signature) in input.tap_script_sigs.iter() { + script_witness.push(signature.to_vec()); + } + for (control_block, (script, _)) in input.tap_scripts.iter() { + script_witness.push(script.to_vec()); + script_witness.push(control_block.serialize()); + } + input.final_script_witness = Some(script_witness); + + // Clear all the data fields as per the spec. + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + input.tap_script_sigs = BTreeMap::new(); + input.tap_scripts = BTreeMap::new(); + input.tap_key_sig = None; + }); + + // EXTRACTOR + let tx = psbt.extract_tx_unchecked_fee_rate(); + tx.verify(|_| { + Some(TxOut { amount: input_amount, script_pubkey: input_script_pubkey.clone() }) + }) + .expect("failed to verify transaction"); + + Ok(tx) + } +} + +// Lifted and modified from BDK at https://github.com/bitcoindevkit/bdk/blob/8fbe40a9181cc9e22cabfc04d57dac5d459da87d/src/wallet/signer.rs#L469-L503 + +// Bitcoin Dev Kit +// Written in 2020 by Alekos Filini +// +// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +// Calling this with `leaf_hash` = `None` will sign for key-spend +fn sign_psbt_taproot( + secret_key: secp256k1::SecretKey, + pubkey: XOnlyPublicKey, + leaf_hash: Option, + psbt_input: &mut psbt::Input, + hash: TapSighash, + sighash_type: TapSighashType, +) { + let keypair = secp256k1::Keypair::from_seckey_byte_array(secret_key.to_secret_bytes()).unwrap(); + let keypair = match leaf_hash { + None => keypair.tap_tweak(psbt_input.tap_merkle_root).to_keypair(), + Some(_) => keypair, // no tweak for script spend + }; + + let signature = secp256k1::schnorr::sign(&hash.to_byte_array(), &keypair); + + let final_signature = taproot::Signature { signature, sighash_type }; + + if let Some(lh) = leaf_hash { + psbt_input.tap_script_sigs.insert((pubkey, lh), final_signature); + } else { + psbt_input.tap_key_sig = Some(final_signature); + } +} diff --git a/bitcoin/src/address/error.rs b/bitcoin/src/address/error.rs new file mode 100644 index 000000000..822909200 --- /dev/null +++ b/bitcoin/src/address/error.rs @@ -0,0 +1,358 @@ +//! Error code for the address module. + +use core::convert::Infallible; +use core::fmt; + +use internals::write_err; + +use crate::address::{Address, NetworkUnchecked}; +use crate::prelude::String; +use crate::script::{witness_program, witness_version}; +use crate::Network; + +/// Error while generating address from script. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum FromScriptError { + /// Script is not a p2pkh, p2sh or witness program. + UnrecognizedScript, + /// A witness program error. + WitnessProgram(witness_program::Error), + /// A witness version construction error. + WitnessVersion(witness_version::TryFromError), +} + +impl From for FromScriptError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for FromScriptError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::WitnessVersion(ref e) => write_err!(f, "witness version construction error"; e), + Self::WitnessProgram(ref e) => write_err!(f, "witness program error"; e), + Self::UnrecognizedScript => write!(f, "script is not a p2pkh, p2sh or witness program"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromScriptError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::UnrecognizedScript => None, + Self::WitnessVersion(ref e) => Some(e), + Self::WitnessProgram(ref e) => Some(e), + } + } +} + +impl From for FromScriptError { + fn from(e: witness_program::Error) -> Self { Self::WitnessProgram(e) } +} + +impl From for FromScriptError { + fn from(e: witness_version::TryFromError) -> Self { Self::WitnessVersion(e) } +} + +/// Address type is either invalid or not supported in rust-bitcoin. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UnknownAddressTypeError(pub String); + +impl fmt::Display for UnknownAddressTypeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "failed to parse {} as address type", self.0; self) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnknownAddressTypeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// Address parsing error. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ParseError { + /// Base58 legacy decoding error. + Base58(Base58Error), + /// Bech32 SegWit decoding error. + Bech32(Bech32Error), + /// Address's network differs from required one. + NetworkValidation(NetworkValidationError), +} + +impl From for ParseError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Base58(ref e) => write_err!(f, "base58 error"; e), + Self::Bech32(ref e) => write_err!(f, "bech32 error"; e), + Self::NetworkValidation(ref e) => write_err!(f, "validation error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Base58(ref e) => Some(e), + Self::Bech32(ref e) => Some(e), + Self::NetworkValidation(ref e) => Some(e), + } + } +} + +impl From for ParseError { + fn from(e: Base58Error) -> Self { Self::Base58(e) } +} + +impl From for ParseError { + fn from(e: Bech32Error) -> Self { Self::Bech32(e) } +} + +impl From for ParseError { + fn from(e: UnknownHrpError) -> Self { Self::Bech32(e.into()) } +} + +impl From for ParseError { + fn from(e: NetworkValidationError) -> Self { Self::NetworkValidation(e) } +} + +/// Unknown HRP error. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UnknownHrpError(pub String); + +impl fmt::Display for UnknownHrpError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "unknown hrp: {}", self.0) } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnknownHrpError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// Address's network differs from required one. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct NetworkValidationError { + /// Network that was required. + pub(crate) required: Network, + /// The address itself. + pub(crate) address: Address, +} + +impl fmt::Display for NetworkValidationError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "address ")?; + fmt::Display::fmt(&self.address.inner(), f)?; + write!(f, " is not valid on {}", self.required) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for NetworkValidationError {} + +/// Bech32 related error. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Bech32Error { + /// Parse SegWit Bech32 error. + ParseBech32(ParseBech32Error), + /// A witness version conversion/parsing error. + WitnessVersion(witness_version::TryFromError), + /// A witness program error. + WitnessProgram(witness_program::Error), + /// Tried to parse an unknown HRP. + UnknownHrp(UnknownHrpError), +} + +impl From for Bech32Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Bech32Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ParseBech32(ref e) => write_err!(f, "SegWit parsing error"; e), + Self::WitnessVersion(ref e) => + write_err!(f, "witness version conversion/parsing error"; e), + Self::WitnessProgram(ref e) => write_err!(f, "witness program error"; e), + Self::UnknownHrp(ref e) => write_err!(f, "unknown hrp error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Bech32Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::ParseBech32(ref e) => Some(e), + Self::WitnessVersion(ref e) => Some(e), + Self::WitnessProgram(ref e) => Some(e), + Self::UnknownHrp(ref e) => Some(e), + } + } +} + +impl From for Bech32Error { + fn from(e: witness_version::TryFromError) -> Self { Self::WitnessVersion(e) } +} + +impl From for Bech32Error { + fn from(e: witness_program::Error) -> Self { Self::WitnessProgram(e) } +} + +impl From for Bech32Error { + fn from(e: UnknownHrpError) -> Self { Self::UnknownHrp(e) } +} + +/// Bech32 parsing related error. +// This wrapper exists because we do not want to expose the `bech32` crate in our public API. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseBech32Error(pub(crate) bech32::segwit::DecodeError); + +impl From for ParseBech32Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParseBech32Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "bech32 parsing error"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseBech32Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} + +/// Base58 related error. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Base58Error { + /// Parse legacy Base58 error. + ParseBase58(base58::Error), + /// Legacy address is too long. + LegacyAddressTooLong(LegacyAddressTooLongError), + /// Invalid base58 payload data length for legacy address. + InvalidBase58PayloadLength(InvalidBase58PayloadLengthError), + /// Invalid legacy address prefix in base58 data payload. + InvalidLegacyPrefix(InvalidLegacyPrefixError), +} + +impl From for Base58Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Base58Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ParseBase58(ref e) => write_err!(f, "legacy parsing error"; e), + Self::LegacyAddressTooLong(ref e) => write_err!(f, "legacy address length error"; e), + Self::InvalidBase58PayloadLength(ref e) => + write_err!(f, "legacy payload length error"; e), + Self::InvalidLegacyPrefix(ref e) => write_err!(f, "legacy prefix error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Base58Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::ParseBase58(ref e) => Some(e), + Self::LegacyAddressTooLong(ref e) => Some(e), + Self::InvalidBase58PayloadLength(ref e) => Some(e), + Self::InvalidLegacyPrefix(ref e) => Some(e), + } + } +} + +impl From for Base58Error { + fn from(e: base58::Error) -> Self { Self::ParseBase58(e) } +} + +impl From for Base58Error { + fn from(e: LegacyAddressTooLongError) -> Self { Self::LegacyAddressTooLong(e) } +} + +impl From for Base58Error { + fn from(e: InvalidBase58PayloadLengthError) -> Self { Self::InvalidBase58PayloadLength(e) } +} + +impl From for Base58Error { + fn from(e: InvalidLegacyPrefixError) -> Self { Self::InvalidLegacyPrefix(e) } +} + +/// Decoded base58 data was an invalid length. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidBase58PayloadLengthError { + /// The base58 payload length we got after decoding address string. + pub(crate) length: usize, +} + +impl InvalidBase58PayloadLengthError { + /// Returns the invalid payload length. + pub fn invalid_base58_payload_length(&self) -> usize { self.length } +} + +impl fmt::Display for InvalidBase58PayloadLengthError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "decoded base58 data was an invalid length: {} (expected 21)", self.length) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidBase58PayloadLengthError {} + +/// Legacy base58 address was too long, max 50 characters. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LegacyAddressTooLongError { + /// The length of the legacy address. + pub(crate) length: usize, +} + +impl LegacyAddressTooLongError { + /// Returns the invalid legacy address length. + pub fn invalid_legacy_address_length(&self) -> usize { self.length } + + #[doc(hidden)] + #[deprecated = "Use invalid_legacy_address_length() instead"] + pub fn invalid_legcay_address_length(&self) -> usize { self.invalid_legacy_address_length() } +} + +impl fmt::Display for LegacyAddressTooLongError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "legacy address is too long: {} (max 50 characters)", self.length) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for LegacyAddressTooLongError {} + +/// Invalid legacy address prefix in decoded base58 data. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidLegacyPrefixError { + /// The invalid prefix byte. + pub(crate) invalid: u8, +} + +impl InvalidLegacyPrefixError { + /// Returns the invalid prefix. + pub fn invalid_legacy_address_prefix(&self) -> u8 { self.invalid } +} + +impl fmt::Display for InvalidLegacyPrefixError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid legacy address prefix in decoded base58 data {}", self.invalid) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidLegacyPrefixError {} diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs new file mode 100644 index 000000000..709d108ea --- /dev/null +++ b/bitcoin/src/address/mod.rs @@ -0,0 +1,1629 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin addresses. +//! +//! Support for segwit and legacy addresses (bech32 and base58 respectively). +//! +//! # Examples +//! +//! ### Creating a new address from a randomly-generated key pair. +//! +//! ```rust +//! #[cfg(all(feature = "rand", feature = "std"))] { +//! use bitcoin::secp256k1::rand; +//! use bitcoin::{Address, Network, PublicKey}; +//! +//! // Generate random key pair. +//! let (_sk, pk) = secp256k1::generate_keypair(&mut rand::rng()); +//! let public_key = PublicKey::new(pk); // Or `PublicKey::from(pk)`. +//! +//! // Generate a mainnet pay-to-pubkey-hash address. +//! let address = Address::p2pkh(&public_key, Network::Bitcoin); +//! } +//! ``` +//! +//! ### Using an `Address` as a struct field. +//! +//! ```rust +//! # #[cfg(feature = "serde")] { +//! # use serde::{self, Deserialize, Serialize}; +//! use bitcoin::address::{Address, NetworkValidation, NetworkValidationUnchecked}; +//! #[derive(Serialize, Deserialize)] +//! struct Foo +//! where V: NetworkValidation, +//! { +//! #[serde(bound(deserialize = "V: NetworkValidationUnchecked"))] +//! address: Address, +//! } +//! # } +//! ``` + +pub mod error; + +use core::fmt; +use core::marker::PhantomData; +use core::str::FromStr; + +use bech32::primitives::gf32::Fe32; +use bech32::primitives::hrp::Hrp; +use hashes::{hash160, HashEngine}; +use internals::array::ArrayExt; + +use crate::constants::{ + PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST, SCRIPT_ADDRESS_PREFIX_MAIN, + SCRIPT_ADDRESS_PREFIX_TEST, +}; +use crate::crypto::key::{ + CompressedPublicKey, PubkeyHash, PublicKey, TweakedPublicKey, UntweakedPublicKey, + XOnlyPublicKey, +}; +use crate::network::{Network, NetworkKind, Params}; +use crate::prelude::{String, ToOwned}; +use crate::script::witness_program::WitnessProgram; +use crate::script::witness_version::WitnessVersion; +use crate::script::{ + self, RedeemScriptSizeError, Script, ScriptExt as _, ScriptHash, ScriptHashableTag, + ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyBufExt as _, ScriptPubKeyExt as _, WScriptHash, + WitnessScript, WitnessScriptExt as _, WitnessScriptSizeError, +}; +use crate::taproot::TapNodeHash; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::error::{ + Base58Error, Bech32Error, FromScriptError, InvalidBase58PayloadLengthError, + InvalidLegacyPrefixError, LegacyAddressTooLongError, NetworkValidationError, + ParseError, UnknownAddressTypeError, UnknownHrpError, ParseBech32Error, +}; + +/// The different types of addresses. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum AddressType { + /// Pay to pubkey hash. + P2pkh, + /// Pay to script hash. + P2sh, + /// Pay to witness pubkey hash. + P2wpkh, + /// Pay to witness script hash. + P2wsh, + /// Pay to Taproot. + P2tr, + /// Pay to anchor. + P2a, +} + +impl fmt::Display for AddressType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match *self { + Self::P2pkh => "p2pkh", + Self::P2sh => "p2sh", + Self::P2wpkh => "p2wpkh", + Self::P2wsh => "p2wsh", + Self::P2tr => "p2tr", + Self::P2a => "p2a", + }) + } +} + +impl FromStr for AddressType { + type Err = UnknownAddressTypeError; + fn from_str(s: &str) -> Result { + match s { + "p2pkh" => Ok(Self::P2pkh), + "p2sh" => Ok(Self::P2sh), + "p2wpkh" => Ok(Self::P2wpkh), + "p2wsh" => Ok(Self::P2wsh), + "p2tr" => Ok(Self::P2tr), + "p2a" => Ok(Self::P2a), + _ => Err(UnknownAddressTypeError(s.to_owned())), + } + } +} + +mod sealed { + pub trait NetworkValidation {} + impl NetworkValidation for super::NetworkChecked {} + impl NetworkValidation for super::NetworkUnchecked {} + + pub trait NetworkValidationUnchecked {} + impl NetworkValidationUnchecked for super::NetworkUnchecked {} +} + +/// Marker of status of address's network validation. See section [*Parsing addresses*](Address#parsing-addresses) +/// on [`Address`] for details. +pub trait NetworkValidation: + sealed::NetworkValidation + Sync + Send + Sized + Unpin + Copy +{ + /// Indicates whether this `NetworkValidation` is `NetworkChecked` or not. + const IS_CHECKED: bool; +} + +/// Marker trait for `FromStr` and `serde::Deserialize`. +/// +/// This allows users to use `V: NetworkValidation` in conjunction with derives. Is only ever +/// implemented for `NetworkUnchecked`. +pub trait NetworkValidationUnchecked: + NetworkValidation + sealed::NetworkValidationUnchecked + Sync + Send + Sized + Unpin +{ +} + +/// Marker that address's network has been successfully validated. See section [*Parsing addresses*](Address#parsing-addresses) +/// on [`Address`] for details. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum NetworkChecked {} + +/// Marker that address's network has not yet been validated. See section [*Parsing addresses*](Address#parsing-addresses) +/// on [`Address`] for details. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum NetworkUnchecked {} + +impl NetworkValidation for NetworkChecked { + const IS_CHECKED: bool = true; +} +impl NetworkValidation for NetworkUnchecked { + const IS_CHECKED: bool = false; +} + +impl NetworkValidationUnchecked for NetworkUnchecked {} + +/// The inner representation of an address, without the network validation tag. +/// +/// This struct represents the inner representation of an address without the network validation +/// tag, which is used to ensure that addresses are used only on the appropriate network. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum AddressInner { + P2pkh { hash: PubkeyHash, network: NetworkKind }, + P2sh { hash: ScriptHash, network: NetworkKind }, + Segwit { program: WitnessProgram, hrp: KnownHrp }, +} + +/// Formats bech32 as upper case if alternate formatting is chosen (`{:#}`). +impl fmt::Display for AddressInner { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + use AddressInner::*; + match self { + P2pkh { hash, network } => { + let mut prefixed = [0; 21]; + prefixed[0] = match network { + NetworkKind::Main => PUBKEY_ADDRESS_PREFIX_MAIN, + NetworkKind::Test => PUBKEY_ADDRESS_PREFIX_TEST, + }; + prefixed[1..].copy_from_slice(hash.as_byte_array()); + base58::encode_check_to_fmt(fmt, &prefixed[..]) + } + P2sh { hash, network } => { + let mut prefixed = [0; 21]; + prefixed[0] = match network { + NetworkKind::Main => SCRIPT_ADDRESS_PREFIX_MAIN, + NetworkKind::Test => SCRIPT_ADDRESS_PREFIX_TEST, + }; + prefixed[1..].copy_from_slice(hash.as_byte_array()); + base58::encode_check_to_fmt(fmt, &prefixed[..]) + } + Segwit { program, hrp } => { + let hrp = hrp.to_hrp(); + let version = Fe32::try_from(program.version().to_num()) + .expect("version nums 0-16 are valid fe32 values"); + let program = program.program().as_ref(); + + if fmt.alternate() { + bech32::segwit::encode_upper_to_fmt_unchecked(fmt, hrp, version, program) + } else { + bech32::segwit::encode_lower_to_fmt_unchecked(fmt, hrp, version, program) + } + } + } + } +} + +/// Known bech32 human-readable parts. +/// +/// This is the human-readable part before the separator (`1`) in a bech32 encoded address e.g., +/// the "bc" in "bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5". +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum KnownHrp { + /// The main Bitcoin network. + Mainnet, + /// The test networks, testnet (testnet3), testnet4, and signet. + Testnets, + /// The regtest network. + Regtest, +} + +impl KnownHrp { + /// Constructs a new [`KnownHrp`] from [`Network`]. + fn from_network(network: Network) -> Self { + use Network::*; + + match network { + Bitcoin => Self::Mainnet, + Testnet(_) | Signet => Self::Testnets, + Regtest => Self::Regtest, + } + } + + /// Constructs a new [`KnownHrp`] from a [`bech32::Hrp`]. + fn from_hrp(hrp: Hrp) -> Result { + if hrp == bech32::hrp::BC { + Ok(Self::Mainnet) + } else if hrp.is_valid_on_testnet() || hrp.is_valid_on_signet() { + Ok(Self::Testnets) + } else if hrp == bech32::hrp::BCRT { + Ok(Self::Regtest) + } else { + Err(UnknownHrpError(hrp.to_lowercase())) + } + } + + /// Converts, infallibly a known HRP to a [`bech32::Hrp`]. + fn to_hrp(self) -> Hrp { + match self { + Self::Mainnet => bech32::hrp::BC, + Self::Testnets => bech32::hrp::TB, + Self::Regtest => bech32::hrp::BCRT, + } + } +} + +impl From for KnownHrp { + fn from(n: Network) -> Self { Self::from_network(n) } +} + +impl From for NetworkKind { + fn from(hrp: KnownHrp) -> Self { + match hrp { + KnownHrp::Mainnet => Self::Main, + KnownHrp::Testnets => Self::Test, + KnownHrp::Regtest => Self::Test, + } + } +} + +/// The data encoded by an `Address`. +/// +/// This is the data used to encumber an output that pays to this address i.e., it is the address +/// excluding the network information. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum AddressData { + /// Data encoded by a P2PKH address. + P2pkh { + /// The pubkey hash used to encumber outputs to this address. + pubkey_hash: PubkeyHash, + }, + /// Data encoded by a P2SH address. + P2sh { + /// The script hash used to encumber outputs to this address. + script_hash: ScriptHash, + }, + /// Data encoded by a SegWit address. + Segwit { + /// The witness program used to encumber outputs to this address. + witness_program: WitnessProgram, + }, +} + +internals::transparent_newtype! { + /// A Bitcoin address. + /// + /// # Parsing addresses + /// + /// When parsing string as an address, one has to pay attention to the network, on which the parsed + /// address is supposed to be valid. For the purpose of this validation, `Address` has + /// [`is_valid_for_network`](Address::is_valid_for_network) method. In order to provide more safety, + /// enforced by compiler, `Address` also contains a special marker type, which indicates whether network of the parsed + /// address has been checked. This marker type will prevent from calling certain functions unless the network + /// verification has been successfully completed. + /// + /// The result of parsing an address is `Address` suggesting that network of the parsed address + /// has not yet been verified. To perform this verification, method [`require_network`](Address::require_network) + /// can be called, providing network on which the address is supposed to be valid. If the verification succeeds, + /// `Address` is returned. + /// + /// The types `Address` and `Address` are synonymous, i.e. they can be used interchangeably. + /// + /// ```rust + /// use std::str::FromStr; + /// use bitcoin::{Address, Network}; + /// use bitcoin::address::{NetworkUnchecked, NetworkChecked}; + /// + /// // variant 1 + /// let address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap(); + /// let _address: Address = address.require_network(Network::Bitcoin).unwrap(); + /// + /// // variant 2 + /// let _address: Address = Address::from_str("32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf").unwrap() + /// .require_network(Network::Bitcoin).unwrap(); + /// + /// // variant 3 + /// let _address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse::>() + /// .unwrap().require_network(Network::Bitcoin).unwrap(); + /// ``` + /// + /// ### Formatting addresses + /// + /// To format address into its textual representation, both `Debug` (for usage in programmer-facing, + /// debugging context) and `Display` (for user-facing output) can be used, with the following caveats: + /// + /// 1. `Display` is implemented only for `Address`: + /// + /// ``` + /// # use bitcoin::address::{Address, NetworkChecked}; + /// let address: Address = "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM".parse::>() + /// .unwrap().assume_checked(); + /// assert_eq!(address.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"); + /// ``` + /// + /// ```ignore + /// # use bitcoin::address::{Address, NetworkChecked}; + /// let address: Address = "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM".parse::>() + /// .unwrap(); + /// let s = address.to_string(); // does not compile + /// ``` + /// + /// 2. `Debug` on `Address` does not produce clean address but address wrapped by + /// an indicator that its network has not been checked. This is to encourage programmer to properly + /// check the network and use `Display` in user-facing context. + /// + /// ``` + /// # use bitcoin::address::{Address, NetworkUnchecked}; + /// let address: Address = "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM".parse::>() + /// .unwrap(); + /// assert_eq!(format!("{:?}", address), "Address(132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM)"); + /// ``` + /// + /// ``` + /// # use bitcoin::address::{Address, NetworkChecked}; + /// let address: Address = "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM".parse::>() + /// .unwrap().assume_checked(); + /// assert_eq!(format!("{:?}", address), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"); + /// ``` + /// + /// # Relevant BIPs + /// + /// * [BIP-0013 - Address Format for pay-to-script-hash](https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki) + /// * [BIP-0016 - Pay to Script Hash](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki) + /// * [BIP-0141 - Segregated Witness (Consensus layer)](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) + /// * [BIP-0142 - Address Format for Segregated Witness](https://github.com/bitcoin/bips/blob/master/bip-0142.mediawiki) + /// * [BIP-0341 - Taproot: SegWit version 1 spending rules](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) + /// * [BIP-0350 - Bech32m format for v1+ witness addresses](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki) + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + // The `#[repr(transparent)]` attribute is used to guarantee the layout of the `Address` struct. It + // is an implementation detail and users should not rely on it in their code. + pub struct Address(PhantomData, AddressInner) + where + V: NetworkValidation; + + impl Address { + fn from_inner_ref(inner: &_) -> &Self; + } +} + +#[cfg(feature = "serde")] +struct DisplayUnchecked<'a, N: NetworkValidation>(&'a Address); + +#[cfg(feature = "serde")] +impl fmt::Display for DisplayUnchecked<'_, N> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0.inner(), fmt) + } +} + +#[cfg(feature = "serde")] +impl<'de, U: NetworkValidationUnchecked> serde::Deserialize<'de> for Address { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + use core::fmt::Formatter; + + struct Visitor(PhantomData); + impl serde::de::Visitor<'_> for Visitor + where + U: NetworkValidationUnchecked + NetworkValidation, + Address: FromStr, + { + type Value = Address; + + fn expecting(&self, f: &mut Formatter) -> core::fmt::Result { + f.write_str("A Bitcoin address") + } + + fn visit_str(self, v: &str) -> core::result::Result + where + E: serde::de::Error, + { + // We know that `U` is only ever `NetworkUnchecked` but the compiler does not. + let address = v.parse::>().map_err(E::custom)?; + Ok(Address::from_inner(address.to_inner())) + } + } + + deserializer.deserialize_str(Visitor(PhantomData::)) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Address { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.collect_str(&DisplayUnchecked(self)) + } +} + +/// Methods on [`Address`] that can be called on both `Address` and +/// `Address`. +impl Address { + fn from_inner(inner: AddressInner) -> Self { Self(PhantomData, inner) } + + fn to_inner(self) -> AddressInner { self.1 } + + fn inner(&self) -> &AddressInner { &self.1 } + + /// Returns a reference to the address as if it was unchecked. + pub fn as_unchecked(&self) -> &Address { + Address::from_inner_ref(self.inner()) + } + + /// Marks the network of this address as unchecked. + pub fn to_unchecked(self) -> Address { Address::from_inner(self.to_inner()) } + + /// Marks the network of this address as unchecked. + #[deprecated(since = "0.33.0", note = "use to_unchecked instead")] + pub fn into_unchecked(self) -> Address { + Address::from_inner(self.to_inner()) + } + + /// Returns the [`NetworkKind`] of this address. + pub fn network_kind(&self) -> NetworkKind { + use AddressInner::*; + match *self.inner() { + P2pkh { hash: _, ref network } => *network, + P2sh { hash: _, ref network } => *network, + Segwit { program: _, ref hrp } => NetworkKind::from(*hrp), + } + } +} + +/// Methods and functions that can be called only on `Address`. +impl Address { + /// Constructs a new pay-to-public-key-hash (P2PKH) [`Address`] from a public key. + /// + /// This is the preferred non-witness type address. + #[inline] + pub fn p2pkh(pk: impl Into, network: impl Into) -> Self { + let hash = pk.into(); + Self::from_inner(AddressInner::P2pkh { hash, network: network.into() }) + } + + /// Constructs a new pay-to-script-hash (P2SH) [`Address`] from a script. + /// + /// This address type was introduced with BIP-0016 and is the popular type to implement multi-sig + /// these days. + #[inline] + pub fn p2sh( + redeem_script: &Script, + network: impl Into, + ) -> Result { + let hash = redeem_script.script_hash()?; + Ok(Self::p2sh_from_hash(hash, network)) + } + + /// Constructs a new pay-to-script-hash (P2SH) [`Address`] from a script hash. + /// + /// # Warning + /// + /// The `hash` pre-image (redeem script) must not exceed 520 bytes in length + /// otherwise outputs created from the returned address will be un-spendable. + pub fn p2sh_from_hash(hash: ScriptHash, network: impl Into) -> Self { + Self::from_inner(AddressInner::P2sh { hash, network: network.into() }) + } + + /// Constructs a new pay-to-witness-public-key-hash (P2WPKH) [`Address`] from a public key. + /// + /// This is the native SegWit address type for an output redeemable with a single signature. + pub fn p2wpkh(pk: CompressedPublicKey, hrp: impl Into) -> Self { + let program = WitnessProgram::p2wpkh(pk); + Self::from_witness_program(program, hrp) + } + + /// Constructs a new pay-to-script-hash (P2SH) [`Address`] that embeds a + /// pay-to-witness-public-key-hash (P2WPKH). + /// + /// This is a SegWit address type that looks familiar (as p2sh) to legacy clients. + pub fn p2shwpkh(pk: CompressedPublicKey, network: impl Into) -> Self { + let builder = ScriptPubKey::builder().push_int_unchecked(0).push_slice(pk.wpubkey_hash()); + let script_hash = builder.as_script().script_hash().expect("script is less than 520 bytes"); + Self::p2sh_from_hash(script_hash, network) + } + + /// Constructs a new pay-to-witness-script-hash (P2WSH) [`Address`] from a witness script. + pub fn p2wsh( + witness_script: &WitnessScript, + hrp: impl Into, + ) -> Result { + let program = WitnessProgram::p2wsh(witness_script)?; + Ok(Self::from_witness_program(program, hrp)) + } + + /// Constructs a new pay-to-witness-script-hash (P2WSH) [`Address`] from a witness script hash. + pub fn p2wsh_from_hash(hash: WScriptHash, hrp: impl Into) -> Self { + let program = WitnessProgram::p2wsh_from_hash(hash); + Self::from_witness_program(program, hrp) + } + + /// Constructs a new pay-to-script-hash (P2SH) [`Address`] that embeds a + /// pay-to-witness-script-hash (P2WSH). + /// + /// This is a SegWit address type that looks familiar (as p2sh) to legacy clients. + pub fn p2shwsh( + witness_script: &WitnessScript, + network: impl Into, + ) -> Result { + let hash = witness_script.wscript_hash()?; + let builder = ScriptPubKey::builder().push_int_unchecked(0).push_slice(hash); + let script_hash = builder.as_script().script_hash().expect("script is less than 520 bytes"); + Ok(Self::p2sh_from_hash(script_hash, network)) + } + + /// Constructs a new pay-to-Taproot (P2TR) [`Address`] from an untweaked key. + pub fn p2tr>( + internal_key: K, + merkle_root: Option, + hrp: impl Into, + ) -> Self { + let internal_key = internal_key.into(); + let program = WitnessProgram::p2tr(internal_key, merkle_root); + Self::from_witness_program(program, hrp) + } + + /// Constructs a new pay-to-Taproot (P2TR) [`Address`] from a pre-tweaked output key. + pub fn p2tr_tweaked(output_key: TweakedPublicKey, hrp: impl Into) -> Self { + let program = WitnessProgram::p2tr_tweaked(output_key); + Self::from_witness_program(program, hrp) + } + + /// Constructs a new pay-to-anchor (P2A) [`Address`]. + pub fn p2a(hrp: impl Into) -> Self { + Self::from_witness_program(WitnessProgram::p2a(), hrp) + } + + /// Constructs a new [`Address`] from an arbitrary [`WitnessProgram`]. + /// + /// This only exists to support future witness versions. If you are doing normal mainnet things + /// then you likely do not need this constructor. + pub fn from_witness_program(program: WitnessProgram, hrp: impl Into) -> Self { + let inner = AddressInner::Segwit { program, hrp: hrp.into() }; + Self::from_inner(inner) + } + + /// Gets the address type of the [`Address`]. + /// + /// # Returns + /// + /// None if unknown, non-standard or related to the future witness version. + #[inline] + pub fn address_type(&self) -> Option { + match *self.inner() { + AddressInner::P2pkh { .. } => Some(AddressType::P2pkh), + AddressInner::P2sh { .. } => Some(AddressType::P2sh), + AddressInner::Segwit { ref program, hrp: _ } => + if program.is_p2wpkh() { + Some(AddressType::P2wpkh) + } else if program.is_p2wsh() { + Some(AddressType::P2wsh) + } else if program.is_p2tr() { + Some(AddressType::P2tr) + } else if program.is_p2a() { + Some(AddressType::P2a) + } else { + None + }, + } + } + + /// Gets the address data from this address. + pub fn to_address_data(self) -> AddressData { + use AddressData::*; + + match *self.inner() { + AddressInner::P2pkh { hash, network: _ } => P2pkh { pubkey_hash: hash }, + AddressInner::P2sh { hash, network: _ } => P2sh { script_hash: hash }, + AddressInner::Segwit { program, hrp: _ } => Segwit { witness_program: program }, + } + } + + /// Gets the pubkey hash for this address if this is a P2PKH address. + pub fn pubkey_hash(&self) -> Option { + use AddressInner::*; + + match *self.inner() { + P2pkh { ref hash, network: _ } => Some(*hash), + _ => None, + } + } + + /// Gets the script hash for this address if this is a P2SH address. + pub fn script_hash(&self) -> Option { + use AddressInner::*; + + match *self.inner() { + P2sh { ref hash, network: _ } => Some(*hash), + _ => None, + } + } + + /// Gets the witness program for this address if this is a SegWit address. + pub fn witness_program(&self) -> Option { + use AddressInner::*; + + match *self.inner() { + Segwit { ref program, hrp: _ } => Some(*program), + _ => None, + } + } + + /// Checks whether or not the address is following Bitcoin standardness rules when + /// *spending* from this address. *NOT* to be called by senders. + /// + ///
+ /// Spending Standardness + /// + /// For forward compatibility, the senders must send to any [`Address`]. Receivers + /// can use this method to check whether or not they can spend from this address. + /// + /// SegWit addresses with unassigned witness versions or non-standard program sizes are + /// considered non-standard. + ///
+ /// + pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() } + + /// Constructs a new [`Address`] from an output script (`scriptPubkey`). + pub fn from_script( + script: &ScriptPubKey, + params: impl AsRef, + ) -> Result { + let network = params.as_ref().network; + if script.is_p2pkh() { + let bytes = script.as_bytes()[3..23].try_into().expect("statically 20B long"); + let hash = PubkeyHash::from_byte_array(bytes); + Ok(Self::p2pkh(hash, network)) + } else if script.is_p2sh() { + let bytes = script.as_bytes()[2..22].try_into().expect("statically 20B long"); + let hash = ScriptHash::from_byte_array(bytes); + Ok(Self::p2sh_from_hash(hash, network)) + } else if script.is_witness_program() { + let opcode = script.first_opcode().expect("is_witness_program guarantees len > 4"); + + let version = WitnessVersion::try_from(opcode)?; + let program = WitnessProgram::new(version, &script.as_bytes()[2..])?; + Ok(Self::from_witness_program(program, network)) + } else { + Err(FromScriptError::UnrecognizedScript) + } + } + + /// Generates a script pubkey spending to this address. + pub fn script_pubkey(&self) -> ScriptPubKeyBuf { + use AddressInner::*; + match *self.inner() { + P2pkh { hash, network: _ } => ScriptPubKeyBuf::new_p2pkh(hash), + P2sh { hash, network: _ } => ScriptPubKeyBuf::new_p2sh(hash), + Segwit { ref program, hrp: _ } => { + let prog = program.program(); + let version = program.version(); + script::new_witness_program_unchecked(version, prog) + } + } + } + + /// Constructs a new URI string *bitcoin:address* optimized to be encoded in QR codes. + /// + /// If the address is bech32, the address becomes uppercase. + /// If the address is base58, the address is left mixed case. + /// + /// Quoting BIP 173 "inside QR codes uppercase SHOULD be used, as those permit the use of + /// alphanumeric mode, which is 45% more compact than the normal byte mode." + /// + /// Note however that despite BIP-0021 explicitly stating that the `bitcoin:` prefix should be + /// parsed as case-insensitive many wallets got this wrong and don't parse correctly. + /// [See compatibility table.](https://github.com/btcpayserver/btcpayserver/issues/2110) + /// + /// If you want to avoid allocation you can use alternate display instead: + /// ``` + /// # use core::fmt::Write; + /// # const ADDRESS: &str = "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4"; + /// # let address = ADDRESS.parse::>().unwrap().assume_checked(); + /// # let mut writer = String::new(); + /// # // magic trick to make error handling look better + /// # (|| -> Result<(), core::fmt::Error> { + /// + /// write!(writer, "{:#}", address)?; + /// + /// # Ok(()) + /// # })().unwrap(); + /// # assert_eq!(writer, ADDRESS); + /// ``` + pub fn to_qr_uri(self) -> String { format!("bitcoin:{:#}", self) } + + /// Returns true if the given pubkey is directly related to the address payload. + /// + /// This is determined by directly comparing the address payload with either the + /// hash of the given public key or the SegWit redeem hash generated from the + /// given key. For Taproot addresses, the supplied key is assumed to be tweaked + pub fn is_related_to_pubkey(&self, pubkey: PublicKey) -> bool { + let pubkey_hash = pubkey.pubkey_hash(); + let payload = self.payload_as_bytes(); + let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); + + (*pubkey_hash.as_byte_array() == *payload) + || (xonly_pubkey.serialize() == *payload) + || (*segwit_redeem_hash(pubkey_hash).as_byte_array() == *payload) + } + + /// Returns true if the supplied xonly public key can be used to derive the address. + /// + /// This will only work for Taproot addresses. The Public Key is + /// assumed to have already been tweaked. + pub fn is_related_to_xonly_pubkey(&self, xonly_pubkey: XOnlyPublicKey) -> bool { + xonly_pubkey.serialize() == *self.payload_as_bytes() + } + + /// Returns true if the address creates a particular script + /// This function doesn't make any allocations. + pub fn matches_script_pubkey(&self, script: &ScriptPubKey) -> bool { + use AddressInner::*; + match *self.inner() { + P2pkh { ref hash, network: _ } if script.is_p2pkh() => + &script.as_bytes()[3..23] == >::as_ref(hash), + P2sh { ref hash, network: _ } if script.is_p2sh() => + &script.as_bytes()[2..22] == >::as_ref(hash), + Segwit { ref program, hrp: _ } if script.is_witness_program() => + &script.as_bytes()[2..] == program.program().as_bytes(), + P2pkh { .. } | P2sh { .. } | Segwit { .. } => false, + } + } + + /// Returns the "payload" for this address. + /// + /// The "payload" is the useful stuff excluding serialization prefix, the exact payload is + /// dependent on the inner address: + /// + /// - For p2sh, the payload is the script hash. + /// - For p2pkh, the payload is the pubkey hash. + /// - For SegWit addresses, the payload is the witness program. + fn payload_as_bytes(&self) -> &[u8] { + use AddressInner::*; + match *self.inner() { + P2sh { ref hash, network: _ } => hash.as_ref(), + P2pkh { ref hash, network: _ } => hash.as_ref(), + Segwit { ref program, hrp: _ } => program.program().as_bytes(), + } + } +} + +/// Methods that can be called only on `Address`. +impl Address { + /// Returns a reference to the checked address. + /// + /// This function is dangerous in case the address is not a valid checked address. + pub fn assume_checked_ref(&self) -> &Address { Address::from_inner_ref(self.inner()) } + + /// Parsed addresses do not always have *one* network. The problem is that legacy testnet, + /// regtest and signet addresses use the same prefix instead of multiple different ones. When + /// parsing, such addresses are always assumed to be testnet addresses (the same is true for + /// bech32 signet addresses). So if one wants to check if an address belongs to a certain + /// network a simple comparison is not enough anymore. Instead this function can be used. + /// + /// ```rust + /// use bitcoin::{Address, Network, TestnetVersion}; + /// use bitcoin::address::NetworkUnchecked; + /// + /// let address: Address = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e".parse().unwrap(); + /// assert!(address.is_valid_for_network(Network::Testnet(TestnetVersion::V3))); + /// assert!(address.is_valid_for_network(Network::Regtest)); + /// assert!(address.is_valid_for_network(Network::Signet)); + /// + /// assert_eq!(address.is_valid_for_network(Network::Bitcoin), false); + /// + /// let address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap(); + /// assert!(address.is_valid_for_network(Network::Bitcoin)); + /// assert_eq!(address.is_valid_for_network(Network::Testnet(TestnetVersion::V4)), false); + /// ``` + pub fn is_valid_for_network(&self, n: Network) -> bool { + use AddressInner::*; + match *self.inner() { + P2pkh { hash: _, ref network } => *network == NetworkKind::from(n), + P2sh { hash: _, ref network } => *network == NetworkKind::from(n), + Segwit { program: _, ref hrp } => *hrp == KnownHrp::from_network(n), + } + } + + /// Checks whether network of this address is as required. + /// + /// For details about this mechanism, see section [*Parsing addresses*](Address#parsing-addresses) + /// on [`Address`]. + /// + /// # Errors + /// + /// This function only ever returns the [`ParseError::NetworkValidation`] variant of + /// `ParseError`. This is not how we normally implement errors in this library but + /// `require_network` is not a typical function, it is conceptually part of string parsing. + /// + /// # Examples + /// + /// ``` + /// use bitcoin::address::{NetworkChecked, NetworkUnchecked, ParseError}; + /// use bitcoin::{Address, Network}; + /// + /// const ADDR: &str = "bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs"; + /// + /// fn parse_and_validate_address(network: Network) -> Result { + /// let address = ADDR.parse::>()? + /// .require_network(network)?; + /// Ok(address) + /// } + /// + /// fn parse_and_validate_address_combinator(network: Network) -> Result { + /// let address = ADDR.parse::>() + /// .and_then(|a| a.require_network(network))?; + /// Ok(address) + /// } + /// + /// fn parse_and_validate_address_show_types(network: Network) -> Result { + /// let address: Address = ADDR.parse::>()? + /// .require_network(network)?; + /// Ok(address) + /// } + /// + /// let network = Network::Bitcoin; // Don't hard code network in applications. + /// let _ = parse_and_validate_address(network).unwrap(); + /// let _ = parse_and_validate_address_combinator(network).unwrap(); + /// let _ = parse_and_validate_address_show_types(network).unwrap(); + /// ``` + #[inline] + pub fn require_network(self, required: Network) -> Result { + if self.is_valid_for_network(required) { + Ok(self.assume_checked()) + } else { + Err(NetworkValidationError { required, address: self }.into()) + } + } + + /// Marks, without any additional checks, network of this address as checked. + /// + /// Improper use of this method may lead to loss of funds. Reader will most likely prefer + /// [`require_network`](Address::require_network) as a safe variant. + /// For details about this mechanism, see section [*Parsing addresses*](Address#parsing-addresses) + /// on [`Address`]. + #[inline] + pub fn assume_checked(self) -> Address { Address::from_inner(self.to_inner()) } + + /// Parses a bech32 Address string + pub fn from_bech32_str(s: &str) -> Result { + let (hrp, witness_version, data) = + bech32::segwit::decode(s).map_err(|e| Bech32Error::ParseBech32(ParseBech32Error(e)))?; + let version = WitnessVersion::try_from(witness_version.to_u8())?; + let program = WitnessProgram::new(version, &data) + .expect("bech32 guarantees valid program length for witness"); + + let hrp = KnownHrp::from_hrp(hrp)?; + let inner = AddressInner::Segwit { program, hrp }; + Ok(Self::from_inner(inner)) + } + + /// Parses a base58 Address string + pub fn from_base58_str(s: &str) -> Result { + if s.len() > 50 { + return Err(LegacyAddressTooLongError { length: s.len() }.into()); + } + let data = base58::decode_check(s)?; + let data: &[u8; 21] = (&*data) + .try_into() + .map_err(|_| InvalidBase58PayloadLengthError { length: data.len() })?; + + let (prefix, &data) = data.split_first(); + + let inner = match *prefix { + PUBKEY_ADDRESS_PREFIX_MAIN => { + let hash = PubkeyHash::from_byte_array(data); + AddressInner::P2pkh { hash, network: NetworkKind::Main } + } + PUBKEY_ADDRESS_PREFIX_TEST => { + let hash = PubkeyHash::from_byte_array(data); + AddressInner::P2pkh { hash, network: NetworkKind::Test } + } + SCRIPT_ADDRESS_PREFIX_MAIN => { + let hash = ScriptHash::from_byte_array(data); + AddressInner::P2sh { hash, network: NetworkKind::Main } + } + SCRIPT_ADDRESS_PREFIX_TEST => { + let hash = ScriptHash::from_byte_array(data); + AddressInner::P2sh { hash, network: NetworkKind::Test } + } + invalid => return Err(InvalidLegacyPrefixError { invalid }.into()), + }; + + Ok(Self::from_inner(inner)) + } +} + +impl From
for ScriptPubKeyBuf { + fn from(a: Address) -> Self { a.script_pubkey() } +} + +// Alternate formatting `{:#}` is used to return an uppercase version of bech32 addresses which should +// be used in QR codes, see [`Address::to_qr_uri`]. +impl fmt::Display for Address { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.inner(), fmt) } +} + +impl fmt::Debug for Address { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if V::IS_CHECKED { + fmt::Display::fmt(&self.inner(), f) + } else { + write!(f, "Address(")?; + fmt::Display::fmt(&self.inner(), f)?; + write!(f, ")") + } + } +} + +/// Address can be parsed only with `NetworkUnchecked`. +/// +/// Only SegWit bech32 addresses prefixed with `bc`, `bcrt` or `tb` and legacy base58 addresses +/// prefixed with `1`, `2`, `3`, `m` or `n` are supported. +/// +/// # Errors +/// +/// - [`ParseError::Bech32`] if the SegWit address begins with a `bc`, `bcrt` or `tb` and is not a +/// valid bech32 address. +/// +/// - [`ParseError::Base58`] if the legacy address begins with a `1`, `2`, `3`, `m` or `n` and is +/// not a valid base58 address. +/// +/// - [`UnknownHrpError`] if the address does not begin with one of the above SegWit or +/// legacy prefixes. +impl FromStr for Address { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + if ["bc1", "bcrt1", "tb1"].iter().any(|&prefix| s.to_lowercase().starts_with(prefix)) { + let address = Address::from_bech32_str(s)?; + // We know that `U` is only ever `NetworkUnchecked` but the compiler does not. + Ok(Self::from_inner(address.to_inner())) + } else if ["1", "2", "3", "m", "n"].iter().any(|&prefix| s.starts_with(prefix)) { + let address = Address::from_base58_str(s)?; + Ok(Self::from_inner(address.to_inner())) + } else { + let hrp = match s.rfind('1') { + Some(pos) => &s[..pos], + None => s, + }; + Err(UnknownHrpError(hrp.to_owned()).into()) + } + } +} + +/// Convert a byte array of a pubkey hash into a SegWit redeem hash +fn segwit_redeem_hash(pubkey_hash: PubkeyHash) -> hash160::Hash { + let mut sha_engine = hash160::Hash::engine(); + sha_engine.input(&[0, 20]); + sha_engine.input(pubkey_hash.as_ref()); + hash160::Hash::from_engine(sha_engine) +} + +#[cfg(test)] +mod tests { + use hex_lit::hex; + + use super::*; + use crate::network::Network::{Bitcoin, Testnet}; + use crate::network::{params, TestnetVersion}; + use crate::script::{RedeemScriptBuf, ScriptBufExt as _, WitnessScriptBuf}; + + fn roundtrips(addr: &Address, network: Network) { + assert_eq!( + addr.to_string().parse::>().unwrap().assume_checked(), + *addr, + "string round-trip failed for {}", + addr, + ); + assert_eq!( + Address::from_script(&addr.script_pubkey(), network) + .expect("failed to create inner address from script_pubkey"), + *addr, + "script round-trip failed for {}", + addr, + ); + + #[cfg(feature = "serde")] + { + let ser = serde_json::to_string(addr).expect("failed to serialize address"); + let back: Address = + serde_json::from_str(&ser).expect("failed to deserialize address"); + assert_eq!(back.assume_checked(), *addr, "serde round-trip failed for {}", addr) + } + } + + #[test] + fn p2pkh_address_58() { + let hash = "162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse::().unwrap(); + let addr = Address::p2pkh(hash, NetworkKind::Main); + + assert_eq!( + addr.script_pubkey(), + ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac" + ) + .unwrap() + ); + assert_eq!(&addr.to_string(), "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM"); + assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn p2pkh_from_key() { + let key = "048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183".parse::().unwrap(); + let addr = Address::p2pkh(key, NetworkKind::Main); + assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY"); + + let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f" + .parse::() + .unwrap(); + let addr = Address::p2pkh(key, NetworkKind::Test); + assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC"); + assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); + roundtrips(&addr, Testnet(TestnetVersion::V3)); + } + + #[test] + fn p2sh_address_58() { + let hash = "162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse::().unwrap(); + let addr = Address::p2sh_from_hash(hash, NetworkKind::Main); + + assert_eq!( + addr.script_pubkey(), + ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087" + ) + .unwrap(), + ); + assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"); + assert_eq!(addr.address_type(), Some(AddressType::P2sh)); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn p2sh_parse() { + let script = RedeemScriptBuf::from_hex_no_length_prefix("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap(); + let addr = Address::p2sh(&script, NetworkKind::Test).unwrap(); + assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr"); + assert_eq!(addr.address_type(), Some(AddressType::P2sh)); + roundtrips(&addr, Testnet(TestnetVersion::V3)); + } + + #[test] + fn p2sh_parse_for_large_script() { + let script = RedeemScriptBuf::from_hex_no_length_prefix("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap(); + let res = Address::p2sh(&script, NetworkKind::Test); + assert_eq!(res.unwrap_err().invalid_size(), script.len()) + } + + #[test] + fn p2wpkh() { + // stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20 + let key = "033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc" + .parse::() + .unwrap(); + let addr = Address::p2wpkh(key, KnownHrp::Mainnet); + assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw"); + assert_eq!(addr.address_type(), Some(AddressType::P2wpkh)); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn p2wsh() { + // stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667 + let script = WitnessScriptBuf::from_hex_no_length_prefix("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap(); + let addr = Address::p2wsh(&script, KnownHrp::Mainnet).expect("script is valid"); + assert_eq!( + &addr.to_string(), + "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej" + ); + assert_eq!(addr.address_type(), Some(AddressType::P2wsh)); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn p2shwpkh() { + // stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01 + let key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766" + .parse::() + .unwrap(); + let addr = Address::p2shwpkh(key, NetworkKind::Main); + assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE"); + assert_eq!(addr.address_type(), Some(AddressType::P2sh)); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn p2shwsh() { + // stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9 + let script = WitnessScriptBuf::from_hex_no_length_prefix("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap(); + let addr = Address::p2shwsh(&script, NetworkKind::Main).expect("script is valid"); + assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr"); + assert_eq!(addr.address_type(), Some(AddressType::P2sh)); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn non_existent_segwit_version() { + // 40-byte program + let program = hex!( + "654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4" + ); + let program = WitnessProgram::new(WitnessVersion::V13, &program).expect("valid program"); + + let addr = Address::from_witness_program(program, KnownHrp::Mainnet); + roundtrips(&addr, Bitcoin); + } + + #[test] + fn address_debug() { + // This is not really testing output of Debug but the ability and proper functioning + // of Debug derivation on structs generic in NetworkValidation. + #[derive(Debug)] + #[allow(unused)] + struct Test { + address: Address, + } + + let addr_str = "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"; + let unchecked = addr_str.parse::>().unwrap(); + + assert_eq!( + format!("{:?}", Test { address: unchecked }), + format!("Test {{ address: Address({}) }}", addr_str) + ); + + assert_eq!( + format!("{:?}", Test { address: unchecked.assume_checked() }), + format!("Test {{ address: {} }}", addr_str) + ); + } + + #[test] + fn address_type() { + let addresses = [ + ("1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY", Some(AddressType::P2pkh)), + ("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k", Some(AddressType::P2sh)), + ("bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw", Some(AddressType::P2wpkh)), + ( + "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", + Some(AddressType::P2wsh), + ), + ( + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", + Some(AddressType::P2tr), + ), + // Related to future extensions, addresses are valid but have no type + // SegWit v1 and len != 32 + ("bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y", None), + // SegWit v2 + ("bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs", None), + ]; + for (address, expected_type) in &addresses { + let addr = address + .parse::>() + .unwrap() + .require_network(Network::Bitcoin) + .expect("mainnet"); + assert_eq!(&addr.address_type(), expected_type); + } + } + + #[test] + #[cfg(feature = "serde")] + fn json_serialize() { + use serde_json; + + let addr = + "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM".parse::>().unwrap().assume_checked(); + let json = serde_json::to_value(addr).unwrap(); + assert_eq!( + json, + serde_json::Value::String("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM".to_owned()) + ); + let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); + assert_eq!(addr.to_string(), into.to_string()); + assert_eq!( + into.script_pubkey(), + ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac" + ) + .unwrap() + ); + + let addr = + "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k".parse::>().unwrap().assume_checked(); + let json = serde_json::to_value(addr).unwrap(); + assert_eq!( + json, + serde_json::Value::String("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k".to_owned()) + ); + let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); + assert_eq!(addr.to_string(), into.to_string()); + assert_eq!( + into.script_pubkey(), + ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087" + ) + .unwrap() + ); + + let addr: Address = + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7" + .parse::>() + .unwrap(); + let json = serde_json::to_value(addr).unwrap(); + assert_eq!( + json, + serde_json::Value::String( + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7".to_owned() + ) + ); + + let addr = "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7" + .parse::>() + .unwrap() + .assume_checked(); + let json = serde_json::to_value(addr).unwrap(); + assert_eq!( + json, + serde_json::Value::String( + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7".to_owned() + ) + ); + let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); + assert_eq!(addr.to_string(), into.to_string()); + assert_eq!( + into.script_pubkey(), + ScriptPubKeyBuf::from_hex_no_length_prefix( + "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262" + ) + .unwrap() + ); + + let addr = "bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl" + .parse::>() + .unwrap() + .assume_checked(); + let json = serde_json::to_value(addr).unwrap(); + assert_eq!( + json, + serde_json::Value::String("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl".to_owned()) + ); + let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); + assert_eq!(addr.to_string(), into.to_string()); + assert_eq!( + into.script_pubkey(), + ScriptPubKeyBuf::from_hex_no_length_prefix( + "001454d26dddb59c7073c6a197946ea1841951fa7a74" + ) + .unwrap() + ); + } + + #[test] + fn qr_string() { + for el in + ["132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"].iter() + { + let addr = el + .parse::>() + .unwrap() + .require_network(Network::Bitcoin) + .expect("mainnet"); + assert_eq!(addr.to_qr_uri(), format!("bitcoin:{}", el)); + } + + for el in [ + "bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl", + "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", + ] + .iter() + { + let addr = el.parse::>().unwrap().assume_checked(); + assert_eq!(addr.to_qr_uri(), format!("bitcoin:{}", el.to_ascii_uppercase())); + } + } + + #[test] + fn p2tr_from_untweaked() { + //Test case from BIP-086 + let internal_key = "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115" + .parse::() + .unwrap(); + let address = Address::p2tr(internal_key, None, KnownHrp::Mainnet); + assert_eq!( + address.to_string(), + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr" + ); + assert_eq!(address.address_type(), Some(AddressType::P2tr)); + roundtrips(&address, Bitcoin); + } + + #[test] + fn is_related_to_pubkey_p2wpkh() { + let address_string = "bc1qhvd6suvqzjcu9pxjhrwhtrlj85ny3n2mqql5w4"; + let address = address_string + .parse::>() + .expect("address") + .require_network(Network::Bitcoin) + .expect("mainnet"); + + let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; + let pubkey = pubkey_string.parse::().expect("pubkey"); + + let result = address.is_related_to_pubkey(pubkey); + assert!(result); + + let unused_pubkey = "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c" + .parse::() + .expect("pubkey"); + assert!(!address.is_related_to_pubkey(unused_pubkey)) + } + + #[test] + fn is_related_to_pubkey_p2shwpkh() { + let address_string = "3EZQk4F8GURH5sqVMLTFisD17yNeKa7Dfs"; + let address = address_string + .parse::>() + .expect("address") + .require_network(Network::Bitcoin) + .expect("mainnet"); + + let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; + let pubkey = pubkey_string.parse::().expect("pubkey"); + + let result = address.is_related_to_pubkey(pubkey); + assert!(result); + + let unused_pubkey = "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c" + .parse::() + .expect("pubkey"); + assert!(!address.is_related_to_pubkey(unused_pubkey)) + } + + #[test] + fn is_related_to_pubkey_p2pkh() { + let address_string = "1J4LVanjHMu3JkXbVrahNuQCTGCRRgfWWx"; + let address = address_string + .parse::>() + .expect("address") + .require_network(Network::Bitcoin) + .expect("mainnet"); + + let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; + let pubkey = pubkey_string.parse::().expect("pubkey"); + + let result = address.is_related_to_pubkey(pubkey); + assert!(result); + + let unused_pubkey = "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c" + .parse::() + .expect("pubkey"); + assert!(!address.is_related_to_pubkey(unused_pubkey)) + } + + #[test] + fn is_related_to_pubkey_p2pkh_uncompressed_key() { + let address_string = "msvS7KzhReCDpQEJaV2hmGNvuQqVUDuC6p"; + let address = address_string + .parse::>() + .expect("address") + .require_network(Network::Testnet(TestnetVersion::V3)) + .expect("testnet"); + + let pubkey_string = "04e96e22004e3db93530de27ccddfdf1463975d2138ac018fc3e7ba1a2e5e0aad8e424d0b55e2436eb1d0dcd5cb2b8bcc6d53412c22f358de57803a6a655fbbd04"; + let pubkey = pubkey_string.parse::().expect("pubkey"); + + let result = address.is_related_to_pubkey(pubkey); + assert!(result); + + let unused_pubkey = "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c" + .parse::() + .expect("pubkey"); + assert!(!address.is_related_to_pubkey(unused_pubkey)) + } + + #[test] + fn is_related_to_pubkey_p2tr() { + let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; + let pubkey = pubkey_string.parse::().expect("pubkey"); + let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); + let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(xonly_pubkey); + let address = Address::p2tr_tweaked(tweaked_pubkey, KnownHrp::Mainnet); + + assert_eq!( + address, + "bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e" + .parse::>() + .expect("address") + .require_network(Network::Bitcoin) + .expect("mainnet") + ); + + let result = address.is_related_to_pubkey(pubkey); + assert!(result); + + let unused_pubkey = "02ba604e6ad9d3864eda8dc41c62668514ef7d5417d3b6db46e45cc4533bff001c" + .parse::() + .expect("pubkey"); + assert!(!address.is_related_to_pubkey(unused_pubkey)); + } + + #[test] + fn is_related_to_xonly_pubkey() { + let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; + let pubkey = pubkey_string.parse::().expect("pubkey"); + let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); + let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(xonly_pubkey); + let address = Address::p2tr_tweaked(tweaked_pubkey, KnownHrp::Mainnet); + + assert_eq!( + address, + "bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e" + .parse::>() + .expect("address") + .require_network(Network::Bitcoin) + .expect("mainnet") + ); + + let result = address.is_related_to_xonly_pubkey(xonly_pubkey); + assert!(result); + } + + #[test] + fn fail_address_from_script() { + use crate::witness_program; + + let bad_p2wpkh = ScriptPubKeyBuf::from_hex_no_length_prefix( + "15000014dbc5b0a8f9d4353b4b54c3db48846bb15abfec", + ) + .unwrap(); + let bad_p2wsh = ScriptPubKeyBuf::from_hex_no_length_prefix( + "00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623", + ) + .unwrap(); + let invalid_segwitv0_script = + ScriptPubKeyBuf::from_hex_no_length_prefix("001161458e330389cd0437ee9fe3641d70cc18") + .unwrap(); + let expected = Err(FromScriptError::UnrecognizedScript); + + assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected); + assert_eq!(Address::from_script(&bad_p2wsh, Network::Bitcoin), expected); + assert_eq!( + Address::from_script(&invalid_segwitv0_script, ¶ms::MAINNET), + Err(FromScriptError::WitnessProgram(witness_program::Error::InvalidSegwitV0Length(17))) + ); + } + + #[test] + fn valid_address_parses_correctly() { + let addr = "p2tr".parse::().expect("false negative while parsing address"); + assert_eq!(addr, AddressType::P2tr); + } + + #[test] + fn invalid_address_parses_error() { + let got = "invalid".parse::(); + let want = Err(UnknownAddressTypeError("invalid".to_string())); + assert_eq!(got, want); + } + + #[test] + fn matches_script_pubkey() { + let addresses = [ + "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY", + "1J4LVanjHMu3JkXbVrahNuQCTGCRRgfWWx", + "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k", + "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE", + "bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs", + "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw", + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", + "bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e", + ]; + for addr in &addresses { + let addr = + addr.parse::>().unwrap().require_network(Network::Bitcoin).unwrap(); + for another in &addresses { + let another = another + .parse::>() + .unwrap() + .require_network(Network::Bitcoin) + .unwrap(); + assert_eq!(addr.matches_script_pubkey(&another.script_pubkey()), addr == another); + } + } + } + + #[test] + #[cfg(feature = "serde")] + fn serde_address_usage_in_struct() { + use serde::{self, Deserialize, Serialize}; + + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] + struct Foo + where + V: NetworkValidation, + { + #[serde(bound(deserialize = "V: NetworkValidationUnchecked"))] + address: Address, + } + + let addr_str = "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"; + let unchecked = addr_str.parse::>().unwrap(); + + // Serialize with an unchecked address. + let foo_unchecked = Foo { address: unchecked }; + let ser = serde_json::to_string(&foo_unchecked).expect("failed to serialize"); + let roundtrip: Foo = + serde_json::from_str(&ser).expect("failed to deserialize"); + assert_eq!(roundtrip, foo_unchecked); + + // Serialize with a checked address. + let foo_checked = Foo { address: unchecked.assume_checked() }; + let ser = serde_json::to_string(&foo_checked).expect("failed to serialize"); + let roundtrip: Foo = + serde_json::from_str(&ser).expect("failed to deserialize"); + assert_eq!(&roundtrip.address, foo_checked.address.as_unchecked()); + assert_eq!(roundtrip, foo_unchecked); + } + + #[test] + fn pay_to_anchor_address_regtest() { + // Verify that P2A uses the expected address for regtest. + // This test-vector is borrowed from the bitcoin source code. + let address_str = "bcrt1pfeesnyr2tx"; + + let script = ScriptPubKeyBuf::new_p2a(); + let address_unchecked = address_str.parse().unwrap(); + let address = Address::from_script(&script, Network::Regtest).unwrap(); + assert_eq!(address.as_unchecked(), &address_unchecked); + assert_eq!(address.to_string(), address_str); + + // Verify that the address is considered standard + // and that the output type is P2A. + assert!(address.is_spend_standard()); + assert_eq!(address.address_type(), Some(AddressType::P2a)); + } + + #[test] + fn base58_invalid_payload_length_reports_decoded_size() { + use crate::constants::PUBKEY_ADDRESS_PREFIX_MAIN; + + let mut payload = [0u8; 22]; // Invalid: should be 21 + payload[0] = PUBKEY_ADDRESS_PREFIX_MAIN; + let encoded = base58::encode_check(&payload); + + let err = Address::::from_base58_str(&encoded).unwrap_err(); + match err { + Base58Error::InvalidBase58PayloadLength(inner) => { + assert_eq!(inner.invalid_base58_payload_length(), 22); // Payload size + assert_ne!(inner.invalid_base58_payload_length(), encoded.len()); // Not string size + } + other => panic!("unexpected error: {other:?}"), + } + } +} diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs new file mode 100644 index 000000000..637b50e00 --- /dev/null +++ b/bitcoin/src/bip158.rs @@ -0,0 +1,718 @@ +// SPDX-License-Identifier: CC0-1.0 + +// This module was largely copied from https://github.com/rust-bitcoin/murmel/blob/master/src/blockfilter.rs +// on 11. June 2019 which is licensed under Apache, that file specifically +// was written entirely by Tamas Blummer, who is re-licensing its contents here as CC0. + +//! BIP 158 Compact Block Filters for Light Clients. +//! +//! This module implements a structure for compact filters on block data, for +//! use in the BIP 157 light client protocol. The filter construction proposed +//! is an alternative to Bloom filters, as used in BIP 37, that minimizes filter +//! size by using Golomb-Rice coding for compression. +//! +//! # Relevant BIPS +//! +//! * [BIP-0157 - Client Side Block Filtering](https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki) +//! * [BIP-0158 - Compact Block Filters for Light Clients](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki) +//! +//! # Examples +//! +//! ```ignore +//! fn get_script_for_coin(coin: &OutPoint) -> Result { +//! // get utxo ... +//! } +//! +//! // create a block filter for a block (server side) +//! let filter = BlockFilter::new_script_filter(&block, get_script_for_coin)?; +//! +//! // or create a filter from known raw data +//! let filter = BlockFilter::new(content); +//! +//! // read and evaluate a filter +//! +//! let query: Iterator = // .. some scripts you care about +//! if filter.match_any(&block_hash, &mut query.map(|s| s.as_bytes())) { +//! // get this block +//! } +//! ``` + +use core::cmp::{self, Ordering}; +use core::convert::Infallible; +use core::fmt; + +use hashes::{sha256d, siphash24}; +use internals::array::ArrayExt as _; +use internals::{write_err, ToU64 as _}; +use io::{BufRead, Write}; + +use crate::block::{Block, BlockHash, Checked}; +use crate::consensus::{ReadExt, WriteExt}; +use crate::prelude::{BTreeSet, Borrow, Vec}; +use crate::script::{ScriptPubKey, ScriptPubKeyExt as _}; +use crate::transaction::OutPoint; + +/// Golomb encoding parameter as in BIP-0158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845 +const P: u8 = 19; +const M: u64 = 784931; + +/// Errors for blockfilter. +#[derive(Debug)] +#[non_exhaustive] +pub enum Error { + /// Missing UTXO, cannot calculate script filter. + UtxoMissing(OutPoint), + /// I/O error reading or writing binary serialization of the filter. + Io(io::Error), +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match self { + Self::UtxoMissing(ref coin) => write!(f, "unresolved UTXO {}", coin), + Self::Io(ref e) => write_err!(f, "I/O error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::UtxoMissing(_) => None, + Self::Io(ref e) => Some(e), + } + } +} + +impl From for Error { + fn from(io: io::Error) -> Self { Self::Io(io) } +} + +/// A block filter, as described by BIP 158. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BlockFilter { + /// Golomb encoded filter + pub content: Vec, +} + + +impl BlockFilter { + /// Constructs a new filter from pre-computed data. + pub fn new(content: &[u8]) -> Self { Self { content: content.to_vec() } } + + /// Computes a SCRIPT_FILTER that contains spent and output scripts. + pub fn new_script_filter( + block: &Block, + script_for_coin: M, + ) -> Result + where + M: Fn(&OutPoint) -> Result, + S: Borrow, + { + let mut out = Vec::new(); + let mut writer = BlockFilterWriter::new(&mut out, block); + + writer.add_output_scripts(); + writer.add_input_scripts(script_for_coin)?; + writer.finish()?; + + Ok(Self { content: out }) + } + + /// Computes the canonical hash for the given filter. + pub fn filter_hash(&self) -> sha256d::Hash { + sha256d::Hash::hash(&self.content) + } + + /// Returns true if any query matches against this [`BlockFilter`]. + pub fn match_any(&self, block_hash: BlockHash, query: I) -> Result + where + I: Iterator, + I::Item: Borrow<[u8]>, + { + let filter_reader = BlockFilterReader::new(block_hash); + filter_reader.match_any(&mut self.content.as_slice(), query) + } + + /// Returns true if all queries match against this [`BlockFilter`]. + pub fn match_all(&self, block_hash: BlockHash, query: I) -> Result + where + I: Iterator, + I::Item: Borrow<[u8]>, + { + let filter_reader = BlockFilterReader::new(block_hash); + filter_reader.match_all(&mut self.content.as_slice(), query) + } +} + +/// Compiles and writes a block filter. +pub struct BlockFilterWriter<'a, W> { + block: &'a Block, + writer: GcsFilterWriter<'a, W>, +} + +impl<'a, W: Write> BlockFilterWriter<'a, W> { + /// Constructs a new [`BlockFilterWriter`] from `block`. + pub fn new(writer: &'a mut W, block: &'a Block) -> Self { + let block_hash_as_int = block.block_hash().to_byte_array(); + let k0 = u64::from_le_bytes(*block_hash_as_int.sub_array::<0, 8>()); + let k1 = u64::from_le_bytes(*block_hash_as_int.sub_array::<8, 8>()); + let writer = GcsFilterWriter::new(writer, k0, k1, M, P); + BlockFilterWriter { block, writer } + } + + /// Adds output scripts of the block to filter (excluding OP_RETURN scripts). + pub fn add_output_scripts(&mut self) { + for transaction in self.block.transactions() { + for output in &transaction.outputs { + if !output.script_pubkey.is_op_return() { + self.add_element(output.script_pubkey.as_bytes()); + } + } + } + } + + /// Adds consumed output scripts of a block to filter. + pub fn add_input_scripts(&mut self, script_for_coin: M) -> Result<(), Error> + where + M: Fn(&OutPoint) -> Result, + S: Borrow, + { + for script in self + .block + .transactions() + .iter() + .skip(1) // skip coinbase + .flat_map(|t| t.inputs.iter().map(|i| &i.previous_output)) + .map(script_for_coin) + { + match script { + Ok(script) => self.add_element(script.borrow().as_bytes()), + Err(e) => return Err(e), + } + } + Ok(()) + } + + /// Adds an arbitrary element to filter. + pub fn add_element(&mut self, data: &[u8]) { self.writer.add_element(data); } + + /// Writes the block filter. + pub fn finish(&mut self) -> Result { self.writer.finish() } +} + +/// Reads and interprets a block filter. +pub struct BlockFilterReader { + reader: GcsFilterReader, +} + +impl BlockFilterReader { + /// Constructs a new [`BlockFilterReader`] from `block_hash`. + pub fn new(block_hash: BlockHash) -> Self { + let block_hash_as_int = block_hash.to_byte_array(); + let k0 = u64::from_le_bytes(*block_hash_as_int.sub_array::<0, 8>()); + let k1 = u64::from_le_bytes(*block_hash_as_int.sub_array::<8, 8>()); + Self { reader: GcsFilterReader::new(k0, k1, M, P) } + } + + /// Returns true if any query matches against this [`BlockFilterReader`]. + pub fn match_any(&self, reader: &mut R, query: I) -> Result + where + I: Iterator, + I::Item: Borrow<[u8]>, + R: BufRead + ?Sized, + { + self.reader.match_any(reader, query) + } + + /// Returns true if all queries match against this [`BlockFilterReader`]. + pub fn match_all(&self, reader: &mut R, query: I) -> Result + where + I: Iterator, + I::Item: Borrow<[u8]>, + R: BufRead + ?Sized, + { + self.reader.match_all(reader, query) + } +} + +/// Golomb-Rice encoded filter reader. +pub struct GcsFilterReader { + filter: GcsFilter, + m: u64, +} + +impl GcsFilterReader { + /// Constructs a new [`GcsFilterReader`] with specific seed to siphash. + pub fn new(k0: u64, k1: u64, m: u64, p: u8) -> Self { + Self { filter: GcsFilter::new(k0, k1, p), m } + } + + /// Returns true if any query matches against this [`GcsFilterReader`]. + pub fn match_any(&self, reader: &mut R, query: I) -> Result + where + I: Iterator, + I::Item: Borrow<[u8]>, + R: BufRead + ?Sized, + { + let n_elements = reader.read_compact_size().unwrap_or(0); + // map hashes to [0, n_elements << grp] + let nm = n_elements * self.m; + let mut mapped = + query.map(|e| map_to_range(self.filter.hash(e.borrow()), nm)).collect::>(); + // sort + mapped.sort_unstable(); + if mapped.is_empty() { + return Ok(false); + } + if n_elements == 0 { + return Ok(false); + } + + // find first match in two sorted arrays in one read pass + let mut reader = BitStreamReader::new(reader); + let mut data = self.filter.golomb_rice_decode(&mut reader)?; + let mut remaining = n_elements - 1; + for p in mapped { + loop { + match data.cmp(&p) { + Ordering::Equal => return Ok(true), + Ordering::Less => + if remaining > 0 { + data += self.filter.golomb_rice_decode(&mut reader)?; + remaining -= 1; + } else { + return Ok(false); + }, + Ordering::Greater => break, + } + } + } + Ok(false) + } + + /// Returns true if all queries match against this [`GcsFilterReader`]. + pub fn match_all(&self, reader: &mut R, query: I) -> Result + where + I: Iterator, + I::Item: Borrow<[u8]>, + R: BufRead + ?Sized, + { + let n_elements = reader.read_compact_size().unwrap_or(0); + // map hashes to [0, n_elements << grp] + let nm = n_elements * self.m; + let mut mapped = + query.map(|e| map_to_range(self.filter.hash(e.borrow()), nm)).collect::>(); + // sort + mapped.sort_unstable(); + mapped.dedup(); + if mapped.is_empty() { + return Ok(true); + } + if n_elements == 0 { + return Ok(false); + } + + // figure if all mapped are there in one read pass + let mut reader = BitStreamReader::new(reader); + let mut data = self.filter.golomb_rice_decode(&mut reader)?; + let mut remaining = n_elements - 1; + for p in mapped { + loop { + match data.cmp(&p) { + Ordering::Equal => break, + Ordering::Less => + if remaining > 0 { + data += self.filter.golomb_rice_decode(&mut reader)?; + remaining -= 1; + } else { + return Ok(false); + }, + Ordering::Greater => return Ok(false), + } + } + } + Ok(true) + } +} + +/// Fast reduction of hash to [0, nm) range. +fn map_to_range(hash: u64, nm: u64) -> u64 { ((u128::from(hash) * u128::from(nm)) >> 64) as u64 } + +/// Golomb-Rice encoded filter writer. +pub struct GcsFilterWriter<'a, W> { + filter: GcsFilter, + writer: &'a mut W, + elements: BTreeSet>, + m: u64, +} + +impl<'a, W: Write> GcsFilterWriter<'a, W> { + /// Constructs a new [`GcsFilterWriter`] wrapping a generic writer, with specific seed to siphash. + pub fn new(writer: &'a mut W, k0: u64, k1: u64, m: u64, p: u8) -> Self { + GcsFilterWriter { filter: GcsFilter::new(k0, k1, p), writer, elements: BTreeSet::new(), m } + } + + /// Adds data to the filter. + pub fn add_element(&mut self, element: &[u8]) { + if !element.is_empty() { + self.elements.insert(element.to_vec()); + } + } + + /// Writes the filter to the wrapped writer. + pub fn finish(&mut self) -> Result { + let nm = self.elements.len().to_u64() * self.m; + + // map hashes to [0, n_elements * M) + let mut mapped: Vec<_> = self + .elements + .iter() + .map(|e| map_to_range(self.filter.hash(e.as_slice()), nm)) + .collect(); + mapped.sort_unstable(); + + // write number of elements as varint + let mut wrote = self.writer.emit_compact_size(mapped.len())?; + + // write out deltas of sorted values into a Golomb-Rice coded bit stream + let mut writer = BitStreamWriter::new(self.writer); + let mut last = 0; + for data in mapped { + wrote += self.filter.golomb_rice_encode(&mut writer, data - last)?; + last = data; + } + wrote += writer.flush()?; + Ok(wrote) + } +} + +/// Golomb Coded Set Filter. +struct GcsFilter { + k0: u64, // sip hash key + k1: u64, // sip hash key + p: u8, +} + +impl GcsFilter { + /// Constructs a new [`GcsFilter`]. + fn new(k0: u64, k1: u64, p: u8) -> Self { Self { k0, k1, p } } + + /// Golomb-Rice encodes a number `n` to a bit stream (parameter 2^k). + fn golomb_rice_encode( + &self, + writer: &mut BitStreamWriter<'_, W>, + n: u64, + ) -> Result + where + W: Write, + { + let mut wrote = 0; + let mut q = n >> self.p; + while q > 0 { + let nbits = cmp::min(q, 64) as u8; // cast ok, 64 fits into a `u8` + wrote += writer.write(!0u64, nbits)?; + q -= u64::from(nbits); + } + wrote += writer.write(0, 1)?; + wrote += writer.write(n, self.p)?; + Ok(wrote) + } + + /// Golomb-Rice decodes a number from a bit stream (parameter 2^k). + fn golomb_rice_decode(&self, reader: &mut BitStreamReader) -> Result + where + R: BufRead + ?Sized, + { + let mut q = 0u64; + while reader.read(1)? == 1 { + q += 1; + } + let r = reader.read(self.p)?; + Ok((q << self.p) + r) + } + + /// Hashes an arbitrary slice with siphash using parameters of this filter. + fn hash(&self, element: &[u8]) -> u64 { + siphash24::Hash::hash_to_u64_with_keys(self.k0, self.k1, element) + } +} + +/// Bitwise stream reader. +pub struct BitStreamReader<'a, R: ?Sized> { + buffer: [u8; 1], + offset: u8, + reader: &'a mut R, +} + +impl<'a, R: BufRead + ?Sized> BitStreamReader<'a, R> { + /// Constructs a new [`BitStreamReader`] that reads bitwise from a given `reader`. + pub fn new(reader: &'a mut R) -> Self { + BitStreamReader { buffer: [0u8], reader, offset: 8 } + } + + /// Reads nbit bits, returning the bits in a `u64` starting with the rightmost bit. + /// + /// # Examples + /// + /// ``` + /// # use bitcoin::bip158::BitStreamReader; + /// # let data = [0xff]; + /// # let mut input = data.as_slice(); + /// let mut reader = BitStreamReader::new(&mut input); // input contains all 1's + /// let res = reader.read(1).expect("read failed"); + /// assert_eq!(res, 1_u64); + /// ``` + pub fn read(&mut self, mut nbits: u8) -> Result { + if nbits > 64 { + return Err(io::Error::new( + io::ErrorKind::Other, + "can not read more than 64 bits at once", + )); + } + let mut data = 0u64; + while nbits > 0 { + if self.offset == 8 { + self.reader.read_exact(&mut self.buffer)?; + self.offset = 0; + } + let bits = cmp::min(8 - self.offset, nbits); + data <<= bits; + data |= ((self.buffer[0] << self.offset) >> (8 - bits)) as u64; + self.offset += bits; + nbits -= bits; + } + Ok(data) + } +} + +/// Bitwise stream writer. +pub struct BitStreamWriter<'a, W> { + buffer: [u8; 1], + offset: u8, + writer: &'a mut W, +} + +impl<'a, W: Write> BitStreamWriter<'a, W> { + /// Constructs a new [`BitStreamWriter`] that writes bitwise to a given `writer`. + pub fn new(writer: &'a mut W) -> Self { + BitStreamWriter { buffer: [0u8], writer, offset: 0 } + } + + /// Writes nbits bits from data. + pub fn write(&mut self, data: u64, mut nbits: u8) -> Result { + if nbits > 64 { + return Err(io::Error::new( + io::ErrorKind::Other, + "can not write more than 64 bits at once", + )); + } + let mut wrote = 0; + while nbits > 0 { + let bits = cmp::min(8 - self.offset, nbits); + self.buffer[0] |= ((data << (64 - nbits)) >> (64 - 8 + self.offset)) as u8; + self.offset += bits; + nbits -= bits; + if self.offset == 8 { + wrote += self.flush()?; + } + } + Ok(wrote) + } + + /// flush bits not yet written. + pub fn flush(&mut self) -> Result { + if self.offset > 0 { + self.writer.write_all(&self.buffer)?; + self.buffer[0] = 0u8; + self.offset = 0; + Ok(1) + } else { + Ok(0) + } + } +} + + +#[cfg(test)] +mod test { + use std::collections::HashMap; + + use hex_lit::hex; + use serde_json::Value; + + use super::*; + use crate::consensus::encode::deserialize; + use crate::ScriptPubKeyBuf; + + #[test] + fn blockfilters() { + let hex = |b| as hex::FromHex>::from_hex(b).unwrap(); + + // test vectors from: https://github.com/jimpo/bitcoin/blob/c7efb652f3543b001b4dd22186a354605b14f47e/src/test/data/blockfilters.json + let data = include_str!("../tests/data/blockfilters.json"); + + let testdata = serde_json::from_str::(data).unwrap().as_array().unwrap().clone(); + for t in testdata.iter().skip(1) { + let block_hash = t.get(1).unwrap().as_str().unwrap().parse::().unwrap(); + let block: Block = deserialize(&hex(t.get(2).unwrap().as_str().unwrap())).unwrap(); + let block = block.assume_checked(None); + assert_eq!(block.block_hash(), block_hash); + let scripts = t.get(3).unwrap().as_array().unwrap(); + let filter_content = hex(t.get(5).unwrap().as_str().unwrap()); + + let mut txmap = HashMap::new(); + let mut si = scripts.iter(); + for tx in block.transactions().iter().skip(1) { + for input in tx.inputs.iter() { + txmap.insert( + input.previous_output, + ScriptPubKeyBuf::from(hex(si.next().unwrap().as_str().unwrap())), + ); + } + } + + let filter = BlockFilter::new_script_filter(&block, |o| { + if let Some(s) = txmap.get(o) { + Ok(s.clone()) + } else { + Err(Error::UtxoMissing(*o)) + } + }) + .unwrap(); + + let test_filter = BlockFilter::new(filter_content.as_slice()); + + assert_eq!(test_filter.content, filter.content); + + let block_hash = &block.block_hash(); + assert!(filter + .match_all( + *block_hash, + &mut txmap.iter().filter_map(|(_, s)| if !s.is_empty() { + Some(s.as_bytes()) + } else { + None + }) + ) + .unwrap()); + + for script in txmap.values() { + let query = [script]; + if !script.is_empty() { + assert!(filter + .match_any(*block_hash, &mut query.iter().map(|s| s.as_bytes())) + .unwrap()); + } + } + } + } + + #[test] + fn filter() { + let mut patterns = BTreeSet::new(); + + patterns.insert(hex!("000000")); + patterns.insert(hex!("111111")); + patterns.insert(hex!("222222")); + patterns.insert(hex!("333333")); + patterns.insert(hex!("444444")); + patterns.insert(hex!("555555")); + patterns.insert(hex!("666666")); + patterns.insert(hex!("777777")); + patterns.insert(hex!("888888")); + patterns.insert(hex!("999999")); + patterns.insert(hex!("aaaaaa")); + patterns.insert(hex!("bbbbbb")); + patterns.insert(hex!("cccccc")); + patterns.insert(hex!("dddddd")); + patterns.insert(hex!("eeeeee")); + patterns.insert(hex!("ffffff")); + + let mut out = Vec::new(); + { + let mut writer = GcsFilterWriter::new(&mut out, 0, 0, M, P); + for p in &patterns { + writer.add_element(p.as_slice()); + } + writer.finish().unwrap(); + } + + let bytes = out; + + { + let query = [hex!("abcdef"), hex!("eeeeee")]; + let reader = GcsFilterReader::new(0, 0, M, P); + assert!(reader + .match_any(&mut bytes.as_slice(), &mut query.iter().map(|v| v.as_slice())) + .unwrap()); + } + { + let query = [hex!("abcdef"), hex!("123456")]; + let reader = GcsFilterReader::new(0, 0, M, P); + assert!(!reader + .match_any(&mut bytes.as_slice(), &mut query.iter().map(|v| v.as_slice())) + .unwrap()); + } + { + let reader = GcsFilterReader::new(0, 0, M, P); + let mut query = Vec::new(); + for p in &patterns { + query.push(p); + } + assert!(reader + .match_all(&mut bytes.as_slice(), &mut query.iter().map(|v| v.as_slice())) + .unwrap()); + } + { + let reader = GcsFilterReader::new(0, 0, M, P); + let mut query = Vec::new(); + for p in &patterns { + query.push(p); + } + query.push(&hex!("abcdef")); + assert!(!reader + .match_all(&mut bytes.as_slice(), &mut query.iter().map(|v| v.as_slice())) + .unwrap()); + } + } + + #[test] + fn bit_stream() { + let mut out = Vec::new(); + { + let mut writer = BitStreamWriter::new(&mut out); + writer.write(0, 1).unwrap(); // 0 + writer.write(2, 2).unwrap(); // 10 + writer.write(6, 3).unwrap(); // 110 + writer.write(11, 4).unwrap(); // 1011 + writer.write(1, 5).unwrap(); // 00001 + writer.write(32, 6).unwrap(); // 100000 + writer.write(7, 7).unwrap(); // 0000111 + writer.flush().unwrap(); + } + let bytes = out; + assert_eq!( + "01011010110000110000000001110000", + format!("{:08b}{:08b}{:08b}{:08b}", bytes[0], bytes[1], bytes[2], bytes[3]) + ); + { + let mut input = bytes.as_slice(); + let mut reader = BitStreamReader::new(&mut input); + assert_eq!(reader.read(1).unwrap(), 0); + assert_eq!(reader.read(2).unwrap(), 2); + assert_eq!(reader.read(3).unwrap(), 6); + assert_eq!(reader.read(4).unwrap(), 11); + assert_eq!(reader.read(5).unwrap(), 1); + assert_eq!(reader.read(6).unwrap(), 32); + assert_eq!(reader.read(7).unwrap(), 7); + // 4 bits remained + assert!(reader.read(5).is_err()); + } + } +} diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs new file mode 100644 index 000000000..013548b77 --- /dev/null +++ b/bitcoin/src/bip32.rs @@ -0,0 +1,1627 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! BIP-0032 implementation. +//! +//! Implementation of BIP-0032 hierarchical deterministic wallets, as defined +//! at . + +use core::convert::Infallible; +use core::ops::Index; +use core::str::FromStr; +use core::{fmt, slice}; + +use hashes::{hash160, hash_newtype, sha512, Hash, HashEngine, Hmac, HmacEngine}; +use internals::array::ArrayExt; +use internals::write_err; + +use crate::crypto::key::{CompressedPublicKey, Keypair, PrivateKey, XOnlyPublicKey}; +use crate::internal_macros; +use crate::network::NetworkKind; +use crate::prelude::{String, Vec}; + +/// Version bytes for extended public keys on the Bitcoin network. +const VERSION_BYTES_MAINNET_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E]; +/// Version bytes for extended private keys on the Bitcoin network. +const VERSION_BYTES_MAINNET_PRIVATE: [u8; 4] = [0x04, 0x88, 0xAD, 0xE4]; +/// Version bytes for extended public keys on any of the testnet networks. +const VERSION_BYTES_TESTNETS_PUBLIC: [u8; 4] = [0x04, 0x35, 0x87, 0xCF]; +/// Version bytes for extended private keys on any of the testnet networks. +const VERSION_BYTES_TESTNETS_PRIVATE: [u8; 4] = [0x04, 0x35, 0x83, 0x94]; + +/// The old name for xpub, extended public key. +#[deprecated(since = "0.31.0", note = "use `Xpub` instead")] +pub type ExtendedPubKey = Xpub; + +/// The old name for xpriv, extended public key. +#[deprecated(since = "0.31.0", note = "use `Xpriv` instead")] +pub type ExtendedPrivKey = Xpriv; + +/// A chain code +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ChainCode([u8; 32]); +internals::impl_array_newtype!(ChainCode, u8, 32); +internal_macros::impl_array_newtype_stringify!(ChainCode, 32); + +impl ChainCode { + fn from_hmac(hmac: Hmac) -> Self { + Self(*hmac.as_byte_array().split_array::<32, 32>().1) + } + + /// Copies the underlying bytes into a new `Vec`. + #[inline] + #[deprecated(since = "TBD", note = "use to_vec instead")] + pub fn to_bytes(self) -> alloc::vec::Vec { self.to_vec() } +} + +/// A fingerprint +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct Fingerprint([u8; 4]); +internals::impl_array_newtype!(Fingerprint, u8, 4); +internal_macros::impl_array_newtype_stringify!(Fingerprint, 4); + +hash_newtype! { + /// Extended key identifier as defined in BIP-0032. + pub struct XKeyIdentifier(hash160::Hash); +} + +hashes::impl_hex_for_newtype!(XKeyIdentifier); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(XKeyIdentifier); + +/// Extended private key +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Xpriv { + /// The network this key is to be used on + pub network: NetworkKind, + /// How many derivations this key is from the master (which is 0) + pub depth: u8, + /// Fingerprint of the parent key (0 for master) + pub parent_fingerprint: Fingerprint, + /// Child number of the key used to derive from parent (0 for master) + pub child_number: ChildNumber, + /// Private key + pub private_key: secp256k1::SecretKey, + /// Chain code + pub chain_code: ChainCode, +} +#[cfg(feature = "serde")] +internals::serde_string_impl!(Xpriv, "a BIP-0032 extended private key"); + +#[cfg(not(feature = "std"))] +impl fmt::Debug for Xpriv { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Xpriv") + .field("network", &self.network) + .field("depth", &self.depth) + .field("parent_fingerprint", &self.parent_fingerprint) + .field("child_number", &self.child_number) + .field("chain_code", &self.chain_code) + .field("private_key", &"[SecretKey]") + .finish() + } +} + +/// Extended public key +#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] +pub struct Xpub { + /// The network kind this key is to be used on + pub network: NetworkKind, + /// How many derivations this key is from the master (which is 0) + pub depth: u8, + /// Fingerprint of the parent key + pub parent_fingerprint: Fingerprint, + /// Child number of the key used to derive from parent (0 for master) + pub child_number: ChildNumber, + /// Public key + pub public_key: secp256k1::PublicKey, + /// Chain code + pub chain_code: ChainCode, +} +#[cfg(feature = "serde")] +internals::serde_string_impl!(Xpub, "a BIP-0032 extended public key"); + +/// A child number for a derived key +#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] +pub enum ChildNumber { + /// Non-hardened key + Normal { + /// Key index, within [0, 2^31 - 1] + index: u32, + }, + /// Hardened key + Hardened { + /// Key index, within [0, 2^31 - 1] + index: u32, + }, +} +impl ChildNumber { + /// Normal child number with index 0. + pub const ZERO_NORMAL: Self = Self::Normal { index: 0 }; + + /// Normal child number with index 1. + pub const ONE_NORMAL: Self = Self::Normal { index: 1 }; + + /// Hardened child number with index 0. + pub const ZERO_HARDENED: Self = Self::Hardened { index: 0 }; + + /// Hardened child number with index 1. + pub const ONE_HARDENED: Self = Self::Hardened { index: 1 }; + + /// Constructs a new [`Normal`] from an index, returns an error if the index is not within + /// [0, 2^31 - 1]. + /// + /// [`Normal`]: #variant.Normal + pub fn from_normal_idx(index: u32) -> Result { + if index & (1 << 31) == 0 { + Ok(Self::Normal { index }) + } else { + Err(IndexOutOfRangeError { index }) + } + } + + /// Constructs a new [`Hardened`] from an index, returns an error if the index is not within + /// [0, 2^31 - 1]. + /// + /// [`Hardened`]: #variant.Hardened + pub fn from_hardened_idx(index: u32) -> Result { + if index & (1 << 31) == 0 { + Ok(Self::Hardened { index }) + } else { + Err(IndexOutOfRangeError { index }) + } + } + + /// Returns `true` if the child number is a [`Normal`] value. + /// + /// [`Normal`]: #variant.Normal + pub fn is_normal(&self) -> bool { !self.is_hardened() } + + /// Returns `true` if the child number is a [`Hardened`] value. + /// + /// [`Hardened`]: #variant.Hardened + pub fn is_hardened(&self) -> bool { + match self { + Self::Hardened { .. } => true, + Self::Normal { .. } => false, + } + } + + /// Returns the child number that is a single increment from this one. + pub fn increment(self) -> Result { + // Bare addition in this function is okay, because we have an invariant that + // `index` is always within [0, 2^31 - 1]. FIXME this is not actually an + // invariant because the fields are public. + match self { + Self::Normal { index: idx } => Self::from_normal_idx(idx + 1), + Self::Hardened { index: idx } => Self::from_hardened_idx(idx + 1), + } + } + + /// Formats the child number using the provided formatting function. + /// + /// For hardened child numbers appends a `'` or `hardened_alt_suffix` + /// depending on the formatter. + fn format_with( + &self, + f: &mut fmt::Formatter, + format_fn: F, + hardened_alt_suffix: &str, + ) -> fmt::Result + where + F: Fn(&u32, &mut fmt::Formatter) -> fmt::Result, + { + match *self { + Self::Hardened { index } => { + format_fn(&index, f)?; + let alt = f.alternate(); + f.write_str(if alt { hardened_alt_suffix } else { "'" }) + } + Self::Normal { index } => format_fn(&index, f), + } + } +} + +impl From for ChildNumber { + fn from(number: u32) -> Self { + if number & (1 << 31) != 0 { + Self::Hardened { index: number ^ (1 << 31) } + } else { + Self::Normal { index: number } + } + } +} + +impl From for u32 { + fn from(cnum: ChildNumber) -> Self { + match cnum { + ChildNumber::Normal { index } => index, + ChildNumber::Hardened { index } => index | (1 << 31), + } + } +} + +impl fmt::Display for ChildNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format_with(f, fmt::Display::fmt, "h") + } +} + +impl fmt::LowerHex for ChildNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format_with(f, fmt::LowerHex::fmt, "h") + } +} + +impl fmt::UpperHex for ChildNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format_with(f, fmt::UpperHex::fmt, "H") + } +} + +impl fmt::Octal for ChildNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format_with(f, fmt::Octal::fmt, "h") + } +} + +impl fmt::Binary for ChildNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format_with(f, fmt::Binary::fmt, "h") + } +} + +impl FromStr for ChildNumber { + type Err = ParseChildNumberError; + + fn from_str(inp: &str) -> Result { + let is_hardened = inp.chars().last().is_some_and(|l| l == '\'' || l == 'h'); + Ok(if is_hardened { + Self::from_hardened_idx( + inp[0..inp.len() - 1].parse().map_err(ParseChildNumberError::ParseInt)?, + ) + .map_err(ParseChildNumberError::IndexOutOfRange)? + } else { + Self::from_normal_idx(inp.parse().map_err(ParseChildNumberError::ParseInt)?) + .map_err(ParseChildNumberError::IndexOutOfRange)? + }) + } +} + +impl AsRef<[Self]> for ChildNumber { + fn as_ref(&self) -> &[Self] { slice::from_ref(self) } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for ChildNumber { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + u32::deserialize(deserializer).map(Self::from) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for ChildNumber { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + u32::from(*self).serialize(serializer) + } +} + +/// Trait that allows possibly failable conversion from a type into a +/// derivation path +pub trait IntoDerivationPath { + /// Converts a given type into a [`DerivationPath`] with possible error + fn into_derivation_path(self) -> Result; +} + +/// A BIP-0032 derivation path. +#[derive(Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub struct DerivationPath(Vec); + +#[cfg(feature = "serde")] +internals::serde_string_impl!(DerivationPath, "a BIP-0032 derivation path"); + +impl Index for DerivationPath +where + Vec: Index, +{ + type Output = as Index>::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { &self.0[index] } +} + +impl Default for DerivationPath { + fn default() -> Self { Self::master() } +} + +impl IntoDerivationPath for T +where + T: Into, +{ + fn into_derivation_path(self) -> Result { + Ok(self.into()) + } +} + +impl IntoDerivationPath for String { + fn into_derivation_path(self) -> Result { self.parse() } +} + +impl IntoDerivationPath for &'_ str { + fn into_derivation_path(self) -> Result { self.parse() } +} + +impl From> for DerivationPath { + fn from(numbers: Vec) -> Self { Self(numbers) } +} + +impl From for Vec { + fn from(path: DerivationPath) -> Self { path.0 } +} + +impl<'a> From<&'a [ChildNumber]> for DerivationPath { + fn from(numbers: &'a [ChildNumber]) -> Self { Self(numbers.to_vec()) } +} + +impl core::iter::FromIterator for DerivationPath { + fn from_iter(iter: T) -> Self + where + T: IntoIterator, + { + Self(Vec::from_iter(iter)) + } +} + +impl<'a> core::iter::IntoIterator for &'a DerivationPath { + type Item = &'a ChildNumber; + type IntoIter = slice::Iter<'a, ChildNumber>; + fn into_iter(self) -> Self::IntoIter { self.0.iter() } +} + +impl AsRef<[ChildNumber]> for DerivationPath { + fn as_ref(&self) -> &[ChildNumber] { &self.0 } +} + +impl FromStr for DerivationPath { + type Err = ParseChildNumberError; + + fn from_str(path: &str) -> Result { + if path.is_empty() || path == "m" || path == "m/" { + return Ok(vec![].into()); + } + + let path = path.strip_prefix("m/").unwrap_or(path); + + let parts = path.split('/'); + let ret: Result, _> = parts.map(str::parse).collect(); + Ok(Self(ret?)) + } +} + +/// An iterator over children of a [DerivationPath]. +/// +/// It is returned by the methods [DerivationPath::children_from], +/// [DerivationPath::normal_children] and [DerivationPath::hardened_children]. +pub struct DerivationPathIterator<'a> { + base: &'a DerivationPath, + next_child: Option, +} + +impl<'a> DerivationPathIterator<'a> { + /// Starts a new [DerivationPathIterator] at the given child. + pub fn start_from(path: &'a DerivationPath, start: ChildNumber) -> Self { + DerivationPathIterator { base: path, next_child: Some(start) } + } +} + +impl Iterator for DerivationPathIterator<'_> { + type Item = DerivationPath; + + fn next(&mut self) -> Option { + let ret = self.next_child?; + self.next_child = ret.increment().ok(); + Some(self.base.child(ret)) + } +} + +impl DerivationPath { + /// Returns length of the derivation path + pub fn len(&self) -> usize { self.0.len() } + + /// Returns `true` if the derivation path is empty + pub fn is_empty(&self) -> bool { self.0.is_empty() } + + /// Returns derivation path for a master key (i.e. empty derivation path) + pub fn master() -> Self { Self(vec![]) } + + /// Returns whether derivation path represents master key (i.e. it's length + /// is empty). True for `m` path. + pub fn is_master(&self) -> bool { self.0.is_empty() } + + /// Constructs a new [DerivationPath] that is a child of this one. + pub fn child(&self, cn: ChildNumber) -> Self { + let mut path = self.0.clone(); + path.push(cn); + Self(path) + } + + /// Converts into a [DerivationPath] that is a child of this one. + pub fn into_child(self, cn: ChildNumber) -> Self { + let mut path = self.0; + path.push(cn); + Self(path) + } + + /// Gets an [Iterator] over the children of this [DerivationPath] + /// starting with the given [ChildNumber]. + pub fn children_from(&self, cn: ChildNumber) -> DerivationPathIterator<'_> { + DerivationPathIterator::start_from(self, cn) + } + + /// Gets an [Iterator] over the unhardened children of this [DerivationPath]. + pub fn normal_children(&self) -> DerivationPathIterator<'_> { + DerivationPathIterator::start_from(self, ChildNumber::Normal { index: 0 }) + } + + /// Gets an [Iterator] over the hardened children of this [DerivationPath]. + pub fn hardened_children(&self) -> DerivationPathIterator<'_> { + DerivationPathIterator::start_from(self, ChildNumber::Hardened { index: 0 }) + } + + /// Concatenate `self` with `path` and return the resulting new path. + /// + /// ``` + /// use bitcoin::bip32::{DerivationPath, ChildNumber}; + /// + /// let base = "m/42".parse::().unwrap(); + /// + /// let deriv_1 = base.extend("0/1".parse::().unwrap()); + /// let deriv_2 = base.extend(&[ + /// ChildNumber::ZERO_NORMAL, + /// ChildNumber::ONE_NORMAL + /// ]); + /// + /// assert_eq!(deriv_1, deriv_2); + /// ``` + pub fn extend>(&self, path: T) -> Self { + let mut new_path = self.clone(); + new_path.0.extend_from_slice(path.as_ref()); + new_path + } + + /// Returns the derivation path as a vector of u32 integers. + /// Unhardened elements are copied as is. + /// 0x80000000 is added to the hardened elements. + /// + /// ``` + /// use bitcoin::bip32::DerivationPath; + /// + /// let path = "m/84'/0'/0'/0/1".parse::().unwrap(); + /// const HARDENED: u32 = 0x80000000; + /// assert_eq!(path.to_u32_vec(), vec![84 + HARDENED, HARDENED, HARDENED, 0, 1]); + /// ``` + pub fn to_u32_vec(&self) -> Vec { self.into_iter().map(|&el| el.into()).collect() } + + /// Constructs a new derivation path from a slice of u32s. + /// ``` + /// use bitcoin::bip32::DerivationPath; + /// + /// const HARDENED: u32 = 0x80000000; + /// let expected = vec![84 + HARDENED, HARDENED, HARDENED, 0, 1]; + /// let path = DerivationPath::from_u32_slice(expected.as_slice()); + /// assert_eq!(path.to_u32_vec(), expected); + /// ``` + pub fn from_u32_slice(numbers: &[u32]) -> Self { + numbers.iter().map(|&n| ChildNumber::from(n)).collect() + } +} + +impl fmt::Display for DerivationPath { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut iter = self.0.iter(); + if let Some(first_element) = iter.next() { + if f.alternate() { + write!(f, "{:#}", first_element)?; + } else { + write!(f, "{}", first_element)?; + } + } + for cn in iter { + f.write_str("/")?; + if f.alternate() { + write!(f, "{:#}", cn)?; + } else { + write!(f, "{}", cn)?; + } + } + Ok(()) + } +} + +impl fmt::Debug for DerivationPath { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self, f) } +} + +/// Full information on the used extended public key: fingerprint of the +/// master extended public key and a derivation path from it. +pub type KeySource = (Fingerprint, DerivationPath); + +/// A BIP-0032 error +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ParseError { + /// A secp256k1 error occurred + Secp256k1(secp256k1::Error), + /// Unknown version magic bytes + UnknownVersion([u8; 4]), + /// Encoded extended key data has wrong length + WrongExtendedKeyLength(usize), + /// Base58 encoding error + Base58(base58::Error), + /// Base58 decoded data was an invalid length. + InvalidBase58PayloadLength(InvalidBase58PayloadLengthError), + /// Invalid private key prefix (byte 45 must be 0) + InvalidPrivateKeyPrefix, + /// Non-zero parent fingerprint for a master key (depth 0) + NonZeroParentFingerprintForMasterKey, + /// Non-zero child number for a master key (depth 0) + NonZeroChildNumberForMasterKey, +} + +impl From for ParseError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Secp256k1(ref e) => write_err!(f, "secp256k1 error"; e), + Self::UnknownVersion(ref bytes) => + write!(f, "unknown version magic bytes: {:?}", bytes), + Self::WrongExtendedKeyLength(ref len) => + write!(f, "encoded extended key data has wrong length {}", len), + Self::Base58(ref e) => write_err!(f, "base58 encoding error"; e), + Self::InvalidBase58PayloadLength(ref e) => write_err!(f, "base58 payload"; e), + Self::InvalidPrivateKeyPrefix => + f.write_str("invalid private key prefix, byte 45 must be 0 as required by BIP-0032"), + Self::NonZeroParentFingerprintForMasterKey => + f.write_str("non-zero parent fingerprint in master key"), + Self::NonZeroChildNumberForMasterKey => + f.write_str("non-zero child number in master key"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Secp256k1(ref e) => Some(e), + Self::Base58(ref e) => Some(e), + Self::InvalidBase58PayloadLength(ref e) => Some(e), + Self::UnknownVersion(_) | Self::WrongExtendedKeyLength(_) => None, + Self::InvalidPrivateKeyPrefix => None, + Self::NonZeroParentFingerprintForMasterKey => None, + Self::NonZeroChildNumberForMasterKey => None, + } + } +} + +impl From for ParseError { + fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) } +} + +impl From for ParseError { + fn from(err: base58::Error) -> Self { Self::Base58(err) } +} + +impl From for ParseError { + fn from(e: InvalidBase58PayloadLengthError) -> Self { + Self::InvalidBase58PayloadLength(e) + } +} + +/// A BIP-0032 error +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum DerivationError { + /// Attempted to derive a hardened child from an xpub. + /// + /// You can only derive hardened children from xprivs. + CannotDeriveHardenedChild, + /// Attempted to derive a child of depth 256 or higher. + /// + /// There is no way to encode such xkeys. + MaximumDepthExceeded, +} + +#[cfg(feature = "std")] +impl std::error::Error for DerivationError {} + +impl fmt::Display for DerivationError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::CannotDeriveHardenedChild => + f.write_str("cannot derive hardened child of public key"), + Self::MaximumDepthExceeded => f.write_str("cannot derive child of depth 256 or higher"), + } + } +} + +/// Out-of-range index when constructing a child number. +/// +/// *Indices* are always in the range [0, 2^31 - 1]. Normal child numbers have the +/// same range, while hardened child numbers lie in the range [2^31, 2^32 - 1]. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct IndexOutOfRangeError { + /// The index that was out of range for a child number. + pub index: u32, +} + +#[cfg(feature = "std")] +impl std::error::Error for IndexOutOfRangeError {} + +impl From for IndexOutOfRangeError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for IndexOutOfRangeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "index {} out of range [0, 2^31 - 1] (do you have a hardened child number, rather than an index?)", self.index) + } +} + +/// Error parsing a child number. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParseChildNumberError { + /// Parsed the child number as an integer, but the integer was out of range. + IndexOutOfRange(IndexOutOfRangeError), + /// Failed to parse the child number as an integer. + ParseInt(core::num::ParseIntError), +} + +impl From for ParseChildNumberError { + fn from(never: Infallible) -> Self { match never {} } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseChildNumberError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + Self::IndexOutOfRange(ref e) => Some(e), + Self::ParseInt(ref e) => Some(e), + } + } +} + +impl fmt::Display for ParseChildNumberError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::IndexOutOfRange(ref e) => e.fmt(f), + Self::ParseInt(ref e) => e.fmt(f), + } + } +} + +impl Xpriv { + /// Constructs a new master key from a seed value + pub fn new_master(network: impl Into, seed: &[u8]) -> Self { + let mut engine = HmacEngine::::new(b"Bitcoin seed"); + engine.input(seed); + let hmac = engine.finalize(); + + Self { + network: network.into(), + depth: 0, + parent_fingerprint: Default::default(), + child_number: ChildNumber::ZERO_NORMAL, + private_key: secp256k1::SecretKey::from_secret_bytes( + *hmac.as_byte_array().split_array::<32, 32>().0, + ) + .expect("cryptographically unreachable"), + chain_code: ChainCode::from_hmac(hmac), + } + } + + /// Constructs a new ECDSA compressed private key matching internal secret key representation. + #[deprecated(since = "TBD", note = "use `to_private_key()` instead")] + pub fn to_priv(self) -> PrivateKey { self.to_private_key() } + + /// Constructs a new ECDSA compressed private key matching internal secret key representation. + pub fn to_private_key(self) -> PrivateKey { + PrivateKey { compressed: true, network: self.network, inner: self.private_key } + } + + /// Constructs a new extended public key from this extended private key. + pub fn to_xpub(self) -> Xpub { + Xpub::from_xpriv(&self) + } + + /// Constructs a new BIP-0340 keypair for Schnorr signatures and Taproot use matching the internal + /// secret key representation. + pub fn to_keypair(self) -> Keypair { + Keypair::from_seckey_byte_array(self.private_key.to_secret_bytes()) + .expect("BIP-0032 internal private key representation is broken") + } + + /// Derives an extended private key from a path. + /// + /// The `path` argument can be both of type `DerivationPath` or `Vec`. + #[deprecated(since = "TBD", note = "use `derive_xpriv()` instead")] + pub fn derive_priv>( + &self, + path: P, + ) -> Result { + self.derive_xpriv(path) + } + + /// Derives an extended private key from a path. + /// + /// The `path` argument can be both of type `DerivationPath` or `Vec`. + pub fn derive_xpriv>( + &self, + path: P, + ) -> Result { + let mut sk: Self = *self; + for cnum in path.as_ref() { + sk = sk.ckd_priv(*cnum)?; + } + Ok(sk) + } + + /// Private->Private child key derivation + fn ckd_priv( + &self, + i: ChildNumber, + ) -> Result { + let mut engine = HmacEngine::::new(&self.chain_code[..]); + match i { + ChildNumber::Normal { .. } => { + // Non-hardened key: compute public data and use that + engine.input( + &secp256k1::PublicKey::from_secret_key(&self.private_key).serialize()[..], + ); + } + ChildNumber::Hardened { .. } => { + // Hardened key: use only secret data to prevent public derivation + engine.input(&[0u8]); + engine.input(&self.private_key[..]); + } + } + + engine.input(&u32::from(i).to_be_bytes()); + let hmac: Hmac = engine.finalize(); + let sk = + secp256k1::SecretKey::from_secret_bytes(*hmac.as_byte_array().split_array::<32, 32>().0) + .expect("statistically impossible to hit"); + let tweaked = + sk.add_tweak(&self.private_key.into()).expect("statistically impossible to hit"); + + Ok(Self { + network: self.network, + depth: self.depth.checked_add(1).ok_or(DerivationError::MaximumDepthExceeded)?, + parent_fingerprint: self.fingerprint(), + child_number: i, + private_key: tweaked, + chain_code: ChainCode::from_hmac(hmac), + }) + } + + /// Decoding extended private key from binary data according to BIP-0032 + pub fn decode(data: &[u8]) -> Result { + let Common { network, depth, parent_fingerprint, child_number, chain_code, key } = + Common::decode(data)?; + + let network = match network { + VERSION_BYTES_MAINNET_PRIVATE => NetworkKind::Main, + VERSION_BYTES_TESTNETS_PRIVATE => NetworkKind::Test, + unknown => return Err(ParseError::UnknownVersion(unknown)), + }; + + let (&zero, private_key) = key.split_first(); + if zero != 0 { + return Err(ParseError::InvalidPrivateKeyPrefix); + } + + Ok(Self { + network, + depth, + parent_fingerprint, + child_number, + chain_code, + private_key: secp256k1::SecretKey::from_secret_bytes(*private_key)?, + }) + } + + /// Extended private key binary encoding according to BIP-0032 + pub fn encode(&self) -> [u8; 78] { + let mut ret = [0; 78]; + ret[0..4].copy_from_slice(&match self.network { + NetworkKind::Main => VERSION_BYTES_MAINNET_PRIVATE, + NetworkKind::Test => VERSION_BYTES_TESTNETS_PRIVATE, + }); + ret[4] = self.depth; + ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); + ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes()); + ret[13..45].copy_from_slice(&self.chain_code[..]); + ret[45] = 0; + ret[46..78].copy_from_slice(&self.private_key[..]); + ret + } + + /// Returns the HASH160 of the public key belonging to the xpriv + pub fn identifier(&self) -> XKeyIdentifier { + Xpub::from_xpriv(self).identifier() + } + + /// Returns the first four bytes of the identifier + pub fn fingerprint(&self) -> Fingerprint { + self.identifier().as_byte_array().sub_array::<0, 4>().into() + } +} + +impl Xpub { + /// Constructs a new extended public key from an extended private key. + #[deprecated(since = "TBD", note = "use `from_xpriv()` instead")] + pub fn from_priv(sk: &Xpriv) -> Self { + Self::from_xpriv(sk) + } + + /// Constructs a new extended public key from an extended private key. + pub fn from_xpriv(xpriv: &Xpriv) -> Self { + Self { + network: xpriv.network, + depth: xpriv.depth, + parent_fingerprint: xpriv.parent_fingerprint, + child_number: xpriv.child_number, + public_key: secp256k1::PublicKey::from_secret_key(&xpriv.private_key), + chain_code: xpriv.chain_code, + } + } + + /// Constructs a new ECDSA compressed public key matching internal public key representation. + #[deprecated(since = "TBD", note = "use `to_public_key()` instead")] + pub fn to_pub(self) -> CompressedPublicKey { self.to_public_key() } + + /// Constructs a new ECDSA compressed public key matching internal public key representation. + pub fn to_public_key(self) -> CompressedPublicKey { CompressedPublicKey(self.public_key) } + + /// Constructs a new BIP-0340 x-only public key for BIP-0340 signatures and Taproot use matching + /// the internal public key representation. + #[deprecated(since = "TBD", note = "use `to_x_only_public_key()` instead")] + pub fn to_x_only_pub(self) -> XOnlyPublicKey { self.to_x_only_public_key() } + + /// Constructs a new BIP-0340 x-only public key for BIP-0340 signatures and Taproot use matching + /// the internal public key representation. + pub fn to_x_only_public_key(self) -> XOnlyPublicKey { XOnlyPublicKey::from(self.public_key) } + + /// Attempts to derive an extended public key from a path. + /// + /// The `path` argument can be any type implementing `AsRef`, such as `DerivationPath`, for instance. + #[deprecated(since = "TBD", note = "use `derive_xpub()` instead")] + pub fn derive_pub>( + &self, + path: P, + ) -> Result { + self.derive_xpub(path) + } + + /// Attempts to derive an extended public key from a path. + /// + /// The `path` argument can be any type implementing `AsRef`, such as `DerivationPath`, for instance. + pub fn derive_xpub>( + &self, + path: P, + ) -> Result { + let mut pk: Self = *self; + for cnum in path.as_ref() { + pk = pk.ckd_pub(*cnum)? + } + Ok(pk) + } + + /// Computes the scalar tweak added to this key to get a child key + pub fn ckd_pub_tweak( + &self, + i: ChildNumber, + ) -> Result<(secp256k1::SecretKey, ChainCode), DerivationError> { + match i { + ChildNumber::Hardened { .. } => Err(DerivationError::CannotDeriveHardenedChild), + ChildNumber::Normal { index: n } => { + let mut engine = HmacEngine::::new(&self.chain_code[..]); + engine.input(&self.public_key.serialize()[..]); + engine.input(&n.to_be_bytes()); + + let hmac = engine.finalize(); + let private_key = secp256k1::SecretKey::from_secret_bytes( + *hmac.as_byte_array().split_array::<32, 32>().0, + ) + .expect("cryptographically unreachable"); + let chain_code = ChainCode::from_hmac(hmac); + Ok((private_key, chain_code)) + } + } + } + + /// Public->Public child key derivation + pub fn ckd_pub( + &self, + i: ChildNumber, + ) -> Result { + let (sk, chain_code) = self.ckd_pub_tweak(i)?; + let tweaked = + self.public_key.add_exp_tweak(&sk.into()).expect("cryptographically unreachable"); + + Ok(Self { + network: self.network, + depth: self.depth.checked_add(1).ok_or(DerivationError::MaximumDepthExceeded)?, + parent_fingerprint: self.fingerprint(), + child_number: i, + public_key: tweaked, + chain_code, + }) + } + + /// Decoding extended public key from binary data according to BIP-0032 + pub fn decode(data: &[u8]) -> Result { + let Common { network, depth, parent_fingerprint, child_number, chain_code, key } = + Common::decode(data)?; + + let network = match network { + VERSION_BYTES_MAINNET_PUBLIC => NetworkKind::Main, + VERSION_BYTES_TESTNETS_PUBLIC => NetworkKind::Test, + unknown => return Err(ParseError::UnknownVersion(unknown)), + }; + + Ok(Self { + network, + depth, + parent_fingerprint, + child_number, + chain_code, + public_key: secp256k1::PublicKey::from_slice(&key)?, + }) + } + + /// Extended public key binary encoding according to BIP-0032 + pub fn encode(&self) -> [u8; 78] { + let mut ret = [0; 78]; + ret[0..4].copy_from_slice(&match self.network { + NetworkKind::Main => VERSION_BYTES_MAINNET_PUBLIC, + NetworkKind::Test => VERSION_BYTES_TESTNETS_PUBLIC, + }); + ret[4] = self.depth; + ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); + ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes()); + ret[13..45].copy_from_slice(&self.chain_code[..]); + ret[45..78].copy_from_slice(&self.public_key.serialize()[..]); + ret + } + + /// Returns the HASH160 of the public key component of the xpub + pub fn identifier(&self) -> XKeyIdentifier { + XKeyIdentifier(hash160::Hash::hash(&self.public_key.serialize())) + } + + /// Returns the first four bytes of the identifier + pub fn fingerprint(&self) -> Fingerprint { + self.identifier().as_byte_array().sub_array::<0, 4>().into() + } +} + +impl fmt::Display for Xpriv { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + base58::encode_check_to_fmt(fmt, &self.encode()[..]) + } +} + +impl FromStr for Xpriv { + type Err = ParseError; + + fn from_str(inp: &str) -> Result { + let data = base58::decode_check(inp)?; + + if data.len() != 78 { + return Err(InvalidBase58PayloadLengthError { length: data.len() }.into()); + } + + Self::decode(&data) + } +} + +impl fmt::Display for Xpub { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + base58::encode_check_to_fmt(fmt, &self.encode()[..]) + } +} + +impl FromStr for Xpub { + type Err = ParseError; + + fn from_str(inp: &str) -> Result { + let data = base58::decode_check(inp)?; + + if data.len() != 78 { + return Err(InvalidBase58PayloadLengthError { length: data.len() }.into()); + } + + Self::decode(&data) + } +} + +impl From for XKeyIdentifier { + fn from(key: Xpub) -> Self { key.identifier() } +} + +impl From<&Xpub> for XKeyIdentifier { + fn from(key: &Xpub) -> Self { key.identifier() } +} + +/// Decoded base58 data was an invalid length. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidBase58PayloadLengthError { + /// The base58 payload length we got after decoding xpriv/xpub string. + pub(crate) length: usize, +} + +impl InvalidBase58PayloadLengthError { + /// Returns the invalid payload length. + pub fn invalid_base58_payload_length(&self) -> usize { self.length } +} + +impl fmt::Display for InvalidBase58PayloadLengthError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "decoded base58 xpriv/xpub data was an invalid length: {} (expected 78)", + self.length + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidBase58PayloadLengthError {} + +// Helps unify decoding +struct Common { + network: [u8; 4], + depth: u8, + parent_fingerprint: Fingerprint, + child_number: ChildNumber, + chain_code: ChainCode, + // public key (compressed) or 0 byte followed by a private key + key: [u8; 33], +} + +impl Common { + fn decode(data: &[u8]) -> Result { + let data: &[u8; 78] = + data.try_into().map_err(|_| ParseError::WrongExtendedKeyLength(data.len()))?; + + let (&network, data) = data.split_array::<4, 74>(); + let (&depth, data) = data.split_first::<73>(); + let (&parent_fingerprint, data) = data.split_array::<4, 69>(); + let (&child_number, data) = data.split_array::<4, 65>(); + let (&chain_code, &key) = data.split_array::<32, 33>(); + + if depth == 0 { + if parent_fingerprint != [0u8; 4] { + return Err(ParseError::NonZeroParentFingerprintForMasterKey); + } + + if child_number != [0u8; 4] { + return Err(ParseError::NonZeroChildNumberForMasterKey); + } + } + + Ok(Self { + network, + depth, + parent_fingerprint: parent_fingerprint.into(), + child_number: u32::from_be_bytes(child_number).into(), + chain_code: chain_code.into(), + key, + }) + } +} + +#[cfg(test)] +mod tests { + use hex_lit::hex; + #[cfg(feature = "serde")] + use internals::serde_round_trip; + + use super::ChildNumber::{Hardened, Normal}; + use super::*; + + #[test] + fn parse_derivation_path_invalid_format() { + let invalid_paths = ["n/0'/0", "4/m/5", "//3/0'", "0h/0x"]; + for path in &invalid_paths { + assert!(matches!( + path.parse::(), + Err(ParseChildNumberError::ParseInt(..)), + )); + } + } + + #[test] + fn test_derivation_path_display() { + let path = DerivationPath::from_str("m/84'/0'/0'/0/0").unwrap(); + assert_eq!(format!("{}", path), "84'/0'/0'/0/0"); + assert_eq!(format!("{:#}", path), "84h/0h/0h/0/0"); + } + + #[test] + fn test_lowerhex_formatting() { + let normal = Normal { index: 42 }; + let hardened = Hardened { index: 42 }; + + assert_eq!(format!("{:x}", normal), "2a"); + assert_eq!(format!("{:#x}", normal), "0x2a"); + + assert_eq!(format!("{:x}", hardened), "2a'"); + assert_eq!(format!("{:#x}", hardened), "0x2ah"); + } + + #[test] + fn test_upperhex_formatting() { + let normal = Normal { index: 42 }; + let hardened = Hardened { index: 42 }; + + assert_eq!(format!("{:X}", normal), "2A"); + assert_eq!(format!("{:#X}", normal), "0x2A"); + + assert_eq!(format!("{:X}", hardened), "2A'"); + assert_eq!(format!("{:#X}", hardened), "0x2AH"); + } + + #[test] + fn test_octal_formatting() { + let normal = Normal { index: 42 }; + let hardened = Hardened { index: 42 }; + + assert_eq!(format!("{:o}", normal), "52"); + assert_eq!(format!("{:#o}", normal), "0o52"); + + assert_eq!(format!("{:o}", hardened), "52'"); + assert_eq!(format!("{:#o}", hardened), "0o52h"); + } + + #[test] + fn test_binary_formatting() { + let normal = Normal { index: 42 }; + let hardened = Hardened { index: 42 }; + + assert_eq!(format!("{:b}", normal), "101010"); + assert_eq!(format!("{:#b}", normal), "0b101010"); + + assert_eq!(format!("{:b}", hardened), "101010'"); + assert_eq!(format!("{:#b}", hardened), "0b101010h"); + } + + #[test] + fn parse_derivation_path_out_of_range() { + let invalid_path = "2147483648"; + assert_eq!( + invalid_path.parse::(), + Err(ParseChildNumberError::IndexOutOfRange(IndexOutOfRangeError { index: 2147483648 })), + ); + } + + #[test] + fn parse_derivation_path_valid_empty_master() { + // Sanity checks. + assert_eq!(DerivationPath::master(), DerivationPath(vec![])); + assert_eq!(DerivationPath::master(), "".parse::().unwrap()); + assert_eq!(DerivationPath::master(), DerivationPath::default()); + + // Empty is the same as with an `m`. + assert_eq!("".parse::().unwrap(), DerivationPath(vec![])); + assert_eq!("m".parse::().unwrap(), DerivationPath(vec![])); + assert_eq!("m/".parse::().unwrap(), DerivationPath(vec![])); + } + + #[test] + fn parse_derivation_path_valid() { + let valid_paths = [ + ("0'", vec![ChildNumber::ZERO_HARDENED]), + ("0'/1", vec![ChildNumber::ZERO_HARDENED, ChildNumber::ONE_NORMAL]), + ( + "0h/1/2'", + vec![ + ChildNumber::ZERO_HARDENED, + ChildNumber::ONE_NORMAL, + ChildNumber::from_hardened_idx(2).unwrap(), + ], + ), + ( + "0'/1/2h/2", + vec![ + ChildNumber::ZERO_HARDENED, + ChildNumber::ONE_NORMAL, + ChildNumber::from_hardened_idx(2).unwrap(), + ChildNumber::from_normal_idx(2).unwrap(), + ], + ), + ( + "0'/1/2'/2/1000000000", + vec![ + ChildNumber::ZERO_HARDENED, + ChildNumber::ONE_NORMAL, + ChildNumber::from_hardened_idx(2).unwrap(), + ChildNumber::from_normal_idx(2).unwrap(), + ChildNumber::from_normal_idx(1000000000).unwrap(), + ], + ), + ]; + for (path, expected) in valid_paths { + // Access the inner private field so we don't have to clone expected. + assert_eq!(path.parse::().unwrap().0, expected); + // Test with the leading `m` for good measure. + let prefixed = format!("m/{}", path); + assert_eq!(prefixed.parse::().unwrap().0, expected); + } + } + + #[test] + fn parse_derivation_path_same_as_into_derivation_path() { + let s = "0'/50/3'/5/545456"; + assert_eq!(s.parse::(), s.into_derivation_path()); + assert_eq!(s.parse::(), s.to_string().into_derivation_path()); + + let s = "m/0'/50/3'/5/545456"; + assert_eq!(s.parse::(), s.into_derivation_path()); + assert_eq!(s.parse::(), s.to_string().into_derivation_path()); + } + + #[test] + fn derivation_path_conversion_index() { + let path = "0h/1/2'".parse::().unwrap(); + let numbers: Vec = path.clone().into(); + let path2: DerivationPath = numbers.into(); + assert_eq!(path, path2); + assert_eq!(&path[..2], &[ChildNumber::ZERO_HARDENED, ChildNumber::ONE_NORMAL]); + let indexed: DerivationPath = path[..2].into(); + assert_eq!(indexed, "0h/1".parse::().unwrap()); + assert_eq!(indexed.child(ChildNumber::from_hardened_idx(2).unwrap()), path); + } + + fn test_path( + network: NetworkKind, + seed: &[u8], + path: DerivationPath, + expected_sk: &str, + expected_pk: &str, + ) { + let mut sk = Xpriv::new_master(network, seed); + let mut pk = Xpub::from_xpriv(&sk); + + // Check derivation convenience method for Xpriv + assert_eq!(&sk.derive_xpriv(&path).unwrap().to_string()[..], expected_sk); + + // Check derivation convenience method for Xpub, should error + // appropriately if any ChildNumber is hardened + if path.0.iter().any(|cnum| cnum.is_hardened()) { + assert_eq!( + pk.derive_xpub(&path), + Err(DerivationError::CannotDeriveHardenedChild) + ); + } else { + assert_eq!(&pk.derive_xpub(&path).unwrap().to_string()[..], expected_pk); + } + + // Derive keys, checking hardened and non-hardened derivation one-by-one + for &num in path.0.iter() { + sk = sk.ckd_priv(num).unwrap(); + match num { + Normal { .. } => { + let pk2 = pk.ckd_pub(num).unwrap(); + pk = Xpub::from_xpriv(&sk); + assert_eq!(pk, pk2); + } + Hardened { .. } => { + assert_eq!( + pk.ckd_pub(num), + Err(DerivationError::CannotDeriveHardenedChild) + ); + pk = Xpub::from_xpriv(&sk); + } + } + } + + // Check result against expected base58 + assert_eq!(&sk.to_string()[..], expected_sk); + assert_eq!(&pk.to_string()[..], expected_pk); + // Check decoded base58 against result + let decoded_sk = expected_sk.parse::(); + let decoded_pk = expected_pk.parse::(); + assert_eq!(Ok(sk), decoded_sk); + assert_eq!(Ok(pk), decoded_pk); + } + + #[test] + fn increment() { + let idx = 9345497; // randomly generated, I promise + let cn = ChildNumber::from_normal_idx(idx).unwrap(); + assert_eq!(cn.increment().ok(), Some(ChildNumber::from_normal_idx(idx + 1).unwrap())); + let cn = ChildNumber::from_hardened_idx(idx).unwrap(); + assert_eq!(cn.increment().ok(), Some(ChildNumber::from_hardened_idx(idx + 1).unwrap())); + + let max = (1 << 31) - 1; + let cn = ChildNumber::from_normal_idx(max).unwrap(); + assert_eq!(cn.increment(), Err(IndexOutOfRangeError { index: 1 << 31 }),); + let cn = ChildNumber::from_hardened_idx(max).unwrap(); + assert_eq!(cn.increment(), Err(IndexOutOfRangeError { index: 1 << 31 }),); + + let cn = ChildNumber::from_normal_idx(350).unwrap(); + let path = "42'".parse::().unwrap(); + let mut iter = path.children_from(cn); + assert_eq!(iter.next(), Some("42'/350".parse().unwrap())); + assert_eq!(iter.next(), Some("42'/351".parse().unwrap())); + + let path = "42'/350'".parse::().unwrap(); + let mut iter = path.normal_children(); + assert_eq!(iter.next(), Some("42'/350'/0".parse().unwrap())); + assert_eq!(iter.next(), Some("42'/350'/1".parse().unwrap())); + + let path = "42'/350'".parse::().unwrap(); + let mut iter = path.hardened_children(); + assert_eq!(iter.next(), Some("42'/350'/0'".parse().unwrap())); + assert_eq!(iter.next(), Some("42'/350'/1'".parse().unwrap())); + + let cn = ChildNumber::from_hardened_idx(42350).unwrap(); + let path = "42'".parse::().unwrap(); + let mut iter = path.children_from(cn); + assert_eq!(iter.next(), Some("42'/42350'".parse().unwrap())); + assert_eq!(iter.next(), Some("42'/42351'".parse().unwrap())); + + let cn = ChildNumber::from_hardened_idx(max).unwrap(); + let path = "42'".parse::().unwrap(); + let mut iter = path.children_from(cn); + assert!(iter.next().is_some()); + assert!(iter.next().is_none()); + } + + #[test] + fn vector_1() { + + let seed = hex!("000102030405060708090a0b0c0d0e0f"); + + // m + test_path(NetworkKind::Main, &seed, "m".parse().unwrap(), + "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); + + // m/0h + test_path(NetworkKind::Main, &seed, "m/0h".parse().unwrap(), + "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", + "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); + + // m/0h/1 + test_path(NetworkKind::Main, &seed, "m/0h/1".parse().unwrap(), + "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", + "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); + + // m/0h/1/2h + test_path(NetworkKind::Main, &seed, "m/0h/1/2h".parse().unwrap(), + "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", + "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); + + // m/0h/1/2h/2 + test_path(NetworkKind::Main, &seed, "m/0h/1/2h/2".parse().unwrap(), + "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", + "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); + + // m/0h/1/2h/2/1000000000 + test_path(NetworkKind::Main, &seed, "m/0h/1/2h/2/1000000000".parse().unwrap(), + "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", + "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); + } + + #[test] + fn vector_2() { + let seed = hex!("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"); + + // m + test_path(NetworkKind::Main, &seed, "m".parse().unwrap(), + "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); + + // m/0 + test_path(NetworkKind::Main, &seed, "m/0".parse().unwrap(), + "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", + "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); + + // m/0/2147483647h + test_path(NetworkKind::Main, &seed, "m/0/2147483647h".parse().unwrap(), + "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", + "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); + + // m/0/2147483647h/1 + test_path(NetworkKind::Main, &seed, "m/0/2147483647h/1".parse().unwrap(), + "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", + "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); + + // m/0/2147483647h/1/2147483646h + test_path(NetworkKind::Main, &seed, "m/0/2147483647h/1/2147483646h".parse().unwrap(), + "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", + "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); + + // m/0/2147483647h/1/2147483646h/2 + test_path(NetworkKind::Main, &seed, "m/0/2147483647h/1/2147483646h/2".parse().unwrap(), + "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", + "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); + } + + #[test] + fn vector_3() { + let seed = hex!("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"); + + // m + test_path(NetworkKind::Main, &seed, "m".parse().unwrap(), + "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", + "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"); + + // m/0h + test_path(NetworkKind::Main, &seed, "m/0h".parse().unwrap(), + "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", + "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); + } + + #[test] + fn test_reject_xpriv_with_non_zero_byte_at_index_45() { + let mut xpriv = base58::decode_check("xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9").unwrap(); + + // Modify byte at index 45 to be non-zero (e.g., 1) + xpriv[45] = 1; + + let result = Xpriv::decode(&xpriv); + assert!(result.is_err()); + + match result { + Err(ParseError::InvalidPrivateKeyPrefix) => {} + _ => panic!("Expected InvalidPrivateKeyPrefix error, got {:?}", result), + } + } + + #[test] + fn test_reject_xpriv_with_zero_depth_and_non_zero_index() { + let result = "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN".parse::(); + assert!(result.is_err()); + + match result { + Err(ParseError::NonZeroChildNumberForMasterKey) => {} + _ => panic!("Expected NonZeroChildNumberForMasterKey error, got {:?}", result), + } + } + + #[test] + fn test_reject_xpriv_with_zero_depth_and_non_zero_parent_fingerprint() { + let result = "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv".parse::(); + assert!(result.is_err()); + + match result { + Err(ParseError::NonZeroParentFingerprintForMasterKey) => {} + _ => panic!("Expected NonZeroParentFingerprintForMasterKey error, got {:?}", result), + } + } + + #[test] + #[cfg(feature = "serde")] + pub fn encode_decode_childnumber() { + serde_round_trip!(ChildNumber::ZERO_NORMAL); + serde_round_trip!(ChildNumber::ONE_NORMAL); + serde_round_trip!(ChildNumber::from_normal_idx((1 << 31) - 1).unwrap()); + serde_round_trip!(ChildNumber::ZERO_HARDENED); + serde_round_trip!(ChildNumber::ONE_HARDENED); + serde_round_trip!(ChildNumber::from_hardened_idx((1 << 31) - 1).unwrap()); + } + + #[test] + #[cfg(feature = "serde")] + pub fn encode_fingerprint_chaincode() { + use serde_json; + let fp = Fingerprint::from([1u8, 2, 3, 42]); + #[rustfmt::skip] + let cc = ChainCode::from( + [1u8,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2] + ); + + serde_round_trip!(fp); + serde_round_trip!(cc); + + assert_eq!("\"0102032a\"", serde_json::to_string(&fp).unwrap()); + assert_eq!( + "\"0102030405060708090001020304050607080900010203040506070809000102\"", + serde_json::to_string(&cc).unwrap() + ); + assert_eq!("0102032a", fp.to_string()); + assert_eq!( + "0102030405060708090001020304050607080900010203040506070809000102", + cc.to_string() + ); + } + + #[test] + fn fmt_child_number() { + assert_eq!("000005h", &format!("{:#06}", ChildNumber::from_hardened_idx(5).unwrap())); + assert_eq!("5h", &format!("{:#}", ChildNumber::from_hardened_idx(5).unwrap())); + assert_eq!("000005'", &format!("{:06}", ChildNumber::from_hardened_idx(5).unwrap())); + assert_eq!("5'", &format!("{}", ChildNumber::from_hardened_idx(5).unwrap())); + assert_eq!("42", &format!("{}", ChildNumber::from_normal_idx(42).unwrap())); + assert_eq!("000042", &format!("{:06}", ChildNumber::from_normal_idx(42).unwrap())); + } + + #[test] + #[should_panic(expected = "Secp256k1(InvalidSecretKey)")] + fn schnorr_broken_privkey_zeros() { + /* this is how we generate key: + let mut sk = secp256k1::key::ONE_KEY; + + let zeros = [0u8; 32]; + unsafe { + sk.as_mut_ptr().copy_from(zeros.as_ptr(), 32); + } + + let xpriv = Xpriv { + network: NetworkKind::Main, + depth: 0, + parent_fingerprint: Default::default(), + child_number: ChildNumber::Normal { index: 0 }, + private_key: sk, + chain_code: ChainCode::from([0u8; 32]) + }; + + println!("{}", xpriv); + */ + + // Xpriv having secret key set to all zeros + let xpriv_str = "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx"; + xpriv_str.parse::().unwrap(); + } + + #[test] + #[should_panic(expected = "Secp256k1(InvalidSecretKey)")] + fn schnorr_broken_privkey_ffs() { + // Xpriv having secret key set to all 0xFF's + let xpriv_str = "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fENZ3QzxW"; + xpriv_str.parse::().unwrap(); + } + + #[test] + fn official_vectors_5() { + let invalid_keys = [ + "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm", + "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH", + "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn", + "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ", + "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4", + "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J", + "xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv", + "xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ", + "xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN", + "xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8", + "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4", + "DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9", + "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx", + "xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G", + "xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY", + "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL", + ]; + for key in invalid_keys { + if key.starts_with("xpub") { + key.parse::().unwrap_err(); + } else { + key.parse::().unwrap_err(); + } + } + } +} diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs new file mode 100644 index 000000000..ef954879c --- /dev/null +++ b/bitcoin/src/blockdata/block.rs @@ -0,0 +1,729 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin blocks. +//! +//! A block is a bundle of transactions with a proof-of-work attached, +//! which commits to an earlier block to form the blockchain. This +//! module describes structures and functions needed to describe +//! these blocks and the blockchain. + +use core::convert::Infallible; +use core::fmt; + +use internals::{compact_size, ToU64}; +use io::{BufRead, Write}; + +use crate::consensus::encode::{self, Decodable, Encodable, WriteExt as _}; +use crate::merkle_tree::{TxMerkleNode, WitnessMerkleNode}; +use crate::network::Params; +use crate::prelude::Vec; +use crate::script::{self, ScriptIntError, ScriptExt as _}; +use crate::transaction::{Coinbase, Transaction, TransactionExt as _}; +use crate::{internal_macros, BlockTime, Target, Weight, Work}; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use primitives::block::{ + Block, Checked, Unchecked, Validation, Version, BlockHash, Header, + WitnessCommitment, compute_merkle_root, compute_witness_root, InvalidBlockError, +}; +#[doc(no_inline)] +pub use units::block::TooBigForRelativeHeightError; +#[doc(inline)] +pub use units::block::{BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInterval}; + +#[deprecated(since = "TBD", note = "use `BlockHeightInterval` instead")] +#[doc(hidden)] +pub type BlockInterval = BlockHeightInterval; + +impl Encodable for BlockHash { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_byte_array().consensus_encode(w) + } +} + +impl Decodable for BlockHash { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<[u8; 32]>::consensus_decode(r)?)) + } +} + +#[rustfmt::skip] +internal_macros::impl_consensus_encoding!(Header, version, prev_blockhash, merkle_root, time, bits, nonce); + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`Header`] type. + pub trait HeaderExt impl for Header { + /// Computes the target (range [0, T] inclusive) that a blockhash must land in to be valid. + fn target(&self) -> Target { self.bits.into() } + + /// Computes the popular "difficulty" measure for mining. + /// + /// Difficulty represents how difficult the current target makes it to find a block, relative to + /// how difficult it would be at the highest possible target (highest target == lowest difficulty). + fn difficulty(&self, params: impl AsRef) -> u128 { + self.target().difficulty(params) + } + + /// Computes the popular "difficulty" measure for mining and returns a float value of f64. + fn difficulty_float(&self, params: impl AsRef) -> f64 { + self.target().difficulty_float(params) + } + + /// Checks that the proof-of-work for the block is valid, returning the block hash. + fn validate_pow(&self, required_target: Target) -> Result { + let target = self.target(); + if target != required_target { + return Err(ValidationError::BadTarget); + } + let block_hash = self.block_hash(); + if target.is_met_by(block_hash) { + Ok(block_hash) + } else { + Err(ValidationError::BadProofOfWork) + } + } + + /// Returns the total work of the block. + fn work(&self) -> Work { self.target().to_work() } + } +} + +impl Encodable for Version { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_consensus().consensus_encode(w) + } +} + +impl Decodable for Version { + fn consensus_decode(r: &mut R) -> Result { + Decodable::consensus_decode(r).map(Self::from_consensus) + } +} + +impl Encodable for BlockTime { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_u32().consensus_encode(w) + } +} + +impl Decodable for BlockTime { + fn consensus_decode(r: &mut R) -> Result { + Decodable::consensus_decode(r).map(Self::from_u32) + } +} + +/// Extension functionality for the [`Block`] type. +pub trait BlockCheckedExt: sealed::Sealed { + /// Constructs a new [`Block`]. + /// + /// # Returns + /// + /// Return the block if it is valid, `None` if not. See [`Block::validate`]. + fn new_checked( + header: Header, + transactions: Vec, + ) -> Result, InvalidBlockError>; + + /// Returns the transaction Merkle root. + fn merkle_root(&self) -> TxMerkleNode; + + /// Returns the Merkle root of transactions hashed for witness. + /// + /// This value was computed during block validation and was cached at that time. + fn witness_root(&mut self) -> Option; + + /// Returns the weight of the block. + /// + /// > Block weight is defined as Base size * 3 + Total size. + fn weight(&self) -> Weight; + + /// Returns the total block size. + /// + /// > Total size is the block size in bytes with transactions serialized as described in BIP-0144, + /// > including base data and witness data. + /// + /// # Panics + /// + /// If the size calculation overflows. + fn total_size(&self) -> usize; + + /// Returns the coinbase transaction. + /// + /// This method is infallible for checked blocks because validation ensures + /// that a valid coinbase transaction is always present. + fn coinbase(&self) -> &Coinbase; + + /// Returns the block height, as encoded in the coinbase transaction according to BIP-0034. + fn bip34_block_height(&self) -> Result; +} + +impl BlockCheckedExt for Block { + fn new_checked( + header: Header, + transactions: Vec, + ) -> Result { + let block = Block::new_unchecked(header, transactions); + block.validate() + } + + fn merkle_root(&self) -> TxMerkleNode { self.header().merkle_root } + + fn witness_root(&mut self) -> Option { self.cached_witness_root() } + + fn weight(&self) -> Weight { + // This is the exact definition of a weight unit, as defined by BIP-0141 (quote above). + let wu = block_base_size(self.transactions()) * 3 + self.total_size(); + Weight::from_wu(wu.to_u64()) + } + + fn total_size(&self) -> usize { + let mut size = Header::SIZE; + + size += compact_size::encoded_size(self.transactions().len()); + size += self.transactions().iter().map(|tx| tx.total_size()).sum::(); + + size + } + + fn coinbase(&self) -> &Coinbase { + let first_tx = &self.transactions()[0]; + Coinbase::assume_coinbase_ref(first_tx) + } + + /// Returns the block height, as encoded in the coinbase transaction according to BIP-0034. + fn bip34_block_height(&self) -> Result { + // Citing the spec: + // Add height as the first item in the coinbase transaction's scriptSig, + // and increase block version to 2. The format of the height is + // "minimally encoded serialized CScript"" -- first byte is number of bytes in the number + // (will be 0x03 on main net for the next 150 or so years with 2^23-1 + // blocks), following bytes are little-endian representation of the + // number (including a sign bit). Height is the height of the mined + // block in the block chain, where the genesis block is height zero (0). + + if self.header().version < Version::TWO { + return Err(Bip34Error::Unsupported); + } + + let cb = self.coinbase(); + let input = cb.first_input(); + let push = input + .script_sig + .instructions_minimal() + .next() + .ok_or(Bip34Error::NotPresent)? + .map_err(to_bip34_error)?; + match (push.script_num(), push.push_bytes().map(|b| b.read_scriptint())) { + (Some(num), Some(Ok(_)) | None) => + Ok(num.try_into().map_err(|_| Bip34Error::NegativeHeight)?), + (_, Some(Err(err))) => Err(err.into()), + (None, _) => Err(Bip34Error::NotPresent), + } + } +} + +fn block_base_size(transactions: &[Transaction]) -> usize { + let mut size = Header::SIZE; + + size += compact_size::encoded_size(transactions.len()); + size += transactions.iter().map(|tx| tx.base_size()).sum::(); + + size +} + +impl Encodable for Block { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + // TODO: Should we be able to encode without cloning? + // This is ok, we decode as unchecked anyway. + let block = self.clone().assume_checked(None); + block.consensus_encode(w) + } +} + +impl Encodable for Block { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += self.header().consensus_encode(w)?; + + let transactions = self.transactions(); + len += w.emit_compact_size(transactions.len())?; + for c in transactions.iter() { + len += c.consensus_encode(w)?; + } + + Ok(len) + } +} + +impl Decodable for Block { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let header = Decodable::consensus_decode_from_finite_reader(r)?; + let transactions = Decodable::consensus_decode_from_finite_reader(r)?; + + Ok(Self::new_unchecked(header, transactions)) + } + + #[inline] + fn consensus_decode(r: &mut R) -> Result { + let mut r = io::Read::take(r, internals::ToU64::to_u64(encode::MAX_VEC_SIZE)); + let header = Decodable::consensus_decode(&mut r)?; + let transactions = Decodable::consensus_decode(&mut r)?; + + Ok(Self::new_unchecked(header, transactions)) + } +} + +mod sealed { + /// Seals the extension traits. + pub trait Sealed {} + impl Sealed for super::Header {} + impl Sealed for super::Block {} +} + +/// An error when looking up a BIP-0034 block height. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Bip34Error { + /// The block does not support BIP-0034 yet. + Unsupported, + /// No push was present where the BIP-0034 push was expected. + NotPresent, + /// The BIP-0034 push was not minimally encoded. + NonMinimalPush, + /// The BIP-0034 push was negative. + NegativeHeight, +} + +impl From for Bip34Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Bip34Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Unsupported => write!(f, "block doesn't support BIP-0034"), + Self::NotPresent => write!(f, "BIP-0034 push not present in block's coinbase"), + Self::NonMinimalPush => write!(f, "byte push not minimally encoded"), + Self::NegativeHeight => write!(f, "negative BIP-0034 height"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Bip34Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Unsupported | Self::NotPresent | Self::NonMinimalPush | Self::NegativeHeight => + None, + } + } +} + +impl From for Bip34Error { + #[inline] + fn from(err: ScriptIntError) -> Self { + match err { + ScriptIntError::NonMinimal => Self::NonMinimalPush, + _ => Self::NotPresent, + } + } +} + +#[inline] +fn to_bip34_error(err: script::Error) -> Bip34Error { + match err { + script::Error::NonMinimalPush => Bip34Error::NonMinimalPush, + _ => Bip34Error::NotPresent, + } +} + +/// A block validation error. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ValidationError { + /// The header hash is not below the target. + BadProofOfWork, + /// The `target` field of a block header did not match the expected difficulty. + BadTarget, +} + +impl From for ValidationError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ValidationError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::BadProofOfWork => f.write_str("block target correct but not attained"), + Self::BadTarget => f.write_str("block target incorrect"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ValidationError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::BadProofOfWork | Self::BadTarget => None, + } + } +} + +#[cfg(test)] +mod tests { + use hex_lit::hex; + use internals::ToU64 as _; + use primitives::Wtxid; + + use super::*; + use crate::consensus::encode::{deserialize, serialize}; + use crate::pow::test_utils::{u128_to_work, u64_to_work}; + use crate::script::{ScriptPubKeyBuf, ScriptSigBuf}; + use crate::transaction::{OutPoint, Transaction, TxIn, TxOut, Txid}; + use crate::{block, Amount, CompactTarget, Network, Sequence, TestnetVersion, Witness}; + + #[test] + fn static_vector() { + // testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b + let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw"); + let block: Block = deserialize(&segwit_block[..]).expect("failed to deserialize block"); + assert!(block.check_merkle_root()); + + let (header, transactions) = block.into_parts(); + let block = Block::new_unchecked(header, transactions).assume_checked(None); + + // Same as `block.check_merkle_root` but do it explicitly. + let hashes_iter = block.transactions().iter().map(|obj| obj.compute_txid()); + let from_iter = TxMerkleNode::calculate_root(hashes_iter.clone()); + assert_eq!(from_iter, Some(block.header().merkle_root)); + } + + #[test] + fn coinbase_and_bip34() { + // testnet block 100,000 + const BLOCK_HEX: &str = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3703a08601000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000"; + let block: Block = deserialize(&hex!(BLOCK_HEX)).unwrap(); + let block = block.assume_checked(None); + + let cb_txid = "d574f343976d8e70d91cb278d21044dd8a396019e6db70755a0a50e4783dba38"; + assert_eq!(block.coinbase().compute_txid().to_string(), cb_txid); + + assert_eq!(block.bip34_block_height(), Ok(100_000)); + + // block with 3-byte bip34 push for height 0x03010000 (non-minimal 1) + const BAD_HEX: &str = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3703010000000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000"; + let bad: Block = deserialize(&hex!(BAD_HEX)).unwrap(); + let bad = bad.assume_checked(None); + + assert_eq!(bad.bip34_block_height(), Err(super::Bip34Error::NonMinimalPush)); + + // Block 15 on Testnet4 has height of 0x5f (15 PUSHNUM) + const BLOCK_HEX_SMALL_HEIGHT_15: &str = "000000200fd8c4c1e88f313b561b2724542ff9be1bc54a7dab8db8ef6359d48a00000000705bf9145e6d3c413702cc61f32e4e7bfe3117b1eb928071a59adcf75694a3fb07d83866ffff001dcf4c5e8401010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff095f00062f4077697a2fffffffff0200f2052a010000001976a9140a59837ccd4df25adc31cdad39be6a8d97557ed688ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"; + let block: Block = deserialize(&hex!(BLOCK_HEX_SMALL_HEIGHT_15)).unwrap(); + let block = block.assume_checked(None); + + assert_eq!(block.bip34_block_height(), Ok(15)); + + // Block 42 on Testnet4 has height of 0x012a (42) + const BLOCK_HEX_SMALL_HEIGHT_42: &str = "000000202803addb5a3f42f3e8d6c8536598b2d872b04f3b4f0698c26afdb17300000000463dd9a37a5d3d5c05f9c80a1485b41f1f513dee00338bbc33f5a6e836fce0345dda3866ffff001d872b9def01010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff09012a062f4077697a2fffffffff0200f2052a010000001976a9140a59837ccd4df25adc31cdad39be6a8d97557ed688ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"; + let block: Block = deserialize(&hex!(BLOCK_HEX_SMALL_HEIGHT_42)).unwrap(); + let block = block.assume_checked(None); + + assert_eq!(block.bip34_block_height(), Ok(42)); + + // Block 42 on Testnet4 using OP_PUSHDATA1 0x4c012a (42) instead of 0x012a (42) + const BLOCK_HEX_SMALL_HEIGHT_42_WRONG: &str = "000000202803addb5a3f42f3e8d6c8536598b2d872b04f3b4f0698c26afdb17300000000463dd9a37a5d3d5c05f9c80a1485b41f1f513dee00338bbc33f5a6e836fce0345dda3866ffff001d872b9def01010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0a4c012a062f4077697a2fffffffff0200f2052a010000001976a9140a59837ccd4df25adc31cdad39be6a8d97557ed688ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"; + let block: Block = deserialize(&hex!(BLOCK_HEX_SMALL_HEIGHT_42_WRONG)).unwrap(); + let block = block.assume_checked(None); + + assert_eq!(block.bip34_block_height(), Err(super::Bip34Error::NonMinimalPush)); + + // Block with a 5 byte height properly minimally encoded + // this is an overflow for ScriptNum (i32) parsing + const BLOCK_HEX_5_BYTE_HEIGHT: &str = "000000202803addb5a3f42f3e8d6c8536598b2d872b04f3b4f0698c26afdb17300000000463dd9a37a5d3d5c05f9c80a1485b41f1f513dee00338bbc33f5a6e836fce0345dda3866ffff001d872b9def01010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0d052a2a2a2a2a062f4077697a2fffffffff0200f2052a010000001976a9140a59837ccd4df25adc31cdad39be6a8d97557ed688ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"; + let block: Block = deserialize(&hex!(BLOCK_HEX_5_BYTE_HEIGHT)).unwrap(); + let block = block.assume_checked(None); + + assert_eq!(block.bip34_block_height(), Err(super::Bip34Error::NotPresent)); + } + + #[test] + fn block() { + let params = Params::new(Network::Bitcoin); + // Mainnet block 00000000b0c5a240b2a61d2e75692224efd4cbecdf6eaf4cc2cf477ca7c270e7 + let some_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000"); + let cutoff_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac"); + + let prevhash = hex!("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000"); + let merkle = hex!("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c"); + let work = u128_to_work(0x100010001_u128); + + let decode: Result = deserialize(&some_block); + let bad_decode: Result = deserialize(&cutoff_block); + + assert!(decode.is_ok()); + assert!(bad_decode.is_err()); + + let block = decode.unwrap(); + // should be also ok for a non-witness block as commitment is optional in that case + let (witness_commitment_matches, witness_root) = + block.check_witness_commitment(); + assert!(witness_commitment_matches); + + let (header, transactions) = block.into_parts(); + let real_decode = + Block::new_unchecked(header, transactions.clone()).assume_checked(witness_root); + + assert_eq!(real_decode.header().version, Version::from_consensus(1)); + assert_eq!(serialize(&real_decode.header().prev_blockhash), prevhash); + assert_eq!( + real_decode.header().merkle_root, + block::compute_merkle_root(&transactions).unwrap() + ); + assert_eq!(serialize(&real_decode.header().merkle_root), merkle); + assert_eq!(real_decode.header().time, BlockTime::from_u32(1231965655)); + assert_eq!(real_decode.header().bits, CompactTarget::from_consensus(486604799)); + assert_eq!(real_decode.header().nonce, 2067413810); + assert_eq!(real_decode.header().work(), work); + + assert_eq!(real_decode.header().difficulty(¶ms), 1); + assert_eq!(real_decode.header().difficulty_float(¶ms), 1.0); + + assert_eq!( + real_decode.header().validate_pow(real_decode.header().target()).unwrap(), + real_decode.block_hash() + ); + assert_eq!(real_decode.total_size(), some_block.len()); + assert_eq!(block_base_size(real_decode.transactions()), some_block.len()); + assert_eq!(real_decode.weight(), Weight::from_vb_unchecked(some_block.len().to_u64())); + + assert_eq!(serialize(&real_decode), some_block); + } + + // Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b + #[test] + fn segwit_block() { + let params = Params::new(Network::Testnet(TestnetVersion::V3)); + let segwit_block = include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw").to_vec(); + + let decode: Result = deserialize(&segwit_block); + + let prevhash = hex!("2aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d74906000000000000"); + let merkle = hex!("10bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67e"); + let work = u64_to_work(0x257c3becdacc64_u64); + + assert!(decode.is_ok()); + + let block = decode.unwrap(); + let (witness_commitment_matches, witness_root) = + block.check_witness_commitment(); + assert!(witness_commitment_matches); + + let (header, transactions) = block.into_parts(); + let real_decode = + Block::new_unchecked(header, transactions.clone()).assume_checked(witness_root); + + assert_eq!(real_decode.header().version, Version::from_consensus(0x2000_0000)); // VERSIONBITS but no bits set + assert_eq!(serialize(&real_decode.header().prev_blockhash), prevhash); + assert_eq!(serialize(&real_decode.header().merkle_root), merkle); + assert_eq!( + real_decode.header().merkle_root, + block::compute_merkle_root(&transactions).unwrap() + ); + assert_eq!(real_decode.header().time, BlockTime::from_u32(1472004949)); + assert_eq!(real_decode.header().bits, CompactTarget::from_consensus(0x1a06d450)); + assert_eq!(real_decode.header().nonce, 1879759182); + assert_eq!(real_decode.header().work(), work); + assert_eq!(real_decode.header().difficulty(¶ms), 2456598); + assert_eq!(real_decode.header().difficulty_float(¶ms), 2456598.4399242126); + + assert_eq!( + real_decode.header().validate_pow(real_decode.header().target()).unwrap(), + real_decode.block_hash() + ); + assert_eq!(real_decode.total_size(), segwit_block.len()); + assert_eq!(block_base_size(real_decode.transactions()), 4283); + assert_eq!(real_decode.weight(), Weight::from_wu(17168)); + + assert_eq!(serialize(&real_decode), segwit_block); + } + + #[test] + fn block_version() { + let block = hex!("ffffff7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let decode: Result = deserialize(&block); + assert!(decode.is_ok()); + + let real_decode = decode.unwrap().assume_checked(None); + assert_eq!(real_decode.header().version, Version::from_consensus(2147483647)); + + let block2 = hex!("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let decode2: Result = deserialize(&block2); + assert!(decode2.is_ok()); + let real_decode2 = decode2.unwrap().assume_checked(None); + assert_eq!(real_decode2.header().version, Version::from_consensus(-2147483648)); + } + + #[test] + fn validate_pow() { + let some_header = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b"); + let some_header: Header = + deserialize(&some_header).expect("can't deserialize correct block header"); + assert_eq!( + some_header.validate_pow(some_header.target()).unwrap(), + some_header.block_hash() + ); + + // test with zero target + match some_header.validate_pow(Target::ZERO) { + Err(ValidationError::BadTarget) => (), + _ => panic!("unexpected result from validate_pow"), + } + + // test with modified header + let mut invalid_header: Header = some_header; + invalid_header.version = Version::from_consensus(invalid_header.version.to_consensus() + 1); + match invalid_header.validate_pow(invalid_header.target()) { + Err(ValidationError::BadProofOfWork) => (), + _ => panic!("unexpected result from validate_pow"), + } + } + + fn header() -> Header { + let header = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b"); + deserialize(&header).expect("can't deserialize correct block header") + } + + #[test] + fn compact_roundtrip() { + let header = header(); + assert_eq!(header.bits, header.target().to_compact_lossy()); + } + + #[test] + fn header_block_hash_regression() { + let header = header(); + let block_hash = "00000000b0c5a240b2a61d2e75692224efd4cbecdf6eaf4cc2cf477ca7c270e7"; + + let want = block_hash.parse::().unwrap(); + let got = header.block_hash(); + assert_eq!(got, want) + } + + #[test] + fn soft_fork_signalling() { + for i in 0..31 { + let version_int = (0x20000000u32 ^ (1 << i)) as i32; + let version = Version::from_consensus(version_int); + if i < 29 { + assert!(version.is_signalling_soft_fork(i)); + } else { + assert!(!version.is_signalling_soft_fork(i)); + } + } + + let segwit_signal = Version::from_consensus(0x20000000 ^ (1 << 1)); + assert!(!segwit_signal.is_signalling_soft_fork(0)); + assert!(segwit_signal.is_signalling_soft_fork(1)); + assert!(!segwit_signal.is_signalling_soft_fork(2)); + } + + #[test] + fn block_validation_success_with_coinbase() { + use crate::constants; + + // Use the genesis block which has a valid coinbase + let genesis = constants::genesis_block(Network::Bitcoin); + + let header = *genesis.header(); + let transactions = genesis.transactions().to_vec(); + + let unchecked_block = Block::new_unchecked(header, transactions); + let validated_block = unchecked_block.validate(); + + assert!(validated_block.is_ok(), "Genesis block should validate successfully"); + } + + #[test] + fn checked_block_coinbase_method() { + use crate::constants; + + let genesis = constants::genesis_block(Network::Bitcoin); + let coinbase = genesis.coinbase(); + + // Test that coinbase method returns the expected transaction + let expected_txid = genesis.transactions()[0].compute_txid(); + assert_eq!(coinbase.compute_txid(), expected_txid); + assert_eq!(coinbase.wtxid(), Wtxid::COINBASE); + + // Test that as_inner() returns the correct transaction + assert_eq!(coinbase.as_transaction(), &genesis.transactions()[0]); + } + + #[test] + fn block_new_checked_validation() { + use crate::constants; + + // Test successful validation with genesis block + let genesis = constants::genesis_block(Network::Bitcoin); + let header = *genesis.header(); + let transactions = genesis.transactions().to_vec(); + + let checked_block = Block::new_checked(header, transactions); + assert!(checked_block.is_ok(), "Genesis block should validate via new_checked"); + + // Test validation failure with empty transactions + let empty_result = Block::new_checked(header, Vec::new()); + match empty_result { + Err(InvalidBlockError::NoTransactions) => (), + other => panic!("Expected NoTransactions error, got: {:?}", other), + } + + // Test validation failure with invalid coinbase + let non_coinbase_tx = Transaction { + version: primitives::transaction::Version::TWO, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { + txid: Txid::from_byte_array([1; 32]), // Not all zeros + vout: 0, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_AND_RBF, + witness: Witness::new(), + }], + outputs: vec![TxOut { amount: Amount::ONE_BTC, script_pubkey: ScriptPubKeyBuf::new() }], + }; + + let invalid_coinbase_result = Block::new_checked(header, vec![non_coinbase_tx]); + match invalid_coinbase_result { + Err(InvalidBlockError::InvalidCoinbase) => (), + other => panic!("Expected InvalidCoinbase error, got: {:?}", other), + } + } + + #[test] + fn coinbase_bip34_height_with_coinbase_type() { + // testnet block 100,000 + const BLOCK_HEX: &str = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3703a08601000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000"; + let block: Block = deserialize(&hex!(BLOCK_HEX)).unwrap(); + let block = block.assume_checked(None); + + // Test that BIP-0034 height extraction works with the Coinbase type + assert_eq!(block.bip34_block_height(), Ok(100_000)); + + // Test that coinbase method returns a Coinbase type + let coinbase = block.coinbase(); + assert!(coinbase.as_transaction().is_coinbase()); + + // Test that the coinbase transaction ID matches expected + let cb_txid = "d574f343976d8e70d91cb278d21044dd8a396019e6db70755a0a50e4783dba38"; + assert_eq!(coinbase.compute_txid().to_string(), cb_txid); + } +} diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs new file mode 100644 index 000000000..d44d35aeb --- /dev/null +++ b/bitcoin/src/blockdata/constants.rs @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Blockdata constants. +//! +//! This module provides various constants relating to the blockchain and +//! consensus code. In particular, it defines the genesis block and its +//! single transaction. + +use crate::block::{self, Block, Checked}; +use crate::internal_macros::impl_array_newtype_stringify; +use crate::locktime::absolute; +use crate::network::{Network, Params}; +use crate::opcodes::all::*; +use crate::pow::CompactTarget; +use crate::transaction::{self, OutPoint, Transaction, TxIn, TxOut}; +use crate::witness::Witness; +use crate::{script, Amount, BlockHash, BlockTime, Sequence, TestnetVersion}; + +/// How many seconds between blocks we expect on average. +pub const TARGET_BLOCK_SPACING: u32 = 600; +/// How many blocks between diffchanges. +pub const DIFFCHANGE_INTERVAL: u32 = 2016; +/// How much time on average should occur between diffchanges. +pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600; + +/// The factor that non-witness serialization data is multiplied by during weight calculation. +pub const WITNESS_SCALE_FACTOR: usize = units::weight::WITNESS_SCALE_FACTOR; +/// The maximum allowed number of signature check operations in a block. +pub const MAX_BLOCK_SIGOPS_COST: i64 = 80_000; +/// Mainnet (bitcoin) pubkey address prefix. +pub const PUBKEY_ADDRESS_PREFIX_MAIN: u8 = 0; // 0x00 +/// Mainnet (bitcoin) script address prefix. +pub const SCRIPT_ADDRESS_PREFIX_MAIN: u8 = 5; // 0x05 +/// Test (testnet, signet, regtest) pubkey address prefix. +pub const PUBKEY_ADDRESS_PREFIX_TEST: u8 = 111; // 0x6f +/// Test (testnet, signet, regtest) script address prefix. +pub const SCRIPT_ADDRESS_PREFIX_TEST: u8 = 196; // 0xc4 +/// The maximum allowed redeem script size for a P2SH output. +pub const MAX_REDEEM_SCRIPT_SIZE: usize = primitives::script::MAX_REDEEM_SCRIPT_SIZE; // 520 +/// The maximum allowed redeem script size of the witness script. +pub const MAX_WITNESS_SCRIPT_SIZE: usize = primitives::script::MAX_WITNESS_SCRIPT_SIZE; // 10_000 +/// The maximum allowed size of any single witness stack element. +pub const MAX_STACK_ELEMENT_SIZE: usize = 520; +/// How many blocks between halvings. +pub const SUBSIDY_HALVING_INTERVAL: u32 = 210_000; +/// Maximum allowed value for an integer in Script. +/// This constant has ambiguous semantics. Please carefully check your intended use-case and define +/// a new constant reflecting that. +#[deprecated(since = "TBD", note = "use a more specific constant instead")] +pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31 +/// Number of blocks needed for an output from a coinbase transaction to be spendable. +pub const COINBASE_MATURITY: u32 = 100; +/// The maximum allowed size for a serialized block, in bytes (only for buffer size limits) +pub const MAX_BLOCK_SERIALIZED_SIZE: usize = 4_000_000; + +// This is the 65 byte (uncompressed) pubkey used as the one-and-only output of the genesis transaction. +// +// ref: https://blockstream.info/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b?expand +// Note output script includes a leading 0x41 and trailing 0xac (added below using the `script::Builder`). +#[rustfmt::skip] +const GENESIS_OUTPUT_PK: [u8; 65] = [ + 0x04, + 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, + 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7, 0x10, + 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, + 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde, 0xb6, + 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, + 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12, 0xde, + 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, + 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f +]; + +#[rustfmt::skip] +const TESTNET4_GENESIS_OUTPUT_PK: [u8; 33] = [0x00; 33]; + +/// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block. +fn bitcoin_genesis_tx(params: &Params) -> Transaction { + // Base + let mut ret = Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![], + outputs: vec![], + }; + + let (in_script, out_script) = { + match params.network { + Network::Testnet(TestnetVersion::V4) => ( + script::Builder::new() + .push_int_unchecked(486604799) + .push_int_non_minimal(4) + .push_slice(b"03/May/2024 000000000000000000001ebd58c244970b3aa9d783bb001011fbe8ea8e98e00e") + .into_script(), + script::Builder::new().push_slice(TESTNET4_GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(), + + ), + _ => ( + script::Builder::new() + .push_int_unchecked(486604799) + .push_int_non_minimal(4) + .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") + .into_script(), + script::Builder::new().push_slice(GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(), + ), + } + }; + + ret.inputs.push(TxIn { + previous_output: OutPoint::COINBASE_PREVOUT, + script_sig: in_script, + sequence: Sequence::MAX, + witness: Witness::default(), + }); + + ret.outputs.push(TxOut { amount: Amount::FIFTY_BTC, script_pubkey: out_script }); + + // end + ret +} + +/// Constructs and returns the genesis block. +pub fn genesis_block(params: impl AsRef) -> Block { + let params = params.as_ref(); + let transactions = vec![bitcoin_genesis_tx(params)]; + let merkle_root = block::compute_merkle_root(&transactions).expect("transactions is not empty"); + let witness_root = block::compute_witness_root(&transactions); + + match params.network { + Network::Bitcoin => Block::new_unchecked( + block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, + merkle_root, + time: BlockTime::from_u32(1231006505), + bits: CompactTarget::from_consensus(0x1d00ffff), + nonce: 2083236893, + }, + transactions, + ) + .assume_checked(witness_root), + Network::Testnet(TestnetVersion::V3) => Block::new_unchecked( + block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, + merkle_root, + time: BlockTime::from_u32(1296688602), + bits: CompactTarget::from_consensus(0x1d00ffff), + nonce: 414098458, + }, + transactions, + ) + .assume_checked(witness_root), + Network::Testnet(TestnetVersion::V4) => Block::new_unchecked( + block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, + merkle_root, + time: BlockTime::from_u32(1714777860), + bits: CompactTarget::from_consensus(0x1d00ffff), + nonce: 393743547, + }, + transactions, + ) + .assume_checked(witness_root), + Network::Signet => Block::new_unchecked( + block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, + merkle_root, + time: BlockTime::from_u32(1598918400), + bits: CompactTarget::from_consensus(0x1e0377ae), + nonce: 52613770, + }, + transactions, + ) + .assume_checked(witness_root), + Network::Regtest => Block::new_unchecked( + block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::GENESIS_PREVIOUS_BLOCK_HASH, + merkle_root, + time: BlockTime::from_u32(1296688602), + bits: CompactTarget::from_consensus(0x207fffff), + nonce: 2, + }, + transactions, + ) + .assume_checked(witness_root), + } +} + +/// The uniquely identifying hash of the target blockchain. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ChainHash([u8; 32]); +internals::impl_array_newtype!(ChainHash, u8, 32); +impl_array_newtype_stringify!(ChainHash, 32); + +impl ChainHash { + // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md + /// `ChainHash` for mainnet bitcoin. + pub const BITCOIN: Self = Self([ + 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131, + 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, + ]); + /// `ChainHash` for testnet3 bitcoin. + #[deprecated(since = "TBD", note = "use `TESTNET3` instead")] + pub const TESTNET: Self = Self([ + 67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, + 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0, + ]); + /// `ChainHash` for testnet3 bitcoin. + pub const TESTNET3: Self = Self([ + 67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, + 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0, + ]); + /// `ChainHash` for testnet4 bitcoin. + pub const TESTNET4: Self = Self([ + 67, 240, 139, 218, 176, 80, 227, 91, 86, 124, 134, 75, 145, 244, 127, 80, 174, 114, 90, + 226, 222, 83, 188, 251, 186, 242, 132, 218, 0, 0, 0, 0, + ]); + /// `ChainHash` for signet bitcoin. + pub const SIGNET: Self = Self([ + 246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, + 240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0, + ]); + /// `ChainHash` for regtest bitcoin. + pub const REGTEST: Self = Self([ + 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, + 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15, + ]); + + /// Returns the hash of the `network` genesis block for use as a chain hash. + /// + /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash) + /// for specification. + pub fn using_genesis_block(params: impl AsRef) -> Self { + match params.as_ref().network { + Network::Bitcoin => Self::BITCOIN, + Network::Testnet(TestnetVersion::V3) => Self::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Self::TESTNET4, + Network::Signet => Self::SIGNET, + Network::Regtest => Self::REGTEST, + } + } + + /// Returns the hash of the `network` genesis block for use as a chain hash. + /// + /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash) + /// for specification. + pub const fn using_genesis_block_const(network: Network) -> Self { + match network { + Network::Bitcoin => Self::BITCOIN, + Network::Testnet(TestnetVersion::V3) => Self::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Self::TESTNET4, + Network::Signet => Self::SIGNET, + Network::Regtest => Self::REGTEST, + } + } + + /// Converts genesis block hash into `ChainHash`. + pub fn from_genesis_block_hash(block_hash: crate::BlockHash) -> Self { + Self(block_hash.to_byte_array()) + } + + /// Copies the underlying bytes into a new `Vec`. + #[inline] + #[deprecated(since = "TBD", note = "use to_vec instead")] + pub fn to_bytes(self) -> alloc::vec::Vec { self.to_vec() } +} + +#[cfg(test)] +mod test { + use hex_lit::hex; + + use super::*; + use crate::consensus::encode::serialize; + use crate::network::params; + use crate::Txid; + + #[test] + fn bitcoin_genesis_first_transaction() { + let gen = bitcoin_genesis_tx(&Params::MAINNET); + + assert_eq!(gen.version, transaction::Version::ONE); + assert_eq!(gen.inputs.len(), 1); + assert_eq!(gen.inputs[0].previous_output.txid, Txid::COINBASE_PREVOUT); + assert_eq!(gen.inputs[0].previous_output.vout, 0xFFFFFFFF); + assert_eq!(serialize(&gen.inputs[0].script_sig), + hex!("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73")); + + assert_eq!(gen.inputs[0].sequence, Sequence::MAX); + assert_eq!(gen.outputs.len(), 1); + assert_eq!(serialize(&gen.outputs[0].script_pubkey), + hex!("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac")); + assert_eq!(gen.outputs[0].amount, "50 BTC".parse::().unwrap()); + assert_eq!(gen.lock_time, absolute::LockTime::ZERO); + + assert_eq!( + gen.compute_wtxid().to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); + } + + #[test] + fn bitcoin_genesis_block_calling_convention() { + // This is the best. + let _ = genesis_block(¶ms::MAINNET); + // this works and is ok too. + let _ = genesis_block(Network::Bitcoin); + let _ = genesis_block(Network::Bitcoin); + // This works too, but is suboptimal because it inlines the const. + let _ = genesis_block(Params::MAINNET); + let _ = genesis_block(&Params::MAINNET); + } + + #[test] + fn bitcoin_genesis_full_block() { + let gen = genesis_block(¶ms::MAINNET); + + assert_eq!(gen.header().version, block::Version::ONE); + assert_eq!(gen.header().prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); + assert_eq!( + gen.header().merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); + + assert_eq!(gen.header().time, BlockTime::from_u32(1231006505)); + assert_eq!(gen.header().bits, CompactTarget::from_consensus(0x1d00ffff)); + assert_eq!(gen.header().nonce, 2083236893); + assert_eq!( + gen.header().block_hash().to_string(), + "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" + ); + } + + #[test] + fn testnet_genesis_full_block() { + let gen = genesis_block(¶ms::TESTNET3); + assert_eq!(gen.header().version, block::Version::ONE); + assert_eq!(gen.header().prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); + assert_eq!( + gen.header().merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); + assert_eq!(gen.header().time, BlockTime::from_u32(1296688602)); + assert_eq!(gen.header().bits, CompactTarget::from_consensus(0x1d00ffff)); + assert_eq!(gen.header().nonce, 414098458); + assert_eq!( + gen.header().block_hash().to_string(), + "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943" + ); + } + + #[test] + fn signet_genesis_full_block() { + let gen = genesis_block(¶ms::SIGNET); + assert_eq!(gen.header().version, block::Version::ONE); + assert_eq!(gen.header().prev_blockhash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); + assert_eq!( + gen.header().merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); + assert_eq!(gen.header().time, BlockTime::from_u32(1598918400)); + assert_eq!(gen.header().bits, CompactTarget::from_consensus(0x1e0377ae)); + assert_eq!(gen.header().nonce, 52613770); + assert_eq!( + gen.header().block_hash().to_string(), + "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6" + ); + } + + // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array + // representing the genesis block is the same as that created by hashing the genesis block. + fn chain_hash_and_genesis_block(network: Network) { + use hashes::sha256; + + // The genesis block hash is a double-sha256 and it is displayed backwards. + let genesis_hash = genesis_block(network).block_hash(); + // We abuse the sha256 hash here so we get a LowerHex impl that does not print the hex backwards. + let hash = sha256::Hash::from_byte_array(genesis_hash.to_byte_array()); + let want = format!("{:02x}", hash); + + let chain_hash = ChainHash::using_genesis_block_const(network); + let got = format!("{:02x}", chain_hash); + + // Compare strings because the spec specifically states how the chain hash must encode to hex. + assert_eq!(got, want); + + #[allow(unreachable_patterns)] // This is specifically trying to catch later added variants. + match network { + Network::Bitcoin => {}, + Network::Testnet(TestnetVersion::V3) => {}, + Network::Testnet(TestnetVersion::V4) => {}, + Network::Signet => {}, + Network::Regtest => {}, + _ => panic!("update ChainHash::using_genesis_block and chain_hash_and_genesis_block with new variants"), + } + } + + macro_rules! chain_hash_genesis_block { + ($($test_name:ident, $network:expr);* $(;)*) => { + $( + #[test] + fn $test_name() { + chain_hash_and_genesis_block($network); + } + )* + } + } + + chain_hash_genesis_block! { + mainnet_chain_hash_genesis_block, Network::Bitcoin; + testnet_chain_hash_genesis_block, Network::Testnet(TestnetVersion::V3); + testnet4_chain_hash_genesis_block, Network::Testnet(TestnetVersion::V4); + signet_chain_hash_genesis_block, Network::Signet; + regtest_chain_hash_genesis_block, Network::Regtest; + } + + // Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md + #[test] + fn mainnet_chain_hash_test_vector() { + let got = ChainHash::using_genesis_block_const(Network::Bitcoin).to_string(); + let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"; + assert_eq!(got, want); + } +} diff --git a/bitcoin/src/blockdata/mod.rs b/bitcoin/src/blockdata/mod.rs new file mode 100644 index 000000000..bc18d858e --- /dev/null +++ b/bitcoin/src/blockdata/mod.rs @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin block data. +//! +//! This module defines structures and functions for storing the blocks and +//! transactions which make up the Bitcoin system. + +pub mod block; +pub mod constants; +pub mod opcodes; +pub mod script; +pub mod transaction; +pub mod witness; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + fee_rate::FeeRate, + weight::Weight +}; + +/// Implements `FeeRate` and associated features. +pub mod fee_rate { + #[cfg(feature = "serde")] + pub use units::fee_rate::serde; + /// Re-export everything from the [`units::fee_rate`] module. + pub use units::fee_rate::FeeRate; +} + +/// Provides absolute and relative locktimes. +pub mod locktime { + pub mod absolute { + //! Provides type [`LockTime`] that implements the logic around nLockTime/OP_CHECKLOCKTIMEVERIFY. + //! + //! There are two types of lock time: lock-by-height and lock-by-time, distinguished by + //! whether `LockTime < LOCKTIME_THRESHOLD`. + + use io::{BufRead, Write}; + + pub use crate::consensus::encode::{self, Decodable, Encodable}; + + /// Re-export everything from the `units::locktime::absolute` module. + #[rustfmt::skip] // Keep public re-exports separate. + #[doc(inline)] + pub use units::locktime::absolute::{error, Height, LockTime, MedianTimePast}; + #[doc(no_inline)] + pub use units::locktime::absolute::{ + ConversionError, IncompatibleHeightError, IncompatibleTimeError, ParseHeightError, ParseTimeError, + }; + + #[deprecated(since = "TBD", note = "use `MedianTimePast` instead")] + #[doc(hidden)] + pub type Time = MedianTimePast; + + impl Encodable for LockTime { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + let v = self.to_consensus_u32(); + v.consensus_encode(w) + } + } + + impl Decodable for LockTime { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + u32::consensus_decode(r).map(Self::from_consensus) + } + } + } + + pub mod relative { + //! Provides type [`LockTime`] that implements the logic around nSequence/OP_CHECKSEQUENCEVERIFY. + //! + //! There are two types of lock time: lock-by-height and lock-by-time, distinguished by + //! whether bit 22 of the `u32` consensus value is set. + + /// Re-export everything from the `units::locktime::relative` module. + #[doc(inline)] + pub use units::locktime::relative::{ + error, LockTime, NumberOf512Seconds, NumberOfBlocks, + }; + #[doc(no_inline)] + pub use units::locktime::relative::{ + DisabledLockTimeError, InvalidHeightError, InvalidTimeError, IsSatisfiedByError, + IsSatisfiedByHeightError, IsSatisfiedByTimeError, TimeOverflowError, + }; + + #[deprecated(since = "TBD", note = "use `NumberOfBlocks` instead")] + #[doc(hidden)] + pub type Height = NumberOfBlocks; + + #[deprecated(since = "TBD", note = "use `NumberOf512Seconds` instead")] + #[doc(hidden)] + pub type Time = NumberOf512Seconds; + } +} + +/// Implements `Weight` and associated features. +pub mod weight { + /// Re-export everything from the [`units::weight`] module. + pub use units::weight::Weight; +} diff --git a/bitcoin/src/blockdata/opcodes.rs b/bitcoin/src/blockdata/opcodes.rs new file mode 100644 index 000000000..764d37f8f --- /dev/null +++ b/bitcoin/src/blockdata/opcodes.rs @@ -0,0 +1,970 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin script opcodes. +//! +//! Bitcoin's script uses a stack-based assembly language. This module defines +//! all of the opcodes for that language. + +#![allow(non_camel_case_types)] + +use core::fmt; + +/// A script Opcode. +/// +/// We do not implement Ord on this type because there is no natural ordering on opcodes, but there +/// may appear to be one (e.g. because all the push opcodes appear in a consecutive block) and we +/// don't want to encourage subtly buggy code. Please use [`Opcode::classify`] to distinguish different +/// types of opcodes. +/// +///
+/// Example of Core bug caused by assuming ordering +/// +/// Bitcoin Core's `IsPushOnly` considers `OP_RESERVED` to be a "push code", allowing this opcode +/// in contexts where only pushes are supposed to be allowed. +///
+#[derive(Copy, Clone, PartialEq, Eq)] +pub struct Opcode { + code: u8, +} + +use self::all::*; + +macro_rules! all_opcodes { + ($($op:ident => $val:expr, $doc:expr);*) => { + /// Enables wildcard imports to bring into scope all opcodes and nothing else. + /// + /// The `all` module is provided so one can use a wildcard import `use bitcoin::opcodes::all::*` to + /// get all the `OP_FOO` opcodes without getting other types defined in `opcodes` (e.g. `Opcode`, `Class`). + /// + /// This module is guaranteed to never contain anything except opcode constants and all opcode + /// constants are guaranteed to begin with OP_. + pub mod all { + use super::Opcode; + $( + #[doc = $doc] + pub const $op: Opcode = Opcode { code: $val}; + )* + + impl Opcode { + /// Returns the string representation of the opcode. + /// + /// This function maps the `Opcode`'s `code` value (a `u8`) to its corresponding + /// Bitcoin Script opcode name. + /// + /// # Example + /// ``` + /// use bitcoin::opcodes::all::*; + /// + /// assert_eq!(OP_1.as_str(), "OP_1"); + /// assert_eq!(OP_1NEGATE.as_str(), "OP_1NEGATE"); + /// assert_eq!(OP_CHECKMULTISIG.as_str(), "OP_CHECKMULTISIG"); + /// ``` + #[inline] + pub fn as_str(&self) -> &'static str { + match *self { + $( + $op => stringify!($op), + )+ + } + } + } + + /// Push an empty array onto the stack. + pub const OP_0: Opcode = OP_PUSHBYTES_0; + /// Empty stack is also FALSE. + pub const OP_FALSE: Opcode = OP_PUSHBYTES_0; + /// Number 1 is also TRUE. + pub const OP_TRUE: Opcode = OP_1; + /// Previously called OP_NOP2. + pub const OP_NOP2: Opcode = OP_CLTV; + /// Previously called OP_NOP3. + pub const OP_NOP3: Opcode = OP_CSV; + + /// Push the array `0x81` onto the stack. + #[deprecated(since = "TBD", note = "use OP_1NEGATE instead")] + pub const OP_PUSHNUM_NEG1: Opcode = OP_1NEGATE; + /// Push the array `0x01` onto the stack. + #[deprecated(since = "TBD", note = "use OP_1 instead")] + pub const OP_PUSHNUM_1: Opcode = OP_1; + /// Push the array `0x02` onto the stack. + #[deprecated(since = "TBD", note = "use OP_2 instead")] + pub const OP_PUSHNUM_2: Opcode = OP_2; + /// Push the array `0x03` onto the stack. + #[deprecated(since = "TBD", note = "use OP_3 instead")] + pub const OP_PUSHNUM_3: Opcode = OP_3; + /// Push the array `0x04` onto the stack. + #[deprecated(since = "TBD", note = "use OP_4 instead")] + pub const OP_PUSHNUM_4: Opcode = OP_4; + /// Push the array `0x05` onto the stack. + #[deprecated(since = "TBD", note = "use OP_5 instead")] + pub const OP_PUSHNUM_5: Opcode = OP_5; + /// Push the array `0x06` onto the stack. + #[deprecated(since = "TBD", note = "use OP_6 instead")] + pub const OP_PUSHNUM_6: Opcode = OP_6; + /// Push the array `0x07` onto the stack. + #[deprecated(since = "TBD", note = "use OP_7 instead")] + pub const OP_PUSHNUM_7: Opcode = OP_7; + /// Push the array `0x08` onto the stack. + #[deprecated(since = "TBD", note = "use OP_8 instead")] + pub const OP_PUSHNUM_8: Opcode = OP_8; + /// Push the array `0x09` onto the stack. + #[deprecated(since = "TBD", note = "use OP_9 instead")] + pub const OP_PUSHNUM_9: Opcode = OP_9; + /// Push the array `0x0a` onto the stack. + #[deprecated(since = "TBD", note = "use OP_10 instead")] + pub const OP_PUSHNUM_10: Opcode = OP_10; + /// Push the array `0x0b` onto the stack. + #[deprecated(since = "TBD", note = "use OP_11 instead")] + pub const OP_PUSHNUM_11: Opcode = OP_11; + /// Push the array `0x0c` onto the stack. + #[deprecated(since = "TBD", note = "use OP_12 instead")] + pub const OP_PUSHNUM_12: Opcode = OP_12; + /// Push the array `0x0d` onto the stack. + #[deprecated(since = "TBD", note = "use OP_13 instead")] + pub const OP_PUSHNUM_13: Opcode = OP_13; + /// Push the array `0x0e` onto the stack. + #[deprecated(since = "TBD", note = "use OP_14 instead")] + pub const OP_PUSHNUM_14: Opcode = OP_14; + /// Push the array `0x0f` onto the stack. + #[deprecated(since = "TBD", note = "use OP_15 instead")] + pub const OP_PUSHNUM_15: Opcode = OP_15; + /// Push the array `0x10` onto the stack. + #[deprecated(since = "TBD", note = "use OP_16 instead")] + pub const OP_PUSHNUM_16: Opcode = OP_16; + } + + impl fmt::Display for Opcode { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Display::fmt(self.as_str(), f) + } + } + } +} + +all_opcodes! { + OP_PUSHBYTES_0 => 0x00, "Push an empty array onto the stack."; + OP_PUSHBYTES_1 => 0x01, "Push the next byte as an array onto the stack."; + OP_PUSHBYTES_2 => 0x02, "Push the next 2 bytes as an array onto the stack."; + OP_PUSHBYTES_3 => 0x03, "Push the next 3 bytes as an array onto the stack."; + OP_PUSHBYTES_4 => 0x04, "Push the next 4 bytes as an array onto the stack."; + OP_PUSHBYTES_5 => 0x05, "Push the next 5 bytes as an array onto the stack."; + OP_PUSHBYTES_6 => 0x06, "Push the next 6 bytes as an array onto the stack."; + OP_PUSHBYTES_7 => 0x07, "Push the next 7 bytes as an array onto the stack."; + OP_PUSHBYTES_8 => 0x08, "Push the next 8 bytes as an array onto the stack."; + OP_PUSHBYTES_9 => 0x09, "Push the next 9 bytes as an array onto the stack."; + OP_PUSHBYTES_10 => 0x0a, "Push the next 10 bytes as an array onto the stack."; + OP_PUSHBYTES_11 => 0x0b, "Push the next 11 bytes as an array onto the stack."; + OP_PUSHBYTES_12 => 0x0c, "Push the next 12 bytes as an array onto the stack."; + OP_PUSHBYTES_13 => 0x0d, "Push the next 13 bytes as an array onto the stack."; + OP_PUSHBYTES_14 => 0x0e, "Push the next 14 bytes as an array onto the stack."; + OP_PUSHBYTES_15 => 0x0f, "Push the next 15 bytes as an array onto the stack."; + OP_PUSHBYTES_16 => 0x10, "Push the next 16 bytes as an array onto the stack."; + OP_PUSHBYTES_17 => 0x11, "Push the next 17 bytes as an array onto the stack."; + OP_PUSHBYTES_18 => 0x12, "Push the next 18 bytes as an array onto the stack."; + OP_PUSHBYTES_19 => 0x13, "Push the next 19 bytes as an array onto the stack."; + OP_PUSHBYTES_20 => 0x14, "Push the next 20 bytes as an array onto the stack."; + OP_PUSHBYTES_21 => 0x15, "Push the next 21 bytes as an array onto the stack."; + OP_PUSHBYTES_22 => 0x16, "Push the next 22 bytes as an array onto the stack."; + OP_PUSHBYTES_23 => 0x17, "Push the next 23 bytes as an array onto the stack."; + OP_PUSHBYTES_24 => 0x18, "Push the next 24 bytes as an array onto the stack."; + OP_PUSHBYTES_25 => 0x19, "Push the next 25 bytes as an array onto the stack."; + OP_PUSHBYTES_26 => 0x1a, "Push the next 26 bytes as an array onto the stack."; + OP_PUSHBYTES_27 => 0x1b, "Push the next 27 bytes as an array onto the stack."; + OP_PUSHBYTES_28 => 0x1c, "Push the next 28 bytes as an array onto the stack."; + OP_PUSHBYTES_29 => 0x1d, "Push the next 29 bytes as an array onto the stack."; + OP_PUSHBYTES_30 => 0x1e, "Push the next 30 bytes as an array onto the stack."; + OP_PUSHBYTES_31 => 0x1f, "Push the next 31 bytes as an array onto the stack."; + OP_PUSHBYTES_32 => 0x20, "Push the next 32 bytes as an array onto the stack."; + OP_PUSHBYTES_33 => 0x21, "Push the next 33 bytes as an array onto the stack."; + OP_PUSHBYTES_34 => 0x22, "Push the next 34 bytes as an array onto the stack."; + OP_PUSHBYTES_35 => 0x23, "Push the next 35 bytes as an array onto the stack."; + OP_PUSHBYTES_36 => 0x24, "Push the next 36 bytes as an array onto the stack."; + OP_PUSHBYTES_37 => 0x25, "Push the next 37 bytes as an array onto the stack."; + OP_PUSHBYTES_38 => 0x26, "Push the next 38 bytes as an array onto the stack."; + OP_PUSHBYTES_39 => 0x27, "Push the next 39 bytes as an array onto the stack."; + OP_PUSHBYTES_40 => 0x28, "Push the next 40 bytes as an array onto the stack."; + OP_PUSHBYTES_41 => 0x29, "Push the next 41 bytes as an array onto the stack."; + OP_PUSHBYTES_42 => 0x2a, "Push the next 42 bytes as an array onto the stack."; + OP_PUSHBYTES_43 => 0x2b, "Push the next 43 bytes as an array onto the stack."; + OP_PUSHBYTES_44 => 0x2c, "Push the next 44 bytes as an array onto the stack."; + OP_PUSHBYTES_45 => 0x2d, "Push the next 45 bytes as an array onto the stack."; + OP_PUSHBYTES_46 => 0x2e, "Push the next 46 bytes as an array onto the stack."; + OP_PUSHBYTES_47 => 0x2f, "Push the next 47 bytes as an array onto the stack."; + OP_PUSHBYTES_48 => 0x30, "Push the next 48 bytes as an array onto the stack."; + OP_PUSHBYTES_49 => 0x31, "Push the next 49 bytes as an array onto the stack."; + OP_PUSHBYTES_50 => 0x32, "Push the next 50 bytes as an array onto the stack."; + OP_PUSHBYTES_51 => 0x33, "Push the next 51 bytes as an array onto the stack."; + OP_PUSHBYTES_52 => 0x34, "Push the next 52 bytes as an array onto the stack."; + OP_PUSHBYTES_53 => 0x35, "Push the next 53 bytes as an array onto the stack."; + OP_PUSHBYTES_54 => 0x36, "Push the next 54 bytes as an array onto the stack."; + OP_PUSHBYTES_55 => 0x37, "Push the next 55 bytes as an array onto the stack."; + OP_PUSHBYTES_56 => 0x38, "Push the next 56 bytes as an array onto the stack."; + OP_PUSHBYTES_57 => 0x39, "Push the next 57 bytes as an array onto the stack."; + OP_PUSHBYTES_58 => 0x3a, "Push the next 58 bytes as an array onto the stack."; + OP_PUSHBYTES_59 => 0x3b, "Push the next 59 bytes as an array onto the stack."; + OP_PUSHBYTES_60 => 0x3c, "Push the next 60 bytes as an array onto the stack."; + OP_PUSHBYTES_61 => 0x3d, "Push the next 61 bytes as an array onto the stack."; + OP_PUSHBYTES_62 => 0x3e, "Push the next 62 bytes as an array onto the stack."; + OP_PUSHBYTES_63 => 0x3f, "Push the next 63 bytes as an array onto the stack."; + OP_PUSHBYTES_64 => 0x40, "Push the next 64 bytes as an array onto the stack."; + OP_PUSHBYTES_65 => 0x41, "Push the next 65 bytes as an array onto the stack."; + OP_PUSHBYTES_66 => 0x42, "Push the next 66 bytes as an array onto the stack."; + OP_PUSHBYTES_67 => 0x43, "Push the next 67 bytes as an array onto the stack."; + OP_PUSHBYTES_68 => 0x44, "Push the next 68 bytes as an array onto the stack."; + OP_PUSHBYTES_69 => 0x45, "Push the next 69 bytes as an array onto the stack."; + OP_PUSHBYTES_70 => 0x46, "Push the next 70 bytes as an array onto the stack."; + OP_PUSHBYTES_71 => 0x47, "Push the next 71 bytes as an array onto the stack."; + OP_PUSHBYTES_72 => 0x48, "Push the next 72 bytes as an array onto the stack."; + OP_PUSHBYTES_73 => 0x49, "Push the next 73 bytes as an array onto the stack."; + OP_PUSHBYTES_74 => 0x4a, "Push the next 74 bytes as an array onto the stack."; + OP_PUSHBYTES_75 => 0x4b, "Push the next 75 bytes as an array onto the stack."; + OP_PUSHDATA1 => 0x4c, "Read the next byte as N; push the next N bytes as an array onto the stack."; + OP_PUSHDATA2 => 0x4d, "Read the next 2 bytes as N; push the next N bytes as an array onto the stack."; + OP_PUSHDATA4 => 0x4e, "Read the next 4 bytes as N; push the next N bytes as an array onto the stack."; + OP_1NEGATE => 0x4f, "Push the array `0x81` onto the stack."; + OP_RESERVED => 0x50, "Synonym for `OP_RETURN`."; + OP_1 => 0x51, "Push the array `0x01` onto the stack."; + OP_2 => 0x52, "Push the array `0x02` onto the stack."; + OP_3 => 0x53, "Push the array `0x03` onto the stack."; + OP_4 => 0x54, "Push the array `0x04` onto the stack."; + OP_5 => 0x55, "Push the array `0x05` onto the stack."; + OP_6 => 0x56, "Push the array `0x06` onto the stack."; + OP_7 => 0x57, "Push the array `0x07` onto the stack."; + OP_8 => 0x58, "Push the array `0x08` onto the stack."; + OP_9 => 0x59, "Push the array `0x09` onto the stack."; + OP_10 => 0x5a, "Push the array `0x0a` onto the stack."; + OP_11 => 0x5b, "Push the array `0x0b` onto the stack."; + OP_12 => 0x5c, "Push the array `0x0c` onto the stack."; + OP_13 => 0x5d, "Push the array `0x0d` onto the stack."; + OP_14 => 0x5e, "Push the array `0x0e` onto the stack."; + OP_15 => 0x5f, "Push the array `0x0f` onto the stack."; + OP_16 => 0x60, "Push the array `0x10` onto the stack."; + OP_NOP => 0x61, "Does nothing."; + OP_VER => 0x62, "Synonym for `OP_RETURN`."; + OP_IF => 0x63, "Pop and execute the next statements if a nonzero element was popped."; + OP_NOTIF => 0x64, "Pop and execute the next statements if a zero element was popped."; + OP_VERIF => 0x65, "Fail the script unconditionally, does not even need to be executed."; + OP_VERNOTIF => 0x66, "Fail the script unconditionally, does not even need to be executed."; + OP_ELSE => 0x67, "Execute statements if those after the previous `OP_IF` were not, and vice-versa. \ + If there is no previous `OP_IF`, this acts as a RETURN."; + OP_ENDIF => 0x68, "Pop and execute the next statements if a zero element was popped."; + OP_VERIFY => 0x69, "If the top value is zero or the stack is empty, fail; otherwise, pop the stack."; + OP_RETURN => 0x6a, "Fail the script immediately. (Must be executed.)."; + OP_TOALTSTACK => 0x6b, "Pop one element from the main stack onto the alt stack."; + OP_FROMALTSTACK => 0x6c, "Pop one element from the alt stack onto the main stack."; + OP_2DROP => 0x6d, "Drops the top two stack items."; + OP_2DUP => 0x6e, "Duplicates the top two stack items as `AB` -> `ABAB`."; + OP_3DUP => 0x6f, "Duplicates the top three stack items as `ABC` -> `ABCABC`."; + OP_2OVER => 0x70, "Duplicates the third and fourth items from the top of the stack."; + OP_2ROT => 0x71, "Moves the two stack items four spaces back to the front, as `xxxxAB` -> `ABxxxx`."; + OP_2SWAP => 0x72, "Swaps the top two pairs, as `ABCD` -> `CDAB`."; + OP_IFDUP => 0x73, "Duplicate the top stack element unless it is zero."; + OP_DEPTH => 0x74, "Push the current number of stack items onto the stack."; + OP_DROP => 0x75, "Drops the top stack item."; + OP_DUP => 0x76, "Duplicates the top stack item."; + OP_NIP => 0x77, "Drops the second-to-top stack item."; + OP_OVER => 0x78, "Copies the second-to-top stack item, as `xA` -> `AxA`."; + OP_PICK => 0x79, "Pop the top stack element as N. Copy the Nth stack element to the top."; + OP_ROLL => 0x7a, "Pop the top stack element as N. Move the Nth stack element to the top."; + OP_ROT => 0x7b, "Rotate the top three stack items, as `[top next1 next2]` -> `[next2 top next1]`."; + OP_SWAP => 0x7c, "Swap the top two stack items."; + OP_TUCK => 0x7d, "Copy the top stack item to before the second item, as `[top next]` -> `[top next top]`."; + OP_CAT => 0x7e, "Fail the script unconditionally, does not even need to be executed."; + OP_SUBSTR => 0x7f, "Fail the script unconditionally, does not even need to be executed."; + OP_LEFT => 0x80, "Fail the script unconditionally, does not even need to be executed."; + OP_RIGHT => 0x81, "Fail the script unconditionally, does not even need to be executed."; + OP_SIZE => 0x82, "Pushes the length of the top stack item onto the stack."; + OP_INVERT => 0x83, "Fail the script unconditionally, does not even need to be executed."; + OP_AND => 0x84, "Fail the script unconditionally, does not even need to be executed."; + OP_OR => 0x85, "Fail the script unconditionally, does not even need to be executed."; + OP_XOR => 0x86, "Fail the script unconditionally, does not even need to be executed."; + OP_EQUAL => 0x87, "Pushes 1 if the inputs are exactly equal, 0 otherwise."; + OP_EQUALVERIFY => 0x88, "Returns success if the inputs are exactly equal, failure otherwise."; + OP_RESERVED1 => 0x89, "Synonym for `OP_RETURN`."; + OP_RESERVED2 => 0x8a, "Synonym for `OP_RETURN`."; + OP_1ADD => 0x8b, "Increment the top stack element in place."; + OP_1SUB => 0x8c, "Decrement the top stack element in place."; + OP_2MUL => 0x8d, "Fail the script unconditionally, does not even need to be executed."; + OP_2DIV => 0x8e, "Fail the script unconditionally, does not even need to be executed."; + OP_NEGATE => 0x8f, "Multiply the top stack item by -1 in place."; + OP_ABS => 0x90, "Absolute value the top stack item in place."; + OP_NOT => 0x91, "Map 0 to 1 and everything else to 0, in place."; + OP_0NOTEQUAL => 0x92, "Map 0 to 0 and everything else to 1, in place."; + OP_ADD => 0x93, "Pop two stack items and push their sum."; + OP_SUB => 0x94, "Pop two stack items and push the second minus the top."; + OP_MUL => 0x95, "Fail the script unconditionally, does not even need to be executed."; + OP_DIV => 0x96, "Fail the script unconditionally, does not even need to be executed."; + OP_MOD => 0x97, "Fail the script unconditionally, does not even need to be executed."; + OP_LSHIFT => 0x98, "Fail the script unconditionally, does not even need to be executed."; + OP_RSHIFT => 0x99, "Fail the script unconditionally, does not even need to be executed."; + OP_BOOLAND => 0x9a, "Pop the top two stack items and push 1 if both are nonzero, else push 0."; + OP_BOOLOR => 0x9b, "Pop the top two stack items and push 1 if either is nonzero, else push 0."; + OP_NUMEQUAL => 0x9c, "Pop the top two stack items and push 1 if both are numerically equal, else push 0."; + OP_NUMEQUALVERIFY => 0x9d, "Pop the top two stack items and return success if both are numerically equal, else return failure."; + OP_NUMNOTEQUAL => 0x9e, "Pop the top two stack items and push 0 if both are numerically equal, else push 1."; + OP_LESSTHAN => 0x9f, "Pop the top two items; push 1 if the second is less than the top, 0 otherwise."; + OP_GREATERTHAN => 0xa0, "Pop the top two items; push 1 if the second is greater than the top, 0 otherwise."; + OP_LESSTHANOREQUAL => 0xa1, "Pop the top two items; push 1 if the second is <= the top, 0 otherwise."; + OP_GREATERTHANOREQUAL => 0xa2, "Pop the top two items; push 1 if the second is >= the top, 0 otherwise."; + OP_MIN => 0xa3, "Pop the top two items; push the smaller."; + OP_MAX => 0xa4, "Pop the top two items; push the larger."; + OP_WITHIN => 0xa5, "Pop the top three items; if the top is >= the second and < the third, push 1, otherwise push 0."; + OP_RIPEMD160 => 0xa6, "Pop the top stack item and push its RIPEMD160 hash."; + OP_SHA1 => 0xa7, "Pop the top stack item and push its SHA1 hash."; + OP_SHA256 => 0xa8, "Pop the top stack item and push its SHA256 hash."; + OP_HASH160 => 0xa9, "Pop the top stack item and push its RIPEMD(SHA256) hash."; + OP_HASH256 => 0xaa, "Pop the top stack item and push its SHA256(SHA256) hash."; + OP_CODESEPARATOR => 0xab, "Ignore this and everything preceding when deciding what to sign when signature-checking."; + OP_CHECKSIG => 0xac, " pushing 1/0 for success/failure."; + OP_CHECKSIGVERIFY => 0xad, " returning success/failure."; + OP_CHECKMULTISIG => 0xae, "Pop N, N pubkeys, M, M signatures, a dummy (due to bug in reference code), \ + and verify that all M signatures are valid. Push 1 for 'all valid', 0 otherwise."; + OP_CHECKMULTISIGVERIFY => 0xaf, "Like the above but return success/failure."; + OP_NOP1 => 0xb0, "Does nothing."; + OP_CLTV => 0xb1, ""; + OP_CSV => 0xb2, ""; + OP_NOP4 => 0xb3, "Does nothing."; + OP_NOP5 => 0xb4, "Does nothing."; + OP_NOP6 => 0xb5, "Does nothing."; + OP_NOP7 => 0xb6, "Does nothing."; + OP_NOP8 => 0xb7, "Does nothing."; + OP_NOP9 => 0xb8, "Does nothing."; + OP_NOP10 => 0xb9, "Does nothing."; + // Every other opcode acts as OP_RETURN + OP_CHECKSIGADD => 0xba, "`OP_CHECKSIGADD` post tapscript."; + OP_RETURN_187 => 0xbb, "Synonym for `OP_RETURN`."; + OP_RETURN_188 => 0xbc, "Synonym for `OP_RETURN`."; + OP_RETURN_189 => 0xbd, "Synonym for `OP_RETURN`."; + OP_RETURN_190 => 0xbe, "Synonym for `OP_RETURN`."; + OP_RETURN_191 => 0xbf, "Synonym for `OP_RETURN`."; + OP_RETURN_192 => 0xc0, "Synonym for `OP_RETURN`."; + OP_RETURN_193 => 0xc1, "Synonym for `OP_RETURN`."; + OP_RETURN_194 => 0xc2, "Synonym for `OP_RETURN`."; + OP_RETURN_195 => 0xc3, "Synonym for `OP_RETURN`."; + OP_RETURN_196 => 0xc4, "Synonym for `OP_RETURN`."; + OP_RETURN_197 => 0xc5, "Synonym for `OP_RETURN`."; + OP_RETURN_198 => 0xc6, "Synonym for `OP_RETURN`."; + OP_RETURN_199 => 0xc7, "Synonym for `OP_RETURN`."; + OP_RETURN_200 => 0xc8, "Synonym for `OP_RETURN`."; + OP_RETURN_201 => 0xc9, "Synonym for `OP_RETURN`."; + OP_RETURN_202 => 0xca, "Synonym for `OP_RETURN`."; + OP_RETURN_203 => 0xcb, "Synonym for `OP_RETURN`."; + OP_RETURN_204 => 0xcc, "Synonym for `OP_RETURN`."; + OP_RETURN_205 => 0xcd, "Synonym for `OP_RETURN`."; + OP_RETURN_206 => 0xce, "Synonym for `OP_RETURN`."; + OP_RETURN_207 => 0xcf, "Synonym for `OP_RETURN`."; + OP_RETURN_208 => 0xd0, "Synonym for `OP_RETURN`."; + OP_RETURN_209 => 0xd1, "Synonym for `OP_RETURN`."; + OP_RETURN_210 => 0xd2, "Synonym for `OP_RETURN`."; + OP_RETURN_211 => 0xd3, "Synonym for `OP_RETURN`."; + OP_RETURN_212 => 0xd4, "Synonym for `OP_RETURN`."; + OP_RETURN_213 => 0xd5, "Synonym for `OP_RETURN`."; + OP_RETURN_214 => 0xd6, "Synonym for `OP_RETURN`."; + OP_RETURN_215 => 0xd7, "Synonym for `OP_RETURN`."; + OP_RETURN_216 => 0xd8, "Synonym for `OP_RETURN`."; + OP_RETURN_217 => 0xd9, "Synonym for `OP_RETURN`."; + OP_RETURN_218 => 0xda, "Synonym for `OP_RETURN`."; + OP_RETURN_219 => 0xdb, "Synonym for `OP_RETURN`."; + OP_RETURN_220 => 0xdc, "Synonym for `OP_RETURN`."; + OP_RETURN_221 => 0xdd, "Synonym for `OP_RETURN`."; + OP_RETURN_222 => 0xde, "Synonym for `OP_RETURN`."; + OP_RETURN_223 => 0xdf, "Synonym for `OP_RETURN`."; + OP_RETURN_224 => 0xe0, "Synonym for `OP_RETURN`."; + OP_RETURN_225 => 0xe1, "Synonym for `OP_RETURN`."; + OP_RETURN_226 => 0xe2, "Synonym for `OP_RETURN`."; + OP_RETURN_227 => 0xe3, "Synonym for `OP_RETURN`."; + OP_RETURN_228 => 0xe4, "Synonym for `OP_RETURN`."; + OP_RETURN_229 => 0xe5, "Synonym for `OP_RETURN`."; + OP_RETURN_230 => 0xe6, "Synonym for `OP_RETURN`."; + OP_RETURN_231 => 0xe7, "Synonym for `OP_RETURN`."; + OP_RETURN_232 => 0xe8, "Synonym for `OP_RETURN`."; + OP_RETURN_233 => 0xe9, "Synonym for `OP_RETURN`."; + OP_RETURN_234 => 0xea, "Synonym for `OP_RETURN`."; + OP_RETURN_235 => 0xeb, "Synonym for `OP_RETURN`."; + OP_RETURN_236 => 0xec, "Synonym for `OP_RETURN`."; + OP_RETURN_237 => 0xed, "Synonym for `OP_RETURN`."; + OP_RETURN_238 => 0xee, "Synonym for `OP_RETURN`."; + OP_RETURN_239 => 0xef, "Synonym for `OP_RETURN`."; + OP_RETURN_240 => 0xf0, "Synonym for `OP_RETURN`."; + OP_RETURN_241 => 0xf1, "Synonym for `OP_RETURN`."; + OP_RETURN_242 => 0xf2, "Synonym for `OP_RETURN`."; + OP_RETURN_243 => 0xf3, "Synonym for `OP_RETURN`."; + OP_RETURN_244 => 0xf4, "Synonym for `OP_RETURN`."; + OP_RETURN_245 => 0xf5, "Synonym for `OP_RETURN`."; + OP_RETURN_246 => 0xf6, "Synonym for `OP_RETURN`."; + OP_RETURN_247 => 0xf7, "Synonym for `OP_RETURN`."; + OP_RETURN_248 => 0xf8, "Synonym for `OP_RETURN`."; + OP_RETURN_249 => 0xf9, "Synonym for `OP_RETURN`."; + OP_RETURN_250 => 0xfa, "Synonym for `OP_RETURN`."; + OP_RETURN_251 => 0xfb, "Synonym for `OP_RETURN`."; + OP_RETURN_252 => 0xfc, "Synonym for `OP_RETURN`."; + OP_RETURN_253 => 0xfd, "Synonym for `OP_RETURN`."; + OP_RETURN_254 => 0xfe, "Synonym for `OP_RETURN`."; + OP_INVALIDOPCODE => 0xff, "Synonym for `OP_RETURN`." +} + +/// Classification context for the opcode. +/// +/// Some opcodes like [`OP_RESERVED`] abort the script in `ClassifyContext::Legacy` context, +/// but will act as `OP_SUCCESSx` in `ClassifyContext::TapScript` (see BIP-0342 for full list). +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum ClassifyContext { + /// Opcode used in tapscript context. + TapScript, + /// Opcode used in legacy context. + Legacy, +} + +impl Opcode { + /// Classifies an Opcode into a broad class. + #[inline] + #[must_use] + pub fn classify(self, ctx: ClassifyContext) -> Class { + match (self, ctx) { + // 3 opcodes illegal in all contexts + (OP_VERIF, _) | (OP_VERNOTIF, _) | (OP_INVALIDOPCODE, _) => Class::IllegalOp, + + // 15 opcodes illegal in Legacy context + #[rustfmt::skip] + (OP_CAT, ctx) | (OP_SUBSTR, ctx) + | (OP_LEFT, ctx) | (OP_RIGHT, ctx) + | (OP_INVERT, ctx) + | (OP_AND, ctx) | (OP_OR, ctx) | (OP_XOR, ctx) + | (OP_2MUL, ctx) | (OP_2DIV, ctx) + | (OP_MUL, ctx) | (OP_DIV, ctx) | (OP_MOD, ctx) + | (OP_LSHIFT, ctx) | (OP_RSHIFT, ctx) if ctx == ClassifyContext::Legacy => Class::IllegalOp, + + // 87 opcodes of SuccessOp class only in TapScript context + (op, ClassifyContext::TapScript) + if op.code == 80 + || op.code == 98 + || (op.code >= 126 && op.code <= 129) + || (op.code >= 131 && op.code <= 134) + || (op.code >= 137 && op.code <= 138) + || (op.code >= 141 && op.code <= 142) + || (op.code >= 149 && op.code <= 153) + || (op.code >= 187 && op.code <= 254) => + Class::SuccessOp, + + // 11 opcodes of NoOp class + (OP_NOP, _) => Class::NoOp, + (op, _) if op.code >= OP_NOP1.code && op.code <= OP_NOP10.code => Class::NoOp, + + // 1 opcode for `OP_RETURN` + (OP_RETURN, _) => Class::ReturnOp, + + // 4 opcodes operating equally to `OP_RETURN` only in Legacy context + (OP_RESERVED, ctx) | (OP_RESERVED1, ctx) | (OP_RESERVED2, ctx) | (OP_VER, ctx) + if ctx == ClassifyContext::Legacy => + Class::ReturnOp, + + // 71 opcodes operating equally to `OP_RETURN` only in Legacy context + (op, ClassifyContext::Legacy) if op.code >= OP_CHECKSIGADD.code => Class::ReturnOp, + + // 2 opcodes operating equally to `OP_RETURN` only in TapScript context + (OP_CHECKMULTISIG, ClassifyContext::TapScript) + | (OP_CHECKMULTISIGVERIFY, ClassifyContext::TapScript) => Class::ReturnOp, + + // 1 opcode of PushNum class + (OP_1NEGATE, _) => Class::PushNum(-1), + + // 16 opcodes of PushNum class + (op, _) if op.code >= OP_1.code && op.code <= OP_16.code => + Class::PushNum(1 + self.code as i32 - OP_1.code as i32), + + // 76 opcodes of PushBytes class + (op, _) if op.code <= OP_PUSHBYTES_75.code => Class::PushBytes(self.code as u32), + + // opcodes of Ordinary class: 61 for Legacy and 60 for TapScript context + (_, _) => Class::Ordinary(Ordinary::with(self)), + } + } + + /// Encodes [`Opcode`] as a byte. + #[inline] + pub const fn to_u8(self) -> u8 { self.code } + + /// Decodes PUSHNUM [`Opcode`] as a `u8` representing its number (1-16). + /// + /// Does not convert `OP_FALSE` to 0. Only `1` to `OP_PUSHNUM_16` are covered. + /// + /// # Returns + /// + /// Returns `None` if `self` is not a PUSHNUM. + #[inline] + #[must_use] + pub const fn decode_pushnum(self) -> Option { + const START: u8 = OP_1.code; + const END: u8 = OP_16.code; + match self.code { + START..=END => Some(self.code - START + 1), + _ => None, + } + } +} + +impl From for Opcode { + #[inline] + fn from(b: u8) -> Self { Self { code: b } } +} + +impl fmt::Debug for Opcode { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Display::fmt(self, f) } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Opcode { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +/// Broad categories of opcodes with similar behavior. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Class { + /// Pushes the given number onto the stack. + PushNum(i32), + /// Pushes the given number of bytes onto the stack. + PushBytes(u32), + /// Fails the script if executed. + ReturnOp, + /// Succeeds the script even if not executed. + SuccessOp, + /// Fails the script even if not executed. + IllegalOp, + /// Does nothing. + NoOp, + /// Any opcode not covered above. + Ordinary(Ordinary), +} + +macro_rules! ordinary_opcode { + ($($op:ident),*) => ( + #[repr(u8)] + #[doc(hidden)] + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + pub enum Ordinary { + $( $op = $op.code ),* + } + + impl fmt::Display for Ordinary { + fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { + match *self { + $(Ordinary::$op => { f.pad(stringify!($op)) }),* + } + } + } + + impl Ordinary { + fn with(b: Opcode) -> Self { + match b { + $( $op => { Ordinary::$op } ),* + _ => unreachable!("construction of `Ordinary` type from non-ordinary opcode {}", b), + } + } + + /// Constructs a new [`Ordinary`] from an [`Opcode`]. + pub fn from_opcode(b: Opcode) -> Option { + match b { + $( $op => { Some(Ordinary::$op) } ),* + _ => None, + } + } + } + ); +} + +// "Ordinary" opcodes -- should be 61 of these +ordinary_opcode! { + // pushdata + OP_PUSHDATA1, OP_PUSHDATA2, OP_PUSHDATA4, + // control flow + OP_IF, OP_NOTIF, OP_ELSE, OP_ENDIF, OP_VERIFY, + // stack + OP_TOALTSTACK, OP_FROMALTSTACK, + OP_2DROP, OP_2DUP, OP_3DUP, OP_2OVER, OP_2ROT, OP_2SWAP, + OP_DROP, OP_DUP, OP_NIP, OP_OVER, OP_PICK, OP_ROLL, OP_ROT, OP_SWAP, OP_TUCK, + OP_IFDUP, OP_DEPTH, OP_SIZE, + // equality + OP_EQUAL, OP_EQUALVERIFY, + // arithmetic + OP_1ADD, OP_1SUB, OP_NEGATE, OP_ABS, OP_NOT, OP_0NOTEQUAL, + OP_ADD, OP_SUB, OP_BOOLAND, OP_BOOLOR, + OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL, OP_LESSTHAN, + OP_GREATERTHAN, OP_LESSTHANOREQUAL, OP_GREATERTHANOREQUAL, + OP_MIN, OP_MAX, OP_WITHIN, + // crypto + OP_RIPEMD160, OP_SHA1, OP_SHA256, OP_HASH160, OP_HASH256, + OP_CODESEPARATOR, OP_CHECKSIG, OP_CHECKSIGVERIFY, + OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY, + OP_CHECKSIGADD +} + +impl Ordinary { + /// Encodes [`Opcode`] as a byte. + #[inline] + pub fn to_u8(self) -> u8 { self as u8 } +} + +#[cfg(test)] +mod tests { + use std::collections::HashSet; + + use super::*; + + macro_rules! roundtrip { + ($unique:expr, $op:ident) => { + assert_eq!($op, Opcode::from($op.to_u8())); + + let s1 = format!("{}", $op); + let s2 = format!("{:?}", $op); + assert_eq!(s1, s2); + assert_eq!(s1, stringify!($op)); + assert!($unique.insert(s1)); + }; + } + + #[test] + fn formatting_works() { + let op = all::OP_NOP; + let s = format!("{:>10}", op); + assert_eq!(s, " OP_NOP"); + } + + #[test] + fn ordinary_op_code() { + let ordinary_op = Ordinary::from_opcode(OP_PUSHDATA1).expect("0x4C"); + assert_eq!(ordinary_op.to_u8(), 0x4C_u8); + } + + #[test] + fn decode_pushnum() { + // Test all possible opcodes + // - Sanity check + assert_eq!(OP_1.code, 0x51_u8); + assert_eq!(OP_16.code, 0x60_u8); + for i in 0x00..=0xff_u8 { + let expected = match i { + // OP_1 ..= OP_16 + 0x51..=0x60 => Some(i - 0x50), + _ => None, + }; + assert_eq!(Opcode::from(i).decode_pushnum(), expected); + } + + // Test the named opcode constants + // - This is the OP right before PUSHNUMs start + assert!(OP_RESERVED.decode_pushnum().is_none()); + assert_eq!(OP_1.decode_pushnum().expect("pushnum"), 1); + assert_eq!(OP_2.decode_pushnum().expect("pushnum"), 2); + assert_eq!(OP_3.decode_pushnum().expect("pushnum"), 3); + assert_eq!(OP_4.decode_pushnum().expect("pushnum"), 4); + assert_eq!(OP_5.decode_pushnum().expect("pushnum"), 5); + assert_eq!(OP_6.decode_pushnum().expect("pushnum"), 6); + assert_eq!(OP_7.decode_pushnum().expect("pushnum"), 7); + assert_eq!(OP_8.decode_pushnum().expect("pushnum"), 8); + assert_eq!(OP_9.decode_pushnum().expect("pushnum"), 9); + assert_eq!(OP_10.decode_pushnum().expect("pushnum"), 10); + assert_eq!(OP_11.decode_pushnum().expect("pushnum"), 11); + assert_eq!(OP_12.decode_pushnum().expect("pushnum"), 12); + assert_eq!(OP_13.decode_pushnum().expect("pushnum"), 13); + assert_eq!(OP_14.decode_pushnum().expect("pushnum"), 14); + assert_eq!(OP_15.decode_pushnum().expect("pushnum"), 15); + assert_eq!(OP_16.decode_pushnum().expect("pushnum"), 16); + // - This is the OP right after PUSHNUMs end + assert!(OP_NOP.decode_pushnum().is_none()); + } + + #[test] + fn classify_test() { + let op174 = OP_CHECKMULTISIG; + assert_eq!( + op174.classify(ClassifyContext::Legacy), + Class::Ordinary(Ordinary::OP_CHECKMULTISIG) + ); + assert_eq!(op174.classify(ClassifyContext::TapScript), Class::ReturnOp); + + let op175 = OP_CHECKMULTISIGVERIFY; + assert_eq!( + op175.classify(ClassifyContext::Legacy), + Class::Ordinary(Ordinary::OP_CHECKMULTISIGVERIFY) + ); + assert_eq!(op175.classify(ClassifyContext::TapScript), Class::ReturnOp); + + let op186 = OP_CHECKSIGADD; + assert_eq!(op186.classify(ClassifyContext::Legacy), Class::ReturnOp); + assert_eq!( + op186.classify(ClassifyContext::TapScript), + Class::Ordinary(Ordinary::OP_CHECKSIGADD) + ); + + let op187 = OP_RETURN_187; + assert_eq!(op187.classify(ClassifyContext::Legacy), Class::ReturnOp); + assert_eq!(op187.classify(ClassifyContext::TapScript), Class::SuccessOp); + } + + #[test] + fn str_roundtrip() { + let mut unique = HashSet::new(); + roundtrip!(unique, OP_PUSHBYTES_0); + roundtrip!(unique, OP_PUSHBYTES_1); + roundtrip!(unique, OP_PUSHBYTES_2); + roundtrip!(unique, OP_PUSHBYTES_3); + roundtrip!(unique, OP_PUSHBYTES_4); + roundtrip!(unique, OP_PUSHBYTES_5); + roundtrip!(unique, OP_PUSHBYTES_6); + roundtrip!(unique, OP_PUSHBYTES_7); + roundtrip!(unique, OP_PUSHBYTES_8); + roundtrip!(unique, OP_PUSHBYTES_9); + roundtrip!(unique, OP_PUSHBYTES_10); + roundtrip!(unique, OP_PUSHBYTES_11); + roundtrip!(unique, OP_PUSHBYTES_12); + roundtrip!(unique, OP_PUSHBYTES_13); + roundtrip!(unique, OP_PUSHBYTES_14); + roundtrip!(unique, OP_PUSHBYTES_15); + roundtrip!(unique, OP_PUSHBYTES_16); + roundtrip!(unique, OP_PUSHBYTES_17); + roundtrip!(unique, OP_PUSHBYTES_18); + roundtrip!(unique, OP_PUSHBYTES_19); + roundtrip!(unique, OP_PUSHBYTES_20); + roundtrip!(unique, OP_PUSHBYTES_21); + roundtrip!(unique, OP_PUSHBYTES_22); + roundtrip!(unique, OP_PUSHBYTES_23); + roundtrip!(unique, OP_PUSHBYTES_24); + roundtrip!(unique, OP_PUSHBYTES_25); + roundtrip!(unique, OP_PUSHBYTES_26); + roundtrip!(unique, OP_PUSHBYTES_27); + roundtrip!(unique, OP_PUSHBYTES_28); + roundtrip!(unique, OP_PUSHBYTES_29); + roundtrip!(unique, OP_PUSHBYTES_30); + roundtrip!(unique, OP_PUSHBYTES_31); + roundtrip!(unique, OP_PUSHBYTES_32); + roundtrip!(unique, OP_PUSHBYTES_33); + roundtrip!(unique, OP_PUSHBYTES_34); + roundtrip!(unique, OP_PUSHBYTES_35); + roundtrip!(unique, OP_PUSHBYTES_36); + roundtrip!(unique, OP_PUSHBYTES_37); + roundtrip!(unique, OP_PUSHBYTES_38); + roundtrip!(unique, OP_PUSHBYTES_39); + roundtrip!(unique, OP_PUSHBYTES_40); + roundtrip!(unique, OP_PUSHBYTES_41); + roundtrip!(unique, OP_PUSHBYTES_42); + roundtrip!(unique, OP_PUSHBYTES_43); + roundtrip!(unique, OP_PUSHBYTES_44); + roundtrip!(unique, OP_PUSHBYTES_45); + roundtrip!(unique, OP_PUSHBYTES_46); + roundtrip!(unique, OP_PUSHBYTES_47); + roundtrip!(unique, OP_PUSHBYTES_48); + roundtrip!(unique, OP_PUSHBYTES_49); + roundtrip!(unique, OP_PUSHBYTES_50); + roundtrip!(unique, OP_PUSHBYTES_51); + roundtrip!(unique, OP_PUSHBYTES_52); + roundtrip!(unique, OP_PUSHBYTES_53); + roundtrip!(unique, OP_PUSHBYTES_54); + roundtrip!(unique, OP_PUSHBYTES_55); + roundtrip!(unique, OP_PUSHBYTES_56); + roundtrip!(unique, OP_PUSHBYTES_57); + roundtrip!(unique, OP_PUSHBYTES_58); + roundtrip!(unique, OP_PUSHBYTES_59); + roundtrip!(unique, OP_PUSHBYTES_60); + roundtrip!(unique, OP_PUSHBYTES_61); + roundtrip!(unique, OP_PUSHBYTES_62); + roundtrip!(unique, OP_PUSHBYTES_63); + roundtrip!(unique, OP_PUSHBYTES_64); + roundtrip!(unique, OP_PUSHBYTES_65); + roundtrip!(unique, OP_PUSHBYTES_66); + roundtrip!(unique, OP_PUSHBYTES_67); + roundtrip!(unique, OP_PUSHBYTES_68); + roundtrip!(unique, OP_PUSHBYTES_69); + roundtrip!(unique, OP_PUSHBYTES_70); + roundtrip!(unique, OP_PUSHBYTES_71); + roundtrip!(unique, OP_PUSHBYTES_72); + roundtrip!(unique, OP_PUSHBYTES_73); + roundtrip!(unique, OP_PUSHBYTES_74); + roundtrip!(unique, OP_PUSHBYTES_75); + roundtrip!(unique, OP_PUSHDATA1); + roundtrip!(unique, OP_PUSHDATA2); + roundtrip!(unique, OP_PUSHDATA4); + roundtrip!(unique, OP_1NEGATE); + roundtrip!(unique, OP_RESERVED); + roundtrip!(unique, OP_1); + roundtrip!(unique, OP_2); + roundtrip!(unique, OP_3); + roundtrip!(unique, OP_4); + roundtrip!(unique, OP_5); + roundtrip!(unique, OP_6); + roundtrip!(unique, OP_7); + roundtrip!(unique, OP_8); + roundtrip!(unique, OP_9); + roundtrip!(unique, OP_10); + roundtrip!(unique, OP_11); + roundtrip!(unique, OP_12); + roundtrip!(unique, OP_13); + roundtrip!(unique, OP_14); + roundtrip!(unique, OP_15); + roundtrip!(unique, OP_16); + roundtrip!(unique, OP_NOP); + roundtrip!(unique, OP_VER); + roundtrip!(unique, OP_IF); + roundtrip!(unique, OP_NOTIF); + roundtrip!(unique, OP_VERIF); + roundtrip!(unique, OP_VERNOTIF); + roundtrip!(unique, OP_ELSE); + roundtrip!(unique, OP_ENDIF); + roundtrip!(unique, OP_VERIFY); + roundtrip!(unique, OP_RETURN); + roundtrip!(unique, OP_TOALTSTACK); + roundtrip!(unique, OP_FROMALTSTACK); + roundtrip!(unique, OP_2DROP); + roundtrip!(unique, OP_2DUP); + roundtrip!(unique, OP_3DUP); + roundtrip!(unique, OP_2OVER); + roundtrip!(unique, OP_2ROT); + roundtrip!(unique, OP_2SWAP); + roundtrip!(unique, OP_IFDUP); + roundtrip!(unique, OP_DEPTH); + roundtrip!(unique, OP_DROP); + roundtrip!(unique, OP_DUP); + roundtrip!(unique, OP_NIP); + roundtrip!(unique, OP_OVER); + roundtrip!(unique, OP_PICK); + roundtrip!(unique, OP_ROLL); + roundtrip!(unique, OP_ROT); + roundtrip!(unique, OP_SWAP); + roundtrip!(unique, OP_TUCK); + roundtrip!(unique, OP_CAT); + roundtrip!(unique, OP_SUBSTR); + roundtrip!(unique, OP_LEFT); + roundtrip!(unique, OP_RIGHT); + roundtrip!(unique, OP_SIZE); + roundtrip!(unique, OP_INVERT); + roundtrip!(unique, OP_AND); + roundtrip!(unique, OP_OR); + roundtrip!(unique, OP_XOR); + roundtrip!(unique, OP_EQUAL); + roundtrip!(unique, OP_EQUALVERIFY); + roundtrip!(unique, OP_RESERVED1); + roundtrip!(unique, OP_RESERVED2); + roundtrip!(unique, OP_1ADD); + roundtrip!(unique, OP_1SUB); + roundtrip!(unique, OP_2MUL); + roundtrip!(unique, OP_2DIV); + roundtrip!(unique, OP_NEGATE); + roundtrip!(unique, OP_ABS); + roundtrip!(unique, OP_NOT); + roundtrip!(unique, OP_0NOTEQUAL); + roundtrip!(unique, OP_ADD); + roundtrip!(unique, OP_SUB); + roundtrip!(unique, OP_MUL); + roundtrip!(unique, OP_DIV); + roundtrip!(unique, OP_MOD); + roundtrip!(unique, OP_LSHIFT); + roundtrip!(unique, OP_RSHIFT); + roundtrip!(unique, OP_BOOLAND); + roundtrip!(unique, OP_BOOLOR); + roundtrip!(unique, OP_NUMEQUAL); + roundtrip!(unique, OP_NUMEQUALVERIFY); + roundtrip!(unique, OP_NUMNOTEQUAL); + roundtrip!(unique, OP_LESSTHAN); + roundtrip!(unique, OP_GREATERTHAN); + roundtrip!(unique, OP_LESSTHANOREQUAL); + roundtrip!(unique, OP_GREATERTHANOREQUAL); + roundtrip!(unique, OP_MIN); + roundtrip!(unique, OP_MAX); + roundtrip!(unique, OP_WITHIN); + roundtrip!(unique, OP_RIPEMD160); + roundtrip!(unique, OP_SHA1); + roundtrip!(unique, OP_SHA256); + roundtrip!(unique, OP_HASH160); + roundtrip!(unique, OP_HASH256); + roundtrip!(unique, OP_CODESEPARATOR); + roundtrip!(unique, OP_CHECKSIG); + roundtrip!(unique, OP_CHECKSIGVERIFY); + roundtrip!(unique, OP_CHECKMULTISIG); + roundtrip!(unique, OP_CHECKMULTISIGVERIFY); + roundtrip!(unique, OP_NOP1); + roundtrip!(unique, OP_CLTV); + roundtrip!(unique, OP_CSV); + roundtrip!(unique, OP_NOP4); + roundtrip!(unique, OP_NOP5); + roundtrip!(unique, OP_NOP6); + roundtrip!(unique, OP_NOP7); + roundtrip!(unique, OP_NOP8); + roundtrip!(unique, OP_NOP9); + roundtrip!(unique, OP_NOP10); + roundtrip!(unique, OP_CHECKSIGADD); + roundtrip!(unique, OP_RETURN_187); + roundtrip!(unique, OP_RETURN_188); + roundtrip!(unique, OP_RETURN_189); + roundtrip!(unique, OP_RETURN_190); + roundtrip!(unique, OP_RETURN_191); + roundtrip!(unique, OP_RETURN_192); + roundtrip!(unique, OP_RETURN_193); + roundtrip!(unique, OP_RETURN_194); + roundtrip!(unique, OP_RETURN_195); + roundtrip!(unique, OP_RETURN_196); + roundtrip!(unique, OP_RETURN_197); + roundtrip!(unique, OP_RETURN_198); + roundtrip!(unique, OP_RETURN_199); + roundtrip!(unique, OP_RETURN_200); + roundtrip!(unique, OP_RETURN_201); + roundtrip!(unique, OP_RETURN_202); + roundtrip!(unique, OP_RETURN_203); + roundtrip!(unique, OP_RETURN_204); + roundtrip!(unique, OP_RETURN_205); + roundtrip!(unique, OP_RETURN_206); + roundtrip!(unique, OP_RETURN_207); + roundtrip!(unique, OP_RETURN_208); + roundtrip!(unique, OP_RETURN_209); + roundtrip!(unique, OP_RETURN_210); + roundtrip!(unique, OP_RETURN_211); + roundtrip!(unique, OP_RETURN_212); + roundtrip!(unique, OP_RETURN_213); + roundtrip!(unique, OP_RETURN_214); + roundtrip!(unique, OP_RETURN_215); + roundtrip!(unique, OP_RETURN_216); + roundtrip!(unique, OP_RETURN_217); + roundtrip!(unique, OP_RETURN_218); + roundtrip!(unique, OP_RETURN_219); + roundtrip!(unique, OP_RETURN_220); + roundtrip!(unique, OP_RETURN_221); + roundtrip!(unique, OP_RETURN_222); + roundtrip!(unique, OP_RETURN_223); + roundtrip!(unique, OP_RETURN_224); + roundtrip!(unique, OP_RETURN_225); + roundtrip!(unique, OP_RETURN_226); + roundtrip!(unique, OP_RETURN_227); + roundtrip!(unique, OP_RETURN_228); + roundtrip!(unique, OP_RETURN_229); + roundtrip!(unique, OP_RETURN_230); + roundtrip!(unique, OP_RETURN_231); + roundtrip!(unique, OP_RETURN_232); + roundtrip!(unique, OP_RETURN_233); + roundtrip!(unique, OP_RETURN_234); + roundtrip!(unique, OP_RETURN_235); + roundtrip!(unique, OP_RETURN_236); + roundtrip!(unique, OP_RETURN_237); + roundtrip!(unique, OP_RETURN_238); + roundtrip!(unique, OP_RETURN_239); + roundtrip!(unique, OP_RETURN_240); + roundtrip!(unique, OP_RETURN_241); + roundtrip!(unique, OP_RETURN_242); + roundtrip!(unique, OP_RETURN_243); + roundtrip!(unique, OP_RETURN_244); + roundtrip!(unique, OP_RETURN_245); + roundtrip!(unique, OP_RETURN_246); + roundtrip!(unique, OP_RETURN_247); + roundtrip!(unique, OP_RETURN_248); + roundtrip!(unique, OP_RETURN_249); + roundtrip!(unique, OP_RETURN_250); + roundtrip!(unique, OP_RETURN_251); + roundtrip!(unique, OP_RETURN_252); + roundtrip!(unique, OP_RETURN_253); + roundtrip!(unique, OP_RETURN_254); + roundtrip!(unique, OP_INVALIDOPCODE); + assert_eq!(unique.len(), 256); + } +} diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs new file mode 100644 index 000000000..79cbf3c45 --- /dev/null +++ b/bitcoin/src/blockdata/script/borrowed.rs @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: CC0-1.0 + +use core::fmt; + +use hex::DisplayHex as _; +use internals::array::ArrayExt; // For `split_first`. +use internals::ToU64 as _; + +use super::witness_version::WitnessVersion; +use super::{ + Builder, Instruction, InstructionIndices, Instructions, PushBytes, RedeemScript, + RedeemScriptSizeError, Script, ScriptHash, ScriptHashableTag, ScriptPubKey, ScriptSig, + TapScript, WScriptHash, WitnessScript, WitnessScriptSizeError, +}; +use crate::consensus::{self, Encodable}; +use crate::key::{PublicKey, UntweakedPublicKey, WPubkeyHash}; +use crate::opcodes::all::*; +use crate::opcodes::{self, Opcode}; +use crate::policy::{DUST_RELAY_TX_FEE, MAX_OP_RETURN_RELAY}; +use crate::prelude::{sink, String, ToString}; +use crate::script::{self, ScriptPubKeyBufExt as _}; +use crate::taproot::{LeafVersion, TapLeafHash, TapNodeHash}; +use crate::witness_program::P2A_PROGRAM; +use crate::{internal_macros, Amount, FeeRate, ScriptPubKeyBuf, WitnessScriptBuf}; + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`Script`] type. + pub trait ScriptExt impl for Script { + /// Constructs a new script builder + fn builder() -> Builder { Builder::new() } + + /// Counts the sigops for this Script using accurate counting. + /// + /// In Bitcoin Core, there are two ways to count sigops, "accurate" and "legacy". + /// This method uses "accurate" counting. This means that OP_CHECKMULTISIG and its + /// verify variant count for N sigops where N is the number of pubkeys used in the + /// multisig. However, it will count for 20 sigops if CHECKMULTISIG is not preceded by an + /// OP_PUSHNUM from 1 - 16 (this would be an invalid script) + /// + /// Bitcoin Core uses accurate counting for sigops contained within redeemScripts (P2SH) + /// and witnessScripts (P2WSH) only. It uses legacy for sigops in scriptSigs and scriptPubkeys. + /// + /// (Note: Taproot scripts don't count toward the sigop count of the block, + /// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD, + /// so do not use this to try and estimate if a Taproot script goes over the sigop budget.) + fn count_sigops(&self) -> usize { self.count_sigops_internal(true) } + + /// Counts the sigops for this Script using legacy counting. + /// + /// In Bitcoin Core, there are two ways to count sigops, "accurate" and "legacy". + /// This method uses "legacy" counting. This means that OP_CHECKMULTISIG and its + /// verify variant count for 20 sigops. + /// + /// Bitcoin Core uses legacy counting for sigops contained within scriptSigs and + /// scriptPubkeys. It uses accurate for redeemScripts (P2SH) and witnessScripts (P2WSH). + /// + /// (Note: Taproot scripts don't count toward the sigop count of the block, + /// nor do they have CHECKMULTISIG operations. This function does not count OP_CHECKSIGADD, + /// so do not use this to try and estimate if a Taproot script goes over the sigop budget.) + fn count_sigops_legacy(&self) -> usize { self.count_sigops_internal(false) } + + /// Checks whether a script is push only. + /// + /// Note: `OP_RESERVED` (`0x50`) and all the OP_PUSHNUM operations + /// are considered push operations. + #[inline] + fn is_push_only(&self) -> bool { + for inst in self.instructions() { + match inst { + Err(_) => return false, + Ok(Instruction::PushBytes(_)) => {} + Ok(Instruction::Op(op)) if op.to_u8() <= 0x60 => {} + // From Bitcoin Core + // if (opcode > OP_PUSHNUM_16 (0x60)) return false + Ok(Instruction::Op(_)) => return false, + } + } + true + } + + /// Returns an iterator over script bytes. + #[inline] + fn bytes(&self) -> Bytes<'_> { Bytes(self.as_bytes().iter().copied()) } + + /// Iterates over the script instructions. + /// + /// Each returned item is a nested enum covering opcodes, datapushes and errors. + /// At most one error will be returned and then the iterator will end. To instead iterate over + /// the script as sequence of bytes call the [`bytes`](Self::bytes) method. + /// + /// To force minimal pushes, use [`instructions_minimal`](Self::instructions_minimal). + #[inline] + fn instructions(&self) -> Instructions<'_> { + Instructions { data: self.as_bytes().iter(), enforce_minimal: false } + } + + /// Iterates over the script instructions while enforcing minimal pushes. + /// + /// This is similar to [`instructions`](Self::instructions) but an error is returned if a push + /// is not minimal. + #[inline] + fn instructions_minimal(&self) -> Instructions<'_> { + Instructions { data: self.as_bytes().iter(), enforce_minimal: true } + } + + /// Iterates over the script instructions and their indices. + /// + /// Unless the script contains an error, the returned item consists of an index pointing to the + /// position in the script where the instruction begins and the decoded instruction - either an + /// opcode or data push. + /// + /// To force minimal pushes, use [`Self::instruction_indices_minimal`]. + #[inline] + fn instruction_indices(&self) -> InstructionIndices<'_> { + InstructionIndices::from_instructions(self.instructions()) + } + + /// Iterates over the script instructions and their indices while enforcing minimal pushes. + /// + /// This is similar to [`instruction_indices`](Self::instruction_indices) but an error is + /// returned if a push is not minimal. + #[inline] + fn instruction_indices_minimal(&self) -> InstructionIndices<'_> { + InstructionIndices::from_instructions(self.instructions_minimal()) + } + + /// Writes the human-readable assembly representation of the script to the formatter. + #[deprecated(since = "TBD", note = "use the script's `Display` impl instead")] + fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result { + write!(f, "{}", self) + } + + /// Returns the human-readable assembly representation of the script. + #[deprecated(since = "TBD", note = "use `to_string()` instead")] + fn to_asm_string(&self) -> String { self.to_string() } + + /// Consensus encodes the script as lower-case hex. + #[deprecated(since = "TBD", note = "use `to_hex_string_no_length_prefix` instead")] + fn to_hex_string(&self) -> String { self.to_hex_string_no_length_prefix() } + + /// Consensus encodes the script as lower-case hex. + /// + /// Consensus encoding includes a length prefix. To hex encode without the length prefix use + /// `to_hex_string_no_length_prefix`. + fn to_hex_string_prefixed(&self) -> String { consensus::encode::serialize_hex(self) } + + /// Encodes the script as lower-case hex. + /// + /// This is **not** consensus encoding. The returned hex string will not include the length + /// prefix. See `to_hex_string_prefixed`. + fn to_hex_string_no_length_prefix(&self) -> String { + self.as_bytes().to_lower_hex_string() + } + + /// Returns the first opcode of the script (if there is any). + fn first_opcode(&self) -> Option { + self.as_bytes().first().copied().map(From::from) + } + + // These methods only exist for scriptPubKey and redeemScript, as indicated by the + // where clauses on them. + + /// Returns 160-bit hash of the script for P2SH outputs. + #[inline] + fn script_hash(&self) -> Result + where T: ScriptHashableTag + { + ScriptHash::from_script(self) + } + + /// Computes the P2SH output corresponding to this redeem script. + fn to_p2sh(&self) -> Result + where T: ScriptHashableTag + { + self.script_hash().map(ScriptPubKeyBuf::new_p2sh) + } + + /// Returns the script code used for spending a P2WPKH output if this script is a script pubkey + /// for a P2WPKH output. The `scriptCode` is described in [BIP-0143]. + /// + /// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and + /// should not be used as one. It is a special template defined in BIP 143 which is used + /// in place of a witness script for purposes of sighash computation. + /// + /// [BIP-0143]: + fn p2wpkh_script_code(&self) -> Option + where T: ScriptHashableTag + { + if self.is_p2wpkh() { + // The `self` script is 0x00, 0x14, + let bytes = <[u8; 20]>::try_from(&self.as_bytes()[2..]).expect("length checked in is_p2wpkh()"); + let wpkh = WPubkeyHash::from_byte_array(bytes); + Some(script::p2wpkh_script_code(wpkh)) + } else { + None + } + } + + /// Returns witness version of the script, if any, assuming the script is a `scriptPubkey`. + /// + /// # Returns + /// + /// The witness version if this script is found to conform to the SegWit rules: + /// + /// > A scriptPubKey (or redeemScript as defined in BIP-0016/P2SH) that consists of a 1-byte + /// > push opcode (for 0 to 16) followed by a data push between 2 and 40 bytes gets a new + /// > special meaning. The value of the first push is called the "version byte". The following + /// > byte vector pushed is called the "witness program". + #[inline] + fn witness_version(&self) -> Option + where T: ScriptHashableTag + { + let script_len = self.len(); + if !(4..=42).contains(&script_len) { + return None; + } + + let ver_opcode = Opcode::from(self.as_bytes()[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16 + let push_opbyte = self.as_bytes()[1]; // Second byte push opcode 2-40 bytes + + if push_opbyte < OP_PUSHBYTES_2.to_u8() || push_opbyte > OP_PUSHBYTES_40.to_u8() { + return None; + } + // Check that the rest of the script has the correct size + if script_len - 2 != push_opbyte as usize { + return None; + } + + WitnessVersion::try_from(ver_opcode).ok() + } + + /// Checks whether a script pubkey is a P2WSH output. + #[inline] + fn is_p2wsh(&self) -> bool + where T: ScriptHashableTag + { + self.len() == 34 + && self.witness_version() == Some(WitnessVersion::V0) + && self.as_bytes()[1] == OP_PUSHBYTES_32.to_u8() + } + + /// Checks whether a script pubkey is a P2WPKH output. + #[inline] + fn is_p2wpkh(&self) -> bool + where T: ScriptHashableTag + { + self.len() == 22 + && self.witness_version() == Some(WitnessVersion::V0) + && self.as_bytes()[1] == OP_PUSHBYTES_20.to_u8() + } + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`WitnessScript`] type. + pub trait WitnessScriptExt impl for WitnessScript { + /// Returns 256-bit hash of the script for P2WSH outputs. + #[inline] + fn wscript_hash(&self) -> Result { + WScriptHash::from_script(self) + } + + /// Computes the P2WSH output corresponding to this witnessScript (aka the "witness redeem + /// script"). + fn to_p2wsh(&self) -> Result { + self.wscript_hash().map(ScriptPubKeyBuf::new_p2wsh) + } + } +} + +crate::internal_macros::define_extension_trait! { + /// Extension functionality for the [`TapScript`] type. + pub trait TapScriptExt impl for TapScript { + /// Computes leaf hash of tapscript. + #[inline] + fn tapscript_leaf_hash(&self) -> TapLeafHash { + TapLeafHash::from_script(self, LeafVersion::TapScript) + } + + /// Computes P2TR output with a given internal key and a single script spending path equal to + /// the current script, assuming that the script is a Tapscript. + fn to_p2tr>( + &self, + internal_key: K, + ) -> ScriptPubKeyBuf { + let internal_key = internal_key.into(); + let leaf_hash = self.tapscript_leaf_hash(); + let merkle_root = TapNodeHash::from(leaf_hash); + ScriptPubKeyBuf::new_p2tr(internal_key, Some(merkle_root)) + } + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`ScriptPubKey`] type. + pub trait ScriptPubKeyExt impl for ScriptPubKey { + /// Checks whether a script pubkey is a P2PK output. + /// + /// You can obtain the public key, if it's valid, + /// by calling [`p2pk_public_key()`](Self::p2pk_public_key) + fn is_p2pk(&self) -> bool { self.p2pk_pubkey_bytes().is_some() } + + /// Returns the public key if this script is P2PK with a **valid** public key. + /// + /// This may return `None` even when [`is_p2pk()`](Self::is_p2pk) returns true. + /// This happens when the public key is invalid (e.g. the point not being on the curve). + /// In this situation the script is unspendable. + fn p2pk_public_key(&self) -> Option { + PublicKey::from_slice(self.p2pk_pubkey_bytes()?).ok() + } + + /// Checks whether a script pubkey is a P2SH output. + #[inline] + fn is_p2sh(&self) -> bool { + self.len() == 23 + && self.as_bytes()[0] == OP_HASH160.to_u8() + && self.as_bytes()[1] == OP_PUSHBYTES_20.to_u8() + && self.as_bytes()[22] == OP_EQUAL.to_u8() + } + + /// Checks whether a script pubkey is a P2PKH output. + #[inline] + fn is_p2pkh(&self) -> bool { + self.len() == 25 + && self.as_bytes()[0] == OP_DUP.to_u8() + && self.as_bytes()[1] == OP_HASH160.to_u8() + && self.as_bytes()[2] == OP_PUSHBYTES_20.to_u8() + && self.as_bytes()[23] == OP_EQUALVERIFY.to_u8() + && self.as_bytes()[24] == OP_CHECKSIG.to_u8() + } + + /// Checks whether a script pubkey is a bare multisig output. + /// + /// In a bare multisig pubkey script the keys are not hashed, the script + /// is of the form: + /// + /// `2 3 OP_CHECKMULTISIG` + #[inline] + fn is_multisig(&self) -> bool { + let required_sigs; + + let mut instructions = self.instructions(); + if let Some(Ok(Instruction::Op(op))) = instructions.next() { + if let Some(pushnum) = op.decode_pushnum() { + required_sigs = pushnum; + } else { + return false; + } + } else { + return false; + } + + let mut num_pubkeys: u8 = 0; + while let Some(Ok(instruction)) = instructions.next() { + match instruction { + Instruction::PushBytes(_) => { + num_pubkeys += 1; + } + Instruction::Op(op) => { + if let Some(pushnum) = op.decode_pushnum() { + if pushnum != num_pubkeys { + return false; + } + } + break; + } + } + } + + if required_sigs > num_pubkeys { + return false; + } + + if let Some(Ok(Instruction::Op(op))) = instructions.next() { + if op != OP_CHECKMULTISIG { + return false; + } + } else { + return false; + } + + instructions.next().is_none() + } + + /// Checks whether a script pubkey is a Segregated Witness (SegWit) program. + #[inline] + fn is_witness_program(&self) -> bool { self.witness_version().is_some() } + + /// Checks whether a script pubkey is a P2TR output. + #[inline] + fn is_p2tr(&self) -> bool { + self.len() == 34 + && self.witness_version() == Some(WitnessVersion::V1) + && self.as_bytes()[1] == OP_PUSHBYTES_32.to_u8() + } + + /// Checks whether a script pubkey is a P2A output. + #[inline] + fn is_p2a(&self) -> bool { + self.len() == 4 + && self.witness_version() == Some(WitnessVersion::V1) + && self.as_bytes()[1] == OP_PUSHBYTES_2.to_u8() + && self.as_bytes()[2..] == P2A_PROGRAM + } + + /// Check if this is a consensus-valid OP_RETURN output. + /// + /// To validate if the OP_RETURN obeys Bitcoin Core's current standardness policy, use + /// [`is_standard_op_return()`](Self::is_standard_op_return) instead. + #[inline] + fn is_op_return(&self) -> bool { + self.as_bytes().first().is_some_and(|&b| b == OP_RETURN.to_u8()) + } + + /// Check if this is an OP_RETURN that obeys Bitcoin Core standardness policy. + /// + /// What this function considers to be standard may change without warning pending Bitcoin Core + /// changes. + #[inline] + fn is_standard_op_return(&self) -> bool { self.is_op_return() && self.len() <= MAX_OP_RETURN_RELAY } + + /// Checks whether a script is trivially known to have no satisfying input. + /// + /// This method has potentially confusing semantics and an unclear purpose, so it's going to be + /// removed. Use `is_op_return` if you want `OP_RETURN` semantics. + #[deprecated(since = "0.32.0", note = "use `is_op_return` instead")] + #[inline] + fn is_provably_unspendable(&self) -> bool { + use crate::opcodes::Class::{IllegalOp, ReturnOp}; + + match self.as_bytes().first() { + Some(b) => { + let first = Opcode::from(*b); + let class = first.classify(opcodes::ClassifyContext::Legacy); + + class == ReturnOp || class == IllegalOp + } + None => false, + } + } + + /// Returns the minimum value an output with this script should have in order to be + /// broadcastable on today’s Bitcoin network. + #[deprecated(since = "0.32.0", note = "use `minimal_non_dust` etc. instead")] + fn dust_value(&self) -> Amount { self.minimal_non_dust() } + + /// Returns the minimum value an output with this script should have in order to be + /// broadcastable on today's Bitcoin network. + /// + /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to. + /// This function uses the default value of 0.00003 BTC/kB (3 sat/vByte). + /// + /// To use a custom value, use [`minimal_non_dust_custom`]. + /// + /// [`minimal_non_dust_custom`]: Self::minimal_non_dust_custom + fn minimal_non_dust(&self) -> Amount { + self.minimal_non_dust_internal(DUST_RELAY_TX_FEE.into()) + .expect("dust_relay_fee or script length should not be absurdly large") + } + + /// Returns the minimum value an output with this script should have in order to be + /// broadcastable on today's Bitcoin network. + /// + /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to. + /// This function lets you set the fee rate used in dust calculation. + /// + /// The current default value in Bitcoin Core (as of v26) is 3 sat/vByte. + /// + /// To use the default Bitcoin Core value, use [`minimal_non_dust`]. + /// + /// [`minimal_non_dust`]: Self::minimal_non_dust + fn minimal_non_dust_custom(&self, dust_relay: FeeRate) -> Option { + self.minimal_non_dust_internal(dust_relay.to_sat_per_kvb_ceil()) + } + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::Script {} +} + +internal_macros::define_extension_trait! { + pub(crate) trait ScriptExtPriv impl for Script { + fn count_sigops_internal(&self, accurate: bool) -> usize { + let mut n = 0; + let mut pushnum_cache = None; + for inst in self.instructions() { + match inst { + Ok(Instruction::Op(opcode)) => { + match opcode { + // p2pk, p2pkh + OP_CHECKSIG | OP_CHECKSIGVERIFY => { + n += 1; + } + OP_CHECKMULTISIG | OP_CHECKMULTISIGVERIFY => { + match (accurate, pushnum_cache) { + (true, Some(pushnum)) => { + // Add the number of pubkeys in the multisig as sigop count + n += usize::from(pushnum); + } + _ => { + // MAX_PUBKEYS_PER_MULTISIG from Bitcoin Core + // https://github.com/bitcoin/bitcoin/blob/v25.0/src/script/script.h#L29-L30 + n += 20; + } + } + } + _ => { + pushnum_cache = opcode.decode_pushnum(); + } + } + } + Ok(Instruction::PushBytes(_)) => { + pushnum_cache = None; + } + // In Bitcoin Core it does `if (!GetOp(pc, opcode)) break;` + Err(_) => break, + } + } + + n + } + + /// Iterates the script to find the last opcode. + /// + /// Returns `None` if the instruction is data push or if the script is empty. + fn last_opcode(&self) -> Option { + match self.instructions().last() { + Some(Ok(Instruction::Op(op))) => Some(op), + _ => None, + } + } + + /// Iterates the script to find the last pushdata. + /// + /// Returns `None` if the instruction is an opcode or if the script is empty. + fn last_pushdata(&self) -> Option<&PushBytes> { + match self.instructions().last() { + // Returns only true data pushes. + // Note: OP_0 (empty push) is included as PushBytes; numeric push opcodes + // OP_1NEGATE and OP_1..OP_16 are opcodes (not pushdata) and thus excluded. + // OP_RESERVED is also excluded. + Some(Ok(Instruction::PushBytes(bytes))) => Some(bytes), + // OP_16 (0x60) and lower are considered "pushes" by Bitcoin Core (excl. OP_RESERVED). + // However we are only interested in the pushdata so we can ignore them. + _ => None, + } + } + } +} + +internal_macros::define_extension_trait! { + pub(crate) trait ScriptPubKeyExtPriv impl for ScriptPubKey { + /// Returns the bytes of the (possibly invalid) public key if this script is P2PK. + fn p2pk_pubkey_bytes(&self) -> Option<&[u8]> { + if let Ok(bytes) = <&[u8; 67]>::try_from(self.as_bytes()) { + let (&first, bytes) = bytes.split_first::<66>(); + let (&last, pubkey) = bytes.split_last::<65>(); + (first == OP_PUSHBYTES_65.to_u8() && last == OP_CHECKSIG.to_u8()).then_some(pubkey) + } else if let Ok(bytes) = <&[u8; 35]>::try_from(self.as_bytes()) { + let (&first, bytes) = bytes.split_first::<34>(); + let (&last, pubkey) = bytes.split_last::<33>(); + (first == OP_PUSHBYTES_33.to_u8() && last == OP_CHECKSIG.to_u8()).then_some(pubkey) + } else { + None + } + } + + fn minimal_non_dust_internal(&self, dust_relay_fee_rate_per_kvb: u64) -> Option { + // This must never be lower than Bitcoin Core's GetDustThreshold() (as of v0.21) as it may + // otherwise allow users to create transactions which likely can never be broadcast/confirmed. + let sats = dust_relay_fee_rate_per_kvb + .checked_mul(if self.is_op_return() { + 0 + } else if self.is_witness_program() { + 32 + 4 + 1 + (107 / 4) + 4 + // The spend cost copied from Core + 8 + // The serialized size of the TxOut's amount field + self.consensus_encode(&mut sink()).expect("sinks don't error").to_u64() // The serialized size of this script_pubkey + } else { + 32 + 4 + 1 + 107 + 4 + // The spend cost copied from Core + 8 + // The serialized size of the TxOut's amount field + self.consensus_encode(&mut sink()).expect("sinks don't error").to_u64() // The serialized size of this script_pubkey + })? + / 1000; // divide by 1000 like in Core to get value as it cancels out DEFAULT_MIN_RELAY_TX_FEE + // Note: We ensure the division happens at the end, since Core performs the division at the end. + // This will make sure none of the implicit floor operations mess with the value. + + Amount::from_sat(sats).ok() + } + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`ScriptSig`] type. + pub trait ScriptSigExt impl for ScriptSig { + /// Get redeemScript following BIP-0016 rules regarding P2SH spending. + /// + /// This does not guarantee that this represents a P2SH input [`ScriptSig`]. + /// It merely gets the last push of the script. + /// + /// Use [`ScriptPubKey::is_p2sh`] on the scriptPubKey to check whether it is actually a P2SH script. + fn redeem_script(&self) -> Option<&RedeemScript> { + // Script must consist entirely of pushes. + if self.instructions().any(|i| i.is_err() || i.unwrap().push_bytes().is_none()) { + return None; + } + + if let Some(Ok(Instruction::PushBytes(b))) = self.instructions().last() { + Some(RedeemScript::from_bytes(b.as_bytes())) + } else { + None + } + } + } +} + +/// Iterator over bytes of a script +pub struct Bytes<'a>(core::iter::Copied>); + +impl Iterator for Bytes<'_> { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { self.0.next() } + + #[inline] + fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn nth(&mut self, n: usize) -> Option { self.0.nth(n) } +} + +impl DoubleEndedIterator for Bytes<'_> { + #[inline] + fn next_back(&mut self) -> Option { self.0.next_back() } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { self.0.nth_back(n) } +} + +impl ExactSizeIterator for Bytes<'_> {} +impl core::iter::FusedIterator for Bytes<'_> {} diff --git a/bitcoin/src/blockdata/script/builder.rs b/bitcoin/src/blockdata/script/builder.rs new file mode 100644 index 000000000..ec7786140 --- /dev/null +++ b/bitcoin/src/blockdata/script/builder.rs @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: CC0-1.0 + +use core::fmt; + +use super::{opcode_to_verify, Error, PushBytes, Script, ScriptBuf}; +use crate::key::{PublicKey, XOnlyPublicKey}; +use crate::locktime::absolute; +use crate::opcodes::all::*; +use crate::opcodes::Opcode; +use crate::prelude::Vec; +use crate::script::{ScriptBufExt as _, ScriptBufExtPriv as _, ScriptExtPriv as _}; +use crate::{relative, Sequence}; + +/// An Object which can be used to construct a script piece by piece. +/// +/// # Panics +/// +/// `Builder` is backed by [`ScriptBuf`] and inherits its panic behavior. This means that +/// attempting to construct scripts larger than `isize::MAX` bytes will panic. +#[derive(PartialEq, Eq, Clone)] +pub struct Builder(ScriptBuf, Option); + +impl Builder { + /// Constructs a new empty script. + #[inline] + pub const fn new() -> Self { Self(ScriptBuf::new(), None) } + + /// Constructs a new empty script builder with at least the specified capacity. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { Self(ScriptBuf::with_capacity(capacity), None) } + + /// Returns the length in bytes of the script. + pub fn len(&self) -> usize { self.0.len() } + + /// Checks whether the script is the empty script. + pub fn is_empty(&self) -> bool { self.0.is_empty() } + + /// Adds instructions to push an integer onto the stack. + /// + /// Integers are encoded as little-endian signed-magnitude numbers, but there are dedicated + /// opcodes to push some small integers. + /// + /// # Errors + /// + /// Only errors if `data == i32::MIN` (CScriptNum cannot have value -2^31). + pub fn push_int(mut self, n: i32) -> Result { + self.0.push_int(n)?; + self.1 = None; + Ok(self) + } + + /// Adds instructions to push an unchecked integer onto the stack. + /// + /// Integers are encoded as little-endian signed-magnitude numbers, but there are dedicated + /// opcodes to push some small integers. + /// + /// This function implements `CScript::push_int64` from Core `script.h`. + /// + /// > Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers. + /// > The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], + /// > but results may overflow (and are valid as long as they are not used in a subsequent + /// > numeric operation). CScriptNum enforces those semantics by storing results as + /// > an int64 and allowing out-of-range values to be returned as a vector of bytes but + /// > throwing an exception if arithmetic is done or the result is interpreted as an integer. + /// + /// Does not check whether `n` is in the range of [-2^31 +1...2^31 -1]. + pub fn push_int_unchecked(mut self, n: i64) -> Self { + self.0.push_int_unchecked(n); + self.1 = None; + self + } + + /// Adds instructions to push an integer onto the stack without optimization. + /// + /// This uses the explicit encoding regardless of the availability of dedicated opcodes. + pub(in crate::blockdata) fn push_int_non_minimal(mut self, data: i64) -> Self { + self.0.push_int_non_minimal(data); + self.1 = None; + self + } + + /// Adds instructions to push some arbitrary data onto the stack. + /// + /// If the data can be exactly produced by a numeric opcode, that opcode + /// will be used, since its behavior is equivalent but will not violate minimality + /// rules. To avoid this, use [`Builder::push_slice_non_minimal`] which will always + /// use a push opcode. + /// + /// However, this method does *not* enforce any numeric minimality rules. + /// If your pushes should be interpreted as numbers, ensure your input does + /// not have any leading zeros. In particular, the number 0 should be encoded + /// as an empty string rather than as a single 0 byte. + pub fn push_slice>(mut self, data: D) -> Self { + self.0.push_slice(data); + self.1 = None; + self + } + + /// Adds instructions to push some arbitrary data onto the stack without minimality. + /// + /// Standardness rules require push minimality according to [CheckMinimalPush] of core. + /// + /// [CheckMinimalPush]: + pub fn push_slice_non_minimal>(mut self, data: D) -> Self { + self.0.push_slice_non_minimal(data); + self.1 = None; + self + } + + /// Adds a single opcode to the script. + pub fn push_opcode(mut self, data: Opcode) -> Self { + self.0.push_opcode(data); + self.1 = Some(data); + self + } + + /// Adds an `OP_VERIFY` to the script or replaces the last opcode with VERIFY form. + /// + /// Some opcodes such as `OP_CHECKSIG` have a verify variant that works as if `VERIFY` was + /// in the script right after. To save space this function appends `VERIFY` only if + /// the most-recently-added opcode *does not* have an alternate `VERIFY` form. If it does + /// the last opcode is replaced. E.g., `OP_CHECKSIG` will become `OP_CHECKSIGVERIFY`. + /// + /// Note that existing `OP_*VERIFY` opcodes do not lead to the instruction being ignored + /// because `OP_VERIFY` consumes an item from the stack so ignoring them would change the + /// semantics. + pub fn push_verify(mut self) -> Self { + // "duplicated code" because we need to update `1` field + match opcode_to_verify(self.1) { + Some(opcode) => { + (self.0).as_byte_vec().pop(); + self.push_opcode(opcode) + } + None => self.push_opcode(OP_VERIFY), + } + } + + /// Adds instructions to push a public key onto the stack. + pub fn push_key(self, key: PublicKey) -> Self { + if key.compressed { + self.push_slice(key.inner.serialize()) + } else { + self.push_slice(key.inner.serialize_uncompressed()) + } + } + + /// Adds instructions to push an XOnly public key onto the stack. + pub fn push_x_only_key(self, x_only_key: XOnlyPublicKey) -> Self { + self.push_slice(x_only_key.serialize()) + } + + /// Adds instructions to push an absolute lock time onto the stack. + pub fn push_lock_time(self, lock_time: absolute::LockTime) -> Self { + self.push_int_unchecked(lock_time.to_consensus_u32().into()) + } + + /// Adds instructions to push a relative lock time onto the stack. + /// + /// This is used when creating scripts that use CHECKSEQUENCEVERIFY (CSV) to enforce + /// relative time locks. + pub fn push_relative_lock_time(self, lock_time: relative::LockTime) -> Self { + self.push_int_unchecked(lock_time.to_consensus_u32().into()) + } + + /// Adds instructions to push a sequence number onto the stack. + /// + /// # Deprecated + /// This method is deprecated in favor of `push_relative_lock_time`. + /// + /// In Bitcoin script semantics, when using CHECKSEQUENCEVERIFY, you typically + /// want to push a relative locktime value to be compared against the input's + /// sequence number, not the sequence number itself. + #[deprecated( + since = "TBD", + note = "Use push_relative_lock_time instead for working with timelocks in scripts" + )] + pub fn push_sequence(self, sequence: Sequence) -> Self { + self.push_int_unchecked(sequence.to_consensus_u32().into()) + } + + /// Converts the `Builder` into `ScriptBuf`. + pub fn into_script(self) -> ScriptBuf { self.0 } + + /// Converts the `Builder` into script bytes + pub fn into_bytes(self) -> Vec { self.0.into() } + + /// Returns the internal script + pub fn as_script(&self) -> &Script { &self.0 } + + /// Returns script bytes + pub fn as_bytes(&self) -> &[u8] { self.0.as_bytes() } +} + +impl Default for Builder { + fn default() -> Self { Self::new() } +} + +/// Constructs a new builder from an existing vector. +impl From> for Builder { + fn from(v: Vec) -> Self { + let script = ScriptBuf::from(v); + let last_op = script.last_opcode(); + Self(script, last_op) + } +} + +impl fmt::Display for Builder { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } +} + +impl fmt::Debug for Builder { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Display::fmt(self, f) } +} diff --git a/bitcoin/src/blockdata/script/instruction.rs b/bitcoin/src/blockdata/script/instruction.rs new file mode 100644 index 000000000..e7037591a --- /dev/null +++ b/bitcoin/src/blockdata/script/instruction.rs @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: CC0-1.0 + +use internals::script::{self, PushDataLenLen}; + +use super::{Error, PushBytes, Script, ScriptBufExtPriv as _}; +use crate::opcodes::{self, Opcode}; + +/// A "parsed opcode" which allows iterating over a [`Script`] in a more sensible way. +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +pub enum Instruction<'a> { + /// Push a bunch of data. + PushBytes(&'a PushBytes), + /// Some non-push opcode. + Op(Opcode), +} + +impl Instruction<'_> { + /// Returns the opcode if the instruction is not a data push. + pub fn opcode(&self) -> Option { + match self { + Instruction::Op(op) => Some(*op), + Instruction::PushBytes(_) => None, + } + } + + /// Returns the pushed bytes if the instruction is a data push. + pub fn push_bytes(&self) -> Option<&PushBytes> { + match self { + Instruction::Op(_) => None, + Instruction::PushBytes(bytes) => Some(bytes), + } + } + + /// Returns the number interpreted by the script parser + /// if it can be coerced into a number. + /// + /// This does not require the script num to be minimal. + pub fn script_num(&self) -> Option { + match self { + Instruction::Op(op) => { + let v = op.to_u8(); + match v { + // OP_PUSHNUM_1 ..= OP_PUSHNUM_16 + 0x51..=0x60 => Some(v as i64 - 0x50), + // OP_PUSHNUM_NEG1 + 0x4f => Some(-1), + _ => None, + } + } + Instruction::PushBytes(bytes) => + super::read_scriptint_non_minimal(bytes.as_bytes()).ok().map(i64::from), + } + } + + /// Returns the number of bytes required to encode the instruction in script. + pub(super) fn script_serialized_len(&self) -> usize { + match self { + Instruction::Op(_) => 1, + // The use of `ScriptSigBuf` here is arbitrary. Rust insists that we pick + // a specific tagged script type. + Instruction::PushBytes(bytes) => + super::ScriptSigBuf::reserved_len_for_slice(bytes.len()), + } + } + + /// Reads an integer from an Instruction, + /// returning Some(i64) for valid opcodes or pushed bytes, otherwise None + pub fn read_int(&self) -> Option { + match self { + Instruction::Op(op) => { + let v = op.to_u8(); + match v { + // OP_PUSHNUM_1 ..= OP_PUSHNUM_16 + 0x51..=0x60 => Some(v as i64 - 0x50), + // OP_PUSHNUM_NEG1 + 0x4f => Some(-1), + _ => None, + } + } + Instruction::PushBytes(bytes) => bytes.read_cltv_scriptint().ok(), + } + } +} + +/// Iterator over a script returning parsed opcodes. +#[derive(Debug, Clone)] +pub struct Instructions<'a> { + pub(crate) data: core::slice::Iter<'a, u8>, + pub(crate) enforce_minimal: bool, +} + +impl<'a> Instructions<'a> { + /// Views the remaining script as a slice. + /// + /// This is analogous to what [`core::str::Chars::as_str`] does. + pub fn as_script(&self) -> &'a Script { Script::from_bytes(self.data.as_slice()) } + + /// The number of remaining bytes in the script. + fn remaining_bytes(&self) -> usize { self.data.as_slice().len() } + + /// Sets the iterator to end so that it won't iterate any longer. + pub(super) fn kill(&mut self) { + let len = self.data.len(); + self.data.nth(len.max(1) - 1); + } + + /// Takes a `len` bytes long slice from iterator and returns it, advancing the iterator. + /// + /// If the iterator is not long enough [`Error::EarlyEndOfScript`] is returned and the iterator + /// is killed to avoid returning an infinite stream of errors. + pub(super) fn take_slice_or_kill(&mut self, len: u32) -> Result<&'a PushBytes, Error> { + let len = len as usize; + if self.data.len() >= len { + let slice = &self.data.as_slice()[..len]; + if len > 0 { + self.data.nth(len - 1); + } + + Ok(slice.try_into().expect("len was created from u32, so can't happen")) + } else { + self.kill(); + Err(Error::EarlyEndOfScript) + } + } + + pub(super) fn next_push_data_len( + &mut self, + len: PushDataLenLen, + min_push_len: usize, + ) -> Option, Error>> { + let n = match script::read_push_data_len(&mut self.data, len) { + Ok(n) => n, + Err(_) => { + self.kill(); + return Some(Err(Error::EarlyEndOfScript)); + } + }; + if self.enforce_minimal && n < min_push_len { + self.kill(); + return Some(Err(Error::NonMinimalPush)); + } + let result = n + .try_into() + .map_err(|_| Error::NumericOverflow) + .and_then(|n| self.take_slice_or_kill(n)) + .map(Instruction::PushBytes); + Some(result) + } +} + +impl<'a> Iterator for Instructions<'a> { + type Item = Result, Error>; + + fn next(&mut self) -> Option, Error>> { + let &byte = self.data.next()?; + + // classify parameter does not really matter here since we are only using + // it for pushes and nums + match Opcode::from(byte).classify(opcodes::ClassifyContext::Legacy) { + opcodes::Class::PushBytes(n) => { + // make sure safety argument holds across refactorings + let n: u32 = n; + + let op_byte = self.data.as_slice().first(); + match (self.enforce_minimal, op_byte, n) { + (true, Some(&op_byte), 1) + if op_byte == 0x81 || (op_byte > 0 && op_byte <= 16) => + { + self.kill(); + Some(Err(Error::NonMinimalPush)) + } + (_, None, 0) => { + // the iterator is already empty, may as well use this information to avoid + // whole take_slice_or_kill function + Some(Ok(Instruction::PushBytes(PushBytes::empty()))) + } + _ => Some(self.take_slice_or_kill(n).map(Instruction::PushBytes)), + } + } + opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA1) => + self.next_push_data_len(PushDataLenLen::One, 76), + opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA2) => + self.next_push_data_len(PushDataLenLen::Two, 0x100), + opcodes::Class::Ordinary(opcodes::Ordinary::OP_PUSHDATA4) => + self.next_push_data_len(PushDataLenLen::Four, 0x10000), + // Everything else we can push right through + _ => Some(Ok(Instruction::Op(Opcode::from(byte)))), + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.data.as_slice().is_empty() { + (0, Some(0)) + } else { + // There will not be more instructions than bytes + (1, Some(self.data.len())) + } + } +} + +impl core::iter::FusedIterator for Instructions<'_> {} + +/// Iterator over script instructions with their positions. +/// +/// The returned indices can be used for slicing [`Script`] [safely](Script#slicing-safety). +/// +/// This is analogous to [`core::str::CharIndices`]. +#[derive(Debug, Clone)] +pub struct InstructionIndices<'a> { + instructions: Instructions<'a>, + pos: usize, +} + +impl<'a> InstructionIndices<'a> { + /// Views the remaining script as a slice. + /// + /// This is analogous to what [`core::str::Chars::as_str`] does. + #[inline] + pub fn as_script(&self) -> &'a Script { self.instructions.as_script() } + + /// Constructs a new `Self` setting `pos` to 0. + pub(super) fn from_instructions(instructions: Instructions<'a>) -> Self { + InstructionIndices { instructions, pos: 0 } + } + + pub(super) fn remaining_bytes(&self) -> usize { self.instructions.remaining_bytes() } + + /// Modifies the iterator using `next_fn` returning the next item. + /// + /// This generically computes the new position and maps the value to be returned from iterator + /// method. + pub(super) fn next_with Option, Error>>>( + &mut self, + next_fn: F, + ) -> Option<::Item> { + let prev_remaining = self.remaining_bytes(); + let prev_pos = self.pos; + let instruction = next_fn(self)?; + // No overflow: there must be less remaining bytes now than previously + let consumed = prev_remaining - self.remaining_bytes(); + // No overflow: sum will never exceed slice length which itself can't exceed `usize` + self.pos += consumed; + Some(instruction.map(move |instruction| (prev_pos, instruction))) + } +} + +impl<'a> Iterator for InstructionIndices<'a> { + /// The `usize` in the tuple represents index at which the returned `Instruction` is located. + type Item = Result<(usize, Instruction<'a>), Error>; + + fn next(&mut self) -> Option { self.next_with(|this| this.instructions.next()) } + + #[inline] + fn size_hint(&self) -> (usize, Option) { self.instructions.size_hint() } + + // the override avoids computing pos multiple times + fn nth(&mut self, n: usize) -> Option { + self.next_with(|this| this.instructions.nth(n)) + } +} + +impl core::iter::FusedIterator for InstructionIndices<'_> {} diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs new file mode 100644 index 000000000..066437692 --- /dev/null +++ b/bitcoin/src/blockdata/script/mod.rs @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin scripts. +//! +//! This module provides the structures and functions needed to support scripts. +//! +//!
+//! What is Bitcoin script +//! +//! Scripts define Bitcoin's digital signature scheme: a signature is formed +//! from a script (the second half of which is defined by a coin to be spent, +//! and the first half provided by the spending transaction), and is valid if and only if +//! the script leaves `TRUE` on the stack after being evaluated. Bitcoin's +//! script is a stack-based assembly language similar in spirit to [Forth]. +//! +//! Script is represented as a sequence of bytes on the wire, each byte representing an operation, +//! or data to be pushed on the stack. +//! +//! See [Bitcoin Wiki: Script][wiki-script] for more information. +//! +//! [Forth]: https://en.wikipedia.org/wiki/Forth_(programming_language) +//! +//! [wiki-script]: https://en.bitcoin.it/wiki/Script +//!
+//! +//! In this library we chose to keep the byte representation in memory and decode opcodes only when +//! processing the script. This is similar to Rust choosing to represent strings as UTF-8-encoded +//! bytes rather than slice of `char`s. In both cases the individual items can have different sizes +//! and forcing them to be larger would waste memory and, in case of Bitcoin script, even some +//! performance (forcing allocations). +//! +//! # `Script` vs `ScriptBuf` vs `Builder` +//! +//! These are the most important types in this module and they are quite similar, so it may seem +//! confusing what the differences are. `Script` is an unsized type much like `str` or `Path` are +//! and `ScriptBuf` is an owned counterpart to `Script` just like `String` is an owned counterpart +//! to `str`. +//! +//! However it is common to construct an owned script and then pass it around. For this case a +//! builder API is more convenient. To support this we provide `Builder` type which is very similar +//! to `ScriptBuf` but its methods take `self` instead of `&mut self` and return `Self`. It also +//! contains a cache that may make some modifications faster. This cache is usually not needed +//! outside of creating the script. +//! +//! At the time of writing there's only one operation using the cache - `push_verify`, so the cache +//! is minimal but we may extend it in the future if needed. + +mod borrowed; +mod builder; +mod instruction; +mod owned; +mod push_bytes; +#[cfg(test)] +mod tests; +pub mod witness_program; +pub mod witness_version; + +use core::convert::Infallible; +use core::fmt; + +use io::{BufRead, Write}; + +use self::witness_version::WitnessVersion; +use crate::consensus::{encode, Decodable, Encodable}; +use crate::internal_macros::impl_asref_push_bytes; +use crate::key::WPubkeyHash; +use crate::opcodes::all::*; +use crate::opcodes::Opcode; +use crate::prelude::Vec; +use crate::OutPoint; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + borrowed::{ScriptExt, TapScriptExt, ScriptPubKeyExt, WitnessScriptExt, ScriptSigExt}, + builder::Builder, + instruction::{Instruction, Instructions, InstructionIndices}, + owned::{ScriptBufExt, ScriptPubKeyBufExt}, + push_bytes::{PushBytes, PushBytesBuf, PushBytesError, PushBytesErrorReport, ScriptIntError}, +}; +#[doc(inline)] +pub use primitives::script::{ + RedeemScript, RedeemScriptBuf, RedeemScriptSizeError, RedeemScriptTag, Script, ScriptBuf, + ScriptHash, ScriptHashableTag, ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyTag, ScriptSig, + ScriptSigBuf, ScriptSigTag, Tag, TapScript, TapScriptBuf, TapScriptTag, WScriptHash, + WitnessScript, WitnessScriptBuf, WitnessScriptSizeError, WitnessScriptTag, +}; + +pub(crate) use self::borrowed::ScriptExtPriv; +pub(crate) use self::owned::ScriptBufExtPriv; + +impl_asref_push_bytes!(ScriptHash, WScriptHash); + +/// Constructs a new [`WitnessScriptBuf`] containing the script code used for spending a P2WPKH output. +/// +/// The `scriptCode` is described in [BIP-0143]. +/// +/// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and +/// should not be used as one. It is a special template defined in BIP-0143 which is used +/// in place of a witness script for purposes of sighash computation. +/// +/// [BIP-0143]: +pub fn p2wpkh_script_code(wpkh: WPubkeyHash) -> WitnessScriptBuf { + Builder::new() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice(wpkh) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_CHECKSIG) + .into_script() +} + +/// Encodes an integer in script(minimal CScriptNum) format. +/// +/// Writes bytes into the buffer and returns the number of bytes written. +/// +/// Note that `write_scriptint`/`read_scriptint` do not roundtrip if the value written requires +/// more than 4 bytes, this is in line with Bitcoin Core (see [`CScriptNum::serialize`]). +/// +/// [`CScriptNum::serialize`]: +pub fn write_scriptint(out: &mut [u8; 8], n: i64) -> usize { + let mut len = 0; + if n == 0 { + return len; + } + + let neg = n < 0; + + let mut abs = n.unsigned_abs(); + while abs > 0xFF { + out[len] = (abs & 0xFF) as u8; + len += 1; + abs >>= 8; + } + // If the number's value causes the sign bit to be set, we need an extra + // byte to get the correct value and correct sign bit + if abs & 0x80 != 0 { + out[len] = abs as u8; + len += 1; + out[len] = if neg { 0x80u8 } else { 0u8 }; + len += 1; + } + // Otherwise we just set the sign bit ourselves + else { + abs |= if neg { 0x80 } else { 0 }; + out[len] = abs as u8; + len += 1; + } + len +} + +/// Decodes an integer in script format without non-minimal error. +/// +/// The overflow error for slices over 4 bytes long is still there. +/// +/// See [`push_bytes::PushBytes::read_scriptint`] for a description of some subtleties of +/// this function. +pub fn read_scriptint_non_minimal(v: &[u8]) -> Result { + if v.is_empty() { + return Ok(0); + } + if v.len() > 4 { + return Err(ScriptIntError::NumericOverflow); + } + + let ret = scriptint_parse(v); + Ok(i32::try_from(ret).expect("4 bytes or less fits in an i32")) +} + +// Caller to guarantee that `v` is not empty. +fn scriptint_parse(v: &[u8]) -> i64 { + let (mut ret, sh) = v.iter().fold((0, 0), |(acc, sh), n| (acc + ((*n as i64) << sh), sh + 8)); + if v[v.len() - 1] & 0x80 != 0 { + ret &= (1 << (sh - 1)) - 1; + ret = -ret; + } + ret +} + +/// Decodes a boolean. +/// +/// This is like "`read_scriptint` then map 0 to false and everything +/// else as true", except that the overflow rules don't apply. +#[inline] +pub fn read_scriptbool(v: &[u8]) -> bool { + match v.split_last() { + Some((last, rest)) => !((last & !0x80 == 0x00) && rest.iter().all(|&b| b == 0)), + None => false, + } +} + +fn opcode_to_verify(opcode: Option) -> Option { + opcode.and_then(|opcode| match opcode { + OP_EQUAL => Some(OP_EQUALVERIFY), + OP_NUMEQUAL => Some(OP_NUMEQUALVERIFY), + OP_CHECKSIG => Some(OP_CHECKSIGVERIFY), + OP_CHECKMULTISIG => Some(OP_CHECKMULTISIGVERIFY), + _ => None, + }) +} + +/// Generates P2WSH-type of scriptPubkey with a given [`WitnessVersion`] and the program bytes. +/// Does not do any checks on version or program length. +/// +/// Convenience method used by `new_p2a`, `new_p2wpkh`, `new_p2wsh`, `new_p2tr`, and `new_p2tr_tweaked`. +pub(crate) fn new_witness_program_unchecked, Tg>( + version: WitnessVersion, + program: T, +) -> ScriptBuf { + let program = program.as_ref(); + debug_assert!(program.len() >= 2 && program.len() <= 40); + // In SegWit v0, the program must be either 20 bytes (P2WPKH) or 32 bytes (P2WSH) long. + debug_assert!(version != WitnessVersion::V0 || program.len() == 20 || program.len() == 32); + Builder::new().push_opcode(version.into()).push_slice(program).into_script() +} + +impl Encodable for Script { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + crate::consensus::encode::consensus_encode_with_size(self.as_bytes(), w) + } +} + +impl Encodable for ScriptBuf { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.as_script().consensus_encode(w) + } +} + +impl Decodable for ScriptBuf { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let v: Vec = Decodable::consensus_decode_from_finite_reader(r)?; + Ok(Self::from_bytes(v)) + } +} + +/// Ways that a script might fail. Not everything is split up as +/// much as it could be; patches welcome if more detailed errors +/// would help you. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// Something did a non-minimal push; for more information see + /// + NonMinimalPush, + /// Some opcode expected a parameter but it was missing or truncated. + EarlyEndOfScript, + /// Tried to read an array off the stack as a number when it was more than 4 bytes. + NumericOverflow, + /// Can not find the spent output. + UnknownSpentOutput(OutPoint), + /// Can not serialize the spending transaction. + Serialization, +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::NonMinimalPush => f.write_str("non-minimal datapush"), + Self::EarlyEndOfScript => f.write_str("unexpected end of script"), + Self::NumericOverflow => + f.write_str("numeric overflow (number on stack larger than 4 bytes)"), + Self::UnknownSpentOutput(ref point) => write!(f, "unknown spent output: {}", point), + Self::Serialization => + f.write_str("can not serialize the spending transaction in Transaction::verify()"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::NonMinimalPush + | Self::EarlyEndOfScript + | Self::NumericOverflow + | Self::UnknownSpentOutput(_) + | Self::Serialization => None, + } + } +} diff --git a/bitcoin/src/blockdata/script/owned.rs b/bitcoin/src/blockdata/script/owned.rs new file mode 100644 index 000000000..b910dced7 --- /dev/null +++ b/bitcoin/src/blockdata/script/owned.rs @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: CC0-1.0 + +#[cfg(doc)] +use core::ops::Deref; + +use hex::FromHex as _; +use internals::ToU64 as _; + +use super::{ + opcode_to_verify, write_scriptint, Builder, Error, Instruction, PushBytes, ScriptBuf, + ScriptExtPriv as _, ScriptPubKeyBuf, +}; +use crate::key::{ + PubkeyHash, PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey, WPubkeyHash, +}; +use crate::opcodes::all::*; +use crate::opcodes::{self, Opcode}; +use crate::prelude::Vec; +use crate::script::witness_program::{WitnessProgram, P2A_PROGRAM}; +use crate::script::witness_version::WitnessVersion; +use crate::script::{self, ScriptHash, WScriptHash}; +use crate::taproot::TapNodeHash; +use crate::{consensus, internal_macros}; + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`ScriptBuf`] type. + pub trait ScriptBufExt impl for ScriptBuf { + /// Constructs a new script builder + fn builder() -> Builder { Builder::new() } + + /// Adds instructions to push an integer onto the stack. + /// + /// Integers are encoded as little-endian signed-magnitude numbers, but there are dedicated + /// opcodes to push some small integers. + /// + /// # Errors + /// + /// Only errors if `data == i32::MIN` (CScriptNum cannot have value -2^31). + fn push_int(&mut self, n: i32) -> Result<(), Error> { + if n == i32::MIN { + // ref: https://github.com/bitcoin/bitcoin/blob/cac846c2fbf6fc69bfc288fd387aa3f68d84d584/src/script/script.h#L230 + Err(Error::NumericOverflow) + } else { + self.push_int_unchecked(n.into()); + Ok(()) + } + } + + /// Adds instructions to push an unchecked integer onto the stack. + /// + /// Integers are encoded as little-endian signed-magnitude numbers, but there are dedicated + /// opcodes to push some small integers. + /// + /// This function implements `CScript::push_int64` from Core `script.h`. + /// + /// > Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers. + /// > The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1], + /// > but results may overflow (and are valid as long as they are not used in a subsequent + /// > numeric operation). CScriptNum enforces those semantics by storing results as + /// > an int64 and allowing out-of-range values to be returned as a vector of bytes but + /// > throwing an exception if arithmetic is done or the result is interpreted as an integer. + /// + /// Does not check whether `n` is in the range of [-2^31 +1...2^31 -1]. + fn push_int_unchecked(&mut self, n: i64) { + match n { + -1 => self.push_opcode(OP_1NEGATE), + 0 => self.push_opcode(OP_PUSHBYTES_0), + 1..=16 => self.push_opcode(Opcode::from(n as u8 + (OP_1.to_u8() - 1))), + _ => self.push_int_non_minimal(n), + } + } + + /// Adds a single opcode to the script. + fn push_opcode(&mut self, data: Opcode) { self.as_byte_vec().push(data.to_u8()); } + + /// Adds instructions to push some arbitrary data onto the stack. + /// + /// If the data can be exactly produced by a numeric opcode, that opcode + /// will be used, since its behavior is equivalent but will not violate minimality + /// rules. To avoid this, use [`ScriptBuf::push_slice_non_minimal`] which will always + /// use a push opcode. + /// + /// However, this method does *not* enforce any numeric minimality rules. + /// If your pushes should be interpreted as numbers, ensure your input does + /// not have any leading zeros. In particular, the number 0 should be encoded + /// as an empty string rather than as a single 0 byte. + fn push_slice>(&mut self, data: D) { + let bytes = data.as_ref().as_bytes(); + if bytes.len() == 1 { + match bytes[0] { + 0x81 => { self.push_opcode(OP_1NEGATE); }, + 1..=16 => { self.push_opcode(Opcode::from(bytes[0] + (OP_1.to_u8() - 1))); }, + _ => { self.push_slice_non_minimal(data); }, + } + } else { + self.push_slice_non_minimal(data); + } + } + + /// Adds instructions to push some arbitrary data onto the stack without minimality. + /// + /// Standardness rules require push minimality according to [CheckMinimalPush] of core. + /// + /// [CheckMinimalPush]: + fn push_slice_non_minimal>(&mut self, data: D) { + let data = data.as_ref(); + self.reserve(Self::reserved_len_for_slice(data.len())); + self.push_slice_no_opt(data); + } + + /// Add a single instruction to the script. + /// + /// # Panics + /// + /// The method panics if the instruction is a data push with length greater or equal to + /// 0x100000000. + fn push_instruction(&mut self, instruction: Instruction<'_>) { + match instruction { + Instruction::Op(opcode) => self.push_opcode(opcode), + Instruction::PushBytes(bytes) => self.push_slice(bytes), + } + } + + /// Like push_instruction, but avoids calling `reserve` to not re-check the length. + fn push_instruction_no_opt(&mut self, instruction: Instruction<'_>) { + match instruction { + Instruction::Op(opcode) => self.push_opcode(opcode), + Instruction::PushBytes(bytes) => self.push_slice_no_opt(bytes), + } + } + + /// Adds an `OP_VERIFY` to the script or replaces the last opcode with VERIFY form. + /// + /// Some opcodes such as `OP_CHECKSIG` have a verify variant that works as if `VERIFY` was + /// in the script right after. To save space this function appends `VERIFY` only if + /// the most-recently-added opcode *does not* have an alternate `VERIFY` form. If it does + /// the last opcode is replaced. E.g., `OP_CHECKSIG` will become `OP_CHECKSIGVERIFY`. + /// + /// Note that existing `OP_*VERIFY` opcodes do not lead to the instruction being ignored + /// because `OP_VERIFY` consumes an item from the stack so ignoring them would change the + /// semantics. + /// + /// This function needs to iterate over the script to find the last instruction. Prefer + /// `Builder` if you're creating the script from scratch or if you want to push `OP_VERIFY` + /// multiple times. + fn scan_and_push_verify(&mut self) { self.push_verify(self.last_opcode()); } + + /// Constructs a new [`ScriptBuf`] from a hex string. + /// + /// The input string is expected to be consensus encoded i.e., includes the length prefix. + fn from_hex_prefixed(s: &str) -> Result + where Self: Sized + { + consensus::encode::deserialize_hex(s) + } + + /// Constructs a new [`ScriptBuf`] from a hex string. + #[deprecated(since = "TBD", note = "use `from_hex_no_length_prefix()` instead")] + fn from_hex(s: &str) -> Result + where Self: Sized + { + Self::from_hex_no_length_prefix(s) + } + + /// Constructs a new [`ScriptBuf`] from a hex string. + /// + /// This is **not** consensus encoding. If your hex string is a consensus encoded script + /// then use `ScriptBuf::from_hex_prefixed`. + fn from_hex_no_length_prefix(s: &str) -> Result + where Self: Sized + { + let v = Vec::from_hex(s)?; + Ok(Self::from_bytes(v)) + } + + // This belongs only on RedeemScript and ScriptPubKey + /// Generates P2WPKH-type of scriptPubkey. + fn new_p2wpkh(pubkey_hash: WPubkeyHash) -> Self { + // pubkey hash is 20 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0) + script::new_witness_program_unchecked(WitnessVersion::V0, pubkey_hash) + } + + } +} + +crate::internal_macros::define_extension_trait! { + /// Extension functionality for the [`ScriptPubKeyBuf`] type. + pub trait ScriptPubKeyBufExt impl for ScriptPubKeyBuf { + /// Generates OP_RETURN-type of scriptPubkey for the given data. + fn new_op_return>(data: T) -> Self { + Builder::new().push_opcode(OP_RETURN).push_slice(data).into_script() + } + + /// Generates P2PK-type of scriptPubkey. + fn new_p2pk(pubkey: PublicKey) -> Self { + Builder::new().push_key(pubkey).push_opcode(OP_CHECKSIG).into_script() + } + + /// Generates P2PKH-type of scriptPubkey. + fn new_p2pkh(pubkey_hash: PubkeyHash) -> Self { + Builder::new() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice(pubkey_hash) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_CHECKSIG) + .into_script() + } + + /// Generates P2SH-type of scriptPubkey with a given hash of the redeem script. + fn new_p2sh(script_hash: ScriptHash) -> Self { + Builder::new() + .push_opcode(OP_HASH160) + .push_slice(script_hash) + .push_opcode(OP_EQUAL) + .into_script() + } + + /// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script. + fn new_p2wsh(script_hash: WScriptHash) -> Self { + // script hash is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0) + script::new_witness_program_unchecked(WitnessVersion::V0, script_hash) + } + + /// Generates P2TR for script spending path using an internal public key and some optional + /// script tree Merkle root. + fn new_p2tr>( + internal_key: K, + merkle_root: Option, + ) -> Self { + let internal_key = internal_key.into(); + let (output_key, _) = internal_key.tap_tweak(merkle_root); + // output key is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv1) + script::new_witness_program_unchecked(WitnessVersion::V1, output_key.serialize()) + } + + /// Generates P2TR for key spending path for a known [`TweakedPublicKey`]. + fn new_p2tr_tweaked(output_key: TweakedPublicKey) -> Self { + // output key is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv1) + script::new_witness_program_unchecked(WitnessVersion::V1, output_key.serialize()) + } + + /// Generates pay to anchor output. + fn new_p2a() -> Self { + script::new_witness_program_unchecked(WitnessVersion::V1, P2A_PROGRAM) + } + + /// Generates P2WSH-type of scriptPubkey with a given [`WitnessProgram`]. + fn new_witness_program(witness_program: &WitnessProgram) -> Self { + Builder::new() + .push_opcode(witness_program.version().into()) + .push_slice(witness_program.program()) + .into_script() + } + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::ScriptBuf {} +} + +internal_macros::define_extension_trait! { + pub(crate) trait ScriptBufExtPriv impl for ScriptBuf { + /// Pretends to convert `&mut ScriptBuf` to `&mut Vec` so that it can be modified. + /// + /// Note: if the returned value leaks the original `ScriptBuf` will become empty. + fn as_byte_vec(&mut self) -> ScriptBufAsVec<'_, T> { + let vec = core::mem::take(self).into_bytes(); + ScriptBufAsVec(self, vec) + } + + /// Pushes the slice without reserving + fn push_slice_no_opt(&mut self, data: &PushBytes) { + let mut this = self.as_byte_vec(); + // Start with a PUSH opcode + match data.len().to_u64() { + n if n < opcodes::Ordinary::OP_PUSHDATA1 as u64 => { + this.push(n as u8); + } + n if n < 0x100 => { + this.push(opcodes::Ordinary::OP_PUSHDATA1.to_u8()); + this.push(n as u8); + } + n if n < 0x10000 => { + this.push(opcodes::Ordinary::OP_PUSHDATA2.to_u8()); + this.push((n % 0x100) as u8); + this.push((n / 0x100) as u8); + } + // `PushBytes` enforces len < 0x100000000 + n => { + this.push(opcodes::Ordinary::OP_PUSHDATA4.to_u8()); + this.push((n % 0x100) as u8); + this.push(((n / 0x100) % 0x100) as u8); + this.push(((n / 0x10000) % 0x100) as u8); + this.push((n / 0x1000000) as u8); + } + } + // Then push the raw bytes + this.extend_from_slice(data.as_bytes()); + } + + /// Computes the sum of `len` and the length of an appropriate push opcode. + fn reserved_len_for_slice(len: usize) -> usize { + len + match len { + 0..=0x4b => 1, + 0x4c..=0xff => 2, + 0x100..=0xffff => 3, + // we don't care about oversized, the other fn will panic anyway + _ => 5, + } + } + + /// Adds an `OP_VERIFY` to the script or changes the most-recently-added opcode to `VERIFY` + /// alternative. + /// + /// See the public fn [`Self::scan_and_push_verify`] to learn more. + fn push_verify(&mut self, last_opcode: Option) { + match opcode_to_verify(last_opcode) { + Some(opcode) => { + self.as_byte_vec().pop(); + self.push_opcode(opcode); + } + None => self.push_opcode(OP_VERIFY), + } + } + + /// Adds instructions to push an integer onto the stack without optimization. + /// + /// This uses the explicit encoding regardless of the availability of dedicated opcodes. + fn push_int_non_minimal(&mut self, data: i64) { + let mut buf = [0u8; 8]; + let len = write_scriptint(&mut buf, data); + self.reserve(Self::reserved_len_for_slice(len)); + self.push_slice_no_opt(&<&PushBytes>::from(&buf)[..len]); + } + } +} + +impl<'a, Tg> core::iter::FromIterator> for ScriptBuf { + fn from_iter(iter: T) -> Self + where + T: IntoIterator>, + { + let mut script = Self::new(); + script.extend(iter); + script + } +} + +impl<'a, Tg> Extend> for ScriptBuf { + fn extend(&mut self, iter: T) + where + T: IntoIterator>, + { + let iter = iter.into_iter(); + // Most of Bitcoin scripts have only a few opcodes, so we can avoid reallocations in many + // cases. + if iter.size_hint().1.map(|max| max < 6).unwrap_or(false) { + let mut iter = iter.fuse(); + // `MaybeUninit` might be faster but we don't want to introduce more `unsafe` than + // required. + let mut head = [None; 5]; + let mut total_size = 0; + for (head, instr) in head.iter_mut().zip(&mut iter) { + total_size += instr.script_serialized_len(); + *head = Some(instr); + } + // Incorrect impl of `size_hint` breaks `Iterator` contract so we're free to panic. + assert!( + iter.next().is_none(), + "Buggy implementation of `Iterator` on {} returns invalid upper bound", + core::any::type_name::() + ); + self.reserve(total_size); + for instr in head.iter().cloned().flatten() { + self.push_instruction_no_opt(instr); + } + } else { + for instr in iter { + self.push_instruction(instr); + } + } + } +} + +/// Pretends that this is a mutable reference to [`ScriptBuf`]'s internal buffer. +/// +/// In reality the backing `Vec` is swapped with an empty one and this is holding both the +/// reference and the vec. The vec is put back when this drops so it also covers panics. (But not +/// leaks, which is OK since we never leak.) +pub(crate) struct ScriptBufAsVec<'a, T>(&'a mut ScriptBuf, Vec); + +impl core::ops::Deref for ScriptBufAsVec<'_, T> { + type Target = Vec; + + fn deref(&self) -> &Self::Target { &self.1 } +} + +impl core::ops::DerefMut for ScriptBufAsVec<'_, T> { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.1 } +} + +impl Drop for ScriptBufAsVec<'_, T> { + fn drop(&mut self) { + let vec = core::mem::take(&mut self.1); + *(self.0) = ScriptBuf::from_bytes(vec); + } +} diff --git a/bitcoin/src/blockdata/script/push_bytes.rs b/bitcoin/src/blockdata/script/push_bytes.rs new file mode 100644 index 000000000..dd19edd12 --- /dev/null +++ b/bitcoin/src/blockdata/script/push_bytes.rs @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Contains `PushBytes` & co + +use core::ops::{Deref, DerefMut}; +use core::fmt; + +use crate::crypto::{ecdsa, taproot}; +use crate::prelude::{Borrow, BorrowMut}; +use crate::script; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +// This is not the usual re-export, `primitive` here is a code audit thing. +pub use self::primitive::{PushBytes, PushBytesBuf}; + +/// This module only contains required operations so that outside functions wouldn't accidentally +/// break invariants. Therefore auditing this module should be sufficient. +mod primitive { + use core::ops::{ + Bound, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, + RangeToInclusive, + }; + + use super::PushBytesError; + use crate::prelude::{ToOwned, Vec}; + + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + fn check_limit(_: usize) -> Result<(), PushBytesError> { Ok(()) } + + #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] + fn check_limit(len: usize) -> Result<(), PushBytesError> { + if len < 0x100000000 { + Ok(()) + } else { + Err(PushBytesError { len }) + } + } + + internals::transparent_newtype! { + /// Byte slices that can be in Bitcoin script. + /// + /// The encoding of Bitcoin script restricts data pushes to be less than 2^32 bytes long. + /// This type represents slices that are guaranteed to be within the limit so they can be put in + /// the script safely. + #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] + pub struct PushBytes([u8]); + + impl PushBytes { + /// Constructs a new `&PushBytes` without checking the length. + /// + /// The caller is responsible for checking that the length is less than the 2^32. + fn from_slice_unchecked(bytes: &_) -> &Self; + + /// Constructs a new `&mut PushBytes` without checking the length. + /// + /// The caller is responsible for checking that the length is less than the 2^32. + fn from_mut_slice_unchecked(bytes: &mut _) -> &mut Self; + } + } + + impl PushBytes { + /// Constructs an empty `&PushBytes`. + pub fn empty() -> &'static Self { Self::from_slice_unchecked(&[]) } + + /// Returns the underlying bytes. + pub fn as_bytes(&self) -> &[u8] { &self.0 } + + /// Returns the underlying mutable bytes. + pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 } + } + + macro_rules! delegate_index { + ($($type:ty),* $(,)?) => { + $( + impl Index<$type> for PushBytes { + type Output = Self; + + #[inline] + #[track_caller] + fn index(&self, index: $type) -> &Self::Output { + Self::from_slice_unchecked(&self.0[index]) + } + } + + impl IndexMut<$type> for PushBytes { + #[inline] + #[track_caller] + fn index_mut(&mut self, index: $type) -> &mut Self::Output { + Self::from_mut_slice_unchecked(&mut self.0[index]) + } + } + )* + } + } + + delegate_index!( + Range, + RangeFrom, + RangeTo, + RangeFull, + RangeInclusive, + RangeToInclusive, + (Bound, Bound) + ); + + impl Index for PushBytes { + type Output = u8; + + #[inline] + #[track_caller] + fn index(&self, index: usize) -> &Self::Output { &self.0[index] } + } + + impl IndexMut for PushBytes { + #[inline] + #[track_caller] + fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.0[index] } + } + + impl<'a> TryFrom<&'a [u8]> for &'a PushBytes { + type Error = PushBytesError; + + fn try_from(bytes: &'a [u8]) -> Result { + check_limit(bytes.len())?; + Ok(PushBytes::from_slice_unchecked(bytes)) + } + } + + impl<'a> TryFrom<&'a mut [u8]> for &'a mut PushBytes { + type Error = PushBytesError; + + fn try_from(bytes: &'a mut [u8]) -> Result { + check_limit(bytes.len())?; + Ok(PushBytes::from_mut_slice_unchecked(bytes)) + } + } + + macro_rules! from_array { + ($($len:literal),* $(,)?) => { + $( + impl<'a> From<&'a [u8; $len]> for &'a PushBytes { + fn from(bytes: &'a [u8; $len]) -> Self { + // Check that the macro wasn't called with a wrong number. + const _: () = [(); 1][($len >= 0x100000000u64) as usize]; + PushBytes::from_slice_unchecked(bytes) + } + } + + impl<'a> From<&'a mut [u8; $len]> for &'a mut PushBytes { + fn from(bytes: &'a mut [u8; $len]) -> Self { + // Macro check already above, no need to duplicate. + // We know the size of array statically and we checked macro input. + PushBytes::from_mut_slice_unchecked(bytes) + } + } + + impl AsRef for [u8; $len] { + fn as_ref(&self) -> &PushBytes { + self.into() + } + } + + impl AsMut for [u8; $len] { + fn as_mut(&mut self) -> &mut PushBytes { + self.into() + } + } + + impl From<[u8; $len]> for PushBytesBuf { + fn from(bytes: [u8; $len]) -> Self { + PushBytesBuf(Vec::from(&bytes)) + } + } + + impl<'a> From<&'a [u8; $len]> for PushBytesBuf { + fn from(bytes: &'a [u8; $len]) -> Self { + PushBytesBuf(Vec::from(bytes)) + } + } + )* + } + } + + // Sizes up to 76 to support all pubkey and signature sizes + from_array! { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76 + } + + /// Owned, growable counterpart to `PushBytes`. + #[derive(Default, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + pub struct PushBytesBuf(Vec); + + impl PushBytesBuf { + /// Constructs an empty `PushBytesBuf`. + #[inline] + pub const fn new() -> Self { Self(Vec::new()) } + + /// Constructs an empty `PushBytesBuf` with reserved capacity. + pub fn with_capacity(capacity: usize) -> Self { Self(Vec::with_capacity(capacity)) } + + /// Reserve capacity for `additional_capacity` bytes. + pub fn reserve(&mut self, additional_capacity: usize) { + self.0.reserve(additional_capacity) + } + + /// Try pushing a single byte. + /// + /// # Errors + /// + /// This method fails if `self` would exceed the limit. + #[allow(deprecated)] + pub fn push(&mut self, byte: u8) -> Result<(), PushBytesError> { + // This is OK on 32 bit archs since vec has its own check and this check is pointless. + check_limit(self.0.len().saturating_add(1))?; + self.0.push(byte); + Ok(()) + } + + /// Try appending a slice to `PushBytesBuf` + /// + /// # Errors + /// + /// This method fails if `self` would exceed the limit. + pub fn extend_from_slice(&mut self, bytes: &[u8]) -> Result<(), PushBytesError> { + let len = self.0.len().saturating_add(bytes.len()); + check_limit(len)?; + self.0.extend_from_slice(bytes); + Ok(()) + } + + /// Remove the last byte from buffer if any. + pub fn pop(&mut self) -> Option { self.0.pop() } + + /// Remove the byte at `index` and return it. + /// + /// # Panics + /// + /// This method panics if `index` is out of bounds. + #[track_caller] + pub fn remove(&mut self, index: usize) -> u8 { self.0.remove(index) } + + /// Remove all bytes from buffer without affecting capacity. + pub fn clear(&mut self) { self.0.clear() } + + /// Remove bytes from buffer past `len`. + pub fn truncate(&mut self, len: usize) { self.0.truncate(len) } + + /// Extracts `PushBytes` slice + pub fn as_push_bytes(&self) -> &PushBytes { + // length guaranteed by our invariant + PushBytes::from_slice_unchecked(&self.0) + } + + /// Extracts mutable `PushBytes` slice + pub fn as_mut_push_bytes(&mut self) -> &mut PushBytes { + // length guaranteed by our invariant + PushBytes::from_mut_slice_unchecked(&mut self.0) + } + + /// Accesses inner `Vec` - provided for `super` to impl other methods. + pub(super) fn inner(&self) -> &Vec { &self.0 } + } + + impl From for Vec { + fn from(value: PushBytesBuf) -> Self { value.0 } + } + + impl TryFrom> for PushBytesBuf { + type Error = PushBytesError; + + fn try_from(vec: Vec) -> Result { + // check len + let _: &PushBytes = vec.as_slice().try_into()?; + Ok(Self(vec)) + } + } + + impl ToOwned for PushBytes { + type Owned = PushBytesBuf; + + fn to_owned(&self) -> Self::Owned { PushBytesBuf(self.0.to_owned()) } + } +} + +impl PushBytes { + /// Returns the number of bytes in buffer. + pub fn len(&self) -> usize { self.as_bytes().len() } + + /// Returns true if the buffer contains zero bytes. + pub fn is_empty(&self) -> bool { self.as_bytes().is_empty() } + + /// Decodes an integer in script(minimal CScriptNum) format. + /// + /// This code is based on the + /// [`CScriptNum` constructor in Bitcoin Core](https://github.com/bitcoin/bitcoin/blob/99a4ddf5ab1b3e514d08b90ad8565827fda7b63b/src/script/script.h#L245) + /// + /// # Errors + /// + /// * [`ScriptIntError::NumericOverflow`] if result is not in range [-2^39 +1...2^39 -1]. + /// * [`ScriptIntError::NonMinimal`] if encoding is non-minimal. + pub fn read_scriptint(&self) -> Result { + // Cast is safe, since the function already checks for byte length > 4 + let ret = self.read_scriptint_internal(4)?; + Ok(i32::try_from(ret).expect("4 bytes or less fits in an i32")) + } + + /// Decodes an integer in script(minimal CScriptNum) format. + /// + /// This is suitable to read input values for CHECKLOCKTIMEVERIFY instructions. + /// + /// Notice that this fails on overflow: the result is the same as in bitcoind, that only 4-byte + /// signed-magnitude values may be read as numbers. They can be added or subtracted (and a long + /// time ago, multiplied and divided), and this may result in numbers which can't be written out + /// in 4 bytes or less. This is ok! The number just can't be read as a number again. This is a + /// bit crazy and subtle, but it makes sense: you can load 32-bit numbers and do anything with + /// them, which back when mult/div was allowed, could result in up to a 64-bit number. We don't + /// want overflow since that's surprising --- and we don't want numbers that don't fit in 64 + /// bits (for efficiency on modern processors). This function will return any value up to 40 + /// bits in length. This is basically a ranged type implementation. + /// + /// This code is based on the + /// [`CScriptNum` constructor in Bitcoin Core](https://github.com/bitcoin/bitcoin/blob/99a4ddf5ab1b3e514d08b90ad8565827fda7b63b/src/script/script.h#L245) + /// + /// # Errors + /// + /// * [`ScriptIntError::NumericOverflow`] if result is not in range [-2^39 +1...2^39 -1]. + /// * [`ScriptIntError::NonMinimal`] if encoding is non-minimal. + pub fn read_cltv_scriptint(&self) -> Result { + self.read_scriptint_internal(5) + } + + /// The internal implementation for reading a script integer. + /// + /// As with `read_cltv_scriptint`, this returns an i64, since that is the maximum size we might + /// need to return data. In practice, if the max_size parameter is 4 or less, this function + /// will always return a value that can fit into an i32, and can thus be safely cast. + fn read_scriptint_internal(&self, max_size: usize) -> Result { + let last = match self.as_bytes().last() { + Some(last) => last, + None => return Ok(0), + }; + if self.len() > max_size { + return Err(ScriptIntError::NumericOverflow); + } + // Comment and code copied from Bitcoin Core: + // https://github.com/bitcoin/bitcoin/blob/447f50e4aed9a8b1d80e1891cda85801aeb80b4e/src/script/script.h#L247-L262 + // If the most-significant-byte - excluding the sign bit - is zero + // then we're not minimal. Note how this test also rejects the + // negative-zero encoding, 0x80. + if (*last & 0x7f) == 0 { + // One exception: if there's more than one byte and the most + // significant bit of the second-most-significant-byte is set + // it would conflict with the sign bit. An example of this case + // is +-255, which encode to 0xff00 and 0xff80 respectively. + // (big-endian). + if self.len() <= 1 || (self[self.len() - 2] & 0x80) == 0 { + return Err(ScriptIntError::NonMinimal); + } + } + + Ok(script::scriptint_parse(self.as_bytes())) + } +} + +impl PushBytesBuf { + /// Returns the number of bytes in buffer. + pub fn len(&self) -> usize { self.inner().len() } + + /// Returns the number of bytes the buffer can contain without reallocating. + pub fn capacity(&self) -> usize { self.inner().capacity() } + + /// Returns true if the buffer contains zero bytes. + pub fn is_empty(&self) -> bool { self.inner().is_empty() } +} + +impl AsRef<[u8]> for PushBytes { + fn as_ref(&self) -> &[u8] { self.as_bytes() } +} + +impl AsMut<[u8]> for PushBytes { + fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() } +} + +impl Deref for PushBytesBuf { + type Target = PushBytes; + + fn deref(&self) -> &Self::Target { self.as_push_bytes() } +} + +impl DerefMut for PushBytesBuf { + fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_push_bytes() } +} + +impl AsRef for PushBytes { + fn as_ref(&self) -> &Self { self } +} + +impl AsMut for PushBytes { + fn as_mut(&mut self) -> &mut Self { self } +} + +impl AsRef for PushBytesBuf { + fn as_ref(&self) -> &PushBytes { self.as_push_bytes() } +} + +impl AsMut for PushBytesBuf { + fn as_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() } +} + +impl Borrow for PushBytesBuf { + fn borrow(&self) -> &PushBytes { self.as_push_bytes() } +} + +impl BorrowMut for PushBytesBuf { + fn borrow_mut(&mut self) -> &mut PushBytes { self.as_mut_push_bytes() } +} + +impl AsRef for ecdsa::SerializedSignature { + #[inline] + fn as_ref(&self) -> &PushBytes { + <&PushBytes>::try_from(>::as_ref(self)).expect("max length 73 bytes is valid") + } +} + +impl AsRef for taproot::SerializedSignature { + #[inline] + fn as_ref(&self) -> &PushBytes { + <&PushBytes>::try_from(>::as_ref(self)).expect("max length 65 bytes is valid") + } +} + +/// Possible errors that can arise from [`PushBytes::read_scriptint`]. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ScriptIntError { + /// The result is not in range [-2^31 +1...2^31 -1]. + NumericOverflow, + /// The resulting encoding is non-minimal. + NonMinimal, +} + +#[cfg(feature = "std")] +impl std::error::Error for ScriptIntError {} + +impl fmt::Display for ScriptIntError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::NumericOverflow => f.write_str("script integer outside of valid range"), + Self::NonMinimal => f.write_str("non-minimal encoded script integer"), + } + } +} + +/// Reports information about failed conversion into `PushBytes`. +/// +/// This should not be needed by general public, except as an additional bound on `TryFrom` when +/// converting to `WitnessProgram`. +pub trait PushBytesErrorReport { + /// How many bytes the input had. + fn input_len(&self) -> usize; +} + +impl PushBytesErrorReport for core::convert::Infallible { + #[inline] + fn input_len(&self) -> usize { match *self {} } +} + +#[doc(inline)] +pub use error::PushBytesError; + +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] +mod error { + use core::fmt; + + /// Error returned on attempt to create too large `PushBytes`. + #[allow(unused)] + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct PushBytesError { + never: core::convert::Infallible, + } + + impl super::PushBytesErrorReport for PushBytesError { + #[inline] + fn input_len(&self) -> usize { match self.never {} } + } + + impl fmt::Display for PushBytesError { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { match self.never {} } + } +} + +// we have 64 bits in mind, but even for esoteric sizes, this code is correct, since it's the +// conservative one that checks for errors +#[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] +mod error { + use core::fmt; + + /// Error returned on attempt to create too large `PushBytes`. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct PushBytesError { + /// How long the input was. + pub(super) len: usize, + } + + impl super::PushBytesErrorReport for PushBytesError { + #[inline] + fn input_len(&self) -> usize { self.len } + } + + impl fmt::Display for PushBytesError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "attempt to prepare {} bytes to be pushed into script but the limit is 2^32-1", + self.len + ) + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for PushBytesError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs new file mode 100644 index 000000000..b31f04cd0 --- /dev/null +++ b/bitcoin/src/blockdata/script/tests.rs @@ -0,0 +1,1075 @@ +// SPDX-License-Identifier: CC0-1.0 + +use hex_lit::hex; + +use super::*; +use crate::consensus::encode::{deserialize, serialize}; +use crate::crypto::key::{PublicKey, XOnlyPublicKey}; +use crate::script::borrowed::{ScriptPubKeyExt as _, ScriptPubKeyExtPriv as _, TapScriptExt as _}; +use crate::script::witness_program::WitnessProgram; +use crate::script::witness_version::WitnessVersion; +use crate::{opcodes, Amount, FeeRate}; + +// Tests should compile and pass no matter what these are. +type Tag = primitives::script::ScriptSigTag; +type Script = crate::ScriptSig; +type ScriptBuf = crate::ScriptSigBuf; + +#[test] +#[rustfmt::skip] +fn script() { + let mut comp = vec![]; + let mut script = Builder::::new(); + assert_eq!(script.as_bytes(), &comp[..]); + + // small ints + script = script.push_int_unchecked(1); comp.push(81u8); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(0); comp.push(0u8); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(4); comp.push(84u8); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(-1); comp.push(79u8); assert_eq!(script.as_bytes(), &comp[..]); + // forced scriptint + script = script.push_int_non_minimal(4); comp.extend([1u8, 4].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // big ints + script = script.push_int_unchecked(17); comp.extend([1u8, 17].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(10000); comp.extend([2u8, 16, 39].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // notice the sign bit set here, hence the extra zero/128 at the end + script = script.push_int_unchecked(10000000); comp.extend([4u8, 128, 150, 152, 0].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + // data + script = script.push_slice(b"NRA4VR"); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // data & number push minimality + // 0x00 (single byte) + script = script.push_slice([0u8]); comp.extend([1u8, 0].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_slice_non_minimal([0u8]); comp.extend([1, 0u8].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // OP_0 (empty byte array) + script = script.push_int(0).unwrap(); comp.extend([0u8].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_non_minimal(0); comp.extend([0u8].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // OP_1..16 + for n in 1..=16 { + script = script.push_slice([n]); comp.extend([0x50 + n].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_slice_non_minimal([n]); comp.extend([1, n].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int(n.into()).unwrap(); comp.extend([0x50 + n].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_non_minimal(n.into()); comp.extend([1, n].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + } + // OP_1NEGATE + script = script.push_slice([0x81]); comp.extend([0x4f].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_slice_non_minimal([0x81]); comp.extend([1, 0x81].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int(-1).unwrap(); comp.extend([0x4f].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_non_minimal(-1); comp.extend([1, 0x81].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + script = script.push_int(0x7fffffff).unwrap(); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0x7F].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(0x7fffffff); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0x7F].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + script = script.push_int(-0x7fffffff).unwrap(); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0xFF].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_int_unchecked(-0x7fffffff); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0xFF].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + // keys + const KEYSTR1: &str = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"; + let key = KEYSTR1[2..].parse::().unwrap(); + script = script.push_key(key); comp.extend_from_slice(&hex!(KEYSTR1)); assert_eq!(script.as_bytes(), &comp[..]); + const KEYSTR2: &str = "41042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"; + let key = KEYSTR2[2..].parse::().unwrap(); + script = script.push_key(key); comp.extend_from_slice(&hex!(KEYSTR2)); assert_eq!(script.as_bytes(), &comp[..]); + + // opcodes + script = script.push_opcode(OP_CHECKSIG); comp.push(0xACu8); assert_eq!(script.as_bytes(), &comp[..]); + script = script.push_opcode(OP_CHECKSIG); comp.push(0xACu8); assert_eq!(script.as_bytes(), &comp[..]); +} + +#[test] +#[rustfmt::skip] +fn script_buf_push_int() { + let mut comp = vec![]; + let mut script = ScriptBuf::new(); + assert_eq!(script.as_bytes(), &comp[..]); + + // small ints + script.push_int_unchecked(1); comp.push(81u8); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(0); comp.push(0u8); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(4); comp.push(84u8); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(-1); comp.push(79u8); assert_eq!(script.as_bytes(), &comp[..]); + // forced scriptint + script.push_int_non_minimal(4); comp.extend([1u8, 4].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // big ints + script.push_int_unchecked(17); comp.extend([1u8, 17].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(10000); comp.extend([2u8, 16, 39].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // notice the sign bit set here, hence the extra zero/128 at the end + script.push_int_unchecked(10000000); comp.extend([4u8, 128, 150, 152, 0].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + script.push_int(0).unwrap(); comp.extend([0u8].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_non_minimal(0); comp.extend([0u8].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + // OP_1..16 + for n in 1..=16 { + script.push_int(n.into()).unwrap(); comp.extend([0x50 + n].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_non_minimal(n.into()); comp.extend([1, n].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + } + + script.push_int(-1).unwrap(); comp.extend([0x4f].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_non_minimal(-1); comp.extend([1, 0x81].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + script.push_int(0x7fffffff).unwrap(); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0x7F].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(0x7fffffff); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0x7F].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + + script.push_int(-0x7fffffff).unwrap(); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0xFF].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); + script.push_int_unchecked(-0x7fffffff); comp.extend([4u8, 0xFF, 0xFF, 0xFF, 0xFF].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]); +} + +#[test] +fn p2pk_pubkey_bytes_valid_key_and_valid_script_returns_expected_key() { + let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"; + let key = key_str.parse::().unwrap(); + let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script(); + let actual = p2pk.p2pk_pubkey_bytes().unwrap(); + assert_eq!(actual.to_vec(), key.to_vec()); +} + +#[test] +fn p2pk_pubkey_bytes_no_checksig_returns_none() { + let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"; + let key = key_str.parse::().unwrap(); + let no_checksig = ScriptPubKey::builder().push_key(key).into_script(); + assert_eq!(no_checksig.p2pk_pubkey_bytes(), None); +} + +#[test] +fn p2pk_pubkey_bytes_empty_script_returns_none() { + let empty_script = ScriptPubKey::builder().into_script(); + assert!(empty_script.p2pk_pubkey_bytes().is_none()); +} + +#[test] +fn p2pk_pubkey_bytes_no_key_returns_none() { + // scripts with no key should return None + let no_push_bytes = ScriptPubKey::builder().push_opcode(OP_CHECKSIG).into_script(); + assert!(no_push_bytes.p2pk_pubkey_bytes().is_none()); +} + +#[test] +fn p2pk_pubkey_bytes_different_op_code_returns_none() { + let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"; + let key = key_str.parse::().unwrap(); + let different_op_code = ScriptPubKey::builder().push_key(key).push_opcode(OP_NOP).into_script(); + assert!(different_op_code.p2pk_pubkey_bytes().is_none()); +} + +#[test] +fn p2pk_pubkey_bytes_incorrect_key_size_returns_none() { + // 63 byte key + let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1"; + let invalid_p2pk_script = + ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script(); + assert!(invalid_p2pk_script.p2pk_pubkey_bytes().is_none()); +} + +#[test] +fn p2pk_pubkey_bytes_invalid_key_returns_some() { + let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1ux"; + let invalid_key_script = + ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script(); + assert!(invalid_key_script.p2pk_pubkey_bytes().is_some()); +} + +#[test] +fn p2pk_pubkey_bytes_compressed_key_returns_expected_key() { + let compressed_key_str = "0311db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"; + let key = compressed_key_str.parse::().unwrap(); + let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script(); + let actual = p2pk.p2pk_pubkey_bytes().unwrap(); + assert_eq!(actual.to_vec(), key.to_vec()); +} + +#[test] +fn p2pk_public_key_valid_key_and_valid_script_returns_expected_key() { + let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"; + let key = key_str.parse::().unwrap(); + let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script(); + let actual = p2pk.p2pk_public_key().unwrap(); + assert_eq!(actual, key); +} + +#[test] +fn p2pk_public_key_no_checksig_returns_none() { + let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"; + let key = key_str.parse::().unwrap(); + let no_checksig = ScriptPubKey::builder().push_key(key).into_script(); + assert_eq!(no_checksig.p2pk_public_key(), None); +} + +#[test] +fn p2pk_public_key_empty_script_returns_none() { + let empty_script = ScriptPubKey::builder().into_script(); + assert!(empty_script.p2pk_public_key().is_none()); +} + +#[test] +fn p2pk_public_key_no_key_returns_none() { + let no_push_bytes = ScriptPubKey::builder().push_opcode(OP_CHECKSIG).into_script(); + assert!(no_push_bytes.p2pk_public_key().is_none()); +} + +#[test] +fn p2pk_public_key_different_op_code_returns_none() { + let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"; + let key = key_str.parse::().unwrap(); + let different_op_code = ScriptPubKey::builder().push_key(key).push_opcode(OP_NOP).into_script(); + assert!(different_op_code.p2pk_public_key().is_none()); +} + +#[test] +fn p2pk_public_key_incorrect_size_returns_none() { + let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1"; + let malformed_key_script = + ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script(); + assert!(malformed_key_script.p2pk_public_key().is_none()); +} + +#[test] +fn p2pk_public_key_invalid_key_returns_none() { + let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1ux"; + let invalid_key_script = + ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script(); + assert!(invalid_key_script.p2pk_public_key().is_none()); +} + +#[test] +fn p2pk_public_key_compressed_key_returns_some() { + let compressed_key_str = "0311db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"; + let key = compressed_key_str.parse::().unwrap(); + let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script(); + let actual = p2pk.p2pk_public_key().unwrap(); + assert_eq!(actual, key); +} + +#[test] +fn script_x_only_key() { + // Notice the "20" which prepends the keystr. That 20 is hexadecimal for "32". The Builder automatically adds the 32 opcode + // to our script in order to give a heads up to the script compiler that it should add the next 32 bytes to the stack. + // From: https://github.com/bitcoin-core/btcdeb/blob/e8c2750c4a4702768c52d15640ed03bf744d2601/doc/tapscript-example.md?plain=1#L43 + const KEYSTR: &str = "209997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be"; + let x_only_key = KEYSTR[2..].parse::().unwrap(); + let script = Builder::::new().push_x_only_key(x_only_key); + assert_eq!(script.into_bytes(), &hex!(KEYSTR) as &[u8]); +} + +#[test] +fn script_builder() { + // from txid 3bb5e6434c11fb93f64574af5d116736510717f2c595eb45b52c28e31622dfff which was in my mempool when I wrote the test + let script = ScriptPubKey::builder() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice(hex!("16e1ae70ff0fa102905d4af297f6912bda6cce19")) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_CHECKSIG) + .into_script(); + assert_eq!( + script.to_hex_string_no_length_prefix(), + "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac" + ); +} + +#[test] +fn script_builder_with_capacity() { + let script = Builder::::with_capacity(42); + + assert!(script.into_script().capacity() >= 42); +} + +#[test] +fn script_generators() { + let pubkey = "0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e" + .parse::() + .unwrap(); + assert!(ScriptPubKeyBuf::new_p2pk(pubkey).is_p2pk()); + + let pubkey_hash = pubkey.pubkey_hash(); + assert!(ScriptPubKeyBuf::new_p2pkh(pubkey_hash).is_p2pkh()); + + let wpubkey_hash = pubkey.wpubkey_hash().unwrap(); + assert!(ScriptPubKeyBuf::new_p2wpkh(wpubkey_hash).is_p2wpkh()); + + let script = RedeemScript::builder().push_opcode(OP_NUMEQUAL).push_verify().into_script(); + let script_hash = script.script_hash().expect("script is less than 520 bytes"); + let p2sh = ScriptPubKeyBuf::new_p2sh(script_hash); + assert!(p2sh.is_p2sh()); + assert_eq!(script.to_p2sh().unwrap(), p2sh); + + let script = WitnessScript::builder().push_opcode(OP_NUMEQUAL).push_verify().into_script(); + let wscript_hash = script.wscript_hash().expect("script is less than 10,000 bytes"); + let p2wsh = ScriptPubKeyBuf::new_p2wsh(wscript_hash); + assert!(p2wsh.is_p2wsh()); + assert_eq!(script.to_p2wsh().unwrap(), p2wsh); + + // Test data are taken from the second output of + // 2ccb3a1f745eb4eefcf29391460250adda5fab78aaddb902d25d3cd97d9d8e61 transaction + let data = hex!("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a"); + let op_return = ScriptPubKeyBuf::new_op_return(data); + assert!(op_return.is_op_return()); + assert_eq!( + op_return.to_hex_string_no_length_prefix(), + "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a" + ); +} + +#[test] +fn script_builder_verify() { + type Builder = super::Builder; + + let simple = Builder::new().push_verify().into_script(); + assert_eq!(simple.to_hex_string_no_length_prefix(), "69"); + let simple2 = Builder::from(vec![]).push_verify().into_script(); + assert_eq!(simple2.to_hex_string_no_length_prefix(), "69"); + + let nonverify = Builder::new().push_verify().push_verify().into_script(); + assert_eq!(nonverify.to_hex_string_no_length_prefix(), "6969"); + let nonverify2 = Builder::from(vec![0x69]).push_verify().into_script(); + assert_eq!(nonverify2.to_hex_string_no_length_prefix(), "6969"); + + let equal = Builder::new().push_opcode(OP_EQUAL).push_verify().into_script(); + assert_eq!(equal.to_hex_string_no_length_prefix(), "88"); + let equal2 = Builder::from(vec![0x87]).push_verify().into_script(); + assert_eq!(equal2.to_hex_string_no_length_prefix(), "88"); + + let numequal = Builder::new().push_opcode(OP_NUMEQUAL).push_verify().into_script(); + assert_eq!(numequal.to_hex_string_no_length_prefix(), "9d"); + let numequal2 = Builder::from(vec![0x9c]).push_verify().into_script(); + assert_eq!(numequal2.to_hex_string_no_length_prefix(), "9d"); + + let checksig = Builder::new().push_opcode(OP_CHECKSIG).push_verify().into_script(); + assert_eq!(checksig.to_hex_string_no_length_prefix(), "ad"); + let checksig2 = Builder::from(vec![0xac]).push_verify().into_script(); + assert_eq!(checksig2.to_hex_string_no_length_prefix(), "ad"); + + let checkmultisig = Builder::new().push_opcode(OP_CHECKMULTISIG).push_verify().into_script(); + assert_eq!(checkmultisig.to_hex_string_no_length_prefix(), "af"); + let checkmultisig2 = Builder::from(vec![0xae]).push_verify().into_script(); + assert_eq!(checkmultisig2.to_hex_string_no_length_prefix(), "af"); + + let trick_slice = Builder::new() + .push_slice([0xae]) // OP_CHECKMULTISIG + .push_verify() + .into_script(); + assert_eq!(trick_slice.to_hex_string_no_length_prefix(), "01ae69"); + let trick_slice2 = Builder::from(vec![0x01, 0xae]).push_verify().into_script(); + assert_eq!(trick_slice2.to_hex_string_no_length_prefix(), "01ae69"); + + let pushint_then_verify = + Builder::new().push_opcode(OP_EQUAL).push_int(5).unwrap().push_verify().into_script(); + assert_eq!(pushint_then_verify.to_hex_string_no_length_prefix(), "875569"); +} + +#[test] +fn script_serialize() { + let hex_script = hex!("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52"); + let script: Result = deserialize(&hex_script); + assert!(script.is_ok()); + assert_eq!(serialize(&script.unwrap()), &hex_script as &[u8]); +} + +#[test] +fn scriptint_round_trip() { + fn build_scriptint(n: i64) -> Vec { + let mut buf = [0u8; 8]; + let len = write_scriptint(&mut buf, n); + assert!(len <= 8); + buf[..len].to_vec() + } + + assert_eq!(build_scriptint(-1), vec![0x81]); + assert_eq!(build_scriptint(255), vec![255, 0]); + assert_eq!(build_scriptint(256), vec![0, 1]); + assert_eq!(build_scriptint(257), vec![1, 1]); + assert_eq!(build_scriptint(511), vec![255, 1]); + let test_vectors = [ + 10, + 100, + 255, + 256, + 1000, + 10000, + 25000, + 200000, + 5000000, + 1000000000, + (1 << 31) - 1, + -((1 << 31) - 1), + ]; + for &i in test_vectors.iter() { + assert_eq!( + Ok(i), + PushBytes::read_scriptint( + <&PushBytes>::try_from(build_scriptint(i).as_slice()).unwrap() + ).map(i64::from) + ); + assert_eq!( + Ok(-i), + PushBytes::read_scriptint( + <&PushBytes>::try_from(build_scriptint(-i).as_slice()).unwrap() + ).map(i64::from) + ); + assert_eq!(Ok(i), read_scriptint_non_minimal(&build_scriptint(i)).map(i64::from)); + assert_eq!(Ok(-i), read_scriptint_non_minimal(&build_scriptint(-i)).map(i64::from)); + } + assert!(PushBytes::read_scriptint( + <&PushBytes>::try_from(build_scriptint(1 << 31).as_slice()).unwrap() + ) + .is_err()); + assert!(PushBytes::read_scriptint( + <&PushBytes>::try_from(build_scriptint(-(1 << 31)).as_slice()).unwrap() + ) + .is_err()); + assert!(read_scriptint_non_minimal(&build_scriptint(1 << 31)).is_err()); + assert!(read_scriptint_non_minimal(&build_scriptint(-(1 << 31))).is_err()); +} + +#[test] +fn non_minimal_scriptints() { + assert_eq!( + PushBytes::read_scriptint(<[_; 2] as AsRef>::as_ref(&[0x80, 0x00])), + Ok(0x80) + ); + assert_eq!( + PushBytes::read_scriptint(<[_; 2] as AsRef>::as_ref(&[0xff, 0x00])), + Ok(0xff) + ); + assert_eq!( + PushBytes::read_scriptint(<[_; 3] as AsRef>::as_ref(&[0x8f, 0x00, 0x00])), + Err(ScriptIntError::NonMinimal) + ); + assert_eq!( + PushBytes::read_scriptint(<[_; 2] as AsRef>::as_ref(&[0x7f, 0x00])), + Err(ScriptIntError::NonMinimal) + ); + + assert_eq!(read_scriptint_non_minimal(&[0x80, 0x00]), Ok(0x80)); + assert_eq!(read_scriptint_non_minimal(&[0xff, 0x00]), Ok(0xff)); + assert_eq!(read_scriptint_non_minimal(&[0x8f, 0x00, 0x00]), Ok(0x8f)); + assert_eq!(read_scriptint_non_minimal(&[0x7f, 0x00]), Ok(0x7f)); +} + +#[test] +fn script_hashes() { + let script = RedeemScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap(); + assert_eq!( + script.script_hash().unwrap().to_string(), + "8292bcfbef1884f73c813dfe9c82fd7e814291ea" + ); + let script = WitnessScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap(); + assert_eq!( + script.wscript_hash().unwrap().to_string(), + "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324" + ); + assert_eq!( + TapScriptBuf::from_hex_no_length_prefix( + "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac" + ) + .unwrap() + .tapscript_leaf_hash() + .to_string(), + "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21" + ); +} + +#[test] +fn provably_unspendable() { + // p2pk + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_op_return()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_op_return()); + // p2pkhash + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac" + ) + .unwrap() + .is_op_return()); + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix( + "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87" + ) + .unwrap() + .is_op_return()); +} + +#[test] +fn op_return() { + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix( + "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87" + ) + .unwrap() + .is_op_return()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac" + ) + .unwrap() + .is_op_return()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("").unwrap().is_op_return()); +} + +#[test] +fn standard_op_return() { + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix( + "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87" + ) + .unwrap() + .is_standard_op_return()); + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e") + .unwrap() + .is_standard_op_return()); + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21") + .unwrap() + .is_standard_op_return()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21524f42") + .unwrap() + .is_standard_op_return()); +} + +#[test] +fn multisig() { + // First multisig? 1-of-2 + // In block 164467, txid 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1 + assert!( + ScriptPubKeyBuf::from_hex_no_length_prefix("514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae") + .unwrap() + .is_multisig() + ); + // 2-of-2 + assert!( + ScriptPubKeyBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae") + .unwrap() + .is_multisig() + ); + + // Extra opcode after OP_CHECKMULTISIG + assert!( + !ScriptPubKeyBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae52") + .unwrap() + .is_multisig() + ); + // Required sigs > num pubkeys + assert!( + !ScriptPubKeyBuf::from_hex_no_length_prefix("5321021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae") + .unwrap() + .is_multisig() + ); + // Num pubkeys != pushnum + assert!( + !ScriptPubKeyBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f453ae") + .unwrap() + .is_multisig() + ); + + // Taproot hash from another test + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac" + ) + .unwrap() + .is_multisig()); + // OP_RETURN from another test + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87" + ) + .unwrap() + .is_multisig()); +} + +#[test] +#[cfg(feature = "serde")] +fn script_json_serialize() { + use serde_json; + + let original = ScriptBuf::from_hex_no_length_prefix("827651a0698faaa9a8a7a687").unwrap(); + let json = serde_json::to_value(&original).unwrap(); + assert_eq!(json, serde_json::Value::String("827651a0698faaa9a8a7a687".to_owned())); + let des = serde_json::from_value::(json).unwrap(); + assert_eq!(original, des); +} + +#[test] +fn script_asm() { + assert_eq!( + ScriptBuf::from_hex_no_length_prefix("6363636363686868686800").unwrap().to_string(), + "OP_IF OP_IF OP_IF OP_IF OP_IF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_0" + ); + assert_eq!(ScriptBuf::from_hex_no_length_prefix("2102715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699ac").unwrap().to_string(), + "OP_PUSHBYTES_33 02715e91d37d239dea832f1460e91e368115d8ca6cc23a7da966795abad9e3b699 OP_CHECKSIG"); + // Elements Alpha peg-out transaction with some signatures removed for brevity. Mainly to test PUSHDATA1 + assert_eq!(ScriptBuf::from_hex_no_length_prefix("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap().to_string(), + "OP_0 OP_PUSHBYTES_71 304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401 OP_0 OP_PUSHDATA1 552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae"); + // Various weird scripts found in transaction 6d7ed9914625c73c0288694a6819196a27ef6c08f98e1270d975a8e65a3dc09a + // which triggered overflow bugs on 32-bit machines in script formatting in the past. + assert_eq!( + ScriptBuf::from_hex_no_length_prefix("01").unwrap().to_string(), + "OP_PUSHBYTES_1 " + ); + assert_eq!( + ScriptBuf::from_hex_no_length_prefix("0201").unwrap().to_string(), + "OP_PUSHBYTES_2 " + ); + assert_eq!(ScriptBuf::from_hex_no_length_prefix("4c").unwrap().to_string(), ""); + assert_eq!( + ScriptBuf::from_hex_no_length_prefix("4c0201").unwrap().to_string(), + "OP_PUSHDATA1 " + ); + assert_eq!(ScriptBuf::from_hex_no_length_prefix("4d").unwrap().to_string(), ""); + assert_eq!( + ScriptBuf::from_hex_no_length_prefix("4dffff01").unwrap().to_string(), + "OP_PUSHDATA2 " + ); + assert_eq!( + ScriptBuf::from_hex_no_length_prefix("4effffffff01").unwrap().to_string(), + "OP_PUSHDATA4 " + ); +} + +#[test] +fn script_buf_collect() { + assert_eq!(&core::iter::empty::>().collect::(), Script::new()); + let script = ScriptBuf::from_hex_no_length_prefix("0047304402202457e78cc1b7f50d0543863c27de75d07982bde8359b9e3316adec0aec165f2f02200203fd331c4e4a4a02f48cf1c291e2c0d6b2f7078a784b5b3649fca41f8794d401004cf1552103244e602b46755f24327142a0517288cebd159eccb6ccf41ea6edf1f601e9af952103bbbacc302d19d29dbfa62d23f37944ae19853cf260c745c2bea739c95328fcb721039227e83246bd51140fe93538b2301c9048be82ef2fb3c7fc5d78426ed6f609ad210229bf310c379b90033e2ecb07f77ecf9b8d59acb623ab7be25a0caed539e2e6472103703e2ed676936f10b3ce9149fa2d4a32060fb86fa9a70a4efe3f21d7ab90611921031e9b7c6022400a6bb0424bbcde14cff6c016b91ee3803926f3440abf5c146d05210334667f975f55a8455d515a2ef1c94fdfa3315f12319a14515d2a13d82831f62f57ae").unwrap(); + assert_eq!(script.instructions().collect::>().unwrap(), script); +} + +#[test] +fn script_p2sh_p2pkh_template() { + // random outputs I picked out of the mempool + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac" + ) + .unwrap() + .is_p2pkh()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac" + ) + .unwrap() + .is_p2sh()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad" + ) + .unwrap() + .is_p2pkh()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("").unwrap().is_p2pkh()); + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87" + ) + .unwrap() + .is_p2sh()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87" + ) + .unwrap() + .is_p2pkh()); + assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix( + "a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87" + ) + .unwrap() + .is_p2sh()); +} + +#[test] +fn script_p2pk() { + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix( + "21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac" + ) + .unwrap() + .is_p2pk()); + assert!(ScriptPubKeyBuf::from_hex_no_length_prefix("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk()); +} + +#[test] +fn p2sh_p2wsh_conversion() { + // Test vectors taken from Core tests/data/script_tests.json + // bare p2wsh + let witness_script = WitnessScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap(); + let expected_without = ScriptPubKeyBuf::from_hex_no_length_prefix( + "0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + ) + .unwrap(); + assert!(witness_script.to_p2wsh().unwrap().is_p2wsh()); + assert_eq!(witness_script.to_p2wsh().unwrap(), expected_without); + + // p2sh + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap(); + let expected_p2shout = ScriptPubKeyBuf::from_hex_no_length_prefix( + "a91491b24bf9f5288532960ac687abb035127b1d28a587", + ) + .unwrap(); + assert!(redeem_script.to_p2sh().unwrap().is_p2sh()); + assert_eq!(redeem_script.to_p2sh().unwrap(), expected_p2shout); + + // p2sh-p2wsh + let witness_script = WitnessScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap(); + let expected_without = ScriptPubKeyBuf::from_hex_no_length_prefix( + "0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + ) + .unwrap(); + let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887", + ) + .unwrap(); + // assert!(witness_script.to_p2sh().unwrap().is_p2sh()); // This is meaningless and no longer compiles + assert_eq!(witness_script.to_p2wsh().unwrap(), expected_without); + assert_eq!(witness_script.to_p2wsh().unwrap().to_p2sh().unwrap(), expected_out); +} + +macro_rules! unwrap_all { + ($($var:ident),*) => { + $( + let $var = $var.unwrap(); + )* + } +} + +#[test] +fn iterator() { + let zero = ScriptBuf::from_hex_no_length_prefix("00").unwrap(); + let zeropush = ScriptBuf::from_hex_no_length_prefix("0100").unwrap(); + + let nonminimal = ScriptBuf::from_hex_no_length_prefix("4c0169b2").unwrap(); // PUSHDATA1 for no reason + let minimal = ScriptBuf::from_hex_no_length_prefix("0169b2").unwrap(); // minimal + let nonminimal_alt = ScriptBuf::from_hex_no_length_prefix("026900b2").unwrap(); // non-minimal number but minimal push (should be OK) + + let v_zero: Result, Error> = zero.instruction_indices_minimal().collect(); + let v_zeropush: Result, Error> = zeropush.instruction_indices_minimal().collect(); + + let v_min: Result, Error> = minimal.instruction_indices_minimal().collect(); + let v_nonmin: Result, Error> = nonminimal.instruction_indices_minimal().collect(); + let v_nonmin_alt: Result, Error> = + nonminimal_alt.instruction_indices_minimal().collect(); + let slop_v_min: Result, Error> = minimal.instruction_indices().collect(); + let slop_v_nonmin: Result, Error> = nonminimal.instruction_indices().collect(); + let slop_v_nonmin_alt: Result, Error> = nonminimal_alt.instruction_indices().collect(); + + unwrap_all!( + v_zero, + v_zeropush, + v_min, + v_nonmin_alt, + slop_v_min, + slop_v_nonmin, + slop_v_nonmin_alt + ); + + assert_eq!(v_zero, vec![(0, Instruction::PushBytes(PushBytes::empty()))]); + assert_eq!(v_zeropush, vec![(0, Instruction::PushBytes([0].as_ref()))]); + + assert_eq!( + v_min, + vec![ + (0, Instruction::PushBytes([105].as_ref())), + (2, Instruction::Op(opcodes::all::OP_NOP3)) + ] + ); + + assert_eq!(v_nonmin.unwrap_err(), Error::NonMinimalPush); + + assert_eq!( + v_nonmin_alt, + vec![ + (0, Instruction::PushBytes([105, 0].as_ref())), + (3, Instruction::Op(opcodes::all::OP_NOP3)) + ] + ); + + assert_eq!(v_min, slop_v_min); + // indices must differ + assert_ne!(v_min, slop_v_nonmin); + // but the instructions must be equal + for ((_, v_min_instr), (_, slop_v_nomin_instr)) in v_min.iter().zip(&slop_v_nonmin) { + assert_eq!(v_min_instr, slop_v_nomin_instr); + } + assert_eq!(v_nonmin_alt, slop_v_nonmin_alt); +} + +#[test] +fn script_ord() { + let script_1 = Builder::::new().push_slice([1, 2, 3, 4]).into_script(); + let script_2 = Builder::new().push_int_unchecked(10).into_script(); + let script_3 = Builder::new().push_int_unchecked(15).into_script(); + let script_4 = Builder::new().push_opcode(OP_RETURN).into_script(); + + assert!(script_1 < script_2); + assert!(script_2 < script_3); + assert!(script_3 < script_4); + + assert!(script_1 <= script_1); + assert!(script_1 >= script_1); + + assert!(script_4 > script_3); + assert!(script_3 > script_2); + assert!(script_2 > script_1); +} + +#[test] +#[cfg(feature = "bitcoinconsensus")] +fn bitcoinconsensus() { + use crate::consensus_validation::ScriptPubKeyExt as _; + + // a random SegWit transaction from the blockchain using native SegWit + let spent_bytes = hex!("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d"); + let spent = ScriptPubKey::from_bytes(&spent_bytes); + let spending = hex!("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000"); + spent.verify(0, Amount::from_sat_u32(18393430), &spending).unwrap(); +} + +#[test] +fn default_dust_value() { + // Check that our dust_value() calculator correctly calculates the dust limit on common + // well-known scriptPubKey types. + let script_p2wpkh = Builder::new().push_int_unchecked(0).push_slice([42; 20]).into_script(); + assert!(script_p2wpkh.is_p2wpkh()); + assert_eq!(script_p2wpkh.minimal_non_dust(), Amount::from_sat_u32(294)); + assert_eq!( + script_p2wpkh.minimal_non_dust_custom(FeeRate::from_sat_per_vb(6)), + Some(Amount::from_sat_u32(588)) + ); + + let script_p2pkh = Builder::new() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice([42; 20]) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_CHECKSIG) + .into_script(); + assert!(script_p2pkh.is_p2pkh()); + assert_eq!(script_p2pkh.minimal_non_dust(), Amount::from_sat_u32(546)); + assert_eq!( + script_p2pkh.minimal_non_dust_custom(FeeRate::from_sat_per_vb(6)), + Some(Amount::from_sat_u32(1092)) + ); +} + +#[test] +fn script_get_sigop_count() { + assert_eq!( + Script::builder() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice([42; 20]) + .push_opcode(OP_EQUAL) + .into_script() + .count_sigops(), + 0 + ); + assert_eq!( + Script::builder() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice([42; 20]) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_CHECKSIG) + .into_script() + .count_sigops(), + 1 + ); + assert_eq!( + Script::builder() + .push_opcode(OP_DUP) + .push_opcode(OP_HASH160) + .push_slice([42; 20]) + .push_opcode(OP_EQUALVERIFY) + .push_opcode(OP_CHECKSIGVERIFY) + .push_opcode(OP_1) + .into_script() + .count_sigops(), + 1 + ); + let multi = Script::builder() + .push_opcode(OP_1) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_opcode(OP_3) + .push_opcode(OP_CHECKMULTISIG) + .into_script(); + assert_eq!(multi.count_sigops(), 3); + assert_eq!(multi.count_sigops_legacy(), 20); + let multi_verify = Script::builder() + .push_opcode(OP_1) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_opcode(OP_3) + .push_opcode(OP_CHECKMULTISIGVERIFY) + .push_opcode(OP_1) + .into_script(); + assert_eq!(multi_verify.count_sigops(), 3); + assert_eq!(multi_verify.count_sigops_legacy(), 20); + let multi_nopushnum_pushdata = Script::builder() + .push_opcode(OP_1) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_opcode(OP_CHECKMULTISIG) + .into_script(); + assert_eq!(multi_nopushnum_pushdata.count_sigops(), 20); + assert_eq!(multi_nopushnum_pushdata.count_sigops_legacy(), 20); + let multi_nopushnum_op = Script::builder() + .push_opcode(OP_1) + .push_slice([3; 33]) + .push_slice([3; 33]) + .push_opcode(OP_DROP) + .push_opcode(OP_CHECKMULTISIG) + .into_script(); + assert_eq!(multi_nopushnum_op.count_sigops(), 20); + assert_eq!(multi_nopushnum_op.count_sigops_legacy(), 20); +} + +#[test] +#[cfg(feature = "serde")] +fn script_serde_human_and_not() { + let script = ScriptBuf::from(vec![0u8, 1u8, 2u8]); + + // Serialize + let json = serde_json::to_string(&script).unwrap(); + assert_eq!(json, "\"000102\""); + let bincode = bincode::serialize(&script).unwrap(); + assert_eq!(bincode, [3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2]); // bincode adds u64 for length, serde_cbor use varint + + // Deserialize + assert_eq!(script, serde_json::from_str::(&json).unwrap()); + assert_eq!(script, bincode::deserialize::(&bincode).unwrap()); +} + +#[test] +fn instructions_are_fused() { + let script = ScriptBuf::new(); + let mut instructions = script.instructions(); + assert!(instructions.next().is_none()); + assert!(instructions.next().is_none()); + assert!(instructions.next().is_none()); + assert!(instructions.next().is_none()); +} + +#[test] +fn script_extend() { + fn cmp_scripts(new_script: &Script, orig_script: &[Instruction<'_>]) { + let mut new_instr = new_script.instructions(); + let mut orig_instr = orig_script.iter().cloned(); + for (new, orig) in new_instr.by_ref().zip(orig_instr.by_ref()) { + assert_eq!(new.unwrap(), orig); + } + assert!(new_instr.next().is_none() && orig_instr.next().is_none()) + } + + let script_5_items = [ + Instruction::Op(OP_DUP), + Instruction::Op(OP_HASH160), + Instruction::PushBytes([42; 20].as_ref()), + Instruction::Op(OP_EQUALVERIFY), + Instruction::Op(OP_CHECKSIG), + ]; + let new_script = script_5_items.iter().cloned().collect::(); + cmp_scripts(&new_script, &script_5_items); + + let script_6_items = [ + Instruction::Op(OP_DUP), + Instruction::Op(OP_HASH160), + Instruction::PushBytes([42; 20].as_ref()), + Instruction::Op(OP_EQUALVERIFY), + Instruction::Op(OP_CHECKSIG), + Instruction::Op(OP_NOP), + ]; + let new_script = script_6_items.iter().cloned().collect::(); + cmp_scripts(&new_script, &script_6_items); + + let script_7_items = [ + Instruction::Op(OP_DUP), + Instruction::Op(OP_HASH160), + Instruction::PushBytes([42; 20].as_ref()), + Instruction::Op(OP_EQUALVERIFY), + Instruction::Op(OP_CHECKSIG), + Instruction::Op(OP_NOP), + ]; + let new_script = script_7_items.iter().cloned().collect::(); + cmp_scripts(&new_script, &script_7_items); +} + +#[test] +fn read_scriptbool_zero_is_false() { + let v: Vec = vec![0x00, 0x00, 0x00, 0x00]; + assert!(!read_scriptbool(&v)); + + let v: Vec = vec![0x00, 0x00, 0x00, 0x80]; // With sign bit set. + assert!(!read_scriptbool(&v)); +} + +#[test] +fn read_scriptbool_non_zero_is_true() { + let v: Vec = vec![0x01, 0x00, 0x00, 0x00]; + assert!(read_scriptbool(&v)); + + let v: Vec = vec![0x01, 0x00, 0x00, 0x80]; // With sign bit set. + assert!(read_scriptbool(&v)); +} + +#[test] +fn instruction_script_num_parse() { + let push_bytes = [ + (PushBytesBuf::from([]), Some(0)), + (PushBytesBuf::from([0x00]), Some(0)), + (PushBytesBuf::from([0x01]), Some(1)), + // Check all the negative 1s + (PushBytesBuf::from([0x81]), Some(-1)), + (PushBytesBuf::from([0x01, 0x80]), Some(-1)), + (PushBytesBuf::from([0x01, 0x00, 0x80]), Some(-1)), + (PushBytesBuf::from([0x01, 0x00, 0x00, 0x80]), Some(-1)), + // Check all the negative 0s + (PushBytesBuf::from([0x80]), Some(0)), + (PushBytesBuf::from([0x00, 0x80]), Some(0)), + (PushBytesBuf::from([0x00, 0x00, 0x80]), Some(0)), + (PushBytesBuf::from([0x00, 0x00, 0x00, 0x80]), Some(0)), + // Too long + (PushBytesBuf::from([0x01, 0x00, 0x00, 0x00, 0x80]), None), + // Check the position of all the bytes + (PushBytesBuf::from([0xef, 0xbe, 0xad, 0x5e]), Some(0x5eadbeef)), + // Add negative + (PushBytesBuf::from([0xef, 0xbe, 0xad, 0xde]), Some(-0x5eadbeef)), + ]; + let ops = [ + (Instruction::Op(opcodes::all::OP_PUSHDATA4), None), + (Instruction::Op(opcodes::all::OP_1NEGATE), Some(-1)), + (Instruction::Op(opcodes::all::OP_RESERVED), None), + (Instruction::Op(opcodes::all::OP_1), Some(1)), + (Instruction::Op(opcodes::all::OP_16), Some(16)), + (Instruction::Op(opcodes::all::OP_NOP), None), + ]; + for (input, expected) in &push_bytes { + assert_eq!(Instruction::PushBytes(input).script_num(), *expected); + } + for (input, expected) in &ops { + assert_eq!(input.script_num(), *expected); + } + + // script_num() is predicated on OP_0/OP_FALSE (0x00) + // being treated as an empty PushBytes + assert_eq!( + Script::from_bytes(&[0x00]).instructions().next(), + Some(Ok(Instruction::PushBytes(PushBytes::empty()))), + ); +} + +#[test] +fn script_push_int_overflow() { + // Only errors if `data == i32::MIN` (CScriptNum cannot have value -2^31). + assert_eq!(Builder::::new().push_int(i32::MIN), Err(Error::NumericOverflow)); +} + +#[test] +fn shortest_witness_program() { + let bytes = [0x00; 2]; // Arbitrary bytes, witprog must be between 2 and 40. + let version = WitnessVersion::V15; // Arbitrary version number, intentionally not 0 or 1. + + let p = WitnessProgram::new(version, &bytes).expect("failed to create witness program"); + let script = ScriptPubKeyBuf::new_witness_program(&p); + + assert_eq!(script.witness_version(), Some(version)); +} + +#[test] +fn longest_witness_program() { + let bytes = [0x00; 40]; // Arbitrary bytes, witprog must be between 2 and 40. + let version = WitnessVersion::V16; // Arbitrary version number, intentionally not 0 or 1. + + let p = WitnessProgram::new(version, &bytes).expect("failed to create witness program"); + let script = ScriptPubKeyBuf::new_witness_program(&p); + + assert_eq!(script.witness_version(), Some(version)); +} diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs new file mode 100644 index 000000000..7ecb923d0 --- /dev/null +++ b/bitcoin/src/blockdata/script/witness_program.rs @@ -0,0 +1,227 @@ +//! The segregated witness program as defined by [BIP-0141]. +//! +//! > A scriptPubKey (or redeemScript as defined in BIP-0016/P2SH) that consists of a 1-byte push +//! > opcode (for 0 to 16) followed by a data push between 2 and 40 bytes gets a new special +//! > meaning. The value of the first push is called the "version byte". The following byte +//! > vector pushed is called the "witness program". +//! +//! [BIP-0141]: + +use core::convert::Infallible; +use core::fmt; + +use internals::array_vec::ArrayVec; + +use super::witness_version::WitnessVersion; +use super::{PushBytes, WScriptHash, WitnessScript, WitnessScriptSizeError}; +use crate::crypto::key::{CompressedPublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey}; +use crate::script::WitnessScriptExt as _; +use crate::taproot::TapNodeHash; + +/// The minimum byte size of a segregated witness program. +pub const MIN_SIZE: usize = 2; + +/// The maximum byte size of a segregated witness program. +pub const MAX_SIZE: usize = 40; + +/// The P2A program which is given by 0x4e73. +pub(crate) const P2A_PROGRAM: [u8; 2] = [78, 115]; + +/// The segregated witness program. +/// +/// The segregated witness program is technically only the program bytes _excluding_ the witness +/// version, however we maintain length invariants on the `program` that are governed by the version +/// number, therefore we carry the version number around along with the program bytes. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WitnessProgram { + /// The SegWit version associated with this witness program. + version: WitnessVersion, + /// The witness program (between 2 and 40 bytes). + program: ArrayVec, +} + +impl WitnessProgram { + /// Constructs a new witness program, copying the content from the given byte slice. + pub fn new(version: WitnessVersion, bytes: &[u8]) -> Result { + let program_len = bytes.len(); + if program_len < MIN_SIZE || program_len > MAX_SIZE { + return Err(Error::InvalidLength(program_len)); + } + + // Specific SegWit v0 check. These addresses can never spend funds sent to them. + if version == WitnessVersion::V0 && (program_len != 20 && program_len != 32) { + return Err(Error::InvalidSegwitV0Length(program_len)); + } + + let program = ArrayVec::from_slice(bytes); + Ok(Self { version, program }) + } + + /// Constructs a new [`WitnessProgram`] from a 20 byte pubkey hash. + fn new_p2wpkh(program: [u8; 20]) -> Self { + Self { version: WitnessVersion::V0, program: ArrayVec::from_slice(&program) } + } + + /// Constructs a new [`WitnessProgram`] from a 32 byte script hash. + fn new_p2wsh(program: [u8; 32]) -> Self { + Self { version: WitnessVersion::V0, program: ArrayVec::from_slice(&program) } + } + + /// Constructs a new [`WitnessProgram`] from a 32 byte serialized Taproot x-only pubkey. + fn new_p2tr(program: [u8; 32]) -> Self { + Self { version: WitnessVersion::V1, program: ArrayVec::from_slice(&program) } + } + + /// Constructs a new [`WitnessProgram`] from `pk` for a P2WPKH output. + pub fn p2wpkh(pk: CompressedPublicKey) -> Self { + let hash = pk.wpubkey_hash(); + Self::new_p2wpkh(hash.to_byte_array()) + } + + /// Constructs a new [`WitnessProgram`] from `script` for a P2WSH output. + pub fn p2wsh(script: &WitnessScript) -> Result { + script.wscript_hash().map(Self::p2wsh_from_hash) + } + + /// Constructs a new [`WitnessProgram`] from `script` for a P2WSH output. + pub fn p2wsh_from_hash(hash: WScriptHash) -> Self { + Self::new_p2wsh(hash.to_byte_array()) + } + + /// Constructs a new [`WitnessProgram`] from an untweaked key for a P2TR output. + /// + /// This function applies BIP-0341 key-tweaking to the untweaked + /// key using the merkle root, if it's present. + pub fn p2tr>( + internal_key: K, + merkle_root: Option, + ) -> Self { + let internal_key = internal_key.into(); + let (output_key, _parity) = internal_key.tap_tweak(merkle_root); + let pubkey = output_key.as_x_only_public_key().serialize(); + Self::new_p2tr(pubkey) + } + + /// Constructs a new [`WitnessProgram`] from a tweaked key for a P2TR output. + pub fn p2tr_tweaked(output_key: TweakedPublicKey) -> Self { + let pubkey = output_key.as_x_only_public_key().serialize(); + Self::new_p2tr(pubkey) + } + + /// Constructs a new [`WitnessProgram`] for a P2A output. + pub const fn p2a() -> Self { + Self { version: WitnessVersion::V1, program: ArrayVec::from_slice(&P2A_PROGRAM) } + } + + /// Returns the witness program version. + pub fn version(&self) -> WitnessVersion { self.version } + + /// Returns the witness program. + pub fn program(&self) -> &PushBytes { + self.program + .as_slice() + .try_into() + .expect("witness programs are always smaller than max size of PushBytes") + } + + /// Returns true if this witness program is for a P2WPKH output. + pub fn is_p2wpkh(&self) -> bool { + self.version == WitnessVersion::V0 && self.program.len() == 20 + } + + /// Returns true if this witness program is for a P2WSH output. + pub fn is_p2wsh(&self) -> bool { + self.version == WitnessVersion::V0 && self.program.len() == 32 + } + + /// Returns true if this witness program is for a P2TR output. + pub fn is_p2tr(&self) -> bool { self.version == WitnessVersion::V1 && self.program.len() == 32 } + + /// Returns true if this witness program is for a P2A output. + pub fn is_p2a(&self) -> bool { + self.version == WitnessVersion::V1 && self.program == P2A_PROGRAM + } +} + +/// Witness program error. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// The witness program must be between 2 and 40 bytes in length. + InvalidLength(usize), + /// A v0 witness program must be either of length 20 or 32. + InvalidSegwitV0Length(usize), +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::InvalidLength(len) => + write!(f, "witness program must be between 2 and 40 bytes: length={}", len), + Self::InvalidSegwitV0Length(len) => + write!(f, "a v0 witness program must be either 20 or 32 bytes: length={}", len), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidLength(_) | Self::InvalidSegwitV0Length(_) => None, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn witness_program_is_too_short() { + let arbitrary_bytes = [0x00; MIN_SIZE - 1]; + assert!(WitnessProgram::new(WitnessVersion::V15, &arbitrary_bytes).is_err()); // Arbitrary version + } + + #[test] + fn witness_program_is_too_long() { + let arbitrary_bytes = [0x00; MAX_SIZE + 1]; + assert!(WitnessProgram::new(WitnessVersion::V15, &arbitrary_bytes).is_err()); // Arbitrary version + } + + #[test] + fn valid_v0_witness_programs() { + let arbitrary_bytes = [0x00; MAX_SIZE]; + + for size in MIN_SIZE..=MAX_SIZE { + let program = WitnessProgram::new(WitnessVersion::V0, &arbitrary_bytes[..size]); + + if size == 20 { + assert!(program.expect("valid witness program").is_p2wpkh()); + continue; + } + if size == 32 { + assert!(program.expect("valid witness program").is_p2wsh()); + continue; + } + assert!(program.is_err()); + } + } + + #[test] + fn valid_v1_witness_programs() { + let arbitrary_bytes = [0x00; 32]; + assert!(WitnessProgram::new(WitnessVersion::V1, &arbitrary_bytes) + .expect("valid witness program") + .is_p2tr()); + + let p2a_bytes = [78, 115]; + assert!(WitnessProgram::new(WitnessVersion::V1, &p2a_bytes) + .expect("valid witness program") + .is_p2a()); + } +} diff --git a/bitcoin/src/blockdata/script/witness_version.rs b/bitcoin/src/blockdata/script/witness_version.rs new file mode 100644 index 000000000..bc09c68c4 --- /dev/null +++ b/bitcoin/src/blockdata/script/witness_version.rs @@ -0,0 +1,250 @@ +//! The segregated witness version byte as defined by [BIP-0141]. +//! +//! > A scriptPubKey (or redeemScript as defined in BIP-0016/P2SH) that consists of a 1-byte push +//! > opcode (for 0 to 16) followed by a data push between 2 and 40 bytes gets a new special +//! > meaning. The value of the first push is called the "version byte". The following byte +//! > vector pushed is called the "witness program". +//! +//! [BIP-0141]: + +use core::convert::Infallible; +use core::fmt; +use core::str::FromStr; + +use internals::write_err; + +use crate::opcodes::all::*; +use crate::opcodes::Opcode; +use crate::parse_int::{self, ParseIntError}; +use crate::script::Instruction; + +/// Version of the segregated witness program. +/// +/// Helps limit possible versions of the witness according to the specification. If a plain `u8` +/// type was used instead it would mean that the version may be > 16, which would be incorrect. +/// +/// First byte of `scriptPubkey` in transaction output for transactions starting with opcodes +/// ranging from 0 to 16 (inclusive). +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[repr(u8)] +pub enum WitnessVersion { + /// Initial version of witness program. Used for P2WPKH and P2WSH outputs + V0 = 0, + /// Version of witness program used for Taproot P2TR outputs. + V1 = 1, + /// Future (unsupported) version of witness program. + V2 = 2, + /// Future (unsupported) version of witness program. + V3 = 3, + /// Future (unsupported) version of witness program. + V4 = 4, + /// Future (unsupported) version of witness program. + V5 = 5, + /// Future (unsupported) version of witness program. + V6 = 6, + /// Future (unsupported) version of witness program. + V7 = 7, + /// Future (unsupported) version of witness program. + V8 = 8, + /// Future (unsupported) version of witness program. + V9 = 9, + /// Future (unsupported) version of witness program. + V10 = 10, + /// Future (unsupported) version of witness program. + V11 = 11, + /// Future (unsupported) version of witness program. + V12 = 12, + /// Future (unsupported) version of witness program. + V13 = 13, + /// Future (unsupported) version of witness program. + V14 = 14, + /// Future (unsupported) version of witness program. + V15 = 15, + /// Future (unsupported) version of witness program. + V16 = 16, +} + +impl WitnessVersion { + /// Returns integer version number representation for a given [`WitnessVersion`] value. + /// + /// NB: this is not the same as an integer representation of the opcode signifying witness + /// version in bitcoin script. Thus, there is no function to directly convert witness version + /// into a byte since the conversion requires context (bitcoin script or just a version number). + pub fn to_num(self) -> u8 { self as u8 } +} + +/// Prints [`WitnessVersion`] number (from 0 to 16) as integer, without any prefix or suffix. +impl fmt::Display for WitnessVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", *self as u8) } +} + +impl FromStr for WitnessVersion { + type Err = FromStrError; + + fn from_str(s: &str) -> Result { + let version: u8 = parse_int::int_from_str(s)?; + Ok(Self::try_from(version)?) + } +} + +impl TryFrom for WitnessVersion { + type Error = TryFromError; + + fn try_from(no: u8) -> Result { + use WitnessVersion::*; + + Ok(match no { + 0 => V0, + 1 => V1, + 2 => V2, + 3 => V3, + 4 => V4, + 5 => V5, + 6 => V6, + 7 => V7, + 8 => V8, + 9 => V9, + 10 => V10, + 11 => V11, + 12 => V12, + 13 => V13, + 14 => V14, + 15 => V15, + 16 => V16, + invalid => return Err(TryFromError { invalid }), + }) + } +} + +impl TryFrom for WitnessVersion { + type Error = TryFromError; + + fn try_from(opcode: Opcode) -> Result { + match opcode.to_u8() { + 0 => Ok(Self::V0), + version if version >= OP_1.to_u8() && version <= OP_16.to_u8() => + Self::try_from(version - OP_1.to_u8() + 1), + invalid => Err(TryFromError { invalid }), + } + } +} + +impl TryFrom> for WitnessVersion { + type Error = TryFromInstructionError; + + fn try_from(instruction: Instruction) -> Result { + match instruction { + Instruction::Op(op) => Ok(Self::try_from(op)?), + Instruction::PushBytes(bytes) if bytes.is_empty() => Ok(Self::V0), + Instruction::PushBytes(_) => Err(TryFromInstructionError::DataPush), + } + } +} + +impl From for Opcode { + fn from(version: WitnessVersion) -> Self { + match version { + WitnessVersion::V0 => OP_PUSHBYTES_0, + no => Self::from(OP_1.to_u8() + no.to_num() - 1), + } + } +} + +/// Error parsing [`WitnessVersion`] from a string. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum FromStrError { + /// Unable to parse integer from string. + Unparsable(ParseIntError), + /// String contained an invalid witness version number. + Invalid(TryFromError), +} + +impl From for FromStrError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for FromStrError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Unparsable(ref e) => write_err!(f, "integer parse error"; e), + Self::Invalid(ref e) => write_err!(f, "invalid version number"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromStrError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Unparsable(ref e) => Some(e), + Self::Invalid(ref e) => Some(e), + } + } +} + +impl From for FromStrError { + fn from(e: ParseIntError) -> Self { Self::Unparsable(e) } +} + +impl From for FromStrError { + fn from(e: TryFromError) -> Self { Self::Invalid(e) } +} + +/// Error attempting to create a [`WitnessVersion`] from an [`Instruction`] +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum TryFromInstructionError { + /// Cannot convert OP to a witness version. + TryFrom(TryFromError), + /// Cannot create a witness version from non-zero data push. + DataPush, +} + +impl From for TryFromInstructionError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for TryFromInstructionError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::TryFrom(ref e) => write_err!(f, "opcode is not a valid witness version"; e), + Self::DataPush => write!(f, "non-zero data push opcode is not a valid witness version"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TryFromInstructionError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::TryFrom(ref e) => Some(e), + Self::DataPush => None, + } + } +} + +impl From for TryFromInstructionError { + fn from(e: TryFromError) -> Self { Self::TryFrom(e) } +} + +/// Error attempting to create a [`WitnessVersion`] from an integer. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TryFromError { + /// The invalid non-witness version integer. + invalid: u8, +} + +impl TryFromError { + /// Returns the invalid non-witness version integer. + pub fn invalid_version(&self) -> u8 { self.invalid } +} + +impl fmt::Display for TryFromError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid witness script version: {}", self.invalid) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TryFromError {} diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs new file mode 100644 index 000000000..f779179df --- /dev/null +++ b/bitcoin/src/blockdata/transaction.rs @@ -0,0 +1,2149 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin transactions. +//! +//! A transaction describes a transfer of money. It consumes previously-unspent +//! transaction outputs and produces new ones, satisfying the condition to spend +//! the old outputs (typically a digital signature with a specific key must be +//! provided) and defining the condition to spend the new ones. The use of digital +//! signatures ensures that coins cannot be spent by unauthorized parties. +//! +//! This module provides the structures and functions needed to support transactions. + +use core::fmt; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use internals::{compact_size, const_casts, write_err, ToU64}; +use io::{BufRead, Write}; + +use super::Weight; +use crate::consensus::{self, encode, Decodable, Encodable}; +use crate::locktime::absolute::{self, Height, MedianTimePast}; +use crate::prelude::{Borrow, Vec}; +use crate::script::{ + RedeemScript, ScriptExt as _, ScriptExtPriv as _, ScriptPubKey, ScriptPubKeyBuf, + ScriptPubKeyExt as _, WitnessScript, +}; +#[cfg(doc)] +use crate::sighash::{EcdsaSighashType, TapSighashType}; +use crate::witness::Witness; +use crate::{internal_macros, Amount, FeeRate, Sequence, SignedAmount}; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use primitives::transaction::{OutPoint, ParseOutPointError, Transaction, Ntxid, Txid, Wtxid, Version, TxIn, TxOut}; + +impl Encodable for Txid { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_byte_array().consensus_encode(w) + } +} + +impl Decodable for Txid { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<[u8; 32]>::consensus_decode(r)?)) + } +} + +impl Encodable for Wtxid { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_byte_array().consensus_encode(w) + } +} + +impl Decodable for Wtxid { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<[u8; 32]>::consensus_decode(r)?)) + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`Txid`] type. + pub trait TxidExt impl for Txid { + /// The "all zeros" TXID. + #[deprecated(since = "TBD", note = "use `Txid::COINBASE_PREVOUT` instead")] + fn all_zeros() -> Self { Self::COINBASE_PREVOUT } + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`Wtxid`] type. + pub trait WtxidExt impl for Wtxid { + /// The "all zeros" wTXID. + #[deprecated(since = "TBD", note = "use `Wtxid::COINBASE` instead")] + fn all_zeros() -> Self { Self::COINBASE } + } +} + +/// Trait that abstracts over a transaction identifier i.e., `Txid` and `Wtxid`. +pub trait TxIdentifier: sealed::Sealed + AsRef<[u8]> {} + +impl TxIdentifier for Txid {} +impl TxIdentifier for Wtxid {} + +// Duplicated in `primitives`. +/// The marker MUST be a 1-byte zero value: 0x00. (BIP-0141) +const SEGWIT_MARKER: u8 = 0x00; +/// The flag MUST be a 1-byte non-zero value. Currently, 0x01 MUST be used. (BIP-0141) +const SEGWIT_FLAG: u8 = 0x01; + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`OutPoint`] type. + pub trait OutPointExt impl for OutPoint { + /// Constructs a new [`OutPoint`]. + #[inline] + #[deprecated(since = "TBD", note = "use struct initialization syntax instead")] + #[allow(clippy::new-ret-no-self)] + fn new(txid: Txid, vout: u32) -> Self { OutPoint { txid, vout } } + + /// Checks if an `OutPoint` is "null". + #[inline] + #[deprecated(since = "TBD", note = "use `outpoint == OutPoint::COINBASE_PREVOUT` instead")] + fn is_null(&self) -> bool { *self == OutPoint::COINBASE_PREVOUT } + } +} + +/// Returns the input base weight. +/// +/// Base weight excludes the witness and script. +// We need to use this const here but do not want to make it public in `primitives::TxIn`. +const TX_IN_BASE_WEIGHT: Weight = + Weight::from_vb_unchecked(OutPoint::SIZE as u64 + Sequence::SIZE as u64); + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`TxIn`] type. + pub trait TxInExt impl for TxIn { + /// Returns true if this input enables the [`absolute::LockTime`] (aka `nLockTime`) of its + /// [`Transaction`]. + /// + /// `nLockTime` is enabled if *any* input enables it. See [`Transaction::is_lock_time_enabled`] + /// to check the overall state. If none of the inputs enables it, the lock time value is simply + /// ignored. If this returns false and OP_CHECKLOCKTIMEVERIFY is used in the redeem script with + /// this input then the script execution will fail [BIP-0065]. + /// + /// [BIP-0065](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki) + fn enables_lock_time(&self) -> bool { self.sequence != Sequence::MAX } + + /// The weight of the TxIn when it's included in a legacy transaction (i.e., a transaction + /// having only legacy inputs). + /// + /// The witness weight is ignored here even when the witness is non-empty. + /// If you want the witness to be taken into account, use `TxIn::segwit_weight` instead. + /// + /// Keep in mind that when adding a TxIn to a transaction, the total weight of the transaction + /// might increase more than `TxIn::legacy_weight`. This happens when the new input added causes + /// the input length `CompactSize` to increase its encoding length. + /// + /// # Panics + /// + /// If the conversion overflows. + fn legacy_weight(&self) -> Weight { + Weight::from_vb(self.base_size().to_u64()).unwrap() + } + + /// The weight of the TxIn when it's included in a SegWit transaction (i.e., a transaction + /// having at least one SegWit input). + /// + /// This always takes into account the witness, even when empty (in which + /// case 1WU for the witness length `00` is included). + /// + /// Keep in mind that when adding a TxIn to a transaction, the total weight of the transaction + /// might increase more than `TxIn::segwit_weight`. This happens when: + /// - the new input added causes the input length `CompactSize` to increase its encoding length + /// - the new input is the first segwit input added - this will add an additional 2WU to the + /// transaction weight to take into account the SegWit marker + /// + /// # Panics + /// + /// If the conversion overflows. + fn segwit_weight(&self) -> Weight { + Weight::from_vb(self.base_size().to_u64()) + .and_then(|w| w.checked_add(Weight::from_wu(self.witness.size().to_u64()))).unwrap() + } + + /// Returns the base size of this input. + /// + /// Base size excludes the witness data (see [`Self::total_size`]). + /// + /// # Panics + /// + /// If the size calculation overflows. + fn base_size(&self) -> usize { + let mut size = OutPoint::SIZE; + + size += compact_size::encoded_size(self.script_sig.len()); + size += self.script_sig.len(); + + size + Sequence::SIZE + } + + /// Returns the total number of bytes that this input contributes to a transaction. + /// + /// Total size includes the witness data (for base size see [`Self::base_size`]). + /// + /// # Panics + /// + /// If the size calculation overflows. + fn total_size(&self) -> usize { self.base_size() + self.witness.size() } + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`TxOut`] type. + pub trait TxOutExt impl for TxOut { + /// The weight of this output. + /// + /// Keep in mind that when adding a [`TxOut`] to a [`Transaction`] the total weight of the + /// transaction might increase more than `TxOut::weight`. This happens when the new output added + /// causes the output length `CompactSize` to increase its encoding length. + /// + /// # Panics + /// + /// If output size * 4 overflows, this should never happen under normal conditions. Use + /// `Weight::from_vb_checked(self.size() as u64)` if you are concerned. + fn weight(&self) -> Weight { + // Size is equivalent to virtual size since all bytes of a TxOut are non-witness bytes. + Weight::from_vb(self.size().to_u64()) + .expect("should never happen under normal conditions") + } + + /// Returns the total number of bytes that this output contributes to a transaction. + /// + /// There is no difference between base size vs total size for outputs. + fn size(&self) -> usize { size_from_script_pubkey(&self.script_pubkey) } + + /// Constructs a new `TxOut` with given script and the smallest possible `value` that is **not** dust + /// per current Core policy. + /// + /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to. + /// This function uses the default value of 0.00003 BTC/kB (3 sat/vByte). + /// + /// To use a custom value, use [`minimal_non_dust_custom`]. + /// + /// [`minimal_non_dust_custom`]: TxOut::minimal_non_dust_custom + fn minimal_non_dust(script_pubkey: ScriptPubKeyBuf) -> Self { + TxOut { amount: script_pubkey.minimal_non_dust(), script_pubkey } + } + + /// Constructs a new `TxOut` with given script and the smallest possible `amount` that is **not** dust + /// per current Core policy. + /// + /// Dust depends on the -dustrelayfee value of the Bitcoin Core node you are broadcasting to. + /// This function lets you set the fee rate used in dust calculation. + /// + /// The current default value in Bitcoin Core (as of v26) is 3 sat/vByte. + /// + /// To use the default Bitcoin Core value, use [`minimal_non_dust`]. + /// + /// [`minimal_non_dust`]: TxOut::minimal_non_dust + fn minimal_non_dust_custom(script_pubkey: ScriptPubKeyBuf, dust_relay_fee: FeeRate) -> Option + where + Self: Sized + { + Some(TxOut { amount: script_pubkey.minimal_non_dust_custom(dust_relay_fee)?, script_pubkey }) + } + } +} + +/// Returns the total number of bytes that this script pubkey would contribute to a transaction. +fn size_from_script_pubkey(script_pubkey: &ScriptPubKey) -> usize { + let len = script_pubkey.len(); + Amount::SIZE + compact_size::encoded_size(len) + len +} + +/// Extension functionality for the [`Transaction`] type. +pub trait TransactionExt: sealed::Sealed { + /// Computes a "normalized TXID" which does not include any signatures. + #[deprecated(since = "0.31.0", note = "use `compute_ntxid()` instead")] + fn ntxid(&self) -> Ntxid; + + /// Computes the [`Txid`]. + #[deprecated(since = "0.31.0", note = "use `compute_txid()` instead")] + fn txid(&self) -> Txid; + + /// Computes the SegWit version of the transaction id. + #[deprecated(since = "0.31.0", note = "use `compute_wtxid()` instead")] + fn wtxid(&self) -> Wtxid; + + /// Returns the weight of this transaction, as defined by BIP-0141. + /// + /// > Transaction weight is defined as Base transaction size * 3 + Total transaction size (ie. + /// > the same method as calculating Block weight from Base size and Total size). + /// + /// For transactions with an empty witness, this is simply the consensus-serialized size times + /// four. For transactions with a witness, this is the non-witness consensus-serialized size + /// multiplied by three plus the with-witness consensus-serialized size. + /// + /// For transactions with no inputs, this function will return a value 2 less than the actual + /// weight of the serialized transaction. The reason is that zero-input transactions, post-SegWit, + /// cannot be unambiguously serialized; we make a choice that adds two extra bytes. For more + /// details see [BIP-0141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) + /// which uses a "input count" of `0x00` as a `marker` for a SegWit-encoded transaction. + /// + /// If you need to use 0-input transactions, we strongly recommend you do so using the PSBT + /// API. The unsigned transaction encoded within PSBT is always a non-SegWit transaction + /// and can therefore avoid this ambiguity. + fn weight(&self) -> Weight; + + /// Returns the base transaction size. + /// + /// > Base transaction size is the size of the transaction serialised with the witness data stripped. + /// + /// # Panics + /// + /// If the size calculation overflows. + fn base_size(&self) -> usize; + + /// Returns the total transaction size. + /// + /// > Total transaction size is the transaction size in bytes serialized as described in BIP-0144, + /// > including base data and witness data. + /// + /// # Panics + /// + /// If the size calculation overflows. + fn total_size(&self) -> usize; + + /// Returns the "virtual size" (vsize) of this transaction. + /// + /// Will be `ceil(weight / 4.0)`. Note this implements the virtual size as per [`BIP-0141`], which + /// is different to what is implemented in Bitcoin Core. The computation should be the same for + /// any remotely sane transaction, and a standardness-rule-correct version is available in the + /// [`policy`] module. + /// + /// > Virtual transaction size is defined as Transaction weight / 4 (rounded up to the next integer). + /// + /// [`BIP-0141`]: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki + /// [`policy`]: crate::policy + fn vsize(&self) -> usize; + + /// Returns `true` if the transaction itself opted in to be BIP-0125-replaceable (RBF). + /// + /// # Warning + /// + /// **Incorrectly relying on RBF may lead to monetary loss!** + /// + /// This **does not** cover the case where a transaction becomes replaceable due to ancestors + /// being RBF. Please note that transactions **may be replaced** even if they **do not** include + /// the RBF signal: . + fn is_explicitly_rbf(&self) -> bool; + + /// Returns true if this [`Transaction`]'s absolute timelock is satisfied at `height`/`time`. + /// + /// # Returns + /// + /// By definition if the lock time is not enabled the transaction's absolute timelock is + /// considered to be satisfied i.e., there are no timelock constraints restricting this + /// transaction from being mined immediately. + fn is_absolute_timelock_satisfied(&self, height: Height, time: MedianTimePast) -> bool; + + /// Returns `true` if this transactions nLockTime is enabled ([BIP-0065]). + /// + /// [BIP-0065]: https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki + fn is_lock_time_enabled(&self) -> bool; + + /// Returns an iterator over lengths of `script_pubkey`s in the outputs. + /// + /// This is useful in combination with [`predict_weight`] if you have the transaction already + /// constructed with a dummy value in the fee output which you'll adjust after calculating the + /// weight. + fn script_pubkey_lens(&self) -> TxOutToScriptPubkeyLengthIter<'_>; + + /// Counts the total number of sigops. + /// + /// This value is for pre-Taproot transactions only. + /// + /// > In Taproot, a different mechanism is used. Instead of having a global per-block limit, + /// > there is a per-transaction-input limit, proportional to the size of that input. + /// > ref: + /// + /// The `spent` parameter is a closure/function that looks up the output being spent by each input + /// It takes in an [`OutPoint`] and returns a [`TxOut`]. If you can't provide this, a placeholder of + /// `|_| None` can be used. Without access to the previous [`TxOut`], any sigops in a redeemScript (P2SH) + /// as well as any SegWit sigops will not be counted for that input. + fn total_sigop_cost(&self, spent: S) -> usize + where + S: FnMut(&OutPoint) -> Option; + + /// Returns a reference to the input at `input_index` if it exists. + fn tx_in(&self, input_index: usize) -> Result<&TxIn, InputsIndexError>; + + /// Returns a reference to the output at `output_index` if it exists. + fn tx_out(&self, output_index: usize) -> Result<&TxOut, OutputsIndexError>; +} + +impl TransactionExt for Transaction { + fn ntxid(&self) -> Ntxid { self.compute_ntxid() } + + fn txid(&self) -> Txid { self.compute_txid() } + + fn wtxid(&self) -> Wtxid { self.compute_wtxid() } + + #[inline] + fn weight(&self) -> Weight { + // This is the exact definition of a weight unit, as defined by BIP-0141 (quote above). + let wu = self.base_size() * 3 + self.total_size(); + Weight::from_wu(wu.to_u64()) + } + + fn base_size(&self) -> usize { + let mut size: usize = 4; // Serialized length of a u32 for the version number. + + size += compact_size::encoded_size(self.inputs.len()); + size += self.inputs.iter().map(|input| input.base_size()).sum::(); + + size += compact_size::encoded_size(self.outputs.len()); + size += self.outputs.iter().map(|output| output.size()).sum::(); + + size + absolute::LockTime::SIZE + } + + #[inline] + fn total_size(&self) -> usize { + let mut size: usize = 4; // Serialized length of a u32 for the version number. + let uses_segwit = self.uses_segwit_serialization(); + + if uses_segwit { + size += 2; // 1 byte for the marker and 1 for the flag. + } + + size += compact_size::encoded_size(self.inputs.len()); + size += self + .inputs + .iter() + .map(|input| if uses_segwit { input.total_size() } else { input.base_size() }) + .sum::(); + + size += compact_size::encoded_size(self.outputs.len()); + size += self.outputs.iter().map(|output| output.size()).sum::(); + + size + absolute::LockTime::SIZE + } + + #[inline] + fn vsize(&self) -> usize { + // No overflow because it's computed from data in memory + self.weight().to_vbytes_ceil() as usize + } + + fn is_explicitly_rbf(&self) -> bool { self.inputs.iter().any(|input| input.sequence.is_rbf()) } + + fn is_absolute_timelock_satisfied(&self, height: Height, time: MedianTimePast) -> bool { + if !self.is_lock_time_enabled() { + return true; + } + self.lock_time.is_satisfied_by(height, time) + } + + fn is_lock_time_enabled(&self) -> bool { self.inputs.iter().any(|i| i.enables_lock_time()) } + + fn script_pubkey_lens(&self) -> TxOutToScriptPubkeyLengthIter<'_> { + TxOutToScriptPubkeyLengthIter { inner: self.outputs.iter() } + } + + fn total_sigop_cost(&self, mut spent: S) -> usize + where + S: FnMut(&OutPoint) -> Option, + { + let mut cost = self.count_p2pk_p2pkh_sigops().saturating_mul(4); + + // coinbase tx is correctly handled because `spent` will always returns None. + cost = cost.saturating_add(self.count_p2sh_sigops(&mut spent).saturating_mul(4)); + cost.saturating_add(self.count_witness_sigops(spent)) + } + + #[inline] + fn tx_in(&self, input_index: usize) -> Result<&TxIn, InputsIndexError> { + self.inputs + .get(input_index) + .ok_or(IndexOutOfBoundsError { index: input_index, length: self.inputs.len() }.into()) + } + + #[inline] + fn tx_out(&self, output_index: usize) -> Result<&TxOut, OutputsIndexError> { + self.outputs + .get(output_index) + .ok_or(IndexOutOfBoundsError { index: output_index, length: self.outputs.len() }.into()) + } +} + +/// Iterates over transaction outputs and for each output yields the length of the scriptPubkey. +// This exists to hardcode the type of the closure created by `map`. +pub struct TxOutToScriptPubkeyLengthIter<'a> { + inner: core::slice::Iter<'a, TxOut>, +} + +impl Iterator for TxOutToScriptPubkeyLengthIter<'_> { + type Item = usize; + + fn next(&mut self) -> Option { self.inner.next().map(|txout| txout.script_pubkey.len()) } +} + +trait TransactionExtPriv { + /// Gets the sigop count. + /// + /// Counts sigops for this transaction's input scriptSigs and output scriptPubkeys i.e., doesn't + /// count sigops in the redeemScript for p2sh or the sigops in the witness (use + /// `count_p2sh_sigops` and `count_witness_sigops` respectively). + fn count_p2pk_p2pkh_sigops(&self) -> usize; + + /// Does not include wrapped SegWit (see `count_witness_sigops`). + fn count_p2sh_sigops(&self, spent: S) -> usize + where + S: FnMut(&OutPoint) -> Option; + + /// Includes wrapped SegWit (returns 0 for Taproot spends). + fn count_witness_sigops(&self, spent: S) -> usize + where + S: FnMut(&OutPoint) -> Option; + + /// Returns whether or not to serialize transaction as specified in BIP-0144. + fn uses_segwit_serialization(&self) -> bool; +} + +impl TransactionExtPriv for Transaction { + /// Gets the sigop count. + fn count_p2pk_p2pkh_sigops(&self) -> usize { + let mut count: usize = 0; + for input in &self.inputs { + // 0 for p2wpkh, p2wsh, and p2sh (including wrapped SegWit). + count = count.saturating_add(input.script_sig.count_sigops_legacy()); + } + for output in &self.outputs { + count = count.saturating_add(output.script_pubkey.count_sigops_legacy()); + } + count + } + + /// Does not include wrapped SegWit (see `count_witness_sigops`). + fn count_p2sh_sigops(&self, mut spent: S) -> usize + where + S: FnMut(&OutPoint) -> Option, + { + fn count_sigops(prevout: &TxOut, input: &TxIn) -> usize { + let mut count: usize = 0; + if prevout.script_pubkey.is_p2sh() { + if let Some(redeem) = input.script_sig.last_pushdata() { + count = count + .saturating_add(RedeemScript::from_bytes(redeem.as_bytes()).count_sigops()); + } + } + count + } + + let mut count: usize = 0; + for input in &self.inputs { + if let Some(prevout) = spent(&input.previous_output) { + count = count.saturating_add(count_sigops(&prevout, input)); + } + } + count + } + + /// Includes wrapped SegWit (returns 0 for Taproot spends). + fn count_witness_sigops(&self, mut spent: S) -> usize + where + S: FnMut(&OutPoint) -> Option, + { + fn count_sigops_with_witness_program( + witness: &Witness, + witness_program: &ScriptPubKey, + ) -> usize { + if witness_program.is_p2wpkh() { + 1 + } else if witness_program.is_p2wsh() { + // Treat the last item of the witness as the witnessScript + witness.last().map(WitnessScript::from_bytes).map(|s| s.count_sigops()).unwrap_or(0) + } else { + 0 + } + } + + fn count_sigops(prevout: TxOut, input: &TxIn) -> usize { + let script_sig = &input.script_sig; + let witness = &input.witness; + + let witness_program = if prevout.script_pubkey.is_witness_program() { + &prevout.script_pubkey + } else if prevout.script_pubkey.is_p2sh() && script_sig.is_push_only() { + // If prevout is P2SH and scriptSig is push only + // then we wrap the last push (redeemScript) in a Script; we use a ScriptPubKey to keep our types + // consistent although strictly speaking it should + // be a RedeemScript. + if let Some(push_bytes) = script_sig.last_pushdata() { + ScriptPubKey::from_bytes(push_bytes.as_bytes()) + } else { + return 0; + } + } else { + return 0; + }; + + // This will return 0 if the redeemScript wasn't a witness program + count_sigops_with_witness_program(witness, witness_program) + } + + let mut count: usize = 0; + for input in &self.inputs { + if let Some(prevout) = spent(&input.previous_output) { + count = count.saturating_add(count_sigops(prevout, input)); + } + } + count + } + + /// Returns whether or not to serialize transaction as specified in BIP-0144. + // This is duplicated in `primitives`, if you change it please do so in both places. + fn uses_segwit_serialization(&self) -> bool { + if self.inputs.iter().any(|input| !input.witness.is_empty()) { + return true; + } + // To avoid serialization ambiguity, no inputs means we use BIP-0141 serialization (see + // `Transaction` docs for full explanation). + self.inputs.is_empty() + } +} + +/// Error attempting to do an out of bounds access on the transaction inputs vector. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InputsIndexError(pub IndexOutOfBoundsError); + +impl fmt::Display for InputsIndexError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write_err!(f, "invalid input index"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InputsIndexError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} + +impl From for InputsIndexError { + fn from(e: IndexOutOfBoundsError) -> Self { Self(e) } +} + +/// Error attempting to do an out of bounds access on the transaction outputs vector. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct OutputsIndexError(pub IndexOutOfBoundsError); + +impl fmt::Display for OutputsIndexError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write_err!(f, "invalid output index"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for OutputsIndexError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} + +impl From for OutputsIndexError { + fn from(e: IndexOutOfBoundsError) -> Self { Self(e) } +} + +/// Error attempting to do an out of bounds access on a vector. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct IndexOutOfBoundsError { + /// Attempted index access. + pub index: usize, + /// Length of the vector where access was attempted. + pub length: usize, +} + +impl fmt::Display for IndexOutOfBoundsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "index {} is out-of-bounds for vector with length {}", self.index, self.length) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for IndexOutOfBoundsError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +impl Encodable for Version { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_u32().consensus_encode(w) + } +} + +impl Decodable for Version { + fn consensus_decode(r: &mut R) -> Result { + Decodable::consensus_decode(r).map(Self::maybe_non_standard) + } +} + +internal_macros::impl_consensus_encoding!(TxOut, amount, script_pubkey); + +impl Encodable for OutPoint { + fn consensus_encode(&self, w: &mut W) -> Result { + let len = self.txid.consensus_encode(w)?; + Ok(len + self.vout.consensus_encode(w)?) + } +} +impl Decodable for OutPoint { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self { + txid: Decodable::consensus_decode(r)?, + vout: Decodable::consensus_decode(r)?, + }) + } +} + +impl Encodable for TxIn { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += self.previous_output.consensus_encode(w)?; + len += self.script_sig.consensus_encode(w)?; + len += self.sequence.consensus_encode(w)?; + Ok(len) + } +} +impl Decodable for TxIn { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + Ok(Self { + previous_output: Decodable::consensus_decode_from_finite_reader(r)?, + script_sig: Decodable::consensus_decode_from_finite_reader(r)?, + sequence: Decodable::consensus_decode_from_finite_reader(r)?, + witness: Witness::default(), + }) + } +} + +impl Encodable for Sequence { + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) + } +} + +impl Decodable for Sequence { + fn consensus_decode(r: &mut R) -> Result { + Decodable::consensus_decode(r).map(Sequence) + } +} + +impl Encodable for Transaction { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += self.version.consensus_encode(w)?; + + // Legacy transaction serialization format only includes inputs and outputs. + if !self.uses_segwit_serialization() { + len += self.inputs.consensus_encode(w)?; + len += self.outputs.consensus_encode(w)?; + } else { + // BIP-0141 (SegWit) transaction serialization also includes marker, flag, and witness data. + len += SEGWIT_MARKER.consensus_encode(w)?; + len += SEGWIT_FLAG.consensus_encode(w)?; + len += self.inputs.consensus_encode(w)?; + len += self.outputs.consensus_encode(w)?; + for input in &self.inputs { + len += input.witness.consensus_encode(w)?; + } + } + len += self.lock_time.consensus_encode(w)?; + Ok(len) + } +} + +impl Decodable for Transaction { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let version = Version::consensus_decode_from_finite_reader(r)?; + let inputs = Vec::::consensus_decode_from_finite_reader(r)?; + // SegWit + if inputs.is_empty() { + let segwit_flag = u8::consensus_decode_from_finite_reader(r)?; + match segwit_flag { + // BIP-0144 input witnesses + 1 => { + let mut inputs = Vec::::consensus_decode_from_finite_reader(r)?; + let outputs = Vec::::consensus_decode_from_finite_reader(r)?; + for txin in inputs.iter_mut() { + txin.witness = Decodable::consensus_decode_from_finite_reader(r)?; + } + if !inputs.is_empty() && inputs.iter().all(|input| input.witness.is_empty()) { + Err(consensus::parse_failed_error( + "witness flag set but no witnesses present", + )) + } else { + Ok(Self { + version, + inputs, + outputs, + lock_time: Decodable::consensus_decode_from_finite_reader(r)?, + }) + } + } + // We don't support anything else + x => Err(encode::ParseError::UnsupportedSegwitFlag(x).into()), + } + // non-SegWit + } else { + Ok(Self { + version, + inputs, + outputs: Decodable::consensus_decode_from_finite_reader(r)?, + lock_time: Decodable::consensus_decode_from_finite_reader(r)?, + }) + } + } +} + +/// Computes the value of an output accounting for the cost of spending it. +/// +/// The effective value is the value of an output value minus the amount to spend it. That is, the +/// effective_value can be calculated as: value - (fee_rate * weight). +/// +/// Note: the effective value of a [`Transaction`] may increase less than the effective value of +/// a [`TxOut`] when adding another [`TxOut`] to the transaction. This happens when the new +/// [`TxOut`] added causes the output length `CompactSize` to increase its encoding length. +/// +/// # Parameters +/// +/// * `fee_rate` - the fee rate of the transaction being created. +/// * `input_weight_prediction` - the predicted input weight. +/// * `value` - the value of the output we are spending. +pub fn effective_value( + fee_rate: FeeRate, + input_weight_prediction: InputWeightPrediction, + value: Amount, +) -> SignedAmount { + let weight = input_weight_prediction.total_weight(); + let fee = fee_rate.to_fee(weight); + + value.signed_sub(fee) +} + +/// Predicts the weight of a to-be-constructed transaction. +/// +/// This function computes the weight of a transaction which is not fully known. All that is needed +/// is the lengths of scripts and witness elements. +/// +/// # Parameters +/// +/// * `inputs` - an iterator which returns `InputWeightPrediction` for each input of the +/// to-be-constructed transaction. +/// * `output_script_lens` - an iterator which returns the length of `script_pubkey` of each output +/// of the to-be-constructed transaction. +/// +/// Note that lengths of the scripts and witness elements must be non-serialized, IOW *without* the +/// length prefix. The length is computed and added inside the function for convenience. +/// +/// If you have the transaction already constructed (except for signatures) with a dummy value for +/// fee output you can use the return value of [`Transaction::script_pubkey_lens`] method directly +/// as the second argument. +/// +/// # Usage +/// +/// When signing a transaction one doesn't know the signature before knowing the transaction fee and +/// the transaction fee is not known before knowing the transaction size which is not known before +/// knowing the signature. This apparent dependency cycle can be broken by knowing the length of the +/// signature without knowing the contents of the signature e.g., we know all Schnorr signatures +/// are 64 bytes long. +/// +/// Additionally, some protocols may require calculating the amounts before knowing various parts +/// of the transaction (assuming their length is known). +/// +/// # Notes on integer overflow +/// +/// Overflows are intentionally not checked because one of the following holds: +/// +/// * The transaction is valid (obeys the block size limit) and the code feeds correct values to +/// this function - no overflow can happen. +/// * The transaction will be so large it doesn't fit in the memory - overflow will happen but +/// then the transaction will fail to construct and even if one serialized it on disk directly +/// it'd be invalid anyway so overflow doesn't matter. +/// * The values fed into this function are inconsistent with the actual lengths the transaction +/// will have - the code is already broken and checking overflows doesn't help. Unfortunately +/// this probably cannot be avoided. +pub fn predict_weight(inputs: I, output_script_lens: O) -> Weight +where + I: IntoIterator, + O: IntoIterator, +{ + let (input_count, input_weight, inputs_with_witnesses) = + inputs.into_iter().fold((0, 0, 0), |(count, weight, with_witnesses), prediction| { + ( + count + 1, + weight + prediction.total_weight().to_wu() as usize, + with_witnesses + (prediction.witness_size > 0) as usize, + ) + }); + + let (output_count, output_scripts_size) = + output_script_lens.into_iter().fold((0, 0), |(count, scripts_size), script_len| { + (count + 1, scripts_size + script_len + compact_size::encoded_size(script_len)) + }); + + predict_weight_internal( + input_count, + input_weight, + inputs_with_witnesses, + output_count, + output_scripts_size, + ) +} + +const fn predict_weight_internal( + input_count: usize, + input_weight: usize, + inputs_with_witnesses: usize, + output_count: usize, + output_scripts_size: usize, +) -> Weight { + // The value field of a TxOut is 8 bytes. + let output_size = 8 * output_count + output_scripts_size; + let non_input_size = 4 // version + + compact_size::encoded_size_const(input_count as u64) // Can't use ToU64 in const context. + + compact_size::encoded_size_const(output_count as u64) + + output_size + + 4; // locktime + let weight = if inputs_with_witnesses == 0 { + non_input_size * 4 + input_weight + } else { + non_input_size * 4 + input_weight + input_count - inputs_with_witnesses + 2 + }; + Weight::from_wu(weight as u64) +} + +/// Predicts the weight of a to-be-constructed transaction in const context. +/// +/// This is a `const` version of [`predict_weight`] which only allows slices due to current Rust +/// limitations around `const fn`. Because of these limitations it may be less efficient than +/// `predict_weight` and thus is intended to be only used in `const` context. +/// +/// Please see the documentation of `predict_weight` to learn more about this function. +pub const fn predict_weight_from_slices( + inputs: &[InputWeightPrediction], + output_script_lens: &[usize], +) -> Weight { + let mut input_weight = 0; + let mut inputs_with_witnesses = 0; + + // for loops not supported in const fn + let mut i = 0; + while i < inputs.len() { + let prediction = inputs[i]; + input_weight += prediction.total_weight().to_wu() as usize; + inputs_with_witnesses += (prediction.witness_size > 0) as usize; + i += 1; + } + + let mut output_scripts_size = 0; + + i = 0; + while i < output_script_lens.len() { + let script_len = output_script_lens[i]; + output_scripts_size += script_len + compact_size::encoded_size_const(script_len as u64); + i += 1; + } + + predict_weight_internal( + inputs.len(), + input_weight, + inputs_with_witnesses, + output_script_lens.len(), + output_scripts_size, + ) +} + +/// Weight prediction of an individual input. +/// +/// This helper type collects information about an input to be used in [`predict_weight`] function. +/// It can only be created using the [`new`](InputWeightPrediction::new) function or using other +/// associated constants/methods. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct InputWeightPrediction { + script_size: u32, + witness_size: u32, +} + +impl InputWeightPrediction { + /// Input weight prediction corresponding to spending of P2WPKH output with the largest possible + /// DER-encoded signature. + /// + /// If the input in your transaction uses P2WPKH you can use this instead of + /// [`InputWeightPrediction::new`]. + /// + /// This is useful when you **do not** use [signature grinding] and want to ensure you are not + /// under-paying. See [`ground_p2wpkh`](Self::ground_p2wpkh) if you do use signature grinding. + /// + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const P2WPKH_MAX: Self = Self::from_slice(0, &[72, 33]); + + /// Input weight prediction corresponding to spending of [nested P2WPKH] output with the largest possible + /// DER-encoded signature. + /// + /// If the input in your transaction uses nested P2WPKH you can use this instead of + /// [`InputWeightPrediction::new`]. + /// + /// This is useful when you **do not** use [signature grinding] and want to ensure you are not + /// under-paying. See [`ground_nested_p2wpkh`](Self::ground_nested_p2wpkh) if you do use signature grinding. + /// + /// [nested P2WPKH]: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh-nested-in-bip16-p2sh + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const NESTED_P2WPKH_MAX: Self = Self::from_slice(23, &[72, 33]); + + /// Input weight prediction corresponding to spending of a P2PKH output with the largest possible + /// DER-encoded signature, and a compressed public key. + /// + /// If the input in your transaction uses P2PKH with a compressed key, you can use this instead of + /// [`InputWeightPrediction::new`]. + /// + /// This is useful when you **do not** use [signature grinding] and want to ensure you are not + /// under-paying. See [`ground_p2pkh_compressed`](Self::ground_p2pkh_compressed) if you do use + /// signature grinding. + /// + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const P2PKH_COMPRESSED_MAX: Self = Self::from_slice(107, &[]); + + /// Input weight prediction corresponding to spending of a P2PKH output with the largest possible + /// DER-encoded signature, and an uncompressed public key. + /// + /// If the input in your transaction uses P2PKH with an uncompressed key, you can use this instead of + /// [`InputWeightPrediction::new`]. + pub const P2PKH_UNCOMPRESSED_MAX: Self = Self::from_slice(139, &[]); + + /// Input weight prediction corresponding to spending of Taproot output using the key and + /// default sighash. + /// + /// If the input in your transaction uses Taproot key spend you can use this instead of + /// [`InputWeightPrediction::new`]. + pub const P2TR_KEY_DEFAULT_SIGHASH: Self = Self::from_slice(0, &[64]); + + /// Input weight prediction corresponding to spending of Taproot output using the key and + /// **non**-default sighash. + /// + /// If the input in your transaction uses Taproot key spend you can use this instead of + /// [`InputWeightPrediction::new`]. + pub const P2TR_KEY_NON_DEFAULT_SIGHASH: Self = Self::from_slice(0, &[65]); + + const fn saturate_to_u32(x: usize) -> u32 { + if x > u32::MAX as usize { + u32::MAX + } else { + x as u32 //cast ok, condition prevents larger than u32::MAX. + } + } + + const fn encoded_size(value: usize) -> u32 { + match value { + 0..=0xFC => 1, + 0xFD..=0xFFFF => 3, + 0x10000..=0xFFFFFFFF => 5, + _ => 9, + } + } + + /// Input weight prediction corresponding to spending of P2WPKH output using [signature + /// grinding]. + /// + /// If the input in your transaction uses P2WPKH and you use signature grinding you can use this + /// instead of [`InputWeightPrediction::new`]. See [`P2WPKH_MAX`](Self::P2WPKH_MAX) if you don't + /// use signature grinding. + /// + /// Note: `bytes_to_grind` is usually `1` because of exponential cost of higher values. + /// + /// # Panics + /// + /// The function panics in const context and debug builds if `bytes_to_grind` is higher than 62. + /// + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const fn ground_p2wpkh(bytes_to_grind: usize) -> Self { + // Written to trigger const/debug panic for unreasonably high values. + let der_signature_size = 10 + (62 - bytes_to_grind); + Self::from_slice(0, &[der_signature_size, 33]) + } + + /// Input weight prediction corresponding to spending of [nested P2WPKH] output using [signature + /// grinding]. + /// + /// If the input in your transaction uses P2WPKH and you use signature grinding you can use this + /// instead of [`InputWeightPrediction::new`]. See [`NESTED_P2WPKH_MAX`](Self::NESTED_P2WPKH_MAX) if you don't + /// use signature grinding. + /// + /// Note: `bytes_to_grind` is usually `1` because of exponential cost of higher values. + /// + /// # Panics + /// + /// The function panics in const context and debug builds if `bytes_to_grind` is higher than 62. + /// + /// [nested P2WPKH]: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh-nested-in-bip16-p2sh + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const fn ground_nested_p2wpkh(bytes_to_grind: usize) -> Self { + // Written to trigger const/debug panic for unreasonably high values. + let der_signature_size = 10 + (62 - bytes_to_grind); + Self::from_slice(23, &[der_signature_size, 33]) + } + + /// Input weight prediction corresponding to spending of a P2PKH output using [signature + /// grinding], and a compressed public key. + /// + /// If the input in your transaction uses compressed P2PKH and you use signature grinding you + /// can use this instead of [`InputWeightPrediction::new`]. See + /// [`P2PKH_COMPRESSED_MAX`](Self::P2PKH_COMPRESSED_MAX) if you don't use signature grinding. + /// + /// Note: `bytes_to_grind` is usually `1` because of exponential cost of higher values. + /// + /// # Panics + /// + /// The function panics in const context and debug builds if `bytes_to_grind` is higher than 62. + /// + /// [signature grinding]: https://bitcoin.stackexchange.com/questions/111660/what-is-signature-grinding + pub const fn ground_p2pkh_compressed(bytes_to_grind: usize) -> Self { + // Written to trigger const/debug panic for unreasonably high values. + let der_signature_size = 10 + (62 - bytes_to_grind); + + Self::from_slice(2 + 33 + der_signature_size, &[]) + } + + /// Computes the prediction for a single input. + pub fn new(input_script_len: usize, witness_element_lengths: T) -> Self + where + T: IntoIterator, + T::Item: Borrow, + { + let (count, total_size) = witness_element_lengths.into_iter().fold( + (0usize, 0u32), + |(count, total_size), elem_len| { + let elem_len = *elem_len.borrow(); + let elem_size = + Self::saturate_to_u32(elem_len).saturating_add(Self::encoded_size(elem_len)); + (count + 1, total_size.saturating_add(elem_size)) + }, + ); + let witness_size = if count > 0 { total_size + Self::encoded_size(count) } else { 0 }; + let script_size = + Self::saturate_to_u32(input_script_len) + Self::encoded_size(input_script_len); + + Self { script_size, witness_size } + } + + /// Computes the prediction for a single input in `const` context. + /// + /// This is a `const` version of [`new`](Self::new) which only allows slices due to current Rust + /// limitations around `const fn`. Because of these limitations it may be less efficient than + /// `new` and thus is intended to be only used in `const` context. + pub const fn from_slice(input_script_len: usize, witness_element_lengths: &[usize]) -> Self { + let mut i = 0; + let mut total_size: u32 = 0; + // for loops not supported in const fn + while i < witness_element_lengths.len() { + let elem_len = witness_element_lengths[i]; + let elem_size = + Self::saturate_to_u32(elem_len).saturating_add(Self::encoded_size(elem_len)); + total_size = total_size.saturating_add(elem_size); + i += 1; + } + let witness_size = if !witness_element_lengths.is_empty() { + total_size.saturating_add(Self::encoded_size(witness_element_lengths.len())) + } else { + 0 + }; + let script_size = Self::saturate_to_u32(input_script_len) + .saturating_add(Self::encoded_size(input_script_len)); + + Self { script_size, witness_size } + } + + /// Computes the **signature weight** added to a transaction by an input with this weight prediction, + /// not counting the prevout (txid, index), sequence, potential witness flag bytes or the witness count. + /// + /// This function's internal arithmetic saturates at u32::MAX, so the return value of this + /// function may be inaccurate for extremely large witness predictions. + #[deprecated(since = "TBD", note = "use `InputWeightPrediction::witness_weight()` instead")] + pub const fn weight(&self) -> Weight { Self::witness_weight(self) } + + /// Computes the signature, prevout (txid, index), and sequence weights of this weight + /// prediction. + /// + /// This function's internal arithmetic saturates at u32::MAX, so the return value of this + /// function may be inaccurate for extremely large witness predictions. + /// + /// See also [`InputWeightPrediction::witness_weight`] + pub const fn total_weight(&self) -> Weight { + // `impl const Trait` is currently unavailable: rust/issues/67792 + // Convert to u64s because we can't use `Add` in const context. + let weight = TX_IN_BASE_WEIGHT.to_wu() + Self::witness_weight(self).to_wu(); + Weight::from_wu(weight) + } + + /// Computes the **signature weight** added to a transaction by an input with this weight prediction, + /// not counting the prevout (txid, index), sequence, potential witness flag bytes or the witness count. + /// + /// This function's internal arithmetic saturates at u32::MAX, so the return value of this + /// function may be inaccurate for extremely large witness predictions. + /// + /// See also [`InputWeightPrediction::total_weight`] + pub const fn witness_weight(&self) -> Weight { + let wu = self.script_size * 4 + self.witness_size; + let wu = const_casts::u32_to_u64(wu); + Weight::from_wu(wu) + } +} + +internals::transparent_newtype! { + /// A wrapper type for the coinbase transaction of a block. + /// + /// This type exists to distinguish coinbase transactions from regular ones at the type level. + #[derive(Clone, PartialEq, Eq, Debug, Hash)] + pub struct Coinbase(Transaction); + + impl Coinbase { + /// Constructs a reference to `Coinbase` from a reference to the inner `Transaction`. + /// + /// This method does not validate that the transaction is actually a coinbase transaction. + /// The caller must ensure that the transaction is indeed a valid coinbase transaction + pub fn assume_coinbase_ref(inner: &_) -> &Self; + } +} + +impl Coinbase { + /// Constructs a `Coinbase` wrapper assuming this transaction is a coinbase transaction. + /// + /// This method does not validate that the transaction is actually a coinbase transaction. + /// The caller must ensure that this transaction is indeed a valid coinbase transaction. + pub fn assume_coinbase(tx: Transaction) -> Self { Self(tx) } + + /// Returns the first input of this coinbase transaction. + /// + /// This method is infallible because a valid coinbase transaction is guaranteed + /// to have exactly one input. + pub fn first_input(&self) -> &TxIn { &self.0.inputs[0] } + + /// Returns a reference to the underlying transaction. + /// + /// Warning: The coinbase input contains dummy prevouts that should not be treated as real prevouts. + #[doc(alias = "as_inner")] + pub fn as_transaction(&self) -> &Transaction { &self.0 } + + /// Returns the underlying transaction. + /// + /// Warning: The coinbase input contains dummy prevouts that should not be treated as real prevouts. + #[doc(alias = "into_inner")] + pub fn into_transaction(self) -> Transaction { self.0 } + + /// Computes the [`Txid`] of this coinbase transaction. + pub fn compute_txid(&self) -> Txid { self.0.compute_txid() } + + /// Returns the wtxid of this coinbase transaction. + /// + /// For coinbase transactions, this is always `Wtxid::COINBASE`. + #[doc(alias = "compute_wtxid")] + pub const fn wtxid(&self) -> Wtxid { Wtxid::COINBASE } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::Transaction {} + impl Sealed for super::Txid {} + impl Sealed for super::Wtxid {} + impl Sealed for super::OutPoint {} + impl Sealed for super::TxIn {} + impl Sealed for super::TxOut {} + impl Sealed for super::Version {} +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for InputWeightPrediction { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match u.int_in_range(0..=7)? { + 0 => Ok(Self::P2WPKH_MAX), + 1 => Ok(Self::NESTED_P2WPKH_MAX), + 2 => Ok(Self::P2PKH_COMPRESSED_MAX), + 3 => Ok(Self::P2PKH_UNCOMPRESSED_MAX), + 4 => Ok(Self::P2TR_KEY_DEFAULT_SIGHASH), + 5 => Ok(Self::P2TR_KEY_NON_DEFAULT_SIGHASH), + 6 => { + let input_script_len = usize::arbitrary(u)?; + let witness_element_lengths: Vec = Vec::arbitrary(u)?; + Ok(Self::new(input_script_len, witness_element_lengths)) + } + _ => { + let input_script_len = usize::arbitrary(u)?; + let witness_element_lengths: Vec = Vec::arbitrary(u)?; + Ok(Self::from_slice(input_script_len, &witness_element_lengths)) + } + } + } +} + +#[cfg(test)] +mod tests { + use hex::FromHex; + use hex_lit::hex; + + use super::*; + use crate::consensus::encode::{deserialize, serialize}; + use crate::constants::WITNESS_SCALE_FACTOR; + use crate::parse_int; + use crate::script::ScriptSigBuf; + use crate::sighash::EcdsaSighashType; + + const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; + + #[test] + fn encode_to_unsized_writer() { + let mut buf = [0u8; 1024]; + let raw_tx = hex!(SOME_TX); + let tx: Transaction = Decodable::consensus_decode(&mut raw_tx.as_slice()).unwrap(); + + let size = tx.consensus_encode(&mut &mut buf[..]).unwrap(); + assert_eq!(size, SOME_TX.len() / 2); + assert_eq!(raw_tx, &buf[..size]); + } + + #[test] + fn outpoint() { + assert_eq!("i don't care".parse::(), Err(ParseOutPointError::Format)); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:1:1" + .parse::(), + Err(ParseOutPointError::Format) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:".parse::(), + Err(ParseOutPointError::Format) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:11111111111" + .parse::(), + Err(ParseOutPointError::TooLong) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:01" + .parse::(), + Err(ParseOutPointError::VoutNotCanonical) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:+42" + .parse::(), + Err(ParseOutPointError::VoutNotCanonical) + ); + assert_eq!( + "i don't care:1".parse::(), + Err(ParseOutPointError::Txid("i don't care".parse::().unwrap_err())) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X:1" + .parse::(), + Err(ParseOutPointError::Txid( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c945X" + .parse::() + .unwrap_err() + )) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol" + .parse::(), + Err(ParseOutPointError::Vout(parse_int::int_from_str::("lol").unwrap_err())) + ); + + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:42" + .parse::(), + Ok(OutPoint { + txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + .parse() + .unwrap(), + vout: 42, + }) + ); + assert_eq!( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0" + .parse::(), + Ok(OutPoint { + txid: "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456" + .parse() + .unwrap(), + vout: 0, + }) + ); + } + + #[test] + fn txin() { + let txin: Result = deserialize(&hex!("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff")); + assert!(txin.is_ok()); + } + + #[test] + fn is_coinbase() { + use crate::constants; + use crate::network::Network; + + let genesis = constants::genesis_block(Network::Bitcoin); + assert!(genesis.transactions()[0].is_coinbase()); + let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); + assert!(!tx.is_coinbase()); + } + + #[test] + fn nonsegwit_transaction() { + let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"); + let tx: Result = deserialize(&tx_bytes); + assert!(tx.is_ok()); + let realtx = tx.unwrap(); + // All these tests aren't really needed because if they fail, the hash check at the end + // will also fail. But these will show you where the failure is so I'll leave them in. + assert_eq!(realtx.version, Version::ONE); + assert_eq!(realtx.inputs.len(), 1); + // In particular this one is easy to get backward -- in bitcoin hashes are encoded + // as little-endian 256-bit numbers rather than as data strings. + assert_eq!( + format!("{:x}", realtx.inputs[0].previous_output.txid), + "ce9ea9f6f5e422c6a9dbcddb3b9a14d1c78fab9ab520cb281aa2a74a09575da1".to_string() + ); + assert_eq!(realtx.inputs[0].previous_output.vout, 1); + assert_eq!(realtx.outputs.len(), 1); + assert_eq!(realtx.lock_time, absolute::LockTime::ZERO); + + assert_eq!( + format!("{:x}", realtx.compute_txid()), + "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string() + ); + assert_eq!( + format!("{:x}", realtx.compute_wtxid()), + "a6eab3c14ab5272a58a5ba91505ba1a4b6d7a3a9fcbd187b6cd99a7b6d548cb7".to_string() + ); + assert_eq!(realtx.weight().to_wu() as usize, tx_bytes.len() * WITNESS_SCALE_FACTOR); + assert_eq!(realtx.total_size(), tx_bytes.len()); + assert_eq!(realtx.vsize(), tx_bytes.len()); + assert_eq!(realtx.base_size(), tx_bytes.len()); + } + + #[test] + fn segwit_invalid_transaction() { + let tx_bytes = hex!("0000fd000001021921212121212121212121f8b372b0239cc1dff600000000004f4f4f4f4f4f4f4f000000000000000000000000000000333732343133380d000000000000000000000000000000ff000000000009000dff000000000000000800000000000000000d"); + let tx: Result = deserialize(&tx_bytes); + assert!(tx.is_err()); + assert!(matches!(tx.unwrap_err(), crate::consensus::DeserializeError::Parse(_))); + } + + #[test] + fn segwit_transaction() { + let tx_bytes = hex!( + "02000000000101595895ea20179de87052b4046dfe6fd515860505d6511a9004cf12a1f93cac7c01000000\ + 00ffffffff01deb807000000000017a9140f3444e271620c736808aa7b33e370bd87cb5a078702483045022\ + 100fb60dad8df4af2841adc0346638c16d0b8035f5e3f3753b88db122e70c79f9370220756e6633b17fd271\ + 0e626347d28d60b0a2d6cbb41de51740644b9fb3ba7751040121028fa937ca8cba2197a37c007176ed89410\ + 55d3bcb8627d085e94553e62f057dcc00000000" + ); + let tx: Result = deserialize(&tx_bytes); + assert!(tx.is_ok()); + let realtx = tx.unwrap(); + // All these tests aren't really needed because if they fail, the hash check at the end + // will also fail. But these will show you where the failure is so I'll leave them in. + assert_eq!(realtx.version, Version::TWO); + assert_eq!(realtx.inputs.len(), 1); + // In particular this one is easy to get backward -- in bitcoin hashes are encoded + // as little-endian 256-bit numbers rather than as data strings. + assert_eq!( + format!("{:x}", realtx.inputs[0].previous_output.txid), + "7cac3cf9a112cf04901a51d605058615d56ffe6d04b45270e89d1720ea955859".to_string() + ); + assert_eq!(realtx.inputs[0].previous_output.vout, 1); + assert_eq!(realtx.outputs.len(), 1); + assert_eq!(realtx.lock_time, absolute::LockTime::ZERO); + + assert_eq!( + format!("{:x}", realtx.compute_txid()), + "f5864806e3565c34d1b41e716f72609d00b55ea5eac5b924c9719a842ef42206".to_string() + ); + assert_eq!( + format!("{:x}", realtx.compute_wtxid()), + "80b7d8a82d5d5bf92905b06f2014dd699e03837ca172e3a59d51426ebbe3e7f5".to_string() + ); + const EXPECTED_WEIGHT: Weight = Weight::from_wu(442); + assert_eq!(realtx.weight(), EXPECTED_WEIGHT); + assert_eq!(realtx.total_size(), tx_bytes.len()); + assert_eq!(realtx.vsize(), 111); + + let expected_strippedsize = (442 - realtx.total_size()) / 3; + assert_eq!(realtx.base_size(), expected_strippedsize); + + // Construct a transaction without the witness data. + let mut tx_without_witness = realtx; + tx_without_witness.inputs.iter_mut().for_each(|input| input.witness.clear()); + assert_eq!(tx_without_witness.total_size(), tx_without_witness.total_size()); + assert_eq!(tx_without_witness.total_size(), expected_strippedsize); + } + + // We temporarily abuse `Transaction` for testing consensus serde adapter. + #[test] + #[cfg(feature = "serde")] + fn consensus_serde() { + use crate::consensus::serde as con_serde; + let json = "\"010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000\""; + let mut deserializer = serde_json::Deserializer::from_str(json); + let tx = + con_serde::With::::deserialize::<'_, Transaction, _>(&mut deserializer) + .unwrap(); + let tx_bytes = Vec::from_hex(&json[1..(json.len() - 1)]).unwrap(); + let expected = deserialize::(&tx_bytes).unwrap(); + assert_eq!(tx, expected); + let mut bytes = Vec::new(); + let mut serializer = serde_json::Serializer::new(&mut bytes); + con_serde::With::::serialize(&tx, &mut serializer).unwrap(); + assert_eq!(bytes, json.as_bytes()) + } + + #[test] + fn transaction_version() { + let tx_bytes = hex!("ffffffff0100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"); + let tx: Result = deserialize(&tx_bytes); + assert!(tx.is_ok()); + let realtx = tx.unwrap(); + assert_eq!(realtx.version, Version::maybe_non_standard(u32::MAX)); + } + + #[test] + fn tx_no_input_deserialization() { + let tx_bytes = hex!( + "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000" + ); + let tx: Transaction = deserialize(&tx_bytes).expect("deserialize tx"); + + assert_eq!(tx.inputs.len(), 0); + assert_eq!(tx.outputs.len(), 1); + + let reser = serialize(&tx); + assert_eq!(tx_bytes, *reser); + } + + #[test] + fn ntxid() { + let tx_bytes = hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"); + let mut tx: Transaction = deserialize(&tx_bytes).unwrap(); + + let old_ntxid = tx.compute_ntxid(); + assert_eq!( + format!("{:x}", old_ntxid), + "c3573dbea28ce24425c59a189391937e00d255150fa973d59d61caf3a06b601d" + ); + // changing sigs does not affect it + tx.inputs[0].script_sig = ScriptSigBuf::new(); + assert_eq!(old_ntxid, tx.compute_ntxid()); + // changing pks does + tx.outputs[0].script_pubkey = ScriptPubKeyBuf::new(); + assert!(old_ntxid != tx.compute_ntxid()); + } + + #[test] + fn txid() { + // SegWit tx from Liquid integration tests, txid/hash from Core decoderawtransaction + let tx_bytes = hex!( + "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\ + 23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\ + 1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\ + 9d5417e592ed99d256ddfd8b3b2238ac73f5da1b06fc0b2e79d54f414d4c0ba0c8f505000000001976a914\ + dcb5898d9036afad9209e6ff0086772795b1441088ac033c0f000000000017a914889f8c10ff2bd4bb9dab\ + b68c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87\ + 033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a914\ + 889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb6\ + 8c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c8703\ + 3c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a91488\ + 9f8c10ff2bd4bb9dabb68c5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c\ + 5c0d700a46925e6c87033c0f000000000017a914889f8c10ff2bd4bb9dabb68c5c0d700a46925e6c870500\ + 47304402200380b8663e727d7e8d773530ef85d5f82c0b067c97ae927800a0876a1f01d8e2022021ee611e\ + f6507dfd217add2cd60a8aea3cbcfec034da0bebf3312d19577b8c290147304402207bd9943ce1c2c5547b\ + 120683fd05d78d23d73be1a5b5a2074ff586b9c853ed4202202881dcf435088d663c9af7b23efb3c03b9db\ + c0c899b247aa94a74d9b4b3c84f501483045022100ba12bba745af3f18f6e56be70f8382ca8e107d1ed5ce\ + aa3e8c360d5ecf78886f022069b38ebaac8fe6a6b97b497cbbb115f3176f7213540bef08f9292e5a72de52\ + de01695321023c9cd9c6950ffee24772be948a45dc5ef1986271e46b686cb52007bac214395a2102756e27\ + cb004af05a6e9faed81fd68ff69959e3c64ac8c9f6cd0e08fd0ad0e75d2103fa40da236bd82202a985a910\ + 4e851080b5940812685769202a3b43e4a8b13e6a53ae050048304502210098b9687b81d725a7970d1eee91\ + ff6b89bc9832c2e0e3fb0d10eec143930b006f02206f77ce19dc58ecbfef9221f81daad90bb4f468df3912\ + 12abc4f084fe2cc9bdef01483045022100e5479f81a3ad564103da5e2ec8e12f61f3ac8d312ab68763c1dd\ + d7bae94c20610220789b81b7220b27b681b1b2e87198897376ba9d033bc387f084c8b8310c8539c2014830\ + 45022100aa1cc48a2d256c0e556616444cc08ae4959d464e5ffff2ae09e3550bdab6ce9f02207192d5e332\ + 9a56ba7b1ead724634d104f1c3f8749fe6081e6233aee3e855817a016953210260de9cc68658c61af984e3\ + ab0281d17cfca1cc035966d335f474932d5e6c5422210355fbb768ce3ce39360277345dbb5f376e706459e\ + 5a2b5e0e09a535e61690647021023222ceec58b94bd25925dd9743dae6b928737491bd940fc5dd7c6f5d5f\ + 2adc1e53ae00000000" + ); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); + + assert_eq!( + format!("{:x}", tx.compute_wtxid()), + "d6ac4a5e61657c4c604dcde855a1db74ec6b3e54f32695d72c5e11c7761ea1b4" + ); + assert_eq!( + format!("{:x}", tx.compute_txid()), + "9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec" + ); + assert_eq!(format!("{:.10x}", tx.compute_txid()), "9652aa62b0"); + assert_eq!(tx.weight(), Weight::from_wu(2718)); + + // non-SegWit tx from my mempool + let tx_bytes = hex!( + "01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\ + 30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\ + 343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\ + 7a8469bd565aff10e8d42cef931fad5121bfb8ffffffff02b825b404000000001976a914ef79e7ee9fff98\ + bcfd08473d2b76b02a48f8c69088ac0000000000000000296a273236303039343836393731373233313237\ + 3633313032313332353630353838373931323132373000000000" + ); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); + + assert_eq!( + format!("{:x}", tx.compute_wtxid()), + "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd" + ); + assert_eq!( + format!("{:x}", tx.compute_txid()), + "971ed48a62c143bbd9c87f4bafa2ef213cfa106c6e140f111931d0be307468dd" + ); + } + + #[test] + fn sighashtype_fromstr_display() { + let sighashtypes = [ + ("SIGHASH_ALL", EcdsaSighashType::All), + ("SIGHASH_NONE", EcdsaSighashType::None), + ("SIGHASH_SINGLE", EcdsaSighashType::Single), + ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", EcdsaSighashType::AllPlusAnyoneCanPay), + ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", EcdsaSighashType::NonePlusAnyoneCanPay), + ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", EcdsaSighashType::SinglePlusAnyoneCanPay), + ]; + for (s, sht) in sighashtypes { + assert_eq!(sht.to_string(), s); + assert_eq!(s.parse::().unwrap(), sht); + } + let sht_mistakes = [ + "SIGHASH_ALL | SIGHASH_ANYONECANPAY", + "SIGHASH_NONE |SIGHASH_ANYONECANPAY", + "SIGHASH_SINGLE| SIGHASH_ANYONECANPAY", + "SIGHASH_ALL SIGHASH_ANYONECANPAY", + "SIGHASH_NONE |", + "SIGHASH_SIGNLE", + "sighash_none", + "Sighash_none", + "SigHash_None", + "SigHash_NONE", + ]; + for s in sht_mistakes { + assert_eq!( + s.parse::().unwrap_err().to_string(), + format!("unrecognized SIGHASH string '{}'", s) + ); + } + } + + #[test] + fn huge_witness() { + let hex = Vec::from_hex(include_str!("../../tests/data/huge_witness.hex").trim()).unwrap(); + deserialize::(&hex).unwrap(); + } + + #[test] + #[cfg(feature = "bitcoinconsensus")] + fn transaction_verify() { + use std::collections::HashMap; + + use crate::consensus_validation::{TransactionExt as _, TxVerifyError}; + use crate::witness::Witness; + + // a random recent SegWit transaction from blockchain using both old and SegWit inputs + let mut spending: Transaction = deserialize(hex!("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700") + .as_slice()).unwrap(); + let spent1: Transaction = deserialize(hex!("020000000001040aacd2c49f5f3c0968cfa8caf9d5761436d95385252e3abb4de8f5dcf8a582f20000000017160014bcadb2baea98af0d9a902e53a7e9adff43b191e9feffffff96cd3c93cac3db114aafe753122bd7d1afa5aa4155ae04b3256344ecca69d72001000000171600141d9984579ceb5c67ebfbfb47124f056662fe7adbfeffffffc878dd74d3a44072eae6178bb94b9253177db1a5aaa6d068eb0e4db7631762e20000000017160014df2a48cdc53dae1aba7aa71cb1f9de089d75aac3feffffffe49f99275bc8363f5f593f4eec371c51f62c34ff11cc6d8d778787d340d6896c0100000017160014229b3b297a0587e03375ab4174ef56eeb0968735feffffff03360d0f00000000001976a9149f44b06f6ee92ddbc4686f71afe528c09727a5c788ac24281b00000000001976a9140277b4f68ff20307a2a9f9b4487a38b501eb955888ac227c0000000000001976a9148020cd422f55eef8747a9d418f5441030f7c9c7788ac0247304402204aa3bd9682f9a8e101505f6358aacd1749ecf53a62b8370b97d59243b3d6984f02200384ad449870b0e6e89c92505880411285ecd41cf11e7439b973f13bad97e53901210205b392ffcb83124b1c7ce6dd594688198ef600d34500a7f3552d67947bbe392802473044022033dfd8d190a4ae36b9f60999b217c775b96eb10dee3a1ff50fb6a75325719106022005872e4e36d194e49ced2ebcf8bb9d843d842e7b7e0eb042f4028396088d292f012103c9d7cbf369410b090480de2aa15c6c73d91b9ffa7d88b90724614b70be41e98e0247304402207d952de9e59e4684efed069797e3e2d993e9f98ec8a9ccd599de43005fe3f713022076d190cc93d9513fc061b1ba565afac574e02027c9efbfa1d7b71ab8dbb21e0501210313ad44bc030cc6cb111798c2bf3d2139418d751c1e79ec4e837ce360cc03b97a024730440220029e75edb5e9413eb98d684d62a077b17fa5b7cc19349c1e8cc6c4733b7b7452022048d4b9cae594f03741029ff841e35996ef233701c1ea9aa55c301362ea2e2f68012103590657108a72feb8dc1dec022cf6a230bb23dc7aaa52f4032384853b9f8388baf9d20700") + .as_slice()).unwrap(); + let spent2: Transaction = deserialize(hex!("0200000000010166c3d39490dc827a2594c7b17b7d37445e1f4b372179649cd2ce4475e3641bbb0100000017160014e69aa750e9bff1aca1e32e57328b641b611fc817fdffffff01e87c5d010000000017a914f3890da1b99e44cd3d52f7bcea6a1351658ea7be87024830450221009eb97597953dc288de30060ba02d4e91b2bde1af2ecf679c7f5ab5989549aa8002202a98f8c3bd1a5a31c0d72950dd6e2e3870c6c5819a6c3db740e91ebbbc5ef4800121023f3d3b8e74b807e32217dea2c75c8d0bd46b8665b3a2d9b3cb310959de52a09bc9d20700") + .as_slice()).unwrap(); + let spent3: Transaction = deserialize(hex!("01000000027a1120a30cef95422638e8dab9dedf720ec614b1b21e451a4957a5969afb869d000000006a47304402200ecc318a829a6cad4aa9db152adbf09b0cd2de36f47b53f5dade3bc7ef086ca702205722cda7404edd6012eedd79b2d6f24c0a0c657df1a442d0a2166614fb164a4701210372f4b97b34e9c408741cd1fc97bcc7ffdda6941213ccfde1cb4075c0f17aab06ffffffffc23b43e5a18e5a66087c0d5e64d58e8e21fcf83ce3f5e4f7ecb902b0e80a7fb6010000006b483045022100f10076a0ea4b4cf8816ed27a1065883efca230933bf2ff81d5db6258691ff75202206b001ef87624e76244377f57f0c84bc5127d0dd3f6e0ef28b276f176badb223a01210309a3a61776afd39de4ed29b622cd399d99ecd942909c36a8696cfd22fc5b5a1affffffff0200127a000000000017a914f895e1dd9b29cb228e9b06a15204e3b57feaf7cc8769311d09000000001976a9144d00da12aaa51849d2583ae64525d4a06cd70fde88ac00000000") + .as_slice()).unwrap(); + + let mut spent = HashMap::new(); + spent.insert(spent1.compute_txid(), spent1); + spent.insert(spent2.compute_txid(), spent2); + spent.insert(spent3.compute_txid(), spent3); + let mut spent2 = spent.clone(); + let mut spent3 = spent.clone(); + + spending + .verify(|point: &OutPoint| { + if let Some(tx) = spent.remove(&point.txid) { + return tx.outputs.get(point.vout as usize).cloned(); + } + None + }) + .unwrap(); + + // test that we fail with repeated use of same input + let mut double_spending = spending.clone(); + let re_use = double_spending.inputs[0].clone(); + double_spending.inputs.push(re_use); + + assert!(double_spending + .verify(|point: &OutPoint| { + if let Some(tx) = spent2.remove(&point.txid) { + return tx.outputs.get(point.vout as usize).cloned(); + } + None + }) + .is_err()); + + // test that we get a failure if we corrupt a signature + let mut witness = spending.inputs[1].witness.to_vec(); + witness[0][10] = 42; + spending.inputs[1].witness = Witness::from_slice(&witness); + + let error = spending + .verify(|point: &OutPoint| { + if let Some(tx) = spent3.remove(&point.txid) { + return tx.outputs.get(point.vout as usize).cloned(); + } + None + }) + .err() + .unwrap(); + + match error { + TxVerifyError::ScriptVerification(_) => {} + _ => panic!("wrong error type"), + } + } + + #[test] + fn sequence_number() { + let seq_final = Sequence::from_consensus(0xFFFFFFFF); + let seq_non_rbf = Sequence::from_consensus(0xFFFFFFFE); + let block_time_lock = Sequence::from_consensus(0xFFFF); + let unit_time_lock = Sequence::from_consensus(0x40FFFF); + let lock_time_disabled = Sequence::from_consensus(0x80000000); + + assert!(seq_final.is_final()); + assert!(!seq_final.is_rbf()); + assert!(!seq_final.is_relative_lock_time()); + assert!(!seq_non_rbf.is_rbf()); + assert!(block_time_lock.is_relative_lock_time()); + assert!(block_time_lock.is_height_locked()); + assert!(block_time_lock.is_rbf()); + assert!(unit_time_lock.is_relative_lock_time()); + assert!(unit_time_lock.is_time_locked()); + assert!(unit_time_lock.is_rbf()); + assert!(!lock_time_disabled.is_relative_lock_time()); + } + + #[test] + fn sequence_from_hex_lower() { + let sequence = Sequence::from_hex("0xffffffff").unwrap(); + assert_eq!(sequence, Sequence::MAX); + } + + #[test] + fn sequence_from_hex_upper() { + let sequence = Sequence::from_hex("0XFFFFFFFF").unwrap(); + assert_eq!(sequence, Sequence::MAX); + } + + #[test] + fn sequence_from_unprefixed_hex_lower() { + let sequence = Sequence::from_unprefixed_hex("ffffffff").unwrap(); + assert_eq!(sequence, Sequence::MAX); + } + + #[test] + fn sequence_from_unprefixed_hex_upper() { + let sequence = Sequence::from_unprefixed_hex("FFFFFFFF").unwrap(); + assert_eq!(sequence, Sequence::MAX); + } + + #[test] + fn sequence_from_str_hex_invalid_hex_should_err() { + let hex = "0xzb93"; + let result = Sequence::from_hex(hex); + assert!(result.is_err()); + } + + #[test] + fn effective_value_happy_path() { + let value = "1 cBTC".parse::().unwrap(); + let fee_rate = FeeRate::from_sat_per_kwu(10); + let effective_value = effective_value(fee_rate, InputWeightPrediction::P2WPKH_MAX, value); + + // 10 sat/kwu * 272 wu = 3 sats (rounding up) + let expected_fee = "3 sats".parse::().unwrap(); + let expected_effective_value = (value.to_signed() - expected_fee).unwrap(); + assert_eq!(effective_value, expected_effective_value); + } + + #[test] + fn effective_value_fee_rate_does_not_overflow() { + let eff_value = + effective_value(FeeRate::MAX, InputWeightPrediction::P2WPKH_MAX, Amount::ZERO); + let want = SignedAmount::from_sat(-1254378597012250).unwrap(); // U64::MAX / 4_000 because of FeeRate::MAX + assert_eq!(eff_value, want) + } + + #[test] + fn txin_txout_weight() { + // [(is_segwit, tx_hex, expected_weight)] + let txs = [ + // one SegWit input (P2WPKH) + (true, "020000000001018a763b78d3e17acea0625bf9e52b0dc1beb2241b2502185348ba8ff4a253176e0100000000ffffffff0280d725000000000017a914c07ed639bd46bf7087f2ae1dfde63b815a5f8b488767fda20300000000160014869ec8520fa2801c8a01bfdd2e82b19833cd0daf02473044022016243edad96b18c78b545325aaff80131689f681079fb107a67018cb7fb7830e02205520dae761d89728f73f1a7182157f6b5aecf653525855adb7ccb998c8e6143b012103b9489bde92afbcfa85129a82ffa512897105d1a27ad9806bded27e0532fc84e700000000", Weight::from_wu(565)), + // one SegWit input (P2WSH) + (true, "01000000000101a3ccad197118a2d4975fadc47b90eacfdeaf8268adfdf10ed3b4c3b7e1ad14530300000000ffffffff0200cc5501000000001976a91428ec6f21f4727bff84bb844e9697366feeb69f4d88aca2a5100d00000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220548f11130353b3a8f943d2f14260345fc7c20bde91704c9f1cbb5456355078cd0220383ed4ed39b079b618bcb279bbc1f2ca18cb028c4641cb522c9c5868c52a0dc20147304402203c332ecccb3181ca82c0600520ee51fee80d3b4a6ab110945e59475ec71e44ac0220679a11f3ca9993b04ccebda3c834876f353b065bb08f50076b25f5bb93c72ae1016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000", Weight::from_wu(766)), + // one SegWit input (P2WPKH) and two legacy inputs (P2PKH) + (true, "010000000001036b6b6ac7e34e97c53c1cc74c99c7948af2e6aac75d8778004ae458d813456764000000006a473044022001deec7d9075109306320b3754188f81a8236d0d232b44bc69f8309115638b8f02204e17a5194a519cf994d0afeea1268740bdc10616b031a521113681cc415e815c012103488d3272a9fad78ee887f0684cb8ebcfc06d0945e1401d002e590c7338b163feffffffffc75bd7aa6424aee972789ec28ba181254ee6d8311b058d165bd045154d7660b0000000006b483045022100c8641bcbee3e4c47a00417875015d8c5d5ea918fb7e96f18c6ffe51bc555b401022074e2c46f5b1109cd79e39a9aa203eadd1d75356415e51d80928a5fb5feb0efee0121033504b4c6dfc3a5daaf7c425aead4c2dbbe4e7387ce8e6be2648805939ecf7054ffffffff494df3b205cd9430a26f8e8c0dc0bb80496fbc555a524d6ea307724bc7e60eee0100000000ffffffff026d861500000000001976a9145c54ed1360072ebaf56e87693b88482d2c6a101588ace407000000000000160014761e31e2629c6e11936f2f9888179d60a5d4c1f900000247304402201fa38a67a63e58b67b6cfffd02f59121ca1c8a1b22e1efe2573ae7e4b4f06c2b022002b9b431b58f6e36b3334fb14eaecee7d2f06967a77ef50d8d5f90dda1057f0c01210257dc6ce3b1100903306f518ee8fa113d778e403f118c080b50ce079fba40e09a00000000", Weight::from_wu(1755)), + // three legacy inputs (P2PKH) + (false, "0100000003e4d7be4314204a239d8e00691128dca7927e19a7339c7948bde56f669d27d797010000006b483045022100b988a858e2982e2daaf0755b37ad46775d6132057934877a5badc91dee2f66ff022020b967c1a2f0916007662ec609987e951baafa6d4fda23faaad70715611d6a2501210254a2dccd8c8832d4677dc6f0e562eaaa5d11feb9f1de2c50a33832e7c6190796ffffffff9e22eb1b3f24c260187d716a8a6c2a7efb5af14a30a4792a6eeac3643172379c000000006a47304402207df07f0cd30dca2cf7bed7686fa78d8a37fe9c2254dfdca2befed54e06b779790220684417b8ff9f0f6b480546a9e90ecee86a625b3ea1e4ca29b080da6bd6c5f67e01210254a2dccd8c8832d4677dc6f0e562eaaa5d11feb9f1de2c50a33832e7c6190796ffffffff1123df3bfb503b59769731da103d4371bc029f57979ebce68067768b958091a1000000006a47304402207a016023c2b0c4db9a7d4f9232fcec2193c2f119a69125ad5bcedcba56dd525e02206a734b3a321286c896759ac98ebfd9d808df47f1ce1fbfbe949891cc3134294701210254a2dccd8c8832d4677dc6f0e562eaaa5d11feb9f1de2c50a33832e7c6190796ffffffff0200c2eb0b000000001976a914e5eb3e05efad136b1405f5c2f9adb14e15a35bb488ac88cfff1b000000001976a9144846db516db3130b7a3c92253599edec6bc9630b88ac00000000", Weight::from_wu(2080)), + // one SegWit input (P2TR) + (true, "01000000000101b5cee87f1a60915c38bb0bc26aaf2b67be2b890bbc54bb4be1e40272e0d2fe0b0000000000ffffffff025529000000000000225120106daad8a5cb2e6fc74783714273bad554a148ca2d054e7a19250e9935366f3033760000000000002200205e6d83c44f57484fd2ef2a62b6d36cdcd6b3e06b661e33fd65588a28ad0dbe060141df9d1bfce71f90d68bf9e9461910b3716466bfe035c7dbabaa7791383af6c7ef405a3a1f481488a91d33cd90b098d13cb904323a3e215523aceaa04e1bb35cdb0100000000", Weight::from_wu(617)), + // one legacy input (P2PKH) + (false, "0100000001c336895d9fa674f8b1e294fd006b1ac8266939161600e04788c515089991b50a030000006a47304402204213769e823984b31dcb7104f2c99279e74249eacd4246dabcf2575f85b365aa02200c3ee89c84344ae326b637101a92448664a8d39a009c8ad5d147c752cbe112970121028b1b44b4903c9103c07d5a23e3c7cf7aeb0ba45ddbd2cfdce469ab197381f195fdffffff040000000000000000536a4c5058325bb7b7251cf9e36cac35d691bd37431eeea426d42cbdecca4db20794f9a4030e6cb5211fabf887642bcad98c9994430facb712da8ae5e12c9ae5ff314127d33665000bb26c0067000bb0bf00322a50c300000000000017a9145ca04fdc0a6d2f4e3f67cfeb97e438bb6287725f8750c30000000000001976a91423086a767de0143523e818d4273ddfe6d9e4bbcc88acc8465003000000001976a914c95cbacc416f757c65c942f9b6b8a20038b9b12988ac00000000", Weight::from_wu(1396)), + ]; + + let empty_transaction_weight = Transaction { + version: Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![], + outputs: vec![], + } + .weight(); + + for (is_segwit, tx, expected_weight) in &txs { + let txin_weight = if *is_segwit { TxIn::segwit_weight } else { TxIn::legacy_weight }; + let tx: Transaction = deserialize(Vec::from_hex(tx).unwrap().as_slice()).unwrap(); + assert_eq!(*is_segwit, tx.uses_segwit_serialization()); + + let mut calculated_weight = empty_transaction_weight + + tx.inputs.iter().fold(Weight::ZERO, |sum, i| sum + txin_weight(i)) + + tx.outputs.iter().fold(Weight::ZERO, |sum, o| sum + o.weight()); + + // The empty tx uses SegWit serialization but a legacy tx does not. + if !tx.uses_segwit_serialization() { + calculated_weight -= Weight::from_wu(2); + } + + assert_eq!(calculated_weight, *expected_weight); + assert_eq!(tx.weight(), *expected_weight); + } + } + + #[test] + fn tx_sigop_count() { + let tx_hexes = [ + // 0 sigops (p2pkh in + p2wpkh out) + ( + "0200000001725aab4d23f76ad10bb569a68f8702ebfb8b076e015179ff9b9425234953\ + ac63000000006a47304402204cae7dc9bb68b588dd6b8afb8b881b752fd65178c25693e\ + a6d5d9a08388fd2a2022011c753d522d5c327741a6d922342c86e05c928309d7e566f68\ + 8148432e887028012103f14b11cfb58b113716e0fa277ab4a32e4d3ed64c6b09b1747ef\ + 7c828d5b06a94fdffffff01e5d4830100000000160014e98527b55cae861e5b9c3a6794\ + 86514c012d6fce00000000", + 0, // Expected (Some) + return_none as fn(&OutPoint) -> Option, // spent fn + 0, // Expected (None) + ), + // 5 sigops (p2wpkh in + p2pkh out (x4)) + ( + "020000000001018c47330b1c4d30e7e2244e8ccb56d411b71e10073bb42fa1813f3f01\ + e144cc4d0100000000fdffffff01f7e30300000000001976a9143b49fd16f7562cfeedc\ + 6a4ba84805f8c2f8e1a2c88ac024830450221009a4dbf077a63f6e4c3628a5fef2a09ec\ + 6f7ca4a4d95bc8bb69195b6b671e9272022074da9ffff5a677fc7b37d66bb4ff1f316c9\ + dbacb92058291d84cd4b83f7c63c9012103d013e9e53c9ca8dd2ddffab1e9df27811503\ + feea7eb0700ff058851bbb37d99000000000", + 5, + return_p2wpkh, + 4, + ), + // 8 sigops (P2WSH 3-of-4 MS (4) in + P2WSH out + P2PKH out (1x4)) + ( + "01000000000101e70d7b4d957122909a665070b0c5bbb693982d09e4e66b9e6b7a8390\ + ce65ef1f0100000000ffffffff02095f2b0000000000220020800a016ea57a08f30c273\ + ae7624f8f91c505ccbd3043829349533f317168248c52594500000000001976a914607f\ + 643372477c044c6d40b814288e40832a602688ac05004730440220282943649e687b5a3\ + bda9403c16f363c2ee2be0ec43fb8df40a08b96a4367d47022014e8f36938eef41a09ee\ + d77a815b0fa120a35f25e3a185310f050959420cee360147304402201e555f894036dd5\ + 78045701e03bf10e093d7e93cd9997e44c1fc65a7b669852302206893f7261e52c9d779\ + 5ba39d99aad30663da43ed675c389542805469fa8eb26a014730440220510fc99bc37d6\ + dbfa7e8724f4802cebdb17b012aaf70ce625e22e6158b139f40022022e9b811751d491f\ + bdec7691b697e88ba84315f6739b9e3bd4425ac40563aed2018b5321029ddecf0cc2013\ + 514961550e981a0b8b60e7952f70561a5bb552aa7f075e71e3c2103316195a59c35a3b2\ + 7b6dfcc3192cc10a7a6bbccd5658dfbe98ca62a13d6a02c121034629d906165742def4e\ + f53c6dade5dcbf88b775774cad151e35ae8285e613b0221035826a29938de2076950811\ + 13c58bcf61fe6adacc3aacceb21c4827765781572d54ae00000000", + 8, + return_p2wsh, + 4, + ), + // 5 sigops (P2SH-P2WPKH in (1), 2 P2SH outs (0), 1 P2PKH out (1x4)) + ( + "010000000001018aec7e0729ba5a2d284303c89b3f397e92d54472a225d28eb0ae2fa6\ + 5a7d1a2e02000000171600145ad5db65f313ab76726eb178c2fd8f21f977838dfdfffff\ + f03102700000000000017a914dca89e03ba124c2c70e55533f91100f2d9dab04587f2d7\ + 1d00000000001976a91442a34f4b0a65bc81278b665d37fd15910d261ec588ac292c3b0\ + 00000000017a91461978dcebd0db2da0235c1ba3e8087f9fd74c57f8702473044022000\ + 9226f8def30a8ffa53e55ca5d71a72a64cd20ae7f3112562e3413bd0731d2c0220360d2\ + 20435e67eef7f2bf0258d1dded706e3824f06d961ba9eeaed300b16c2cc012103180cff\ + 753d3e4ee1aa72b2b0fd72ce75956d04f4c19400a3daed0b18c3ab831e00000000", + 5, + return_p2sh, + 4, + ), + // 12 sigops (1 P2SH 2-of-3 MS in (3x4), P2SH outs (0)) + ( + "010000000115fe9ec3dc964e41f5267ea26cfe505f202bf3b292627496b04bece84da9\ + b18903000000fc004730440220442827f1085364bda58c5884cee7b289934083362db6d\ + fb627dc46f6cdbf5793022078cfa524252c381f2a572f0c41486e2838ca94aa268f2384\ + d0e515744bf0e1e9014730440220160e49536bb29a49c7626744ee83150174c22fa40d5\ + 8fb4cd554a907a6a7b825022045f6cf148504b334064686795f0968c689e542f475b8ef\ + 5a5fa42383948226a3014c69522103e54bc61efbcb8eeff3a5ab2a92a75272f5f6820e3\ + 8e3d28edb54beb06b86c0862103a553e30733d7a8df6d390d59cc136e2c9d9cf4e808f3\ + b6ab009beae68dd60822210291c5a54bb8b00b6f72b90af0ac0ecaf78fab026d8eded28\ + 2ad95d4d65db268c953aeffffffff024c4f0d000000000017a9146ebf0484bd5053f727\ + c755a750aa4c815dfa112887a06b12020000000017a91410065dd50b3a7f299fef3b1c5\ + 3b8216399916ab08700000000", + 12, + return_p2sh, + 0, + ), + // 3 sigops (1 P2SH-P2WSH 2-of-3 MS in (3), P2SH + P2WSH outs (0)) + ( + "0100000000010117a31277a8ba3957be351fe4cffd080e05e07f9ee1594d638f55dd7d\ + 707a983c01000000232200203a33fc9628c29f36a492d9fd811fd20231fbd563f7863e7\ + 9c4dc0ed34ea84b15ffffffff033bed03000000000017a914fb00d9a49663fd8ae84339\ + 8ae81299a1941fb8d287429404000000000017a9148fe08d81882a339cf913281eca8af\ + 39110507c798751ab1300000000002200208819e4bac0109b659de6b9168b83238a050b\ + ef16278e470083b39d28d2aa5a6904004830450221009faf81f72ec9b14a39f0f0e12f0\ + 1a7175a4fe3239cd9a015ff2085985a9b0e3f022059e1aaf96c9282298bdc9968a46d8a\ + d28e7299799835cf982b02c35e217caeae0147304402202b1875355ee751e0c8b21990b\ + 7ea73bd84dfd3bd17477b40fc96552acba306ad02204913bc43acf02821a3403132aa0c\ + 33ac1c018d64a119f6cb55dfb8f408d997ef01695221023c15bf3436c0b4089e0ed0428\ + 5101983199d0967bd6682d278821c1e2ac3583621034d924ccabac6d190ce8343829834\ + cac737aa65a9abe521bcccdcc3882d97481f21035d01d092bb0ebcb793ba3ffa0aeb143\ + 2868f5277d5d3d2a7d2bc1359ec13abbd53aee1560c00", + 3, + return_p2sh, + 0, + ), + // 80 sigops (1 P2PKH ins (0), 1 BARE MS outs (20x4)) + ( + "0100000001628c1726fecd23331ae9ff2872341b82d2c03180aa64f9bceefe457448db\ + e579020000006a47304402204799581a5b34ae5adca21ef22c55dbfcee58527127c95d0\ + 1413820fe7556ed970220391565b24dc47ce57fe56bf029792f821a392cdb5a3d45ed85\ + c158997e7421390121037b2fb5b602e51c493acf4bf2d2423bcf63a09b3b99dfb7bd3c8\ + d74733b5d66f5ffffffff011c0300000000000069512103a29472a1848105b2225f0eca\ + 5c35ada0b0abbc3c538818a53eca177f4f4dcd9621020c8fd41b65ae6b980c072c5a9f3\ + aec9f82162c92eb4c51d914348f4390ac39122102222222222222222222222222222222\ + 222222222222222222222222222222222253ae00000000", + 80, + return_none, + 80, + ), + ]; + + // All we need is to trigger 3 cases for prevout + fn return_p2sh(_outpoint: &OutPoint) -> Option { + Some( + deserialize(&hex!( + "cc721b000000000017a91428203c10cc8f18a77412caaa83dabaf62b8fbb0f87" + )) + .unwrap(), + ) + } + fn return_p2wpkh(_outpoint: &OutPoint) -> Option { + Some( + deserialize(&hex!( + "e695779d000000001600141c6977423aa4b82a0d7f8496cdf3fc2f8b4f580c" + )) + .unwrap(), + ) + } + fn return_p2wsh(_outpoint: &OutPoint) -> Option { + Some( + deserialize(&hex!( + "66b51e0900000000220020dbd6c9d5141617eff823176aa226eb69153c1e31334ac37469251a2539fc5c2b" + )) + .unwrap(), + ) + } + fn return_none(_outpoint: &OutPoint) -> Option { None } + + for (hx, expected, spent_fn, expected_none) in tx_hexes.iter() { + let tx_bytes = Vec::from_hex(hx).unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); + assert_eq!(tx.total_sigop_cost(spent_fn), *expected); + assert_eq!(tx.total_sigop_cost(return_none), *expected_none); + } + } + + #[test] + fn weight_predictions() { + // TXID 3d3381f968e3a73841cba5e73bf47dcea9f25a9f7663c51c81f1db8229a309a0 + let tx_raw = hex!( + "01000000000103fc9aa70afba04da865f9821734b556cca9fb5710\ + fc1338b97fba811033f755e308000000000000000019b37457784d\ + d04936f011f733b8016c247a9ef08d40007a54a5159d1fc62ee216\ + 00000000000000004c4f2937c6ccf8256d9711a19df1ae62172297\ + 0bf46be925ff15f490efa1633d01000000000000000002c0e1e400\ + 0000000017a9146983f776902c1d1d0355ae0962cb7bc69e9afbde\ + 8706a1e600000000001600144257782711458506b89f255202d645\ + e25c41144702483045022100dcada0499865a49d0aab8cb113c5f8\ + 3fd5a97abc793f97f3f53aa4b9d1192ed702202094c7934666a30d\ + 6adb1cc9e3b6bc14d2ffebd3200f3908c40053ef2df640b5012103\ + 15434bb59b615a383ae87316e784fc11835bb97fab33fdd2578025\ + e9968d516e0247304402201d90b3197650569eba4bc0e0b1e2dca7\ + 7dfac7b80d4366f335b67e92e0546e4402203b4be1d443ad7e3a5e\ + a92aafbcdc027bf9ccf5fe68c0bc8f3ebb6ab806c5464c012103e0\ + 0d92b0fe60731a54fdbcc6920934159db8ffd69d55564579b69a22\ + ec5bb7530247304402205ab83b734df818e64d8b9e86a8a75f9d00\ + 5c0c6e1b988d045604853ab9ccbde002205a580235841df609d6bd\ + 67534bdcd301999b18e74e197e9e476cdef5fdcbf822012102ebb3\ + e8a4638ede4721fb98e44e3a3cd61fecfe744461b85e0b6a6a1017\ + 5d5aca00000000" + ); + + let tx = Transaction::consensus_decode::<&[u8]>(&mut tx_raw.as_ref()).unwrap(); + let input_weights = vec![ + InputWeightPrediction::P2WPKH_MAX, + InputWeightPrediction::ground_p2wpkh(1), + InputWeightPrediction::ground_p2wpkh(1), + ]; + // Outputs: [P2SH, P2WPKH] + + // Confirm the transaction's predicted weight matches its actual weight. + let predicted = predict_weight(input_weights, tx.script_pubkey_lens()); + let expected = tx.weight(); + assert_eq!(predicted, expected); + + // Confirm signature grinding input weight predictions are aligned with constants. + assert_eq!( + InputWeightPrediction::ground_p2wpkh(0).witness_weight(), + InputWeightPrediction::P2WPKH_MAX.witness_weight() + ); + assert_eq!( + InputWeightPrediction::ground_nested_p2wpkh(0).witness_weight(), + InputWeightPrediction::NESTED_P2WPKH_MAX.witness_weight() + ); + assert_eq!( + InputWeightPrediction::ground_p2pkh_compressed(0).witness_weight(), + InputWeightPrediction::P2PKH_COMPRESSED_MAX.witness_weight() + ); + } + + #[test] + fn weight_prediction_const_from_slices() { + let predict = [ + InputWeightPrediction::P2WPKH_MAX, + InputWeightPrediction::NESTED_P2WPKH_MAX, + InputWeightPrediction::P2PKH_COMPRESSED_MAX, + InputWeightPrediction::P2PKH_UNCOMPRESSED_MAX, + InputWeightPrediction::P2TR_KEY_DEFAULT_SIGHASH, + InputWeightPrediction::P2TR_KEY_NON_DEFAULT_SIGHASH, + ]; + + let weight = predict_weight_from_slices(&predict, &[1]); + assert_eq!(weight, Weight::from_wu(2493)); + } + + #[test] + // needless_borrows_for_generic_args incorrectly identifies &[] as a needless borrow + #[allow(clippy::needless_borrows_for_generic_args)] + fn weight_prediction_new() { + let p2wpkh_max = InputWeightPrediction::new(0, [72, 33]); + assert_eq!(p2wpkh_max.script_size, 1); + assert_eq!(p2wpkh_max.witness_size, 108); + assert_eq!(p2wpkh_max.total_weight(), Weight::from_wu(272)); + assert_eq!(p2wpkh_max.total_weight(), InputWeightPrediction::P2WPKH_MAX.total_weight()); + + let nested_p2wpkh_max = InputWeightPrediction::new(23, [72, 33]); + assert_eq!(nested_p2wpkh_max.script_size, 24); + assert_eq!(nested_p2wpkh_max.witness_size, 108); + assert_eq!(nested_p2wpkh_max.total_weight(), Weight::from_wu(364)); + assert_eq!( + nested_p2wpkh_max.total_weight(), + InputWeightPrediction::NESTED_P2WPKH_MAX.total_weight() + ); + + let p2pkh_compressed_max = InputWeightPrediction::new(107, &[]); + assert_eq!(p2pkh_compressed_max.script_size, 108); + assert_eq!(p2pkh_compressed_max.witness_size, 0); + assert_eq!(p2pkh_compressed_max.total_weight(), Weight::from_wu(592)); + assert_eq!( + p2pkh_compressed_max.total_weight(), + InputWeightPrediction::P2PKH_COMPRESSED_MAX.total_weight() + ); + + let p2pkh_uncompressed_max = InputWeightPrediction::new(139, &[]); + assert_eq!(p2pkh_uncompressed_max.script_size, 140); + assert_eq!(p2pkh_uncompressed_max.witness_size, 0); + assert_eq!(p2pkh_uncompressed_max.total_weight(), Weight::from_wu(720)); + assert_eq!( + p2pkh_uncompressed_max.total_weight(), + InputWeightPrediction::P2PKH_UNCOMPRESSED_MAX.total_weight() + ); + + let p2tr_key_default_sighash = InputWeightPrediction::new(0, [64]); + assert_eq!(p2tr_key_default_sighash.script_size, 1); + assert_eq!(p2tr_key_default_sighash.witness_size, 66); + assert_eq!(p2tr_key_default_sighash.total_weight(), Weight::from_wu(230)); + assert_eq!( + p2tr_key_default_sighash.total_weight(), + InputWeightPrediction::P2TR_KEY_DEFAULT_SIGHASH.total_weight() + ); + + let p2tr_key_non_default_sighash = InputWeightPrediction::new(0, [65]); + assert_eq!(p2tr_key_non_default_sighash.script_size, 1); + assert_eq!(p2tr_key_non_default_sighash.witness_size, 67); + assert_eq!(p2tr_key_non_default_sighash.total_weight(), Weight::from_wu(231)); + assert_eq!( + p2tr_key_non_default_sighash.total_weight(), + InputWeightPrediction::P2TR_KEY_NON_DEFAULT_SIGHASH.total_weight() + ); + } + + #[test] + + fn outpoint_format() { + let outpoint = OutPoint::COINBASE_PREVOUT; + + let debug = "OutPoint { txid: 0000000000000000000000000000000000000000000000000000000000000000, vout: 4294967295 }"; + assert_eq!(debug, format!("{:?}", &outpoint)); + + let display = "0000000000000000000000000000000000000000000000000000000000000000:4294967295"; + assert_eq!(display, format!("{}", &outpoint)); + + let pretty_debug = "OutPoint {\n txid: 0x0000000000000000000000000000000000000000000000000000000000000000,\n vout: 4294967295,\n}"; + assert_eq!(pretty_debug, format!("{:#?}", &outpoint)); + + let debug_txid = "0000000000000000000000000000000000000000000000000000000000000000"; + assert_eq!(debug_txid, format!("{:?}", &outpoint.txid)); + + let display_txid = "0000000000000000000000000000000000000000000000000000000000000000"; + assert_eq!(display_txid, format!("{}", &outpoint.txid)); + + let pretty_txid = "0x0000000000000000000000000000000000000000000000000000000000000000"; + assert_eq!(pretty_txid, format!("{:#}", &outpoint.txid)); + } + + #[test] + fn coinbase_assume_methods() { + use crate::constants; + use crate::network::Network; + + let genesis = constants::genesis_block(Network::Bitcoin); + let coinbase_tx = &genesis.transactions()[0]; + + // Test that we can create a Coinbase reference using assume_coinbase_ref + let coinbase_ref = Coinbase::assume_coinbase_ref(coinbase_tx); + assert_eq!(coinbase_ref.compute_txid(), coinbase_tx.compute_txid()); + assert_eq!(coinbase_ref.wtxid(), Wtxid::COINBASE); + + // Test that we can create a Coinbase using assume_coinbase + let coinbase_owned = Coinbase::assume_coinbase(coinbase_tx.clone()); + assert_eq!(coinbase_owned.compute_txid(), coinbase_tx.compute_txid()); + assert_eq!(coinbase_owned.wtxid(), Wtxid::COINBASE); + } +} diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs new file mode 100644 index 000000000..061db6960 --- /dev/null +++ b/bitcoin/src/blockdata/witness.rs @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! A witness. +//! +//! This module contains the [`Witness`] struct and related methods to operate on it + +use io::{BufRead, Write}; + +use crate::consensus::encode::{self, Error, ParseError, WriteExt}; +use crate::consensus::{Decodable, Encodable}; +use crate::crypto::ecdsa; +use crate::crypto::key::SerializedXOnlyPublicKey; +use crate::taproot::{self, ControlBlock, LeafScript, TaprootMerkleBranch, TAPROOT_ANNEX_PREFIX}; +use crate::{internal_macros, TapScript, WitnessScript}; + +type BorrowedControlBlock<'a> = ControlBlock<&'a TaprootMerkleBranch, &'a SerializedXOnlyPublicKey>; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use primitives::witness::{Iter, Witness}; +#[doc(no_inline)] +pub use primitives::witness::UnexpectedEofError; + +impl Decodable for Witness { + fn consensus_decode(r: &mut R) -> Result { + io::decode_from_read(r).map_err(|e| Error::Parse(ParseError::Witness(e))) + } +} + +impl Encodable for Witness { + // `self.content` includes the varints so encoding here includes them, as expected. + fn consensus_encode(&self, w: &mut W) -> Result { + let mut written = w.emit_compact_size(self.len())?; + + for element in self.iter() { + written += encode::consensus_encode_with_size(element, w)? + } + + Ok(written) + } +} + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`Witness`] type. + pub trait WitnessExt impl for Witness { + /// Constructs a new witness required to spend a P2WPKH output. + /// + /// The witness will be made up of the DER encoded signature + sighash_type followed by the + /// serialized public key. Also useful for spending a P2SH-P2WPKH output. + /// + /// It is expected that `pubkey` is related to the secret key used to create `signature`. + fn p2wpkh(signature: ecdsa::Signature, pubkey: secp256k1::PublicKey) -> Self { + let mut witness = Witness::new(); + witness.push(signature.serialize()); + witness.push(pubkey.serialize()); + witness + } + + /// Constructs a new witness required to do a key path spend of a P2TR output. + fn p2tr_key_spend(signature: &taproot::Signature) -> Self { + let mut witness = Witness::new(); + witness.push(signature.serialize()); + witness + } + + /// Finishes constructing the P2TR script spend witness by pushing the required items. + fn push_p2tr_script_spend(&mut self, script: &TapScript, control_block: &ControlBlock>, annex: Option<&[u8]>) { + self.push(script.as_bytes()); + self.push(&*control_block.encode_to_arrayvec()); + if let Some(annex) = annex { + self.push(annex); + } + } + + /// Pushes, as a new element on the witness, an ECDSA signature. + /// + /// Pushes the DER encoded signature + sighash_type, requires an allocation. + fn push_ecdsa_signature(&mut self, signature: ecdsa::Signature) { + self.push(signature.serialize()) + } + + /// Returns the leaf script if this witness is a Taproot script spend. + /// + /// **Deprecated** since this does not return the leaf version. Code that + /// assumes a leaf version may be subtly broken once a new Tapscript version + /// is deployed. + #[deprecated(since = "TBD", note = "use taproot_leaf_script instead")] + fn tapscript(&self) -> Option<&TapScript> { + match P2TrSpend::from_witness(self) { + Some(P2TrSpend::Script { leaf_script, .. }) => Some(leaf_script), + _ => None, + } + } + + /// Returns the leaf script and version if this witness is a Taproot script spend. + /// + /// This method does not include the control block or annex; to obtain those, call + /// [`Self::taproot_control_block`] and [`Self::taproot_annex`]. + /// + /// Although this method does not have access to the output being spent, if the + /// transaction is valid and this method returns `Some`, you can be assured that + /// it is a real Taproot script spend (and not some other kind of output contrived + /// to have a Taproot-shaped witness). + /// See [BIP-0341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki), + /// in particular footnote 7, for more information. + fn taproot_leaf_script(&self) -> Option> { + match P2TrSpend::from_witness(self) { + Some(P2TrSpend::Script { leaf_script, control_block, .. }) => { + Some(LeafScript { version: control_block.leaf_version, script: leaf_script, }) + }, + _ => None, + } + } + + /// If this witness is a Taproot script spend, return the control block. + /// + /// Although this method does not have access to the output being spent, if the + /// transaction is valid and this method returns `Some`, you can be assured that + /// it is a real Taproot script spend (and not some other kind of output contrived + /// to have a Taproot-shaped witness). + /// See [BIP-0341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki), + /// in particular footnote 7, for more information. + fn taproot_control_block(&self) -> Option> { + match P2TrSpend::from_witness(self) { + Some(P2TrSpend::Script { control_block, .. }) => Some(control_block), + _ => None, + } + } + + /// If this witness is a Taproot script spend with an annex, return that. + fn taproot_annex(&self) -> Option<&[u8]> { + P2TrSpend::from_witness(self)?.annex() + } + + /// Get the Segwit version 0 witness script. + /// + /// Unlike the Taproot case, we do no validation to determine whether this is a + /// witness script: it may be a Taproot control block, annex, or some other kind + /// of object. If you are not certain whether the output being spent is Segwit v0, + /// use [`crate::script::ScriptExt::is_p2wsh`] on the output's script. + fn witness_script(&self) -> Option<&WitnessScript> { self.last().map(WitnessScript::from_bytes) } + } +} + +/// Represents a possible Taproot spend. +/// +/// Taproot can be spent as key spend or script spend and, depending on which it is, different data +/// is in the witness. This type helps representing that data more cleanly when parsing the witness +/// because there are a lot of conditions that make reasoning hard. It's better to parse it at one +/// place and pass it along. +/// +/// This type is so far private but it could be published eventually. The design is geared towards +/// it but it's not fully finished. +enum P2TrSpend<'a> { + Key { + // This field is technically present in witness in case of key spend but none of our code + // uses it yet. Rather than deleting it, it's kept here commented as documentation and as + // an easy way to add it if anything needs it - by just uncommenting. + // signature: &'a [u8], + annex: Option<&'a [u8]>, + }, + Script { + leaf_script: &'a TapScript, + control_block: BorrowedControlBlock<'a>, + annex: Option<&'a [u8]>, + }, +} + +impl<'a> P2TrSpend<'a> { + /// Parses `Witness` to determine what kind of Taproot spend this is. + /// + /// Note: this assumes `witness` is a Taproot spend. The function cannot figure it out for sure + /// (without knowing the output), so it doesn't attempt to check anything other than what is + /// required for the program to not crash. + /// + /// In other words, if the caller is certain that the witness is a valid p2tr spend (e.g. + /// obtained from Bitcoin Core) then it's OK to unwrap this but not vice versa - `Some` does + /// not imply correctness. + fn from_witness(witness: &'a Witness) -> Option { + // BIP-0341 says: + // If there are at least two witness elements, and the first byte of + // the last element is 0x50, this last element is called annex a + // and is removed from the witness stack. + // + // However here we're not removing anything, so we have to adjust the numbers to account + // for the fact that annex is still there. + match witness.len() { + 0 => None, + 1 => Some(P2TrSpend::Key { + /* signature: witness.last().expect("len > 0") ,*/ annex: None, + }), + 2 if witness.last().expect("len > 0").starts_with(&[TAPROOT_ANNEX_PREFIX]) => { + let spend = P2TrSpend::Key { + // signature: witness.get_back(1).expect("len > 1"), + annex: witness.last(), + }; + Some(spend) + } + // 2 => this is script spend without annex - same as when there are 3+ elements and the + // last one does NOT start with TAPROOT_ANNEX_PREFIX. This is handled in the catchall + // arm. + 3.. if witness.last().expect("len > 0").starts_with(&[TAPROOT_ANNEX_PREFIX]) => { + let control_block = witness.get_back(1).expect("len > 1"); + let control_block = BorrowedControlBlock::decode_borrowed(control_block).ok()?; + let spend = P2TrSpend::Script { + leaf_script: TapScript::from_bytes(witness.get_back(2).expect("len > 2")), + control_block, + annex: witness.last(), + }; + Some(spend) + } + _ => { + let control_block = witness.last().expect("len > 0"); + let control_block = BorrowedControlBlock::decode_borrowed(control_block).ok()?; + let spend = P2TrSpend::Script { + leaf_script: TapScript::from_bytes(witness.get_back(1).expect("len > 1")), + control_block, + annex: None, + }; + Some(spend) + } + } + } + + fn annex(&self) -> Option<&'a [u8]> { + match self { + P2TrSpend::Key { annex, .. } => *annex, + P2TrSpend::Script { annex, .. } => *annex, + } + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::Witness {} +} + +#[cfg(test)] +mod test { + use hex_lit::hex; + + use super::*; + use crate::consensus::{deserialize, encode, serialize}; + use crate::hex::DisplayHex; + use crate::sighash::EcdsaSighashType; + use crate::taproot::LeafVersion; + use crate::Transaction; + + #[test] + fn exact_sized_iterator() { + let mut witness = Witness::default(); + for i in 0..5 { + assert_eq!(witness.iter().len(), i); + witness.push([0u8]); + } + let mut iter = witness.iter(); + for i in (0..=5).rev() { + assert_eq!(iter.len(), i); + iter.next(); + } + } + + #[test] + fn push_ecdsa_sig() { + // The very first signature in block 734,958 + let sig_bytes = + hex!("304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b541"); + let signature = secp256k1::ecdsa::Signature::from_der(&sig_bytes).unwrap(); + let mut witness = Witness::default(); + let signature = crate::ecdsa::Signature { signature, sighash_type: EcdsaSighashType::All }; + witness.push_ecdsa_signature(signature); + let expected_witness = vec![hex!( + "304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b54101") + ]; + assert_eq!(witness.to_vec(), expected_witness); + } + + #[test] + fn consensus_serialize() { + let el_0 = + hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").to_vec(); + let el_1 = hex!("000000").to_vec(); + + let mut want_witness = Witness::default(); + want_witness.push(&el_0); + want_witness.push(&el_1); + + let vec = vec![el_0, el_1]; + + // Puts a CompactSize at the front as well as one at the front of each element. + let want_ser: Vec = encode::serialize(&vec); + + // `from_slice` expects bytes slices _without_ leading `CompactSize`. + let got_witness = Witness::from_slice(&vec); + assert_eq!(got_witness, want_witness); + + let got_ser = encode::serialize(&got_witness); + assert_eq!(got_ser, want_ser); + + let roundtrip: Witness = encode::deserialize(&got_ser).unwrap(); + assert_eq!(roundtrip, want_witness) + } + + #[test] + fn get_tapscript() { + let tapscript = hex!("deadbeef"); + let control_block = + hex!("c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + // annex starting with 0x50 causes the branching logic. + let annex = hex!("50"); + + let witness = Witness::from([tapscript.as_slice(), &control_block]); + let witness_annex = Witness::from([tapscript.as_slice(), &control_block, &annex]); + + // With or without annex, the tapscript should be returned. + assert_eq!(witness.tapscript(), Some(TapScript::from_bytes(&tapscript[..]))); + assert_eq!(witness_annex.tapscript(), Some(TapScript::from_bytes(&tapscript[..]))); + } + + #[test] + fn get_taproot_leaf_script() { + let tapscript = hex!("deadbeef"); + let control_block = + hex!("c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + // annex starting with 0x50 causes the branching logic. + let annex = hex!("50"); + + let witness = Witness::from([tapscript.as_slice(), &control_block]); + let witness_annex = Witness::from([tapscript.as_slice(), &control_block, &annex]); + + let expected_leaf_script = LeafScript { + version: LeafVersion::TapScript, + script: TapScript::from_bytes(&tapscript), + }; + + // With or without annex, the tapscript should be returned. + assert_eq!(witness.taproot_leaf_script().unwrap(), expected_leaf_script); + assert_eq!(witness_annex.taproot_leaf_script().unwrap(), expected_leaf_script); + } + + #[test] + fn get_tapscript_from_keypath() { + let signature = hex!("deadbeef"); + // annex starting with 0x50 causes the branching logic. + let annex = hex!("50"); + + let witness = Witness::from([signature]); + let witness_annex = Witness::from([signature.as_slice(), &annex]); + + // With or without annex, no tapscript should be returned. + assert_eq!(witness.tapscript(), None); + assert_eq!(witness_annex.tapscript(), None); + } + + #[test] + fn get_control_block() { + let tapscript = hex!("deadbeef"); + let control_block = + hex!("c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + let expected_control_block = BorrowedControlBlock::decode_borrowed(&control_block).unwrap(); + // annex starting with 0x50 causes the branching logic. + let annex = hex!("50"); + let signature = vec![0xff; 64]; + + let witness = Witness::from([tapscript.as_slice(), &control_block]); + let witness_annex = Witness::from([tapscript.as_slice(), &control_block, &annex]); + let witness_key_spend_annex = Witness::from([signature.as_slice(), &annex]); + + // With or without annex, the tapscript should be returned. + assert_eq!(witness.taproot_control_block().unwrap(), expected_control_block); + assert_eq!(witness_annex.taproot_control_block().unwrap(), expected_control_block); + assert!(witness_key_spend_annex.taproot_control_block().is_none()) + } + + #[test] + fn get_annex() { + let tapscript = hex!("deadbeef"); + let control_block = + hex!("c0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + // annex starting with 0x50 causes the branching logic. + let annex = hex!("50"); + + let witness = Witness::from([tapscript.as_slice(), &control_block]); + let witness_annex = Witness::from([tapscript.as_slice(), &control_block, &annex]); + + // With or without annex, the tapscript should be returned. + assert_eq!(witness.taproot_annex(), None); + assert_eq!(witness_annex.taproot_annex(), Some(&annex[..])); + + // Now for keyspend + let signature = hex!("deadbeef"); + // annex starting with 0x50 causes the branching logic. + let annex = hex!("50"); + + let witness = Witness::from([signature]); + let witness_annex = Witness::from([signature.as_slice(), &annex]); + + // With or without annex, the tapscript should be returned. + assert_eq!(witness.taproot_annex(), None); + assert_eq!(witness_annex.taproot_annex(), Some(&annex[..])); + } + + #[test] + fn tx() { + const S: &str = "02000000000102b44f26b275b8ad7b81146ba3dbecd081f9c1ea0dc05b97516f56045cfcd3df030100000000ffffffff1cb4749ae827c0b75f3d0a31e63efc8c71b47b5e3634a4c698cd53661cab09170100000000ffffffff020b3a0500000000001976a9143ea74de92762212c96f4dd66c4d72a4deb20b75788ac630500000000000016001493a8dfd1f0b6a600ab01df52b138cda0b82bb7080248304502210084622878c94f4c356ce49c8e33a063ec90f6ee9c0208540888cfab056cd1fca9022014e8dbfdfa46d318c6887afd92dcfa54510e057565e091d64d2ee3a66488f82c0121026e181ffb98ebfe5a64c983073398ea4bcd1548e7b971b4c175346a25a1c12e950247304402203ef00489a0d549114977df2820fab02df75bebb374f5eee9e615107121658cfa02204751f2d1784f8e841bff6d3bcf2396af2f1a5537c0e4397224873fbd3bfbe9cf012102ae6aa498ce2dd204e9180e71b4fb1260fe3d1a95c8025b34e56a9adf5f278af200000000"; + let tx_bytes = hex!(S); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); + + let expected_wit = ["304502210084622878c94f4c356ce49c8e33a063ec90f6ee9c0208540888cfab056cd1fca9022014e8dbfdfa46d318c6887afd92dcfa54510e057565e091d64d2ee3a66488f82c01", "026e181ffb98ebfe5a64c983073398ea4bcd1548e7b971b4c175346a25a1c12e95"]; + for (i, wit_el) in tx.inputs[0].witness.iter().enumerate() { + assert_eq!(expected_wit[i], wit_el.to_lower_hex_string()); + } + assert_eq!(expected_wit[1], tx.inputs[0].witness.last().unwrap().to_lower_hex_string()); + assert_eq!( + expected_wit[0], + tx.inputs[0].witness.get_back(1).unwrap().to_lower_hex_string() + ); + assert_eq!(expected_wit[0], tx.inputs[0].witness.get(0).unwrap().to_lower_hex_string()); + assert_eq!(expected_wit[1], tx.inputs[0].witness.get(1).unwrap().to_lower_hex_string()); + assert_eq!(None, tx.inputs[0].witness.get(2)); + assert_eq!(expected_wit[0], tx.inputs[0].witness[0].to_lower_hex_string()); + assert_eq!(expected_wit[1], tx.inputs[0].witness[1].to_lower_hex_string()); + + let tx_bytes_back = serialize(&tx); + assert_eq!(tx_bytes_back, tx_bytes); + } + + #[test] + fn fuzz_cases() { + let bytes = hex!("26ff0000000000c94ce592cf7a4cbb68eb00ce374300000057cd0000000000000026"); + assert!(deserialize::(&bytes).is_err()); // OversizedVectorAllocation + + let bytes = hex!("24000000ffffffffffffffffffffffff"); + assert!(deserialize::(&bytes).is_err()); // OversizedVectorAllocation + } +} diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs new file mode 100644 index 000000000..f3d56cd1c --- /dev/null +++ b/bitcoin/src/consensus/encode.rs @@ -0,0 +1,1164 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin consensus-encodable types. +//! +//! This is basically a replacement of the `Encodable` trait which does +//! normalization of endianness etc., to ensure that the encoding matches +//! the network consensus encoding. +//! +//! Essentially, anything that must go on the _disk_ or _network_ must be +//! encoded using the `Encodable` trait, since this data must be the same for +//! all systems. Any data going to the _user_ e.g., over JSONRPC, should use the +//! ordinary `Encodable` trait. (This should also be the same across systems, of +//! course, but has some critical differences from the network format e.g., +//! scripts come with an opcode decode, hashes are big-endian, numbers are +//! typically big-endian decimals, etc.) + +use core::any::TypeId; +use core::{cmp, mem, slice}; + +use hashes::{sha256, sha256d, Hash}; +use hex::DisplayHex as _; +use internals::{compact_size, ToU64}; +use io::{BufRead, Cursor, Read, Write}; + +use super::IterReader; +use crate::prelude::{rc, sync, Box, Cow, String, Vec}; +use crate::taproot::TapLeafHash; + +#[rustfmt::skip] // Keep public re-exports separate. +pub use super::{Error, FromHexError, ParseError, DeserializeError}; + +/// Encodes an object into a vector. +pub fn serialize(data: &T) -> Vec { + let mut encoder = Vec::new(); + let len = data.consensus_encode(&mut encoder).expect("in-memory writers don't error"); + debug_assert_eq!(len, encoder.len()); + encoder +} + +/// Encodes an object into a hex-encoded string. +pub fn serialize_hex(data: &T) -> String { + serialize(data).to_lower_hex_string() +} + +/// Deserializes an object from a vector, will error if said deserialization +/// doesn't consume the entire vector. +pub fn deserialize(data: &[u8]) -> Result { + let (rv, consumed) = deserialize_partial(data)?; + + // Fail if data are not consumed entirely. + if consumed == data.len() { + Ok(rv) + } else { + Err(DeserializeError::Unconsumed) + } +} + +/// Deserializes any decodable type from a hex string, will error if said deserialization +/// doesn't consume the entire vector. +pub fn deserialize_hex(hex: &str) -> Result { + let iter = hex::HexSliceToBytesIter::new(hex)?; + let reader = IterReader::new(iter); + Ok(reader.decode().map_err(FromHexError::Decode)?) +} + +/// Deserializes an object from a vector, but will not report an error if said deserialization +/// doesn't consume the entire vector. +pub fn deserialize_partial(data: &[u8]) -> Result<(T, usize), ParseError> { + let mut decoder = Cursor::new(data); + + let rv = match Decodable::consensus_decode_from_finite_reader(&mut decoder) { + Ok(rv) => rv, + Err(Error::Parse(e)) => return Err(e), + Err(Error::Io(_)) => + unreachable!("consensus_decode code never returns an I/O error for in-memory reads"), + }; + let consumed = decoder.position() as usize; + + Ok((rv, consumed)) +} + +/// Extensions of `Write` to encode data as per Bitcoin consensus. +pub trait WriteExt: Write { + /// Outputs a 64-bit unsigned integer. + fn emit_u64(&mut self, v: u64) -> Result<(), io::Error>; + /// Outputs a 32-bit unsigned integer. + fn emit_u32(&mut self, v: u32) -> Result<(), io::Error>; + /// Outputs a 16-bit unsigned integer. + fn emit_u16(&mut self, v: u16) -> Result<(), io::Error>; + /// Outputs an 8-bit unsigned integer. + fn emit_u8(&mut self, v: u8) -> Result<(), io::Error>; + + /// Outputs a 64-bit signed integer. + fn emit_i64(&mut self, v: i64) -> Result<(), io::Error>; + /// Outputs a 32-bit signed integer. + fn emit_i32(&mut self, v: i32) -> Result<(), io::Error>; + /// Outputs a 16-bit signed integer. + fn emit_i16(&mut self, v: i16) -> Result<(), io::Error>; + /// Outputs an 8-bit signed integer. + fn emit_i8(&mut self, v: i8) -> Result<(), io::Error>; + + /// Outputs a variable sized integer ([`CompactSize`]). + /// + /// [`CompactSize`]: + fn emit_compact_size(&mut self, v: impl ToU64) -> Result; + + /// Outputs a boolean. + fn emit_bool(&mut self, v: bool) -> Result<(), io::Error>; + + /// Outputs a byte slice. + fn emit_slice(&mut self, v: &[u8]) -> Result; +} + +/// Extensions of `Read` to decode data as per Bitcoin consensus. +pub trait ReadExt: Read { + /// Reads a 64-bit unsigned integer. + fn read_u64(&mut self) -> Result; + /// Reads a 32-bit unsigned integer. + fn read_u32(&mut self) -> Result; + /// Reads a 16-bit unsigned integer. + fn read_u16(&mut self) -> Result; + /// Reads an 8-bit unsigned integer. + fn read_u8(&mut self) -> Result; + + /// Reads a 64-bit signed integer. + fn read_i64(&mut self) -> Result; + /// Reads a 32-bit signed integer. + fn read_i32(&mut self) -> Result; + /// Reads a 16-bit signed integer. + fn read_i16(&mut self) -> Result; + /// Reads an 8-bit signed integer. + fn read_i8(&mut self) -> Result; + + /// Reads a variable sized integer ([`CompactSize`]). + /// + /// [`CompactSize`]: + fn read_compact_size(&mut self) -> Result; + + /// Reads a boolean. + fn read_bool(&mut self) -> Result; + + /// Reads a byte slice. + fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error>; +} + +macro_rules! encoder_fn { + ($name:ident, $val_type:ty) => { + #[inline] + fn $name(&mut self, v: $val_type) -> core::result::Result<(), io::Error> { + self.write_all(&v.to_le_bytes()) + } + }; +} + +macro_rules! decoder_fn { + ($name:ident, $val_type:ty, $byte_len: expr) => { + #[inline] + fn $name(&mut self) -> core::result::Result<$val_type, Error> { + let mut val = [0; $byte_len]; + self.read_exact(&mut val[..])?; + Ok(<$val_type>::from_le_bytes(val)) + } + }; +} + +impl WriteExt for W { + encoder_fn!(emit_u64, u64); + encoder_fn!(emit_u32, u32); + encoder_fn!(emit_u16, u16); + encoder_fn!(emit_i64, i64); + encoder_fn!(emit_i32, i32); + encoder_fn!(emit_i16, i16); + + #[inline] + fn emit_i8(&mut self, v: i8) -> Result<(), io::Error> { self.write_all(&[v as u8]) } + #[inline] + fn emit_u8(&mut self, v: u8) -> Result<(), io::Error> { self.write_all(&[v]) } + #[inline] + fn emit_bool(&mut self, v: bool) -> Result<(), io::Error> { self.write_all(&[v as u8]) } + #[inline] + fn emit_slice(&mut self, v: &[u8]) -> Result { + self.write_all(v)?; + Ok(v.len()) + } + #[inline] + fn emit_compact_size(&mut self, v: impl ToU64) -> Result { + let encoded = compact_size::encode(v.to_u64()); + self.emit_slice(&encoded)?; + Ok(encoded.len()) + } +} + +impl ReadExt for R { + decoder_fn!(read_u64, u64, 8); + decoder_fn!(read_u32, u32, 4); + decoder_fn!(read_u16, u16, 2); + decoder_fn!(read_i64, i64, 8); + decoder_fn!(read_i32, i32, 4); + decoder_fn!(read_i16, i16, 2); + + #[inline] + fn read_u8(&mut self) -> Result { + let mut slice = [0u8; 1]; + self.read_exact(&mut slice)?; + Ok(slice[0]) + } + #[inline] + fn read_i8(&mut self) -> Result { + let mut slice = [0u8; 1]; + self.read_exact(&mut slice)?; + Ok(slice[0] as i8) + } + #[inline] + fn read_bool(&mut self) -> Result { ReadExt::read_i8(self).map(|bit| bit != 0) } + #[inline] + fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> { Ok(self.read_exact(slice)?) } + #[inline] + #[rustfmt::skip] // Formatter munges code comments below. + fn read_compact_size(&mut self) -> Result { + match self.read_u8()? { + 0xFF => { + let x = self.read_u64()?; + if x < 0x1_0000_0000 { // I.e., would have fit in a `u32`. + Err(ParseError::NonMinimalCompactSize.into()) + } else { + Ok(x) + } + } + 0xFE => { + let x = self.read_u32()?; + if x < 0x1_0000 { // I.e., would have fit in a `u16`. + Err(ParseError::NonMinimalCompactSize.into()) + } else { + Ok(x as u64) + } + } + 0xFD => { + let x = self.read_u16()?; + if x < 0xFD { // Could have been encoded as a `u8`. + Err(ParseError::NonMinimalCompactSize.into()) + } else { + Ok(x as u64) + } + } + n => Ok(n as u64), + } + } +} + +/// Maximum size, in bytes, of a vector we are allowed to decode. +pub const MAX_VEC_SIZE: usize = 4_000_000; + +/// Data which can be encoded in a consensus-consistent way. +pub trait Encodable { + /// Encodes an object with a well-defined format. + /// + /// # Returns + /// + /// The number of bytes written on success. The only errors returned are errors propagated from + /// the writer. + fn consensus_encode(&self, writer: &mut W) -> Result; +} + +/// Data which can be decoded in a consensus-consistent way. +pub trait Decodable: Sized { + /// Decodes `Self` from a size-limited reader. + /// + /// Like `consensus_decode` but relies on the reader being limited in the amount of data it + /// returns, e.g. by being wrapped in [`std::io::Take`]. + /// + /// Failing to abide to this requirement might lead to memory exhaustion caused by malicious + /// inputs. + /// + /// Users should default to `consensus_decode`, but when data to be decoded is already in a byte + /// vector of a limited size, calling this function directly might be marginally faster (due to + /// avoiding extra checks). + /// + /// # Rules for trait implementations + /// + /// * Simple types that have a fixed size (own and member fields), don't have to overwrite + /// this method, or be concern with it. + /// * Types that deserialize using externally provided length should implement it: + /// * Make `consensus_decode` forward to `consensus_decode_from_finite_reader` with the + /// reader wrapped by `Take`. Failure to do so, without other forms of memory exhaustion + /// protection might lead to resource exhaustion vulnerability. + /// * Put a max cap on things like `Vec::with_capacity` to avoid oversized allocations, and + /// rely on the reader running out of data, and collections reallocating on a legitimately + /// oversized input data, instead of trying to enforce arbitrary length limits. + /// * Types that contain other types that implement custom + /// `consensus_decode_from_finite_reader`, should also implement it applying same rules, and + /// in addition make sure to call `consensus_decode_from_finite_reader` on all members, to + /// avoid creating redundant `Take` wrappers. Failure to do so might result only in a tiny + /// performance hit. + #[inline] + fn consensus_decode_from_finite_reader( + reader: &mut R, + ) -> Result { + // This method is always strictly less general than, `consensus_decode`, so it's safe and + // make sense to default to just calling it. This way most types, that don't care about + // protecting against resource exhaustion due to malicious input, can just ignore it. + Self::consensus_decode(reader) + } + + /// Decodes an object with a well-defined format. + /// + /// This is the method that should be implemented for a typical, fixed sized type + /// implementing this trait. Default implementation is wrapping the reader + /// in [`crate::io::Take`] to limit the input size to [`MAX_VEC_SIZE`], and forwards the call to + /// [`Self::consensus_decode_from_finite_reader`], which is convenient + /// for types that override [`Self::consensus_decode_from_finite_reader`] + /// instead. + #[inline] + fn consensus_decode(reader: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut reader.take(MAX_VEC_SIZE.to_u64())) + } +} + +// Primitive types +macro_rules! impl_int_encodable { + ($ty:ident, $meth_dec:ident, $meth_enc:ident) => { + impl Decodable for $ty { + #[inline] + fn consensus_decode( + r: &mut R, + ) -> core::result::Result { + ReadExt::$meth_dec(r) + } + } + impl Encodable for $ty { + #[inline] + fn consensus_encode( + &self, + w: &mut W, + ) -> core::result::Result { + w.$meth_enc(*self)?; + Ok(mem::size_of::<$ty>()) + } + } + }; +} + +impl_int_encodable!(u8, read_u8, emit_u8); +impl_int_encodable!(u16, read_u16, emit_u16); +impl_int_encodable!(u32, read_u32, emit_u32); +impl_int_encodable!(u64, read_u64, emit_u64); +impl_int_encodable!(i8, read_i8, emit_i8); +impl_int_encodable!(i16, read_i16, emit_i16); +impl_int_encodable!(i32, read_i32, emit_i32); +impl_int_encodable!(i64, read_i64, emit_i64); + +/// Returns 1 for 0..=0xFC, 3 for 0xFD..=(2^16-1), 5 for 0x10000..=(2^32-1), and 9 otherwise. +#[inline] +pub const fn varint_size_u64(v: u64) -> usize { + match v { + 0..=0xFC => 1, + 0xFD..=0xFFFF => 3, + 0x10000..=0xFFFFFFFF => 5, + _ => 9, + } +} + +/// Returns 1 for 0..=0xFC, 3 for 0xFD..=(2^16-1), 5 for 0x10000..=(2^32-1), and 9 otherwise. +#[inline] +pub fn varint_size(v: impl ToU64) -> usize { varint_size_u64(v.to_u64()) } + +impl Encodable for bool { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + w.emit_bool(*self)?; + Ok(1) + } +} + +impl Decodable for bool { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + ReadExt::read_bool(r) + } +} + +impl Encodable for String { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + consensus_encode_with_size(self.as_bytes(), w) + } +} + +impl Decodable for String { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Self::from_utf8(Decodable::consensus_decode(r)?) + .map_err(|_| super::parse_failed_error("String was not valid UTF8")) + } +} + +impl Encodable for Cow<'static, str> { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + consensus_encode_with_size(self.as_bytes(), w) + } +} + +impl Decodable for Cow<'static, str> { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + String::from_utf8(Decodable::consensus_decode(r)?) + .map_err(|_| super::parse_failed_error("String was not valid UTF8")) + .map(Cow::Owned) + } +} + +macro_rules! impl_array { + ( $size:literal ) => { + impl Encodable for [u8; $size] { + #[inline] + fn consensus_encode( + &self, + w: &mut W, + ) -> core::result::Result { + let n = w.emit_slice(&self[..])?; + Ok(n) + } + } + + impl Decodable for [u8; $size] { + #[inline] + fn consensus_decode( + r: &mut R, + ) -> core::result::Result { + let mut ret = [0; $size]; + r.read_slice(&mut ret)?; + Ok(ret) + } + } + }; +} + +impl_array!(2); +impl_array!(4); +impl_array!(6); +impl_array!(8); +impl_array!(10); +impl_array!(12); +impl_array!(16); +impl_array!(32); +impl_array!(33); + +impl Decodable for [u16; 8] { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + let mut res = [0; 8]; + for item in &mut res { + *item = Decodable::consensus_decode(r)?; + } + Ok(res) + } +} + +impl Encodable for [u16; 8] { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + for c in self.iter() { + c.consensus_encode(w)?; + } + Ok(16) + } +} + +impl Encodable for Vec { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self[..].consensus_encode(w) + } +} + +impl Decodable for Vec { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + if TypeId::of::() == TypeId::of::() { + let len = r.read_compact_size()? as usize; + // most real-world vec of bytes data, wouldn't be larger than 128KiB + let opts = ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }; + let bytes = read_bytes_from_finite_reader(r, opts)?; + + // unsafe: We've just checked that T is `u8` so the transmute here is a no-op. + unsafe { Ok(mem::transmute::, Self>(bytes)) } + } else { + let len = r.read_compact_size()?; + // Limit the initial vec allocation to at most 8,000 bytes, which is + // sufficient for most use cases. We don't allocate more space upfront + // than this, since `len` is an untrusted allocation capacity. If the + // vector does overflow the initial capacity `push` will just reallocate. + // Note: OOM protection relies on reader eventually running out of + // data to feed us. + let max_init_capacity = 8000 / mem::size_of::(); + let mut ret = Self::with_capacity(cmp::min(len as usize, max_init_capacity)); + for _ in 0..len { + ret.push(Decodable::consensus_decode_from_finite_reader(r)?); + } + Ok(ret) + } + } +} + +pub(crate) fn consensus_encode_with_size( + data: &[u8], + w: &mut W, +) -> Result { + Ok(w.emit_compact_size(data.len())? + w.emit_slice(data)?) +} + +struct ReadBytesFromFiniteReaderOpts { + len: usize, + chunk_size: usize, +} + +/// Read `opts.len` bytes from reader, where `opts.len` could potentially be malicious. +/// +/// This function relies on reader being bound in amount of data +/// it returns for OOM protection. See [`Decodable::consensus_decode_from_finite_reader`]. +#[inline] +fn read_bytes_from_finite_reader( + d: &mut D, + mut opts: ReadBytesFromFiniteReaderOpts, +) -> Result, Error> { + let mut ret = vec![]; + + assert_ne!(opts.chunk_size, 0); + + while opts.len > 0 { + let chunk_start = ret.len(); + let chunk_size = core::cmp::min(opts.len, opts.chunk_size); + let chunk_end = chunk_start + chunk_size; + ret.resize(chunk_end, 0u8); + d.read_slice(&mut ret[chunk_start..chunk_end])?; + opts.len -= chunk_size; + } + + Ok(ret) +} + +impl Encodable for Box<[u8]> { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + consensus_encode_with_size(self, w) + } +} + +impl Decodable for Box<[u8]> { + #[inline] + fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + >::consensus_decode_from_finite_reader(r).map(From::from) + } +} + +impl Encodable for [T] { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + (&self).consensus_encode(w) + } +} + +impl Encodable for &[T] { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + if TypeId::of::() == TypeId::of::() { + let len = self.len(); + let ptr = self.as_ptr(); + + // unsafe: We've just checked that T is `u8`. + let v = unsafe { slice::from_raw_parts(ptr.cast::(), len) }; + consensus_encode_with_size(v, w) + } else { + let mut len = w.emit_compact_size(self.len())?; + for c in self.iter() { + len += c.consensus_encode(w)?; + } + Ok(len) + } + } +} + +impl Encodable for &'_ T { + fn consensus_encode(&self, w: &mut W) -> Result { + (**self).consensus_encode(w) + } +} + +impl Encodable for &'_ mut T { + fn consensus_encode(&self, w: &mut W) -> Result { + (**self).consensus_encode(w) + } +} + +impl Encodable for rc::Rc { + fn consensus_encode(&self, w: &mut W) -> Result { + (**self).consensus_encode(w) + } +} + +/// Note: This will fail to compile on old Rust for targets that don't support atomics +#[cfg(target_has_atomic = "ptr")] +impl Encodable for sync::Arc { + fn consensus_encode(&self, w: &mut W) -> Result { + (**self).consensus_encode(w) + } +} + +macro_rules! tuple_encode { + ($($x:ident),*) => { + impl <$($x: Encodable),*> Encodable for ($($x),*) { + #[inline] + #[allow(non_snake_case)] + fn consensus_encode( + &self, + w: &mut W, + ) -> core::result::Result { + let &($(ref $x),*) = self; + let mut len = 0; + $(len += $x.consensus_encode(w)?;)* + Ok(len) + } + } + + impl<$($x: Decodable),*> Decodable for ($($x),*) { + #[inline] + #[allow(non_snake_case)] + fn consensus_decode(r: &mut R) -> core::result::Result { + Ok(($({let $x = Decodable::consensus_decode(r)?; $x }),*)) + } + } + }; +} + +tuple_encode!(T0, T1); +tuple_encode!(T0, T1, T2); +tuple_encode!(T0, T1, T2, T3); +tuple_encode!(T0, T1, T2, T3, T4); +tuple_encode!(T0, T1, T2, T3, T4, T5); +tuple_encode!(T0, T1, T2, T3, T4, T5, T6); +tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); + +impl Encodable for sha256d::Hash { + fn consensus_encode(&self, w: &mut W) -> Result { + self.as_byte_array().consensus_encode(w) + } +} + +impl Decodable for sha256d::Hash { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<::Bytes>::consensus_decode(r)?)) + } +} + +impl Encodable for sha256::Hash { + fn consensus_encode(&self, w: &mut W) -> Result { + self.as_byte_array().consensus_encode(w) + } +} + +impl Decodable for sha256::Hash { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<::Bytes>::consensus_decode(r)?)) + } +} + +impl Encodable for TapLeafHash { + fn consensus_encode(&self, w: &mut W) -> Result { + self.as_byte_array().consensus_encode(w) + } +} + +impl Decodable for TapLeafHash { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<::Bytes>::consensus_decode(r)?)) + } +} + +#[cfg(test)] +mod tests { + use core::fmt; + use core::mem::discriminant; + + use super::*; + use crate::block::BlockHash; + use crate::merkle_tree::TxMerkleNode; + use crate::prelude::{Cow, Vec}; + use crate::transaction::{Transaction, TxIn, TxOut}; + + #[test] + fn serialize_int() { + // bool + assert_eq!(serialize(&false), [0u8]); + assert_eq!(serialize(&true), [1u8]); + // u8 + assert_eq!(serialize(&1u8), [1u8]); + assert_eq!(serialize(&0u8), [0u8]); + assert_eq!(serialize(&255u8), [255u8]); + // u16 + assert_eq!(serialize(&1u16), [1u8, 0]); + assert_eq!(serialize(&256u16), [0u8, 1]); + assert_eq!(serialize(&5000u16), [136u8, 19]); + // u32 + assert_eq!(serialize(&1u32), [1u8, 0, 0, 0]); + assert_eq!(serialize(&256u32), [0u8, 1, 0, 0]); + assert_eq!(serialize(&5000u32), [136u8, 19, 0, 0]); + assert_eq!(serialize(&500000u32), [32u8, 161, 7, 0]); + assert_eq!(serialize(&168430090u32), [10u8, 10, 10, 10]); + // i32 + assert_eq!(serialize(&-1i32), [255u8, 255, 255, 255]); + assert_eq!(serialize(&-256i32), [0u8, 255, 255, 255]); + assert_eq!(serialize(&-5000i32), [120u8, 236, 255, 255]); + assert_eq!(serialize(&-500000i32), [224u8, 94, 248, 255]); + assert_eq!(serialize(&-168430090i32), [246u8, 245, 245, 245]); + assert_eq!(serialize(&1i32), [1u8, 0, 0, 0]); + assert_eq!(serialize(&256i32), [0u8, 1, 0, 0]); + assert_eq!(serialize(&5000i32), [136u8, 19, 0, 0]); + assert_eq!(serialize(&500000i32), [32u8, 161, 7, 0]); + assert_eq!(serialize(&168430090i32), [10u8, 10, 10, 10]); + // u64 + assert_eq!(serialize(&1u64), [1u8, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&256u64), [0u8, 1, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&5000u64), [136u8, 19, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&500000u64), [32u8, 161, 7, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&723401728380766730u64), [10u8, 10, 10, 10, 10, 10, 10, 10]); + // i64 + assert_eq!(serialize(&-1i64), [255u8, 255, 255, 255, 255, 255, 255, 255]); + assert_eq!(serialize(&-256i64), [0u8, 255, 255, 255, 255, 255, 255, 255]); + assert_eq!(serialize(&-5000i64), [120u8, 236, 255, 255, 255, 255, 255, 255]); + assert_eq!(serialize(&-500000i64), [224u8, 94, 248, 255, 255, 255, 255, 255]); + assert_eq!(serialize(&-723401728380766730i64), [246u8, 245, 245, 245, 245, 245, 245, 245]); + assert_eq!(serialize(&1i64), [1u8, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&256i64), [0u8, 1, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&5000i64), [136u8, 19, 0, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&500000i64), [32u8, 161, 7, 0, 0, 0, 0, 0]); + assert_eq!(serialize(&723401728380766730i64), [10u8, 10, 10, 10, 10, 10, 10, 10]); + } + + fn test_varint_encode(n: u8, x: &[u8]) -> Result { + let mut input = [0u8; 9]; + input[0] = n; + input[1..x.len() + 1].copy_from_slice(x); + (&input[..]).read_compact_size() + } + + #[test] + fn encode_t_slice() { + // Multi-element u8 case + let enc_buf = serialize(&[1u8, 2, 3, 4].as_slice()); + assert_eq!(enc_buf, [4u8, 1, 2, 3, 4]); + + // Empty u64 case + let enc_buf = serialize::<&[u64]>(&[0u64; 0].as_slice()); + assert_eq!(enc_buf, [0u8]); + + // multi-element u32 case + let enc_buf = serialize(&[654321u32, 123456].as_slice()); + assert_eq!(enc_buf, [2u8, 241, 251, 9, 0, 64, 226, 1, 0]) + } + + #[test] + fn encode_u8_slice() { + // Multi-element case + let enc_buf = serialize([1u8, 2, 3, 4].as_slice()); + assert_eq!(enc_buf, [4u8, 1, 2, 3, 4]); + + // Empty case + let enc_buf = serialize::<[u8]>([0u8; 0].as_slice()); + assert_eq!(enc_buf, [0u8]); + + // Single-element case + let enc_buf = serialize([42u8].as_slice()); + assert_eq!(enc_buf, [1u8, 42]); + } + + #[test] + fn encode_u8_slice_matches_vec() { + let assert_vec_eq = |data: Vec| { + let enc_buf = serialize::<[u8]>(data.as_slice()); + let vec_enc_buf = serialize::>(&data); + assert_eq!(enc_buf, vec_enc_buf); + }; + + // Multi-element case + let data = vec![1u8, 2, 3, 4]; + assert_vec_eq(data); + + // Empty case + let data = Vec::new(); + assert_vec_eq(data); + + // Single-element case + let data = vec![42u8]; + assert_vec_eq(data); + } + + #[test] + fn serialize_varint() { + fn encode(v: u64) -> Vec { + let mut buf = Vec::new(); + buf.emit_compact_size(v).unwrap(); + buf + } + + assert_eq!(encode(10), [10u8]); + assert_eq!(encode(0xFC), [0xFCu8]); + assert_eq!(encode(0xFD), [0xFDu8, 0xFD, 0]); + assert_eq!(encode(0xFFF), [0xFDu8, 0xFF, 0xF]); + assert_eq!(encode(0xF0F0F0F), [0xFEu8, 0xF, 0xF, 0xF, 0xF]); + assert_eq!(encode(0xF0F0F0F0F0E0), vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0],); + assert_eq!(test_varint_encode(0xFF, &0x100000000_u64.to_le_bytes()).unwrap(), 0x100000000,); + assert_eq!(test_varint_encode(0xFE, &0x10000_u64.to_le_bytes()).unwrap(), 0x10000); + assert_eq!(test_varint_encode(0xFD, &0xFD_u64.to_le_bytes()).unwrap(), 0xFD); + + // Test that length calc is working correctly + fn test_varint_len(varint: u64, expected: usize) { + let mut encoder = vec![]; + assert_eq!(encoder.emit_compact_size(varint).unwrap(), expected); + assert_eq!(varint_size(varint), expected); + } + test_varint_len(0, 1); + test_varint_len(0xFC, 1); + test_varint_len(0xFD, 3); + test_varint_len(0xFFFF, 3); + test_varint_len(0x10000, 5); + test_varint_len(0xFFFFFFFF, 5); + test_varint_len(0xFFFFFFFF + 1, 9); + test_varint_len(u64::MAX, 9); + } + + #[test] + fn deserialize_nonminimal_vec() { + // Check the edges for variant int + assert_eq!( + discriminant( + &test_varint_encode(0xFF, &(0x100000000_u64 - 1).to_le_bytes()).unwrap_err() + ), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant(&test_varint_encode(0xFE, &(0x10000_u64 - 1).to_le_bytes()).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant(&test_varint_encode(0xFD, &(0xFD_u64 - 1).to_le_bytes()).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0x00, 0x00]).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]).unwrap_err()), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant( + &deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + .unwrap_err() + ), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + assert_eq!( + discriminant( + &deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]) + .unwrap_err() + ), + discriminant(&ParseError::NonMinimalCompactSize.into()) + ); + + let mut vec_256 = vec![0; 259]; + vec_256[0] = 0xfd; + vec_256[1] = 0x00; + vec_256[2] = 0x01; + assert!(deserialize::>(&vec_256).is_ok()); + + let mut vec_253 = vec![0; 256]; + vec_253[0] = 0xfd; + vec_253[1] = 0xfd; + vec_253[2] = 0x00; + assert!(deserialize::>(&vec_253).is_ok()); + } + + #[test] + fn serialize_vector() { + assert_eq!(serialize(&vec![1u8, 2, 3]), [3u8, 1, 2, 3]); + } + + #[test] + fn serialize_strbuf() { + assert_eq!(serialize(&"Andrew".to_string()), [6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]); + } + + #[test] + fn deserialize_int() { + // bool + assert!((deserialize(&[58u8, 0]) as Result).is_err()); + assert_eq!(deserialize(&[58u8]).ok(), Some(true)); + assert_eq!(deserialize(&[1u8]).ok(), Some(true)); + assert_eq!(deserialize(&[0u8]).ok(), Some(false)); + assert!((deserialize(&[0u8, 1]) as Result).is_err()); + + // u8 + assert_eq!(deserialize(&[58u8]).ok(), Some(58u8)); + + // u16 + assert_eq!(deserialize(&[0x01u8, 0x02]).ok(), Some(0x0201u16)); + assert_eq!(deserialize(&[0xABu8, 0xCD]).ok(), Some(0xCDABu16)); + assert_eq!(deserialize(&[0xA0u8, 0x0D]).ok(), Some(0xDA0u16)); + let failure16: Result = deserialize(&[1u8]); + assert!(failure16.is_err()); + + // i16 + assert_eq!(deserialize(&[0x32_u8, 0xF4]).ok(), Some(-0x0bce_i16)); + assert_eq!(deserialize(&[0xFF_u8, 0xFE]).ok(), Some(-0x0101_i16)); + assert_eq!(deserialize(&[0x00_u8, 0x00]).ok(), Some(-0_i16)); + assert_eq!(deserialize(&[0xFF_u8, 0xFA]).ok(), Some(-0x0501_i16)); + + // u32 + assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0]).ok(), Some(0xCDABu32)); + assert_eq!(deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD]).ok(), Some(0xCDAB0DA0u32)); + + let failure32: Result = deserialize(&[1u8, 2, 3]); + assert!(failure32.is_err()); + + // i32 + assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0]).ok(), Some(0xCDABi32)); + assert_eq!(deserialize(&[0xA0u8, 0x0D, 0xAB, 0x2D]).ok(), Some(0x2DAB0DA0i32)); + + assert_eq!(deserialize(&[0, 0, 0, 0]).ok(), Some(-0_i32)); + assert_eq!(deserialize(&[0, 0, 0, 0]).ok(), Some(0_i32)); + + assert_eq!(deserialize(&[0xFF, 0xFF, 0xFF, 0xFF]).ok(), Some(-1_i32)); + assert_eq!(deserialize(&[0xFE, 0xFF, 0xFF, 0xFF]).ok(), Some(-2_i32)); + assert_eq!(deserialize(&[0x01, 0xFF, 0xFF, 0xFF]).ok(), Some(-255_i32)); + assert_eq!(deserialize(&[0x02, 0xFF, 0xFF, 0xFF]).ok(), Some(-254_i32)); + + let failurei32: Result = deserialize(&[1u8, 2, 3]); + assert!(failurei32.is_err()); + + // u64 + assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0, 0, 0, 0, 0]).ok(), Some(0xCDABu64)); + assert_eq!( + deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), + Some(0x99000099CDAB0DA0u64) + ); + let failure64: Result = deserialize(&[1u8, 2, 3, 4, 5, 6, 7]); + assert!(failure64.is_err()); + + // i64 + assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0, 0, 0, 0, 0]).ok(), Some(0xCDABi64)); + assert_eq!( + deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), + Some(-0x66ffff663254f260i64) + ); + assert_eq!( + deserialize(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-1_i64) + ); + assert_eq!( + deserialize(&[0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-2_i64) + ); + assert_eq!( + deserialize(&[0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-255_i64) + ); + assert_eq!( + deserialize(&[0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-254_i64) + ); + + let failurei64: Result = deserialize(&[1u8, 2, 3, 4, 5, 6, 7]); + assert!(failurei64.is_err()); + } + + #[test] + fn deserialize_vec() { + assert_eq!(deserialize(&[3u8, 2, 3, 4]).ok(), Some(vec![2u8, 3, 4])); + assert!((deserialize(&[4u8, 2, 3, 4, 5, 6]) as Result, _>).is_err()); + // found by cargo fuzz + assert!(deserialize::>(&[ + 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6b, 0xa, 0xa, 0x3a + ]) + .is_err()); + + // Check serialization that `if len > MAX_VEC_SIZE {return err}` isn't inclusive, + // by making sure it fails with `MissingData` and not an `OversizedVectorAllocation` Error. + let err = deserialize::(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err(); + assert!(matches!(err, DeserializeError::Parse(ParseError::MissingData))); + + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::(); + test_len_is_max_vec::>(); + test_len_is_max_vec::(); + } + + fn test_len_is_max_vec() + where + Vec: Decodable, + T: fmt::Debug, + { + let mut buf = Vec::new(); + buf.emit_compact_size(super::MAX_VEC_SIZE / mem::size_of::()).unwrap(); + let err = deserialize::>(&buf).unwrap_err(); + assert!(matches!(err, DeserializeError::Parse(ParseError::MissingData))); + } + + #[test] + fn deserialize_strbuf() { + assert_eq!( + deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), + Some("Andrew".to_string()) + ); + assert_eq!( + deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), + Some(Cow::Borrowed("Andrew")) + ); + } + + #[test] + fn limit_read() { + let witness = vec![vec![0u8; 3_999_999]; 2]; + let ser = serialize(&witness); + let mut reader = io::Cursor::new(ser); + let err = Vec::>::consensus_decode(&mut reader); + assert!(err.is_err()); + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn serialization_round_trips() { + use secp256k1::rand::{self, Rng}; + + macro_rules! round_trip { + ($($val_type:ty),*) => { + $( + let r: $val_type = rand::rng().random(); + assert_eq!(deserialize::<$val_type>(&serialize(&r)).unwrap(), r); + )* + }; + } + macro_rules! round_trip_bytes { + ($(($val_type:ty, $data:expr)),*) => { + $( + rand::rng().fill(&mut $data[..]); + assert_eq!(deserialize::<$val_type>(&serialize(&$data)).unwrap()[..], $data[..]); + )* + }; + } + + let mut data = Vec::with_capacity(256); + let mut data64 = Vec::with_capacity(256); + for _ in 0..10 { + round_trip! {bool, i8, u8, i16, u16, i32, u32, i64, u64, + (bool, i8, u16, i32), (u64, i64, u32, i32, u16, i16), (i8, u8, i16, u16, i32, u32, i64, u64), + [u8; 2], [u8; 4], [u8; 8], [u8; 12], [u8; 16], [u8; 32]}; + + data.clear(); + data64.clear(); + let len = rand::rng().random_range(1..256); + data.resize(len, 0u8); + data64.resize(len, 0u64); + let mut arr33 = [0u8; 33]; + let mut arr16 = [0u16; 8]; + round_trip_bytes! {(Vec, data), ([u8; 33], arr33), ([u16; 8], arr16), (Vec, data64)}; + } + } + + #[test] + fn test_read_bytes_from_finite_reader() { + let data: Vec = (0..10).collect(); + + for chunk_size in 1..20 { + assert_eq!( + read_bytes_from_finite_reader( + &mut io::Cursor::new(&data), + ReadBytesFromFiniteReaderOpts { len: data.len(), chunk_size } + ) + .unwrap(), + data + ); + } + } + + #[test] + fn deserialize_tx_hex() { + let hex = include_str!("../../tests/data/previous_tx_0_hex"); // An arbitrary transaction. + assert!(deserialize_hex::(hex).is_ok()) + } + + #[test] + fn deserialize_tx_hex_too_many_bytes() { + use crate::consensus::DecodeError; + + let mut hex = include_str!("../../tests/data/previous_tx_0_hex").to_string(); // An arbitrary transaction. + hex.push_str("abcdef"); + assert!(matches!( + deserialize_hex::(&hex).unwrap_err(), + FromHexError::Decode(DecodeError::Unconsumed) + )); + } + + #[test] + fn deserialize_extreme_tx() { + use crate::{ScriptSigBuf, Witness}; + + // Start with transaction from `deserialize_tx_hex` + let hex = include_str!("../../tests/data/previous_tx_0_hex"); // An arbitrary transaction. + let tx = deserialize_hex::(hex).unwrap(); + + assert_eq!(tx.inputs.len(), 1); + assert_eq!(tx.outputs.len(), 2); + assert_eq!(tx.inputs[0].witness.len(), 2); + + // 1. Test with 4 million witnesses. + let mut tx_copy = tx.clone(); + tx_copy.inputs[0].witness = Witness::from_slice(&vec![vec![]; 4_000_000]); + let roundtrip = deserialize(&serialize(&tx_copy)).unwrap(); + assert_eq!(tx_copy, roundtrip); + + // 2. Test with a single large witness. (Size of 4 megs, including length prefix) + let mut tx_copy = tx.clone(); + tx_copy.inputs[0].witness = Witness::from_slice(&vec![vec![0; 4_000_000 - 9]; 1]); + let roundtrip = deserialize(&serialize(&tx_copy)).unwrap(); + assert_eq!(tx_copy, roundtrip); + + // 3. Combine these; with the witness stack we can exceed a total size of 4M but + // only by a tiny bit. (It is not part of our API guarantee that such things + // will round-trip, but we unit test them anyway to help notice changes.) + let mut tx_copy = tx.clone(); + tx_copy.inputs[0].witness = Witness::from_slice(&vec![vec![0; 997]; 4_000]); + let roundtrip = deserialize(&serialize(&tx_copy)).unwrap(); + assert_eq!(tx_copy, roundtrip); + + // 4. Test with a large script sig. With scriptsigs there is no limit on how large + // an object we can parse, which is inconsistent with witnesses. Also not an + // API guarantee. + let mut tx_copy = tx; + tx_copy.inputs[0].script_sig = ScriptSigBuf::from(vec![0; 8_000_001]); + let roundtrip = deserialize(&serialize(&tx_copy)).unwrap(); + assert_eq!(tx_copy, roundtrip); + } +} diff --git a/bitcoin/src/consensus/error.rs b/bitcoin/src/consensus/error.rs new file mode 100644 index 000000000..d16b1a3f2 --- /dev/null +++ b/bitcoin/src/consensus/error.rs @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Consensus encoding errors. + +use core::convert::Infallible; +use core::fmt; + +use hex::error::{InvalidCharError, OddLengthStringError}; +use internals::write_err; + +#[cfg(doc)] +use super::IterReader; + +/// Error deserializing from a slice. +#[derive(Debug)] +#[non_exhaustive] +pub enum DeserializeError { + /// Error parsing encoded object. + Parse(ParseError), + /// Data unconsumed error. + Unconsumed, +} + +impl From for DeserializeError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for DeserializeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Parse(ref e) => write_err!(f, "error parsing encoded object"; e), + Self::Unconsumed => write!(f, "data not consumed entirely when deserializing"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for DeserializeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Parse(ref e) => Some(e), + Self::Unconsumed => None, + } + } +} + +impl From for DeserializeError { + fn from(e: ParseError) -> Self { Self::Parse(e) } +} + +/// Error when consensus decoding from an `[IterReader]`. +/// +/// This is the same as a `DeserializeError` with an additional variant to return any error yielded +/// by the inner bytes iterator. +#[derive(Debug)] +pub enum DecodeError { + /// Invalid consensus encoding. + Parse(ParseError), + /// Data unconsumed error. + Unconsumed, + /// Other decoding error. + Other(E), // Yielded by the inner iterator. +} + +impl From for DecodeError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Parse(ref e) => write_err!(f, "error parsing encoded object"; e), + Self::Unconsumed => write!(f, "data not consumed entirely when deserializing"), + Self::Other(ref other) => write!(f, "other decoding error: {:?}", other), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Parse(ref e) => Some(e), + Self::Unconsumed => None, + Self::Other(ref e) => Some(e), + } + } +} + +/// Encoding error. +#[derive(Debug)] +#[non_exhaustive] +pub enum Error { + /// An I/O error. + Io(io::Error), + /// Error parsing encoded object. + Parse(ParseError), +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Io(ref e) => write_err!(f, "I/O error"; e), + Self::Parse(ref e) => write_err!(f, "error parsing encoded object"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Io(ref e) => Some(e), + Self::Parse(ref e) => Some(e), + } + } +} + +impl From for Error { + fn from(e: io::Error) -> Self { + use io::ErrorKind; + + match e.kind() { + ErrorKind::UnexpectedEof => Self::Parse(ParseError::MissingData), + _ => Self::Io(e), + } + } +} + +impl From for Error { + fn from(e: ParseError) -> Self { Self::Parse(e) } +} + +/// Encoding is invalid. +#[derive(Debug)] +#[non_exhaustive] +pub enum ParseError { + /// Missing data (early end of file or slice too short). + MissingData, // TODO: Can we add more context? + /// Tried to allocate an oversized vector. + OversizedVectorAllocation { + /// The capacity requested. + requested: usize, + /// The maximum capacity. + max: usize, + }, + /// Checksum was invalid. + InvalidChecksum { + /// The expected checksum. + expected: [u8; 4], + /// The invalid checksum. + actual: [u8; 4], + }, + /// CompactSize was encoded in a non-minimal way. + NonMinimalCompactSize, + /// Parsing error. + ParseFailed(&'static str), + /// Unsupported SegWit flag. + UnsupportedSegwitFlag(u8), + /// Witness decoding error. + Witness(io::ReadError), +} + +impl From for ParseError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::MissingData => write!(f, "missing data (early end of file or slice too short)"), + Self::OversizedVectorAllocation { requested: ref r, max: ref m } => + write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m), + Self::InvalidChecksum { expected: ref e, actual: ref a } => write!( + f, + "invalid checksum: expected {:02x}{:02x}{:02x}{:02x}, actual {:02x}{:02x}{:02x}{:02x}", + e[0], e[1], e[2], e[3], a[0], a[1], a[2], a[3], + ), + Self::NonMinimalCompactSize => write!(f, "non-minimal compact size"), + Self::ParseFailed(ref s) => write!(f, "parse failed: {}", s), + Self::UnsupportedSegwitFlag(ref swflag) => + write!(f, "unsupported SegWit version: {}", swflag), + Self::Witness(ref e) => write_err!(f, "witness"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Witness(ref e) => Some(e), + Self::MissingData + | Self::OversizedVectorAllocation { .. } + | Self::InvalidChecksum { .. } + | Self::NonMinimalCompactSize + | Self::ParseFailed(_) + | Self::UnsupportedSegwitFlag(_) => None, + } + } +} + +/// Hex deserialization error. +#[derive(Debug)] +pub enum FromHexError { + /// Purported hex string had odd length. + OddLengthString(OddLengthStringError), + /// Decoding error. + Decode(DecodeError), +} + +impl fmt::Display for FromHexError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::OddLengthString(ref e) => + write_err!(f, "odd length, failed to create bytes from hex"; e), + Self::Decode(ref e) => write_err!(f, "decoding error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromHexError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::OddLengthString(ref e) => Some(e), + Self::Decode(ref e) => Some(e), + } + } +} + +impl From for FromHexError { + #[inline] + fn from(e: OddLengthStringError) -> Self { Self::OddLengthString(e) } +} + +/// Constructs a new `Error::ParseFailed` error. +// This whole variant should go away because of the inner string. +pub(crate) fn parse_failed_error(msg: &'static str) -> Error { + Error::Parse(ParseError::ParseFailed(msg)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn invalid_checksum_display() { + let e = ParseError::InvalidChecksum { + expected: [0xde, 0xad, 0xbe, 0xef], + actual: [0xca, 0xfe, 0xba, 0xbe], + }; + + let want = "invalid checksum: expected deadbeef, actual cafebabe"; + let got = format!("{}", e); + assert_eq!(got, want); + } + + #[test] + fn invalid_checksum_display_expected_leading_zeros() { + let e = ParseError::InvalidChecksum { + expected: [0x00, 0x00, 0x00, 0x0f], + actual: [0xca, 0xfe, 0xba, 0xbe], + }; + + let want = "invalid checksum: expected 0000000f, actual cafebabe"; + let got = format!("{}", e); + assert_eq!(got, want); + } + + #[test] + fn invalid_checksum_display_actual_leading_zeros() { + let e = ParseError::InvalidChecksum { + expected: [0xde, 0xad, 0xbe, 0xef], + actual: [0x00, 0x00, 0x00, 0x0e], + }; + + let want = "invalid checksum: expected deadbeef, actual 0000000e"; + let got = format!("{}", e); + assert_eq!(got, want); + } +} diff --git a/bitcoin/src/consensus/mod.rs b/bitcoin/src/consensus/mod.rs new file mode 100644 index 000000000..dbfa9c4d6 --- /dev/null +++ b/bitcoin/src/consensus/mod.rs @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin consensus. +//! +//! This module defines structures, functions, and traits that are needed to +//! conform to Bitcoin consensus. + +pub mod encode; +mod error; +#[cfg(feature = "serde")] +pub mod serde; + +use core::fmt; + +use io::{BufRead, Read}; + +use crate::consensus; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + encode::{deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt}, + error::{Error, FromHexError, DecodeError, ParseError, DeserializeError}, +}; +pub(crate) use self::error::parse_failed_error; + +struct IterReader>> { + iterator: core::iter::Fuse, + buf: Option, + error: Option, +} + +impl>> IterReader { + pub(crate) fn new(iterator: I) -> Self { + Self { iterator: iterator.fuse(), buf: None, error: None } + } + + fn decode(mut self) -> Result> { + let result = T::consensus_decode(&mut self); + match (result, self.error) { + (Ok(_), None) if self.iterator.next().is_some() => Err(DecodeError::Unconsumed), + (Ok(value), None) => Ok(value), + (Ok(_), Some(error)) => panic!("{} silently ate the error: {:?}", core::any::type_name::(), error), + + (Err(consensus::encode::Error::Io(io_error)), Some(de_error)) if io_error.kind() == io::ErrorKind::Other && io_error.get_ref().is_none() => Err(DecodeError::Other(de_error)), + (Err(consensus::encode::Error::Parse(parse_error)), None) => Err(DecodeError::Parse(parse_error)), + (Err(consensus::encode::Error::Io(io_error)), de_error) => panic!("unexpected I/O error {:?} returned from {}::consensus_decode(), deserialization error: {:?}", io_error, core::any::type_name::(), de_error), + (Err(consensus_error), Some(de_error)) => panic!("{} should've returned `Other` I/O error because of deserialization error {:?} but it returned consensus error {:?} instead", core::any::type_name::(), de_error, consensus_error), + } + } +} + +impl>> Read for IterReader { + fn read(&mut self, mut buf: &mut [u8]) -> io::Result { + let mut count = 0; + if buf.is_empty() { + return Ok(0); + } + + if let Some(first) = self.buf.take() { + buf[0] = first; + buf = &mut buf[1..]; + count += 1; + } + for (dst, src) in buf.iter_mut().zip(&mut self.iterator) { + match src { + Ok(byte) => *dst = byte, + Err(error) => { + self.error = Some(error); + return Err(io::ErrorKind::Other.into()); + } + } + // bounded by the length of buf + count += 1; + } + Ok(count) + } +} + +impl>> BufRead for IterReader { + fn fill_buf(&mut self) -> Result<&[u8], io::Error> { + // matching on reference rather than using `ref` confuses borrow checker + if let Some(ref byte) = self.buf { + Ok(core::slice::from_ref(byte)) + } else { + match self.iterator.next() { + Some(Ok(byte)) => { + self.buf = Some(byte); + Ok(core::slice::from_ref(self.buf.as_ref().expect("we've just filled it"))) + } + Some(Err(error)) => { + self.error = Some(error); + Err(io::ErrorKind::Other.into()) + } + None => Ok(&[]), + } + } + } + + fn consume(&mut self, len: usize) { + debug_assert!(len <= 1); + if len > 0 { + self.buf = None; + } + } +} diff --git a/bitcoin/src/consensus/serde.rs b/bitcoin/src/consensus/serde.rs new file mode 100644 index 000000000..79a3e7d72 --- /dev/null +++ b/bitcoin/src/consensus/serde.rs @@ -0,0 +1,511 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Serde serialization via consensus encoding +//! +//! This provides functions for (de)serializing any type as consensus-encoded bytes. +//! For human-readable formats it serializes as a string with a consumer-supplied encoding, for +//! binary formats it serializes as a sequence of bytes (not `serialize_bytes` to avoid allocations). +//! +//! The string encoding has to be specified using a marker type implementing the encoding strategy. +//! This crate provides hex encoding via `Hex` and `Hex` + +use core::fmt; +use core::marker::PhantomData; + +use io::Write; +use serde::de::{SeqAccess, Unexpected, Visitor}; +use serde::ser::SerializeSeq; +use serde::{Deserializer, Serializer}; + +use super::{Decodable, Encodable, ParseError}; +use crate::consensus::{DecodeError, IterReader}; + +/// Hex-encoding strategy +pub struct Hex(PhantomData) +where + Case: hex::Case; + +impl Default for Hex { + fn default() -> Self { Self(Default::default()) } +} + +impl ByteEncoder for Hex { + type Encoder = hex::Encoder; +} + +/// Implements hex encoding. +pub mod hex { + use core::fmt; + use core::marker::PhantomData; + + use hex::buf_encoder::BufEncoder; + + /// Marker for upper/lower case type-level flags ("type-level enum"). + /// + /// You may use this trait in bounds only. + pub trait Case: sealed::Case {} + impl Case for T {} + + /// Marker for using lower-case hex encoding. + pub enum Lower {} + /// Marker for using upper-case hex encoding. + pub enum Upper {} + + mod sealed { + pub trait Case { + /// Internal detail, don't depend on it!!! + const INTERNAL_CASE: hex::Case; + } + + impl Case for super::Lower { + const INTERNAL_CASE: hex::Case = hex::Case::Lower; + } + + impl Case for super::Upper { + const INTERNAL_CASE: hex::Case = hex::Case::Upper; + } + } + + // We just guessed at a reasonably sane value. + const HEX_BUF_SIZE: usize = 512; + + /// Hex byte encoder. + // We wrap `BufEncoder` to not leak internal representation. + pub struct Encoder(BufEncoder<{ HEX_BUF_SIZE }>, PhantomData); + + impl From> for Encoder { + fn from(_: super::Hex) -> Self { + Self(BufEncoder::new(C::INTERNAL_CASE), Default::default()) + } + } + + impl super::EncodeBytes for Encoder { + fn encode_chunk(&mut self, writer: &mut W, mut bytes: &[u8]) -> fmt::Result { + while !bytes.is_empty() { + if self.0.is_full() { + self.flush(writer)?; + } + bytes = self.0.put_bytes_min(bytes); + } + Ok(()) + } + + fn flush(&mut self, writer: &mut W) -> fmt::Result { + writer.write_str(self.0.as_str())?; + self.0.clear(); + Ok(()) + } + } + + // Newtypes to hide internal details. + + /// Error returned when a hex string decoder can't be created. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct DecodeInitError(hex::OddLengthStringError); + + /// Error returned when a hex string contains invalid characters. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct DecodeError(hex::InvalidCharError); + + /// Hex decoder state. + pub struct Decoder<'a>(hex::HexSliceToBytesIter<'a>); + + impl<'a> Decoder<'a> { + fn new(s: &'a str) -> Result { + match hex::HexToBytesIter::new(s) { + Ok(iter) => Ok(Decoder(iter)), + Err(error) => Err(DecodeInitError(error)), + } + } + } + + impl Iterator for Decoder<'_> { + type Item = Result; + + fn next(&mut self) -> Option { + self.0.next().map(|result| result.map_err(DecodeError)) + } + } + + impl<'a, C: Case> super::ByteDecoder<'a> for super::Hex { + type InitError = DecodeInitError; + type DecodeError = DecodeError; + type Decoder = Decoder<'a>; + + fn from_str(s: &'a str) -> Result { Decoder::new(s) } + } + + impl super::IntoDeError for DecodeInitError { + fn into_de_error(self) -> E { + E::invalid_length(self.0.length(), &"an even number of ASCII-encoded hex digits") + } + } + + impl super::IntoDeError for DecodeError { + fn into_de_error(self) -> E { + use serde::de::Unexpected; + + const EXPECTED_CHAR: &str = "an ASCII-encoded hex digit"; + + match self.0.invalid_char() { + c if c.is_ascii() => E::invalid_value(Unexpected::Char(c as _), &EXPECTED_CHAR), + c => E::invalid_value(Unexpected::Unsigned(c.into()), &EXPECTED_CHAR), + } + } + } +} + +struct DisplayWrapper<'a, T: 'a + Encodable, E>(&'a T, PhantomData); + +impl<'a, T: 'a + Encodable, E: ByteEncoder> fmt::Display for DisplayWrapper<'a, T, E> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut writer = IoWrapper::<'_, _, E::Encoder>::new(f, E::default().into()); + self.0.consensus_encode(&mut writer).map_err(|error| { + #[cfg(debug_assertions)] + { + if error.kind() != io::ErrorKind::Other + || error.get_ref().is_some() + || !writer.writer.was_error + { + panic!( + "{} returned an unexpected error: {:?}", + core::any::type_name::(), + error + ); + } + } + #[cfg(not(debug_assertions))] + let _ = error; + fmt::Error + })?; + let result = writer.actually_flush(); + if result.is_err() { + writer.writer.assert_was_error::(); + } + result + } +} + +struct ErrorTrackingWriter { + writer: W, + #[cfg(debug_assertions)] + was_error: bool, +} + +impl ErrorTrackingWriter { + fn new(writer: W) -> Self { + Self { + writer, + #[cfg(debug_assertions)] + was_error: false, + } + } + + #[track_caller] + fn assert_no_error(&self, fun: &str) { + #[cfg(debug_assertions)] + { + if self.was_error { + panic!("`{}` called on errored writer", fun); + } + } + #[cfg(not(debug_assertions))] + let _ = fun; + } + + fn assert_was_error(&self) { + #[cfg(debug_assertions)] + { + if !self.was_error { + panic!("{} returned an error unexpectedly", core::any::type_name::()); + } + } + } + + fn set_error(&mut self, was: bool) { + #[cfg(debug_assertions)] + { + self.was_error |= was; + } + #[cfg(not(debug_assertions))] + let _ = was; + } + + fn check_err(&mut self, result: Result) -> Result { + self.set_error(result.is_err()); + result + } +} + +impl fmt::Write for ErrorTrackingWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.assert_no_error("write_str"); + let result = self.writer.write_str(s); + self.check_err(result) + } + + fn write_char(&mut self, c: char) -> fmt::Result { + self.assert_no_error("write_char"); + let result = self.writer.write_char(c); + self.check_err(result) + } +} + +struct IoWrapper<'a, W: fmt::Write, E: EncodeBytes> { + writer: ErrorTrackingWriter<&'a mut W>, + encoder: E, +} + +impl<'a, W: fmt::Write, E: EncodeBytes> IoWrapper<'a, W, E> { + fn new(writer: &'a mut W, encoder: E) -> Self { + IoWrapper { writer: ErrorTrackingWriter::new(writer), encoder } + } + + fn actually_flush(&mut self) -> fmt::Result { self.encoder.flush(&mut self.writer) } +} + +impl Write for IoWrapper<'_, W, E> { + fn write(&mut self, bytes: &[u8]) -> io::Result { + match self.encoder.encode_chunk(&mut self.writer, bytes) { + Ok(()) => Ok(bytes.len()), + Err(fmt::Error) => { + self.writer.assert_was_error::(); + Err(io::Error::from(io::ErrorKind::Other)) + } + } + } + // we intentionally ignore flushes because we will do a single flush at the end. + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +/// Provides an instance of byte-to-string encoder. +/// +/// This is basically a type constructor used in places where value arguments are not accepted. +/// Such as the generic `serialize`. +pub trait ByteEncoder: Default { + /// The encoder state. + type Encoder: EncodeBytes + From; +} + +/// Transforms given bytes and writes to the writer. +/// +/// The encoder is allowed to be buffered (and probably should be). +/// The design passing writer each time bypasses the need for GAT. +pub trait EncodeBytes { + /// Transform the provided slice and write to the writer. + /// + /// This is similar to the `write_all` method on `io::Write`. + fn encode_chunk(&mut self, writer: &mut W, bytes: &[u8]) -> fmt::Result; + + /// Write data in buffer (if any) to the writer. + fn flush(&mut self, writer: &mut W) -> fmt::Result; +} + +/// Provides an instance of string-to-byte decoder. +/// +/// This is basically a type constructor used in places where value arguments are not accepted. +/// Such as the generic `serialize`. +pub trait ByteDecoder<'a> { + /// Error returned when decoder can't be created. + /// + /// This is typically returned when string length is invalid. + type InitError: IntoDeError + fmt::Debug; + + /// Error returned when decoding fails. + /// + /// This is typically returned when the input string contains malformed chars. + type DecodeError: IntoDeError + fmt::Debug; + + /// The decoder state. + type Decoder: Iterator>; + + /// Constructs a new decoder from string. + fn from_str(s: &'a str) -> Result; +} + +/// Converts error into a type implementing `serde::de::Error` +pub trait IntoDeError { + /// Performs the conversion. + fn into_de_error(self) -> E; +} + +struct BinWriter { + serializer: S, + error: Option, +} + +impl Write for BinWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { self.write_all(buf).map(|_| buf.len()) } + + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + for byte in buf { + if let Err(error) = self.serializer.serialize_element(byte) { + self.error = Some(error); + return Err(io::ErrorKind::Other.into()); + } + } + Ok(()) + } + + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +struct DisplayExpected(D); + +impl serde::de::Expected for DisplayExpected { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, formatter) + } +} + +// not a trait impl because we panic on some variants +fn consensus_error_into_serde(error: ParseError) -> E { + match error { + ParseError::MissingData => E::custom("missing data (early end of file or slice too short)"), + ParseError::OversizedVectorAllocation { requested, max } => E::custom(format_args!( + "the requested allocation of {} items exceeds maximum of {}", + requested, max + )), + ParseError::InvalidChecksum { expected, actual } => E::invalid_value( + Unexpected::Bytes(&actual), + &DisplayExpected(format_args!( + "checksum {:02x}{:02x}{:02x}{:02x}", + expected[0], expected[1], expected[2], expected[3] + )), + ), + ParseError::NonMinimalCompactSize => + E::custom(format_args!("compact size was not encoded minimally")), + ParseError::ParseFailed(msg) => E::custom(msg), + ParseError::UnsupportedSegwitFlag(flag) => + E::invalid_value(Unexpected::Unsigned(flag.into()), &"segwit version 1 flag"), + ParseError::Witness(e) => E::custom(e), + } +} + +impl DecodeError +where + E: serde::de::Error, +{ + fn unify(self) -> E { + match self { + Self::Other(error) => error, + Self::Unconsumed => E::custom(format_args!("got more bytes than expected")), + Self::Parse(e) => consensus_error_into_serde(e), + } + } +} + +impl IntoDeError for DecodeError +where + E: IntoDeError, +{ + fn into_de_error(self) -> DE { + match self { + Self::Other(error) => error.into_de_error(), + Self::Unconsumed => DE::custom(format_args!("got more bytes than expected")), + Self::Parse(e) => consensus_error_into_serde(e), + } + } +} + +/// Helper for `#[serde(with = "")]`. +/// +/// To (de)serialize a field using consensus encoding you can write e.g.: +/// +/// ``` +/// # use serde::{Serialize, Deserialize}; +/// use bitcoin::Transaction; +/// use bitcoin::consensus; +/// +/// #[derive(Serialize, Deserialize)] +/// pub struct MyStruct { +/// #[serde(with = "consensus::serde::With::")] +/// tx: Transaction, +/// } +/// ``` +pub struct With(PhantomData); + +impl With { + /// Serializes the value as consensus-encoded + pub fn serialize( + value: &T, + serializer: S, + ) -> Result + where + E: ByteEncoder, + { + if serializer.is_human_readable() { + serializer.collect_str(&DisplayWrapper::<'_, _, E>(value, Default::default())) + } else { + let serializer = serializer.serialize_seq(None)?; + let mut writer = BinWriter { serializer, error: None }; + + let result = value.consensus_encode(&mut writer); + match (result, writer.error) { + (Ok(_), None) => writer.serializer.end(), + (Ok(_), Some(error)) => + panic!("{} silently ate an I/O error: {:?}", core::any::type_name::(), error), + (Err(io_error), Some(ser_error)) + if io_error.kind() == io::ErrorKind::Other && io_error.get_ref().is_none() => + Err(ser_error), + (Err(io_error), ser_error) => panic!( + "{} returned an unexpected I/O error: {:?} serialization error: {:?}", + core::any::type_name::(), + io_error, + ser_error + ), + } + } + } + + /// Deserializes the value as consensus-encoded + pub fn deserialize<'d, T: Decodable, D: Deserializer<'d>>( + deserializer: D, + ) -> Result + where + for<'a> E: ByteDecoder<'a>, + { + if deserializer.is_human_readable() { + deserializer.deserialize_str(HRVisitor::<_, E>(Default::default())) + } else { + deserializer.deserialize_seq(BinVisitor(Default::default())) + } + } +} + +struct HRVisitor ByteDecoder<'a>>(PhantomData (T, D)>); + +impl ByteDecoder<'a>> Visitor<'_> for HRVisitor { + type Value = T; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("bytes encoded as a hex string") + } + + fn visit_str(self, s: &str) -> Result { + let decoder = D::from_str(s).map_err(IntoDeError::into_de_error)?; + IterReader::new(decoder).decode().map_err(IntoDeError::into_de_error) + } +} + +struct BinVisitor(PhantomData T>); + +impl<'de, T: Decodable> Visitor<'de> for BinVisitor { + type Value = T; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence of bytes") + } + + fn visit_seq>(self, s: S) -> Result { + IterReader::new(SeqIterator(s, Default::default())).decode().map_err(DecodeError::unify) + } +} + +struct SeqIterator<'a, S: serde::de::SeqAccess<'a>>(S, PhantomData<&'a ()>); + +impl<'a, S: serde::de::SeqAccess<'a>> Iterator for SeqIterator<'a, S> { + type Item = Result; + + fn next(&mut self) -> Option { self.0.next_element::().transpose() } +} diff --git a/bitcoin/src/consensus_validation.rs b/bitcoin/src/consensus_validation.rs new file mode 100644 index 000000000..a998e6024 --- /dev/null +++ b/bitcoin/src/consensus_validation.rs @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Transaction and script validation. +//! +//! Relies on the `bitcoinconsensus` crate that uses Bitcoin Core libconsensus to perform validation. + +use core::convert::Infallible; +use core::fmt; + +use internals::write_err; + +use crate::amount::Amount; +use crate::consensus::encode; +#[cfg(doc)] +use crate::consensus_validation; +use crate::internal_macros::define_extension_trait; +use crate::script::ScriptPubKey; +use crate::transaction::{OutPoint, Transaction, TxOut}; + +/// Verifies spend of an input script. +/// +/// Shorthand for [`consensus_validation::verify_script_with_flags`] with flag +/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]. +/// +/// # Parameters +/// +/// * `index` - the input index in spending which is spending this transaction. +/// * `amount` - the amount this script guards. +/// * `spending_tx` - the transaction that attempts to spend the output holding this script. +/// +/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html +pub fn verify_script( + script: &ScriptPubKey, + index: usize, + amount: Amount, + spending_tx: &[u8], +) -> Result<(), BitcoinconsensusError> { + verify_script_with_flags( + script, + index, + amount, + spending_tx, + bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT, + ) +} + +/// Verifies spend of an input script. +/// +/// # Parameters +/// +/// * `index` - the input index in spending which is spending this transaction. +/// * `amount` - the amount this script guards. +/// * `spending_tx` - the transaction that attempts to spend the output holding this script. +/// * `flags` - the verification flags, see [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`] and similar. +/// +/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html +pub fn verify_script_with_flags>( + script: &ScriptPubKey, + index: usize, + amount: Amount, + spending_tx: &[u8], + flags: F, +) -> Result<(), BitcoinconsensusError> { + bitcoinconsensus::verify_with_flags( + script.as_bytes(), + amount.to_sat(), + spending_tx, + None, + index, + flags.into(), + ) + .map_err(BitcoinconsensusError) +} + +/// Verifies that this transaction is able to spend its inputs. +/// +/// Shorthand for [`consensus_validation::verify_transaction_with_flags`] with flag +/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]. +/// +/// The `spent` closure should not return the same [`TxOut`] twice! +/// +/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html +pub fn verify_transaction(tx: &Transaction, spent: S) -> Result<(), TxVerifyError> +where + S: FnMut(&OutPoint) -> Option, +{ + verify_transaction_with_flags(tx, spent, bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT) +} + +/// Verifies that this transaction is able to spend its inputs. +/// +/// The `spent` closure should not return the same [`TxOut`] twice! +pub fn verify_transaction_with_flags( + tx: &Transaction, + mut spent: S, + flags: F, +) -> Result<(), TxVerifyError> +where + S: FnMut(&OutPoint) -> Option, + F: Into, +{ + let serialized_tx = encode::serialize(tx); + let flags: u32 = flags.into(); + for (idx, input) in tx.inputs.iter().enumerate() { + if let Some(output) = spent(&input.previous_output) { + verify_script_with_flags( + &output.script_pubkey, + idx, + output.amount, + serialized_tx.as_slice(), + flags, + )?; + } else { + return Err(TxVerifyError::UnknownSpentOutput(input.previous_output)); + } + } + Ok(()) +} + +define_extension_trait! { + /// Extension functionality to add validation support to the [`ScriptPubKey`] type. + pub trait ScriptPubKeyExt impl for ScriptPubKey { + /// Verifies spend of an input script. + /// + /// Shorthand for [`Self::verify_with_flags`] with flag [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]. + /// + /// # Parameters + /// + /// * `index` - the input index in spending which is spending this transaction. + /// * `amount` - the amount this script guards. + /// * `spending_tx` - the transaction that attempts to spend the output holding this script. + /// + /// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html + fn verify( + &self, + index: usize, + amount: Amount, + spending_tx: &[u8], + ) -> Result<(), BitcoinconsensusError> { + verify_script(self, index, amount, spending_tx) + } + + /// Verifies spend of an input script. + /// + /// # Parameters + /// + /// * `index` - the input index in spending which is spending this transaction. + /// * `amount` - the amount this script guards. + /// * `spending_tx` - the transaction that attempts to spend the output holding this script. + /// * `flags` - the verification flags, see [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`] and similar. + /// + /// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html + fn verify_with_flags( + &self, + index: usize, + amount: Amount, + spending_tx: &[u8], + flags: impl Into, + ) -> Result<(), BitcoinconsensusError> { + verify_script_with_flags(self, index, amount, spending_tx, flags) + } + } +} + +/// Extension functionality for the [`Transaction`] type. +pub trait TransactionExt: sealed::Sealed { + /// Verifies that this transaction is able to spend its inputs. + /// + /// Shorthand for [`Self::verify_with_flags`] with flag [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]. + /// + /// The `spent` closure should not return the same [`TxOut`] twice! + /// + /// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html + fn verify(&self, spent: S) -> Result<(), TxVerifyError> + where + S: FnMut(&OutPoint) -> Option; + + /// Verifies that this transaction is able to spend its inputs. + /// + /// The `spent` closure should not return the same [`TxOut`] twice! + fn verify_with_flags(&self, spent: S, flags: F) -> Result<(), TxVerifyError> + where + S: FnMut(&OutPoint) -> Option, + F: Into; +} + +impl TransactionExt for Transaction { + fn verify(&self, spent: S) -> Result<(), TxVerifyError> + where + S: FnMut(&OutPoint) -> Option, + { + verify_transaction(self, spent) + } + + fn verify_with_flags(&self, spent: S, flags: F) -> Result<(), TxVerifyError> + where + S: FnMut(&OutPoint) -> Option, + F: Into, + { + verify_transaction_with_flags(self, spent, flags) + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::ScriptPubKey {} + impl Sealed for super::Transaction {} +} + +/// Wrapped error from `bitcoinconsensus`. +// We do this for two reasons: +// 1. We don't want the error to be part of the public API because we do not want to expose the +// unusual versioning used in `bitcoinconsensus` to users of `rust-bitcoin`. +// 2. We want to implement `std::error::Error` if the "std" feature is enabled in `rust-bitcoin` but +// not in `bitcoinconsensus`. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct BitcoinconsensusError(bitcoinconsensus::Error); + +impl fmt::Display for BitcoinconsensusError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "bitcoinconsensus error"; &self.0) + } +} + +#[cfg(all(feature = "std", feature = "bitcoinconsensus"))] +impl std::error::Error for BitcoinconsensusError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} + +/// An error during transaction validation. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum TxVerifyError { + /// Error validating the script with bitcoinconsensus library. + ScriptVerification(BitcoinconsensusError), + /// Can not find the spent output. + UnknownSpentOutput(OutPoint), +} + +impl From for TxVerifyError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for TxVerifyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ScriptVerification(ref e) => + write_err!(f, "bitcoinconsensus verification failed"; e), + Self::UnknownSpentOutput(ref p) => write!(f, "unknown spent output: {}", p), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TxVerifyError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::ScriptVerification(ref e) => Some(e), + Self::UnknownSpentOutput(_) => None, + } + } +} + +impl From for TxVerifyError { + fn from(e: BitcoinconsensusError) -> Self { Self::ScriptVerification(e) } +} diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs new file mode 100644 index 000000000..9aada52fa --- /dev/null +++ b/bitcoin/src/crypto/ecdsa.rs @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! ECDSA Bitcoin signatures. +//! +//! This module provides ECDSA signatures used by Bitcoin that can be roundtrip (de)serialized. + +use core::borrow::Borrow; +use core::convert::Infallible; +use core::ops::Deref; +use core::str::FromStr; +use core::{fmt, iter}; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hex::FromHex; +use internals::{impl_to_hex_from_lower_hex, write_err}; +use io::Write; + +use crate::prelude::{DisplayHex, Vec}; +#[cfg(doc)] +use crate::script::ScriptPubKeyBufExt as _; +use crate::sighash::{EcdsaSighashType, NonStandardSighashTypeError}; + +const MAX_SIG_LEN: usize = 73; + +/// An ECDSA signature with the corresponding hash type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Signature { + /// The underlying ECDSA Signature. + pub signature: secp256k1::ecdsa::Signature, + /// The corresponding hash type. + pub sighash_type: EcdsaSighashType, +} + +impl Signature { + /// Constructs a new ECDSA Bitcoin signature for [`EcdsaSighashType::All`]. + pub fn sighash_all(signature: secp256k1::ecdsa::Signature) -> Self { + Self { signature, sighash_type: EcdsaSighashType::All } + } + + /// Deserializes from slice following the standardness rules for [`EcdsaSighashType`]. + pub fn from_slice(sl: &[u8]) -> Result { + let (sighash_type, sig) = sl.split_last().ok_or(DecodeError::EmptySignature)?; + let sighash_type = EcdsaSighashType::from_standard(*sighash_type as u32)?; + let signature = + secp256k1::ecdsa::Signature::from_der(sig).map_err(DecodeError::Secp256k1)?; + Ok(Self { signature, sighash_type }) + } + + /// Serializes an ECDSA signature (inner secp256k1 signature in DER format). + /// + /// This does **not** perform extra heap allocation. + pub fn serialize(&self) -> SerializedSignature { + let mut buf = [0u8; MAX_SIG_LEN]; + let signature = self.signature.serialize_der(); + buf[..signature.len()].copy_from_slice(&signature); + buf[signature.len()] = self.sighash_type as u8; + SerializedSignature { data: buf, len: signature.len() + 1 } + } + + /// Serializes an ECDSA signature (inner secp256k1 signature in DER format) into `Vec`. + /// + /// Note: this performs an extra heap allocation, you might prefer the + /// [`serialize`](Self::serialize) method instead. + pub fn to_vec(self) -> Vec { + self.signature + .serialize_der() + .iter() + .copied() + .chain(iter::once(self.sighash_type as u8)) + .collect() + } + + /// Serializes an ECDSA signature (inner secp256k1 signature in DER format) to a `writer`. + #[inline] + pub fn serialize_to_writer(&self, writer: &mut W) -> Result<(), io::Error> { + let sig = self.serialize(); + sig.write_to(writer) + } +} + +impl fmt::Display for Signature { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.signature.serialize_der().as_hex(), f)?; + fmt::LowerHex::fmt(&[self.sighash_type as u8].as_hex(), f) + } +} + +impl FromStr for Signature { + type Err = ParseSignatureError; + + fn from_str(s: &str) -> Result { + let bytes = Vec::from_hex(s)?; + Ok(Self::from_slice(&bytes)?) + } +} + +/// Holds signature serialized in-line (not in `Vec`). +/// +/// This avoids allocation and allows proving maximum size of the signature (73 bytes). +/// The type can be used largely as a byte slice. It implements all standard traits one would +/// expect and has familiar methods. +/// +/// However, the usual use case is to push it into a script. This can be done directly passing it +/// into [`push_slice`](crate::script::ScriptBufExt::push_slice). +#[derive(Copy, Clone)] +pub struct SerializedSignature { + data: [u8; MAX_SIG_LEN], + len: usize, +} + +impl SerializedSignature { + /// Constructs a new SerializedSignature from a Signature. + /// + /// In other words this serializes a `Signature` into a `SerializedSignature`. + #[inline] + pub fn from_signature(sig: Signature) -> Self { sig.serialize() } + + /// Converts the serialized signature into the [`Signature`] struct. + /// + /// In other words this deserializes the `SerializedSignature`. + #[inline] + pub fn to_signature(self) -> Result { + Signature::from_slice(&self) + } + + /// Returns the length of the serialized signature data. + #[inline] + // `len` is never 0, so `is_empty` would always return `false`. + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { self.len } + + /// Returns an iterator over bytes of the signature. + #[inline] + pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() } + + /// Writes this serialized signature to a `writer`. + #[inline] + pub fn write_to(&self, writer: &mut W) -> Result<(), io::Error> { + writer.write_all(self) + } +} + +impl fmt::Debug for SerializedSignature { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) } +} + +impl fmt::Display for SerializedSignature { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) } +} + +impl fmt::LowerHex for SerializedSignature { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::LowerHex::fmt(&(**self).as_hex(), f) + } +} +impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignature| signature.len + * 2); + +impl fmt::UpperHex for SerializedSignature { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::UpperHex::fmt(&(**self).as_hex(), f) + } +} + +impl PartialEq for SerializedSignature { + #[inline] + fn eq(&self, other: &Self) -> bool { **self == **other } +} + +impl PartialEq<[u8]> for SerializedSignature { + #[inline] + fn eq(&self, other: &[u8]) -> bool { **self == *other } +} + +impl PartialEq for [u8] { + #[inline] + fn eq(&self, other: &SerializedSignature) -> bool { *self == **other } +} + +impl PartialOrd for SerializedSignature { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for SerializedSignature { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { (**self).cmp(&**other) } +} + +impl PartialOrd<[u8]> for SerializedSignature { + fn partial_cmp(&self, other: &[u8]) -> Option { + (**self).partial_cmp(other) + } +} + +impl PartialOrd for [u8] { + fn partial_cmp(&self, other: &SerializedSignature) -> Option { + self.partial_cmp(&**other) + } +} + +impl Eq for SerializedSignature {} + +impl core::hash::Hash for SerializedSignature { + fn hash(&self, state: &mut H) { core::hash::Hash::hash(&**self, state) } +} + +impl AsRef<[u8]> for SerializedSignature { + #[inline] + fn as_ref(&self) -> &[u8] { &self.data[..self.len] } +} + +impl Borrow<[u8]> for SerializedSignature { + #[inline] + fn borrow(&self) -> &[u8] { &self.data[..self.len] } +} + +impl Deref for SerializedSignature { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &Self::Target { &self.data[..self.len] } +} + +impl<'a> IntoIterator for &'a SerializedSignature { + type IntoIter = core::slice::Iter<'a, u8>; + type Item = &'a u8; + + #[inline] + fn into_iter(self) -> Self::IntoIter { (**self).iter() } +} + +/// Error encountered while parsing an ECDSA signature from a byte slice. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum DecodeError { + /// Non-standard sighash type. + SighashType(NonStandardSighashTypeError), + /// Signature was empty. + EmptySignature, + /// A secp256k1 error. + Secp256k1(secp256k1::Error), +} + +impl From for DecodeError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::SighashType(ref e) => write_err!(f, "non-standard signature hash type"; e), + Self::EmptySignature => write!(f, "empty ECDSA signature"), + Self::Secp256k1(ref e) => write_err!(f, "secp256k1"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Secp256k1(ref e) => Some(e), + Self::SighashType(ref e) => Some(e), + Self::EmptySignature => None, + } + } +} + +impl From for DecodeError { + fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) } +} + +impl From for DecodeError { + fn from(e: NonStandardSighashTypeError) -> Self { Self::SighashType(e) } +} + +/// Error encountered while parsing an ECDSA signature from a string. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ParseSignatureError { + /// Hex string decoding error. + Hex(hex::HexToBytesError), + /// Signature byte slice decoding error. + Decode(DecodeError), +} + +impl From for ParseSignatureError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParseSignatureError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Hex(ref e) => write_err!(f, "signature hex decoding error"; e), + Self::Decode(ref e) => write_err!(f, "signature byte slice decoding error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseSignatureError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Hex(ref e) => Some(e), + Self::Decode(ref e) => Some(e), + } + } +} + +impl From for ParseSignatureError { + fn from(e: hex::HexToBytesError) -> Self { Self::Hex(e) } +} + +impl From for ParseSignatureError { + fn from(e: DecodeError) -> Self { Self::Decode(e) } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Signature { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + // The valid range of r and s should be between 0 and n-1 where + // n = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141 + let high_min = 0x0u128; + let high_max = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEu128; + let low_min = 0x0u128; + let low_max = 0xBAAEDCE6AF48A03BBFD25E8CD0364140u128; + + // Equally weight the chances of getting a minimum value for a signature, maximum value for + // a signature, and an arbitrary valid signature + let choice = u.int_in_range(0..=2)?; + let (high, low) = match choice { + 0 => (high_min, low_min), + 1 => (high_max, low_max), + _ => (u.int_in_range(high_min..=high_max)?, u.int_in_range(low_min..=low_max)?), + }; + + // We can use the same bytes for r and s since they're just arbitrary values + let mut bytes: [u8; 32] = [0; 32]; + bytes[..16].copy_from_slice(&high.to_be_bytes()); + bytes[16..].copy_from_slice(&low.to_be_bytes()); + + let mut signature_bytes: [u8; 64] = [0; 64]; + signature_bytes[..32].copy_from_slice(&bytes); + signature_bytes[32..].copy_from_slice(&bytes); + + Ok(Self { + signature: secp256k1::ecdsa::Signature::from_compact(&signature_bytes).unwrap(), + sighash_type: EcdsaSighashType::arbitrary(u)?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_SIGNATURE_HEX: &str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"; + + #[test] + fn write_serialized_signature() { + let sig = Signature { + signature: secp256k1::ecdsa::Signature::from_str(TEST_SIGNATURE_HEX).unwrap(), + sighash_type: EcdsaSighashType::All, + }; + + let mut buf = vec![]; + sig.serialize_to_writer(&mut buf).expect("write failed"); + + assert_eq!(sig.to_vec(), buf) + } + + #[test] + fn iterate_serialized_signature() { + let sig = Signature { + signature: secp256k1::ecdsa::Signature::from_str(TEST_SIGNATURE_HEX).unwrap(), + sighash_type: EcdsaSighashType::All, + }; + + assert_eq!(sig.serialize().iter().copied().collect::>(), sig.to_vec()); + } +} diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs new file mode 100644 index 000000000..30e0b87b6 --- /dev/null +++ b/bitcoin/src/crypto/key.rs @@ -0,0 +1,1835 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin keys. +//! +//! This module provides keys used in Bitcoin that can be roundtrip +//! (de)serialized. + +use core::convert::Infallible; +use core::fmt::{self, Write as _}; +use core::ops; +use core::str::FromStr; + +use hashes::hash160; +use hex::{FromHex, HexToArrayError}; +use internals::array::ArrayExt; +use internals::array_vec::ArrayVec; +use internals::{impl_to_hex_from_lower_hex, write_err}; +use io::{Read, Write}; + +use crate::crypto::ecdsa; +use crate::internal_macros::impl_asref_push_bytes; +use crate::network::NetworkKind; +use crate::prelude::{DisplayHex, String, Vec}; +use crate::script::{self, WitnessScriptBuf}; +use crate::taproot::{TapNodeHash, TapTweakHash}; + +#[rustfmt::skip] // Keep public re-exports separate. +pub use secp256k1::{constants, Keypair, Parity, Verification}; +#[cfg(all(feature = "rand", feature = "std"))] +pub use secp256k1::rand; +pub use serialized_x_only::SerializedXOnlyPublicKey; + +/// A Bitcoin Schnorr X-only public key used for BIP-0340 signatures. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct XOnlyPublicKey(secp256k1::XOnlyPublicKey); + +impl XOnlyPublicKey { + /// Constructs a new x-only public key from the provided generic secp256k1 x-only public key. + pub fn new(key: impl Into) -> Self { Self(key.into()) } + + /// Constructs an x-only public key from a keypair. + /// + /// Returns the x-only public key and the parity of the full public key. + #[inline] + pub fn from_keypair(keypair: &Keypair) -> (Self, Parity) { + let (xonly, parity) = secp256k1::XOnlyPublicKey::from_keypair(keypair); + (Self::new(xonly), parity) + } + + /// Constructs an x-only public key from a 32-byte x-coordinate. + /// + /// Returns an error if the provided bytes don't represent a valid secp256k1 point x-coordinate. + #[inline] + pub fn from_byte_array( + data: &[u8; constants::SCHNORR_PUBLIC_KEY_SIZE], + ) -> Result { + secp256k1::XOnlyPublicKey::from_byte_array(*data) + .map(Self::new) + .map_err(|_| ParseXOnlyPublicKeyError::InvalidXCoordinate) + } + + /// Returns the inner secp256k1 x-only public key. + #[inline] + pub fn into_inner(self) -> secp256k1::XOnlyPublicKey { self.0 } + + /// Serializes the x-only public key as a byte-encoded x coordinate value (32 bytes). + #[inline] + pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] { self.0.serialize() } + + /// Converts this x-only public key to a full public key given the parity. + #[inline] + pub fn public_key(&self, parity: Parity) -> PublicKey { self.0.public_key(parity).into() } + + /// Verifies that a tweak produced by [`XOnlyPublicKey::add_tweak`] was computed correctly. + /// + /// Should be called on the original untweaked key. Takes the tweaked key and output parity from + /// [`XOnlyPublicKey::add_tweak`] as input. + #[inline] + pub fn tweak_add_check( + &self, + tweaked_key: &Self, + tweaked_parity: Parity, + tweak: secp256k1::Scalar, + ) -> bool { + self.0.tweak_add_check(&tweaked_key.0, tweaked_parity, tweak) + } + + /// Tweaks an [`XOnlyPublicKey`] by adding the generator multiplied with the given tweak to it. + /// + /// # Returns + /// + /// The newly tweaked key plus an opaque type representing the parity of the tweaked key, this + /// should be provided to `tweak_add_check` which can be used to verify a tweak more efficiently + /// than regenerating it and checking equality. + /// + /// # Errors + /// + /// If the resulting key would be invalid. + #[inline] + pub fn add_tweak( + &self, + tweak: &secp256k1::Scalar, + ) -> Result<(Self, Parity), TweakXOnlyPublicKeyError> { + match self.0.add_tweak(tweak) { + Ok((xonly, parity)) => Ok((Self(xonly), parity)), + Err(secp256k1::Error::InvalidTweak) => Err(TweakXOnlyPublicKeyError::BadTweak), + Err(secp256k1::Error::InvalidParityValue(_)) => + Err(TweakXOnlyPublicKeyError::ParityError), + Err(_) => Err(TweakXOnlyPublicKeyError::ResultKeyInvalid), + } + } +} + +impl FromStr for XOnlyPublicKey { + type Err = ParseXOnlyPublicKeyError; + fn from_str(s: &str) -> Result { + secp256k1::XOnlyPublicKey::from_str(s) + .map(Self::from) + .map_err(|_| ParseXOnlyPublicKeyError::InvalidXCoordinate) + } +} + +impl From for XOnlyPublicKey { + fn from(pk: secp256k1::XOnlyPublicKey) -> Self { Self::new(pk) } +} + +impl From for XOnlyPublicKey { + fn from(pk: secp256k1::PublicKey) -> Self { Self::new(pk) } +} + +impl fmt::LowerHex for XOnlyPublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } +} +// Allocate for serialized size +impl_to_hex_from_lower_hex!(XOnlyPublicKey, |_| constants::SCHNORR_PUBLIC_KEY_SIZE * 2); + +impl fmt::Display for XOnlyPublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } +} + +/// A Bitcoin ECDSA public key. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PublicKey { + /// Whether this public key should be serialized as compressed. + pub compressed: bool, + /// The actual ECDSA key. + pub inner: secp256k1::PublicKey, +} + +impl PublicKey { + /// Constructs a new compressed ECDSA public key from the provided generic secp256k1 public key. + pub fn new(key: impl Into) -> Self { + Self { compressed: true, inner: key.into() } + } + + /// Constructs a new uncompressed (legacy) ECDSA public key from the provided generic secp256k1 + /// public key. + pub fn new_uncompressed(key: impl Into) -> Self { + Self { compressed: false, inner: key.into() } + } + + fn with_serialized R>(&self, f: F) -> R { + if self.compressed { + f(&self.inner.serialize()) + } else { + f(&self.inner.serialize_uncompressed()) + } + } + + /// Returns bitcoin 160-bit hash of the public key. + pub fn pubkey_hash(&self) -> PubkeyHash { + PubkeyHash(self.with_serialized(hash160::Hash::hash)) + } + + /// Returns bitcoin 160-bit hash of the public key for witness program + pub fn wpubkey_hash(&self) -> Result { + if self.compressed { + Ok(WPubkeyHash::from_byte_array( + hash160::Hash::hash(&self.inner.serialize()).to_byte_array(), + )) + } else { + Err(UncompressedPublicKeyError) + } + } + + /// Returns the script code used to spend a P2WPKH input. + /// + /// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and + /// should not be used as one. It is a special template defined in BIP 143 which is used + /// in place of a witness script for purposes of sighash computation. + pub fn p2wpkh_script_code(&self) -> Result { + let key = CompressedPublicKey::try_from(*self)?; + Ok(key.p2wpkh_script_code()) + } + + /// Writes the public key into a writer. + pub fn write_into(&self, writer: &mut W) -> Result<(), io::Error> { + self.with_serialized(|bytes| writer.write_all(bytes)) + } + + /// Reads the public key from a reader. + /// + /// This internally reads the first byte before reading the rest, so + /// use of a `BufReader` is recommended. + pub fn read_from(reader: &mut R) -> Result { + let mut bytes = [0; 65]; + + reader.read_exact(&mut bytes[0..1])?; + let bytes = if bytes[0] < 4 { &mut bytes[..33] } else { &mut bytes[..65] }; + + reader.read_exact(&mut bytes[1..])?; + Self::from_slice(bytes).map_err(|e| { + // Need a static string for no-std io + #[cfg(feature = "std")] + let reason = e; + #[cfg(not(feature = "std"))] + let reason = match e { + FromSliceError::Secp256k1(_) => "secp256k1 error", + FromSliceError::InvalidKeyPrefix(_) => "invalid key prefix", + FromSliceError::InvalidLength(_) => "invalid length", + }; + io::Error::new(io::ErrorKind::InvalidData, reason) + }) + } + + /// Serializes the public key to bytes. + #[deprecated(since = "TBD", note = "use to_vec instead")] + pub fn to_bytes(self) -> Vec { self.to_vec() } + + /// Serializes the public key to bytes. + pub fn to_vec(self) -> Vec { + let mut buf = Vec::new(); + self.write_into(&mut buf).expect("vecs don't error"); + buf + } + + /// Serializes the public key into a `SortKey`. + /// + /// `SortKey` is not too useful by itself, but it can be used to sort a + /// `[PublicKey]` slice using `sort_unstable_by_key`, `sort_by_cached_key`, + /// `sort_by_key`, or any of the other `*_by_key` methods on slice. + /// Pass the method into the sort method directly. (ie. `PublicKey::to_sort_key`) + /// + /// This method of sorting is in line with Bitcoin Core's implementation of + /// sorting keys for output descriptors such as `sortedmulti()`. + /// + /// If every `PublicKey` in the slice is `compressed == true` then this will sort + /// the keys in a + /// [BIP-0067](https://github.com/bitcoin/bips/blob/master/bip-0067.mediawiki) + /// compliant way. + /// + /// # Example: Using with `sort_unstable_by_key` + /// + /// ```rust + /// use bitcoin::PublicKey; + /// + /// let pk = |s: &str| s.parse::().unwrap(); + /// + /// let mut unsorted = [ + /// pk("04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc38e98ac269ffe028345c31ac8d0a365f29c8f7e7cfccac72f84e1acd02bc554f35"), + /// pk("038f47dcd43ba6d97fc9ed2e3bba09b175a45fac55f0683e8cf771e8ced4572354"), + /// pk("028bde91b10013e08949a318018fedbd896534a549a278e220169ee2a36517c7aa"), + /// pk("04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc3816753d96001fd7cba3ce5372f5c9a0d63708183033538d07b1e532fc43aaacfa"), + /// pk("032b8324c93575034047a52e9bca05a46d8347046b91a032eff07d5de8d3f2730b"), + /// pk("045d753414fa292ea5b8f56e39cfb6a0287b2546231a5cb05c4b14ab4b463d171f5128148985b23eccb1e2905374873b1f09b9487f47afa6b1f2b0083ac8b4f7e8"), + /// pk("0234dd69c56c36a41230d573d68adeae0030c9bc0bf26f24d3e1b64c604d293c68"), + /// ]; + /// let sorted = [ + /// // These first 4 keys are in a BIP-0067 compatible sorted order + /// // (since they are compressed) + /// pk("0234dd69c56c36a41230d573d68adeae0030c9bc0bf26f24d3e1b64c604d293c68"), + /// pk("028bde91b10013e08949a318018fedbd896534a549a278e220169ee2a36517c7aa"), + /// pk("032b8324c93575034047a52e9bca05a46d8347046b91a032eff07d5de8d3f2730b"), + /// pk("038f47dcd43ba6d97fc9ed2e3bba09b175a45fac55f0683e8cf771e8ced4572354"), + /// // Uncompressed keys are not BIP-0067 compliant, but are sorted + /// // after compressed keys in Bitcoin Core using `sortedmulti()` + /// pk("045d753414fa292ea5b8f56e39cfb6a0287b2546231a5cb05c4b14ab4b463d171f5128148985b23eccb1e2905374873b1f09b9487f47afa6b1f2b0083ac8b4f7e8"), + /// pk("04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc3816753d96001fd7cba3ce5372f5c9a0d63708183033538d07b1e532fc43aaacfa"), + /// pk("04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc38e98ac269ffe028345c31ac8d0a365f29c8f7e7cfccac72f84e1acd02bc554f35"), + /// ]; + /// + /// unsorted.sort_unstable_by_key(|k| PublicKey::to_sort_key(*k)); + /// + /// assert_eq!(unsorted, sorted); + /// ``` + pub fn to_sort_key(self) -> SortKey { + if self.compressed { + let buf = ArrayVec::from_slice(&self.inner.serialize()); + SortKey(buf) + } else { + let buf = ArrayVec::from_slice(&self.inner.serialize_uncompressed()); + SortKey(buf) + } + } + + /// Deserializes a public key from a slice. + pub fn from_slice(data: &[u8]) -> Result { + let compressed = match data.len() { + 33 => true, + 65 => false, + len => { + return Err(FromSliceError::InvalidLength(len)); + } + }; + + if !compressed && data[0] != 0x04 { + return Err(FromSliceError::InvalidKeyPrefix(data[0])); + } + + Ok(Self { compressed, inner: secp256k1::PublicKey::from_slice(data)? }) + } + + /// Computes the public key as supposed to be used with this secret. + pub fn from_private_key( + sk: PrivateKey, + ) -> Self { + sk.public_key() + } + + /// Checks that `sig` is a valid ECDSA signature for `msg` using this public key. + pub fn verify( + &self, + msg: secp256k1::Message, + sig: ecdsa::Signature, + ) -> Result<(), secp256k1::Error> { + secp256k1::ecdsa::verify(&sig.signature, msg, &self.inner) + } +} + +impl From for PublicKey { + fn from(pk: secp256k1::PublicKey) -> Self { Self::new(pk) } +} + +impl From for XOnlyPublicKey { + fn from(pk: PublicKey) -> Self { Self::new(pk.inner) } +} + +/// An opaque return type for PublicKey::to_sort_key. +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +pub struct SortKey(ArrayVec); + +impl fmt::Display for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.with_serialized(|bytes| fmt::Display::fmt(&bytes.as_hex(), f)) + } +} + +impl FromStr for PublicKey { + type Err = ParsePublicKeyError; + fn from_str(s: &str) -> Result { + match s.len() { + 66 => { + let bytes = <[u8; 33]>::from_hex(s).map_err(|e| match e { + HexToArrayError::InvalidChar(e) => ParsePublicKeyError::InvalidChar(e), + HexToArrayError::InvalidLength(_) => unreachable!("length checked already"), + })?; + Ok(Self::from_slice(&bytes)?) + } + 130 => { + let bytes = <[u8; 65]>::from_hex(s).map_err(|e| match e { + HexToArrayError::InvalidChar(e) => ParsePublicKeyError::InvalidChar(e), + HexToArrayError::InvalidLength(_) => unreachable!("length checked already"), + })?; + Ok(Self::from_slice(&bytes)?) + } + len => Err(ParsePublicKeyError::InvalidHexLength(len)), + } + } +} + +hashes::hash_newtype! { + /// A hash of a public key. + pub struct PubkeyHash(hash160::Hash); + /// SegWit version of a public key hash. + pub struct WPubkeyHash(hash160::Hash); +} + +hashes::impl_hex_for_newtype!(PubkeyHash, WPubkeyHash); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(PubkeyHash, WPubkeyHash); + +impl_asref_push_bytes!(PubkeyHash, WPubkeyHash); + +impl From for PubkeyHash { + fn from(key: PublicKey) -> Self { key.pubkey_hash() } +} + +impl From<&PublicKey> for PubkeyHash { + fn from(key: &PublicKey) -> Self { key.pubkey_hash() } +} + +/// An always-compressed Bitcoin ECDSA public key. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct CompressedPublicKey(pub secp256k1::PublicKey); + +impl CompressedPublicKey { + /// Returns bitcoin 160-bit hash of the public key. + pub fn pubkey_hash(&self) -> PubkeyHash { PubkeyHash(hash160::Hash::hash(&self.to_bytes())) } + + /// Returns bitcoin 160-bit hash of the public key for witness program. + pub fn wpubkey_hash(&self) -> WPubkeyHash { + WPubkeyHash::from_byte_array(hash160::Hash::hash(&self.to_bytes()).to_byte_array()) + } + + /// Returns the script code used to spend a P2WPKH input. + /// + /// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and + /// should not be used as one. It is a special template defined in BIP 143 which is used + /// in place of a witness script for purposes of sighash computation. + pub fn p2wpkh_script_code(&self) -> WitnessScriptBuf { + script::p2wpkh_script_code(self.wpubkey_hash()) + } + + /// Writes the public key into a writer. + pub fn write_into(&self, writer: &mut W) -> Result<(), io::Error> { + writer.write_all(&self.to_bytes()) + } + + /// Reads the public key from a reader. + /// + /// This internally reads the first byte before reading the rest, so + /// use of a `BufReader` is recommended. + pub fn read_from(reader: &mut R) -> Result { + let mut bytes = [0; 33]; + + reader.read_exact(&mut bytes)?; + #[allow(unused_variables)] // e when std not enabled + Self::from_slice(&bytes).map_err(|e| { + // Need a static string for no-std io + #[cfg(feature = "std")] + let reason = e; + #[cfg(not(feature = "std"))] + let reason = "secp256k1 error"; + io::Error::new(io::ErrorKind::InvalidData, reason) + }) + } + + /// Serializes the public key. + /// + /// As the type name suggests, the key is serialized in compressed format. + /// + /// Note that this can be used as a sort key to get BIP-0067-compliant sorting. + /// That's why this type doesn't have the `to_sort_key` method - it would duplicate this one. + pub fn to_bytes(self) -> [u8; 33] { self.0.serialize() } + + /// Deserializes a public key from a slice. + pub fn from_slice(data: &[u8]) -> Result { + secp256k1::PublicKey::from_slice(data).map(CompressedPublicKey) + } + + /// Computes the public key as supposed to be used with this secret. + pub fn from_private_key( + sk: PrivateKey, + ) -> Result { + sk.public_key().try_into() + } + + /// Checks that `sig` is a valid ECDSA signature for `msg` using this public key. + pub fn verify( + &self, + msg: secp256k1::Message, + sig: ecdsa::Signature, + ) -> Result<(), secp256k1::Error> { + Ok(secp256k1::ecdsa::verify(&sig.signature, msg, &self.0)?) + } +} + +impl fmt::Display for CompressedPublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::LowerHex::fmt(&self.to_bytes().as_hex(), f) + } +} + +impl fmt::Debug for CompressedPublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_fmt(format_args!("CompressedPublicKey({})", self)) + } +} + +impl FromStr for CompressedPublicKey { + type Err = ParseCompressedPublicKeyError; + + fn from_str(s: &str) -> Result { + Self::from_slice(&<[u8; 33]>::from_hex(s)?).map_err(Into::into) + } +} + +impl TryFrom for CompressedPublicKey { + type Error = UncompressedPublicKeyError; + + fn try_from(value: PublicKey) -> Result { + if value.compressed { + Ok(Self(value.inner)) + } else { + Err(UncompressedPublicKeyError) + } + } +} + +impl From for PublicKey { + fn from(value: CompressedPublicKey) -> Self { Self::new(value.0) } +} + +impl From for XOnlyPublicKey { + fn from(pk: CompressedPublicKey) -> Self { pk.0.into() } +} + +impl From for PubkeyHash { + fn from(key: CompressedPublicKey) -> Self { key.pubkey_hash() } +} + +impl From<&CompressedPublicKey> for PubkeyHash { + fn from(key: &CompressedPublicKey) -> Self { key.pubkey_hash() } +} + +impl From for WPubkeyHash { + fn from(key: CompressedPublicKey) -> Self { key.wpubkey_hash() } +} + +impl From<&CompressedPublicKey> for WPubkeyHash { + fn from(key: &CompressedPublicKey) -> Self { key.wpubkey_hash() } +} + +/// A Bitcoin ECDSA private key. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct PrivateKey { + /// Whether this private key should be serialized as compressed. + pub compressed: bool, + /// The network kind on which this key should be used. + pub network: NetworkKind, + /// The actual ECDSA key. + pub inner: secp256k1::SecretKey, +} + +impl PrivateKey { + /// Constructs a new compressed ECDSA private key using the secp256k1 algorithm and + /// a secure random number generator. + #[cfg(all(feature = "rand", feature = "std"))] + pub fn generate(network: impl Into) -> Self { + let secret_key = secp256k1::SecretKey::new(&mut rand::rng()); + Self::new(secret_key, network.into()) + } + /// Constructs a new compressed ECDSA private key from the provided generic secp256k1 private key + /// and the specified network. + pub fn new(key: secp256k1::SecretKey, network: impl Into) -> Self { + Self { compressed: true, network: network.into(), inner: key } + } + + /// Constructs a new uncompressed (legacy) ECDSA private key from the provided generic secp256k1 + /// private key and the specified network. + pub fn new_uncompressed(key: secp256k1::SecretKey, network: impl Into) -> Self { + Self { compressed: false, network: network.into(), inner: key } + } + + /// Constructs a new public key from this private key. + pub fn public_key(&self) -> PublicKey { + PublicKey { + compressed: self.compressed, + inner: secp256k1::PublicKey::from_secret_key(&self.inner), + } + } + + /// Serializes the private key to bytes. + #[deprecated(since = "TBD", note = "use to_vec instead")] + pub fn to_bytes(self) -> Vec { self.to_vec() } + + /// Serializes the private key to bytes. + pub fn to_vec(self) -> Vec { self.inner[..].to_vec() } + + /// Deserializes a private key from a byte array. + pub fn from_byte_array( + data: [u8; 32], + network: impl Into, + ) -> Result { + Ok(Self::new(secp256k1::SecretKey::from_secret_bytes(data)?, network)) + } + + /// Deserializes a private key from a slice. + #[deprecated(since = "TBD", note = "use from_byte_array instead")] + pub fn from_slice( + data: &[u8], + network: impl Into, + ) -> Result { + let array = data.try_into().map_err(|_| secp256k1::Error::InvalidSecretKey)?; + Self::from_byte_array(array, network) + } + + /// Formats the private key to WIF format. + #[rustfmt::skip] + pub fn fmt_wif(&self, fmt: &mut dyn fmt::Write) -> fmt::Result { + let mut ret = [0; 34]; + ret[0] = if self.network.is_mainnet() { 128 } else { 239 }; + + ret[1..33].copy_from_slice(&self.inner[..]); + let privkey = if self.compressed { + ret[33] = 1; + base58::encode_check(&ret[..]) + } else { + base58::encode_check(&ret[..33]) + }; + fmt.write_str(&privkey) + } + + /// Gets the WIF encoding of this private key. + pub fn to_wif(self) -> String { + let mut buf = String::new(); + buf.write_fmt(format_args!("{}", self)).unwrap(); + buf.shrink_to_fit(); + buf + } + + /// Parses the WIF encoded private key. + pub fn from_wif(wif: &str) -> Result { + let data = base58::decode_check(wif)?; + + let (compressed, data) = if let Ok(data) = <&[u8; 33]>::try_from(&*data) { + (false, data) + } else if let Ok(data) = <&[u8; 34]>::try_from(&*data) { + let (compressed_flag, data) = data.split_last::<33>(); + if *compressed_flag != 1 { + return Err(InvalidWifCompressionFlagError { invalid: *compressed_flag }.into()); + } + (true, data) + } else { + return Err(InvalidBase58PayloadLengthError { length: data.len() }.into()); + }; + + let (network, key) = data.split_first(); + let network = match *network { + 128 => NetworkKind::Main, + 239 => NetworkKind::Test, + invalid => { + return Err(InvalidAddressVersionError { invalid }.into()); + } + }; + + Ok(Self { compressed, network, inner: secp256k1::SecretKey::from_secret_bytes(*key)? }) + } + + /// Returns a new private key with the negated secret value. + /// + /// The resulting key corresponds to the same x-only public key (identical x-coordinate) + /// but with the opposite y-coordinate parity. This is useful for ensuring compatibility + /// with specific public key formats and BIP-0340 requirements. + #[inline] + pub fn negate(&self) -> Self { + Self { compressed: self.compressed, network: self.network, inner: self.inner.negate() } + } +} + +impl fmt::Display for PrivateKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_wif(f) } +} + +impl FromStr for PrivateKey { + type Err = FromWifError; + fn from_str(s: &str) -> Result { Self::from_wif(s) } +} + +impl ops::Index for PrivateKey { + type Output = [u8]; + fn index(&self, _: ops::RangeFull) -> &[u8] { &self.inner[..] } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for PrivateKey { + fn serialize(&self, s: S) -> Result { + s.collect_str(self) + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for PrivateKey { + fn deserialize>(d: D) -> Result { + struct WifVisitor; + + impl serde::de::Visitor<'_> for WifVisitor { + type Value = PrivateKey; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("an ASCII WIF string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + if let Ok(s) = core::str::from_utf8(v) { + s.parse::().map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + v.parse::().map_err(E::custom) + } + } + + d.deserialize_str(WifVisitor) + } +} + +#[cfg(feature = "serde")] +#[allow(clippy::collapsible_else_if)] // Aids readability. +impl serde::Serialize for PublicKey { + fn serialize(&self, s: S) -> Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + self.with_serialized(|bytes| s.serialize_bytes(bytes)) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for PublicKey { + fn deserialize>(d: D) -> Result { + if d.is_human_readable() { + struct HexVisitor; + + impl serde::de::Visitor<'_> for HexVisitor { + type Value = PublicKey; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + if let Ok(hex) = core::str::from_utf8(v) { + hex.parse::().map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + v.parse::().map_err(E::custom) + } + } + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; + + impl serde::de::Visitor<'_> for BytesVisitor { + type Value = PublicKey; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + PublicKey::from_slice(v).map_err(E::custom) + } + } + + d.deserialize_bytes(BytesVisitor) + } + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for CompressedPublicKey { + fn serialize(&self, s: S) -> Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(&self.to_bytes()) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for CompressedPublicKey { + fn deserialize>(d: D) -> Result { + if d.is_human_readable() { + struct HexVisitor; + + impl serde::de::Visitor<'_> for HexVisitor { + type Value = CompressedPublicKey; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a 66 digits long ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + if let Ok(hex) = core::str::from_utf8(v) { + hex.parse::().map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + v.parse::().map_err(E::custom) + } + } + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; + + impl serde::de::Visitor<'_> for BytesVisitor { + type Value = CompressedPublicKey; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + CompressedPublicKey::from_slice(v).map_err(E::custom) + } + } + + d.deserialize_bytes(BytesVisitor) + } + } +} +/// Untweaked BIP-0340 X-coord-only public key. +pub type UntweakedPublicKey = XOnlyPublicKey; + +/// Tweaked BIP-0340 X-coord-only public key. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct TweakedPublicKey(XOnlyPublicKey); + +impl fmt::LowerHex for TweakedPublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } +} +// Allocate for serialized size +impl_to_hex_from_lower_hex!(TweakedPublicKey, |_| constants::SCHNORR_PUBLIC_KEY_SIZE * 2); + +impl fmt::Display for TweakedPublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } +} + +/// Untweaked BIP-0340 key pair. +pub type UntweakedKeypair = Keypair; + +/// Tweaked BIP-0340 key pair. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(all(feature = "rand", feature = "std"))] { +/// # use bitcoin::key::{Keypair, TweakedKeypair, TweakedPublicKey}; +/// # use bitcoin::secp256k1::rand; +/// # let keypair = TweakedKeypair::dangerous_assume_tweaked(Keypair::new(&mut rand::rng())); +/// // There are various conversion methods available to get a tweaked pubkey from a tweaked keypair. +/// let (_pk, _parity) = keypair.public_parts(); +/// let _pk = TweakedPublicKey::from_keypair(keypair); +/// let _pk = TweakedPublicKey::from(keypair); +/// # } +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +pub struct TweakedKeypair(Keypair); + +/// A trait for tweaking BIP-0340 key types (x-only public keys and key pairs). +pub trait TapTweak { + /// Tweaked key type with optional auxiliary information. + type TweakedAux; + /// Tweaked key type. + type TweakedKey; + + /// Tweaks an untweaked key with corresponding public key value and optional script tree Merkle + /// root. For the [`Keypair`] type this also tweaks the private key in the pair. + /// + /// This is done by using the equation Q = P + H(P|c)G, where + /// * Q is the tweaked public key + /// * P is the internal public key + /// * H is the hash function + /// * c is the commitment data + /// * G is the generator point + /// + /// # Returns + /// + /// The tweaked key and its parity. + fn tap_tweak( + self, + merkle_root: Option, + ) -> Self::TweakedAux; + + /// Directly converts an [`UntweakedPublicKey`] to a [`TweakedPublicKey`]. + /// + /// This method is dangerous and can lead to loss of funds if used incorrectly. + /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal. + fn dangerous_assume_tweaked(self) -> Self::TweakedKey; +} + +impl TapTweak for UntweakedPublicKey { + type TweakedAux = (TweakedPublicKey, Parity); + type TweakedKey = TweakedPublicKey; + + /// Tweaks an untweaked public key with corresponding public key value and optional script tree + /// Merkle root. + /// + /// This is done by using the equation Q = P + H(P|c)G, where + /// * Q is the tweaked public key + /// * P is the internal public key + /// * H is the hash function + /// * c is the commitment data + /// * G is the generator point + /// + /// # Returns + /// + /// The tweaked key and its parity. + fn tap_tweak( + self, + merkle_root: Option, + ) -> (TweakedPublicKey, Parity) { + let tweak = TapTweakHash::from_key_and_merkle_root(self, merkle_root).to_scalar(); + let (output_key, parity) = self.add_tweak(&tweak).expect("Tap tweak failed"); + + debug_assert!(self.tweak_add_check(&output_key, parity, tweak)); + (TweakedPublicKey(output_key), parity) + } + + fn dangerous_assume_tweaked(self) -> TweakedPublicKey { TweakedPublicKey(self) } +} + +impl TapTweak for UntweakedKeypair { + type TweakedAux = TweakedKeypair; + type TweakedKey = TweakedKeypair; + + /// Applies a Taproot tweak to both keys within the keypair. + /// + /// If `merkle_root` is provided, produces a Taproot key that can be spent by any + /// of the script paths committed to by the root. If it is not provided, produces + /// a Taproot key which can [provably only be spent via + /// keyspend](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-23). + /// + /// # Returns + /// + /// The tweaked keypair. + fn tap_tweak( + self, + merkle_root: Option, + ) -> TweakedKeypair { + let (pubkey, _parity) = XOnlyPublicKey::from_keypair(&self); + let tweak = TapTweakHash::from_key_and_merkle_root(pubkey, merkle_root).to_scalar(); + let tweaked = self.add_xonly_tweak(&tweak).expect("Tap tweak failed"); + TweakedKeypair(tweaked) + } + + fn dangerous_assume_tweaked(self) -> TweakedKeypair { TweakedKeypair(self) } +} + +impl TweakedPublicKey { + /// Returns the [`TweakedPublicKey`] for `keypair`. + #[inline] + pub fn from_keypair(keypair: TweakedKeypair) -> Self { + let (xonly, _parity) = keypair.0.x_only_public_key(); + Self(xonly.into()) + } + + /// Constructs a new [`TweakedPublicKey`] from a [`XOnlyPublicKey`]. No tweak is applied, consider + /// calling `tap_tweak` on an [`UntweakedPublicKey`] instead of using this constructor. + /// + /// This method is dangerous and can lead to loss of funds if used incorrectly. + /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal. + #[inline] + pub fn dangerous_assume_tweaked(key: XOnlyPublicKey) -> Self { Self(key) } + + /// Returns the underlying public key. + #[inline] + #[doc(hidden)] + #[deprecated(since = "0.32.6", note = "use to_x_only_public_key() instead")] + pub fn to_inner(self) -> XOnlyPublicKey { self.0 } + + /// Returns the underlying x-only public key. + #[inline] + pub fn to_x_only_public_key(self) -> XOnlyPublicKey { self.0 } + + /// Returns a reference to the underlying x-only public key. + #[inline] + pub fn as_x_only_public_key(&self) -> &XOnlyPublicKey { &self.0 } + + /// Serializes the key as a byte-encoded x coordinate value (32 bytes). + #[inline] + pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] { self.0.serialize() } +} + +impl TweakedKeypair { + /// Constructs a new [`TweakedKeypair`] from a [`Keypair`]. No tweak is applied, consider + /// calling `tap_tweak` on an [`UntweakedKeypair`] instead of using this constructor. + /// + /// This method is dangerous and can lead to loss of funds if used incorrectly. + /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal. + #[inline] + pub fn dangerous_assume_tweaked(pair: Keypair) -> Self { Self(pair) } + + /// Returns the underlying key pair. + #[inline] + #[doc(hidden)] + #[deprecated(since = "0.32.6", note = "use to_keypair() instead")] + pub fn to_inner(self) -> Keypair { self.0 } + + /// Returns the underlying key pair. + #[inline] + pub fn to_keypair(self) -> Keypair { self.0 } + + /// Returns a reference to the underlying key pair. + #[inline] + pub fn as_keypair(&self) -> &Keypair { &self.0 } + + /// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeypair`]. + #[inline] + pub fn public_parts(&self) -> (TweakedPublicKey, Parity) { + let (xonly, parity) = self.0.x_only_public_key(); + (TweakedPublicKey(xonly.into()), parity) + } +} + +impl From for XOnlyPublicKey { + #[inline] + fn from(pair: TweakedPublicKey) -> Self { pair.0 } +} + +impl From for Keypair { + #[inline] + fn from(pair: TweakedKeypair) -> Self { pair.0 } +} + +impl From for TweakedPublicKey { + #[inline] + fn from(pair: TweakedKeypair) -> Self { Self::from_keypair(pair) } +} + +/// Error returned while generating key from slice. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum FromSliceError { + /// Invalid key prefix error. + InvalidKeyPrefix(u8), + /// A secp256k1 error. + Secp256k1(secp256k1::Error), + /// Invalid Length of the slice. + InvalidLength(usize), +} + +impl From for FromSliceError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for FromSliceError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Secp256k1(e) => write_err!(f, "secp256k1"; e), + Self::InvalidKeyPrefix(b) => write!(f, "key prefix invalid: {}", b), + Self::InvalidLength(got) => + write!(f, "slice length should be 33 or 65 bytes, got: {}", got), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromSliceError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Secp256k1(ref e) => Some(e), + Self::InvalidKeyPrefix(_) | Self::InvalidLength(_) => None, + } + } +} + +impl From for FromSliceError { + fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) } +} + +/// Error generated from WIF key format. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum FromWifError { + /// A base58 decoding error. + Base58(base58::Error), + /// Base58 decoded data was an invalid length. + InvalidBase58PayloadLength(InvalidBase58PayloadLengthError), + /// Base58 decoded data contained an invalid address version byte. + InvalidAddressVersion(InvalidAddressVersionError), + /// A secp256k1 error. + Secp256k1(secp256k1::Error), + /// Invalid WIF compression flag. + InvalidWifCompressionFlag(InvalidWifCompressionFlagError), +} + +impl From for FromWifError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for FromWifError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Base58(ref e) => write_err!(f, "invalid base58"; e), + Self::InvalidBase58PayloadLength(ref e) => + write_err!(f, "decoded base58 data was an invalid length"; e), + Self::InvalidAddressVersion(ref e) => + write_err!(f, "decoded base58 data contained an invalid address version byte"; e), + Self::Secp256k1(ref e) => write_err!(f, "private key validation failed"; e), + Self::InvalidWifCompressionFlag(ref e) => + write_err!(f, "invalid WIF compression flag"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromWifError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Base58(ref e) => Some(e), + Self::InvalidBase58PayloadLength(ref e) => Some(e), + Self::InvalidAddressVersion(ref e) => Some(e), + Self::Secp256k1(ref e) => Some(e), + Self::InvalidWifCompressionFlag(ref e) => Some(e), + } + } +} + +impl From for FromWifError { + fn from(e: base58::Error) -> Self { Self::Base58(e) } +} + +impl From for FromWifError { + fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) } +} + +impl From for FromWifError { + fn from(e: InvalidBase58PayloadLengthError) -> Self { Self::InvalidBase58PayloadLength(e) } +} + +impl From for FromWifError { + fn from(e: InvalidAddressVersionError) -> Self { Self::InvalidAddressVersion(e) } +} + +impl From for FromWifError { + fn from(e: InvalidWifCompressionFlagError) -> Self { Self::InvalidWifCompressionFlag(e) } +} + +/// Error returned while constructing public key from string. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParsePublicKeyError { + /// Error originated while parsing string. + Encoding(FromSliceError), + /// Hex decoding error. + InvalidChar(hex::InvalidCharError), + /// `PublicKey` hex should be 66 or 130 digits long. + InvalidHexLength(usize), +} + +impl From for ParsePublicKeyError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParsePublicKeyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Encoding(ref e) => write_err!(f, "string error"; e), + Self::InvalidChar(ref e) => write_err!(f, "hex decoding"; e), + Self::InvalidHexLength(got) => + write!(f, "pubkey string should be 66 or 130 digits long, got: {}", got), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParsePublicKeyError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Encoding(ref e) => Some(e), + Self::InvalidChar(ref e) => Some(e), + Self::InvalidHexLength(_) => None, + } + } +} + +impl From for ParsePublicKeyError { + fn from(e: FromSliceError) -> Self { Self::Encoding(e) } +} + +/// Error returned when parsing a [`CompressedPublicKey`] from a string. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParseCompressedPublicKeyError { + /// secp256k1 Error. + Secp256k1(secp256k1::Error), + /// hex to array conversion error. + Hex(hex::HexToArrayError), +} + +impl From for ParseCompressedPublicKeyError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ParseCompressedPublicKeyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Secp256k1(e) => write_err!(f, "secp256k1 error"; e), + Self::Hex(e) => write_err!(f, "invalid hex"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseCompressedPublicKeyError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Secp256k1(e) => Some(e), + Self::Hex(e) => Some(e), + } + } +} + +impl From for ParseCompressedPublicKeyError { + fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) } +} + +impl From for ParseCompressedPublicKeyError { + fn from(e: hex::HexToArrayError) -> Self { Self::Hex(e) } +} + +/// SegWit public keys must always be compressed. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UncompressedPublicKeyError; + +impl fmt::Display for UncompressedPublicKeyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("SegWit public keys must always be compressed") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UncompressedPublicKeyError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// Decoded base58 data was an invalid length. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidBase58PayloadLengthError { + /// The base58 payload length we got after decoding WIF string. + pub(crate) length: usize, +} + +impl InvalidBase58PayloadLengthError { + /// Returns the invalid payload length. + pub fn invalid_base58_payload_length(&self) -> usize { self.length } +} + +impl fmt::Display for InvalidBase58PayloadLengthError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "decoded base58 data was an invalid length: {} (expected 33 or 34)", self.length) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidBase58PayloadLengthError {} + +/// Invalid address version in decoded base58 data. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidAddressVersionError { + /// The invalid version. + pub(crate) invalid: u8, +} + +impl InvalidAddressVersionError { + /// Returns the invalid version. + pub fn invalid_address_version(&self) -> u8 { self.invalid } +} + +impl fmt::Display for InvalidAddressVersionError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid address version in decoded base58 data {}", self.invalid) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidAddressVersionError {} + +/// Invalid compression flag for a WIF key +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidWifCompressionFlagError { + /// The invalid compression flag. + pub(crate) invalid: u8, +} + +impl InvalidWifCompressionFlagError { + /// Returns the invalid compression flag. + pub fn invalid_compression_flag(&self) -> u8 { self.invalid } +} + +impl fmt::Display for InvalidWifCompressionFlagError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid WIF compression flag. Expected a 0x01 byte at the end of the key but found: {}", self.invalid) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidWifCompressionFlagError {} + +mod serialized_x_only { + internals::transparent_newtype! { + /// An array of bytes that's semantically an x-only public but was **not** validated. + /// + /// This can be useful when validation is not desired but semantics of the bytes should be + /// preserved. The validation can still happen using `to_validated()` method. + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + pub struct SerializedXOnlyPublicKey([u8; 32]); + + impl SerializedXOnlyPublicKey { + pub(crate) fn from_bytes_ref(bytes: &_) -> Self; + } + } + + impl SerializedXOnlyPublicKey { + /// Marks the supplied bytes as a serialized x-only public key. + pub const fn from_byte_array(bytes: [u8; 32]) -> Self { Self(bytes) } + + /// Returns the raw bytes. + pub const fn to_byte_array(self) -> [u8; 32] { self.0 } + + /// Returns a reference to the raw bytes. + pub const fn as_byte_array(&self) -> &[u8; 32] { &self.0 } + } +} + +impl SerializedXOnlyPublicKey { + /// Returns `XOnlyPublicKey` if the bytes are valid. + pub fn to_validated(self) -> Result { + XOnlyPublicKey::from_byte_array(self.as_byte_array()) + } +} + +impl AsRef<[u8; 32]> for SerializedXOnlyPublicKey { + fn as_ref(&self) -> &[u8; 32] { self.as_byte_array() } +} + +impl From<&Self> for SerializedXOnlyPublicKey { + fn from(borrowed: &Self) -> Self { *borrowed } +} + +impl fmt::Debug for SerializedXOnlyPublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.as_byte_array().as_hex(), f) + } +} + +/// Error that can occur when parsing an [`XOnlyPublicKey`] from bytes. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParseXOnlyPublicKeyError { + /// The provided bytes do not represent a valid secp256k1 point x-coordinate. + InvalidXCoordinate, +} + +impl fmt::Display for ParseXOnlyPublicKeyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::InvalidXCoordinate => write!(f, "Invalid X coordinate for secp256k1 point"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseXOnlyPublicKeyError {} + +/// Error that can occur when tweaking an [`XOnlyPublicKey`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum TweakXOnlyPublicKeyError { + /// The tweak value was invalid. + BadTweak, + /// The resulting public key would be invalid. + ResultKeyInvalid, + /// Invalid parity value encountered during the operation. + ParityError, +} + +impl fmt::Display for TweakXOnlyPublicKeyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::BadTweak => write!(f, "Invalid tweak value"), + Self::ResultKeyInvalid => write!(f, "Resulting public key would be invalid"), + Self::ParityError => write!(f, "Invalid parity value encountered"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TweakXOnlyPublicKeyError {} + +#[cfg(test)] +mod tests { + use super::*; + use crate::address::Address; + + #[test] + fn key_derivation() { + // mainnet compressed WIF with invalid compression flag. + let sk = PrivateKey::from_wif("L2x4uC2YgfFWZm9tF4pjDnVR6nJkheizFhEr2KvDNnTEmEqVzPJY"); + assert!(matches!( + sk, + Err(FromWifError::InvalidWifCompressionFlag(InvalidWifCompressionFlagError { + invalid: 49 + })) + )); + + // testnet compressed + let sk = + PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); + assert_eq!(sk.network, NetworkKind::Test); + assert!(sk.compressed); + assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); + + let pk = Address::p2pkh(sk.public_key(), sk.network); + assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx"); + + // test string conversion + assert_eq!(&sk.to_string(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); + let sk_str = + "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy".parse::().unwrap(); + assert_eq!(&sk.to_wif(), &sk_str.to_wif()); + + // mainnet uncompressed + let sk = + PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); + assert_eq!(sk.network, NetworkKind::Main); + assert!(!sk.compressed); + assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3"); + + let mut pk = sk.public_key(); + assert!(!pk.compressed); + assert_eq!(&pk.to_string(), "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"); + assert_eq!(pk, "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133" + .parse::().unwrap()); + let addr = Address::p2pkh(pk, sk.network); + assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8"); + pk.compressed = true; + assert_eq!( + &pk.to_string(), + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ); + assert_eq!( + pk, + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + .parse::() + .unwrap() + ); + } + + #[test] + fn pubkey_hash() { + let pk = "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + .parse::() + .unwrap(); + let upk = "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133" + .parse::().unwrap(); + assert_eq!(pk.pubkey_hash().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4"); + assert_eq!(upk.pubkey_hash().to_string(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a"); + } + + #[test] + fn wpubkey_hash() { + let pk = "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + .parse::() + .unwrap(); + let upk = "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133".parse::().unwrap(); + assert_eq!( + pk.wpubkey_hash().unwrap().to_string(), + "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4" + ); + assert!(upk.wpubkey_hash().is_err()); + } + + #[test] + #[cfg(feature = "serde")] + fn skey_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + static KEY_WIF: &str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"; + static PK_STR: &str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef"; + static PK_STR_U: &str = "\ + 04\ + 9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\ + 87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\ + "; + #[rustfmt::skip] + static PK_BYTES: [u8; 33] = [ + 0x03, + 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, + 0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c, + 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, + 0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef, + ]; + #[rustfmt::skip] + static PK_BYTES_U: [u8; 65] = [ + 0x04, + 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, + 0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c, + 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, + 0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef, + 0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4, + 0xf5, 0xc7, 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda, + 0x7c, 0xff, 0x3a, 0xff, 0x6e, 0x81, 0x9e, 0x4e, + 0xe9, 0x71, 0xd8, 0x6b, 0x5e, 0x61, 0x87, 0x5d, + ]; + + let sk = KEY_WIF.parse::().unwrap(); + let pk = PublicKey::from_private_key(sk); + let pk_u = PublicKey { inner: pk.inner, compressed: false }; + + assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]); + assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]); + assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]); + assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]); + assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]); + } + + fn random_key(mut seed: u8) -> PublicKey { + loop { + let mut data = [0; 65]; + for byte in &mut data[..] { + *byte = seed; + // totally a rng + seed = seed.wrapping_mul(41).wrapping_add(43); + } + if data[0] % 2 == 0 { + data[0] = 4; + if let Ok(key) = PublicKey::from_slice(&data[..]) { + return key; + } + } else { + data[0] = 2 + (data[0] >> 7); + if let Ok(key) = PublicKey::from_slice(&data[..33]) { + return key; + } + } + } + } + + #[test] + fn pubkey_read_write() { + const N_KEYS: usize = 20; + let keys: Vec<_> = (0..N_KEYS).map(|i| random_key(i as u8)).collect(); + + let mut v = vec![]; + for k in &keys { + k.write_into(&mut v).expect("writing into vec"); + } + + let mut reader = v.as_slice(); + let mut dec_keys = vec![]; + for _ in 0..N_KEYS { + dec_keys.push(PublicKey::read_from(&mut reader).expect("reading from vec")); + } + assert_eq!(keys, dec_keys); + assert!(PublicKey::read_from(&mut reader).is_err()); + + // sanity checks + let mut empty: &[u8] = &[]; + assert!(PublicKey::read_from(&mut empty).is_err()); + assert!(PublicKey::read_from(&mut &[0; 33][..]).is_err()); + assert!(PublicKey::read_from(&mut &[2; 32][..]).is_err()); + assert!(PublicKey::read_from(&mut &[0; 65][..]).is_err()); + assert!(PublicKey::read_from(&mut &[4; 64][..]).is_err()); + } + + #[test] + fn pubkey_to_sort_key() { + let key1 = "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8" + .parse::() + .unwrap(); + let key2 = PublicKey { inner: key1.inner, compressed: false }; + let arrayvec1 = ArrayVec::from_slice( + &<[u8; 33]>::from_hex( + "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", + ) + .unwrap(), + ); + let expected1 = SortKey(arrayvec1); + let arrayvec2 = ArrayVec::from_slice(&<[u8; 65]>::from_hex( + "04ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f81794e7f3d5e420641a3bc690067df5541470c966cbca8c694bf39aa16d836918", + ).unwrap()); + let expected2 = SortKey(arrayvec2); + assert_eq!(key1.to_sort_key(), expected1); + assert_eq!(key2.to_sort_key(), expected2); + } + + #[test] + fn pubkey_sort() { + struct Vector { + input: Vec, + expect: Vec, + } + let fmt = |v: Vec<_>| { + v.into_iter().map(|s: &str| s.parse::().unwrap()).collect::>() + }; + let vectors = vec![ + // Start BIP-0067 vectors + // Vector 1 + Vector { + input: fmt(vec![ + "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", + "02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f", + ]), + expect: fmt(vec![ + "02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f", + "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", + ]), + }, + // Vector 2 (Already sorted, no action required) + Vector { + input: fmt(vec![ + "02632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed0", + "027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e77", + "02e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b404", + ]), + expect: fmt(vec![ + "02632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed0", + "027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e77", + "02e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b404", + ]), + }, + // Vector 3 + Vector { + input: fmt(vec![ + "030000000000000000000000000000000000004141414141414141414141414141", + "020000000000000000000000000000000000004141414141414141414141414141", + "020000000000000000000000000000000000004141414141414141414141414140", + "030000000000000000000000000000000000004141414141414141414141414140", + ]), + expect: fmt(vec![ + "020000000000000000000000000000000000004141414141414141414141414140", + "020000000000000000000000000000000000004141414141414141414141414141", + "030000000000000000000000000000000000004141414141414141414141414140", + "030000000000000000000000000000000000004141414141414141414141414141", + ]), + }, + // Vector 4: (from bitcore) + Vector { + input: fmt(vec![ + "022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da", + "03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9", + "021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18", + ]), + expect: fmt(vec![ + "021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18", + "022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da", + "03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9", + ]), + }, + // Non-BIP67 vectors + Vector { + input: fmt(vec![ + "02c690d642c1310f3a1ababad94e3930e4023c930ea472e7f37f660fe485263b88", + "0234dd69c56c36a41230d573d68adeae0030c9bc0bf26f24d3e1b64c604d293c68", + "041a181bd0e79974bd7ca552e09fc42ba9c3d5dbb3753741d6f0ab3015dbfd9a22d6b001a32f5f51ac6f2c0f35e73a6a62f59e848fa854d3d21f3f231594eeaa46", + "032b8324c93575034047a52e9bca05a46d8347046b91a032eff07d5de8d3f2730b", + "04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc3816753d96001fd7cba3ce5372f5c9a0d63708183033538d07b1e532fc43aaacfa", + "028e1c947c8c0b8ed021088b8e981491ac7af2b8fabebea1abdb448424c8ed75b7", + "045d753414fa292ea5b8f56e39cfb6a0287b2546231a5cb05c4b14ab4b463d171f5128148985b23eccb1e2905374873b1f09b9487f47afa6b1f2b0083ac8b4f7e8", + "03004a8a3d242d7957c0b60fb7208d386fa6a0193aabd1f3f095ffd0ac097e447b", + "04eb0db2d71ccbb0edd8fb35092cbcae2f7fa1f06d4c170804bf52007924b569a8d2d6f6bc8fd2b3caa3253fa1bb674443743bf7fb9f94f9c0b0831a252894cfa8", + "04516cde23e14f2319423b7a4a7ae48b1dadceb5e9c123198d417d10895684c42eb05e210f90ccbc72448803a22312e3f122ff2939956ccef4f7316f836295ddd5", + "038f47dcd43ba6d97fc9ed2e3bba09b175a45fac55f0683e8cf771e8ced4572354", + "04c6bec3b07586a4b085a78cbb97e9bab6f1d3c9ebf299b65dec85213c5eacd44487de86017183120bb7ea3b6c6660c5037615fe1add2a73f800cbeeae22c60438", + "03e1a1cfa9eaff604ae237b7af31ffe4c01be22eb96f3da0e62c5850dd4b4386c1", + "028d3a2d9f1b1c5c75845944f93bc183ba23aecde53f1978b8aa1b77661be6114f", + "028bde91b10013e08949a318018fedbd896534a549a278e220169ee2a36517c7aa", + "04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc38e98ac269ffe028345c31ac8d0a365f29c8f7e7cfccac72f84e1acd02bc554f35", + ]), + expect: fmt(vec![ + "0234dd69c56c36a41230d573d68adeae0030c9bc0bf26f24d3e1b64c604d293c68", + "028bde91b10013e08949a318018fedbd896534a549a278e220169ee2a36517c7aa", + "028d3a2d9f1b1c5c75845944f93bc183ba23aecde53f1978b8aa1b77661be6114f", + "028e1c947c8c0b8ed021088b8e981491ac7af2b8fabebea1abdb448424c8ed75b7", + "02c690d642c1310f3a1ababad94e3930e4023c930ea472e7f37f660fe485263b88", + "03004a8a3d242d7957c0b60fb7208d386fa6a0193aabd1f3f095ffd0ac097e447b", + "032b8324c93575034047a52e9bca05a46d8347046b91a032eff07d5de8d3f2730b", + "038f47dcd43ba6d97fc9ed2e3bba09b175a45fac55f0683e8cf771e8ced4572354", + "03e1a1cfa9eaff604ae237b7af31ffe4c01be22eb96f3da0e62c5850dd4b4386c1", + "041a181bd0e79974bd7ca552e09fc42ba9c3d5dbb3753741d6f0ab3015dbfd9a22d6b001a32f5f51ac6f2c0f35e73a6a62f59e848fa854d3d21f3f231594eeaa46", + "04516cde23e14f2319423b7a4a7ae48b1dadceb5e9c123198d417d10895684c42eb05e210f90ccbc72448803a22312e3f122ff2939956ccef4f7316f836295ddd5", + "045d753414fa292ea5b8f56e39cfb6a0287b2546231a5cb05c4b14ab4b463d171f5128148985b23eccb1e2905374873b1f09b9487f47afa6b1f2b0083ac8b4f7e8", + // These two pubkeys are mirrored. This helps verify the sort past the x value. + "04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc3816753d96001fd7cba3ce5372f5c9a0d63708183033538d07b1e532fc43aaacfa", + "04c4b0bbb339aa236bff38dbe6a451e111972a7909a126bc424013cba2ec33bc38e98ac269ffe028345c31ac8d0a365f29c8f7e7cfccac72f84e1acd02bc554f35", + "04c6bec3b07586a4b085a78cbb97e9bab6f1d3c9ebf299b65dec85213c5eacd44487de86017183120bb7ea3b6c6660c5037615fe1add2a73f800cbeeae22c60438", + "04eb0db2d71ccbb0edd8fb35092cbcae2f7fa1f06d4c170804bf52007924b569a8d2d6f6bc8fd2b3caa3253fa1bb674443743bf7fb9f94f9c0b0831a252894cfa8", + ]), + }, + ]; + for mut vector in vectors { + vector.input.sort_by_cached_key(|k| PublicKey::to_sort_key(*k)); + assert_eq!(vector.input, vector.expect); + } + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn public_key_constructors() { + use secp256k1::rand; + + let kp = Keypair::new(&mut rand::rng()); + + let _ = PublicKey::new(kp); + let _ = PublicKey::new_uncompressed(kp); + } + + #[test] + fn public_key_from_str_wrong_length() { + // Sanity checks, we accept string length 130 digits. + let s = "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"; + assert_eq!(s.len(), 130); + assert!(s.parse::().is_ok()); + // And 66 digits. + let s = "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"; + assert_eq!(s.len(), 66); + assert!(s.parse::().is_ok()); + + let s = "aoeusthb"; + assert_eq!(s.len(), 8); + let res = s.parse::(); + assert!(res.is_err()); + assert_eq!(res.unwrap_err(), ParsePublicKeyError::InvalidHexLength(8)); + } + + #[test] + fn public_key_from_str_invalid_str() { + // Ensuring test cases fail when PublicKey::from_str is used on invalid keys + let s = "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b142"; + assert_eq!(s.len(), 130); + let res = s.parse::(); + assert!(res.is_err()); + assert_eq!( + res.unwrap_err(), + ParsePublicKeyError::Encoding(FromSliceError::Secp256k1( + secp256k1::Error::InvalidPublicKey + )) + ); + + let s = "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd169"; + assert_eq!(s.len(), 66); + let res = s.parse::(); + assert!(res.is_err()); + assert_eq!( + res.unwrap_err(), + ParsePublicKeyError::Encoding(FromSliceError::Secp256k1( + secp256k1::Error::InvalidPublicKey + )) + ); + + let s = "062e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"; + assert_eq!(s.len(), 130); + let res = s.parse::(); + assert!(res.is_err()); + assert_eq!( + res.unwrap_err(), + ParsePublicKeyError::Encoding(FromSliceError::InvalidKeyPrefix(6)) + ); + + let s = "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b13g"; + assert_eq!(s.len(), 130); + let res = s.parse::(); + assert!(res.is_err()); + if let Err(ParsePublicKeyError::InvalidChar(err)) = res { + assert_eq!(err.invalid_char(), b'g'); + assert_eq!(err.pos(), 129); + } else { + panic!("expected ParsePublicKeyError::InvalidChar"); + } + + let s = "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1ag"; + assert_eq!(s.len(), 66); + let res = s.parse::(); + assert!(res.is_err()); + if let Err(ParsePublicKeyError::InvalidChar(err)) = res { + assert_eq!(err.invalid_char(), b'g'); + assert_eq!(err.pos(), 65); + } else { + panic!("expected ParsePublicKeyError::InvalidChar"); + } + } + + #[test] + #[allow(deprecated)] // tests the deprecated function + #[allow(deprecated_in_future)] + fn invalid_private_key_len() { + use crate::Network; + assert!(PrivateKey::from_slice(&[1u8; 31], Network::Regtest).is_err()); + assert!(PrivateKey::from_slice(&[1u8; 33], Network::Regtest).is_err()); + } + + #[test] + fn xonly_pubkey_from_bytes() { + let key_bytes = &<[u8; 32]>::from_hex( + "5b1e57ec453cd33fdc7cfc901450a3931fd315422558f2fb7fefb064e6e7d60d", + ).expect("Failed to convert hex string to byte array"); + let xonly_pub_key = XOnlyPublicKey::from_byte_array(key_bytes) + .expect("Failed to create an XOnlyPublicKey from a byte array"); + // Confirm that the public key from bytes serializes back to the same bytes + assert_eq!(&xonly_pub_key.serialize(), key_bytes); + } + + #[test] + fn xonly_pubkey_into_inner() { + let key_bytes = &<[u8; 32]>::from_hex( + "5b1e57ec453cd33fdc7cfc901450a3931fd315422558f2fb7fefb064e6e7d60d", + ).expect("Failed to convert hex string to byte array"); + let inner_key = secp256k1::XOnlyPublicKey::from_byte_array(*key_bytes) + .expect("Failed to create a secp256k1 x-only public key from a byte array"); + let btc_pubkey = XOnlyPublicKey::new(inner_key); + // Confirm that the into_inner() returns the same data that was initially wrapped + assert_eq!(inner_key, btc_pubkey.into_inner()); + } +} diff --git a/bitcoin/src/crypto/mod.rs b/bitcoin/src/crypto/mod.rs new file mode 100644 index 000000000..d14e73048 --- /dev/null +++ b/bitcoin/src/crypto/mod.rs @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Cryptography +//! +//! Cryptography related functionality: keys and signatures. + +pub mod ecdsa; +pub mod key; +pub mod sighash; +// Contents re-exported in `bitcoin::taproot`. +pub(crate) mod taproot; diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs new file mode 100644 index 000000000..8a91607e7 --- /dev/null +++ b/bitcoin/src/crypto/sighash.rs @@ -0,0 +1,2248 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Signature hash implementation (used in transaction signing). +//! +//! Efficient implementation of the algorithm to compute the message to be signed according to +//! [BIP-0341], [BIP-0143] and legacy (before BIP-0143). +//! +//! Computing signature hashes is required to sign a transaction and this module is designed to +//! handle its complexity efficiently. Computing these hashes is as simple as creating +//! [`SighashCache`] and calling its methods. +//! +//! [BIP-0341]: +//! [BIP-0143]: + +use core::convert::Infallible; +use core::{fmt, str}; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::{hash_newtype, sha256, sha256d, sha256t, sha256t_tag}; +use internals::write_err; +use io::Write; + +use crate::consensus::{encode, Encodable}; +use crate::prelude::{Borrow, BorrowMut, String, ToOwned}; +use crate::script::{ScriptExt as _, ScriptHashableTag}; +use crate::taproot::{LeafVersion, TapLeafHash, TapLeafTag, TAPROOT_ANNEX_PREFIX}; +use crate::transaction::TransactionExt as _; +use crate::witness::Witness; +use crate::{ + transaction, Amount, ScriptPubKey, Sequence, TapScript, Transaction, TxOut, WitnessScript, +}; + +/// Used for signature hash for invalid use of SIGHASH_SINGLE. +#[rustfmt::skip] +pub(crate) const UINT256_ONE: [u8; 32] = [ + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +]; + +macro_rules! impl_message_from_hash { + ($ty:ident) => { + impl From<$ty> for secp256k1::Message { + fn from(hash: $ty) -> secp256k1::Message { + secp256k1::Message::from_digest(hash.to_byte_array()) + } + } + }; +} + +hash_newtype! { + /// Hash of a transaction according to the legacy signature algorithm. + #[hash_newtype(forward)] + pub struct LegacySighash(sha256d::Hash); + + /// Hash of a transaction according to the SegWit version 0 signature algorithm. + #[hash_newtype(forward)] + pub struct SegwitV0Sighash(sha256d::Hash); +} + +hashes::impl_hex_for_newtype!(LegacySighash, SegwitV0Sighash); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(LegacySighash, SegwitV0Sighash); + +impl_message_from_hash!(LegacySighash); +impl_message_from_hash!(SegwitV0Sighash); + +// Implement private engine/from_engine methods for use within this module; +// but outside of it, it should not be possible to construct these hash +// types from arbitrary data (except by casting via to/from_byte_array). +impl LegacySighash { + fn engine() -> sha256d::HashEngine { sha256d::Hash::engine() } + fn from_engine(e: sha256d::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) } +} +impl SegwitV0Sighash { + fn engine() -> sha256d::HashEngine { sha256d::Hash::engine() } + fn from_engine(e: sha256d::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) } +} + +sha256t_tag! { + pub struct TapSighashTag = hash_str("TapSighash"); +} + +hash_newtype! { + /// Taproot-tagged hash with tag \"TapSighash\". + /// + /// This hash type is used for computing Taproot signature hash. + pub struct TapSighash(sha256t::Hash); +} + +hashes::impl_hex_for_newtype!(TapSighash); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(TapSighash); + +/// Efficiently calculates signature hash message for legacy, SegWit and Taproot inputs. +#[derive(Debug)] +pub struct SighashCache> { + /// Access to transaction required for transaction introspection. Moreover, type + /// `T: Borrow` allows us to use borrowed and mutable borrowed types, + /// the latter in particular is necessary for [`SighashCache::witness_mut`]. + tx: T, + + /// Common cache for Taproot and SegWit inputs, `None` for legacy inputs. + common_cache: Option, + + /// Cache for SegWit v0 inputs (the result of another round of sha256 on `common_cache`). + segwit_cache: Option, + + /// Cache for Taproot v1 inputs. + taproot_cache: Option, +} + +/// Common values cached between SegWit and Taproot inputs. +#[derive(Debug)] +struct CommonCache { + prevouts: sha256::Hash, + sequences: sha256::Hash, + + /// In theory `outputs` could be an `Option` since `SIGHASH_NONE` and `SIGHASH_SINGLE` do not + /// need it, but since `SIGHASH_ALL` is by far the most used variant we don't bother. + outputs: sha256::Hash, +} + +/// Values cached for SegWit inputs, equivalent to [`CommonCache`] plus another round of `sha256`. +#[derive(Debug)] +struct SegwitCache { + prevouts: sha256d::Hash, + sequences: sha256d::Hash, + outputs: sha256d::Hash, +} + +/// Values cached for Taproot inputs. +#[derive(Debug)] +struct TaprootCache { + amounts: sha256::Hash, + script_pubkeys: sha256::Hash, +} + +/// Contains outputs of previous transactions. In the case [`TapSighashType`] variant is +/// `SIGHASH_ANYONECANPAY`, [`Prevouts::One`] may be used. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum Prevouts<'u, T> +where + T: 'u + Borrow, +{ + /// `One` variant allows provision of the single prevout needed. It's useful, for example, when + /// modifier `SIGHASH_ANYONECANPAY` is provided, only prevout of the current input is needed. + /// The first `usize` argument is the input index this [`TxOut`] is referring to. + One(usize, T), + /// When `SIGHASH_ANYONECANPAY` is not provided, or when the caller is giving all prevouts so + /// the same variable can be used for multiple inputs. + All(&'u [T]), +} + +const KEY_VERSION_0: u8 = 0u8; + +/// Information related to the script path spending. +/// +/// This can be hashed into a [`TapLeafHash`]. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct ScriptPath<'s> { + script: &'s TapScript, + leaf_version: LeafVersion, +} + +/// Hashtype of an input's signature, encoded in the last byte of the signature. +/// Fixed values so they can be cast as integer types for encoding. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum TapSighashType { + /// 0x0: Used when not explicitly specified, defaults to [`TapSighashType::All`] + Default = 0x00, + /// 0x1: Sign all outputs. + All = 0x01, + /// 0x2: Sign no outputs --- anyone can choose the destination. + None = 0x02, + /// 0x3: Sign the output whose index matches this input's index. If none exists, + /// sign the hash `0000000000000000000000000000000000000000000000000000000000000001`. + /// (This rule is probably an unintentional C++ism, but it's consensus so we have + /// to follow it.) + Single = 0x03, + /// 0x81: Sign all outputs but only this input. + AllPlusAnyoneCanPay = 0x81, + /// 0x82: Sign no outputs and only this input. + NonePlusAnyoneCanPay = 0x82, + /// 0x83: Sign one output and only this input (see `Single` for what "one output" means). + SinglePlusAnyoneCanPay = 0x83, +} +#[cfg(feature = "serde")] +internals::serde_string_impl!(TapSighashType, "a TapSighashType data"); + +impl fmt::Display for TapSighashType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use TapSighashType::*; + + let s = match self { + Default => "SIGHASH_DEFAULT", + All => "SIGHASH_ALL", + None => "SIGHASH_NONE", + Single => "SIGHASH_SINGLE", + AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", + NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", + SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", + }; + f.write_str(s) + } +} + +impl str::FromStr for TapSighashType { + type Err = SighashTypeParseError; + + fn from_str(s: &str) -> Result { + use TapSighashType::*; + + match s { + "SIGHASH_DEFAULT" => Ok(Default), + "SIGHASH_ALL" => Ok(All), + "SIGHASH_NONE" => Ok(None), + "SIGHASH_SINGLE" => Ok(Single), + "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(AllPlusAnyoneCanPay), + "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(NonePlusAnyoneCanPay), + "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SinglePlusAnyoneCanPay), + _ => Err(SighashTypeParseError { unrecognized: s.to_owned() }), + } + } +} + +impl Prevouts<'_, T> +where + T: Borrow, +{ + fn check_all(&self, tx: &Transaction) -> Result<(), PrevoutsSizeError> { + if let Prevouts::All(prevouts) = self { + if prevouts.len() != tx.inputs.len() { + return Err(PrevoutsSizeError); + } + } + Ok(()) + } + + fn get_all(&self) -> Result<&[T], PrevoutsKindError> { + match self { + Prevouts::All(prevouts) => Ok(*prevouts), + _ => Err(PrevoutsKindError), + } + } + + fn get(&self, input_index: usize) -> Result<&TxOut, PrevoutsIndexError> { + match self { + Prevouts::One(index, prevout) => + if input_index == *index { + Ok(prevout.borrow()) + } else { + Err(PrevoutsIndexError::InvalidOneIndex) + }, + Prevouts::All(prevouts) => prevouts + .get(input_index) + .map(|x| x.borrow()) + .ok_or(PrevoutsIndexError::InvalidAllIndex), + } + } +} + +/// The number of supplied prevouts differs from the number of inputs in the transaction. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct PrevoutsSizeError; + +impl fmt::Display for PrevoutsSizeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "number of supplied prevouts differs from the number of inputs in transaction") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for PrevoutsSizeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// A single prevout was provided but all prevouts are needed without `ANYONECANPAY`. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct PrevoutsKindError; + +impl fmt::Display for PrevoutsKindError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "single prevout provided but all prevouts are needed without `ANYONECANPAY`") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for PrevoutsKindError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// [`Prevouts`] index related errors. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum PrevoutsIndexError { + /// Invalid index when accessing a [`Prevouts::One`] kind. + InvalidOneIndex, + /// Invalid index when accessing a [`Prevouts::All`] kind. + InvalidAllIndex, +} + +impl From for PrevoutsIndexError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for PrevoutsIndexError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidOneIndex => write!(f, "invalid index when accessing a Prevouts::One kind"), + Self::InvalidAllIndex => write!(f, "invalid index when accessing a Prevouts::All kind"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for PrevoutsIndexError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidOneIndex | Self::InvalidAllIndex => None, + } + } +} + +impl<'s> ScriptPath<'s> { + /// Constructs a new `ScriptPath` structure. + pub fn new(script: &'s TapScript, leaf_version: LeafVersion) -> Self { + ScriptPath { script, leaf_version } + } + /// Constructs a new `ScriptPath` structure using default leaf version value. + pub fn with_defaults(script: &'s TapScript) -> Self { + Self::new(script, LeafVersion::TapScript) + } + /// Computes the leaf hash for this `ScriptPath`. + pub fn leaf_hash(&self) -> TapLeafHash { + let mut enc = sha256t::Hash::::engine(); + + self.leaf_version + .to_consensus() + .consensus_encode(&mut enc) + .expect("writing to hash engine should never fail"); + self.script.consensus_encode(&mut enc).expect("writing to hash engine should never fail"); + + let inner = sha256t::Hash::::from_engine(enc); + TapLeafHash::from_byte_array(inner.to_byte_array()) + } +} + +impl<'s> From> for TapLeafHash { + fn from(script_path: ScriptPath<'s>) -> Self { script_path.leaf_hash() } +} + +/// Hashtype of an input's signature, encoded in the last byte of the signature. +/// +/// Fixed values so they can be cast as integer types for encoding (see also +/// [`TapSighashType`]). +#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash)] +pub enum EcdsaSighashType { + /// 0x1: Sign all outputs. + All = 0x01, + /// 0x2: Sign no outputs --- anyone can choose the destination. + None = 0x02, + /// 0x3: Sign the output whose index matches this input's index. If none exists, + /// sign the hash `0000000000000000000000000000000000000000000000000000000000000001`. + /// (This rule is probably an unintentional C++ism, but it's consensus so we have + /// to follow it.) + Single = 0x03, + /// 0x81: Sign all outputs but only this input. + AllPlusAnyoneCanPay = 0x81, + /// 0x82: Sign no outputs and only this input. + NonePlusAnyoneCanPay = 0x82, + /// 0x83: Sign one output and only this input (see `Single` for what "one output" means). + SinglePlusAnyoneCanPay = 0x83, +} +#[cfg(feature = "serde")] +internals::serde_string_impl!(EcdsaSighashType, "a EcdsaSighashType data"); + +impl fmt::Display for EcdsaSighashType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use EcdsaSighashType::*; + + let s = match self { + All => "SIGHASH_ALL", + None => "SIGHASH_NONE", + Single => "SIGHASH_SINGLE", + AllPlusAnyoneCanPay => "SIGHASH_ALL|SIGHASH_ANYONECANPAY", + NonePlusAnyoneCanPay => "SIGHASH_NONE|SIGHASH_ANYONECANPAY", + SinglePlusAnyoneCanPay => "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", + }; + f.write_str(s) + } +} + +impl str::FromStr for EcdsaSighashType { + type Err = SighashTypeParseError; + + fn from_str(s: &str) -> Result { + use EcdsaSighashType::*; + + match s { + "SIGHASH_ALL" => Ok(All), + "SIGHASH_NONE" => Ok(None), + "SIGHASH_SINGLE" => Ok(Single), + "SIGHASH_ALL|SIGHASH_ANYONECANPAY" => Ok(AllPlusAnyoneCanPay), + "SIGHASH_NONE|SIGHASH_ANYONECANPAY" => Ok(NonePlusAnyoneCanPay), + "SIGHASH_SINGLE|SIGHASH_ANYONECANPAY" => Ok(SinglePlusAnyoneCanPay), + _ => Err(SighashTypeParseError { unrecognized: s.to_owned() }), + } + } +} + +impl EcdsaSighashType { + /// Splits the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean. + pub(crate) fn split_anyonecanpay_flag(self) -> (Self, bool) { + use EcdsaSighashType::*; + + match self { + All => (All, false), + None => (None, false), + Single => (Single, false), + AllPlusAnyoneCanPay => (All, true), + NonePlusAnyoneCanPay => (None, true), + SinglePlusAnyoneCanPay => (Single, true), + } + } + + /// Checks if the sighash type is [`Self::Single`] or [`Self::SinglePlusAnyoneCanPay`]. + /// + /// This matches Bitcoin Core's behavior where SIGHASH_SINGLE bug check is based on the base + /// type (after masking with 0x1f), regardless of the ANYONECANPAY flag. + /// + /// See: + pub fn is_single(&self) -> bool { matches!(self, Self::Single | Self::SinglePlusAnyoneCanPay) } + + /// Constructs a new [`EcdsaSighashType`] from a raw `u32`. + /// + /// **Note**: this replicates consensus behaviour, for current standardness rules correctness + /// you probably want [`Self::from_standard`]. + /// + /// This might cause unexpected behavior because it does not roundtrip. That is, + /// `EcdsaSighashType::from_consensus(n) as u32 != n` for non-standard values of `n`. While + /// verifying signatures, the user should retain the `n` and use it to compute the signature hash + /// message. + pub fn from_consensus(n: u32) -> Self { + use EcdsaSighashType::*; + + // In Bitcoin Core, the SignatureHash function will mask the (int32) value with + // 0x1f to (apparently) deactivate ACP when checking for SINGLE and NONE bits. + // We however want to be matching also against on ACP-masked ALL, SINGLE, and NONE. + // So here we re-activate ACP. + let mask = 0x1f | 0x80; + match n & mask { + // "real" sighashes + 0x01 => All, + 0x02 => None, + 0x03 => Single, + 0x81 => AllPlusAnyoneCanPay, + 0x82 => NonePlusAnyoneCanPay, + 0x83 => SinglePlusAnyoneCanPay, + // catchalls + x if x & 0x80 == 0x80 => AllPlusAnyoneCanPay, + _ => All, + } + } + + /// Constructs a new [`EcdsaSighashType`] from a raw `u32`. + /// + /// # Errors + /// + /// If `n` is a non-standard sighash value. + pub fn from_standard(n: u32) -> Result { + use EcdsaSighashType::*; + + match n { + // Standard sighashes, see https://github.com/bitcoin/bitcoin/blob/b805dbb0b9c90dadef0424e5b3bf86ac308e103e/src/script/interpreter.cpp#L189-L198 + 0x01 => Ok(All), + 0x02 => Ok(None), + 0x03 => Ok(Single), + 0x81 => Ok(AllPlusAnyoneCanPay), + 0x82 => Ok(NonePlusAnyoneCanPay), + 0x83 => Ok(SinglePlusAnyoneCanPay), + non_standard => Err(NonStandardSighashTypeError(non_standard)), + } + } + + /// Converts [`EcdsaSighashType`] to a `u32` sighash flag. + /// + /// The returned value is guaranteed to be a valid according to standardness rules. + pub fn to_u32(self) -> u32 { self as u32 } +} + +impl From for TapSighashType { + fn from(s: EcdsaSighashType) -> Self { + use TapSighashType::*; + + match s { + EcdsaSighashType::All => All, + EcdsaSighashType::None => None, + EcdsaSighashType::Single => Single, + EcdsaSighashType::AllPlusAnyoneCanPay => AllPlusAnyoneCanPay, + EcdsaSighashType::NonePlusAnyoneCanPay => NonePlusAnyoneCanPay, + EcdsaSighashType::SinglePlusAnyoneCanPay => SinglePlusAnyoneCanPay, + } + } +} + +impl TapSighashType { + /// Breaks the sighash flag into the "real" sighash flag and the `SIGHASH_ANYONECANPAY` boolean. + pub(crate) fn split_anyonecanpay_flag(self) -> (Self, bool) { + use TapSighashType::*; + + match self { + Default => (Default, false), + All => (All, false), + None => (None, false), + Single => (Single, false), + AllPlusAnyoneCanPay => (All, true), + NonePlusAnyoneCanPay => (None, true), + SinglePlusAnyoneCanPay => (Single, true), + } + } + + /// Constructs a new [`TapSighashType`] from a raw `u8`. + pub fn from_consensus_u8(sighash_type: u8) -> Result { + use TapSighashType::*; + + Ok(match sighash_type { + 0x00 => Default, + 0x01 => All, + 0x02 => None, + 0x03 => Single, + 0x81 => AllPlusAnyoneCanPay, + 0x82 => NonePlusAnyoneCanPay, + 0x83 => SinglePlusAnyoneCanPay, + x => return Err(InvalidSighashTypeError(x.into())), + }) + } +} + +/// Integer is not a consensus valid sighash type. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidSighashTypeError(pub u32); + +impl fmt::Display for InvalidSighashTypeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "invalid sighash type {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidSighashTypeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// This type is consensus valid but an input including it would prevent the transaction from +/// being relayed on today's Bitcoin network. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct NonStandardSighashTypeError(pub u32); + +impl fmt::Display for NonStandardSighashTypeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "non-standard sighash type {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for NonStandardSighashTypeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// Error returned for failure during parsing one of the sighash types. +/// +/// This is currently returned for unrecognized sighash strings. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct SighashTypeParseError { + /// The unrecognized string we attempted to parse. + pub unrecognized: String, +} + +impl fmt::Display for SighashTypeParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "unrecognized SIGHASH string '{}'", self.unrecognized) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SighashTypeParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +impl> SighashCache { + /// Constructs a new `SighashCache` from an unsigned transaction. + /// + /// The sighash components are computed in a lazy manner when required. For the generated + /// sighashes to be valid, no fields in the transaction may change except for script_sig and + /// witness. + pub fn new(tx: R) -> Self { + Self { tx, common_cache: None, taproot_cache: None, segwit_cache: None } + } + + /// Returns the reference to the cached transaction. + pub fn transaction(&self) -> &Transaction { self.tx.borrow() } + + /// Destroys the cache and recovers the stored transaction. + pub fn into_transaction(self) -> R { self.tx } + + /// Encodes the BIP-0341 signing data for any flag type into a given object implementing the + /// [`io::Write`] trait. + /// + /// In order to sign, the data written by this function must be hashed using a tagged hash. For + /// example usage see [`Self::taproot_signature_hash`] and + /// [`Self::taproot_key_spend_signature_hash`]. + pub fn taproot_encode_signing_data_to>( + &mut self, + writer: &mut W, + input_index: usize, + prevouts: &Prevouts, + annex: Option, + leaf_hash_code_separator: Option<(TapLeafHash, u32)>, + sighash_type: TapSighashType, + ) -> Result<(), SigningDataError> { + prevouts.check_all(self.tx.borrow()).map_err(SigningDataError::sighash)?; + + let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag(); + + // epoch + 0u8.consensus_encode(writer)?; + + // * Control: + // hash_type (1). + (sighash_type as u8).consensus_encode(writer)?; + + // * Transaction Data: + // nVersion (4): the nVersion of the transaction. + self.tx.borrow().version.consensus_encode(writer)?; + + // nLockTime (4): the nLockTime of the transaction. + self.tx.borrow().lock_time.consensus_encode(writer)?; + + // If the hash_type & 0x80 does not equal SIGHASH_ANYONECANPAY: + // sha_prevouts (32): the SHA256 of the serialization of all input outpoints. + // sha_amounts (32): the SHA256 of the serialization of all spent output amounts. + // sha_scriptpubkeys (32): the SHA256 of the serialization of all spent output scriptPubKeys. + // sha_sequences (32): the SHA256 of the serialization of all input nSequence. + if !anyone_can_pay { + self.common_cache().prevouts.consensus_encode(writer)?; + self.taproot_cache(prevouts.get_all().map_err(SigningDataError::sighash)?) + .amounts + .consensus_encode(writer)?; + self.taproot_cache(prevouts.get_all().map_err(SigningDataError::sighash)?) + .script_pubkeys + .consensus_encode(writer)?; + self.common_cache().sequences.consensus_encode(writer)?; + } + + // If hash_type & 3 does not equal SIGHASH_NONE or SIGHASH_SINGLE: + // sha_outputs (32): the SHA256 of the serialization of all outputs in CTxOut format. + if sighash != TapSighashType::None && sighash != TapSighashType::Single { + self.common_cache().outputs.consensus_encode(writer)?; + } + + // * Data about this input: + // spend_type (1): equal to (ext_flag * 2) + annex_present, where annex_present is 0 + // if no annex is present, or 1 otherwise + let mut spend_type = 0u8; + if annex.is_some() { + spend_type |= 1u8; + } + if leaf_hash_code_separator.is_some() { + spend_type |= 2u8; + } + spend_type.consensus_encode(writer)?; + + // If hash_type & 0x80 equals SIGHASH_ANYONECANPAY: + // outpoint (36): the COutPoint of this input (32-byte hash + 4-byte little-endian). + // amount (8): value of the previous output spent by this input. + // scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. + // nSequence (4): nSequence of this input. + if anyone_can_pay { + let txin = &self.tx.borrow().tx_in(input_index).map_err(SigningDataError::sighash)?; + let previous_output = prevouts.get(input_index).map_err(SigningDataError::sighash)?; + txin.previous_output.consensus_encode(writer)?; + previous_output.amount.consensus_encode(writer)?; + previous_output.script_pubkey.consensus_encode(writer)?; + txin.sequence.consensus_encode(writer)?; + } else { + (input_index as u32).consensus_encode(writer)?; + } + + // If an annex is present (the lowest bit of spend_type is set): + // sha_annex (32): the SHA256 of (compact_size(size of annex) || annex), where annex + // includes the mandatory 0x50 prefix. + if let Some(annex) = annex { + let mut enc = sha256::Hash::engine(); + annex.consensus_encode(&mut enc)?; + let hash = sha256::Hash::from_engine(enc); + hash.consensus_encode(writer)?; + } + + // * Data about this output: + // If hash_type & 3 equals SIGHASH_SINGLE: + // sha_single_output (32): the SHA256 of the corresponding output in CTxOut format. + if sighash == TapSighashType::Single { + let mut enc = sha256::Hash::engine(); + self.tx + .borrow() + .outputs + .get(input_index) + .ok_or(TaprootError::SingleMissingOutput(SingleMissingOutputError { + input_index, + outputs_length: self.tx.borrow().outputs.len(), + })) + .map_err(SigningDataError::Sighash)? + .consensus_encode(&mut enc)?; + let hash = sha256::Hash::from_engine(enc); + hash.consensus_encode(writer)?; + } + + // if (scriptpath): + // ss += TaggedHash("TapLeaf", bytes([leaf_ver]) + ser_string(script)) + // ss += bytes([0]) + // ss += struct.pack(">( + &mut self, + input_index: usize, + prevouts: &Prevouts, + annex: Option, + leaf_hash_code_separator: Option<(TapLeafHash, u32)>, + sighash_type: TapSighashType, + ) -> Result { + let mut enc = sha256t::Hash::::engine(); + self.taproot_encode_signing_data_to( + &mut enc, + input_index, + prevouts, + annex, + leaf_hash_code_separator, + sighash_type, + ) + .map_err(SigningDataError::unwrap_sighash)?; + let inner = sha256t::Hash::::from_engine(enc); + Ok(TapSighash::from_byte_array(inner.to_byte_array())) + } + + /// Computes the BIP-0341 sighash for a key spend. + pub fn taproot_key_spend_signature_hash>( + &mut self, + input_index: usize, + prevouts: &Prevouts, + sighash_type: TapSighashType, + ) -> Result { + let mut enc = sha256t::Hash::::engine(); + self.taproot_encode_signing_data_to( + &mut enc, + input_index, + prevouts, + None, + None, + sighash_type, + ) + .map_err(SigningDataError::unwrap_sighash)?; + let inner = sha256t::Hash::::from_engine(enc); + Ok(TapSighash::from_byte_array(inner.to_byte_array())) + } + + /// Computes the BIP-0341 sighash for a script spend. + /// + /// Assumes the default `OP_CODESEPARATOR` position of `0xFFFFFFFF`. Custom values can be + /// provided through the more fine-grained API of [`SighashCache::taproot_encode_signing_data_to`]. + pub fn taproot_script_spend_signature_hash, T: Borrow>( + &mut self, + input_index: usize, + prevouts: &Prevouts, + leaf_hash: S, + sighash_type: TapSighashType, + ) -> Result { + let mut enc = sha256t::Hash::::engine(); + self.taproot_encode_signing_data_to( + &mut enc, + input_index, + prevouts, + None, + Some((leaf_hash.into(), 0xFFFFFFFF)), + sighash_type, + ) + .map_err(SigningDataError::unwrap_sighash)?; + let inner = sha256t::Hash::::from_engine(enc); + Ok(TapSighash::from_byte_array(inner.to_byte_array())) + } + + /// Encodes the BIP-0143 signing data for any flag type into a given object implementing the + /// [`std::io::Write`] trait. + /// + /// `script_code` is dependent on the type of the spend transaction. For p2wpkh use + /// [`WitnessScript::p2wpkh_script_code`], for p2wsh just pass in the witness script. (Also see + /// [`Self::p2wpkh_signature_hash`] and [`SighashCache::p2wsh_signature_hash`].) + /// + /// In order to sign, the data written by this function must be hashed using a double SHA256 + /// hash. This can be achieved either by using the [`hashes::sha256d::Hash`] type or one of the + /// custom sighash types in this module ([`SegwitV0Sighash`] and [`LegacySighash`]). + pub fn segwit_v0_encode_signing_data_to( + &mut self, + writer: &mut W, + input_index: usize, + script_code: &WitnessScript, + amount: Amount, + sighash_type: EcdsaSighashType, + ) -> Result<(), SigningDataError> { + let zero_hash = [0; 32]; + + let (sighash, anyone_can_pay) = sighash_type.split_anyonecanpay_flag(); + + self.tx.borrow().version.consensus_encode(writer)?; + + if !anyone_can_pay { + self.segwit_cache().prevouts.consensus_encode(writer)?; + } else { + zero_hash.consensus_encode(writer)?; + } + + if !anyone_can_pay + && sighash != EcdsaSighashType::Single + && sighash != EcdsaSighashType::None + { + self.segwit_cache().sequences.consensus_encode(writer)?; + } else { + zero_hash.consensus_encode(writer)?; + } + + { + let txin = &self.tx.borrow().tx_in(input_index).map_err(SigningDataError::sighash)?; + txin.previous_output.consensus_encode(writer)?; + script_code.consensus_encode(writer)?; + amount.consensus_encode(writer)?; + txin.sequence.consensus_encode(writer)?; + } + + if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None { + self.segwit_cache().outputs.consensus_encode(writer)?; + } else if sighash == EcdsaSighashType::Single + && input_index < self.tx.borrow().outputs.len() + { + let mut single_enc = LegacySighash::engine(); + self.tx.borrow().outputs[input_index].consensus_encode(&mut single_enc)?; + let hash = LegacySighash::from_engine(single_enc); + writer.write_all(hash.as_byte_array())?; + } else { + writer.write_all(&zero_hash)?; + } + + self.tx.borrow().lock_time.consensus_encode(writer)?; + sighash_type.to_u32().consensus_encode(writer)?; + Ok(()) + } + + /// Computes the BIP-0143 sighash to spend a p2wpkh transaction for any flag type. + /// + /// `script_pubkey` is the `scriptPubkey` (native SegWit) of the spend transaction + /// ([`TxOut::script_pubkey`]) or the `redeemScript` (wrapped SegWit). + pub fn p2wpkh_signature_hash( + &mut self, + input_index: usize, + script_pubkey: &crate::script::Script, + amount: Amount, + sighash_type: EcdsaSighashType, + ) -> Result { + let script_code = script_pubkey.p2wpkh_script_code().ok_or(P2wpkhError::NotP2wpkhScript)?; + + let mut enc = SegwitV0Sighash::engine(); + self.segwit_v0_encode_signing_data_to( + &mut enc, + input_index, + &script_code, + amount, + sighash_type, + ) + .map_err(SigningDataError::unwrap_sighash)?; + Ok(SegwitV0Sighash::from_engine(enc)) + } + + /// Computes the BIP-0143 sighash to spend a p2wsh transaction for any flag type. + /// + /// `witness_script` is the script that goes into the [`Witness`], + /// not the one that goes into `script_pubkey` of a [`TxOut`]. + pub fn p2wsh_signature_hash( + &mut self, + input_index: usize, + witness_script: &WitnessScript, + amount: Amount, + sighash_type: EcdsaSighashType, + ) -> Result { + let mut enc = SegwitV0Sighash::engine(); + self.segwit_v0_encode_signing_data_to( + &mut enc, + input_index, + witness_script, + amount, + sighash_type, + ) + .map_err(SigningDataError::unwrap_sighash)?; + Ok(SegwitV0Sighash::from_engine(enc)) + } + + /// Encodes the legacy signing data from which a signature hash for a given input index with a + /// given sighash flag can be computed. + /// + /// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the + /// [`EcdsaSighashType`] appended to the resulting sig, and a script written around this, but + /// this is the general (and hard) part. + /// + /// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSighashType`], + /// because internally 4 bytes are being hashed, even though only the lowest byte is appended to + /// signature in a transaction. + /// + /// # Warning + /// + /// - Does NOT attempt to support OP_CODESEPARATOR. In general this would require evaluating + /// `script_pubkey` to determine which separators get evaluated and which don't, which we don't + /// have the information to determine. + /// - Does NOT handle the sighash single bug (see "Return type" section) + /// + /// # Returns + /// + /// This function can't handle the SIGHASH_SINGLE bug internally, so it returns [`EncodeSigningDataResult`] + /// that must be handled by the caller (see [`EncodeSigningDataResult::is_sighash_single_bug`]). + pub fn legacy_encode_signing_data_to, T: ScriptHashableTag>( + &self, + writer: &mut W, + input_index: usize, + script_pubkey: &crate::script::Script, + sighash_type: U, + ) -> EncodeSigningDataResult> { + // Validate input_index. + if let Err(e) = self.tx.borrow().tx_in(input_index) { + return EncodeSigningDataResult::WriteResult(Err(SigningDataError::Sighash(e))); + } + let sighash_type: u32 = sighash_type.into(); + + if is_invalid_use_of_sighash_single( + sighash_type, + input_index, + self.tx.borrow().outputs.len(), + ) { + // We cannot correctly handle the SIGHASH_SINGLE bug here because usage of this function + // will result in the data written to the writer being hashed, however the correct + // handling of the SIGHASH_SINGLE bug is to return the 'one array' - either implement + // this behaviour manually or use `signature_hash()`. + return EncodeSigningDataResult::SighashSingleBug; + } + + fn encode_signing_data_to_inner( + self_: &Transaction, + writer: &mut W, + input_index: usize, + script_pubkey: &crate::script::Script, + sighash_type: u32, + ) -> Result<(), io::Error> { + use crate::consensus::encode::WriteExt; + + let (sighash, anyone_can_pay) = + EcdsaSighashType::from_consensus(sighash_type).split_anyonecanpay_flag(); + + self_.version.consensus_encode(writer)?; + // Add all inputs necessary.. + if anyone_can_pay { + writer.emit_compact_size(1u8)?; + self_.inputs[input_index].previous_output.consensus_encode(writer)?; + script_pubkey.consensus_encode(writer)?; + self_.inputs[input_index].sequence.consensus_encode(writer)?; + } else { + writer.emit_compact_size(self_.inputs.len())?; + for (n, input) in self_.inputs.iter().enumerate() { + input.previous_output.consensus_encode(writer)?; + if n == input_index { + script_pubkey.consensus_encode(writer)?; + } else { + ScriptPubKey::new().consensus_encode(writer)?; + } + if n != input_index + && (sighash == EcdsaSighashType::Single + || sighash == EcdsaSighashType::None) + { + Sequence::ZERO.consensus_encode(writer)?; + } else { + input.sequence.consensus_encode(writer)?; + } + } + } + // ..then all outputs + match sighash { + EcdsaSighashType::All => { + self_.outputs.consensus_encode(writer)?; + } + EcdsaSighashType::Single => { + // sign all outputs up to and including this one, but erase + // all of them except for this one + let count = input_index.min(self_.outputs.len() - 1); + writer.emit_compact_size(count + 1)?; + for _ in 0..count { + // consensus encoding of the "NULL txout" - max amount, empty script_pubkey + writer + .write_all(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00])?; + } + self_.outputs[count].consensus_encode(writer)?; + } + EcdsaSighashType::None => { + writer.emit_compact_size(0u8)?; + } + _ => unreachable!(), + }; + self_.lock_time.consensus_encode(writer)?; + sighash_type.to_le_bytes().consensus_encode(writer)?; + Ok(()) + } + + EncodeSigningDataResult::WriteResult( + encode_signing_data_to_inner( + self.tx.borrow(), + writer, + input_index, + script_pubkey, + sighash_type, + ) + .map_err(Into::into), + ) + } + + /// Computes a legacy signature hash for a given input index with a given sighash flag. + /// + /// To actually produce a scriptSig, this hash needs to be run through an ECDSA signer, the + /// [`EcdsaSighashType`] appended to the resulting sig, and a script written around this, but + /// this is the general (and hard) part. + /// + /// The `sighash_type` supports an arbitrary `u32` value, instead of just [`EcdsaSighashType`], + /// because internally 4 bytes are being hashed, even though only the lowest byte is appended to + /// signature in a transaction. + /// + /// This function correctly handles the sighash single bug by returning the 'one array'. The + /// sighash single bug becomes exploitable when one tries to sign a transaction with + /// `SIGHASH_SINGLE` and there is not a corresponding output with the same index as the input. + /// + /// # Warning + /// + /// Does NOT attempt to support OP_CODESEPARATOR. In general this would require evaluating + /// `script_pubkey` to determine which separators get evaluated and which don't, which we don't + /// have the information to determine. + pub fn legacy_signature_hash( + &self, + input_index: usize, + script_pubkey: &crate::script::Script, + sighash_type: u32, + ) -> Result { + let mut engine = LegacySighash::engine(); + match self + .legacy_encode_signing_data_to(&mut engine, input_index, script_pubkey, sighash_type) + .is_sighash_single_bug() + { + Ok(true) => Ok(LegacySighash::from_byte_array(UINT256_ONE)), + Ok(false) => Ok(LegacySighash::from_engine(engine)), + Err(e) => Err(e.unwrap_sighash()), + } + } + + #[inline] + fn common_cache(&mut self) -> &CommonCache { + Self::common_cache_minimal_borrow(&mut self.common_cache, self.tx.borrow()) + } + + fn common_cache_minimal_borrow<'a>( + common_cache: &'a mut Option, + tx: &Transaction, + ) -> &'a CommonCache { + common_cache.get_or_insert_with(|| { + let mut enc_prevouts = sha256::Hash::engine(); + let mut enc_sequences = sha256::Hash::engine(); + for txin in tx.inputs.iter() { + txin.previous_output.consensus_encode(&mut enc_prevouts).unwrap(); + txin.sequence.consensus_encode(&mut enc_sequences).unwrap(); + } + CommonCache { + prevouts: sha256::Hash::from_engine(enc_prevouts), + sequences: sha256::Hash::from_engine(enc_sequences), + outputs: { + let mut enc = sha256::Hash::engine(); + for txout in tx.outputs.iter() { + txout.consensus_encode(&mut enc).unwrap(); + } + sha256::Hash::from_engine(enc) + }, + } + }) + } + + fn segwit_cache(&mut self) -> &SegwitCache { + let common_cache = &mut self.common_cache; + let tx = self.tx.borrow(); + self.segwit_cache.get_or_insert_with(|| { + let common_cache = Self::common_cache_minimal_borrow(common_cache, tx); + SegwitCache { + prevouts: common_cache.prevouts.hash_again(), + sequences: common_cache.sequences.hash_again(), + outputs: common_cache.outputs.hash_again(), + } + }) + } + + fn taproot_cache>(&mut self, prevouts: &[T]) -> &TaprootCache { + self.taproot_cache.get_or_insert_with(|| { + let mut enc_amounts = sha256::Hash::engine(); + let mut enc_script_pubkeys = sha256::Hash::engine(); + for prevout in prevouts { + prevout.borrow().amount.consensus_encode(&mut enc_amounts).unwrap(); + prevout.borrow().script_pubkey.consensus_encode(&mut enc_script_pubkeys).unwrap(); + } + TaprootCache { + amounts: sha256::Hash::from_engine(enc_amounts), + script_pubkeys: sha256::Hash::from_engine(enc_script_pubkeys), + } + }) + } +} + +impl> SighashCache { + /// Allows modification of witnesses. + /// + /// As a lint against accidental changes to the transaction that would invalidate the cache and + /// signatures, `SighashCache` borrows the Transaction so that modifying it is not possible + /// without hacks with `UnsafeCell` (which is hopefully a strong indication that something is + /// wrong). However modifying witnesses never invalidates the cache and is actually useful - one + /// usually wants to put the signature generated for an input into the witness of that input. + /// + /// This method allows doing exactly that if the transaction is owned by the `SighashCache` or + /// borrowed mutably. + /// + /// # Examples + /// + /// ```ignore + /// # // Example is an incomplete section of code that does not compile by itself + /// let mut sighasher = SighashCache::new(&mut tx_to_sign); + /// let sighash = sighasher.p2wpkh_signature_hash(input_index, &utxo.script_pubkey, amount, sighash_type)?; + /// + /// let signature = { + /// // Sign the sighash using secp256k1 + /// }; + /// + /// *sighasher.witness_mut(input_index).unwrap() = Witness::p2wpkh(&signature, &pk); + /// ``` + /// + /// For full signing code see the [`SegWit v0`] and [`taproot`] signing examples. + /// + /// [`SegWit v0`]: + /// [`taproot`]: + pub fn witness_mut(&mut self, input_index: usize) -> Option<&mut Witness> { + self.tx.borrow_mut().inputs.get_mut(input_index).map(|i| &mut i.witness) + } +} + +/// The `Annex` struct is a slice wrapper enforcing first byte is `0x50`. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct Annex<'a>(&'a [u8]); + +impl<'a> Annex<'a> { + /// Constructs a new `Annex` struct checking the first byte is `0x50`. + pub fn new(annex_bytes: &'a [u8]) -> Result { + match annex_bytes.first() { + Some(&TAPROOT_ANNEX_PREFIX) => Ok(Annex(annex_bytes)), + Some(other) => Err(AnnexError::IncorrectPrefix(*other)), + None => Err(AnnexError::Empty), + } + } + + /// Returns the Annex bytes data (including first byte `0x50`). + pub fn as_bytes(&self) -> &[u8] { self.0 } +} + +impl Encodable for Annex<'_> { + fn consensus_encode(&self, w: &mut W) -> Result { + encode::consensus_encode_with_size(self.0, w) + } +} + +/// Error computing a Taproot sighash. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum TaprootError { + /// Index out of bounds when accessing transaction input vector. + InputsIndex(transaction::InputsIndexError), + /// Using `SIGHASH_SINGLE` requires an output at the same index as the input. + SingleMissingOutput(SingleMissingOutputError), + /// Prevouts size error. + PrevoutsSize(PrevoutsSizeError), + /// Prevouts index error. + PrevoutsIndex(PrevoutsIndexError), + /// Prevouts kind error. + PrevoutsKind(PrevoutsKindError), + /// Invalid Sighash type. + InvalidSighashType(u32), +} + +impl From for TaprootError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for TaprootError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InputsIndex(ref e) => write_err!(f, "inputs index"; e), + Self::SingleMissingOutput(ref e) => write_err!(f, "sighash single"; e), + Self::PrevoutsSize(ref e) => write_err!(f, "prevouts size"; e), + Self::PrevoutsIndex(ref e) => write_err!(f, "prevouts index"; e), + Self::PrevoutsKind(ref e) => write_err!(f, "prevouts kind"; e), + Self::InvalidSighashType(hash_ty) => + write!(f, "invalid Taproot sighash type : {} ", hash_ty), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TaprootError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InputsIndex(ref e) => Some(e), + Self::SingleMissingOutput(ref e) => Some(e), + Self::PrevoutsSize(ref e) => Some(e), + Self::PrevoutsIndex(ref e) => Some(e), + Self::PrevoutsKind(ref e) => Some(e), + Self::InvalidSighashType(_) => None, + } + } +} + +impl From for TaprootError { + fn from(e: transaction::InputsIndexError) -> Self { Self::InputsIndex(e) } +} + +impl From for TaprootError { + fn from(e: PrevoutsSizeError) -> Self { Self::PrevoutsSize(e) } +} + +impl From for TaprootError { + fn from(e: PrevoutsKindError) -> Self { Self::PrevoutsKind(e) } +} + +impl From for TaprootError { + fn from(e: PrevoutsIndexError) -> Self { Self::PrevoutsIndex(e) } +} + +/// Error computing a P2WPKH sighash. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum P2wpkhError { + /// Error computing the sighash. + Sighash(transaction::InputsIndexError), + /// Script is not a witness program for a p2wpkh output. + NotP2wpkhScript, +} + +impl From for P2wpkhError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for P2wpkhError { + fn from(value: transaction::InputsIndexError) -> Self { Self::Sighash(value) } +} + +impl fmt::Display for P2wpkhError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Sighash(ref e) => write_err!(f, "error encoding SegWit v0 signing data"; e), + Self::NotP2wpkhScript => write!(f, "script is not a script pubkey for a p2wpkh output"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for P2wpkhError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Sighash(ref e) => Some(e), + Self::NotP2wpkhScript => None, + } + } +} + +/// Using `SIGHASH_SINGLE` requires an output at the same index as the input. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct SingleMissingOutputError { + /// Input index. + pub input_index: usize, + /// Length of the output vector. + pub outputs_length: usize, +} + +impl fmt::Display for SingleMissingOutputError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "sighash single requires an output at the same index as the input \ + (input index: {}, outputs length: {})", + self.input_index, self.outputs_length + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SingleMissingOutputError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// Annex must be at least one byte long and the first bytes must be `0x50`. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum AnnexError { + /// The annex is empty. + Empty, + /// Incorrect prefix byte in the annex. + IncorrectPrefix(u8), +} + +impl From for AnnexError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for AnnexError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Empty => write!(f, "the annex is empty"), + Self::IncorrectPrefix(byte) => + write!(f, "incorrect prefix byte in the annex {:02x}, expecting 0x50", byte), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for AnnexError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Empty | Self::IncorrectPrefix(_) => None, + } + } +} + +fn is_invalid_use_of_sighash_single(sighash: u32, input_index: usize, outputs_len: usize) -> bool { + let ty = EcdsaSighashType::from_consensus(sighash); + ty.is_single() && input_index >= outputs_len +} + +/// Result of [`SighashCache::legacy_encode_signing_data_to`]. +/// +/// This type forces the caller to handle SIGHASH_SINGLE bug case. +/// +/// This corner case can't be expressed using standard `Result`, +/// in a way that is both convenient and not-prone to accidental +/// mistakes (like calling `.expect("writer never fails")`). +#[must_use] +pub enum EncodeSigningDataResult { + /// Input data is an instance of `SIGHASH_SINGLE` bug + SighashSingleBug, + /// Operation performed normally. + WriteResult(Result<(), E>), +} + +impl EncodeSigningDataResult { + /// Checks for SIGHASH_SINGLE bug returning error if the writer failed. + /// + /// This method is provided for easy and correct handling of the result because + /// SIGHASH_SINGLE bug is a special case that must not be ignored nor cause panicking. + /// Since the data is usually written directly into a hasher which never fails, + /// the recommended pattern to handle this is: + /// + /// ```rust + /// # use bitcoin::consensus::deserialize; + /// # use bitcoin::hashes::{sha256d, hex::FromHex}; + /// # use bitcoin::sighash::SighashCache; + /// # use bitcoin::Transaction; + /// # let mut writer = sha256d::Hash::engine(); + /// # let input_index = 0; + /// # let script_pubkey = bitcoin::ScriptPubKeyBuf::new(); + /// # let sighash_u32 = 0u32; + /// # const SOME_TX: &'static str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; + /// # let raw_tx = Vec::from_hex(SOME_TX).unwrap(); + /// # let tx: Transaction = deserialize(&raw_tx).unwrap(); + /// let cache = SighashCache::new(&tx); + /// if cache.legacy_encode_signing_data_to(&mut writer, input_index, &script_pubkey, sighash_u32) + /// .is_sighash_single_bug() + /// .expect("writer can't fail") { + /// // use a hash value of "1", instead of computing the actual hash due to SIGHASH_SINGLE bug + /// } else { + /// // use the hash from `writer` + /// } + /// ``` + #[allow(clippy::wrong_self_convention)] // Consume self so we can take the error. + pub fn is_sighash_single_bug(self) -> Result { + match self { + Self::SighashSingleBug => Ok(true), + Self::WriteResult(Ok(())) => Ok(false), + Self::WriteResult(Err(e)) => Err(e), + } + } + + /// Maps a `Result` to `Result` by applying a function to a + /// contained [`Err`] value, leaving an [`Ok`] value untouched. + /// + /// Like [`Result::map_err`]. + pub fn map_err(self, f: F) -> EncodeSigningDataResult + where + F: FnOnce(E) -> E2, + { + match self { + Self::SighashSingleBug => EncodeSigningDataResult::SighashSingleBug, + Self::WriteResult(Err(e)) => + EncodeSigningDataResult::WriteResult(Err(f(e))), + Self::WriteResult(Ok(o)) => + EncodeSigningDataResult::WriteResult(Ok(o)), + } + } +} + +/// Error returned when writing signing data fails. +#[derive(Debug)] +pub enum SigningDataError { + /// Can happen only when using `*_encode_signing_*` methods with custom writers, engines + /// like those used in `*_signature_hash` methods do not error. + Io(io::Error), + /// An argument to the called sighash function was invalid. + Sighash(E), +} + +impl From for SigningDataError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl SigningDataError { + /// Returns the sighash variant, panicking if it's I/O. + /// + /// This is used when encoding to hash engine when we know that I/O doesn't fail. + fn unwrap_sighash(self) -> E { + match self { + Self::Sighash(error) => error, + Self::Io(error) => panic!("hash engine error {}", error), + } + } + + fn sighash>(error: E2) -> Self { Self::Sighash(error.into()) } +} + +// We cannot simultaneously impl `From`. it was determined that this alternative requires less +// manual `map_err` calls. +impl From for SigningDataError { + fn from(value: io::Error) -> Self { Self::Io(value) } +} + +impl fmt::Display for SigningDataError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Io(error) => write_err!(f, "failed to write sighash data"; error), + Self::Sighash(error) => write_err!(f, "failed to compute sighash data"; error), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SigningDataError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Io(error) => Some(error), + Self::Sighash(error) => Some(error), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for EcdsaSighashType { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let choice = u.int_in_range(0..=5)?; + match choice { + 0 => Ok(Self::All), + 1 => Ok(Self::None), + 2 => Ok(Self::Single), + 3 => Ok(Self::AllPlusAnyoneCanPay), + 4 => Ok(Self::NonePlusAnyoneCanPay), + _ => Ok(Self::SinglePlusAnyoneCanPay), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for TapSighashType { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let choice = u.int_in_range(0..=6)?; + match choice { + 0 => Ok(Self::Default), + 1 => Ok(Self::All), + 2 => Ok(Self::None), + 3 => Ok(Self::Single), + 4 => Ok(Self::AllPlusAnyoneCanPay), + 5 => Ok(Self::NonePlusAnyoneCanPay), + _ => Ok(Self::SinglePlusAnyoneCanPay), + } + } +} + +#[cfg(test)] +mod tests { + use hashes::HashEngine; + use hex::FromHex; + use hex_lit::hex; + + use super::*; + use crate::consensus::deserialize; + use crate::locktime::absolute; + use crate::script::{ + ScriptBufExt as _, ScriptPubKey, ScriptPubKeyBuf, TapScriptBuf, WitnessScriptBuf, + }; + use crate::TxIn; + + extern crate serde_json; + + const DUMMY_TXOUT: TxOut = TxOut { amount: Amount::MIN, script_pubkey: ScriptPubKeyBuf::new() }; + + #[test] + fn sighash_single_bug() { + // We need a tx with more inputs than outputs. + let tx = Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn::EMPTY_COINBASE, TxIn::EMPTY_COINBASE], + outputs: vec![DUMMY_TXOUT], + }; + let script = ScriptPubKeyBuf::new(); + let cache = SighashCache::new(&tx); + + let sighash_single = 3; + let got = cache.legacy_signature_hash(1, &script, sighash_single).expect("sighash"); + let want = LegacySighash::from_byte_array(UINT256_ONE); + assert_eq!(got, want); + + // https://github.com/rust-bitcoin/rust-bitcoin/issues/4112 + let sighash_single = 131; + let got = cache.legacy_signature_hash(1, &script, sighash_single).expect("sighash"); + let want = LegacySighash::from_byte_array(UINT256_ONE); + assert_eq!(got, want); + } + + #[test] + #[cfg(feature = "serde")] + fn legacy_sighash() { + use serde_json::Value; + + use crate::sighash::SighashCache; + + fn run_test_sighash( + tx: &str, + script: &str, + input_index: usize, + hash_type: i64, + expected_result: &str, + ) { + let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()[..]).unwrap(); + let script = ScriptPubKeyBuf::from(Vec::from_hex(script).unwrap()); + let mut raw_expected = Vec::from_hex(expected_result).unwrap(); + raw_expected.reverse(); + let bytes = <[u8; 32]>::try_from(&raw_expected[..]).unwrap(); + let want = LegacySighash::from_byte_array(bytes); + + let cache = SighashCache::new(&tx); + let got = cache.legacy_signature_hash(input_index, &script, hash_type as u32).unwrap(); + + assert_eq!(got, want); + } + + // These test vectors were stolen from libbtc, which is Copyright 2014 Jonas Schnelli MIT + // They were transformed by replacing {...} with run_test_sighash(...), then the ones containing + // OP_CODESEPARATOR in their pubkeys were removed + let data = include_str!("../../tests/data/legacy_sighash.json"); + + let testdata = serde_json::from_str::(data).unwrap().as_array().unwrap().clone(); + for t in testdata.iter().skip(1) { + let tx = t.get(0).unwrap().as_str().unwrap(); + let script = t.get(1).unwrap().as_str().unwrap_or(""); + let input_index = t.get(2).unwrap().as_u64().unwrap(); + let hash_type = t.get(3).unwrap().as_i64().unwrap(); + let expected_sighash = t.get(4).unwrap().as_str().unwrap(); + run_test_sighash(tx, script, input_index as usize, hash_type, expected_sighash); + } + } + + #[test] + fn tap_sighash_hash() { + let bytes = hex!("00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000"); + let expected = hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0"); + let mut enc = sha256t::Hash::::engine(); + enc.input(&bytes); + let hash = sha256t::Hash::::from_engine(enc); + assert_eq!(expected, hash.to_byte_array()); + } + + #[test] + fn sighashes_keyspending() { + // following test case has been taken from Bitcoin Core test framework + + test_taproot_sighash( + "020000000164eb050a5e3da0c2a65e4786f26d753b7bc69691fabccafb11f7acef36641f1846010000003101b2b404392a22000000000017a9147f2bde86fe78bf68a0544a4f290e12f0b7e0a08c87580200000000000017a91425d11723074ecfb96a0a83c3956bfaf362ae0c908758020000000000001600147e20f938993641de67bb0cdd71682aa34c4d29ad5802000000000000160014c64984dc8761acfa99418bd6bedc79b9287d652d72000000", + "01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500", + 0, + "33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703", + TapSighashType::Default, None, None, None + ); + + test_taproot_sighash( + "0200000002fff49be59befe7566050737910f6ccdc5e749c7f8860ddc140386463d88c5ad0f3000000002cf68eb4a3d67f9d4c079249f7e4f27b8854815cb1ed13842d4fbf395f9e217fd605ee24090100000065235d9203f458520000000000160014b6d48333bb13b4c644e57c43a9a26df3a44b785e58020000000000001976a914eea9461a9e1e3f765d3af3e726162e0229fe3eb688ac58020000000000001976a9143a8869c9f2b5ea1d4ff3aeeb6a8fb2fffb1ad5fe88ac0ad7125c", + "02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece", + 1, + "626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8", + TapSighashType::All, None, None, None + ); + + test_taproot_sighash( + "0200000001350005f65aa830ced2079df348e2d8c2bdb4f10e2dde6a161d8a07b40d1ad87dae000000001611d0d603d9dc0e000000000017a914459b6d7d6bbb4d8837b4bf7e9a4556f952da2f5c8758020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88ac58020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88aca71c1f4f", + "01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c", + 0, + "dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c", + TapSighashType::AllPlusAnyoneCanPay, None, None, None + ); + + test_taproot_sighash( + "020000000185bed1a6da2bffbd60ec681a1bfb71c5111d6395b99b3f8b2bf90167111bcb18f5010000007c83ace802ded24a00000000001600142c4698f9f7a773866879755aa78c516fb332af8e5802000000000000160014d38639dfbac4259323b98a472405db0c461b31fa61073747", + "0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621", + 0, + "3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067", + TapSighashType::None, None, None, None + ); + + test_taproot_sighash( + "eb93dbb901028c8515589dac980b6e7f8e4088b77ed866ca0d6d210a7218b6fd0f6b22dd6d7300000000eb4740a9047efc0e0000000000160014913da2128d8fcf292b3691db0e187414aa1783825802000000000000160014913da2128d8fcf292b3691db0e187414aa178382580200000000000017a9143dd27f01c6f7ef9bb9159937b17f17065ed01a0c875802000000000000160014d7630e19df70ada9905ede1722b800c0005f246641000000", + "013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55", + 0, + "2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae", + TapSighashType::NonePlusAnyoneCanPay, None, None, None + ); + + test_taproot_sighash( + "02000000017836b409a5fed32211407e44b971591f2032053f14701fb5b3a30c0ff382f2cc9c0100000061ac55f60288fb5600000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ac58020000000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ace4000000", + "01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80", + 0, + "30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88", + TapSighashType::Single, None, None, None + ); + + test_taproot_sighash( + "0100000001aa6deae89d5e0aaca58714fc76ef6f3c8284224888089232d4e663843ed3ab3eae010000008b6657a60450cb4c0000000000160014a3d42b5413ef0c0701c4702f3cd7d4df222c147058020000000000001976a91430b4ed8723a4ee8992aa2c8814cfe5c3ad0ab9d988ac5802000000000000160014365b1166a6ed0a5e8e9dff17a6d00bbb43454bc758020000000000001976a914bc98c51a84fe7fad5dc380eb8b39586eff47241688ac4f313247", + "0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69", + 0, + "bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df", + TapSighashType::SinglePlusAnyoneCanPay, None, None, None + ); + } + + #[test] + fn sighashes_with_annex() { + test_taproot_sighash( + "0200000001df8123752e8f37d132c4e9f1ff7e4f9b986ade9211267e9ebd5fd22a5e718dec6d01000000ce4023b903cb7b23000000000017a914a18b36ea7a094db2f4940fc09edf154e86de7bd787580200000000000017a914afd0d512a2c5c2b40e25669e9cc460303c325b8b87580200000000000017a914a18b36ea7a094db2f4940fc09edf154e86de7bd787f6020000", + "01ea49260000000000225120ab5e9800806bf18cb246edcf5fe63441208fe955a4b5a35bbff65f5db622a010", + 0, + "3b003000add359a364a156e73e02846782a59d0d95ca8c4638aaad99f2ef915c", + TapSighashType::SinglePlusAnyoneCanPay, + Some("507b979802e62d397acb29f56743a791894b99372872fc5af06a4f6e8d242d0615cda53062bb20e6ec79756fe39183f0c128adfe85559a8fa042b042c018aa8010143799e44f0893c40e1e"), + None, + None, + ); + } + + #[test] + fn sighashes_with_script_path() { + test_taproot_sighash( + "020000000189fc651483f9296b906455dd939813bf086b1bbe7c77635e157c8e14ae29062195010000004445b5c7044561320000000000160014331414dbdada7fb578f700f38fb69995fc9b5ab958020000000000001976a914268db0a8104cc6d8afd91233cc8b3d1ace8ac3ef88ac580200000000000017a914ec00dcb368d6a693e11986d265f659d2f59e8be2875802000000000000160014c715799a49a0bae3956df9c17cb4440a673ac0df6f010000", + "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182", + 0, + "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e", + TapSighashType::All, + None, + Some("20cc4e1107aea1d170c5ff5b6817e1303010049724fb3caa7941792ea9d29b3e2bacab"), + None, + ); + } + + #[test] + fn sighashes_with_script_path_raw_hash() { + test_taproot_sighash( + "020000000189fc651483f9296b906455dd939813bf086b1bbe7c77635e157c8e14ae29062195010000004445b5c7044561320000000000160014331414dbdada7fb578f700f38fb69995fc9b5ab958020000000000001976a914268db0a8104cc6d8afd91233cc8b3d1ace8ac3ef88ac580200000000000017a914ec00dcb368d6a693e11986d265f659d2f59e8be2875802000000000000160014c715799a49a0bae3956df9c17cb4440a673ac0df6f010000", + "011bec34000000000022512028055142ea437db73382e991861446040b61dd2185c4891d7daf6893d79f7182", + 0, + "d66de5274a60400c7b08c86ba6b7f198f40660079edf53aca89d2a9501317f2e", + TapSighashType::All, + None, + None, + Some("15a2530514e399f8b5cf0b3d3112cf5b289eaa3e308ba2071b58392fdc6da68a"), + ); + } + + #[test] + fn sighashes_with_annex_and_script() { + test_taproot_sighash( + "020000000132fb72cb8fba496755f027a9743e2d698c831fdb8304e4d1a346ac92cbf51acba50100000026bdc7df044aad34000000000017a9144fa2554ed6174586854fa3bc01de58dcf33567d0875802000000000000160014950367e1e62cdf240b35b883fc2f5e39f0eb9ab95802000000000000160014950367e1e62cdf240b35b883fc2f5e39f0eb9ab958020000000000001600141b31217d48ccc8760dcc0710fade5866d628e733a02d5122", + "011458360000000000225120a7baec3fb9f84614e3899fcc010c638f80f13539344120e1f4d8b68a9a011a13", + 0, + "a0042aa434f9a75904b64043f2a283f8b4c143c7f4f7f49a6cbe5b9f745f4c15", + TapSighashType::All, + Some("50a6272b470e1460e3332ade7bb14b81671c564fb6245761bd5bd531394b28860e0b3808ab229fb51791fb6ae6fa82d915b2efb8f6df83ae1f5ab3db13e30928875e2a22b749d89358de481f19286cd4caa792ce27f9559082d227a731c5486882cc707f83da361c51b7aadd9a0cf68fe7480c410fa137b454482d9a1ebf0f96d760b4d61426fc109c6e8e99a508372c45caa7b000a41f8251305da3f206c1849985ba03f3d9592832b4053afbd23ab25d0465df0bc25a36c223aacf8e04ec736a418c72dc319e4da3e972e349713ca600965e7c665f2090d5a70e241ac164115a1f5639f28b1773327715ca307ace64a2de7f0e3df70a2ffee3857689f909c0dad46d8a20fa373a4cc6eed6d4c9806bf146f0d76baae1"), + Some("7520ab9160dd8299dc1367659be3e8f66781fe440d52940c7f8d314a89b9f2698d406ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac"), + None, + ); + } + + #[test] + #[rustfmt::skip] // Allow long function call `taproot_signature_hash`. + fn sighash_errors() { + use crate::transaction::{IndexOutOfBoundsError, InputsIndexError}; + + let dumb_tx = Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn::EMPTY_COINBASE], + outputs: vec![], + }; + let mut c = SighashCache::new(&dumb_tx); + + // 1.29 fixes + let empty_vec = vec![]; + let empty_prevouts : Prevouts = Prevouts::All(&empty_vec); + assert_eq!( + c.taproot_signature_hash(0, &empty_prevouts, None, None, TapSighashType::All), + Err(TaprootError::PrevoutsSize(PrevoutsSizeError)) + ); + let two = [DUMMY_TXOUT, DUMMY_TXOUT]; + let too_many_prevouts = Prevouts::All(&two); + assert_eq!( + c.taproot_signature_hash(0, &too_many_prevouts, None, None, TapSighashType::All), + Err(TaprootError::PrevoutsSize(PrevoutsSizeError)) + ); + let tx_out = DUMMY_TXOUT; + let prevout = Prevouts::One(1, &tx_out); + assert_eq!( + c.taproot_signature_hash(0, &prevout, None, None, TapSighashType::All), + Err(TaprootError::PrevoutsKind(PrevoutsKindError)) + ); + assert_eq!( + c.taproot_signature_hash(0, &prevout, None, None, TapSighashType::AllPlusAnyoneCanPay), + Err(TaprootError::PrevoutsIndex(PrevoutsIndexError::InvalidOneIndex)) + ); + assert_eq!( + c.taproot_signature_hash(10, &prevout, None, None, TapSighashType::AllPlusAnyoneCanPay), + Err(InputsIndexError(IndexOutOfBoundsError { + index: 10, + length: 1 + }).into()) + ); + let prevout = Prevouts::One(0, &tx_out); + assert_eq!( + c.taproot_signature_hash(0, &prevout, None, None, TapSighashType::SinglePlusAnyoneCanPay), + Err(TaprootError::SingleMissingOutput(SingleMissingOutputError { + input_index: 0, + outputs_length: 0 + })) + ); + assert_eq!( + c.legacy_signature_hash(10, ScriptPubKey::new(), 0u32), + Err(InputsIndexError(IndexOutOfBoundsError { + index: 10, + length: 1 + })) + ); + } + + #[test] + fn annex_errors() { + assert_eq!(Annex::new(&[]), Err(AnnexError::Empty)); + assert_eq!(Annex::new(&[0x51]), Err(AnnexError::IncorrectPrefix(0x51))); + assert_eq!(Annex::new(&[0x51, 0x50]), Err(AnnexError::IncorrectPrefix(0x51))); + } + + #[allow(clippy::too_many_arguments)] + fn test_taproot_sighash( + tx_hex: &str, + prevout_hex: &str, + input_index: usize, + expected_hash: &str, + sighash_type: TapSighashType, + annex_hex: Option<&str>, + script_hex: Option<&str>, + script_leaf_hash: Option<&str>, + ) { + let tx_bytes = Vec::from_hex(tx_hex).unwrap(); + let tx: Transaction = deserialize(&tx_bytes).unwrap(); + let prevout_bytes = Vec::from_hex(prevout_hex).unwrap(); + let prevouts: Vec = deserialize(&prevout_bytes).unwrap(); + let annex_inner; + let annex = match annex_hex { + Some(annex_hex) => { + annex_inner = Vec::from_hex(annex_hex).unwrap(); + Some(Annex::new(&annex_inner).unwrap()) + } + None => None, + }; + + let leaf_hash = match (script_hex, script_leaf_hash) { + (Some(script_hex), _) => { + let script_inner = TapScriptBuf::from_hex_no_length_prefix(script_hex).unwrap(); + Some(ScriptPath::with_defaults(&script_inner).leaf_hash()) + } + (_, Some(script_leaf_hash)) => Some(script_leaf_hash.parse::().unwrap()), + _ => None, + }; + // All our tests use the default `0xFFFFFFFF` codeseparator value + let leaf_hash = leaf_hash.map(|lh| (lh, 0xFFFFFFFF)); + + let prevouts = if sighash_type.split_anyonecanpay_flag().1 && tx_bytes[0] % 2 == 0 { + // for anyonecanpay the `Prevouts::All` variant is good anyway, but sometimes we want to + // test other codepaths + Prevouts::One(input_index, prevouts[input_index].clone()) + } else { + Prevouts::All(&prevouts) + }; + + let mut sighash_cache = SighashCache::new(&tx); + + let hash = sighash_cache + .taproot_signature_hash(input_index, &prevouts, annex, leaf_hash, sighash_type) + .unwrap(); + let expected = Vec::from_hex(expected_hash).unwrap(); + assert_eq!(expected, hash.to_byte_array()); + } + + #[cfg(feature = "serde")] + #[test] + fn bip_341_sighash_tests() { + use hex::DisplayHex; + + fn sighash_deser_numeric<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + use serde::de::{Deserialize, Error, Unexpected}; + + let raw = u8::deserialize(deserializer)?; + TapSighashType::from_consensus_u8(raw).map_err(|_| { + D::Error::invalid_value( + Unexpected::Unsigned(raw.into()), + &"number in range 0-3 or 0x81-0x83", + ) + }) + } + + use secp256k1::SecretKey; + + use crate::consensus::serde as con_serde; + use crate::crypto::key::XOnlyPublicKey; + use crate::taproot::{TapNodeHash, TapTweakHash}; + + #[derive(serde::Deserialize)] + struct UtxoSpent { + #[serde(rename = "scriptPubKey")] + script_pubkey: ScriptPubKeyBuf, + #[serde(rename = "amountSats")] + #[serde(with = "crate::amount::serde::as_sat")] + amount: Amount, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KpsGiven { + #[serde(with = "con_serde::With::")] + raw_unsigned_tx: Transaction, + utxos_spent: Vec, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KpsIntermediary { + hash_prevouts: sha256::Hash, + hash_outputs: sha256::Hash, + hash_sequences: sha256::Hash, + hash_amounts: sha256::Hash, + hash_script_pubkeys: sha256::Hash, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KpsInputSpendingGiven { + txin_index: usize, + internal_privkey: SecretKey, + merkle_root: Option, + #[serde(deserialize_with = "sighash_deser_numeric")] + hash_type: TapSighashType, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KpsInputSpendingIntermediary { + internal_pubkey: XOnlyPublicKey, + tweak: TapTweakHash, + tweaked_privkey: SecretKey, + sig_msg: String, + //precomputed_used: Vec, // unused + sig_hash: TapSighash, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KpsInputSpendingExpected { + witness: Vec, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KpsInputSpending { + given: KpsInputSpendingGiven, + intermediary: KpsInputSpendingIntermediary, + expected: KpsInputSpendingExpected, + // auxiliary: KpsAuxiliary, //unused + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct KeyPathSpending { + given: KpsGiven, + intermediary: KpsIntermediary, + input_spending: Vec, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + struct TestData { + version: u64, + key_path_spending: Vec, + //script_pubkey: Vec, // unused + } + + let json_str = include_str!("../../tests/data/bip341_tests.json"); + let mut data = + serde_json::from_str::(json_str).expect("JSON was not well-formatted"); + + assert_eq!(data.version, 1u64); + let key_path = data.key_path_spending.remove(0); + + let raw_unsigned_tx = key_path.given.raw_unsigned_tx; + let utxos = key_path + .given + .utxos_spent + .into_iter() + .map(|txo| TxOut { amount: txo.amount, script_pubkey: txo.script_pubkey }) + .collect::>(); + + // Test intermediary + let mut cache = SighashCache::new(&raw_unsigned_tx); + + let expected = key_path.intermediary; + // Compute all caches + assert_eq!(expected.hash_amounts, cache.taproot_cache(&utxos).amounts); + assert_eq!(expected.hash_outputs, cache.common_cache().outputs); + assert_eq!(expected.hash_prevouts, cache.common_cache().prevouts); + assert_eq!(expected.hash_script_pubkeys, cache.taproot_cache(&utxos).script_pubkeys); + assert_eq!(expected.hash_sequences, cache.common_cache().sequences); + + for mut inp in key_path.input_spending { + let tx_ind = inp.given.txin_index; + let internal_priv_key = inp.given.internal_privkey; + let merkle_root = inp.given.merkle_root; + let hash_ty = inp.given.hash_type; + + let expected = inp.intermediary; + let sig_str = inp.expected.witness.remove(0); + let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 { + (sig_str.parse::().unwrap(), TapSighashType::Default) + } else { + let hash_ty = u8::from_str_radix(&sig_str[128..130], 16).unwrap(); + let hash_ty = TapSighashType::from_consensus_u8(hash_ty).unwrap(); + (sig_str[..128].parse::().unwrap(), hash_ty) + }; + + // tests + let keypair = secp256k1::Keypair::from_secret_key(&internal_priv_key); + let (internal_key, _parity) = XOnlyPublicKey::from_keypair(&keypair); + let tweak = TapTweakHash::from_key_and_merkle_root(internal_key, merkle_root); + let tweaked_keypair = keypair.add_xonly_tweak(&tweak.to_scalar()).unwrap(); + let mut sig_msg = Vec::new(); + cache + .taproot_encode_signing_data_to( + &mut sig_msg, + tx_ind, + &Prevouts::All(&utxos), + None, + None, + hash_ty, + ) + .unwrap(); + let sighash = cache + .taproot_signature_hash(tx_ind, &Prevouts::All(&utxos), None, None, hash_ty) + .unwrap(); + + let key_spend_sig = secp256k1::schnorr::sign_with_aux_rand( + &sighash.to_byte_array(), + &tweaked_keypair, + &[0u8; 32], + ); + + assert_eq!(expected.internal_pubkey, internal_key); + assert_eq!(expected.tweak, tweak); + assert_eq!(expected.sig_msg, sig_msg.to_lower_hex_string()); + assert_eq!(expected.sig_hash, sighash); + assert_eq!(expected_hash_ty, hash_ty); + assert_eq!(expected_key_spend_sig, key_spend_sig); + + let tweaked_priv_key = SecretKey::from_keypair(&tweaked_keypair); + assert_eq!(expected.tweaked_privkey, tweaked_priv_key); + } + } + + #[test] + fn sighashtype_fromstr_display() { + let sighashtypes = [ + ("SIGHASH_DEFAULT", TapSighashType::Default), + ("SIGHASH_ALL", TapSighashType::All), + ("SIGHASH_NONE", TapSighashType::None), + ("SIGHASH_SINGLE", TapSighashType::Single), + ("SIGHASH_ALL|SIGHASH_ANYONECANPAY", TapSighashType::AllPlusAnyoneCanPay), + ("SIGHASH_NONE|SIGHASH_ANYONECANPAY", TapSighashType::NonePlusAnyoneCanPay), + ("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY", TapSighashType::SinglePlusAnyoneCanPay), + ]; + for (s, sht) in sighashtypes { + assert_eq!(sht.to_string(), s); + assert_eq!(s.parse::().unwrap(), sht); + } + let sht_mistakes = [ + "SIGHASH_ALL | SIGHASH_ANYONECANPAY", + "SIGHASH_NONE |SIGHASH_ANYONECANPAY", + "SIGHASH_SINGLE| SIGHASH_ANYONECANPAY", + "SIGHASH_ALL SIGHASH_ANYONECANPAY", + "SIGHASH_NONE |", + "SIGHASH_SIGNLE", + "DEFAULT", + "ALL", + "sighash_none", + "Sighash_none", + "SigHash_None", + "SigHash_NONE", + ]; + for s in sht_mistakes { + assert_eq!( + s.parse::().unwrap_err().to_string(), + format!("unrecognized SIGHASH string '{}'", s) + ); + } + } + + #[test] + fn bip143_p2wpkh() { + let tx = deserialize::( + &hex!( + "0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f000000\ + 0000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a01000000\ + 00ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093\ + 510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000" + ), + ).unwrap(); + + let spk = ScriptPubKeyBuf::from_hex_no_length_prefix( + "00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1", + ) + .unwrap(); + let amount = Amount::from_sat_u32(600_000_000); + + let mut cache = SighashCache::new(&tx); + assert_eq!( + cache.p2wpkh_signature_hash(1, &spk, amount, EcdsaSighashType::All).unwrap(), + "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670" + .parse::() + .unwrap(), + ); + + let cache = cache.segwit_cache(); + // Parse hex into Vec because BIP-0143 test vector displays forwards but our sha256d::Hash displays backwards. + assert_eq!( + cache.prevouts.as_byte_array(), + &Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37") + .unwrap()[..], + ); + assert_eq!( + cache.sequences.as_byte_array(), + &Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b") + .unwrap()[..], + ); + assert_eq!( + cache.outputs.as_byte_array(), + &Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5") + .unwrap()[..], + ); + } + + #[test] + fn bip143_p2wpkh_nested_in_p2sh() { + let tx = deserialize::( + &hex!( + "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000\ + 0000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac00\ + 08af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000" + ), + ).unwrap(); + + let spk = ScriptPubKeyBuf::from_hex_no_length_prefix( + "001479091972186c449eb1ded22b78e40d009bdf0089", + ) + .unwrap(); + let amount = Amount::from_sat_u32(1_000_000_000); + + let mut cache = SighashCache::new(&tx); + assert_eq!( + cache.p2wpkh_signature_hash(0, &spk, amount, EcdsaSighashType::All).unwrap(), + "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6" + .parse::() + .unwrap(), + ); + + let cache = cache.segwit_cache(); + // Parse hex into Vec because BIP-0143 test vector displays forwards but our sha256d::Hash displays backwards. + assert_eq!( + cache.prevouts.as_byte_array(), + &Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a") + .unwrap()[..], + ); + assert_eq!( + cache.sequences.as_byte_array(), + &Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198") + .unwrap()[..], + ); + assert_eq!( + cache.outputs.as_byte_array(), + &Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83") + .unwrap()[..], + ); + } + + // Note, if you are looking at the test vectors in BIP-0143 and wondering why there is a `cf` + // prepended to all the script_code hex it is the length byte, it gets added when we consensus + // encode a script. + fn bip143_p2wsh_nested_in_p2sh_data() -> (Transaction, WitnessScriptBuf, Amount) { + let tx = deserialize::(&hex!( + "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\ + ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\ + 05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000" + )) + .unwrap(); + + let witness_script = WitnessScriptBuf::from_hex_no_length_prefix( + "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\ + bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b\ + 9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\ + c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\ + 2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\ + 56ae", + ) + .unwrap(); + + let amount = Amount::from_sat_u32(987_654_321); + (tx, witness_script, amount) + } + + #[test] + fn bip143_p2wsh_nested_in_p2sh_sighash_type_all() { + let (tx, witness_script, amount) = bip143_p2wsh_nested_in_p2sh_data(); + let mut cache = SighashCache::new(&tx); + assert_eq!( + cache.p2wsh_signature_hash(0, &witness_script, amount, EcdsaSighashType::All).unwrap(), + "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c" + .parse::() + .unwrap(), + ); + + // We only test the cache intermediate values for `EcdsaSighashType::All` because they are + // not the same as the BIP test vectors for all the rest of the sighash types. These fields + // are private so it does not effect sighash cache usage, we do test against the produced + // sighash for all sighash types. + + let cache = cache.segwit_cache(); + // Parse hex into Vec because BIP-0143 test vector displays forwards but our sha256d::Hash displays backwards. + assert_eq!( + cache.prevouts.as_byte_array(), + &Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0") + .unwrap()[..], + ); + assert_eq!( + cache.sequences.as_byte_array(), + &Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044") + .unwrap()[..], + ); + assert_eq!( + cache.outputs.as_byte_array(), + &Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc") + .unwrap()[..], + ); + } + + macro_rules! check_bip143_p2wsh_nested_in_p2sh { + ($($test_name:ident, $sighash_type:ident, $sighash:literal);* $(;)?) => { + $( + #[test] + fn $test_name() { + use EcdsaSighashType::*; + + let (tx, witness_script, amount) = bip143_p2wsh_nested_in_p2sh_data(); + let mut cache = SighashCache::new(&tx); + assert_eq!( + cache + .p2wsh_signature_hash(0, &witness_script, amount, $sighash_type) + .unwrap(), + $sighash + .parse::() + .unwrap(), + ); + } + )* + } + } + check_bip143_p2wsh_nested_in_p2sh! { + // EcdsaSighashType::All tested above. + bip143_p2wsh_nested_in_p2sh_sighash_none, None, "e9733bc60ea13c95c6527066bb975a2ff29a925e80aa14c213f686cbae5d2f36"; + bip143_p2wsh_nested_in_p2sh_sighash_single, Single, "1e1f1c303dc025bd664acb72e583e933fae4cff9148bf78c157d1e8f78530aea"; + bip143_p2wsh_nested_in_p2sh_sighash_all_plus_anyonecanpay, AllPlusAnyoneCanPay, "2a67f03e63a6a422125878b40b82da593be8d4efaafe88ee528af6e5a9955c6e"; + bip143_p2wsh_nested_in_p2sh_sighash_none_plus_anyonecanpay, NonePlusAnyoneCanPay, "781ba15f3779d5542ce8ecb5c18716733a5ee42a6f51488ec96154934e2c890a"; + bip143_p2wsh_nested_in_p2sh_sighash_single_plus_anyonecanpay, SinglePlusAnyoneCanPay, "511e8e52ed574121fc1b654970395502128263f62662e076dc6baf05c2e6a99b"; + } +} diff --git a/bitcoin/src/crypto/taproot.rs b/bitcoin/src/crypto/taproot.rs new file mode 100644 index 000000000..ae8d6e3f3 --- /dev/null +++ b/bitcoin/src/crypto/taproot.rs @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Taproot signatures. +//! +//! This module provides Taproot signatures used by Bitcoin that can be roundtrip (de)serialized. + +use core::borrow::Borrow; +use core::convert::Infallible; +use core::ops::Deref; +use core::fmt; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use internals::array::ArrayExt; +use internals::{impl_to_hex_from_lower_hex, write_err}; +use io::Write; + +use crate::prelude::{DisplayHex, Vec}; +use crate::sighash::{InvalidSighashTypeError, TapSighashType}; + +pub use self::into_iter::IntoIter; + +const MAX_LEN: usize = 65; // 64 for sig, 1B sighash flag + +/// A BIP-0340-0341 serialized Taproot signature with the corresponding hash type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Signature { + /// The underlying schnorr signature. + pub signature: secp256k1::schnorr::Signature, + /// The corresponding hash type. + pub sighash_type: TapSighashType, +} + +impl Signature { + /// Deserializes the signature from a slice. + pub fn from_slice(sl: &[u8]) -> Result { + if let Ok(signature) = <[u8; 64]>::try_from(sl) { + // default type + let signature = secp256k1::schnorr::Signature::from_byte_array(signature); + Ok(Self { signature, sighash_type: TapSighashType::Default }) + } else if let Ok(signature) = <[u8; 65]>::try_from(sl) { + let (sighash_type, signature) = signature.split_last(); + let sighash_type = TapSighashType::from_consensus_u8(*sighash_type)?; + let signature = secp256k1::schnorr::Signature::from_byte_array(*signature); + Ok(Self { signature, sighash_type }) + } else { + Err(SigFromSliceError::InvalidSignatureSize(sl.len())) + } + } + + /// Serializes the signature (without heap allocation). + /// + /// This returns a type with an API very similar to that of `Box<[u8]>`. + /// You can get a slice from it using deref coercions or turn it into an iterator. + pub fn serialize(self) -> SerializedSignature { + let mut buf = [0; MAX_LEN]; + let ser_sig = self.signature.to_byte_array(); + buf[..64].copy_from_slice(&ser_sig); + let len = if self.sighash_type == TapSighashType::Default { + // default sighash type, don't add extra sighash byte + 64 + } else { + buf[64] = self.sighash_type as u8; + 65 + }; + SerializedSignature::from_raw_parts(buf, len) + } + + /// Serializes the signature. + /// + /// Note: this allocates on the heap, prefer [`serialize`](Self::serialize) if vec is not needed. + pub fn to_vec(self) -> Vec { + let mut ser_sig = self.signature.as_ref().to_vec(); + // If default sighash type, don't add extra sighash byte + if self.sighash_type != TapSighashType::Default { + ser_sig.push(self.sighash_type as u8); + } + ser_sig + } + + /// Serializes the signature to `writer`. + #[inline] + pub fn serialize_to_writer(&self, writer: &mut W) -> Result<(), io::Error> { + let sig = self.serialize(); + sig.write_to(writer) + } +} + +/// A serialized Taproot Signature +/// +/// Serialized Taproot signatures have the issue that they can have different lengths. +/// We want to avoid using `Vec` since that would require allocations making the code slower and +/// unable to run on platforms without an allocator. +#[derive(Copy, Clone)] +pub struct SerializedSignature { + data: [u8; MAX_LEN], + len: usize, +} + +impl SerializedSignature { + /// Constructs a new SerializedSignature from a Signature. + /// + /// In other words this serializes a `Signature` into a `SerializedSignature`. + #[inline] + pub fn from_signature(sig: Signature) -> Self { sig.serialize() } + + /// Converts the serialized signature into the [`Signature`] struct. + /// + /// In other words this deserializes the `SerializedSignature`. + #[inline] + pub fn to_signature(self) -> Result { + Signature::from_slice(&self) + } + + /// Returns the length of the serialized signature data. + #[inline] + // `len` is never 0, so `is_empty` would always return `false`. + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { self.len } + + /// Returns an iterator over bytes of the signature. + #[inline] + pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() } + + /// Writes this serialized signature to a `writer`. + #[inline] + pub fn write_to(&self, writer: &mut W) -> Result<(), io::Error> { + writer.write_all(self) + } + + /// Constructs new `SerializedSignature` from data and length. + /// + /// # Panics + /// + /// If `len` > `MAX_LEN` + #[inline] + pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self { + assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN); + Self { data, len } + } + + /// Set the length of the object. + #[inline] + pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; } +} + +impl fmt::Debug for SerializedSignature { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) } +} + +impl fmt::Display for SerializedSignature { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + hex::fmt_hex_exact!(f, MAX_LEN, self, hex::Case::Lower) + } +} + +impl fmt::LowerHex for SerializedSignature { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::LowerHex::fmt(&(**self).as_hex(), f) + } +} +impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignature| signature.len + * 2); + +impl fmt::UpperHex for SerializedSignature { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::UpperHex::fmt(&(**self).as_hex(), f) + } +} + +impl PartialEq for SerializedSignature { + #[inline] + fn eq(&self, other: &Self) -> bool { **self == **other } +} + +impl PartialEq<[u8]> for SerializedSignature { + #[inline] + fn eq(&self, other: &[u8]) -> bool { **self == *other } +} + +impl PartialEq for [u8] { + #[inline] + fn eq(&self, other: &SerializedSignature) -> bool { *self == **other } +} + +impl PartialOrd for SerializedSignature { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for SerializedSignature { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { (**self).cmp(&**other) } +} + +impl PartialOrd<[u8]> for SerializedSignature { + fn partial_cmp(&self, other: &[u8]) -> Option { + (**self).partial_cmp(other) + } +} + +impl PartialOrd for [u8] { + fn partial_cmp(&self, other: &SerializedSignature) -> Option { + self.partial_cmp(&**other) + } +} + +impl Eq for SerializedSignature {} + +impl core::hash::Hash for SerializedSignature { + fn hash(&self, state: &mut H) { (**self).hash(state) } +} + +impl AsRef<[u8]> for SerializedSignature { + #[inline] + fn as_ref(&self) -> &[u8] { &self.data[..self.len] } +} + +impl Borrow<[u8]> for SerializedSignature { + #[inline] + fn borrow(&self) -> &[u8] { &self.data[..self.len] } +} + +impl Deref for SerializedSignature { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { &self.data[..self.len] } +} + +impl IntoIterator for SerializedSignature { + type IntoIter = IntoIter; + type Item = u8; + + #[inline] + fn into_iter(self) -> Self::IntoIter { IntoIter::new(self) } +} + +impl<'a> IntoIterator for &'a SerializedSignature { + type IntoIter = core::slice::Iter<'a, u8>; + type Item = &'a u8; + + #[inline] + fn into_iter(self) -> Self::IntoIter { (**self).iter() } +} + +impl From for SerializedSignature { + fn from(value: Signature) -> Self { Self::from_signature(value) } +} + +impl<'a> From<&'a Signature> for SerializedSignature { + fn from(value: &'a Signature) -> Self { Self::from_signature(*value) } +} + +impl TryFrom for Signature { + type Error = SigFromSliceError; + + fn try_from(value: SerializedSignature) -> Result { value.to_signature() } +} + +impl<'a> TryFrom<&'a SerializedSignature> for Signature { + type Error = SigFromSliceError; + + fn try_from(value: &'a SerializedSignature) -> Result { + value.to_signature() + } +} + + +/// Separate mod to prevent outside code from accidentally breaking invariants. +mod into_iter { + use super::*; + + /// Owned iterator over the bytes of [`SerializedSignature`] + /// + /// Created by [`IntoIterator::into_iter`] method. + // allowed because of https://github.com/rust-lang/rust/issues/98348 + #[allow(missing_copy_implementations)] + #[derive(Debug, Clone)] + pub struct IntoIter { + signature: SerializedSignature, + // invariant: pos <= signature.len() + pos: usize, + } + + impl IntoIter { + #[inline] + pub(crate) fn new(signature: SerializedSignature) -> Self { + Self { + signature, + // for all unsigned n: 0 <= n + pos: 0, + } + } + + /// Returns the remaining bytes as a slice. + /// + /// This method is analogous to [`core::slice::Iter::as_slice`]. + #[inline] + pub fn as_slice(&self) -> &[u8] { &self.signature[self.pos..] } + } + + impl Iterator for IntoIter { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + let byte = *self.signature.get(self.pos)?; + // can't overflow or break invariant because if pos is too large we return early + self.pos += 1; + Some(byte) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + // can't overflow thanks to the invariant + let len = self.signature.len() - self.pos; + (len, Some(len)) + } + + // override for speed + #[inline] + fn nth(&mut self, n: usize) -> Option { + if n >= self.len() { + // upholds invariant because the values will be equal + self.pos = self.signature.len(); + None + } else { + // if n < signature.len() - self.pos then n + self.pos < signature.len() which neither + // overflows nor breaks the invariant + self.pos += n; + self.next() + } + } + } + + impl ExactSizeIterator for IntoIter {} + + impl core::iter::FusedIterator for IntoIter {} + + impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if self.pos == self.signature.len() { + return None; + } + + // if len is 0 then pos is also 0 thanks to the invariant so we would return before we + // reach this + let new_len = self.signature.len() - 1; + let byte = self.signature[new_len]; + self.signature.set_len_unchecked(new_len); + Some(byte) + } + } +} + +/// An error constructing a [`taproot::Signature`] from a byte slice. +/// +/// [`taproot::Signature`]: crate::crypto::taproot::Signature +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum SigFromSliceError { + /// Invalid signature hash type. + SighashType(InvalidSighashTypeError), + /// A secp256k1 error. + Secp256k1(secp256k1::Error), + /// Invalid Taproot signature size + InvalidSignatureSize(usize), +} + +impl From for SigFromSliceError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for SigFromSliceError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::SighashType(ref e) => write_err!(f, "sighash"; e), + Self::Secp256k1(ref e) => write_err!(f, "secp256k1"; e), + Self::InvalidSignatureSize(sz) => write!(f, "invalid Taproot signature size: {}", sz), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SigFromSliceError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Secp256k1(ref e) => Some(e), + Self::SighashType(ref e) => Some(e), + Self::InvalidSignatureSize(_) => None, + } + } +} + +impl From for SigFromSliceError { + fn from(e: secp256k1::Error) -> Self { Self::Secp256k1(e) } +} + +impl From for SigFromSliceError { + fn from(err: InvalidSighashTypeError) -> Self { Self::SighashType(err) } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Signature { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let arbitrary_bytes: [u8; secp256k1::constants::SCHNORR_SIGNATURE_SIZE] = u.arbitrary()?; + + Ok(Self { + signature: secp256k1::schnorr::Signature::from_byte_array(arbitrary_bytes), + sighash_type: TapSighashType::arbitrary(u)?, + }) + } +} + +#[cfg(test)] +mod tests { + use super::{SerializedSignature, MAX_LEN}; + + #[test] + fn iterator_ops_are_homomorphic() { + let mut fake_signature_data = [0; MAX_LEN]; + for (i, byte) in fake_signature_data.iter_mut().enumerate() { + *byte = i as u8; + } + + let fake_signature = SerializedSignature { data: fake_signature_data, len: MAX_LEN }; + + let mut iter1 = fake_signature.into_iter(); + let mut iter2 = fake_signature.iter(); + + // while let so we can compare size_hint and as_slice + while let (Some(a), Some(b)) = (iter1.next(), iter2.next()) { + assert_eq!(a, *b); + assert_eq!(iter1.size_hint(), iter2.size_hint()); + assert_eq!(iter1.as_slice(), iter2.as_slice()); + } + + let mut iter1 = fake_signature.into_iter(); + let mut iter2 = fake_signature.iter(); + + // manual next_back instead of rev() so that we can check as_slice() + // if next_back is implemented correctly then rev() is also correct - provided by `core` + while let (Some(a), Some(b)) = (iter1.next_back(), iter2.next_back()) { + assert_eq!(a, *b); + assert_eq!(iter1.size_hint(), iter2.size_hint()); + assert_eq!(iter1.as_slice(), iter2.as_slice()); + } + } +} diff --git a/bitcoin/src/hash_types.rs b/bitcoin/src/hash_types.rs new file mode 100644 index 000000000..9f63e8b07 --- /dev/null +++ b/bitcoin/src/hash_types.rs @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin hash types. +//! +//! This module is deprecated. You can find hash types in their respective, hopefully obvious, modules. + +#[deprecated(since = "TBD", note = "use `crate::T` instead")] +pub use crate::{BlockHash, TxMerkleNode, Txid, WitnessCommitment, WitnessMerkleNode, Wtxid}; + +#[cfg(test)] +mod tests { + use super::*; + use crate::key::{PubkeyHash, WPubkeyHash}; + use crate::script::{ScriptHash, WScriptHash}; + use crate::{LegacySighash, SegwitV0Sighash, TapSighash, XKeyIdentifier}; + + #[rustfmt::skip] + /// sha256d of the empty string + const DUMMY32: [u8; 32] = [ + 0x5d, 0xf6, 0xe0, 0xe2, 0x76, 0x13, 0x59, 0xd3, + 0x0a, 0x82, 0x75, 0x05, 0x8e, 0x29, 0x9f, 0xcc, + 0x03, 0x81, 0x53, 0x45, 0x45, 0xf5, 0x5c, 0xf4, + 0x3e, 0x41, 0x98, 0x3f, 0x5d, 0x4c, 0x94, 0x56, + ]; + /// hash160 of the empty string + #[rustfmt::skip] + const DUMMY20: [u8; 20] = [ + 0xb4, 0x72, 0xa2, 0x66, 0xd0, 0xbd, 0x89, 0xc1, 0x37, 0x06, + 0xa4, 0x13, 0x2c, 0xcf, 0xb1, 0x6f, 0x7c, 0x3b, 0x9f, 0xcb, + ]; + + #[test] + fn hash_display() { + assert_eq!( + Txid::from_byte_array(DUMMY32).to_string(), + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + ); + + assert_eq!( + Wtxid::from_byte_array(DUMMY32).to_string(), + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + ); + assert_eq!( + BlockHash::from_byte_array(DUMMY32).to_string(), + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + ); + assert_eq!( + LegacySighash::from_byte_array(DUMMY32).to_string(), + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", + ); + assert_eq!( + SegwitV0Sighash::from_byte_array(DUMMY32).to_string(), + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", + ); + assert_eq!( + TapSighash::from_byte_array(DUMMY32).to_string(), + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", + ); + + assert_eq!( + PubkeyHash::from_byte_array(DUMMY20).to_string(), + "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb", + ); + assert_eq!( + ScriptHash::from_byte_array(DUMMY20).to_string(), + "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb", + ); + assert_eq!( + WPubkeyHash::from_byte_array(DUMMY20).to_string(), + "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb", + ); + assert_eq!( + WScriptHash::from_byte_array(DUMMY32).to_string(), + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456", + ); + + assert_eq!( + TxMerkleNode::from_byte_array(DUMMY32).to_string(), + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + ); + assert_eq!( + WitnessMerkleNode::from_byte_array(DUMMY32).to_string(), + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + ); + assert_eq!( + WitnessCommitment::from_byte_array(DUMMY32).to_string(), + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + ); + assert_eq!( + XKeyIdentifier::from_byte_array(DUMMY20).to_string(), + "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb", + ); + + } +} diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs new file mode 100644 index 000000000..34d3e38ea --- /dev/null +++ b/bitcoin/src/internal_macros.rs @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Internal macros. +//! +//! Macros meant to be used inside the Rust Bitcoin library. + +macro_rules! impl_consensus_encoding { + ($thing:ident, $($field:ident),+) => ( + impl $crate::consensus::Encodable for $thing { + #[inline] + fn consensus_encode( + &self, + w: &mut W, + ) -> core::result::Result { + let mut len = 0; + $(len += self.$field.consensus_encode(w)?;)+ + Ok(len) + } + } + + impl $crate::consensus::Decodable for $thing { + + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> core::result::Result<$thing, $crate::consensus::encode::Error> { + Ok($thing { + $($field: $crate::consensus::Decodable::consensus_decode_from_finite_reader(r)?),+ + }) + } + + #[inline] + fn consensus_decode( + r: &mut R, + ) -> core::result::Result<$thing, $crate::consensus::encode::Error> { + let mut r = $crate::io::Read::take(r, internals::ToU64::to_u64($crate::consensus::encode::MAX_VEC_SIZE)); + Ok($thing { + $($field: $crate::consensus::Decodable::consensus_decode(&mut r)?),+ + }) + } + } + ); +} +pub(crate) use impl_consensus_encoding; + +/// Implements several string-ish traits for byte-based newtypes. +/// +/// - `fmt::Display` and `str::FromStr` (using lowercase hex) +/// - `fmt::LowerHex` and `UpperHex` +/// - `fmt::Debug` (using `LowerHex`) +/// - `serde::Serialize` and `Deserialize` (using lowercase hex) +/// +/// As well as an inherent `from_hex` method. +macro_rules! impl_array_newtype_stringify { + ($t:ident, $len:literal) => { + impl $t { + /// Constructs a new `Self` from a hex string. + pub fn from_hex(s: &str) -> Result { + Ok($t($crate::hex::FromHex::from_hex(s)?)) + } + } + + impl core::fmt::LowerHex for $t { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + use $crate::hex::{display, Case}; + display::fmt_hex_exact!(f, $len, &self.0, Case::Lower) + } + } + + impl core::fmt::UpperHex for $t { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + use $crate::hex::{display, Case}; + display::fmt_hex_exact!(f, $len, &self.0, Case::Upper) + } + } + + impl core::fmt::Display for $t { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::LowerHex::fmt(self, f) + } + } + + impl core::fmt::Debug for $t { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::LowerHex::fmt(self, f) + } + } + + impl core::str::FromStr for $t { + type Err = $crate::hex::HexToArrayError; + fn from_str(s: &str) -> core::result::Result { Self::from_hex(s) } + } + + #[cfg(feature = "serde")] + impl $crate::serde::Serialize for $t { + fn serialize( + &self, + s: S, + ) -> core::result::Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(&self[..]) + } + } + } + + #[cfg(feature = "serde")] + impl<'de> $crate::serde::Deserialize<'de> for $t { + fn deserialize>( + d: D, + ) -> core::result::Result<$t, D::Error> { + if d.is_human_readable() { + struct HexVisitor; + + impl<'de> $crate::serde::de::Visitor<'de> for HexVisitor { + type Value = $t; + + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> core::result::Result + where + E: $crate::serde::de::Error, + { + use $crate::serde::de::Unexpected; + + if let Ok(hex) = core::str::from_utf8(v) { + core::str::FromStr::from_str(hex).map_err(E::custom) + } else { + return Err(E::invalid_value(Unexpected::Bytes(v), &self)); + } + } + + fn visit_str(self, hex: &str) -> core::result::Result + where + E: $crate::serde::de::Error, + { + core::str::FromStr::from_str(hex).map_err(E::custom) + } + } + + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; + + impl<'de> $crate::serde::de::Visitor<'de> for BytesVisitor { + type Value = $t; + + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> core::result::Result + where + E: $crate::serde::de::Error, + { + if v.len() != $len { + Err(E::invalid_length(v.len(), &stringify!($len))) + } else { + let mut ret = [0; $len]; + ret.copy_from_slice(v); + Ok($t(ret)) + } + } + } + + d.deserialize_bytes(BytesVisitor) + } + } + } + }; +} +pub(crate) use impl_array_newtype_stringify; + +#[rustfmt::skip] +macro_rules! impl_asref_push_bytes { + ($($hashtype:ident),*) => { + $( + impl AsRef<$crate::script::PushBytes> for $hashtype { + fn as_ref(&self) -> &$crate::script::PushBytes { + self.as_byte_array().into() + } + } + + impl From<$hashtype> for $crate::script::PushBytesBuf { + fn from(hash: $hashtype) -> Self { + hash.as_byte_array().into() + } + } + )* + }; +} +pub(crate) use impl_asref_push_bytes; + +macro_rules! only_doc_attrs { + ({}, {$($fun:tt)*}) => { + $($fun)* + }; + ({#[doc = $($doc:tt)*] $($all_attrs:tt)*}, {$($fun:tt)*}) => { + $crate::internal_macros::only_doc_attrs!({ $($all_attrs)* }, { #[doc = $($doc)*] $($fun)* }); + }; + ({#[doc($($doc:tt)*)] $($all_attrs:tt)*}, {$($fun:tt)*}) => { + $crate::internal_macros::only_doc_attrs!({ $($all_attrs)* }, { #[doc($($doc)*)] $($fun)* }); + }; + ({#[$($other:tt)*] $($all_attrs:tt)*}, {$($fun:tt)*}) => { + $crate::internal_macros::only_doc_attrs!({ $($all_attrs)* }, { $($fun)* }); + }; +} +pub(crate) use only_doc_attrs; + +macro_rules! only_non_doc_attrs { + ({}, {$($fun:tt)*}) => { + $($fun)* + }; + ({#[doc = $($doc:tt)*] $($all_attrs:tt)*}, {$($fun:tt)*}) => { + $crate::internal_macros::only_doc_attrs!({ $($all_attrs)* }, { #[doc = $($doc)*] $($fun)* }); + }; + ({#[doc($($doc:tt)*)] $($all_attrs:tt)*}, {$($fun:tt)*}) => { + $crate::internal_macros::only_doc_attrs!({ $($all_attrs)* }, { $($fun)* }); + }; + ({#[$($other:tt)*] $($all_attrs:tt)*}, {$($fun:tt)*}) => { + $crate::internal_macros::only_doc_attrs!({ $($all_attrs)* }, { #[$(other)*] $($fun)* }); + }; +} +pub(crate) use only_non_doc_attrs; + +/// Defines a trait `$trait_name` and implements it for `ty`, used to define extension traits. +macro_rules! define_extension_trait { + ($(#[$($trait_attrs:tt)*])* $trait_vis:vis trait $trait_name:ident$(<$traitgen:ident $(= $traitdefault:ty)?>)? impl$(<$implgen:ident $(= $impldefault:ty)?>)? for $ty:ident$(<$tygen:ident $(= $tydefault:ty)?>)? { + $( + $(#[$($fn_attrs:tt)*])* + fn $fn:ident$(<$($gen:ident: $gent:path),*>)?($($params:tt)*) $( -> $ret:ty )? $(where $wherety:ident $(= $whereeq:ident)? $(: $wherebound:ident)?)? $body:block + )* + }) => { + #[cfg_attr(docsrs, doc(notable_trait))] + $(#[$($trait_attrs)*])* $trait_vis trait $trait_name$(<$traitgen $(= $traitdefault)?>)?: sealed::Sealed { + $( + $crate::internal_macros::only_doc_attrs! { + { $(#[$($fn_attrs)*])* }, + { + fn $fn$(<$($gen: $gent),*>)?($($params)*) $( -> $ret)? $(where $wherety $(= $whereeq)? $(: $wherebound)?)?; + } + } + )* + } + + impl$(<$implgen $(= $impldefault)?>)? $trait_name$(<$traitgen $(= $traitdefault)?>)? for $ty$(<$tygen $(= $tydefault)?>)? { + $( + $crate::internal_macros::only_non_doc_attrs! { + { $(#[$($fn_attrs)*])* }, + { + fn $fn$(<$($gen: $gent),*>)?($($params)*) $( -> $ret )? $(where $wherety $(= $whereeq)? $(: $wherebound)?)? $body + } + } + )* + } + }; +} +pub(crate) use define_extension_trait; + + diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs new file mode 100644 index 000000000..06b3c405b --- /dev/null +++ b/bitcoin/src/lib.rs @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Rust Bitcoin Library +//! +//! This is a library that supports the Bitcoin network protocol and associated primitives. It is +//! designed for Rust programs built to work with the Bitcoin network. +//! +//! Except for its dependency on libsecp256k1 (and optionally libbitcoinconsensus), this library is +//! written entirely in Rust. It illustrates the benefits of strong type safety, including ownership +//! and lifetime, for financial and/or cryptographic software. +//! +//! See README.md for detailed documentation about development and supported environments. +//! +//! # Cargo features +//! +//! * `base64` (dependency) - enables encoding of PSBTs and message signatures. +//! * `bitcoinconsensus` (dependency) - enables validating scripts and transactions. +//! * `default` - enables `std` and `secp-recovery`. +//! * `rand` (transitive dependency) - makes it more convenient to generate random values. +//! * `serde` (dependency) - implements `serde`-based serialization and deserialization. +//! * `secp-lowmemory` - optimizations for low-memory devices. +//! * `secp-recovery` - enables calculating public key from a signature and message. +//! * `std` - the usual dependency on `std`. + +#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] +// Experimental features we need. +#![cfg_attr(docsrs, feature(doc_notable_trait))] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Instead of littering the codebase for non-fuzzing and bench code just globally allow. +#![cfg_attr(fuzzing, allow(dead_code, unused_imports))] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::incompatible_msrv)] // Has FPs and we're testing it which is more reliable anyway. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +// We only support machines with index size of 4 bytes or more. +// +// Bitcoin consensus code relies on being able to have containers with more than 65536 (2^16) +// entries in them so we cannot support consensus logic on machines that only have 16-bit memory +// addresses. +// +// We specifically do not use `target_pointer_width` because of the possibility that pointer width +// does not equal index size. +// +// ref: https://github.com/rust-bitcoin/rust-bitcoin/pull/2929#discussion_r1661848565 +internals::const_assert!( + core::mem::size_of::() >= 4; + "platforms that have usize less than 32 bits are not supported" +); + +#[macro_use] +extern crate alloc; + +/// Encodes and decodes base64 as bytes or utf8. +#[cfg(feature = "base64")] +pub extern crate base64; + +/// Bitcoin base58 encoding and decoding. +pub extern crate base58; + +/// Re-export the `bech32` crate. +pub extern crate bech32; + +/// Rust implementation of cryptographic hash function algorithms. +pub extern crate hashes; + +/// Re-export the `hex-conservative` crate. +pub extern crate hex; + +/// Re-export the `bitcoin-io` crate. +pub extern crate io; + +/// Re-export the `rust-secp256k1` crate. +/// +/// Rust wrapper library for Pieter Wuille's libsecp256k1. Implements ECDSA and BIP-0340 signatures +/// for the SECG elliptic curve group secp256k1 and related utilities. +pub extern crate secp256k1; + +#[cfg(feature = "serde")] +#[macro_use] +extern crate serde; + +mod internal_macros; + +pub mod ext { + //! Re-export all the extension traits so downstream can use wildcard imports. + //! + //! As part of stabilizing `primitives` and `units` we created a bunch of extension traits in + //! `rust-bitcoin` to hold all then API that we are not yet ready to stabilize. This module + //! re-exports all of them to improve ergonomics for users comfortable with wildcard imports. + //! + //! # Examples + //! + //! ``` + //! # #![allow(unused_imports)] // Because that is what we are demoing. + //! // Wildcard import all of the extension crates. + //! use bitcoin::ext::*; + //! + //! // If, for some reason, you want the name to be in scope access it via the module. E.g. + //! use bitcoin::script::ScriptSigExt; + //! ``` + #[rustfmt::skip] // Use terse custom grouping. + pub use crate::{ + block::{BlockCheckedExt as _, HeaderExt as _}, + pow::CompactTargetExt as _, + script::{ScriptExt as _, ScriptBufExt as _, TapScriptExt as _, ScriptPubKeyExt as _, ScriptPubKeyBufExt as _, WitnessScriptExt as _, ScriptSigExt as _}, + transaction::{TxidExt as _, WtxidExt as _, OutPointExt as _, TxInExt as _, TxOutExt as _, TransactionExt as _}, + witness::WitnessExt as _, + }; + #[cfg(feature = "bitcoinconsensus")] + pub use crate::consensus_validation::{ScriptPubKeyExt as _, TransactionExt as _}; +} +#[macro_use] +pub mod address; +pub mod bip158; +pub mod bip32; +pub mod blockdata; +pub mod consensus; +#[cfg(feature = "bitcoinconsensus")] +pub mod consensus_validation; +// Private until we either make this a crate or flatten it - still to be decided. +pub(crate) mod crypto; +pub mod hash_types; +pub mod merkle_tree; +pub mod network; +pub mod policy; +pub mod pow; +pub mod psbt; +pub mod sign_message; +pub mod taproot; + +// Re-export the type from where it is defined but the module from the highest place up the stack +// that it is available in the event that we add some functionality there. +#[doc(inline)] +pub use primitives::{ + block::{ + Block, BlockHash, Checked as BlockChecked, Header as BlockHeader, + Unchecked as BlockUnchecked, Validation as BlockValidation, Version as BlockVersion, + WitnessCommitment, compute_merkle_root, compute_witness_root, InvalidBlockError, + }, + merkle_tree::{TxMerkleNode, WitnessMerkleNode}, + pow::CompactTarget, // No `pow` module outside of `primitives`. + script::{ + RedeemScript, RedeemScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf, + TapScript, TapScriptBuf, WitnessScript, WitnessScriptBuf, ScriptHashableTag, + Tag, RedeemScriptTag, ScriptPubKeyTag, ScriptSigTag, TapScriptTag, WitnessScriptTag, + }, + transaction::{Ntxid, OutPoint, Transaction, TxIn, TxOut, Txid, Version as TransactionVersion, Wtxid}, + witness::Witness, +}; +#[doc(inline)] +pub use units::{ + amount::{Amount, SignedAmount}, + block::{BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInterval}, + fee_rate::FeeRate, + parse_int, + result::{self, NumOpResult}, + sequence::{self, Sequence}, + time::{self, BlockTime, BlockTimeDecoder, BlockTimeDecoderError}, + weight::Weight, +}; + +#[deprecated(since = "TBD", note = "use `BlockHeightInterval` instead")] +#[doc(hidden)] +pub type BlockInterval = BlockHeightInterval; + +#[doc(inline)] +pub use crate::{ + address::{Address, AddressType, KnownHrp}, + bip32::XKeyIdentifier, + crypto::ecdsa, + crypto::key::{self, CompressedPublicKey, PrivateKey, PublicKey, XOnlyPublicKey}, + crypto::sighash::{self, LegacySighash, SegwitV0Sighash, TapSighash, TapSighashTag}, + merkle_tree::MerkleBlock, + network::params::{self, Params}, + network::{Network, NetworkKind, TestnetVersion}, + pow::{Target, Work}, + psbt::Psbt, + sighash::{EcdsaSighashType, TapSighashType}, + taproot::{TapBranchTag, TapLeafHash, TapLeafTag, TapNodeHash, TapTweakHash, TapTweakTag}, +}; +// Re-export all modules from `blockdata`, users should never need to use `blockdata` directly. +#[doc(inline)] +pub use crate::{ + // Also, re-export types and modules from `blockdata` that don't come from `primitives`. + blockdata::locktime::{absolute, relative}, + blockdata::opcodes::{self, Opcode}, + blockdata::script::witness_program::{self, WitnessProgram}, + blockdata::script::witness_version::{self, WitnessVersion}, + // These modules also re-export all the respective `primitives` types. + blockdata::{block, constants, fee_rate, locktime, script, transaction, weight, witness}, +}; + +#[rustfmt::skip] +#[allow(unused_imports)] +mod prelude { + #[cfg(all(not(feature = "std"), not(test)))] + pub use alloc::{string::{String, ToString}, vec::Vec, boxed::Box, borrow::{Borrow, BorrowMut, Cow, ToOwned}, slice, rc}; + + #[cfg(all(not(feature = "std"), not(test), target_has_atomic = "ptr"))] + pub use alloc::sync; + + #[cfg(any(feature = "std", test))] + pub use std::{string::{String, ToString}, vec::Vec, boxed::Box, borrow::{Borrow, BorrowMut, Cow, ToOwned}, rc, sync}; + + #[cfg(all(not(feature = "std"), not(test)))] + pub use alloc::collections::{BTreeMap, BTreeSet, btree_map, BinaryHeap}; + + #[cfg(any(feature = "std", test))] + pub use std::collections::{BTreeMap, BTreeSet, btree_map, BinaryHeap}; + + pub use crate::io::sink; + + pub use hex::DisplayHex; +} + +pub mod amount { + //! Bitcoin amounts. + //! + //! This module mainly introduces the [`Amount`] and [`SignedAmount`] types. + //! We refer to the documentation on the types for more information. + + use crate::consensus::{self, encode, Decodable, Encodable}; + use crate::io::{BufRead, Write}; + + #[rustfmt::skip] // Keep public re-exports separate. + #[cfg(feature = "serde")] + pub use units::amount::serde; + #[doc(inline)] + pub use units::amount::{Amount, SignedAmount}; + #[doc(no_inline)] + pub use units::amount::{ + Denomination, Display, OutOfRangeError, ParseAmountError, ParseDenominationError, + ParseError, + }; + + /// Error types for bitcoin amounts. + pub mod error { + pub use units::amount::error::{ + InputTooLargeError, InvalidCharacterError, MissingDenominationError, + MissingDigitsError, OutOfRangeError, ParseAmountError, ParseDenominationError, + ParseError, PossiblyConfusingDenominationError, TooPreciseError, + UnknownDenominationError, + }; + } + + impl Decodable for Amount { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Self::from_sat(Decodable::consensus_decode(r)?).map_err(|_| { + consensus::parse_failed_error("amount is greater than Amount::MAX_MONEY") + }) + } + } + + impl Encodable for Amount { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_sat().consensus_encode(w) + } + } +} + +mod encode_impls { + //! Encodable/Decodable implementations. + // While we are deprecating, re-exporting, and generally moving things around just put these here. + + use crate::consensus::{encode, Decodable, Encodable}; + use crate::io::{BufRead, Write}; + use crate::{BlockHeight, BlockHeightInterval}; + + /// Implements Encodable and Decodable for a simple wrapper type. + /// + /// Wrapper type is required to implement `to_u32()` and `From`. + macro_rules! impl_encodable_for_u32_wrapper { + ($ty:ident) => { + impl Decodable for $ty { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + let inner = u32::consensus_decode(r)?; + Ok($ty::from(inner)) + } + } + + impl Encodable for $ty { + #[inline] + fn consensus_encode( + &self, + w: &mut W, + ) -> Result { + let inner = self.to_u32(); + inner.consensus_encode(w) + } + } + }; + } + + impl_encodable_for_u32_wrapper!(BlockHeight); + impl_encodable_for_u32_wrapper!(BlockHeightInterval); +} diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs new file mode 100644 index 000000000..04223129f --- /dev/null +++ b/bitcoin/src/merkle_tree/block.rs @@ -0,0 +1,869 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// This code was translated from merkleblock.h, merkleblock.cpp and pmt_tests.cpp +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2018 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +//! Merkle Block and Partial Merkle Tree. +//! +//! Support proofs that transaction(s) belong to a block. + +use core::convert::Infallible; +use core::fmt; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use internals::ToU64 as _; +use io::{BufRead, Write}; + +use crate::block::{self, Block, Checked}; +use crate::consensus::encode::{self, Decodable, Encodable, ReadExt, WriteExt, MAX_VEC_SIZE}; +use crate::merkle_tree::TxMerkleNode; +use crate::prelude::Vec; +use crate::transaction::{Transaction, Txid}; +use crate::Weight; + +/// Data structure that represents a block header paired to a partial Merkle tree. +/// +/// NOTE: This assumes that the given Block has *at least* 1 transaction. If the Block has 0 txs, +/// it will hit an assertion. +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct MerkleBlock { + /// The block header + pub header: block::Header, + /// Transactions making up a partial Merkle tree + pub txn: PartialMerkleTree, +} + +impl MerkleBlock { + /// Constructs a new MerkleBlock from a block, that contains proofs for specific txids. + /// + /// The `block` is a full block containing the header and transactions and `match_txids` is a + /// function that returns true for the ids that should be included in the partial Merkle tree. + /// + /// # Examples + /// + /// ```rust + /// use bitcoin::hex::FromHex; + /// use bitcoin::{Block, MerkleBlock, Txid}; + /// + /// // Block 80000 + /// let block_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad2\ + /// 7b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33\ + /// a5914ce6ed5b1b01e32f5702010000000100000000000000000000000000000000000000000000000000\ + /// 00000000000000ffffffff0704e6ed5b1b014effffffff0100f2052a01000000434104b68a50eaa0287e\ + /// ff855189f949c1c6e5f58b37c88231373d8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413\ + /// bba7fbff9bc762419a76d87b16086eac000000000100000001a6b97044d03da79c005b20ea9c0e1a6d9d\ + /// c12d9f7b91a5911c9030a439eed8f5000000004948304502206e21798a42fae0e854281abd38bacd1aee\ + /// d3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d\ + /// 5d6cc8d25c6b241501ffffffff0100f2052a010000001976a914404371705fa9bd789a2fcd52d2c580b6\ + /// 5d35549d88ac00000000").unwrap(); + /// let block: Block = bitcoin::consensus::deserialize(&block_bytes).unwrap(); + /// let block = block.validate().expect("valid block"); + /// + /// // Constructs a new Merkle block containing a single transaction + /// let txid = "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::().unwrap(); + /// let match_txids: Vec = vec![txid].into_iter().collect(); + /// let mb = MerkleBlock::from_block_with_predicate(&block, |t| match_txids.contains(t)); + /// + /// // Authenticate and extract matched transaction ids + /// let mut matches: Vec = vec![]; + /// let mut index: Vec = vec![]; + /// assert!(mb.extract_matches(&mut matches, &mut index).is_ok()); + /// assert_eq!(txid, matches[0]); + /// ``` + pub fn from_block_with_predicate(block: &Block, match_txids: F) -> Self + where + F: Fn(&Txid) -> bool, + { + let block_txids: Vec<_> = + block.transactions().iter().map(Transaction::compute_txid).collect(); + Self::from_header_txids_with_predicate(block.header(), &block_txids, match_txids) + } + + /// Constructs a new MerkleBlock from the block's header and txids, that contain proofs for specific txids. + /// + /// The `header` is the block header, `block_txids` is the full list of txids included in the block and + /// `match_txids` is a function that returns true for the ids that should be included in the partial Merkle tree. + pub fn from_header_txids_with_predicate( + header: &block::Header, + block_txids: &[Txid], + match_txids: F, + ) -> Self + where + F: Fn(&Txid) -> bool, + { + let matches: Vec = block_txids.iter().map(match_txids).collect(); + + let pmt = PartialMerkleTree::from_txids(block_txids, &matches); + Self { header: *header, txn: pmt } + } + + /// Extracts the matching txid's represented by this partial Merkle tree + /// and their respective indices within the partial tree. + /// returns Ok(()) on success, or error in case of failure + pub fn extract_matches( + &self, + matches: &mut Vec, + indexes: &mut Vec, + ) -> Result<(), MerkleBlockError> { + let merkle_root = self.txn.extract_matches(matches, indexes)?; + + if merkle_root.eq(&self.header.merkle_root) { + Ok(()) + } else { + Err(MerkleBlockError::MerkleRootMismatch) + } + } +} + +impl Encodable for MerkleBlock { + fn consensus_encode(&self, w: &mut W) -> Result { + let len = self.header.consensus_encode(w)? + self.txn.consensus_encode(w)?; + Ok(len) + } +} + +impl Decodable for MerkleBlock { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self { + header: Decodable::consensus_decode(r)?, + txn: Decodable::consensus_decode(r)?, + }) + } +} + +/// Data structure that represents a partial Merkle tree. +/// +/// It represents a subset of the txid's of a known block, in a way that +/// allows recovery of the list of txid's and the Merkle root, in an +/// authenticated way. +/// +/// The encoding works as follows: we traverse the tree in depth-first order, +/// storing a bit for each traversed node, signifying whether the node is the +/// parent of at least one matched leaf txid (or a matched txid itself). In +/// case we are at the leaf level, or this bit is 0, its Merkle node hash is +/// stored, and its children are not explored further. Otherwise, no hash is +/// stored, but we recurse into both (or the only) child branch. During +/// decoding, the same depth-first traversal is performed, consuming bits and +/// hashes as they are written during encoding. +/// +/// The serialization is fixed and provides a hard guarantee about the +/// encoded size: +/// +/// SIZE <= 10 + ceil(32.25*N) +/// +/// Where N represents the number of leaf nodes of the partial tree. N itself +/// is bounded by: +/// +/// N <= total_transactions +/// N <= 1 + matched_transactions*tree_height +/// +/// The serialization format: +/// - uint32 total_transactions (4 bytes) +/// - CompactSize number of hashes (1-3 bytes) +/// - uint256[] hashes in depth-first order (<= 32*N bytes) +/// - CompactSize number of bytes of flag bits (1-3 bytes) +/// - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits) +/// +/// The size constraints follow from this. +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct PartialMerkleTree { + /// The total number of transactions in the block + num_transactions: u32, + /// node-is-parent-of-matched-txid bits + bits: Vec, + /// Transaction ids and internal hashes + hashes: Vec, +} + +impl PartialMerkleTree { + /// Returns the total number of transactions in the block. + pub fn num_transactions(&self) -> u32 { self.num_transactions } + + /// Returns the node-is-parent-of-matched-txid bits of the partial Merkle tree. + pub fn bits(&self) -> &Vec { &self.bits } + + /// Returns the transaction ids and internal hashes of the partial Merkle tree. + pub fn hashes(&self) -> &Vec { &self.hashes } + + /// Constructs a new partial Merkle tree + /// The `txids` are the transaction hashes of the block and the `matches` is the contains flags + /// wherever a tx hash should be included in the proof. + /// + /// # Panics + /// + /// Panics when `txids` is empty or when `matches` has a different length + /// + /// # Examples + /// + /// ```rust + /// use bitcoin::Txid; + /// use bitcoin::merkle_tree::PartialMerkleTree; + /// + /// // Block 80000 + /// let txids: Vec = [ + /// "c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25", + /// "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2", + /// ] + /// .iter() + /// .map(|hex| hex.parse::().unwrap()) + /// .collect(); + /// + /// // Select the second transaction + /// let matches = vec![false, true]; + /// let tree = PartialMerkleTree::from_txids(&txids, &matches); + /// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok()); + /// ``` + pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self { + // We can never have zero txs in a Merkle block, we always need the coinbase tx + assert_ne!(txids.len(), 0); + assert_eq!(txids.len(), matches.len()); + + let mut pmt = Self { + num_transactions: txids.len() as u32, + bits: Vec::with_capacity(txids.len()), + hashes: vec![], + }; + let height = pmt.calc_tree_height(); + + // traverse the partial tree + pmt.traverse_and_build(height, 0, txids, matches); + pmt + } + + /// Extracts the matching txid's represented by this partial Merkle tree + /// and their respective indices within the partial tree. + /// returns the Merkle root, or error in case of failure + pub fn extract_matches( + &self, + matches: &mut Vec, + indexes: &mut Vec, + ) -> Result { + matches.clear(); + indexes.clear(); + // An empty set will not work + if self.num_transactions == 0 { + return Err(MerkleBlockError::NoTransactions); + }; + // check for excessively high numbers of transactions + if self.num_transactions.to_u64() > Weight::MAX_BLOCK / Weight::MIN_TRANSACTION { + return Err(MerkleBlockError::TooManyTransactions); + } + // there can never be more hashes provided than one for every txid + if self.hashes.len() as u32 > self.num_transactions { + return Err(MerkleBlockError::TooManyHashes); + }; + // there must be at least one bit per node in the partial tree, and at least one node per hash + if self.bits.len() < self.hashes.len() { + return Err(MerkleBlockError::NotEnoughBits); + }; + + let height = self.calc_tree_height(); + + // traverse the partial tree + let mut bits_used = 0u32; + let mut hash_used = 0u32; + let hash_merkle_root = + self.traverse_and_extract(height, 0, &mut bits_used, &mut hash_used, matches, indexes)?; + // Verify that all bits were consumed (except for the padding caused by + // serializing it as a byte sequence) + if bits_used.div_ceil(8) != self.bits.len().div_ceil(8) as u32 { + return Err(MerkleBlockError::NotAllBitsConsumed); + } + // Verify that all hashes were consumed + if hash_used != self.hashes.len() as u32 { + return Err(MerkleBlockError::NotAllHashesConsumed); + } + Ok(hash_merkle_root) + } + + /// Calculates the height of the tree. + fn calc_tree_height(&self) -> u32 { + let mut height = 0; + while self.calc_tree_width(height) > 1 { + height += 1; + } + height + } + + /// Helper function to efficiently calculate the number of nodes at given height + /// in the Merkle tree + #[inline] + fn calc_tree_width(&self, height: u32) -> u32 { + (self.num_transactions + (1 << height) - 1) >> height + } + + /// Calculates the hash of a node in the Merkle tree (at leaf level: the txid's themselves) + fn calc_hash(&self, height: u32, pos: u32, txids: &[Txid]) -> TxMerkleNode { + if height == 0 { + // Hash at height 0 is the txid itself + TxMerkleNode::from_byte_array(txids[pos as usize].to_byte_array()) + } else { + // Calculate left hash + let left = self.calc_hash(height - 1, pos * 2, txids); + // Calculate right hash if not beyond the end of the array - copy left hash otherwise + let right = if pos * 2 + 1 < self.calc_tree_width(height - 1) { + self.calc_hash(height - 1, pos * 2 + 1, txids) + } else { + left + }; + // Combine subhashes + left.combine(&right) + } + } + + /// Recursive function that traverses tree nodes, storing the data as bits and hashes + fn traverse_and_build(&mut self, height: u32, pos: u32, txids: &[Txid], matches: &[bool]) { + // Determine whether this node is the parent of at least one matched txid + let mut parent_of_match = false; + let mut p = pos << height; + while p < (pos + 1) << height && p < self.num_transactions { + parent_of_match |= matches[p as usize]; + p += 1; + } + // Store as flag bit + self.bits.push(parent_of_match); + + if height == 0 || !parent_of_match { + // If at height 0, or nothing interesting below, store hash and stop + let hash = self.calc_hash(height, pos, txids); + self.hashes.push(hash); + } else { + // Otherwise, don't store any hash, but descend into the subtrees + self.traverse_and_build(height - 1, pos * 2, txids, matches); + if pos * 2 + 1 < self.calc_tree_width(height - 1) { + self.traverse_and_build(height - 1, pos * 2 + 1, txids, matches); + } + } + } + + /// Recursive function that traverses tree nodes, consuming the bits and hashes produced by + /// TraverseAndBuild. It returns the hash of the respective node and its respective index. + fn traverse_and_extract( + &self, + height: u32, + pos: u32, + bits_used: &mut u32, + hash_used: &mut u32, + matches: &mut Vec, + indexes: &mut Vec, + ) -> Result { + if *bits_used as usize >= self.bits.len() { + return Err(MerkleBlockError::BitsArrayOverflow); + } + let parent_of_match = self.bits[*bits_used as usize]; + *bits_used += 1; + if height == 0 || !parent_of_match { + // If at height 0, or nothing interesting below, use stored hash and do not descend + if *hash_used as usize >= self.hashes.len() { + return Err(MerkleBlockError::HashesArrayOverflow); + } + let hash = self.hashes[*hash_used as usize]; + *hash_used += 1; + if height == 0 && parent_of_match { + // in case of height 0, we have a matched txid + matches.push(Txid::from_byte_array(hash.to_byte_array())); + indexes.push(pos); + } + Ok(hash) + } else { + // otherwise, descend into the subtrees to extract matched txids and hashes + let left = self.traverse_and_extract( + height - 1, + pos * 2, + bits_used, + hash_used, + matches, + indexes, + )?; + let right; + if pos * 2 + 1 < self.calc_tree_width(height - 1) { + right = self.traverse_and_extract( + height - 1, + pos * 2 + 1, + bits_used, + hash_used, + matches, + indexes, + )?; + if right == left { + // The left and right branches should never be identical, as the transaction + // hashes covered by them must each be unique. + return Err(MerkleBlockError::IdenticalHashesFound); + } + } else { + right = left; + } + // and combine them before returning + Ok(left.combine(&right)) + } + } +} + +impl Encodable for PartialMerkleTree { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut ret = self.num_transactions.consensus_encode(w)?; + ret += self.hashes.consensus_encode(w)?; + + let nb_bytes_for_bits = self.bits.len().div_ceil(8); + ret += w.emit_compact_size(nb_bytes_for_bits)?; + for chunk in self.bits.chunks(8) { + let mut byte = 0u8; + for (i, bit) in chunk.iter().enumerate() { + byte |= (*bit as u8) << i; + } + ret += byte.consensus_encode(w)?; + } + Ok(ret) + } +} + +impl Decodable for PartialMerkleTree { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let num_transactions: u32 = Decodable::consensus_decode(r)?; + let hashes: Vec = Decodable::consensus_decode(r)?; + + let nb_bytes_for_bits = r.read_compact_size()? as usize; + if nb_bytes_for_bits > MAX_VEC_SIZE { + return Err(encode::ParseError::OversizedVectorAllocation { + requested: nb_bytes_for_bits, + max: MAX_VEC_SIZE, + } + .into()); + } + let mut bits = vec![false; nb_bytes_for_bits * 8]; + for chunk in bits.chunks_mut(8) { + let byte = u8::consensus_decode(r)?; + for (i, bit) in chunk.iter_mut().enumerate() { + *bit = (byte & (1 << i)) != 0; + } + } + + Ok(Self { num_transactions, hashes, bits }) + } +} + +/// An error when verifying the Merkle block. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum MerkleBlockError { + /// Merkle root in the header doesn't match to the root calculated from partial Merkle tree. + MerkleRootMismatch, + /// Partial Merkle tree contains no transactions. + NoTransactions, + /// There are too many transactions. + TooManyTransactions, + /// There are too many hashes + TooManyHashes, + /// There must be at least one bit per node in the partial tree, + /// and at least one node per hash + NotEnoughBits, + /// Not all bits were consumed + NotAllBitsConsumed, + /// Not all hashes were consumed + NotAllHashesConsumed, + /// Overflowed the bits array + BitsArrayOverflow, + /// Overflowed the hashes array + HashesArrayOverflow, + /// The left and right branches should never be identical + IdenticalHashesFound, +} + +impl From for MerkleBlockError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for MerkleBlockError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::MerkleRootMismatch => write!(f, "Merkle header root doesn't match to the root calculated from the partial Merkle tree"), + Self::NoTransactions => write!(f, "partial Merkle tree contains no transactions"), + Self::TooManyTransactions => write!(f, "too many transactions"), + Self::TooManyHashes => write!(f, "proof contains more hashes than transactions"), + Self::NotEnoughBits => write!(f, "proof contains fewer bits than hashes"), + Self::NotAllBitsConsumed => write!(f, "not all bits were consumed"), + Self::NotAllHashesConsumed => write!(f, "not all hashes were consumed"), + Self::BitsArrayOverflow => write!(f, "overflowed the bits array"), + Self::HashesArrayOverflow => write!(f, "overflowed the hashes array"), + Self::IdenticalHashesFound => write!(f, "found identical transaction hashes"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for MerkleBlockError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::MerkleRootMismatch + | Self::NoTransactions + | Self::TooManyTransactions + | Self::TooManyHashes + | Self::NotEnoughBits + | Self::NotAllBitsConsumed + | Self::NotAllHashesConsumed + | Self::BitsArrayOverflow + | Self::HashesArrayOverflow + | Self::IdenticalHashesFound => None, + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for PartialMerkleTree { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + num_transactions: u.arbitrary()?, + bits: Vec::::arbitrary(u)?, + hashes: Vec::::arbitrary(u)?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for MerkleBlock { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { header: u.arbitrary()?, txn: u.arbitrary()? }) + } +} + +#[cfg(test)] +mod tests { + use hex::{DisplayHex, FromHex}; + use hex_lit::hex; + #[cfg(all(feature = "rand", feature = "std"))] + use {core::cmp, secp256k1::rand::prelude::*}; + + use super::*; + use crate::block::Unchecked; + use crate::consensus::encode; + use crate::Txid; + + #[cfg(all(feature = "rand", feature = "std"))] + macro_rules! pmt_tests { + ($($name:ident),* $(,)?) => { + $( + #[test] + fn $name() { + pmt_test_from_name(stringify!($name)); + } + )* + } + } + + #[cfg(all(feature = "rand", feature = "std"))] + pmt_tests!( + pmt_test_1, + pmt_test_4, + pmt_test_7, + pmt_test_17, + pmt_test_56, + pmt_test_100, + pmt_test_127, + pmt_test_256, + pmt_test_312, + pmt_test_513, + pmt_test_1000, + pmt_test_4095 + ); + + /// Parses the transaction count out of `name` with form: `pmt_test_$num`. + #[cfg(all(feature = "rand", feature = "std"))] + fn pmt_test_from_name(name: &str) { pmt_test(name[9..].parse().unwrap()) } + + #[cfg(all(feature = "rand", feature = "std"))] + fn pmt_test(tx_count: usize) { + let mut rng = secp256k1::rand::rng(); + // Create some fake tx ids + let tx_ids = (1..=tx_count) + .map(|i| format!("{:064x}", i).parse::().unwrap()) + .collect::>(); + + // Calculate the Merkle root and height + let hashes = tx_ids.iter().copied(); + let merkle_root_1 = TxMerkleNode::calculate_root(hashes).expect("hashes is not empty"); + let mut height = 1; + let mut ntx = tx_count; + while ntx > 1 { + ntx = ntx.div_ceil(2); + height += 1; + } + + // Check with random subsets with inclusion chances 1, 1/2, 1/4, ..., 1/128 + for att in 1..15 { + let mut matches = vec![false; tx_count]; + let mut match_txid1 = vec![]; + for j in 0..tx_count { + // Generate `att / 2` random bits + let rand_bits = match att / 2 { + 0 => 0, + bits => rng.random::() >> (64 - bits), + }; + let include = rand_bits == 0; + matches[j] = include; + + if include { + match_txid1.push(tx_ids[j]); + }; + } + + // Build the partial Merkle tree + let pmt1 = PartialMerkleTree::from_txids(&tx_ids, &matches); + let serialized = encode::serialize(&pmt1); + + // Verify PartialMerkleTree's size guarantees + let n = cmp::min(tx_count, 1 + match_txid1.len() * height); + assert!(serialized.len() <= 10 + (258 * n).div_ceil(8)); + + // Deserialize into a tester copy + let pmt2: PartialMerkleTree = + encode::deserialize(&serialized).expect("could not deserialize own data"); + + // Extract Merkle root and matched txids from copy + let mut match_txid2: Vec = vec![]; + let mut indexes = vec![]; + let merkle_root_2 = pmt2 + .extract_matches(&mut match_txid2, &mut indexes) + .expect("could not extract matches"); + + // Check that it has the same Merkle root as the original, and a valid one + assert_eq!(merkle_root_1, merkle_root_2); + assert_ne!(merkle_root_2, TxMerkleNode::from_byte_array([0; 32])); + + // check that it contains the matched transactions (in the same order!) + assert_eq!(match_txid1, match_txid2); + + // check that random bit flips break the authentication + for _ in 0..4 { + let mut pmt3: PartialMerkleTree = encode::deserialize(&serialized).unwrap(); + pmt3.damage(&mut rng); + let mut match_txid3 = vec![]; + let merkle_root_3 = pmt3.extract_matches(&mut match_txid3, &mut indexes).unwrap(); + assert_ne!(merkle_root_3, merkle_root_1); + } + } + } + + #[test] + fn pmt_malleability() { + // Create some fake tx ids with the last 2 hashes repeating + let txids: Vec = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10] + .iter() + .map(|i| format!("{:064x}", i).parse::().unwrap()) + .collect(); + + let matches = + vec![false, false, false, false, false, false, false, false, false, true, true, false]; + + let tree = PartialMerkleTree::from_txids(&txids, &matches); + // Should fail due to duplicate txs found + let result = tree.extract_matches(&mut vec![], &mut vec![]); + assert!(result.is_err()); + } + + #[test] + fn merkleblock_serialization() { + // Got it by running the rpc call + // `gettxoutproof '["220ebc64e21abece964927322cba69180ed853bb187fbc6923bac7d010b9d87a"]'` + let mb_hex = include_str!("../../tests/data/merkle_block.hex"); + + let bytes = Vec::from_hex(mb_hex).unwrap(); + let mb: MerkleBlock = encode::deserialize(&bytes).unwrap(); + assert_eq!(get_block_13b8a().block_hash(), mb.header.block_hash()); + assert_eq!( + mb.header.merkle_root, + mb.txn.extract_matches(&mut vec![], &mut vec![]).unwrap() + ); + // Serialize again and check that it matches the original bytes + assert_eq!(mb_hex, encode::serialize(&mb).to_lower_hex_string().as_str()); + } + + /// Constructs a new MerkleBlock using a list of txids which will be found in the + /// given block. + #[test] + fn merkleblock_construct_from_txids_found() { + let block = get_block_13b8a(); + + let txids: Vec = [ + "74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20", + "f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07", + ] + .iter() + .map(|hex| hex.parse::().unwrap()) + .collect(); + + let txid1 = txids[0]; + let txid2 = txids[1]; + let txids = [txid1, txid2]; + + let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t)); + + assert_eq!(merkle_block.header.block_hash(), block.block_hash()); + + let mut matches: Vec = vec![]; + let mut index: Vec = vec![]; + + assert_eq!( + merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(), + block.header().merkle_root + ); + assert_eq!(matches.len(), 2); + + // Ordered by occurrence in depth-first tree traversal. + assert_eq!(matches[0], txid2); + assert_eq!(index[0], 1); + + assert_eq!(matches[1], txid1); + assert_eq!(index[1], 8); + } + + /// Constructs a new MerkleBlock using a list of txids which will not be found in the given block + #[test] + fn merkleblock_construct_from_txids_not_found() { + let block = get_block_13b8a(); + let txids: Vec = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"] + .iter() + .map(|hex| hex.parse::().unwrap()) + .collect(); + + let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t)); + + assert_eq!(merkle_block.header.block_hash(), block.block_hash()); + + let mut matches: Vec = vec![]; + let mut index: Vec = vec![]; + + assert_eq!( + merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(), + block.header().merkle_root + ); + assert_eq!(matches.len(), 0); + assert_eq!(index.len(), 0); + } + + #[cfg(all(feature = "rand", feature = "std"))] + impl PartialMerkleTree { + /// Flip one bit in one of the hashes - this should break the authentication + fn damage(&mut self, rng: &mut ThreadRng) { + let n = rng.random_range(0..self.hashes.len()); + let bit = rng.random::(); + let hashes = &mut self.hashes; + let mut hash = hashes[n].to_byte_array(); + hash[(bit >> 3) as usize] ^= 1 << (bit & 7); + hashes[n] = TxMerkleNode::from_byte_array(hash); + } + } + + /// Returns a real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af) + /// with 9 txs. + fn get_block_13b8a() -> Block { + let block_hex = include_str!("../../tests/data/block_13b8a.hex"); + let block: Block = + encode::deserialize(&Vec::from_hex(block_hex).unwrap()).unwrap(); + block.validate().expect("block should be valid") + } + + macro_rules! check_calc_tree_width { + ($($test_name:ident, $num_transactions:literal, $height:literal, $expected_width:literal);* $(;)?) => { + $( + #[test] + fn $test_name() { + let pmt = PartialMerkleTree { + num_transactions: $num_transactions, + bits: vec![], + hashes: vec![], + }; + let got = pmt.calc_tree_width($height); + assert_eq!(got, $expected_width) + } + )* + } + } + + // tree_width_ + // + // height 0 is the bottom of the tree, where the leaves are. + check_calc_tree_width! { + tree_width_01, 1, 0, 1; + // + tree_width_02, 2, 0, 2; + tree_width_03, 2, 1, 1; + // + tree_width_04, 3, 0, 3; + tree_width_05, 3, 1, 2; + tree_width_06, 3, 2, 1; + // + tree_width_07, 4, 0, 4; + tree_width_08, 4, 1, 2; + tree_width_09, 4, 2, 1; + // + tree_width_10, 5, 0, 5; + tree_width_11, 5, 1, 3; + tree_width_12, 5, 2, 2; + tree_width_13, 5, 3, 1; + // + tree_width_14, 6, 0, 6; + tree_width_15, 6, 1, 3; + tree_width_16, 6, 2, 2; + tree_width_17, 6, 3, 1; + // + tree_width_18, 7, 0, 7; + tree_width_19, 7, 1, 4; + tree_width_20, 7, 2, 2; + tree_width_21, 7, 3, 1; + } + + #[test] + fn regression_2606() { + // Attempt to deserialize a partial Merkle tree with a number of hashes that would + // overflow the maximum allowed size. + let bytes = hex!( + "000006000000000000000004ee00000004c7f1ccb1000000ffff000000010000\ + 0000ffffffffff1f000000000400000000000002000000000500000000000000\ + 000000000300000000000003000000000200000000ff00000000c7f1ccb10407\ + 00000000000000ccb100c76538b100000004bfa9c251681b1b00040000000025\ + 00000004bfaac251681b1b25\ + " + ); + let deser = encode::deserialize::(&bytes); + + // The attempt to deserialize should result in an error. + assert!(deser.is_err()); + } + + #[test] + fn extract_matches_from_merkleblock() { + // Get the proof from a bitcoind by running in the terminal: + // $ TXID="5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2" + // $ bitcoin-cli gettxoutproof [\"$TXID\"] + let mb_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b913719\ + 0000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33a5914ce6ed5b\ + 1b01e32f570200000002252bf9d75c4f481ebb6278d708257d1f12beb6dd30301d26c623f789b2ba6fc0e2d3\ + 2adb5f8ca820731dff234a84e78ec30bce4ec69dbd562d0b2b8266bf4e5a0105").unwrap(); + let mb: MerkleBlock = encode::deserialize(&mb_bytes).unwrap(); + + // Authenticate and extract matched transaction ids + let mut matches: Vec = vec![]; + let mut index: Vec = vec![]; + assert!(mb.extract_matches(&mut matches, &mut index).is_ok()); + + // The matches and index vectors are coupled, should be the same length. + assert_eq!(matches.len(), index.len()); + + // There should only be one match. + assert_eq!(matches.len(), 1); + + // The match should come from index 1. + assert_eq!(index[0], 1); + + // And we know the txid we want. + let want = "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2" + .parse::() + .expect("failed to parse txid"); + assert_eq!(matches[0], want); + } +} diff --git a/bitcoin/src/merkle_tree/mod.rs b/bitcoin/src/merkle_tree/mod.rs new file mode 100644 index 000000000..819959491 --- /dev/null +++ b/bitcoin/src/merkle_tree/mod.rs @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Merkle tree functions. +//! +//! # Examples +//! +//! ``` +//! # use bitcoin::Txid; +//! # use bitcoin::merkle_tree::TxMerkleNode; +//! # let tx1 = Txid::from_byte_array([0xAA; 32]); // Arbitrary dummy hash values. +//! # let tx2 = Txid::from_byte_array([0xFF; 32]); +//! let tx_hashes = [tx1, tx2]; // All the hashes we wish to merkelize. +//! let root = TxMerkleNode::calculate_root(tx_hashes.into_iter()); +//! assert!(root.is_some()); +//! ``` + +mod block; + +use io::{BufRead, Write}; + +#[rustfmt::skip] +#[doc(inline)] +pub use self::block::{MerkleBlock, MerkleBlockError, PartialMerkleTree}; +pub use primitives::{TxMerkleNode, WitnessMerkleNode}; + +use crate::consensus::{encode, Decodable, Encodable}; + +impl Encodable for TxMerkleNode { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_byte_array().consensus_encode(w) + } +} + +impl Decodable for TxMerkleNode { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<[u8; 32]>::consensus_decode(r)?)) + } +} + +impl Encodable for WitnessMerkleNode { + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_byte_array().consensus_encode(w) + } +} + +impl Decodable for WitnessMerkleNode { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self::from_byte_array(<[u8; 32]>::consensus_decode(r)?)) + } +} diff --git a/bitcoin/src/network/mod.rs b/bitcoin/src/network/mod.rs new file mode 100644 index 000000000..3de1b280c --- /dev/null +++ b/bitcoin/src/network/mod.rs @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin network. +//! +//! The term "network" is overloaded, here [`Network`] refers to the specific +//! Bitcoin network we are operating on e.g., signet, regtest. The terms +//! "network" and "chain" are often used interchangeably for this concept. + +pub mod params; + +use core::fmt; +use core::str::FromStr; + +use internals::write_err; +#[cfg(feature = "serde")] +use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::constants::ChainHash; +use crate::prelude::{String, ToOwned}; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::params::Params; + +/// What kind of network we are on. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum NetworkKind { + /// The Bitcoin mainnet network. + Main, + /// Some kind of testnet network. + Test, +} + +// We explicitly do not provide `is_testnet`, using `!network.is_mainnet()` is less +// ambiguous due to confusion caused by signet/testnet/regtest. +impl NetworkKind { + /// Returns true if this is real mainnet bitcoin. + pub fn is_mainnet(&self) -> bool { *self == Self::Main } +} + +impl From for NetworkKind { + fn from(n: Network) -> Self { + use Network::*; + + match n { + Bitcoin => Self::Main, + Testnet(_) | Signet | Regtest => Self::Test, + } + } +} + +/// The testnet version to act on. +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)] +#[non_exhaustive] +pub enum TestnetVersion { + /// Testnet version 3. + V3, + /// Testnet version 4. + V4, +} + +/// The cryptocurrency network to act on. +/// +/// This is an exhaustive enum, meaning that we cannot add any future networks without defining a +/// new, incompatible version of this type. If you are using this type directly and wish to support the +/// new network, this will be a breaking change to your APIs and likely require changes in your code. +/// +/// If you are concerned about forward compatibility, consider using `T: Into` instead of +/// this type as a parameter to functions in your public API, or directly using the `Params` type. +// For extensive discussion on the usage of `non_exhaustive` please see: +// https://github.com/rust-bitcoin/rust-bitcoin/issues/2225 +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)] +pub enum Network { + /// Mainnet Bitcoin. + Bitcoin, + /// Bitcoin's testnet network. + Testnet(TestnetVersion), + /// Bitcoin's signet network. + Signet, + /// Bitcoin's regtest network. + Regtest, +} + +#[cfg(feature = "serde")] +impl Serialize for Network { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.as_display_str()) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Network { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct NetworkVisitor; + + impl Visitor<'_> for NetworkVisitor { + type Value = Network; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a valid network identifier") + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + Network::from_str(value).map_err(E::custom) + } + } + + deserializer.deserialize_str(NetworkVisitor) + } +} + +impl Network { + /// Converts a `Network` to its equivalent `bitcoind -chain` argument name. + /// + /// ```bash + /// $ bitcoin-23.0/bin/bitcoind --help | grep -C 3 '\-chain=' + /// Chain selection options: + /// + /// -chain= + /// Use the chain (default: main). Allowed values: main, test, signet, regtest + /// ``` + pub fn to_core_arg(self) -> &'static str { + match self { + Self::Bitcoin => "main", + // For user-side compatibility, testnet3 is retained as test + Self::Testnet(TestnetVersion::V3) => "test", + Self::Testnet(TestnetVersion::V4) => "testnet4", + Self::Signet => "signet", + Self::Regtest => "regtest", + } + } + + /// Converts a `bitcoind -chain` argument name to its equivalent `Network`. + /// + /// ```bash + /// $ bitcoin-23.0/bin/bitcoind --help | grep -C 3 '\-chain=' + /// Chain selection options: + /// + /// -chain= + /// Use the chain (default: main). Allowed values: main, test, signet, regtest + /// ``` + pub fn from_core_arg(core_arg: &str) -> Result { + use Network::*; + + let network = match core_arg { + "main" => Bitcoin, + "test" => Testnet(TestnetVersion::V3), + "testnet4" => Testnet(TestnetVersion::V4), + "signet" => Signet, + "regtest" => Regtest, + _ => return Err(ParseNetworkError(core_arg.to_owned())), + }; + Ok(network) + } + + /// Return the network's chain hash (genesis block hash). + /// + /// # Examples + /// + /// ```rust + /// use bitcoin::Network; + /// use bitcoin::constants::ChainHash; + /// + /// let network = Network::Bitcoin; + /// assert_eq!(network.chain_hash(), ChainHash::BITCOIN); + /// ``` + pub fn chain_hash(self) -> ChainHash { ChainHash::using_genesis_block_const(self) } + + /// Constructs a new `Network` from the chain hash (genesis block hash). + /// + /// # Examples + /// + /// ```rust + /// use bitcoin::Network; + /// use bitcoin::constants::ChainHash; + /// + /// assert_eq!(Ok(Network::Bitcoin), Network::try_from(ChainHash::BITCOIN)); + /// ``` + pub fn from_chain_hash(chain_hash: ChainHash) -> Option { + Self::try_from(chain_hash).ok() + } + + /// Returns the associated network parameters. + pub const fn params(self) -> &'static Params { + match self { + Self::Bitcoin => &Params::BITCOIN, + Self::Testnet(TestnetVersion::V3) => &Params::TESTNET3, + Self::Testnet(TestnetVersion::V4) => &Params::TESTNET4, + Self::Signet => &Params::SIGNET, + Self::Regtest => &Params::REGTEST, + } + } + + /// Returns a string representation of the `Network` enum variant. + /// This is useful for displaying the network type as a string. + const fn as_display_str(self) -> &'static str { + match self { + Self::Bitcoin => "bitcoin", + Self::Testnet(TestnetVersion::V3) => "testnet", + Self::Testnet(TestnetVersion::V4) => "testnet4", + Self::Signet => "signet", + Self::Regtest => "regtest", + } + } +} + +#[cfg(feature = "serde")] +pub mod as_core_arg { + //! Module for serialization/deserialization of network variants into/from Bitcoin Core values + #![allow(missing_docs)] + + use crate::Network; + + pub fn serialize(network: &Network, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(network.to_core_arg()) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct NetworkVisitor; + + impl serde::de::Visitor<'_> for NetworkVisitor { + type Value = Network; + + fn visit_str(self, s: &str) -> Result { + Network::from_core_arg(s).map_err(|_| { + E::invalid_value( + serde::de::Unexpected::Str(s), + &"bitcoin network encoded as a string (either main, test, testnet4, signet or regtest)", + ) + }) + } + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + write!( + formatter, + "bitcoin network encoded as a string (either main, test, testnet4, signet or regtest)" + ) + } + } + + deserializer.deserialize_str(NetworkVisitor) + } +} + +/// An error in parsing network string. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct ParseNetworkError(String); + +impl fmt::Display for ParseNetworkError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write_err!(f, "failed to parse {} as network", self.0; self) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseNetworkError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +impl FromStr for Network { + type Err = ParseNetworkError; + + #[inline] + fn from_str(s: &str) -> Result { + match s { + "bitcoin" => Ok(Self::Bitcoin), + // For user-side compatibility, testnet3 is retained as testnet + "testnet" => Ok(Self::Testnet(TestnetVersion::V3)), + "testnet4" => Ok(Self::Testnet(TestnetVersion::V4)), + "signet" => Ok(Self::Signet), + "regtest" => Ok(Self::Regtest), + _ => Err(ParseNetworkError(s.to_owned())), + } + } +} + +impl fmt::Display for Network { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{}", self.as_display_str()) + } +} + +/// Error in parsing network from chain hash. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UnknownChainHashError(ChainHash); + +impl fmt::Display for UnknownChainHashError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "unknown chain hash: {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnknownChainHashError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +impl TryFrom for Network { + type Error = UnknownChainHashError; + + fn try_from(chain_hash: ChainHash) -> Result { + match chain_hash { + // Note: any new network entries must be matched against here. + ChainHash::BITCOIN => Ok(Self::Bitcoin), + ChainHash::TESTNET3 => Ok(Self::Testnet(TestnetVersion::V3)), + ChainHash::TESTNET4 => Ok(Self::Testnet(TestnetVersion::V4)), + ChainHash::SIGNET => Ok(Self::Signet), + ChainHash::REGTEST => Ok(Self::Regtest), + _ => Err(UnknownChainHashError(chain_hash)), + } + } +} + +#[cfg(test)] +mod tests { + use super::{Network, TestnetVersion}; + + #[test] + fn string() { + assert_eq!(Network::Bitcoin.to_string(), "bitcoin"); + assert_eq!(Network::Testnet(TestnetVersion::V3).to_string(), "testnet"); + assert_eq!(Network::Testnet(TestnetVersion::V4).to_string(), "testnet4"); + assert_eq!(Network::Regtest.to_string(), "regtest"); + assert_eq!(Network::Signet.to_string(), "signet"); + + assert_eq!("bitcoin".parse::().unwrap(), Network::Bitcoin); + assert_eq!("testnet".parse::().unwrap(), Network::Testnet(TestnetVersion::V3)); + assert_eq!("testnet4".parse::().unwrap(), Network::Testnet(TestnetVersion::V4)); + assert_eq!("regtest".parse::().unwrap(), Network::Regtest); + assert_eq!("signet".parse::().unwrap(), Network::Signet); + assert!("fakenet".parse::().is_err()); + } + + #[test] + #[cfg(feature = "serde")] + fn serde_roundtrip() { + use Network::*; + let tests = vec![ + (Bitcoin, "bitcoin"), + (Testnet(TestnetVersion::V3), "testnet"), + (Testnet(TestnetVersion::V4), "testnet4"), + (Signet, "signet"), + (Regtest, "regtest"), + ]; + + for tc in tests { + let network = tc.0; + + let want = format!("\"{}\"", tc.1); + let got = serde_json::to_string(&tc.0).expect("failed to serialize network"); + assert_eq!(got, want); + + let back: Network = serde_json::from_str(&got).expect("failed to deserialize network"); + assert_eq!(back, network); + } + } + + #[test] + fn from_to_core_arg() { + let expected_pairs = [ + (Network::Bitcoin, "main"), + (Network::Testnet(TestnetVersion::V3), "test"), + (Network::Testnet(TestnetVersion::V4), "testnet4"), + (Network::Regtest, "regtest"), + (Network::Signet, "signet"), + ]; + + for (net, core_arg) in &expected_pairs { + assert_eq!(Network::from_core_arg(core_arg), Ok(*net)); + assert_eq!(net.to_core_arg(), *core_arg); + } + } + + #[test] + #[cfg(feature = "serde")] + fn serde_as_core_arg() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct T { + #[serde(with = "crate::network::as_core_arg")] + pub network: Network, + } + + serde_test::assert_tokens( + &T { network: Network::Bitcoin }, + &[ + serde_test::Token::Struct { name: "T", len: 1 }, + serde_test::Token::Str("network"), + serde_test::Token::Str("main"), + serde_test::Token::StructEnd, + ], + ); + } +} diff --git a/bitcoin/src/network/params.rs b/bitcoin/src/network/params.rs new file mode 100644 index 000000000..7fd79a000 --- /dev/null +++ b/bitcoin/src/network/params.rs @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin consensus parameters. +//! +//! This module provides a predefined set of parameters for different Bitcoin +//! chains (such as mainnet, testnet, testnet4). +//! +//! # Custom Signets Example +//! +//! In various places in this crate we take `AsRef` as a parameter, in order to create a +//! custom type that can be used in such places you might want to do the following: +//! +//! ``` +//! use bitcoin::network::Params; +//! use bitcoin::{WitnessScript, WitnessScriptBuf, Network, Target}; +//! +//! const POW_TARGET_SPACING: u64 = 120; // Two minutes. +//! +//! pub struct CustomParams { +//! params: Params, +//! challenge_script: WitnessScriptBuf, +//! } +//! +//! impl CustomParams { +//! /// Constructs a new custom params. +//! pub fn new() -> Self { +//! let mut params = Params::new(Network::Signet); +//! params.pow_target_spacing = POW_TARGET_SPACING; +//! +//! // This would be something real (see BIP-00325). +//! let challenge_script = WitnessScriptBuf::new(); +//! +//! Self { +//! params, +//! challenge_script, +//! } +//! } +//! +//! /// Returns the custom signet challenge script. +//! pub fn challenge_script(&self) -> &WitnessScript { &self.challenge_script } +//! } +//! +//! impl AsRef for CustomParams { +//! fn as_ref(&self) -> &Params { &self.params } +//! } +//! +//! impl Default for CustomParams { +//! fn default() -> Self { Self::new() } +//! } +//! +//! # { // Just check the code above is usable. +//! # let target = Target::MAX_ATTAINABLE_SIGNET; +//! # +//! # let signet = Params::SIGNET; +//! # let _ = target.difficulty(signet); +//! # +//! # let custom = CustomParams::new(); +//! # let _ = custom.challenge_script(); +//! # let _ = target.difficulty(custom); +//! # } +//! ``` + +use super::{Network, TestnetVersion}; +#[cfg(doc)] +use crate::pow::CompactTarget; +use crate::pow::Target; +use crate::{BlockHeight, BlockHeightInterval}; + +/// Parameters that influence chain consensus. +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct Params { + /// Network for which parameters are valid. + pub network: Network, + /// Time when BIP-0016 becomes active. + pub bip16_time: u32, + /// Block height at which BIP-0034 becomes active. + pub bip34_height: BlockHeight, + /// Block height at which BIP-0065 becomes active. + pub bip65_height: BlockHeight, + /// Block height at which BIP-0066 becomes active. + pub bip66_height: BlockHeight, + /// Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, + /// (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP-0009 deployments. + /// Examples: 1916 for 95%, 1512 for testchains. + pub rule_change_activation_threshold: BlockHeightInterval, + /// Number of blocks with the same set of rules. + pub miner_confirmation_window: BlockHeightInterval, + /// Proof of work limit value. It contains the lowest possible difficulty. + #[deprecated(since = "0.32.0", note = "use `max_attainable_target` instead")] + pub pow_limit: Target, + /// The maximum **attainable** target value for these params. + /// + /// Not all target values are attainable because consensus code uses the compact format to + /// represent targets (see [`CompactTarget`]). + /// + /// Note that this value differs from Bitcoin Core's powLimit field in that this value is + /// attainable, but Bitcoin Core's is not. Specifically, because targets in Bitcoin are always + /// rounded to the nearest float expressible in "compact form", not all targets are attainable. + /// Still, this should not affect consensus as the only place where the non-compact form of + /// this is used in Bitcoin Core's consensus algorithm is in comparison and there are no + /// compact-expressible values between Bitcoin Core's and the limit expressed here. + pub max_attainable_target: Target, + /// Expected amount of time to mine one block. + pub pow_target_spacing: u64, + /// Difficulty recalculation interval. + pub pow_target_timespan: u32, + /// Determines whether minimal difficulty may be used for blocks or not. + pub allow_min_difficulty_blocks: bool, + /// Determines whether retargeting is disabled for this network or not. + pub no_pow_retargeting: bool, +} + +/// The mainnet parameters. +/// +/// Use this for a static reference e.g., `¶ms::MAINNET`. +/// +/// For more on static vs const see The Rust Reference [using-statics-or-consts] section. +/// +/// [using-statics-or-consts]: +pub static MAINNET: Params = Params::MAINNET; +/// The testnet3 parameters. +#[deprecated(since = "TBD", note = "use `TESTNET3` instead")] +pub static TESTNET: Params = Params::TESTNET3; +/// The testnet3 parameters. +pub static TESTNET3: Params = Params::TESTNET3; +/// The testnet4 parameters. +pub static TESTNET4: Params = Params::TESTNET4; +/// The signet parameters. +pub static SIGNET: Params = Params::SIGNET; +/// The regtest parameters. +pub static REGTEST: Params = Params::REGTEST; + +#[allow(deprecated)] // For `pow_limit`. +impl Params { + /// The mainnet parameters (alias for `Params::MAINNET`). + pub const BITCOIN: Self = Self::MAINNET; + + /// The mainnet parameters. + pub const MAINNET: Self = Self { + network: Network::Bitcoin, + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(227931), // 000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8 + bip65_height: BlockHeight::from_u32(388381), // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 + bip66_height: BlockHeight::from_u32(363725), // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 + rule_change_activation_threshold: BlockHeightInterval::from_u32(1916), // 95% + miner_confirmation_window: BlockHeightInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_MAINNET, + max_attainable_target: Target::MAX_ATTAINABLE_MAINNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: false, + no_pow_retargeting: false, + }; + + /// The testnet3 parameters. + #[deprecated(since = "TBD", note = "use `TESTNET3` instead")] + pub const TESTNET: Self = Self { + network: Network::Testnet(TestnetVersion::V3), + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(21111), // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8 + bip65_height: BlockHeight::from_u32(581885), // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 + bip66_height: BlockHeight::from_u32(330776), // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 + rule_change_activation_threshold: BlockHeightInterval::from_u32(1512), // 75% + miner_confirmation_window: BlockHeightInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_TESTNET, + max_attainable_target: Target::MAX_ATTAINABLE_TESTNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: true, + no_pow_retargeting: false, + }; + + /// The testnet3 parameters. + pub const TESTNET3: Self = Self { + network: Network::Testnet(TestnetVersion::V3), + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(21111), // 0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8 + bip65_height: BlockHeight::from_u32(581885), // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 + bip66_height: BlockHeight::from_u32(330776), // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 + rule_change_activation_threshold: BlockHeightInterval::from_u32(1512), // 75% + miner_confirmation_window: BlockHeightInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_TESTNET, + max_attainable_target: Target::MAX_ATTAINABLE_TESTNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: true, + no_pow_retargeting: false, + }; + + /// The testnet4 parameters. + pub const TESTNET4: Self = Self { + network: Network::Testnet(TestnetVersion::V4), + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(1), + bip65_height: BlockHeight::from_u32(1), + bip66_height: BlockHeight::from_u32(1), + rule_change_activation_threshold: BlockHeightInterval::from_u32(1512), // 75% + miner_confirmation_window: BlockHeightInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_TESTNET, + max_attainable_target: Target::MAX_ATTAINABLE_TESTNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: true, + no_pow_retargeting: false, + }; + + /// The signet parameters. + pub const SIGNET: Self = Self { + network: Network::Signet, + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(1), + bip65_height: BlockHeight::from_u32(1), + bip66_height: BlockHeight::from_u32(1), + rule_change_activation_threshold: BlockHeightInterval::from_u32(1916), // 95% + miner_confirmation_window: BlockHeightInterval::from_u32(2016), + pow_limit: Target::MAX_ATTAINABLE_SIGNET, + max_attainable_target: Target::MAX_ATTAINABLE_SIGNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: false, + no_pow_retargeting: false, + }; + + /// The regtest parameters. + pub const REGTEST: Self = Self { + network: Network::Regtest, + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: BlockHeight::from_u32(100000000), // not activated on regtest + bip65_height: BlockHeight::from_u32(1351), + bip66_height: BlockHeight::from_u32(1251), // used only in rpc tests + rule_change_activation_threshold: BlockHeightInterval::from_u32(108), // 75% + miner_confirmation_window: BlockHeightInterval::from_u32(144), + pow_limit: Target::MAX_ATTAINABLE_REGTEST, + max_attainable_target: Target::MAX_ATTAINABLE_REGTEST, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: true, + no_pow_retargeting: true, + }; + + /// Constructs parameters set for the given network. + pub const fn new(network: Network) -> Self { + match network { + Network::Bitcoin => Self::MAINNET, + Network::Testnet(TestnetVersion::V3) => Self::TESTNET3, + Network::Testnet(TestnetVersion::V4) => Self::TESTNET4, + Network::Signet => Self::SIGNET, + Network::Regtest => Self::REGTEST, + } + } + + /// Calculates the number of blocks between difficulty adjustments. + pub fn difficulty_adjustment_interval(&self) -> u64 { + u64::from(self.pow_target_timespan) / self.pow_target_spacing + } +} + +impl From for Params { + fn from(value: Network) -> Self { Self::new(value) } +} + +impl From<&Network> for Params { + fn from(value: &Network) -> Self { Self::new(*value) } +} + +impl From for &'static Params { + fn from(value: Network) -> Self { value.params() } +} + +impl From<&Network> for &'static Params { + fn from(value: &Network) -> Self { value.params() } +} + +impl AsRef for Params { + fn as_ref(&self) -> &Self { self } +} + +impl AsRef for Network { + fn as_ref(&self) -> &Params { Self::params(*self) } +} diff --git a/bitcoin/src/policy.rs b/bitcoin/src/policy.rs new file mode 100644 index 000000000..96b77bbab --- /dev/null +++ b/bitcoin/src/policy.rs @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin policy. +//! +//! This module exposes some constants and functions used in the reference +//! implementation and which, as a consequence, define some network rules. +//! +//! # *Warning* +//! While the constants present in this module are very unlikely to change, they do not define +//! Bitcoin. As such they must not be relied upon as if they were consensus rules. +//! +//! These values were taken from bitcoind v0.21.1 (194b9b8792d9b0798fdb570b79fa51f1d1f5ebaf). + +use core::cmp; + +use super::constants::{MAX_BLOCK_SIGOPS_COST, WITNESS_SCALE_FACTOR}; + +/// Maximum weight of a transaction for it to be relayed by most nodes on the network +pub const MAX_STANDARD_TX_WEIGHT: u32 = 400_000; + +/// Minimum non-witness size for a standard transaction, set to 65 bytes. +pub const MIN_STANDARD_TX_NONWITNESS_SIZE: u32 = 65; + +/// Maximum number of sigops in a standard tx. +pub const MAX_STANDARD_TX_SIGOPS_COST: u32 = MAX_BLOCK_SIGOPS_COST as u32 / 5; + +/// The minimum incremental *feerate* (despite the name), in sats per virtual kilobyte for RBF. +pub const DEFAULT_INCREMENTAL_RELAY_FEE: u32 = 1_000; + +/// The number of bytes equivalent per signature operation. Affects transaction relay through the +/// virtual size computation. +pub const DEFAULT_BYTES_PER_SIGOP: u32 = 20; + +/// The minimum feerate, in sats per kilo-virtualbyte, for defining dust. An output is considered +/// dust if spending it under this feerate would cost more in fee. +pub const DUST_RELAY_TX_FEE: u32 = 3_000; + +/// Minimum feerate, in sats per virtual kilobyte, for a transaction to be relayed by most nodes on +/// the network. +pub const DEFAULT_MIN_RELAY_TX_FEE: u32 = 1_000; + +/// Default number of hours for an unconfirmed transaction to expire in most of the network nodes' +/// mempools. +pub const DEFAULT_MEMPOOL_EXPIRY: u32 = 336; + +// 80 bytes of data, +1 for OP_RETURN, +2 for the pushdata opcodes. +pub(crate) const MAX_OP_RETURN_RELAY: usize = 83; + +/// The virtual transaction size, as computed by default by bitcoind node. +pub fn get_virtual_tx_size(weight: i64, n_sigops: i64) -> i64 { + (cmp::max(weight, n_sigops * DEFAULT_BYTES_PER_SIGOP as i64) + WITNESS_SCALE_FACTOR as i64 - 1) + / WITNESS_SCALE_FACTOR as i64 +} diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs new file mode 100644 index 000000000..0abb20987 --- /dev/null +++ b/bitcoin/src/pow.rs @@ -0,0 +1,2054 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Proof-of-work related integer types. +//! +//! Provides the [`Work`] and [`Target`] types that are used in proof-of-work calculations. The +//! functions here are designed to be fast, by that we mean it is safe to use them to check headers. + +use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub}; +use core::{cmp, fmt}; + +use internals::impl_to_hex_from_lower_hex; +use io::{BufRead, Write}; +use units::parse_int::{self, ParseIntError, PrefixedHexError, UnprefixedHexError}; + +use crate::block::{BlockHash, Header}; +use crate::consensus::encode::{self, Decodable, Encodable}; +use crate::internal_macros; +use crate::network::Params; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use primitives::CompactTarget; + +/// Implement traits and methods shared by `Target` and `Work`. +macro_rules! do_impl { + ($ty:ident) => { + impl $ty { + #[doc = "Constructs `"] + #[doc = stringify!($ty)] + #[doc = "` from a prefixed hex string."] + pub fn from_hex(s: &str) -> Result { + Ok($ty(U256::from_hex(s)?)) + } + + #[doc = "Constructs `"] + #[doc = stringify!($ty)] + #[doc = "` from an unprefixed hex string."] + pub fn from_unprefixed_hex(s: &str) -> Result { + Ok($ty(U256::from_unprefixed_hex(s)?)) + } + + #[doc = "Constructs `"] + #[doc = stringify!($ty)] + #[doc = "` from a big-endian byte array."] + #[inline] + pub fn from_be_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_be_bytes(bytes)) } + + #[doc = "Constructs `"] + #[doc = stringify!($ty)] + #[doc = "` from a little-endian byte array."] + #[inline] + pub fn from_le_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_le_bytes(bytes)) } + + #[doc = "Converts `"] + #[doc = stringify!($ty)] + #[doc = "` to a big-endian byte array."] + #[inline] + pub fn to_be_bytes(self) -> [u8; 32] { self.0.to_be_bytes() } + + #[doc = "Converts `"] + #[doc = stringify!($ty)] + #[doc = "` to a little-endian byte array."] + #[inline] + pub fn to_le_bytes(self) -> [u8; 32] { self.0.to_le_bytes() } + } + + impl fmt::Display for $ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { + fmt::Display::fmt(&self.0, f) + } + } + + impl fmt::LowerHex for $ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { + fmt::LowerHex::fmt(&self.0, f) + } + } + + impl fmt::UpperHex for $ty { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { + fmt::UpperHex::fmt(&self.0, f) + } + } + }; +} + +/// A 256 bit integer representing work. +/// +/// Work is a measure of how difficult it is to find a hash below a given [`Target`]. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Work(U256); + +impl Work { + /// Converts this [`Work`] to [`Target`]. + pub fn to_target(self) -> Target { Target(self.0.inverse()) } + + /// Returns log2 of this work. + /// + /// The result inherently suffers from a loss of precision and is, therefore, meant to be + /// used mainly for informative and displaying purposes, similarly to Bitcoin Core's + /// `log2_work` output in its logs. + #[cfg(feature = "std")] + pub fn log2(self) -> f64 { self.0.to_f64().log2() } +} +do_impl!(Work); +impl_to_hex_from_lower_hex!(Work, |_| 64); + +impl Add for Work { + type Output = Self; + fn add(self, rhs: Self) -> Self { Self(self.0 + rhs.0) } +} + +impl Sub for Work { + type Output = Self; + fn sub(self, rhs: Self) -> Self { Self(self.0 - rhs.0) } +} + +/// A 256 bit integer representing target. +/// +/// The SHA-256 hash of a block's header must be lower than or equal to the current target for the +/// block to be accepted by the network. The lower the target, the more difficult it is to generate +/// a block. (See also [`Work`].) +/// +/// ref: +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Target(U256); + +impl Target { + /// When parsing nBits, Bitcoin Core converts a negative target threshold into a target of zero. + pub const ZERO: Self = Self(U256::ZERO); + /// The maximum possible target. + /// + /// This value is used to calculate difficulty, which is defined as how difficult the current + /// target makes it to find a block relative to how difficult it would be at the highest + /// possible target. Remember highest target == lowest difficulty. + /// + /// ref: + // In Bitcoind this is ~(u256)0 >> 32 stored as a floating-point type so it gets truncated, hence + // the low 208 bits are all zero. + pub const MAX: Self = Self(U256(0xFFFF_u128 << (208 - 128), 0)); + + /// The maximum **attainable** target value on mainnet. + /// + /// Not all target values are attainable because consensus code uses the compact format to + /// represent targets (see [`CompactTarget`]). + pub const MAX_ATTAINABLE_MAINNET: Self = Self(U256(0xFFFF_u128 << (208 - 128), 0)); + + /// The proof of work limit on testnet. + // Taken from Bitcoin Core but had lossy conversion to/from compact form. + // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L208 + pub const MAX_ATTAINABLE_TESTNET: Self = Self(U256(0xFFFF_u128 << (208 - 128), 0)); + + /// The proof of work limit on regtest. + // Taken from Bitcoin Core but had lossy conversion to/from compact form. + // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L411 + pub const MAX_ATTAINABLE_REGTEST: Self = Self(U256(0x7FFF_FF00u128 << 96, 0)); + + /// The proof of work limit on signet. + // Taken from Bitcoin Core but had lossy conversion to/from compact form. + // https://github.com/bitcoin/bitcoin/blob/8105bce5b384c72cf08b25b7c5343622754e7337/src/kernel/chainparams.cpp#L348 + pub const MAX_ATTAINABLE_SIGNET: Self = Self(U256(0x0377_ae00 << 80, 0)); + + /// Computes the [`Target`] value from a compact representation. + /// + /// ref: + pub fn from_compact(c: CompactTarget) -> Self { + let bits = c.to_consensus(); + // This is a floating-point "compact" encoding originally used by + // OpenSSL, which satoshi put into consensus code, so we're stuck + // with it. The exponent needs to have 3 subtracted from it, hence + // this goofy decoding code. 3 is due to 3 bytes in the mantissa. + let (mant, expt) = { + let unshifted_expt = bits >> 24; + if unshifted_expt <= 3 { + ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt as usize)), 0) + } else { + (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3)) + } + }; + + // The mantissa is signed but may not be negative. + if mant > 0x7F_FFFF { + Self::ZERO + } else { + Self(U256::from(mant) << expt) + } + } + + /// Computes the compact value from a [`Target`] representation. + /// + /// The compact form is by definition lossy, this means that + /// `t == Target::from_compact(t.to_compact_lossy())` does not always hold. + pub fn to_compact_lossy(self) -> CompactTarget { + let mut size = self.0.bits().div_ceil(8); + let mut compact = if size <= 3 { + (self.0.low_u64() << (8 * (3 - size))) as u32 + } else { + let bn = self.0 >> (8 * (size - 3)); + bn.low_u32() + }; + + if (compact & 0x0080_0000) != 0 { + compact >>= 8; + size += 1; + } + + CompactTarget::from_consensus(compact | (size << 24)) + } + + /// Returns true if block hash is less than or equal to this [`Target`]. + /// + /// Proof-of-work validity for a block requires the hash of the block to be less than or equal + /// to the target. + pub fn is_met_by(&self, hash: BlockHash) -> bool { + let hash = U256::from_le_bytes(hash.to_byte_array()); + hash <= self.0 + } + + /// Converts this [`Target`] to [`Work`]. + /// + /// "Work" is defined as the work done to mine a block with this target value (recorded in the + /// block header in compact form as nBits). This is not the same as the difficulty to mine a + /// block with this target (see `Self::difficulty`). + pub fn to_work(self) -> Work { Work(self.0.inverse()) } + + /// Computes the popular "difficulty" measure for mining. + /// + /// Difficulty represents how difficult the current target makes it to find a block, relative to + /// how difficult it would be at the highest possible target (highest target == lowest difficulty). + /// + /// For example, a difficulty of 6,695,826 means that at a given hash rate, it will, on average, + /// take ~6.6 million times as long to find a valid block as it would at a difficulty of 1, or + /// alternatively, it will take, again on average, ~6.6 million times as many hashes to find a + /// valid block + /// + /// # Note + /// + /// Difficulty is calculated using the following algorithm `max / current` where [max] is + /// defined for the Bitcoin network and `current` is the current [target] for this block. As + /// such, a low target implies a high difficulty. Since [`Target`] is represented as a 256 bit + /// integer but `difficulty()` returns only 128 bits this means for targets below approximately + /// `0xffff_ffff_ffff_ffff_ffff_ffff` `difficulty()` will saturate at `u128::MAX`. + /// + /// # Panics + /// + /// Panics if `self` is zero (divide by zero). + /// + /// [max]: Target::max + /// [target]: crate::block::HeaderExt::target + pub fn difficulty(&self, params: impl AsRef) -> u128 { + // Panic here may be easier to debug than during the actual division. + assert_ne!(self.0, U256::ZERO, "divide by zero"); + + let max = params.as_ref().max_attainable_target; + let d = max.0 / self.0; + d.saturating_to_u128() + } + + /// Computes the popular "difficulty" measure for mining and returns a float value of f64. + /// + /// See [`difficulty`] for details. + /// + /// # Panics + /// + /// Panics if `self` is zero (divide by zero). + /// + /// [`difficulty`]: Target::difficulty + pub fn difficulty_float(&self, params: impl AsRef) -> f64 { + // We want to explicitly panic to be uniform with `difficulty()` + // (float division by zero does not panic). + // Note, target 0 is basically impossible to obtain by any "normal" means. + assert_ne!(self.0, U256::ZERO, "divide by zero"); + let max = params.as_ref().max_attainable_target; + max.0.to_f64() / self.0.to_f64() + } + + /// Computes the minimum valid [`Target`] threshold allowed for a block in which a difficulty + /// adjustment occurs. + #[deprecated(since = "0.32.0", note = "use `min_transition_threshold` instead")] + pub fn min_difficulty_transition_threshold(&self) -> Self { self.min_transition_threshold() } + + /// Computes the maximum valid [`Target`] threshold allowed for a block in which a difficulty + /// adjustment occurs. + #[deprecated(since = "0.32.0", note = "use `max_transition_threshold` instead")] + pub fn max_difficulty_transition_threshold(&self) -> Self { + self.max_transition_threshold_unchecked() + } + + /// Computes the minimum valid [`Target`] threshold allowed for a block in which a difficulty + /// adjustment occurs. + /// + /// The difficulty can only decrease or increase by a factor of 4 max on each difficulty + /// adjustment period. + /// + /// # Returns + /// + /// In line with Bitcoin Core this function may return a target value of zero. + pub fn min_transition_threshold(&self) -> Self { Self(self.0 >> 2) } + + /// Computes the maximum valid [`Target`] threshold allowed for a block in which a difficulty + /// adjustment occurs. + /// + /// The difficulty can only decrease or increase by a factor of 4 max on each difficulty + /// adjustment period. + /// + /// We also check that the calculated target is not greater than the maximum allowed target, + /// this value is network specific - hence the `params` parameter. + pub fn max_transition_threshold(&self, params: impl AsRef) -> Self { + let max_attainable = params.as_ref().max_attainable_target; + cmp::min(self.max_transition_threshold_unchecked(), max_attainable) + } + + /// Computes the maximum valid [`Target`] threshold allowed for a block in which a difficulty + /// adjustment occurs. + /// + /// The difficulty can only decrease or increase by a factor of 4 max on each difficulty + /// adjustment period. + /// + /// # Returns + /// + /// This function may return a value greater than the maximum allowed target for this network. + /// + /// The return value should be checked against [`Params::max_attainable_target`] or use one of + /// the `Target::MAX_ATTAINABLE_FOO` constants. + pub fn max_transition_threshold_unchecked(&self) -> Self { Self(self.0 << 2) } +} +do_impl!(Target); +impl_to_hex_from_lower_hex!(Target, |_| 64); + +internal_macros::define_extension_trait! { + /// Extension functionality for the [`CompactTarget`] type. + pub trait CompactTargetExt impl for CompactTarget { + /// Constructs a new `CompactTarget` from a prefixed hex string. + fn from_hex(s: &str) -> Result + where + Self: Sized + { + let target = parse_int::hex_u32_prefixed(s)?; + Ok(Self::from_consensus(target)) + } + + /// Constructs a new `CompactTarget` from an unprefixed hex string. + fn from_unprefixed_hex(s: &str) -> Result + where + Self: Sized + { + let target = parse_int::hex_u32_unprefixed(s)?; + Ok(Self::from_consensus(target)) + } + + /// Computes the [`CompactTarget`] from a difficulty adjustment. + /// + /// ref: + /// + /// Given the previous Target, represented as a [`CompactTarget`], the difficulty is adjusted + /// by taking the timespan between them, and multiplying the current [`CompactTarget`] by a factor + /// of the net timespan and expected timespan. The [`CompactTarget`] may not adjust by more than + /// a factor of 4, or adjust beyond the maximum threshold for the network. + /// + /// # Note + /// + /// Under the consensus rules, the difference in the number of blocks between the headers does + /// not equate to the `difficulty_adjustment_interval` of [`Params`]. This is due to an off-by-one + /// error, and, the expected number of blocks in between headers is `difficulty_adjustment_interval - 1` + /// when calculating the difficulty adjustment. + /// + /// Take the example of the first difficulty adjustment. Block 2016 introduces a new [`CompactTarget`], + /// which takes the net timespan between Block 2015 and Block 0, and recomputes the difficulty. + /// + /// To calculate the timespan, users should first convert their u32 timestamps to i64s before subtracting them + /// + /// # Returns + /// + /// The expected [`CompactTarget`] recalculation. + fn from_next_work_required( + last: CompactTarget, + timespan: i64, + params: impl AsRef, + ) -> Self { + let params = params.as_ref(); + if params.no_pow_retargeting { + return last; + } + // Comments relate to the `pow.cpp` file from Core. + // ref: + let min_timespan = params.pow_target_timespan >> 2; // Lines 56/57 + let max_timespan = params.pow_target_timespan << 2; // Lines 58/59 + let actual_timespan = timespan.clamp(min_timespan.into(), max_timespan.into()); + let prev_target: Target = last.into(); + let maximum_retarget = prev_target.max_transition_threshold(params); // bnPowLimit + let retarget = prev_target.0; // bnNew + let retarget = retarget.mul(u128::try_from(actual_timespan).expect("clamped value won't be negative").into()); + let retarget = retarget.div(params.pow_target_timespan.into()); + let retarget = Target(retarget); + if retarget.ge(&maximum_retarget) { + return maximum_retarget.to_compact_lossy(); + } + retarget.to_compact_lossy() + } + + /// Computes the [`CompactTarget`] from a difficulty adjustment, + /// assuming these are the relevant block headers. + /// + /// Given two headers, representing the start and end of a difficulty adjustment epoch, + /// compute the [`CompactTarget`] based on the net time between them and the current + /// [`CompactTarget`]. + /// + /// # Note + /// + /// See [`CompactTarget::from_next_work_required`] + /// + /// For example, to successfully compute the first difficulty adjustment on the Bitcoin network, + /// one would pass the header for Block 2015 as `current` and the header for Block 0 as + /// `last_epoch_boundary`. + /// + /// # Returns + /// + /// The expected [`CompactTarget`] recalculation. + fn from_header_difficulty_adjustment( + last_epoch_boundary: Header, + current: Header, + params: impl AsRef, + ) -> Self { + let timespan = i64::from(current.time.to_u32()) - i64::from(last_epoch_boundary.time.to_u32()); + let bits = current.bits; + CompactTarget::from_next_work_required(bits, timespan, params) + } + } +} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::CompactTarget {} +} + +impl From for Target { + fn from(c: CompactTarget) -> Self { Self::from_compact(c) } +} + +impl Encodable for CompactTarget { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.to_consensus().consensus_encode(w) + } +} + +impl Decodable for CompactTarget { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + u32::consensus_decode(r).map(Self::from_consensus) + } +} + +/// Big-endian 256 bit integer type. +// (high, low): u.0 contains the high bits, u.1 contains the low bits. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +struct U256(u128, u128); + +impl U256 { + const MAX: Self = + Self(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff, 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff); + + const ZERO: Self = Self(0, 0); + + const ONE: Self = Self(0, 1); + + /// Constructs a new `U256` from a prefixed hex string. + fn from_hex(s: &str) -> Result { + let checked = parse_int::hex_remove_prefix(s)?; + Ok(Self::from_hex_internal(checked)?) + } + + /// Constructs a new `U256` from an unprefixed hex string. + fn from_unprefixed_hex(s: &str) -> Result { + let checked = parse_int::hex_check_unprefixed(s)?; + Ok(Self::from_hex_internal(checked)?) + } + + // Caller to ensure `s` does not contain a prefix. + fn from_hex_internal(s: &str) -> Result { + let (high, low) = if s.len() <= 32 { + let low = parse_int::hex_u128_unchecked(s)?; + (0, low) + } else { + let high_len = s.len() - 32; + let high_s = &s[..high_len]; + let low_s = &s[high_len..]; + + let high = parse_int::hex_u128_unchecked(high_s)?; + let low = parse_int::hex_u128_unchecked(low_s)?; + (high, low) + }; + + Ok(Self(high, low)) + } + + /// Constructs a new `U256` from a big-endian array of `u8`s. + fn from_be_bytes(a: [u8; 32]) -> Self { + let (high, low) = split_in_half(a); + let big = u128::from_be_bytes(high); + let little = u128::from_be_bytes(low); + Self(big, little) + } + + /// Constructs a new `U256` from a little-endian array of `u8`s. + fn from_le_bytes(a: [u8; 32]) -> Self { + let (high, low) = split_in_half(a); + let little = u128::from_le_bytes(high); + let big = u128::from_le_bytes(low); + Self(big, little) + } + + /// Converts `U256` to a big-endian array of `u8`s. + fn to_be_bytes(self) -> [u8; 32] { + let mut out = [0; 32]; + out[..16].copy_from_slice(&self.0.to_be_bytes()); + out[16..].copy_from_slice(&self.1.to_be_bytes()); + out + } + + /// Converts `U256` to a little-endian array of `u8`s. + fn to_le_bytes(self) -> [u8; 32] { + let mut out = [0; 32]; + out[..16].copy_from_slice(&self.1.to_le_bytes()); + out[16..].copy_from_slice(&self.0.to_le_bytes()); + out + } + + /// Calculates 2^256 / (x + 1) where x is a 256 bit unsigned integer. + /// + /// 2**256 / (x + 1) == ~x / (x + 1) + 1 + /// + /// (Equation shamelessly stolen from bitcoind) + fn inverse(&self) -> Self { + // We should never have a target/work of zero so this doesn't matter + // that much but we define the inverse of 0 as max. + if self.is_zero() { + return Self::MAX; + } + // We define the inverse of 1 as max. + if self.is_one() { + return Self::MAX; + } + // We define the inverse of max as 1. + if self.is_max() { + return Self::ONE; + } + + let ret = !*self / self.wrapping_inc(); + ret.wrapping_inc() + } + + fn is_zero(&self) -> bool { self.0 == 0 && self.1 == 0 } + + fn is_one(&self) -> bool { self.0 == 0 && self.1 == 1 } + + fn is_max(&self) -> bool { self.0 == u128::MAX && self.1 == u128::MAX } + + /// Returns the low 32 bits. + fn low_u32(&self) -> u32 { self.low_u128() as u32 } + + /// Returns the low 64 bits. + fn low_u64(&self) -> u64 { self.low_u128() as u64 } + + /// Returns the low 128 bits. + fn low_u128(&self) -> u128 { self.1 } + + /// Returns this `U256` as a `u128` saturating to `u128::MAX` if `self` is too big. + // Mutagen gives false positive because >= and > both return u128::MAX + fn saturating_to_u128(&self) -> u128 { + if *self > Self::from(u128::MAX) { + u128::MAX + } else { + self.low_u128() + } + } + + /// Returns the least number of bits needed to represent the number. + fn bits(&self) -> u32 { + if self.0 > 0 { + 256 - self.0.leading_zeros() + } else { + 128 - self.1.leading_zeros() + } + } + + /// Wrapping multiplication by `u64`. + /// + /// # Returns + /// + /// The multiplication result along with a boolean indicating whether an arithmetic overflow + /// occurred. If an overflow occurred then the wrapped value is returned. + fn mul_u64(self, rhs: u64) -> (Self, bool) { + let mut carry: u128 = 0; + let mut split_le = + [self.1 as u64, (self.1 >> 64) as u64, self.0 as u64, (self.0 >> 64) as u64]; + + for word in &mut split_le { + // This will not overflow, for proof see https://github.com/rust-bitcoin/rust-bitcoin/pull/1496#issuecomment-1365938572 + let n = carry + u128::from(rhs) * u128::from(*word); + + *word = n as u64; // Intentional truncation, save the low bits + carry = n >> 64; // and carry the high bits. + } + + let low = u128::from(split_le[0]) | (u128::from(split_le[1]) << 64); + let high = u128::from(split_le[2]) | (u128::from(split_le[3]) << 64); + (Self(high, low), carry != 0) + } + + /// Calculates quotient and remainder. + /// + /// # Returns + /// + /// (quotient, remainder) + /// + /// # Panics + /// + /// If `rhs` is zero. + fn div_rem(self, rhs: Self) -> (Self, Self) { + let mut sub_copy = self; + let mut shift_copy = rhs; + let mut ret = [0u128; 2]; + + let my_bits = self.bits(); + let your_bits = rhs.bits(); + + // Check for division by 0 + assert!(your_bits != 0, "attempted to divide {} by zero", self); + + // Early return in case we are dividing by a larger number than us + if my_bits < your_bits { + return (Self::ZERO, sub_copy); + } + + // Bitwise long division + let mut shift = my_bits - your_bits; + shift_copy = shift_copy << shift; + loop { + if sub_copy >= shift_copy { + ret[1 - (shift / 128) as usize] |= 1 << (shift % 128); + sub_copy = sub_copy.wrapping_sub(shift_copy); + } + shift_copy = shift_copy >> 1; + if shift == 0 { + break; + } + shift -= 1; + } + + (Self(ret[0], ret[1]), sub_copy) + } + + /// Calculates `self` + `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic + /// overflow would occur. If an overflow would have occurred then the wrapped value is returned. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_add(self, rhs: Self) -> (Self, bool) { + let mut ret = Self::ZERO; + let mut ret_overflow = false; + + let (high, overflow) = self.0.overflowing_add(rhs.0); + ret.0 = high; + ret_overflow |= overflow; + + let (low, overflow) = self.1.overflowing_add(rhs.1); + ret.1 = low; + if overflow { + let (high, overflow) = ret.0.overflowing_add(1); + ret.0 = high; + ret_overflow |= overflow; + } + + (ret, ret_overflow) + } + + /// Calculates `self` - `rhs` + /// + /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic + /// overflow would occur. If an overflow would have occurred then the wrapped value is returned. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_sub(self, rhs: Self) -> (Self, bool) { + let ret = self.wrapping_add(!rhs).wrapping_add(Self::ONE); + let overflow = rhs > self; + (ret, overflow) + } + + /// Calculates the multiplication of `self` and `rhs`. + /// + /// Returns a tuple of the multiplication along with a boolean + /// indicating whether an arithmetic overflow would occur. If an + /// overflow would have occurred then the wrapped value is returned. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn overflowing_mul(self, rhs: Self) -> (Self, bool) { + let mut ret = Self::ZERO; + let mut ret_overflow = false; + + for i in 0..3 { + let to_mul = (rhs >> (64 * i)).low_u64(); + let (mul_res, _) = self.mul_u64(to_mul); + ret = ret.wrapping_add(mul_res << (64 * i)); + } + + let to_mul = (rhs >> 192).low_u64(); + let (mul_res, overflow) = self.mul_u64(to_mul); + ret_overflow |= overflow; + let (sum, overflow) = ret.overflowing_add(mul_res); + ret = sum; + ret_overflow |= overflow; + + (ret, ret_overflow) + } + + /// Wrapping (modular) addition. Computes `self + rhs`, wrapping around at the boundary of the + /// type. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_add(self, rhs: Self) -> Self { + let (ret, _overflow) = self.overflowing_add(rhs); + ret + } + + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the boundary of + /// the type. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_sub(self, rhs: Self) -> Self { + let (ret, _overflow) = self.overflowing_sub(rhs); + ret + } + + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at the boundary of + /// the type. + #[must_use = "this returns the result of the operation, without modifying the original"] + #[cfg(test)] + fn wrapping_mul(self, rhs: Self) -> Self { + let (ret, _overflow) = self.overflowing_mul(rhs); + ret + } + + /// Returns `self` incremented by 1 wrapping around at the boundary of the type. + #[must_use = "this returns the result of the increment, without modifying the original"] + fn wrapping_inc(&self) -> Self { + let mut ret = Self::ZERO; + + ret.1 = self.1.wrapping_add(1); + if ret.1 == 0 { + ret.0 = self.0.wrapping_add(1); + } else { + ret.0 = self.0; + } + ret + } + + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, where `mask` removes any + /// high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is + /// restricted to the range of the type, rather than the bits shifted out of the LHS being + /// returned to the other end. We do not currently support `rotate_left`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_shl(self, rhs: u32) -> Self { + let shift = rhs & 0x000000ff; + + let mut ret = Self::ZERO; + let word_shift = shift >= 128; + let bit_shift = shift % 128; + + if word_shift { + ret.0 = self.1 << bit_shift + } else { + ret.0 = self.0 << bit_shift; + if bit_shift > 0 { + ret.0 += self.1.wrapping_shr(128 - bit_shift); + } + ret.1 = self.1 << bit_shift; + } + ret + } + + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, where `mask` removes any + /// high-order bits of `rhs` that would cause the shift to exceed the bitwidth of the type. + /// + /// Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is + /// restricted to the range of the type, rather than the bits shifted out of the LHS being + /// returned to the other end. We do not currently support `rotate_right`. + #[must_use = "this returns the result of the operation, without modifying the original"] + fn wrapping_shr(self, rhs: u32) -> Self { + let shift = rhs & 0x000000ff; + + let mut ret = Self::ZERO; + let word_shift = shift >= 128; + let bit_shift = shift % 128; + + if word_shift { + ret.1 = self.0 >> bit_shift + } else { + ret.0 = self.0 >> bit_shift; + ret.1 = self.1 >> bit_shift; + if bit_shift > 0 { + ret.1 += self.0.wrapping_shl(128 - bit_shift); + } + } + ret + } + + /// Format `self` to `f` as a decimal when value is known to be non-zero. + fn fmt_decimal(&self, f: &mut fmt::Formatter) -> fmt::Result { + const DIGITS: usize = 78; // U256::MAX has 78 base 10 digits. + const TEN: U256 = U256(0, 10); + + let mut buf = [0_u8; DIGITS]; + let mut i = DIGITS - 1; // We loop backwards. + let mut cur = *self; + + loop { + let digit = (cur % TEN).low_u128() as u8; // Cast after rem 10 is lossless. + buf[i] = digit + b'0'; + cur = cur / TEN; + if cur.is_zero() { + break; + } + i -= 1; + } + let s = core::str::from_utf8(&buf[i..]).expect("digits 0-9 are valid UTF8"); + f.pad_integral(true, "", s) + } + + /// Converts self to f64. + #[inline] + fn to_f64(self) -> f64 { + // Reference: https://blog.m-ou.se/floats/ + // Step 1: Get leading zeroes + let leading_zeroes = 256 - self.bits(); + // Step 2: Get msb to be farthest left bit + let left_aligned = self.wrapping_shl(leading_zeroes); + // Step 3: Shift msb to fit in lower 53 bits (128-53=75) to get the mantissa + // * Shifting the border of the 2 u128s to line up with mantissa and dropped bits + let middle_aligned = left_aligned >> 75; + // * This is the 53 most significant bits as u128 + let mantissa = middle_aligned.0; + // Step 4: Dropped bits (except for last 75 bits) are all in the second u128. + // Bitwise OR the rest of the bits into it, preserving the highest bit, + // so we take the lower 75 bits of middle_aligned.1 and mix it in. (See blog for explanation) + let dropped_bits = middle_aligned.1 | (left_aligned.1 & 0x7FF_FFFF_FFFF_FFFF_FFFF); + // Step 5: The msb of the dropped bits has been preserved, and all other bits + // if any were set, would be set somewhere in the other 127 bits. + // If msb of dropped bits is 0, it is mantissa + 0 + // If msb of dropped bits is 1, it is mantissa + 0 only if mantissa lowest bit is 0 + // and other bits of the dropped bits are all 0. + // (This is why we only care if the other non-msb dropped bits are all 0 or not, + // so we can just OR them to make sure any bits show up somewhere.) + let mantissa = + (mantissa + ((dropped_bits - ((dropped_bits >> 127) & !mantissa)) >> 127)) as u64; + // Step 6: Calculate the exponent + // If self is 0, exponent should be 0 (special meaning) and mantissa will end up 0 too + // Otherwise, (255 - n) + 1022 so it simplifies to 1277 - n + // 1023 and 1022 are the cutoffs for the exponent having the msb next to the decimal point + let exponent = if self == Self::ZERO { 0 } else { 1277 - leading_zeroes as u64 }; + // Step 7: sign bit is always 0, exponent is shifted into place + // Use addition instead of bitwise OR to saturate the exponent if mantissa overflows + f64::from_bits((exponent << 52) + mantissa) + } +} + +impl> From for U256 { + fn from(x: T) -> Self { Self(0, x.into()) } +} + +impl Add for U256 { + type Output = Self; + fn add(self, rhs: Self) -> Self { + let (res, overflow) = self.overflowing_add(rhs); + debug_assert!(!overflow, "addition of U256 values overflowed"); + res + } +} + +impl Sub for U256 { + type Output = Self; + fn sub(self, rhs: Self) -> Self { + let (res, overflow) = self.overflowing_sub(rhs); + debug_assert!(!overflow, "subtraction of U256 values overflowed"); + res + } +} + +impl Mul for U256 { + type Output = Self; + fn mul(self, rhs: Self) -> Self { + let (res, overflow) = self.overflowing_mul(rhs); + debug_assert!(!overflow, "multiplication of U256 values overflowed"); + res + } +} + +impl Div for U256 { + type Output = Self; + fn div(self, rhs: Self) -> Self { self.div_rem(rhs).0 } +} + +impl Rem for U256 { + type Output = Self; + fn rem(self, rhs: Self) -> Self { self.div_rem(rhs).1 } +} + +impl Not for U256 { + type Output = Self; + + fn not(self) -> Self { Self(!self.0, !self.1) } +} + +impl Shl for U256 { + type Output = Self; + fn shl(self, shift: u32) -> Self { self.wrapping_shl(shift) } +} + +impl Shr for U256 { + type Output = Self; + fn shr(self, shift: u32) -> Self { self.wrapping_shr(shift) } +} + +impl fmt::Display for U256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.is_zero() { + f.pad_integral(true, "", "0") + } else { + self.fmt_decimal(f) + } + } +} + +impl fmt::Debug for U256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:#x}", self) } +} + +macro_rules! impl_hex { + ($hex:path, $case:expr) => { + impl $hex for U256 { + fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { + hex::fmt_hex_exact!(f, 32, &self.to_be_bytes(), $case) + } + } + }; +} +impl_hex!(fmt::LowerHex, hex::Case::Lower); +impl_hex!(fmt::UpperHex, hex::Case::Upper); + +#[cfg(feature = "serde")] +impl crate::serde::Serialize for U256 { + fn serialize(&self, serializer: S) -> Result + where + S: crate::serde::Serializer, + { + struct DisplayHex(U256); + + impl fmt::Display for DisplayHex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}", self.0) } + } + + if serializer.is_human_readable() { + serializer.collect_str(&DisplayHex(*self)) + } else { + let bytes = self.to_be_bytes(); + serializer.serialize_bytes(&bytes) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> crate::serde::Deserialize<'de> for U256 { + fn deserialize>(d: D) -> Result { + use hex::FromHex; + + use crate::serde::de; + + if d.is_human_readable() { + struct HexVisitor; + + impl de::Visitor<'_> for HexVisitor { + type Value = U256; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("a 32 byte ASCII hex string") + } + + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + if s.len() != 64 { + return Err(de::Error::invalid_length(s.len(), &self)); + } + + let b = <[u8; 32]>::from_hex(s) + .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?; + + Ok(U256::from_be_bytes(b)) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + if let Ok(hex) = core::str::from_utf8(v) { + let b = <[u8; 32]>::from_hex(hex).map_err(|_| { + de::Error::invalid_value(de::Unexpected::Str(hex), &self) + })?; + + Ok(U256::from_be_bytes(b)) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + } + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; + + impl serde::de::Visitor<'_> for BytesVisitor { + type Value = U256; + + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.write_str("a sequence of bytes") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + let b = v.try_into().map_err(|_| de::Error::invalid_length(v.len(), &self))?; + Ok(U256::from_be_bytes(b)) + } + } + + d.deserialize_bytes(BytesVisitor) + } + } +} + +/// Splits a 32 byte array into two 16 byte arrays. +fn split_in_half(a: [u8; 32]) -> ([u8; 16], [u8; 16]) { + let mut high = [0_u8; 16]; + let mut low = [0_u8; 16]; + + high.copy_from_slice(&a[..16]); + low.copy_from_slice(&a[16..]); + + (high, low) +} + +#[cfg(kani)] +impl kani::Arbitrary for U256 { + fn any() -> Self { + let high: u128 = kani::any(); + let low: u128 = kani::any(); + Self(high, low) + } +} + +/// In test code, U256s are a pain to work with, so we just convert Rust primitives in many places +#[cfg(test)] +pub mod test_utils { + use crate::pow::{Target, Work, U256}; + + /// Converts a `u64` to a [`Work`] + pub fn u64_to_work(u: u64) -> Work { Work(U256::from(u)) } + + /// Converts a `u128` to a [`Work`] + pub fn u128_to_work(u: u128) -> Work { Work(U256::from(u)) } + + /// Converts a `u32` to a [`Target`] + pub fn u32_to_target(u: u32) -> Target { Target(U256::from(u)) } + + /// Converts a `u64` to a [`Target`] + pub fn u64_to_target(u: u64) -> Target { Target(U256::from(u)) } +} + +#[cfg(test)] +mod tests { + use super::*; + #[cfg(feature = "std")] + use crate::pow::test_utils::u128_to_work; + use crate::pow::test_utils::{u32_to_target, u64_to_target}; + use crate::BlockTime; + + impl U256 { + fn bit_at(&self, index: usize) -> bool { + if index > 255 { + panic!("index out of bounds"); + } + + let word = if index < 128 { self.1 } else { self.0 }; + (word & (1 << (index % 128))) != 0 + } + + /// Constructs a new U256 from a big-endian array of u64's + fn from_array(a: [u64; 4]) -> Self { + let mut ret = Self::ZERO; + ret.0 = ((a[0] as u128) << 64) ^ (a[1] as u128); + ret.1 = ((a[2] as u128) << 64) ^ (a[3] as u128); + ret + } + } + + #[test] + fn u256_num_bits() { + assert_eq!(U256::from(255_u64).bits(), 8); + assert_eq!(U256::from(256_u64).bits(), 9); + assert_eq!(U256::from(300_u64).bits(), 9); + assert_eq!(U256::from(60000_u64).bits(), 16); + assert_eq!(U256::from(70000_u64).bits(), 17); + + let u = U256::from(u128::MAX) << 1; + assert_eq!(u.bits(), 129); + + // Try to read the following lines out loud quickly + let mut shl = U256::from(70000_u64); + shl = shl << 100; + assert_eq!(shl.bits(), 117); + shl = shl << 100; + assert_eq!(shl.bits(), 217); + shl = shl << 100; + assert_eq!(shl.bits(), 0); + } + + #[test] + fn u256_bit_at() { + assert!(!U256::from(10_u64).bit_at(0)); + assert!(U256::from(10_u64).bit_at(1)); + assert!(!U256::from(10_u64).bit_at(2)); + assert!(U256::from(10_u64).bit_at(3)); + assert!(!U256::from(10_u64).bit_at(4)); + + let u = U256(0xa000_0000_0000_0000_0000_0000_0000_0000, 0); + assert!(u.bit_at(255)); + assert!(!u.bit_at(254)); + assert!(u.bit_at(253)); + assert!(!u.bit_at(252)); + } + + #[test] + fn u256_lower_hex() { + assert_eq!( + format!("{:x}", U256::from(0xDEADBEEF_u64)), + "00000000000000000000000000000000000000000000000000000000deadbeef", + ); + assert_eq!( + format!("{:#x}", U256::from(0xDEADBEEF_u64)), + "0x00000000000000000000000000000000000000000000000000000000deadbeef", + ); + assert_eq!( + format!("{:x}", U256::MAX), + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ); + assert_eq!( + format!("{:#x}", U256::MAX), + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ); + } + + #[test] + fn u256_upper_hex() { + assert_eq!( + format!("{:X}", U256::from(0xDEADBEEF_u64)), + "00000000000000000000000000000000000000000000000000000000DEADBEEF", + ); + assert_eq!( + format!("{:#X}", U256::from(0xDEADBEEF_u64)), + "0x00000000000000000000000000000000000000000000000000000000DEADBEEF", + ); + assert_eq!( + format!("{:X}", U256::MAX), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + ); + assert_eq!( + format!("{:#X}", U256::MAX), + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + ); + } + + #[test] + fn u256_display() { + assert_eq!(format!("{}", U256::from(100_u32)), "100",); + assert_eq!(format!("{}", U256::ZERO), "0",); + assert_eq!(format!("{}", U256::from(u64::MAX)), format!("{}", u64::MAX),); + assert_eq!( + format!("{}", U256::MAX), + "115792089237316195423570985008687907853269984665640564039457584007913129639935", + ); + } + + macro_rules! check_format { + ($($test_name:ident, $val:literal, $format_string:literal, $expected:literal);* $(;)?) => { + $( + #[test] + fn $test_name() { + assert_eq!(format!($format_string, U256::from($val)), $expected); + } + )* + } + } + check_format! { + check_fmt_0, 0_u32, "{}", "0"; + check_fmt_1, 0_u32, "{:2}", " 0"; + check_fmt_2, 0_u32, "{:02}", "00"; + + check_fmt_3, 1_u32, "{}", "1"; + check_fmt_4, 1_u32, "{:2}", " 1"; + check_fmt_5, 1_u32, "{:02}", "01"; + + check_fmt_10, 10_u32, "{}", "10"; + check_fmt_11, 10_u32, "{:2}", "10"; + check_fmt_12, 10_u32, "{:02}", "10"; + check_fmt_13, 10_u32, "{:3}", " 10"; + check_fmt_14, 10_u32, "{:03}", "010"; + + check_fmt_20, 1_u32, "{:<2}", "1 "; + check_fmt_21, 1_u32, "{:<02}", "01"; + check_fmt_22, 1_u32, "{:>2}", " 1"; // This is default but check it anyways. + check_fmt_23, 1_u32, "{:>02}", "01"; + check_fmt_24, 1_u32, "{:^3}", " 1 "; + check_fmt_25, 1_u32, "{:^03}", "001"; + // Sanity check, for integral types precision is ignored. + check_fmt_30, 0_u32, "{:.1}", "0"; + check_fmt_31, 0_u32, "{:4.1}", " 0"; + check_fmt_32, 0_u32, "{:04.1}", "0000"; + } + + #[test] + fn u256_comp() { + let small = U256::from_array([0, 0, 0, 10]); + let big = U256::from_array([0, 0, 0x0209_E737_8231_E632, 0x8C8C_3EE7_0C64_4118]); + let bigger = U256::from_array([0, 0, 0x0209_E737_8231_E632, 0x9C8C_3EE7_0C64_4118]); + let biggest = U256::from_array([1, 0, 0x0209_E737_8231_E632, 0x5C8C_3EE7_0C64_4118]); + + assert!(small < big); + assert!(big < bigger); + assert!(bigger < biggest); + assert!(bigger <= biggest); + assert!(biggest <= biggest); + assert!(bigger >= big); + assert!(bigger >= small); + assert!(small <= small); + } + + const WANT: U256 = + U256(0x1bad_cafe_dead_beef_deaf_babe_2bed_feed, 0xbaad_f00d_defa_ceda_11fe_d2ba_d1c0_ffe0); + + #[rustfmt::skip] + const BE_BYTES: [u8; 32] = [ + 0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed, + 0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0, + ]; + + #[rustfmt::skip] + const LE_BYTES: [u8; 32] = [ + 0xe0, 0xff, 0xc0, 0xd1, 0xba, 0xd2, 0xfe, 0x11, 0xda, 0xce, 0xfa, 0xde, 0x0d, 0xf0, 0xad, 0xba, + 0xed, 0xfe, 0xed, 0x2b, 0xbe, 0xba, 0xaf, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xfe, 0xca, 0xad, 0x1b, + ]; + + // Sanity check that we have the bytes in the correct big-endian order. + #[test] + fn sanity_be_bytes() { + let mut out = [0_u8; 32]; + out[..16].copy_from_slice(&WANT.0.to_be_bytes()); + out[16..].copy_from_slice(&WANT.1.to_be_bytes()); + assert_eq!(out, BE_BYTES); + } + + // Sanity check that we have the bytes in the correct little-endian order. + #[test] + fn sanity_le_bytes() { + let mut out = [0_u8; 32]; + out[..16].copy_from_slice(&WANT.1.to_le_bytes()); + out[16..].copy_from_slice(&WANT.0.to_le_bytes()); + assert_eq!(out, LE_BYTES); + } + + #[test] + fn u256_to_be_bytes() { + assert_eq!(WANT.to_be_bytes(), BE_BYTES); + } + + #[test] + fn u256_from_be_bytes() { + assert_eq!(U256::from_be_bytes(BE_BYTES), WANT); + } + + #[test] + fn u256_to_le_bytes() { + assert_eq!(WANT.to_le_bytes(), LE_BYTES); + } + + #[test] + fn u256_from_le_bytes() { + assert_eq!(U256::from_le_bytes(LE_BYTES), WANT); + } + + #[test] + fn u256_from_u8() { + let u = U256::from(0xbe_u8); + assert_eq!(u, U256(0, 0xbe)); + } + + #[test] + fn u256_from_u16() { + let u = U256::from(0xbeef_u16); + assert_eq!(u, U256(0, 0xbeef)); + } + + #[test] + fn u256_from_u32() { + let u = U256::from(0xdeadbeef_u32); + assert_eq!(u, U256(0, 0xdeadbeef)); + } + + #[test] + fn u256_from_u64() { + let u = U256::from(0xdead_beef_cafe_babe_u64); + assert_eq!(u, U256(0, 0xdead_beef_cafe_babe)); + } + + #[test] + fn u256_from_u128() { + let u = U256::from(0xdead_beef_cafe_babe_0123_4567_89ab_cdefu128); + assert_eq!(u, U256(0, 0xdead_beef_cafe_babe_0123_4567_89ab_cdef)); + } + + macro_rules! test_from_unsigned_integer_type { + ($($test_name:ident, $ty:ident);* $(;)?) => { + $( + #[test] + fn $test_name() { + // Internal representation is big-endian. + let want = U256(0, 0xAB); + + let x = 0xAB as $ty; + let got = U256::from(x); + + assert_eq!(got, want); + } + )* + } + } + test_from_unsigned_integer_type! { + from_unsigned_integer_type_u8, u8; + from_unsigned_integer_type_u16, u16; + from_unsigned_integer_type_u32, u32; + from_unsigned_integer_type_u64, u64; + from_unsigned_integer_type_u128, u128; + } + + #[test] + fn u256_from_be_array_u64() { + let array = [ + 0x1bad_cafe_dead_beef, + 0xdeaf_babe_2bed_feed, + 0xbaad_f00d_defa_ceda, + 0x11fe_d2ba_d1c0_ffe0, + ]; + + let uint = U256::from_array(array); + assert_eq!(uint, WANT); + } + + #[test] + fn u256_shift_left() { + let u = U256::from(1_u32); + assert_eq!(u << 0, u); + assert_eq!(u << 1, U256::from(2_u64)); + assert_eq!(u << 63, U256::from(0x8000_0000_0000_0000_u64)); + assert_eq!(u << 64, U256::from_array([0, 0, 0x0000_0000_0000_0001, 0])); + assert_eq!(u << 127, U256(0, 0x8000_0000_0000_0000_0000_0000_0000_0000)); + assert_eq!(u << 128, U256(1, 0)); + + let x = U256(0, 0x8000_0000_0000_0000_0000_0000_0000_0000); + assert_eq!(x << 1, U256(1, 0)); + } + + #[test] + fn u256_shift_right() { + let u = U256(1, 0); + assert_eq!(u >> 0, u); + assert_eq!(u >> 1, U256(0, 0x8000_0000_0000_0000_0000_0000_0000_0000)); + assert_eq!(u >> 127, U256(0, 2)); + assert_eq!(u >> 128, U256(0, 1)); + } + + #[test] + fn u256_arithmetic() { + let init = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + let copy = init; + + let add = init.wrapping_add(copy); + assert_eq!(add, U256::from_array([0, 0, 1, 0xBD5B_7DDF_BD5B_7DDE])); + // Bitshifts + let shl = add << 88; + assert_eq!(shl, U256::from_array([0, 0x01BD_5B7D, 0xDFBD_5B7D_DE00_0000, 0])); + let shr = shl >> 40; + assert_eq!(shr, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5B, 0x7DDE_0000_0000_0000])); + // Increment + let mut incr = shr; + incr = incr.wrapping_inc(); + assert_eq!(incr, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5B, 0x7DDE_0000_0000_0001])); + // Subtraction + let sub = incr.wrapping_sub(init); + assert_eq!(sub, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5A, 0x9F30_4110_2152_4112])); + // Multiplication + let (mult, _) = sub.mul_u64(300); + assert_eq!(mult, U256::from_array([0, 0, 0x0209_E737_8231_E632, 0x8C8C_3EE7_0C64_4118])); + // Division + assert_eq!(U256::from(105_u32) / U256::from(5_u32), U256::from(21_u32)); + let div = mult / U256::from(300_u32); + assert_eq!(div, U256::from_array([0, 0, 0x0001_BD5B_7DDF_BD5A, 0x9F30_4110_2152_4112])); + + assert_eq!(U256::from(105_u32) % U256::from(5_u32), U256::ZERO); + assert_eq!(U256::from(35498456_u32) % U256::from(3435_u32), U256::from(1166_u32)); + let rem_src = mult.wrapping_mul(U256::from(39842_u32)).wrapping_add(U256::from(9054_u32)); + assert_eq!(rem_src % U256::from(39842_u32), U256::from(9054_u32)); + } + + #[test] + fn u256_bit_inversion() { + let v = U256(1, 0); + let want = U256( + 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_fffe, + 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff, + ); + assert_eq!(!v, want); + + let v = U256(0x0c0c_0c0c_0c0c_0c0c_0c0c_0c0c_0c0c_0c0c, 0xeeee_eeee_eeee_eeee); + let want = U256( + 0xf3f3_f3f3_f3f3_f3f3_f3f3_f3f3_f3f3_f3f3, + 0xffff_ffff_ffff_ffff_1111_1111_1111_1111, + ); + assert_eq!(!v, want); + } + + #[test] + fn u256_mul_u64_by_one() { + let v = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + assert_eq!(v, v.mul_u64(1_u64).0); + } + + #[test] + fn u256_mul_u64_by_zero() { + let v = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + assert_eq!(U256::ZERO, v.mul_u64(0_u64).0); + } + + #[test] + fn u256_mul_u64() { + let u64_val = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + + let u96_res = u64_val.mul_u64(0xFFFF_FFFF).0; + let u128_res = u96_res.mul_u64(0xFFFF_FFFF).0; + let u160_res = u128_res.mul_u64(0xFFFF_FFFF).0; + let u192_res = u160_res.mul_u64(0xFFFF_FFFF).0; + let u224_res = u192_res.mul_u64(0xFFFF_FFFF).0; + let u256_res = u224_res.mul_u64(0xFFFF_FFFF).0; + + assert_eq!(u96_res, U256::from_array([0, 0, 0xDEAD_BEEE, 0xFFFF_FFFF_2152_4111])); + assert_eq!( + u128_res, + U256::from_array([0, 0, 0xDEAD_BEEE_2152_4110, 0x2152_4111_DEAD_BEEF]) + ); + assert_eq!( + u160_res, + U256::from_array([0, 0xDEAD_BEED, 0x42A4_8222_0000_0001, 0xBD5B_7DDD_2152_4111]) + ); + assert_eq!( + u192_res, + U256::from_array([ + 0, + 0xDEAD_BEEC_63F6_C334, + 0xBD5B_7DDF_BD5B_7DDB, + 0x63F6_C333_DEAD_BEEF + ]) + ); + assert_eq!( + u224_res, + U256::from_array([ + 0xDEAD_BEEB, + 0x8549_0448_5964_BAAA, + 0xFFFF_FFFB_A69B_4558, + 0x7AB6_FBBB_2152_4111 + ]) + ); + assert_eq!( + u256_res, + U256( + 0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550, + 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF, + ) + ); + } + + #[test] + fn u256_addition() { + let x = U256::from(u128::MAX); + let (add, overflow) = x.overflowing_add(U256::ONE); + assert!(!overflow); + assert_eq!(add, U256(1, 0)); + + let (add, _) = add.overflowing_add(U256::ONE); + assert_eq!(add, U256(1, 1)); + } + + #[test] + fn u256_subtraction() { + let (sub, overflow) = U256::ONE.overflowing_sub(U256::ONE); + assert!(!overflow); + assert_eq!(sub, U256::ZERO); + + let x = U256(1, 0); + let (sub, overflow) = x.overflowing_sub(U256::ONE); + assert!(!overflow); + assert_eq!(sub, U256::from(u128::MAX)); + } + + #[test] + fn u256_multiplication() { + let u64_val = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + + let u128_res = u64_val.wrapping_mul(u64_val); + + assert_eq!(u128_res, U256(0, 0xC1B1_CD13_A4D1_3D46_048D_1354_216D_A321)); + + let u256_res = u128_res.wrapping_mul(u128_res); + + assert_eq!( + u256_res, + U256( + 0x928D_92B4_D7F5_DF33_4AFC_FF6F_0375_C608, + 0xF5CF_7F36_18C2_C886_F4E1_66AA_D40D_0A41, + ) + ); + } + + #[test] + fn u256_multiplication_bits_in_each_word() { + // Put a digit in the least significant bit of each 64 bit word. + let u = (1_u128 << 64) | 1_u128; + let x = U256(u, u); + + // Put a digit in the second least significant bit of each 64 bit word. + let u = (2_u128 << 64) | 2_u128; + let y = U256(u, u); + + let (got, overflow) = x.overflowing_mul(y); + + let want = U256( + 0x0000_0000_0000_0008_0000_0000_0000_0008, + 0x0000_0000_0000_0006_0000_0000_0000_0004, + ); + assert!(!overflow); + assert_eq!(got, want) + } + + #[test] + fn u256_increment() { + let mut val = U256( + 0xEFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, + 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFE, + ); + val = val.wrapping_inc(); + assert_eq!( + val, + U256( + 0xEFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, + 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF, + ) + ); + val = val.wrapping_inc(); + assert_eq!( + val, + U256( + 0xF000_0000_0000_0000_0000_0000_0000_0000, + 0x0000_0000_0000_0000_0000_0000_0000_0000, + ) + ); + + assert_eq!(U256::MAX.wrapping_inc(), U256::ZERO); + } + + #[test] + fn u256_extreme_bitshift() { + // Shifting a u64 by 64 bits gives an undefined value, so make sure that + // we're doing the Right Thing here + let init = U256::from(0xDEAD_BEEF_DEAD_BEEF_u64); + + assert_eq!(init << 64, U256(0, 0xDEAD_BEEF_DEAD_BEEF_0000_0000_0000_0000)); + let add = (init << 64).wrapping_add(init); + assert_eq!(add, U256(0, 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF)); + assert_eq!(add >> 0, U256(0, 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF)); + assert_eq!(add << 0, U256(0, 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF)); + assert_eq!(add >> 64, U256(0, 0x0000_0000_0000_0000_DEAD_BEEF_DEAD_BEEF)); + assert_eq!( + add << 64, + U256(0xDEAD_BEEF_DEAD_BEEF, 0xDEAD_BEEF_DEAD_BEEF_0000_0000_0000_0000) + ); + } + + #[test] + fn u256_to_from_hex_roundtrips() { + let val = U256( + 0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550, + 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF, + ); + let hex = format!("0x{:x}", val); + let got = U256::from_hex(&hex).expect("failed to parse hex"); + assert_eq!(got, val); + } + + #[test] + fn u256_to_from_unprefixed_hex_roundtrips() { + let val = U256( + 0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550, + 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF, + ); + let hex = format!("{:x}", val); + let got = U256::from_unprefixed_hex(&hex).expect("failed to parse hex"); + assert_eq!(got, val); + } + + #[test] + fn u256_from_hex_32_characters_long() { + let hex = "a69b455cd41bb662a69b4555deadbeef"; + let want = U256(0x00, 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF); + let got = U256::from_unprefixed_hex(hex).expect("failed to parse hex"); + assert_eq!(got, want); + } + + #[test] + #[cfg(feature = "serde")] + fn u256_serde() { + let check = |uint, hex| { + let json = format!("\"{}\"", hex); + assert_eq!(::serde_json::to_string(&uint).unwrap(), json); + assert_eq!(::serde_json::from_str::(&json).unwrap(), uint); + + let bin_encoded = bincode::serialize(&uint).unwrap(); + let bin_decoded: U256 = bincode::deserialize(&bin_encoded).unwrap(); + assert_eq!(bin_decoded, uint); + }; + + check(U256::ZERO, "0000000000000000000000000000000000000000000000000000000000000000"); + check( + U256::from(0xDEADBEEF_u32), + "00000000000000000000000000000000000000000000000000000000deadbeef", + ); + check( + U256::from_array([0xdd44, 0xcc33, 0xbb22, 0xaa11]), + "000000000000dd44000000000000cc33000000000000bb22000000000000aa11", + ); + check(U256::MAX, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + check( + U256( + 0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550, + 0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF, + ), + "deadbeeaa69b455cd41bb662a69b4550a69b455cd41bb662a69b4555deadbeef", + ); + + assert!(::serde_json::from_str::( + "\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg\"" + ) + .is_err()); // invalid char + assert!(::serde_json::from_str::( + "\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ) + .is_err()); // invalid length + assert!(::serde_json::from_str::( + "\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ) + .is_err()); // invalid length + } + + #[test] + fn u256_is_max_correct_negative() { + let tc = [U256::ZERO, U256::ONE, U256::from(u128::MAX)]; + for t in tc { + assert!(!t.is_max()) + } + } + + #[test] + fn u256_is_max_correct_positive() { + assert!(U256::MAX.is_max()); + + let u = u128::MAX; + assert!(((U256::from(u) << 128) + U256::from(u)).is_max()); + } + + #[test] + fn compact_target_from_hex_lower() { + let target = CompactTarget::from_hex("0x010034ab").unwrap(); + assert_eq!(target, CompactTarget::from_consensus(0x010034ab)); + } + + #[test] + fn compact_target_from_hex_upper() { + let target = CompactTarget::from_hex("0X010034AB").unwrap(); + assert_eq!(target, CompactTarget::from_consensus(0x010034ab)); + } + + #[test] + fn compact_target_from_unprefixed_hex_lower() { + let target = CompactTarget::from_unprefixed_hex("010034ab").unwrap(); + assert_eq!(target, CompactTarget::from_consensus(0x010034ab)); + } + + #[test] + fn compact_target_from_unprefixed_hex_upper() { + let target = CompactTarget::from_unprefixed_hex("010034AB").unwrap(); + assert_eq!(target, CompactTarget::from_consensus(0x010034ab)); + } + + #[test] + fn compact_target_from_hex_invalid_hex_should_err() { + let hex = "0xzbf9"; + let result = CompactTarget::from_hex(hex); + assert!(result.is_err()); + } + + #[test] + fn compact_target_lower_hex_and_upper_hex() { + assert_eq!(format!("{:08x}", CompactTarget::from_consensus(0x01D0F456)), "01d0f456"); + assert_eq!(format!("{:08X}", CompactTarget::from_consensus(0x01d0f456)), "01D0F456"); + } + + #[test] + fn compact_target_from_upwards_difficulty_adjustment() { + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(503543726); // Genesis compact target on Signet + let start_time: i64 = 1598918400; // Genesis block unix time + let end_time: i64 = 1599332177; // Block 2015 unix time + let timespan = end_time - start_time; // Faster than expected + let adjustment = CompactTarget::from_next_work_required(starting_bits, timespan, ¶ms); + let adjustment_bits = CompactTarget::from_consensus(503394215); // Block 2016 compact target + assert_eq!(adjustment, adjustment_bits); + } + + #[test] + fn compact_target_from_downwards_difficulty_adjustment() { + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(503394215); // Block 2016 compact target + let start_time: i64 = 1599332844; // Block 2016 unix time + let end_time: i64 = 1600591200; // Block 4031 unix time + let timespan = end_time - start_time; // Slower than expected + let adjustment = CompactTarget::from_next_work_required(starting_bits, timespan, ¶ms); + let adjustment_bits = CompactTarget::from_consensus(503397348); // Block 4032 compact target + assert_eq!(adjustment, adjustment_bits); + } + + #[test] + fn compact_target_from_upwards_difficulty_adjustment_using_headers() { + use crate::block::Version; + use crate::constants::genesis_block; + use crate::TxMerkleNode; + let params = Params::new(crate::Network::Signet); + let epoch_start = *genesis_block(¶ms).header(); + + // Block 2015, the only information used are `bits` and `time` + let current = Header { + version: Version::ONE, + prev_blockhash: BlockHash::from_byte_array([0; 32]), + merkle_root: TxMerkleNode::from_byte_array([0; 32]), + time: BlockTime::from_u32(1599332177), + bits: epoch_start.bits, + nonce: epoch_start.nonce, + }; + let adjustment = + CompactTarget::from_header_difficulty_adjustment(epoch_start, current, params); + let adjustment_bits = CompactTarget::from_consensus(503394215); // Block 2016 compact target + assert_eq!(adjustment, adjustment_bits); + } + + #[test] + fn compact_target_from_downwards_difficulty_adjustment_using_headers() { + use crate::block::Version; + use crate::TxMerkleNode; + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(503394215); // Block 2016 compact target + + // Block 2016, the only information used is `time` + let epoch_start = Header { + version: Version::ONE, + prev_blockhash: BlockHash::from_byte_array([0; 32]), + merkle_root: TxMerkleNode::from_byte_array([0; 32]), + time: BlockTime::from_u32(1599332844), + bits: starting_bits, + nonce: 0, + }; + + // Block 4031, the only information used are `bits` and `time` + let current = Header { + version: Version::ONE, + prev_blockhash: BlockHash::from_byte_array([0; 32]), + merkle_root: TxMerkleNode::from_byte_array([0; 32]), + time: BlockTime::from_u32(1600591200), + bits: starting_bits, + nonce: 0, + }; + let adjustment = + CompactTarget::from_header_difficulty_adjustment(epoch_start, current, params); + let adjustment_bits = CompactTarget::from_consensus(503397348); // Block 4032 compact target + assert_eq!(adjustment, adjustment_bits); + } + + #[test] + fn compact_target_from_maximum_upward_difficulty_adjustment() { + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(503403001); + let timespan = params.pow_target_timespan / 5; + let got = CompactTarget::from_next_work_required(starting_bits, timespan.into(), params); + let want = + Target::from_compact(starting_bits).min_transition_threshold().to_compact_lossy(); + assert_eq!(got, want); + } + + #[test] + fn compact_target_from_maximum_upward_difficulty_adjustment_with_negative_timespan() { + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(503403001); + let timespan: i64 = -i64::from(params.pow_target_timespan); + let got = CompactTarget::from_next_work_required(starting_bits, timespan, params); + let want = + Target::from_compact(starting_bits).min_transition_threshold().to_compact_lossy(); + assert_eq!(got, want); + } + + #[test] + fn compact_target_from_minimum_downward_difficulty_adjustment() { + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(403403001); // High difficulty for Signet + let timespan = 5 * params.pow_target_timespan; // Really slow. + let got = CompactTarget::from_next_work_required(starting_bits, timespan.into(), ¶ms); + let want = + Target::from_compact(starting_bits).max_transition_threshold(params).to_compact_lossy(); + assert_eq!(got, want); + } + + #[test] + fn compact_target_from_adjustment_is_max_target() { + let params = Params::new(crate::Network::Signet); + let starting_bits = CompactTarget::from_consensus(503543726); // Genesis compact target on Signet + let timespan = 5 * params.pow_target_timespan; // Really slow. + let got = CompactTarget::from_next_work_required(starting_bits, timespan.into(), ¶ms); + let want = params.max_attainable_target.to_compact_lossy(); + assert_eq!(got, want); + } + + #[test] + fn target_from_compact() { + // (nBits, target) + let tests = [ + (0x0100_3456_u32, 0x00_u64), // High bit set. + (0x0112_3456_u32, 0x12_u64), + (0x0200_8000_u32, 0x80_u64), + (0x0500_9234_u32, 0x9234_0000_u64), + (0x0492_3456_u32, 0x00_u64), // High bit set (0x80 in 0x92). + (0x0412_3456_u32, 0x1234_5600_u64), // Inverse of above; no high bit. + ]; + + for (n_bits, target) in tests { + let want = u64_to_target(target); + let got = Target::from_compact(CompactTarget::from_consensus(n_bits)); + assert_eq!(got, want); + } + } + + #[test] + fn target_is_met_by_for_target_equals_hash() { + let hash = "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c" + .parse::() + .expect("failed to parse block hash"); + let target = Target(U256::from_le_bytes(hash.to_byte_array())); + assert!(target.is_met_by(hash)); + } + + #[test] + fn max_target_from_compact() { + // The highest possible target is defined as 0x1d00ffff + let bits = 0x1d00ffff_u32; + let want = Target::MAX; + let got = Target::from_compact(CompactTarget::from_consensus(bits)); + assert_eq!(got, want) + } + + #[test] + fn target_difficulty_float() { + let params = Params::new(crate::Network::Bitcoin); + + assert_eq!(Target::MAX.difficulty_float(¶ms), 1.0_f64); + assert_eq!( + Target::from_compact(CompactTarget::from_consensus(0x1c00ffff_u32)) + .difficulty_float(¶ms), + 256.0_f64 + ); + assert_eq!( + Target::from_compact(CompactTarget::from_consensus(0x1b00ffff_u32)) + .difficulty_float(¶ms), + 65536.0_f64 + ); + assert_eq!( + Target::from_compact(CompactTarget::from_consensus(0x1a00f3a2_u32)) + .difficulty_float(¶ms), + 17628585.065897066_f64 + ); + } + + #[test] + fn roundtrip_compact_target() { + let consensus = 0x1d00_ffff; + let compact = CompactTarget::from_consensus(consensus); + let t = Target::from_compact(CompactTarget::from_consensus(consensus)); + assert_eq!(t, Target::from(compact)); // From/Into sanity check. + + let back = t.to_compact_lossy(); + assert_eq!(back, compact); // From/Into sanity check. + + assert_eq!(back.to_consensus(), consensus); + } + + #[test] + fn roundtrip_target_work() { + let target = u32_to_target(0xdeadbeef_u32); + let work = target.to_work(); + let back = work.to_target(); + assert_eq!(back, target) + } + + #[test] + #[cfg(feature = "std")] + fn work_log2() { + // Compare work log2 to historical Bitcoin Core values found in Core logs. + let tests: &[(u128, f64)] = &[ + // (chainwork, core log2) // height + (0x200020002, 33.000022), // 1 + (0xa97d67041c5e51596ee7, 79.405055), // 308004 + (0x1dc45d79394baa8ab18b20, 84.895644), // 418141 + (0x8c85acb73287e335d525b98, 91.134654), // 596624 + (0x2ef447e01d1642c40a184ada, 93.553183), // 738965 + ]; + + for &(chainwork, core_log2) in tests { + // Core log2 in the logs is rounded to 6 decimal places. + let log2 = (u128_to_work(chainwork).log2() * 1e6).round() / 1e6; + assert_eq!(log2, core_log2) + } + + assert_eq!(Work(U256::ONE).log2(), 0.0); + assert_eq!(Work(U256::MAX).log2(), 256.0); + } + + #[test] + fn u256_zero_min_max_inverse() { + assert_eq!(U256::MAX.inverse(), U256::ONE); + assert_eq!(U256::ONE.inverse(), U256::MAX); + assert_eq!(U256::ZERO.inverse(), U256::MAX); + } + + #[test] + fn u256_max_min_inverse_roundtrip() { + let max = U256::MAX; + + for min in [U256::ZERO, U256::ONE].iter() { + // lower target means more work required. + assert_eq!(Target(max).to_work(), Work(U256::ONE)); + assert_eq!(Target(*min).to_work(), Work(max)); + + assert_eq!(Work(max).to_target(), Target(U256::ONE)); + assert_eq!(Work(*min).to_target(), Target(max)); + } + } + + #[test] + fn u256_wrapping_add_wraps_at_boundary() { + assert_eq!(U256::MAX.wrapping_add(U256::ONE), U256::ZERO); + assert_eq!(U256::MAX.wrapping_add(U256::from(2_u8)), U256::ONE); + } + + #[test] + fn u256_wrapping_sub_wraps_at_boundary() { + assert_eq!(U256::ZERO.wrapping_sub(U256::ONE), U256::MAX); + assert_eq!(U256::ONE.wrapping_sub(U256::from(2_u8)), U256::MAX); + } + + #[test] + fn mul_u64_overflows() { + let (_, overflow) = U256::MAX.mul_u64(2); + assert!(overflow, "max * 2 should overflow"); + } + + #[test] + #[cfg(debug_assertions)] + #[should_panic] + fn u256_overflowing_addition_panics() { let _ = U256::MAX + U256::ONE; } + + #[test] + #[cfg(debug_assertions)] + #[should_panic] + fn u256_overflowing_subtraction_panics() { let _ = U256::ZERO - U256::ONE; } + + #[test] + #[cfg(debug_assertions)] + #[should_panic] + fn u256_multiplication_by_max_panics() { let _ = U256::MAX * U256::MAX; } + + #[test] + #[cfg(debug_assertions)] + #[should_panic] + fn work_overflowing_addition_panics() { let _ = Work(U256::MAX) + Work(U256::ONE); } + + #[test] + #[cfg(debug_assertions)] + #[should_panic] + fn work_overflowing_subtraction_panics() { let _ = Work(U256::ZERO) - Work(U256::ONE); } + + #[test] + fn u256_to_f64() { + assert_eq!(U256::ZERO.to_f64(), 0.0_f64); + assert_eq!(U256::ONE.to_f64(), 1.0_f64); + assert_eq!(U256::MAX.to_f64(), 1.157920892373162e77_f64); + assert_eq!((U256::MAX >> 1).to_f64(), 5.78960446186581e76_f64); + assert_eq!((U256::MAX >> 128).to_f64(), 3.402823669209385e38_f64); + assert_eq!((U256::MAX >> (256 - 54)).to_f64(), 1.8014398509481984e16_f64); + // 53 bits and below should not use exponents + assert_eq!((U256::MAX >> (256 - 53)).to_f64(), 9007199254740991.0_f64); + assert_eq!((U256::MAX >> (256 - 32)).to_f64(), 4294967295.0_f64); + assert_eq!((U256::MAX >> (256 - 16)).to_f64(), 65535.0_f64); + assert_eq!((U256::MAX >> (256 - 8)).to_f64(), 255.0_f64); + } +} + +#[cfg(kani)] +mod verification { + use super::*; + + #[kani::unwind(5)] // mul_u64 loops over 4 64 bit ints so use one more than 4 + #[kani::proof] + fn check_mul_u64() { + let x: U256 = kani::any(); + let y: u64 = kani::any(); + + let _ = x.mul_u64(y); + } +} diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs new file mode 100644 index 000000000..3a62df06e --- /dev/null +++ b/bitcoin/src/psbt/error.rs @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: CC0-1.0 + +use core::convert::Infallible; +use core::fmt; + +use internals::write_err; + +use crate::bip32::Xpub; +use crate::consensus::encode; +use crate::prelude::Box; +use crate::psbt::raw; +use crate::{ecdsa, key, taproot, OutPoint, Transaction, Txid}; + +/// Enum for marking psbt hash error. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum PsbtHash { + Ripemd, + Sha256, + Hash160, + Hash256, +} +/// Ways that a Partially Signed Transaction might fail. +#[derive(Debug)] +#[non_exhaustive] +pub enum Error { + /// Magic bytes for a PSBT must be the ASCII for "psbt" serialized in most + /// significant byte order. + InvalidMagic, + /// Missing both the witness and non-witness utxo. + MissingUtxo, + /// The separator for a PSBT must be `0xff`. + InvalidSeparator, + /// Returned when output index is out of bounds in relation to the output in non-witness UTXO. + PsbtUtxoOutOfbounds, + /// Known keys must be according to spec. + InvalidKey(raw::Key), + /// Non-proprietary key type found when proprietary key was expected + InvalidProprietaryKey, + /// Keys within key-value map should never be duplicated. + DuplicateKey(raw::Key), + /// The scriptSigs for the unsigned transaction must be empty. + UnsignedTxHasScriptSigs, + /// The scriptWitnesses for the unsigned transaction must be empty. + UnsignedTxHasScriptWitnesses, + /// A PSBT must have an unsigned transaction. + MustHaveUnsignedTx, + /// Signals that there are no more key-value pairs in a key-value map. + NoMorePairs, + /// Attempting to combine with a PSBT describing a different unsigned + /// transaction. + UnexpectedUnsignedTx { + /// Expected + expected: Box, + /// Actual + actual: Box, + }, + /// Unable to parse as a standard sighash type. + NonStandardSighashType(u32), + /// Invalid hash when parsing slice. + InvalidHash(core::array::TryFromSliceError), + /// The pre-image must hash to the corresponding psbt hash + InvalidPreimageHashPair { + /// Hash-type + hash_type: PsbtHash, + /// Pre-image + preimage: Box<[u8]>, + /// Hash value + hash: Box<[u8]>, + }, + /// Conflicting data during combine procedure: + /// global extended public key has inconsistent key sources + CombineInconsistentKeySources(Box), + /// Serialization error in bitcoin consensus-encoded structures + ConsensusEncoding(encode::Error), + /// Deserialization error in bitcoin consensus-encoded structures. + ConsensusDeserialize(encode::DeserializeError), + /// Error parsing bitcoin consensus-encoded object. + ConsensusParse(encode::ParseError), + /// Negative fee + NegativeFee, + /// Integer overflow in fee calculation + FeeOverflow, + /// Non-witness UTXO (which is a complete transaction) has `Txid` that + /// does not match the transaction input. + IncorrectNonWitnessUtxo { + /// The index of the input in question. + index: usize, + /// The outpoint of the input, as it appears in the unsigned transaction. + input_outpoint: OutPoint, + /// The [`Txid`] of the non-witness UTXO. + non_witness_utxo_txid: Txid, + }, + /// Parsing error indicating invalid public keys + InvalidPublicKey(key::FromSliceError), + /// Parsing error indicating invalid secp256k1 public keys + InvalidSecp256k1PublicKey(secp256k1::Error), + /// Parsing error indicating invalid xonly public keys + InvalidXOnlyPublicKey, + /// Parsing error indicating invalid ECDSA signatures + InvalidEcdsaSignature(ecdsa::DecodeError), + /// Parsing error indicating invalid Taproot signatures + InvalidTaprootSignature(taproot::SigFromSliceError), + /// Parsing error indicating invalid control block + InvalidControlBlock, + /// Parsing error indicating invalid leaf version + InvalidLeafVersion, + /// Parsing error indicating a Taproot error + Taproot(&'static str), + /// Taproot tree deserialization error + TapTree(taproot::IncompleteBuilderError), + /// Error related to an xpub key + XPubKey(&'static str), + /// Error related to PSBT version + Version(&'static str), + /// PSBT data is not consumed entirely + PartialDataConsumption, + /// I/O error. + Io(io::Error), +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::InvalidMagic => f.write_str("invalid magic"), + Self::MissingUtxo => f.write_str("UTXO information is not present in PSBT"), + Self::InvalidSeparator => f.write_str("invalid separator"), + Self::PsbtUtxoOutOfbounds => + f.write_str("output index is out of bounds of non witness script output array"), + Self::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), + Self::InvalidProprietaryKey => + write!(f, "non-proprietary key type found when proprietary key was expected"), + Self::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), + Self::UnsignedTxHasScriptSigs => + f.write_str("the unsigned transaction has script sigs"), + Self::UnsignedTxHasScriptWitnesses => + f.write_str("the unsigned transaction has script witnesses"), + Self::MustHaveUnsignedTx => + f.write_str("partially signed transactions must have an unsigned transaction"), + Self::NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), + Self::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!( + f, + "different unsigned transaction: expected {}, actual {}", + e.compute_txid(), + a.compute_txid() + ), + Self::NonStandardSighashType(ref sht) => + write!(f, "non-standard sighash type: {}", sht), + Self::InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e), + Self::InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => { + // directly using debug forms of psbthash enums + write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash) + } + Self::CombineInconsistentKeySources(ref s) => { + write!(f, "combine conflict: {}", s) + } + Self::ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e), + Self::ConsensusDeserialize(ref e) => + write_err!(f, "bitcoin consensus deserialization error"; e), + Self::ConsensusParse(ref e) => + write_err!(f, "error parsing bitcoin consensus encoded object"; e), + Self::NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"), + Self::FeeOverflow => f.write_str("integer overflow in fee calculation"), + Self::IncorrectNonWitnessUtxo { index, input_outpoint, non_witness_utxo_txid } => { + write!( + f, + "non-witness utxo txid is {}, which does not match input {}'s outpoint {}", + non_witness_utxo_txid, index, input_outpoint + ) + } + Self::InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e), + Self::InvalidSecp256k1PublicKey(ref e) => + write_err!(f, "invalid secp256k1 public key"; e), + Self::InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"), + Self::InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e), + Self::InvalidTaprootSignature(ref e) => write_err!(f, "invalid Taproot signature"; e), + Self::InvalidControlBlock => f.write_str("invalid control block"), + Self::InvalidLeafVersion => f.write_str("invalid leaf version"), + Self::Taproot(s) => write!(f, "Taproot error - {}", s), + Self::TapTree(ref e) => write_err!(f, "Taproot tree error"; e), + Self::XPubKey(s) => write!(f, "xpub key error - {}", s), + Self::Version(s) => write!(f, "version error {}", s), + Self::PartialDataConsumption => + f.write_str("data not consumed entirely when explicitly deserializing"), + Self::Io(ref e) => write_err!(f, "I/O error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidHash(ref e) => Some(e), + Self::ConsensusEncoding(ref e) => Some(e), + Self::ConsensusDeserialize(ref e) => Some(e), + Self::ConsensusParse(ref e) => Some(e), + Self::Io(ref e) => Some(e), + Self::InvalidMagic + | Self::MissingUtxo + | Self::InvalidSeparator + | Self::PsbtUtxoOutOfbounds + | Self::InvalidKey(_) + | Self::InvalidProprietaryKey + | Self::DuplicateKey(_) + | Self::UnsignedTxHasScriptSigs + | Self::UnsignedTxHasScriptWitnesses + | Self::MustHaveUnsignedTx + | Self::NoMorePairs + | Self::UnexpectedUnsignedTx { .. } + | Self::NonStandardSighashType(_) + | Self::InvalidPreimageHashPair { .. } + | Self::CombineInconsistentKeySources(_) + | Self::NegativeFee + | Self::FeeOverflow + | Self::IncorrectNonWitnessUtxo { .. } + | Self::InvalidPublicKey(_) + | Self::InvalidSecp256k1PublicKey(_) + | Self::InvalidXOnlyPublicKey + | Self::InvalidEcdsaSignature(_) + | Self::InvalidTaprootSignature(_) + | Self::InvalidControlBlock + | Self::InvalidLeafVersion + | Self::Taproot(_) + | Self::TapTree(_) + | Self::XPubKey(_) + | Self::Version(_) + | Self::PartialDataConsumption => None, + } + } +} + +impl From for Error { + fn from(e: core::array::TryFromSliceError) -> Self { Self::InvalidHash(e) } +} + +impl From for Error { + fn from(e: encode::Error) -> Self { Self::ConsensusEncoding(e) } +} + +impl From for Error { + fn from(e: encode::DeserializeError) -> Self { Self::ConsensusDeserialize(e) } +} + +impl From for Error { + fn from(e: encode::ParseError) -> Self { Self::ConsensusParse(e) } +} + +impl From for Error { + fn from(e: io::Error) -> Self { Self::Io(e) } +} diff --git a/bitcoin/src/psbt/macros.rs b/bitcoin/src/psbt/macros.rs new file mode 100644 index 000000000..4044a5e52 --- /dev/null +++ b/bitcoin/src/psbt/macros.rs @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: CC0-1.0 + +#[allow(unused_macros)] +macro_rules! combine { + ($thing:ident, $slf:ident, $other:ident) => { + if let (&None, Some($thing)) = (&$slf.$thing, $other.$thing) { + $slf.$thing = Some($thing); + } + }; +} + +macro_rules! impl_psbt_de_serialize { + ($thing:ty) => { + impl_psbt_serialize!($thing); + impl_psbt_deserialize!($thing); + }; +} + +macro_rules! impl_psbt_deserialize { + ($thing:ty) => { + impl $crate::psbt::serialize::Deserialize for $thing { + fn deserialize(bytes: &[u8]) -> core::result::Result { + $crate::consensus::deserialize(&bytes[..]).map_err(|e| $crate::psbt::Error::from(e)) + } + } + }; +} + +macro_rules! impl_psbt_serialize { + ($thing:ty) => { + impl $crate::psbt::serialize::Serialize for $thing { + fn serialize(&self) -> $crate::prelude::Vec { $crate::consensus::serialize(self) } + } + }; +} + +macro_rules! impl_psbtmap_serialize { + ($thing:ty) => { + impl $crate::psbt::serialize::Serialize for $thing { + fn serialize(&self) -> Vec { self.serialize_map() } + } + }; +} + +macro_rules! impl_psbtmap_deserialize { + ($thing:ty) => { + impl $crate::psbt::serialize::Deserialize for $thing { + fn deserialize(bytes: &[u8]) -> core::result::Result { + let mut decoder = bytes; + Self::decode(&mut decoder) + } + } + }; +} + +macro_rules! impl_psbtmap_decoding { + ($thing:ty) => { + impl $thing { + pub(crate) fn decode( + r: &mut R, + ) -> core::result::Result { + let mut rv: Self = core::default::Default::default(); + + loop { + match $crate::psbt::raw::Pair::decode(r) { + Ok(pair) => rv.insert_pair(pair)?, + Err($crate::psbt::Error::NoMorePairs) => return Ok(rv), + Err(e) => return Err(e), + } + } + } + } + }; +} + +macro_rules! impl_psbtmap_ser_de_serialize { + ($thing:ty) => { + impl_psbtmap_decoding!($thing); + impl_psbtmap_serialize!($thing); + impl_psbtmap_deserialize!($thing); + }; +} + +#[rustfmt::skip] +macro_rules! impl_psbt_insert_pair { + ($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => { + if $raw_key.key_data.is_empty() { + if $slf.$unkeyed_name.is_none() { + let val: $unkeyed_value_type = $crate::psbt::serialize::Deserialize::deserialize(&$raw_value)?; + $slf.$unkeyed_name = Some(val) + } else { + return Err($crate::psbt::Error::DuplicateKey($raw_key).into()); + } + } else { + return Err($crate::psbt::Error::InvalidKey($raw_key).into()); + } + }; + ($slf:ident.$keyed_name:ident <= <$raw_key:ident: $keyed_key_type:ty>|<$raw_value:ident: $keyed_value_type:ty>) => { + if !$raw_key.key_data.is_empty() { + let key_val: $keyed_key_type = $crate::psbt::serialize::Deserialize::deserialize(&$raw_key.key_data)?; + match $slf.$keyed_name.entry(key_val) { + $crate::prelude::btree_map::Entry::Vacant(empty_key) => { + let val: $keyed_value_type = $crate::psbt::serialize::Deserialize::deserialize(&$raw_value)?; + empty_key.insert(val); + } + $crate::prelude::btree_map::Entry::Occupied(_) => return Err($crate::psbt::Error::DuplicateKey($raw_key).into()), + } + } else { + return Err($crate::psbt::Error::InvalidKey($raw_key).into()); + } + }; +} + +#[rustfmt::skip] +macro_rules! psbt_insert_hash_pair { + (&mut $slf:ident.$map:ident <= $raw_key:ident|$raw_value:ident|$hash:ident|$hash_type_error:path) => { + if $raw_key.key_data.is_empty() { + return Err($crate::psbt::Error::InvalidKey($raw_key)); + } + let key_val: $hash::Hash = Deserialize::deserialize(&$raw_key.key_data)?; + match $slf.$map.entry(key_val) { + btree_map::Entry::Vacant(empty_key) => { + let val: Vec = Deserialize::deserialize(&$raw_value)?; + if $hash::hash(&val) != key_val { + return Err($crate::psbt::Error::InvalidPreimageHashPair { + preimage: val.into_boxed_slice(), + hash: Box::from(key_val.borrow()), + hash_type: $hash_type_error, + }); + } + empty_key.insert(val); + } + btree_map::Entry::Occupied(_) => return Err($crate::psbt::Error::DuplicateKey($raw_key)), + } + } +} + +#[rustfmt::skip] +macro_rules! impl_psbt_get_pair { + ($rv:ident.push($slf:ident.$unkeyed_name:ident, $unkeyed_typeval:ident)) => { + if let Some(ref $unkeyed_name) = $slf.$unkeyed_name { + $rv.push($crate::psbt::raw::Pair { + key: $crate::psbt::raw::Key { + type_value: $unkeyed_typeval, + key_data: vec![], + }, + value: $crate::psbt::serialize::Serialize::serialize($unkeyed_name), + }); + } + }; + ($rv:ident.push_map($slf:ident.$keyed_name:ident, $keyed_typeval:ident)) => { + for (key, val) in &$slf.$keyed_name { + $rv.push($crate::psbt::raw::Pair { + key: $crate::psbt::raw::Key { + type_value: $keyed_typeval, + key_data: $crate::psbt::serialize::Serialize::serialize(key), + }, + value: $crate::psbt::serialize::Serialize::serialize(val), + }); + } + }; +} + +// macros for serde of hashes +macro_rules! impl_psbt_hash_de_serialize { + ($hash_type:ty) => { + impl_psbt_hash_serialize!($hash_type); + impl_psbt_hash_deserialize!($hash_type); + }; +} + +macro_rules! impl_psbt_hash_deserialize { + ($hash_type:ty) => { + impl $crate::psbt::serialize::Deserialize for $hash_type { + fn deserialize(bytes: &[u8]) -> core::result::Result { + const LEN: usize = <$hash_type as hashes::Hash>::LEN; + let bytes = + <[u8; LEN]>::try_from(bytes).map_err(|e| $crate::psbt::Error::from(e))?; + Ok(<$hash_type>::from_byte_array(bytes)) + } + } + }; +} + +macro_rules! impl_psbt_hash_serialize { + ($hash_type:ty) => { + impl $crate::psbt::serialize::Serialize for $hash_type { + fn serialize(&self) -> $crate::prelude::Vec { self.as_byte_array().to_vec() } + } + }; +} diff --git a/bitcoin/src/psbt/map/global.rs b/bitcoin/src/psbt/map/global.rs new file mode 100644 index 000000000..6a24c1311 --- /dev/null +++ b/bitcoin/src/psbt/map/global.rs @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: CC0-1.0 + +use internals::ToU64 as _; +use io::{BufRead, Cursor, Read}; + +use crate::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpub}; +use crate::consensus::encode::MAX_VEC_SIZE; +use crate::consensus::{encode, Decodable}; +use crate::prelude::{btree_map, BTreeMap, Vec}; +use crate::psbt::map::Map; +use crate::psbt::{raw, Error, Psbt}; +use crate::transaction::Transaction; + +/// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00 +const PSBT_GLOBAL_UNSIGNED_TX: u64 = 0x00; +/// Type: Extended Public Key PSBT_GLOBAL_XPUB = 0x01 +const PSBT_GLOBAL_XPUB: u64 = 0x01; +/// Type: Version Number PSBT_GLOBAL_VERSION = 0xFB +const PSBT_GLOBAL_VERSION: u64 = 0xFB; +/// Type: Proprietary Use Type PSBT_GLOBAL_PROPRIETARY = 0xFC +const PSBT_GLOBAL_PROPRIETARY: u64 = 0xFC; + +impl Map for Psbt { + fn get_pairs(&self) -> Vec { + let mut rv: Vec = Default::default(); + + rv.push(raw::Pair { + key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key_data: vec![] }, + value: { + // Manually serialized to ensure 0-input txs are serialized + // without witnesses. + let mut ret = Vec::new(); + ret.extend(encode::serialize(&self.unsigned_tx.version)); + ret.extend(encode::serialize(&self.unsigned_tx.inputs)); + ret.extend(encode::serialize(&self.unsigned_tx.outputs)); + ret.extend(encode::serialize(&self.unsigned_tx.lock_time)); + ret + }, + }); + + for (xpub, (fingerprint, derivation)) in &self.xpub { + rv.push(raw::Pair { + key: raw::Key { type_value: PSBT_GLOBAL_XPUB, key_data: xpub.encode().to_vec() }, + value: { + let mut ret = Vec::with_capacity(4 + derivation.len() * 4); + ret.extend(fingerprint.as_bytes()); + derivation.into_iter().for_each(|n| ret.extend(&u32::from(*n).to_le_bytes())); + ret + }, + }); + } + + // Serializing version only for non-default value; otherwise test vectors fail + if self.version > 0 { + rv.push(raw::Pair { + key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key_data: vec![] }, + value: self.version.to_le_bytes().to_vec(), + }); + } + + for (key, value) in self.proprietary.iter() { + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); + } + + for (key, value) in self.unknown.iter() { + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); + } + + rv + } +} + +impl Psbt { + pub(crate) fn decode_global(r: &mut R) -> Result { + let mut r = r.take(MAX_VEC_SIZE.to_u64()); + let mut tx: Option = None; + let mut version: Option = None; + let mut unknowns: BTreeMap> = Default::default(); + let mut xpub_map: BTreeMap = Default::default(); + let mut proprietary: BTreeMap> = Default::default(); + + loop { + match raw::Pair::decode(&mut r) { + Ok(pair) => { + match pair.key.type_value { + PSBT_GLOBAL_UNSIGNED_TX => { + // key has to be empty + if pair.key.key_data.is_empty() { + // there can only be one unsigned transaction + if tx.is_none() { + let vlen: usize = pair.value.len(); + let mut decoder = Cursor::new(pair.value); + + // Manually deserialized to ensure 0-input + // txs without witnesses are deserialized + // properly. + tx = Some(Transaction { + version: Decodable::consensus_decode(&mut decoder)?, + inputs: Decodable::consensus_decode(&mut decoder)?, + outputs: Decodable::consensus_decode(&mut decoder)?, + lock_time: Decodable::consensus_decode(&mut decoder)?, + }); + + if decoder.position() != vlen.to_u64() { + return Err(Error::PartialDataConsumption); + } + } else { + return Err(Error::DuplicateKey(pair.key)); + } + } else { + return Err(Error::InvalidKey(pair.key)); + } + } + PSBT_GLOBAL_XPUB => { + if !pair.key.key_data.is_empty() { + let xpub = Xpub::decode(&pair.key.key_data) + .map_err(|_| Error::XPubKey( + "can't deserialize ExtendedPublicKey from global XPUB key data" + ))?; + + if pair.value.is_empty() || pair.value.len() % 4 != 0 { + return Err(Error::XPubKey( + "incorrect length of global xpub derivation data", + )); + } + + let child_count = pair.value.len() / 4 - 1; + let mut decoder = Cursor::new(pair.value); + let mut fingerprint = [0u8; 4]; + decoder.read_exact(&mut fingerprint[..]).map_err(|_| { + Error::XPubKey("can't read global xpub fingerprint") + })?; + let mut path = Vec::::with_capacity(child_count); + while let Ok(index) = u32::consensus_decode(&mut decoder) { + path.push(ChildNumber::from(index)) + } + let derivation = DerivationPath::from(path); + // Keys, according to BIP-0174, must be unique + if xpub_map + .insert(xpub, (Fingerprint::from(fingerprint), derivation)) + .is_some() + { + return Err(Error::XPubKey("repeated global xpub key")); + } + } else { + return Err(Error::XPubKey( + "Xpub global key must contain serialized Xpub data", + )); + } + } + PSBT_GLOBAL_VERSION => { + // key has to be empty + if pair.key.key_data.is_empty() { + // there can only be one version + if version.is_none() { + let vlen: usize = pair.value.len(); + let mut decoder = Cursor::new(pair.value); + if vlen != 4 { + return Err(Error::Version( + "invalid global version value length (must be 4 bytes)", + )); + } + version = Some(Decodable::consensus_decode(&mut decoder)?); + // We only understand version 0 PSBTs. According to BIP-0174 we + // should throw an error if we see anything other than version 0. + if version != Some(0) { + return Err(Error::Version( + "PSBT versions greater than 0 are not supported", + )); + } + } else { + return Err(Error::DuplicateKey(pair.key)); + } + } else { + return Err(Error::InvalidKey(pair.key)); + } + } + PSBT_GLOBAL_PROPRIETARY => match proprietary + .entry(raw::ProprietaryKey::try_from(pair.key.clone())?) + { + btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(pair.value); + } + btree_map::Entry::Occupied(_) => + return Err(Error::DuplicateKey(pair.key)), + }, + _ => match unknowns.entry(pair.key) { + btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(pair.value); + } + btree_map::Entry::Occupied(k) => + return Err(Error::DuplicateKey(k.key().clone())), + }, + } + } + Err(crate::psbt::Error::NoMorePairs) => break, + Err(e) => return Err(e), + } + } + + if let Some(tx) = tx { + Ok(Self { + unsigned_tx: tx, + version: version.unwrap_or(0), + xpub: xpub_map, + proprietary, + unknown: unknowns, + inputs: vec![], + outputs: vec![], + }) + } else { + Err(Error::MustHaveUnsignedTx) + } + } +} diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs new file mode 100644 index 000000000..e38c87dd4 --- /dev/null +++ b/bitcoin/src/psbt/map/input.rs @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: CC0-1.0 + +use core::fmt; +use core::str::FromStr; + +use hashes::{hash160, ripemd160, sha256, sha256d}; + +use crate::bip32::KeySource; +use crate::crypto::key::{PublicKey, XOnlyPublicKey}; +use crate::crypto::{ecdsa, taproot}; +use crate::prelude::{btree_map, BTreeMap, Borrow, Box, ToOwned, Vec}; +use crate::psbt::map::Map; +use crate::psbt::serialize::Deserialize; +use crate::psbt::{error, raw, Error}; +use crate::script::{RedeemScriptBuf, ScriptSigBuf, TapScriptBuf, WitnessScriptBuf}; +use crate::sighash::{ + EcdsaSighashType, InvalidSighashTypeError, NonStandardSighashTypeError, SighashTypeParseError, + TapSighashType, +}; +use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash}; +use crate::transaction::{Transaction, TxOut}; +use crate::witness::Witness; + +/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 +const PSBT_IN_NON_WITNESS_UTXO: u64 = 0x00; +/// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01 +const PSBT_IN_WITNESS_UTXO: u64 = 0x01; +/// Type: Partial Signature PSBT_IN_PARTIAL_SIG = 0x02 +const PSBT_IN_PARTIAL_SIG: u64 = 0x02; +/// Type: Sighash Type PSBT_IN_SIGHASH_TYPE = 0x03 +const PSBT_IN_SIGHASH_TYPE: u64 = 0x03; +/// Type: Redeem Script PSBT_IN_REDEEM_SCRIPT = 0x04 +const PSBT_IN_REDEEM_SCRIPT: u64 = 0x04; +/// Type: Witness Script PSBT_IN_WITNESS_SCRIPT = 0x05 +const PSBT_IN_WITNESS_SCRIPT: u64 = 0x05; +/// Type: BIP-0032 Derivation Path PSBT_IN_BIP32_DERIVATION = 0x06 +const PSBT_IN_BIP32_DERIVATION: u64 = 0x06; +/// Type: Finalized scriptSig PSBT_IN_FINAL_SCRIPTSIG = 0x07 +const PSBT_IN_FINAL_SCRIPTSIG: u64 = 0x07; +/// Type: Finalized scriptWitness PSBT_IN_FINAL_SCRIPTWITNESS = 0x08 +const PSBT_IN_FINAL_SCRIPTWITNESS: u64 = 0x08; +/// Type: RIPEMD160 preimage PSBT_IN_RIPEMD160 = 0x0a +const PSBT_IN_RIPEMD160: u64 = 0x0a; +/// Type: SHA256 preimage PSBT_IN_SHA256 = 0x0b +const PSBT_IN_SHA256: u64 = 0x0b; +/// Type: HASH160 preimage PSBT_IN_HASH160 = 0x0c +const PSBT_IN_HASH160: u64 = 0x0c; +/// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d +const PSBT_IN_HASH256: u64 = 0x0d; +/// Type: Taproot Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13 +const PSBT_IN_TAP_KEY_SIG: u64 = 0x13; +/// Type: Taproot Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14 +const PSBT_IN_TAP_SCRIPT_SIG: u64 = 0x14; +/// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x15 +const PSBT_IN_TAP_LEAF_SCRIPT: u64 = 0x15; +/// Type: Taproot Key BIP-0032 Derivation Path PSBT_IN_TAP_BIP32_DERIVATION = 0x16 +const PSBT_IN_TAP_BIP32_DERIVATION: u64 = 0x16; +/// Type: Taproot Internal Key PSBT_IN_TAP_INTERNAL_KEY = 0x17 +const PSBT_IN_TAP_INTERNAL_KEY: u64 = 0x17; +/// Type: Taproot Merkle Root PSBT_IN_TAP_MERKLE_ROOT = 0x18 +const PSBT_IN_TAP_MERKLE_ROOT: u64 = 0x18; +/// Type: MuSig2 Public Keys Participating in Aggregate Input PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a +const PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS: u64 = 0x1a; +/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC +const PSBT_IN_PROPRIETARY: u64 = 0xFC; + +/// A key-value map for an input of the corresponding index in the unsigned +/// transaction. +#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] +pub struct Input { + /// The non-witness transaction this input spends from. Should only be + /// `Option::Some` for inputs which spend non-SegWit outputs or + /// if it is unknown whether an input spends a SegWit output. + pub non_witness_utxo: Option, + /// The transaction output this input spends from. Should only be + /// `Option::Some` for inputs which spend SegWit outputs, + /// including P2SH embedded ones. + pub witness_utxo: Option, + /// A map from public keys to their corresponding signature as would be + /// pushed to the stack from a scriptSig or witness for a non-Taproot inputs. + pub partial_sigs: BTreeMap, + /// The sighash type to be used for this input. Signatures for this input + /// must use the sighash type. + pub sighash_type: Option, + /// The redeem script for this input. + pub redeem_script: Option, + /// The witness script for this input. + pub witness_script: Option, + /// A map from public keys needed to sign this input to their corresponding + /// master key fingerprints and derivation paths. + pub bip32_derivation: BTreeMap, + /// The finalized, fully-constructed scriptSig with signatures and any other + /// scripts necessary for this input to pass validation. + pub final_script_sig: Option, + /// The finalized, fully-constructed scriptWitness with signatures and any + /// other scripts necessary for this input to pass validation. + pub final_script_witness: Option, + /// RIPEMD160 hash to preimage map. + pub ripemd160_preimages: BTreeMap>, + /// SHA256 hash to preimage map. + pub sha256_preimages: BTreeMap>, + /// HASH160 hash to preimage map. + pub hash160_preimages: BTreeMap>, + /// HASH256 hash to preimage map. + pub hash256_preimages: BTreeMap>, + /// Serialized Taproot signature with sighash type for key spend. + pub tap_key_sig: Option, + /// Map of `|` with signature. + pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), taproot::Signature>, + /// Map of Control blocks to Script version pair. + pub tap_scripts: BTreeMap, + /// Map of tap root x only keys to origin info and leaf hashes contained in it. + pub tap_key_origins: BTreeMap, KeySource)>, + /// Taproot Internal key. + pub tap_internal_key: Option, + /// Taproot Merkle root. + pub tap_merkle_root: Option, + /// Mapping from MuSig2 aggregate keys to the participant keys from which they were aggregated. + pub musig2_participant_pubkeys: BTreeMap>, + /// Proprietary key-value pairs for this input. + pub proprietary: BTreeMap>, + /// Unknown key-value pairs for this input. + pub unknown: BTreeMap>, +} + +/// A Signature hash type for the corresponding input. +/// +/// As of Taproot upgrade, the signature hash type can be either [`EcdsaSighashType`] or +/// [`TapSighashType`] but it is not possible to know directly which signature hash type the user is +/// dealing with. Therefore, the user is responsible for converting to/from [`PsbtSighashType`] +/// from/to the desired signature hash type they need. +/// +/// # Examples +/// +/// ``` +/// use bitcoin::{EcdsaSighashType, TapSighashType}; +/// use bitcoin::psbt::PsbtSighashType; +/// +/// let _ecdsa_sighash_all: PsbtSighashType = EcdsaSighashType::All.into(); +/// let _tap_sighash_all: PsbtSighashType = TapSighashType::All.into(); +/// ``` +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PsbtSighashType { + pub(in crate::psbt) inner: u32, +} + +impl fmt::Display for PsbtSighashType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.taproot_hash_ty() { + Err(_) => write!(f, "{:#x}", self.inner), + Ok(taproot_hash_ty) => fmt::Display::fmt(&taproot_hash_ty, f), + } + } +} + +impl FromStr for PsbtSighashType { + type Err = SighashTypeParseError; + + #[inline] + fn from_str(s: &str) -> Result { + // We accept strings of form: "SIGHASH_ALL" etc. + // + // NB: some of Taproot sighash types are non-standard for pre-Taproot + // inputs. We also do not support SIGHASH_RESERVED in verbatim form + // ("0xFF" string should be used instead). + if let Ok(ty) = s.parse::() { + return Ok(ty.into()); + } + + // We accept non-standard sighash values. + if let Ok(inner) = u32::from_str_radix(s.trim_start_matches("0x"), 16) { + return Ok(Self { inner }); + } + + Err(SighashTypeParseError { unrecognized: s.to_owned() }) + } +} +impl From for PsbtSighashType { + fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self { + Self { inner: ecdsa_hash_ty as u32 } + } +} + +impl From for PsbtSighashType { + fn from(taproot_hash_ty: TapSighashType) -> Self { + Self { inner: taproot_hash_ty as u32 } + } +} + +impl PsbtSighashType { + /// Ambiguous `ALL` sighash type, may refer to either [`EcdsaSighashType::All`] + /// or [`TapSighashType::All`]. + /// + /// This is equivalent to either `EcdsaSighashType::All.into()` or `TapSighashType::All.into()`. + /// For sighash types other than `ALL` use the ECDSA or Taproot sighash type directly. + /// + /// # Examples + /// + /// ``` + /// use bitcoin::{EcdsaSighashType, TapSighashType}; + /// use bitcoin::psbt::PsbtSighashType; + /// let _ecdsa_sighash_anyone_can_pay: PsbtSighashType = EcdsaSighashType::AllPlusAnyoneCanPay.into(); + /// let _tap_sighash_anyone_can_pay: PsbtSighashType = TapSighashType::AllPlusAnyoneCanPay.into(); + /// ``` + pub const ALL: Self = Self { inner: 0x01 }; + + /// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be + /// converted to one. + pub fn ecdsa_hash_ty(self) -> Result { + EcdsaSighashType::from_standard(self.inner) + } + + /// Returns the [`TapSighashType`] if the [`PsbtSighashType`] can be + /// converted to one. + pub fn taproot_hash_ty(self) -> Result { + if self.inner > 0xffu32 { + Err(InvalidSighashTypeError(self.inner)) + } else { + TapSighashType::from_consensus_u8(self.inner as u8) + } + } + + /// Constructs a new [`PsbtSighashType`] from a raw `u32`. + /// + /// Allows construction of a non-standard or non-valid sighash flag + /// ([`EcdsaSighashType`], [`TapSighashType`] respectively). + pub fn from_u32(n: u32) -> Self { Self { inner: n } } + + /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag. + /// + /// No guarantees are made as to the standardness or validity of the returned value. + pub fn to_u32(self) -> u32 { self.inner } +} + +impl Input { + /// Obtains the [`EcdsaSighashType`] for this input if one is specified. If no sighash type is + /// specified, returns [`EcdsaSighashType::All`]. + /// + /// # Errors + /// + /// If the `sighash_type` field is set to a non-standard ECDSA sighash value. + pub fn ecdsa_hash_ty(&self) -> Result { + self.sighash_type + .map(|sighash_type| sighash_type.ecdsa_hash_ty()) + .unwrap_or(Ok(EcdsaSighashType::All)) + } + + /// Obtains the [`TapSighashType`] for this input if one is specified. If no sighash type is + /// specified, returns [`TapSighashType::Default`]. + /// + /// # Errors + /// + /// If the `sighash_type` field is set to an invalid Taproot sighash value. + pub fn taproot_hash_ty(&self) -> Result { + self.sighash_type + .map(|sighash_type| sighash_type.taproot_hash_ty()) + .unwrap_or(Ok(TapSighashType::Default)) + } + + pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { + let raw::Pair { key: raw_key, value: raw_value } = pair; + + match raw_key.type_value { + PSBT_IN_NON_WITNESS_UTXO => { + impl_psbt_insert_pair! { + self.non_witness_utxo <= | + } + } + PSBT_IN_WITNESS_UTXO => { + impl_psbt_insert_pair! { + self.witness_utxo <= | + } + } + PSBT_IN_PARTIAL_SIG => { + impl_psbt_insert_pair! { + self.partial_sigs <= | + } + } + PSBT_IN_SIGHASH_TYPE => { + impl_psbt_insert_pair! { + self.sighash_type <= | + } + } + PSBT_IN_REDEEM_SCRIPT => { + impl_psbt_insert_pair! { + self.redeem_script <= | + } + } + PSBT_IN_WITNESS_SCRIPT => { + impl_psbt_insert_pair! { + self.witness_script <= | + } + } + PSBT_IN_BIP32_DERIVATION => { + impl_psbt_insert_pair! { + self.bip32_derivation <= | + } + } + PSBT_IN_FINAL_SCRIPTSIG => { + impl_psbt_insert_pair! { + self.final_script_sig <= | + } + } + PSBT_IN_FINAL_SCRIPTWITNESS => { + impl_psbt_insert_pair! { + self.final_script_witness <= | + } + } + PSBT_IN_RIPEMD160 => { + psbt_insert_hash_pair! { + &mut self.ripemd160_preimages <= raw_key|raw_value|ripemd160|error::PsbtHash::Ripemd + } + } + PSBT_IN_SHA256 => { + psbt_insert_hash_pair! { + &mut self.sha256_preimages <= raw_key|raw_value|sha256|error::PsbtHash::Sha256 + } + } + PSBT_IN_HASH160 => { + psbt_insert_hash_pair! { + &mut self.hash160_preimages <= raw_key|raw_value|hash160|error::PsbtHash::Hash160 + } + } + PSBT_IN_HASH256 => { + psbt_insert_hash_pair! { + &mut self.hash256_preimages <= raw_key|raw_value|sha256d|error::PsbtHash::Hash256 + } + } + PSBT_IN_TAP_KEY_SIG => { + impl_psbt_insert_pair! { + self.tap_key_sig <= | + } + } + PSBT_IN_TAP_SCRIPT_SIG => { + impl_psbt_insert_pair! { + self.tap_script_sigs <= | + } + } + PSBT_IN_TAP_LEAF_SCRIPT => { + impl_psbt_insert_pair! { + self.tap_scripts <= |< raw_value: (TapScriptBuf, LeafVersion)> + } + } + PSBT_IN_TAP_BIP32_DERIVATION => { + impl_psbt_insert_pair! { + self.tap_key_origins <= |< raw_value: (Vec, KeySource)> + } + } + PSBT_IN_TAP_INTERNAL_KEY => { + impl_psbt_insert_pair! { + self.tap_internal_key <= |< raw_value: XOnlyPublicKey> + } + } + PSBT_IN_TAP_MERKLE_ROOT => { + impl_psbt_insert_pair! { + self.tap_merkle_root <= |< raw_value: TapNodeHash> + } + } + PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS => { + impl_psbt_insert_pair! { + self.musig2_participant_pubkeys <= |< raw_value: Vec > + } + } + PSBT_IN_PROPRIETARY => { + let key = raw::ProprietaryKey::try_from(raw_key.clone())?; + match self.proprietary.entry(key) { + btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(raw_value); + } + btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)), + } + } + _ => match self.unknown.entry(raw_key) { + btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(raw_value); + } + btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), + }, + } + + Ok(()) + } + + /// Combines this [`Input`] with `other` `Input` (as described by BIP 174). + pub fn combine(&mut self, other: Self) { + combine!(non_witness_utxo, self, other); + + if let (&None, Some(witness_utxo)) = (&self.witness_utxo, other.witness_utxo) { + self.witness_utxo = Some(witness_utxo); + self.non_witness_utxo = None; // Clear out any non-witness UTXO when we set a witness one + } + + self.partial_sigs.extend(other.partial_sigs); + self.bip32_derivation.extend(other.bip32_derivation); + self.ripemd160_preimages.extend(other.ripemd160_preimages); + self.sha256_preimages.extend(other.sha256_preimages); + self.hash160_preimages.extend(other.hash160_preimages); + self.hash256_preimages.extend(other.hash256_preimages); + self.tap_script_sigs.extend(other.tap_script_sigs); + self.tap_scripts.extend(other.tap_scripts); + self.tap_key_origins.extend(other.tap_key_origins); + self.musig2_participant_pubkeys.extend(other.musig2_participant_pubkeys); + self.proprietary.extend(other.proprietary); + self.unknown.extend(other.unknown); + + combine!(redeem_script, self, other); + combine!(witness_script, self, other); + combine!(final_script_sig, self, other); + combine!(final_script_witness, self, other); + combine!(tap_key_sig, self, other); + combine!(tap_internal_key, self, other); + combine!(tap_merkle_root, self, other); + } +} + +impl Map for Input { + fn get_pairs(&self) -> Vec { + let mut rv: Vec = Default::default(); + + impl_psbt_get_pair! { + rv.push(self.non_witness_utxo, PSBT_IN_NON_WITNESS_UTXO) + } + + impl_psbt_get_pair! { + rv.push(self.witness_utxo, PSBT_IN_WITNESS_UTXO) + } + + impl_psbt_get_pair! { + rv.push_map(self.partial_sigs, PSBT_IN_PARTIAL_SIG) + } + + impl_psbt_get_pair! { + rv.push(self.sighash_type, PSBT_IN_SIGHASH_TYPE) + } + + impl_psbt_get_pair! { + rv.push(self.redeem_script, PSBT_IN_REDEEM_SCRIPT) + } + + impl_psbt_get_pair! { + rv.push(self.witness_script, PSBT_IN_WITNESS_SCRIPT) + } + + impl_psbt_get_pair! { + rv.push_map(self.bip32_derivation, PSBT_IN_BIP32_DERIVATION) + } + + impl_psbt_get_pair! { + rv.push(self.final_script_sig, PSBT_IN_FINAL_SCRIPTSIG) + } + + impl_psbt_get_pair! { + rv.push(self.final_script_witness, PSBT_IN_FINAL_SCRIPTWITNESS) + } + + impl_psbt_get_pair! { + rv.push_map(self.ripemd160_preimages, PSBT_IN_RIPEMD160) + } + + impl_psbt_get_pair! { + rv.push_map(self.sha256_preimages, PSBT_IN_SHA256) + } + + impl_psbt_get_pair! { + rv.push_map(self.hash160_preimages, PSBT_IN_HASH160) + } + + impl_psbt_get_pair! { + rv.push_map(self.hash256_preimages, PSBT_IN_HASH256) + } + + impl_psbt_get_pair! { + rv.push(self.tap_key_sig, PSBT_IN_TAP_KEY_SIG) + } + + impl_psbt_get_pair! { + rv.push_map(self.tap_script_sigs, PSBT_IN_TAP_SCRIPT_SIG) + } + + impl_psbt_get_pair! { + rv.push_map(self.tap_scripts, PSBT_IN_TAP_LEAF_SCRIPT) + } + + impl_psbt_get_pair! { + rv.push_map(self.tap_key_origins, PSBT_IN_TAP_BIP32_DERIVATION) + } + + impl_psbt_get_pair! { + rv.push(self.tap_internal_key, PSBT_IN_TAP_INTERNAL_KEY) + } + + impl_psbt_get_pair! { + rv.push(self.tap_merkle_root, PSBT_IN_TAP_MERKLE_ROOT) + } + + impl_psbt_get_pair! { + rv.push_map(self.musig2_participant_pubkeys, PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS) + } + + for (key, value) in self.proprietary.iter() { + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); + } + + for (key, value) in self.unknown.iter() { + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); + } + + rv + } +} + +impl_psbtmap_ser_de_serialize!(Input); + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn psbt_sighash_type_ecdsa() { + for ecdsa in &[ + EcdsaSighashType::All, + EcdsaSighashType::None, + EcdsaSighashType::Single, + EcdsaSighashType::AllPlusAnyoneCanPay, + EcdsaSighashType::NonePlusAnyoneCanPay, + EcdsaSighashType::SinglePlusAnyoneCanPay, + ] { + let sighash = PsbtSighashType::from(*ecdsa); + let s = format!("{}", sighash); + let back = s.parse::().unwrap(); + assert_eq!(back, sighash); + assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa); + } + } + + #[test] + fn psbt_sighash_type_taproot() { + for tap in &[ + TapSighashType::Default, + TapSighashType::All, + TapSighashType::None, + TapSighashType::Single, + TapSighashType::AllPlusAnyoneCanPay, + TapSighashType::NonePlusAnyoneCanPay, + TapSighashType::SinglePlusAnyoneCanPay, + ] { + let sighash = PsbtSighashType::from(*tap); + let s = format!("{}", sighash); + let back = s.parse::().unwrap(); + assert_eq!(back, sighash); + assert_eq!(back.taproot_hash_ty().unwrap(), *tap); + } + } + + #[test] + fn psbt_sighash_type_notstd() { + let nonstd = 0xdddddddd; + let sighash = PsbtSighashType { inner: nonstd }; + let s = format!("{}", sighash); + let back = s.parse::().unwrap(); + + assert_eq!(back, sighash); + assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashTypeError(nonstd))); + assert_eq!(back.taproot_hash_ty(), Err(InvalidSighashTypeError(nonstd))); + } + + #[test] + fn psbt_sighash_const_all() { + assert_eq!(PsbtSighashType::ALL.to_u32(), 0x01); + assert_eq!(PsbtSighashType::ALL.ecdsa_hash_ty().unwrap(), EcdsaSighashType::All); + assert_eq!(PsbtSighashType::ALL.taproot_hash_ty().unwrap(), TapSighashType::All); + } +} diff --git a/bitcoin/src/psbt/map/mod.rs b/bitcoin/src/psbt/map/mod.rs new file mode 100644 index 000000000..58c28699a --- /dev/null +++ b/bitcoin/src/psbt/map/mod.rs @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: CC0-1.0 + +mod global; +mod input; +mod output; + +use crate::prelude::Vec; +use crate::psbt::raw; +use crate::psbt::serialize::Serialize; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + input::{Input, PsbtSighashType}, + output::Output, +}; + +/// A trait that describes a PSBT key-value map. +pub(super) trait Map { + /// Attempt to get all key-value pairs. + fn get_pairs(&self) -> Vec; + + /// Serialize Psbt binary map data according to BIP-0174 specification. + /// + /// := * 0x00 + /// + /// Why is the separator here 0x00 instead of 0xff? The separator here is used to distinguish between each chunk of data. + /// A separator of 0x00 would mean that the unserializer can read it as a key length of 0, which would never occur with + /// actual keys. It can thus be used as a separator and allow for easier unserializer implementation. + fn serialize_map(&self) -> Vec { + let mut buf = Vec::new(); + for pair in Map::get_pairs(self) { + buf.extend(&pair.serialize()); + } + buf.push(0x00_u8); + buf + } +} diff --git a/bitcoin/src/psbt/map/output.rs b/bitcoin/src/psbt/map/output.rs new file mode 100644 index 000000000..d48fc337d --- /dev/null +++ b/bitcoin/src/psbt/map/output.rs @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: CC0-1.0 + +use crate::bip32::KeySource; +use crate::crypto::key::XOnlyPublicKey; +use crate::prelude::{btree_map, BTreeMap, Vec}; +use crate::psbt::map::Map; +use crate::psbt::{raw, Error}; +use crate::script::{RedeemScriptBuf, WitnessScriptBuf}; +use crate::taproot::{TapLeafHash, TapTree}; + +/// Type: Redeem ScriptBuf PSBT_OUT_REDEEM_SCRIPT = 0x00 +const PSBT_OUT_REDEEM_SCRIPT: u64 = 0x00; +/// Type: Witness ScriptBuf PSBT_OUT_WITNESS_SCRIPT = 0x01 +const PSBT_OUT_WITNESS_SCRIPT: u64 = 0x01; +/// Type: BIP-0032 Derivation Path PSBT_OUT_BIP32_DERIVATION = 0x02 +const PSBT_OUT_BIP32_DERIVATION: u64 = 0x02; +/// Type: Taproot Internal Key PSBT_OUT_TAP_INTERNAL_KEY = 0x05 +const PSBT_OUT_TAP_INTERNAL_KEY: u64 = 0x05; +/// Type: Taproot Tree PSBT_OUT_TAP_TREE = 0x06 +const PSBT_OUT_TAP_TREE: u64 = 0x06; +/// Type: Taproot Key BIP-0032 Derivation Path PSBT_OUT_TAP_BIP32_DERIVATION = 0x07 +const PSBT_OUT_TAP_BIP32_DERIVATION: u64 = 0x07; +/// Type: MuSig2 Public Keys Participating in Aggregate Output PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x08 +const PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS: u64 = 0x08; +/// Type: Proprietary Use Type PSBT_OUT_PROPRIETARY = 0xFC +const PSBT_OUT_PROPRIETARY: u64 = 0xFC; + +/// A key-value map for an output of the corresponding index in the unsigned +/// transaction. +#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] +pub struct Output { + /// The redeem script for this output. + pub redeem_script: Option, + /// The witness script for this output. + pub witness_script: Option, + /// A map from public keys needed to spend this output to their + /// corresponding master key fingerprints and derivation paths. + pub bip32_derivation: BTreeMap, + /// The internal pubkey. + pub tap_internal_key: Option, + /// Taproot Output tree. + pub tap_tree: Option, + /// Map of tap root x only keys to origin info and leaf hashes contained in it. + pub tap_key_origins: BTreeMap, KeySource)>, + /// Mapping from MuSig2 aggregate keys to the participant keys from which they were aggregated. + pub musig2_participant_pubkeys: BTreeMap>, + /// Proprietary key-value pairs for this output. + pub proprietary: BTreeMap>, + /// Unknown key-value pairs for this output. + pub unknown: BTreeMap>, +} + +impl Output { + pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { + let raw::Pair { key: raw_key, value: raw_value } = pair; + + match raw_key.type_value { + PSBT_OUT_REDEEM_SCRIPT => { + impl_psbt_insert_pair! { + self.redeem_script <= | + } + } + PSBT_OUT_WITNESS_SCRIPT => { + impl_psbt_insert_pair! { + self.witness_script <= | + } + } + PSBT_OUT_BIP32_DERIVATION => { + impl_psbt_insert_pair! { + self.bip32_derivation <= | + } + } + PSBT_OUT_PROPRIETARY => { + let key = raw::ProprietaryKey::try_from(raw_key.clone())?; + match self.proprietary.entry(key) { + btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(raw_value); + } + btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)), + } + } + PSBT_OUT_TAP_INTERNAL_KEY => { + impl_psbt_insert_pair! { + self.tap_internal_key <= | + } + } + PSBT_OUT_TAP_TREE => { + impl_psbt_insert_pair! { + self.tap_tree <= | + } + } + PSBT_OUT_TAP_BIP32_DERIVATION => { + impl_psbt_insert_pair! { + self.tap_key_origins <= |< raw_value: (Vec, KeySource)> + } + } + PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS => { + impl_psbt_insert_pair! { + self.musig2_participant_pubkeys <= |< raw_value: Vec > + } + } + _ => match self.unknown.entry(raw_key) { + btree_map::Entry::Vacant(empty_key) => { + empty_key.insert(raw_value); + } + btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), + }, + } + + Ok(()) + } + + /// Combines this [`Output`] with `other` `Output` (as described by BIP 174). + pub fn combine(&mut self, other: Self) { + self.bip32_derivation.extend(other.bip32_derivation); + self.proprietary.extend(other.proprietary); + self.unknown.extend(other.unknown); + self.tap_key_origins.extend(other.tap_key_origins); + self.musig2_participant_pubkeys.extend(other.musig2_participant_pubkeys); + + combine!(redeem_script, self, other); + combine!(witness_script, self, other); + combine!(tap_internal_key, self, other); + combine!(tap_tree, self, other); + } +} + +impl Map for Output { + fn get_pairs(&self) -> Vec { + let mut rv: Vec = Default::default(); + + impl_psbt_get_pair! { + rv.push(self.redeem_script, PSBT_OUT_REDEEM_SCRIPT) + } + + impl_psbt_get_pair! { + rv.push(self.witness_script, PSBT_OUT_WITNESS_SCRIPT) + } + + impl_psbt_get_pair! { + rv.push_map(self.bip32_derivation, PSBT_OUT_BIP32_DERIVATION) + } + + impl_psbt_get_pair! { + rv.push(self.tap_internal_key, PSBT_OUT_TAP_INTERNAL_KEY) + } + + impl_psbt_get_pair! { + rv.push(self.tap_tree, PSBT_OUT_TAP_TREE) + } + + impl_psbt_get_pair! { + rv.push_map(self.tap_key_origins, PSBT_OUT_TAP_BIP32_DERIVATION) + } + + impl_psbt_get_pair! { + rv.push_map(self.musig2_participant_pubkeys, PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS) + } + + for (key, value) in self.proprietary.iter() { + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); + } + + for (key, value) in self.unknown.iter() { + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); + } + + rv + } +} + +impl_psbtmap_ser_de_serialize!(Output); diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs new file mode 100644 index 000000000..79374e71c --- /dev/null +++ b/bitcoin/src/psbt/mod.rs @@ -0,0 +1,2630 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Partially Signed Bitcoin Transactions. +//! +//! Implementation of BIP-0174 Partially Signed Bitcoin Transaction Format as +//! defined at +//! except we define PSBTs containing non-standard sighash types as invalid. + +#[macro_use] +mod macros; +mod error; +mod map; +pub mod raw; +pub mod serialize; + +use core::convert::Infallible; +use core::{cmp, fmt}; +#[cfg(feature = "std")] +use std::collections::{HashMap, HashSet}; + +use internals::write_err; +use secp256k1::{Keypair, Message}; + +use crate::bip32::{self, KeySource, Xpriv, Xpub}; +use crate::crypto::key::{PrivateKey, PublicKey}; +use crate::crypto::{ecdsa, taproot}; +use crate::key::{TapTweak, XOnlyPublicKey}; +use crate::prelude::{btree_map, BTreeMap, BTreeSet, Borrow, Box, Vec}; +use crate::script::{ScriptExt as _, ScriptPubKeyExt as _}; +use crate::sighash::{self, EcdsaSighashType, Prevouts, SighashCache}; +use crate::transaction::{self, Transaction, TransactionExt as _, TxOut}; +use crate::{Amount, FeeRate, TapLeafHash, TapSighash, TapSighashType}; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + map::{Input, Output, PsbtSighashType}, + error::Error, +}; + +/// A Partially Signed Transaction. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Psbt { + /// The unsigned transaction, scriptSigs and witnesses for each input must be empty. + pub unsigned_tx: Transaction, + /// The version number of this PSBT. If omitted, the version number is 0. + pub version: u32, + /// A global map from extended public keys to the used key fingerprint and + /// derivation path as defined by BIP 32. + pub xpub: BTreeMap, + /// Global proprietary key-value pairs. + pub proprietary: BTreeMap>, + /// Unknown global key-value pairs. + pub unknown: BTreeMap>, + + /// The corresponding key-value map for each input in the unsigned transaction. + pub inputs: Vec, + /// The corresponding key-value map for each output in the unsigned transaction. + pub outputs: Vec, +} + +impl Psbt { + /// Returns an iterator for the funding UTXOs of the psbt + /// + /// For each PSBT input that contains UTXO information `Ok` is returned containing that information. + /// The order of returned items is same as the order of inputs. + /// + /// # Errors + /// + /// The function returns error when UTXO information is not present or is invalid. + /// + /// # Panics + /// + /// The function panics if the length of transaction inputs is not equal to the length of PSBT inputs. + pub fn iter_funding_utxos(&self) -> impl Iterator> { + assert_eq!(self.inputs.len(), self.unsigned_tx.inputs.len()); + self.unsigned_tx.inputs.iter().zip(&self.inputs).map(|(tx_input, psbt_input)| { + match (&psbt_input.witness_utxo, &psbt_input.non_witness_utxo) { + (Some(witness_utxo), _) => Ok(witness_utxo), + (None, Some(non_witness_utxo)) => { + let vout = tx_input.previous_output.vout as usize; + non_witness_utxo.outputs.get(vout).ok_or(Error::PsbtUtxoOutOfbounds) + } + (None, None) => Err(Error::MissingUtxo), + } + }) + } + + /// Checks that unsigned transaction does not have scriptSig's or witness data. + fn unsigned_tx_checks(&self) -> Result<(), Error> { + for txin in &self.unsigned_tx.inputs { + if !txin.script_sig.is_empty() { + return Err(Error::UnsignedTxHasScriptSigs); + } + + if !txin.witness.is_empty() { + return Err(Error::UnsignedTxHasScriptWitnesses); + } + } + + Ok(()) + } + + /// Constructs a new PSBT from an unsigned transaction. + /// + /// # Errors + /// + /// If transactions is not unsigned. + pub fn from_unsigned_tx(tx: Transaction) -> Result { + let psbt = Self { + inputs: vec![Default::default(); tx.inputs.len()], + outputs: vec![Default::default(); tx.outputs.len()], + + unsigned_tx: tx, + xpub: Default::default(), + version: 0, + proprietary: Default::default(), + unknown: Default::default(), + }; + psbt.unsigned_tx_checks()?; + Ok(psbt) + } + + /// The default `max_fee_rate` value used for extracting transactions with [`extract_tx`] + /// + /// As of 2023, even the biggest overpayers during the highest fee markets only paid around + /// 1000 sats/vByte. 25k sats/vByte is obviously a mistake at this point. + /// + /// [`extract_tx`]: Psbt::extract_tx + pub const DEFAULT_MAX_FEE_RATE: FeeRate = FeeRate::from_sat_per_vb(25_000); + + /// An alias for [`extract_tx_fee_rate_limit`]. + /// + /// [`extract_tx_fee_rate_limit`]: Psbt::extract_tx_fee_rate_limit + #[allow(clippy::result_large_err)] // The PSBT returned in `SendingToomuch` is large. + pub fn extract_tx(self) -> Result { + self.internal_extract_tx_with_fee_rate_limit(Self::DEFAULT_MAX_FEE_RATE) + } + + /// Extracts the [`Transaction`] from a [`Psbt`] by filling in the available signature information. + /// + /// # Errors + /// + /// [`ExtractTxError`] variants will contain either the [`Psbt`] itself or the [`Transaction`] + /// that was extracted. These can be extracted from the Errors in order to recover. + /// See the error documentation for info on the variants. In general, it covers large fees. + #[allow(clippy::result_large_err)] // The PSBT returned in `SendingToomuch` is large. + pub fn extract_tx_fee_rate_limit(self) -> Result { + self.internal_extract_tx_with_fee_rate_limit(Self::DEFAULT_MAX_FEE_RATE) + } + + /// Extracts the [`Transaction`] from a [`Psbt`] by filling in the available signature information. + /// + /// # Errors + /// + /// See [`extract_tx`]. + /// + /// [`extract_tx`]: Psbt::extract_tx + #[allow(clippy::result_large_err)] // The PSBT returned in `SendingToomuch` is large. + pub fn extract_tx_with_fee_rate_limit( + self, + max_fee_rate: FeeRate, + ) -> Result { + self.internal_extract_tx_with_fee_rate_limit(max_fee_rate) + } + + /// Perform [`extract_tx_fee_rate_limit`] without the fee rate check. + /// + /// This can result in a transaction with absurdly high fees. Use with caution. + /// + /// [`extract_tx_fee_rate_limit`]: Psbt::extract_tx_fee_rate_limit + pub fn extract_tx_unchecked_fee_rate(self) -> Transaction { self.internal_extract_tx() } + + #[inline] + fn internal_extract_tx(self) -> Transaction { + let mut tx: Transaction = self.unsigned_tx; + + for (vin, psbtin) in tx.inputs.iter_mut().zip(self.inputs.into_iter()) { + vin.script_sig = psbtin.final_script_sig.unwrap_or_default(); + vin.witness = psbtin.final_script_witness.unwrap_or_default(); + } + + tx + } + + #[inline] + #[allow(clippy::result_large_err)] // The PSBT returned in `SendingToomuch` is large. + fn internal_extract_tx_with_fee_rate_limit( + self, + max_fee_rate: FeeRate, + ) -> Result { + let fee = match self.fee() { + Ok(fee) => fee, + Err(Error::MissingUtxo) => + return Err(ExtractTxError::MissingInputAmount { tx: self.internal_extract_tx() }), + Err(Error::NegativeFee) => return Err(ExtractTxError::SendingTooMuch { psbt: self }), + Err(Error::FeeOverflow) => + return Err(ExtractTxError::AbsurdFeeRate { + fee_rate: FeeRate::MAX, + tx: self.internal_extract_tx(), + }), + _ => unreachable!(), + }; + + // Note: Move prevents usage of &self from now on. + let tx = self.internal_extract_tx(); + + let fee_rate = (fee / tx.weight()).unwrap_or(FeeRate::MAX); + if fee_rate > max_fee_rate { + Err(ExtractTxError::AbsurdFeeRate { fee_rate, tx }) + } else { + Ok(tx) + } + } + + /// Combines this [`Psbt`] with `other` PSBT as described by BIP-0174. + /// + /// In accordance with BIP-0174 this function is commutative i.e., `A.combine(B) == B.combine(A)` + pub fn combine(&mut self, other: Self) -> Result<(), Error> { + if self.unsigned_tx != other.unsigned_tx { + return Err(Error::UnexpectedUnsignedTx { + expected: Box::new(self.unsigned_tx.clone()), + actual: Box::new(other.unsigned_tx), + }); + } + + // BIP-0174: The Combiner must remove any duplicate key-value pairs, in accordance with + // the specification. It can pick arbitrarily when conflicts occur. + + // Keeping the highest version + self.version = cmp::max(self.version, other.version); + + // Merging xpubs + for (xpub, (fingerprint1, derivation1)) in other.xpub { + match self.xpub.entry(xpub) { + btree_map::Entry::Vacant(entry) => { + entry.insert((fingerprint1, derivation1)); + } + btree_map::Entry::Occupied(mut entry) => { + // Here in case of the conflict we select the version with algorithm: + // 1) if everything is equal we do nothing + // 2) report an error if + // - derivation paths are equal and fingerprints are not + // - derivation paths are of the same length, but not equal + // - derivation paths has different length, but the shorter one + // is not the strict suffix of the longer one + // 3) choose longest derivation otherwise + + let (fingerprint2, derivation2) = entry.get().clone(); + + if (derivation1 == derivation2 && fingerprint1 == fingerprint2) + || (derivation1.len() < derivation2.len() + && derivation1[..] + == derivation2[derivation2.len() - derivation1.len()..]) + { + continue; + } else if derivation2.len() <= derivation1.len() + && derivation2[..] == derivation1[derivation1.len() - derivation2.len()..] + { + entry.insert((fingerprint1, derivation1)); + continue; + } + return Err(Error::CombineInconsistentKeySources(Box::new(xpub))); + } + } + } + + self.proprietary.extend(other.proprietary); + self.unknown.extend(other.unknown); + + for (self_input, other_input) in self.inputs.iter_mut().zip(other.inputs.into_iter()) { + self_input.combine(other_input); + } + + for (self_output, other_output) in self.outputs.iter_mut().zip(other.outputs.into_iter()) { + self_output.combine(other_output); + } + + Ok(()) + } + + /// Attempts to create _all_ the required signatures for this PSBT using `k`. + /// + /// If you just want to sign an input with one specific key consider using `sighash_ecdsa` or + /// `sighash_taproot`. This function does not support scripts that contain `OP_CODESEPARATOR`. + /// + /// # Returns + /// + /// A map of input index -> keys used to sign, for Taproot specifics please see [`SigningKeys`]. + /// + /// If an error is returned some signatures may already have been added to the PSBT. Since + /// `partial_sigs` is a [`BTreeMap`] it is safe to retry, previous sigs will be overwritten. + pub fn sign( + &mut self, + k: &K, + ) -> Result + where + K: GetKey, + { + let tx = self.unsigned_tx.clone(); // clone because we need to mutably borrow when signing. + let mut cache = SighashCache::new(&tx); + + let mut used = BTreeMap::new(); + let mut errors = BTreeMap::new(); + + for i in 0..self.inputs.len() { + match self.signing_algorithm(i) { + Ok(SigningAlgorithm::Ecdsa) => + match self.bip32_sign_ecdsa(k, i, &mut cache) { + Ok(v) => { + used.insert(i, SigningKeys::Ecdsa(v)); + } + Err(e) => { + errors.insert(i, e); + } + }, + Ok(SigningAlgorithm::Schnorr) => { + match self.bip32_sign_schnorr(k, i, &mut cache) { + Ok(v) => { + used.insert(i, SigningKeys::Schnorr(v)); + } + Err(e) => { + errors.insert(i, e); + } + } + } + Err(e) => { + errors.insert(i, e); + } + } + } + if errors.is_empty() { + Ok(used) + } else { + Err((used, errors)) + } + } + + /// Attempts to create all signatures required by this PSBT's `bip32_derivation` field, adding + /// them to `partial_sigs`. + /// + /// # Returns + /// + /// - Ok: A list of the public keys used in signing. + /// - Err: Error encountered trying to calculate the sighash AND we had the signing key. + fn bip32_sign_ecdsa( + &mut self, + k: &K, + input_index: usize, + cache: &mut SighashCache, + ) -> Result, SignError> + where + T: Borrow, + K: GetKey, + { + let msg_sighash_ty_res = self.sighash_ecdsa(input_index, cache); + + let input = &mut self.inputs[input_index]; // Index checked in call to `sighash_ecdsa`. + + let mut used = vec![]; // List of pubkeys used to sign the input. + + for (pk, key_source) in input.bip32_derivation.iter() { + let sk = if let Ok(Some(sk)) = k.get_key(&KeyRequest::Bip32(key_source.clone())) { + sk + } else if let Ok(Some(sk)) = k.get_key(&KeyRequest::Pubkey(PublicKey::new(*pk))) { + sk + } else { + continue; + }; + + // Only return the error if we have a secret key to sign this input. + let (msg, sighash_ty) = match msg_sighash_ty_res { + Err(e) => return Err(e), + Ok((msg, sighash_ty)) => (msg, sighash_ty), + }; + + let sig = ecdsa::Signature { + signature: secp256k1::ecdsa::sign(msg, &sk.inner), + sighash_type: sighash_ty, + }; + + let pk = sk.public_key(); + + input.partial_sigs.insert(pk, sig); + used.push(pk); + } + + Ok(used) + } + + /// Attempts to create all signatures required by this PSBT's `tap_key_origins` field, adding + /// them to `tap_key_sig` or `tap_script_sigs`. + /// + /// # Returns + /// + /// - Ok: A list of the xonly public keys used in signing. When signing a key path spend we + /// return the internal key. + /// - Err: Error encountered trying to calculate the sighash AND we had the signing key. + fn bip32_sign_schnorr( + &mut self, + k: &K, + input_index: usize, + cache: &mut SighashCache, + ) -> Result, SignError> + where + T: Borrow, + K: GetKey, + { + let mut input = self.checked_input(input_index)?.clone(); + + let mut used = vec![]; // List of pubkeys used to sign the input. + + for (&xonly, (leaf_hashes, key_source)) in input.tap_key_origins.iter() { + let sk = if let Ok(Some(secret_key)) = + k.get_key(&KeyRequest::Bip32(key_source.clone())) + { + secret_key + } else if let Ok(Some(sk)) = k.get_key(&KeyRequest::XOnlyPubkey(xonly)) { + sk + } else { + continue; + }; + + // Considering the responsibility of the PSBT's finalizer to extract valid signatures, + // the goal of this algorithm is to provide signatures to the best of our ability: + // 1) If the conditions for key path spend are met, proceed to provide the signature for key path spend + // 2) If the conditions for script path spend are met, proceed to provide the signature for script path spend + + // key path spend + if let Some(internal_key) = input.tap_internal_key { + // BIP-0371: The internal key does not have leaf hashes, so can be indicated with a hashes len of 0. + + // Based on input.tap_internal_key.is_some() alone, it is not sufficient to determine whether it is a key path spend. + // According to BIP-0371, we also need to consider the condition leaf_hashes.is_empty() for a more accurate determination. + if internal_key == xonly && leaf_hashes.is_empty() && input.tap_key_sig.is_none() { + let (sighash, sighash_type) = self.sighash_taproot(input_index, cache, None)?; + let key_pair = Keypair::from_secret_key(&sk.inner) + .tap_tweak(input.tap_merkle_root) + .to_keypair(); + + #[cfg(all(feature = "rand", feature = "std"))] + let signature = secp256k1::schnorr::sign(&sighash.to_byte_array(), &key_pair); + #[cfg(not(all(feature = "rand", feature = "std")))] + let signature = + secp256k1::schnorr::sign_no_aux_rand(&sighash.to_byte_array(), &key_pair); + + let signature = taproot::Signature { signature, sighash_type }; + input.tap_key_sig = Some(signature); + + used.push(internal_key); + } + } + + // script path spend + if let Some((leaf_hashes, _)) = input.tap_key_origins.get(&xonly) { + let leaf_hashes = leaf_hashes + .iter() + .filter(|lh| !input.tap_script_sigs.contains_key(&(xonly, **lh))) + .cloned() + .collect::>(); + + if !leaf_hashes.is_empty() { + let key_pair = Keypair::from_secret_key(&sk.inner); + + for lh in leaf_hashes { + let (sighash, sighash_type) = + self.sighash_taproot(input_index, cache, Some(lh))?; + + #[cfg(all(feature = "rand", feature = "std"))] + let signature = secp256k1::schnorr::sign(&sighash.to_byte_array(), &key_pair); + #[cfg(not(all(feature = "rand", feature = "std")))] + let signature = + secp256k1::schnorr::sign_no_aux_rand(&sighash.to_byte_array(), &key_pair); + + let signature = taproot::Signature { signature, sighash_type }; + input.tap_script_sigs.insert((xonly, lh), signature); + } + + used.push(sk.public_key().into()); + } + } + } + + self.inputs[input_index] = input; // input_index is checked above. + + Ok(used) + } + + /// Returns the sighash message to sign an ECDSA input along with the sighash type. + /// + /// Uses the [`EcdsaSighashType`] from this input if one is specified. If no sighash type is + /// specified uses [`EcdsaSighashType::All`]. This function does not support scripts that + /// contain `OP_CODESEPARATOR`. + pub fn sighash_ecdsa>( + &self, + input_index: usize, + cache: &mut SighashCache, + ) -> Result<(Message, EcdsaSighashType), SignError> { + use OutputType::*; + + if self.signing_algorithm(input_index)? != SigningAlgorithm::Ecdsa { + return Err(SignError::WrongSigningAlgorithm); + } + + let input = self.checked_input(input_index)?; + let utxo = self.spend_utxo(input_index)?; + let spk = &utxo.script_pubkey; // scriptPubkey for input spend utxo. + + let hash_ty = input.ecdsa_hash_ty().map_err(|_| SignError::InvalidSighashType)?; // Only support standard sighash types. + + match self.output_type(input_index)? { + Bare => { + let sighash = cache + .legacy_signature_hash(input_index, spk, hash_ty.to_u32()) + .expect("input checked above"); + Ok((Message::from(sighash), hash_ty)) + } + Sh => { + let script_code = + input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?; + let sighash = cache + .legacy_signature_hash(input_index, script_code, hash_ty.to_u32()) + .expect("input checked above"); + Ok((Message::from(sighash), hash_ty)) + } + Wpkh => { + let sighash = + cache.p2wpkh_signature_hash(input_index, spk, utxo.amount, hash_ty)?; + Ok((Message::from(sighash), hash_ty)) + } + ShWpkh => { + let redeem_script = input.redeem_script.as_ref().expect("checked above"); + let sighash = cache.p2wpkh_signature_hash( + input_index, + redeem_script, + utxo.amount, + hash_ty, + )?; + Ok((Message::from(sighash), hash_ty)) + } + Wsh | ShWsh => { + let witness_script = + input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?; + let sighash = cache + .p2wsh_signature_hash(input_index, witness_script, utxo.amount, hash_ty) + .map_err(SignError::SegwitV0Sighash)?; + Ok((Message::from(sighash), hash_ty)) + } + Tr => { + // This PSBT signing API is WIP, Taproot to come shortly. + Err(SignError::Unsupported) + } + } + } + + /// Returns the sighash to sign a Taproot input along with the sighash type. + /// + /// Uses the [`TapSighashType`] from this input if one is specified. If no sighash type is + /// specified uses [`TapSighashType::Default`]. + fn sighash_taproot>( + &self, + input_index: usize, + cache: &mut SighashCache, + leaf_hash: Option, + ) -> Result<(TapSighash, TapSighashType), SignError> { + use OutputType::*; + + if self.signing_algorithm(input_index)? != SigningAlgorithm::Schnorr { + return Err(SignError::WrongSigningAlgorithm); + } + + let input = self.checked_input(input_index)?; + + match self.output_type(input_index)? { + Tr => { + let hash_ty = input + .sighash_type + .unwrap_or_else(|| TapSighashType::Default.into()) + .taproot_hash_ty() + .map_err(|_| SignError::InvalidSighashType)?; + + let spend_utxos = + (0..self.inputs.len()).map(|i| self.spend_utxo(i).ok()).collect::>(); + let all_spend_utxos; + + let is_anyone_can_pay = PsbtSighashType::from(hash_ty).to_u32() & 0x80 != 0; + + let prev_outs = if is_anyone_can_pay { + Prevouts::One( + input_index, + spend_utxos[input_index].ok_or(SignError::MissingSpendUtxo)?, + ) + } else if spend_utxos.iter().all(Option::is_some) { + all_spend_utxos = spend_utxos.iter().filter_map(|x| *x).collect::>(); + Prevouts::All(&all_spend_utxos) + } else { + return Err(SignError::MissingSpendUtxo); + }; + + let sighash = if let Some(leaf_hash) = leaf_hash { + cache.taproot_script_spend_signature_hash( + input_index, + &prev_outs, + leaf_hash, + hash_ty, + )? + } else { + cache.taproot_key_spend_signature_hash(input_index, &prev_outs, hash_ty)? + }; + Ok((sighash, hash_ty)) + } + _ => Err(SignError::Unsupported), + } + } + + /// Returns the spending utxo for this PSBT's input at `input_index`. + pub fn spend_utxo(&self, input_index: usize) -> Result<&TxOut, SignError> { + let input = self.checked_input(input_index)?; + let utxo = if let Some(witness_utxo) = &input.witness_utxo { + witness_utxo + } else if let Some(non_witness_utxo) = &input.non_witness_utxo { + let vout = self.unsigned_tx.inputs[input_index].previous_output.vout; + &non_witness_utxo.outputs[vout as usize] + } else { + return Err(SignError::MissingSpendUtxo); + }; + Ok(utxo) + } + + /// Gets the input at `input_index` after checking that it is a valid index. + fn checked_input(&self, input_index: usize) -> Result<&Input, IndexOutOfBoundsError> { + // No `?` operator in const context. + match self.check_index_is_within_bounds(input_index) { + Ok(_) => Ok(&self.inputs[input_index]), + Err(e) => Err(e), + } + } + + /// Checks `input_index` is within bounds for the PSBT `inputs` array and + /// for the PSBT `unsigned_tx` `input` array. + fn check_index_is_within_bounds( + &self, + input_index: usize, + ) -> Result<(), IndexOutOfBoundsError> { + if input_index >= self.inputs.len() { + return Err(IndexOutOfBoundsError::Inputs { + index: input_index, + length: self.inputs.len(), + }); + } + + if input_index >= self.unsigned_tx.inputs.len() { + return Err(IndexOutOfBoundsError::TxInput { + index: input_index, + length: self.unsigned_tx.inputs.len(), + }); + } + + Ok(()) + } + + /// Returns the algorithm used to sign this PSBT's input at `input_index`. + fn signing_algorithm(&self, input_index: usize) -> Result { + let output_type = self.output_type(input_index)?; + Ok(output_type.signing_algorithm()) + } + + /// Returns the [`OutputType`] of the spend utxo for this PSBT's input at `input_index`. + fn output_type(&self, input_index: usize) -> Result { + let input = self.checked_input(input_index)?; + let utxo = self.spend_utxo(input_index)?; + let spk = utxo.script_pubkey.clone(); + + // Anything that is not SegWit and is not p2sh is `Bare`. + if !(spk.is_witness_program() || spk.is_p2sh()) { + return Ok(OutputType::Bare); + } + + if spk.is_p2wpkh() { + return Ok(OutputType::Wpkh); + } + + if spk.is_p2wsh() { + return Ok(OutputType::Wsh); + } + + if spk.is_p2sh() { + if input.redeem_script.as_ref().map(|s| s.is_p2wpkh()).unwrap_or(false) { + return Ok(OutputType::ShWpkh); + } + if input.redeem_script.as_ref().map(|x| x.is_p2wsh()).unwrap_or(false) { + return Ok(OutputType::ShWsh); + } + return Ok(OutputType::Sh); + } + + if spk.is_p2tr() { + return Ok(OutputType::Tr); + } + + // Something is wrong with the input scriptPubkey or we do not know how to sign + // because there has been a new softfork that we do not yet support. + Err(SignError::UnknownOutputType) + } + + /// Calculates transaction fee. + /// + /// 'Fee' being the amount that will be paid for mining a transaction with the current inputs + /// and outputs i.e., the difference in value of the total inputs and the total outputs. + /// + /// # Errors + /// + /// - [`Error::MissingUtxo`] when UTXO information for any input is not present or is invalid. + /// - [`Error::NegativeFee`] if calculated value is negative. + /// - [`Error::FeeOverflow`] if an integer overflow occurs. + pub fn fee(&self) -> Result { + let mut inputs = Amount::ZERO; + for utxo in self.iter_funding_utxos() { + inputs = inputs.checked_add(utxo?.amount).ok_or(Error::FeeOverflow)?; + } + let mut outputs = Amount::ZERO; + for out in &self.unsigned_tx.outputs { + outputs = outputs.checked_add(out.amount).ok_or(Error::FeeOverflow)?; + } + inputs.checked_sub(outputs).ok_or(Error::NegativeFee) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for Psbt { + fn serialize(&self, serializer: S) -> Result { + use crate::prelude::ToString; + + if serializer.is_human_readable() { + serializer.serialize_str(&self.to_string()) + } else { + serializer.serialize_bytes(&self.serialize()) + } + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for Psbt { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + + impl serde::de::Visitor<'_> for Visitor { + type Value = Psbt; + + fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "a psbt") + } + + fn visit_bytes(self, bytes: &[u8]) -> Result { + Psbt::deserialize(bytes).map_err(|e| serde::de::Error::custom(e)) + } + + fn visit_str(self, s: &str) -> Result { + s.parse().map_err(|e| serde::de::Error::custom(e)) + } + } + + if deserializer.is_human_readable() { + deserializer.deserialize_str(Visitor) + } else { + deserializer.deserialize_bytes(Visitor) + } + } +} + +/// Data required to call [`GetKey`] to get the private key to sign an input. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum KeyRequest { + /// Request a private key using the associated public key. + Pubkey(PublicKey), + /// Request a private key using BIP-0032 fingerprint and derivation path. + Bip32(KeySource), + /// Request a private key using the associated x-only public key. + XOnlyPubkey(XOnlyPublicKey), +} + +/// Trait to get a private key from a key request, key is then used to sign an input. +pub trait GetKey { + /// An error occurred while getting the key. + type Error: core::fmt::Debug; + + /// Attempts to get the private key for `key_request`. + /// + /// # Returns + /// + /// - `Some(key)` if the key is found. + /// - `None` if the key was not found but no error was encountered. + /// - `Err` if an error was encountered while looking for the key. + fn get_key( + &self, + key_request: &KeyRequest, + ) -> Result, Self::Error>; +} + +impl GetKey for Xpriv { + type Error = GetKeyError; + + fn get_key( + &self, + key_request: &KeyRequest, + ) -> Result, Self::Error> { + match key_request { + KeyRequest::Pubkey(_) => Err(GetKeyError::NotSupported), + KeyRequest::XOnlyPubkey(_) => Err(GetKeyError::NotSupported), + KeyRequest::Bip32((fingerprint, path)) => { + let key = if self.fingerprint() == *fingerprint { + let k = self.derive_xpriv(path).map_err(GetKeyError::Bip32)?; + Some(k.to_private_key()) + } else if self.parent_fingerprint == *fingerprint + && !path.is_empty() + && path[0] == self.child_number + { + let k = self.derive_xpriv(&path[1..]).map_err(GetKeyError::Bip32)?; + Some(k.to_private_key()) + } else { + None + }; + Ok(key) + } + } + } +} + +/// Map of input index -> signing key for that input (see [`SigningKeys`]). +pub type SigningKeysMap = BTreeMap; + +/// A list of keys used to sign an input. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum SigningKeys { + /// Keys used to sign an ECDSA input. + Ecdsa(Vec), + /// Keys used to sign a Taproot input. + /// + /// - Key path spend: This is the internal key. + /// - Script path spend: This is the pubkey associated with the secret key that signed. + Schnorr(Vec), +} + +/// Map of input index -> the error encountered while attempting to sign that input. +pub type SigningErrors = BTreeMap; + +#[rustfmt::skip] +macro_rules! impl_get_key_for_set { + ($set:ident) => { + +impl GetKey for $set { + type Error = GetKeyError; + + fn get_key( + &self, + key_request: &KeyRequest, + ) -> Result, Self::Error> { + // OK to stop at the first error because Xpriv::get_key() can only fail + // if this isn't a KeyRequest::Bip32, which would fail for all Xprivs. + self.iter() + .find_map(|xpriv| xpriv.get_key(key_request).transpose()) + .transpose() + } +}}} +impl_get_key_for_set!(Vec); +impl_get_key_for_set!(BTreeSet); +#[cfg(feature = "std")] +impl_get_key_for_set!(HashSet); + +#[rustfmt::skip] +macro_rules! impl_get_key_for_pubkey_map { + ($map:ident) => { + +impl GetKey for $map { + type Error = GetKeyError; + + fn get_key( + &self, + key_request: &KeyRequest, + ) -> Result, Self::Error> { + match key_request { + KeyRequest::Pubkey(pk) => Ok(self.get(&pk).cloned()), + KeyRequest::XOnlyPubkey(xonly) => { + let pubkey_even = xonly.public_key(secp256k1::Parity::Even); + let key = self.get(&pubkey_even).cloned(); + + if key.is_some() { + return Ok(key); + } + + let pubkey_odd = xonly.public_key(secp256k1::Parity::Odd); + if let Some(priv_key) = self.get(&pubkey_odd).copied() { + let negated_priv_key = priv_key.negate(); + return Ok(Some(negated_priv_key)); + } + + Ok(None) + }, + KeyRequest::Bip32(_) => Err(GetKeyError::NotSupported), + } + } +}}} +impl_get_key_for_pubkey_map!(BTreeMap); +#[cfg(feature = "std")] +impl_get_key_for_pubkey_map!(HashMap); + +#[rustfmt::skip] +macro_rules! impl_get_key_for_xonly_map { + ($map:ident) => { + +impl GetKey for $map { + type Error = GetKeyError; + + fn get_key( + &self, + key_request: &KeyRequest, + ) -> Result, Self::Error> { + match key_request { + KeyRequest::XOnlyPubkey(xonly) => Ok(self.get(xonly).cloned()), + KeyRequest::Pubkey(pk) => { + let (xonly, parity) = pk.inner.x_only_public_key(); + + if let Some(mut priv_key) = self.get(&XOnlyPublicKey::from(xonly)).cloned() { + let computed_pk = priv_key.public_key(); + let (_, computed_parity) = computed_pk.inner.x_only_public_key(); + + if computed_parity != parity { + priv_key = priv_key.negate(); + } + + return Ok(Some(priv_key)); + } + + Ok(None) + }, + KeyRequest::Bip32(_) => Err(GetKeyError::NotSupported), + } + } +}}} +impl_get_key_for_xonly_map!(BTreeMap); +#[cfg(feature = "std")] +impl_get_key_for_xonly_map!(HashMap); + +/// Errors when getting a key. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum GetKeyError { + /// A bip32 derivation error. + Bip32(bip32::DerivationError), + /// The GetKey operation is not supported for this key request. + NotSupported, +} + +impl From for GetKeyError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for GetKeyError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Bip32(ref e) => write_err!(f, "bip32 derivation"; e), + Self::NotSupported => + f.write_str("the GetKey operation is not supported for this key request"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for GetKeyError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::NotSupported => None, + Self::Bip32(ref e) => Some(e), + } + } +} + +/// The various output types supported by the Bitcoin network. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum OutputType { + /// An output of type: pay-to-pubkey or pay-to-pubkey-hash. + Bare, + /// A pay-to-witness-pubkey-hash output (P2WPKH). + Wpkh, + /// A pay-to-witness-script-hash output (P2WSH). + Wsh, + /// A nested SegWit output, pay-to-witness-pubkey-hash nested in a pay-to-script-hash. + ShWpkh, + /// A nested SegWit output, pay-to-witness-script-hash nested in a pay-to-script-hash. + ShWsh, + /// A pay-to-script-hash output excluding wrapped SegWit (P2SH). + Sh, + /// A Taproot output (P2TR). + Tr, +} + +impl OutputType { + /// The signing algorithm used to sign this output type. + pub fn signing_algorithm(&self) -> SigningAlgorithm { + use OutputType::*; + + match self { + Bare | Wpkh | Wsh | ShWpkh | ShWsh | Sh => SigningAlgorithm::Ecdsa, + Tr => SigningAlgorithm::Schnorr, + } + } +} + +/// Signing algorithms supported by the Bitcoin network. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum SigningAlgorithm { + /// The Elliptic Curve Digital Signature Algorithm (see [wikipedia]). + /// + /// [wikipedia]: https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm + Ecdsa, + /// The Schnorr signature algorithm (see [wikipedia]). + /// + /// [wikipedia]: https://en.wikipedia.org/wiki/Schnorr_signature + Schnorr, +} + +/// Errors encountered while calculating the sighash message. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum SignError { + /// Input index out of bounds. + IndexOutOfBounds(IndexOutOfBoundsError), + /// Invalid Sighash type. + InvalidSighashType, + /// Missing input utxo. + MissingInputUtxo, + /// Missing Redeem script. + MissingRedeemScript, + /// Missing spending utxo. + MissingSpendUtxo, + /// Missing witness script. + MissingWitnessScript, + /// Signing algorithm and key type does not match. + MismatchedAlgoKey, + /// Attempted to ECDSA sign a non-ECDSA input. + NotEcdsa, + /// The `scriptPubkey` is not a P2WPKH script. + NotWpkh, + /// Sighash computation error (SegWit v0 input). + SegwitV0Sighash(transaction::InputsIndexError), + /// Sighash computation error (p2wpkh input). + P2wpkhSighash(sighash::P2wpkhError), + /// Sighash computation error (Taproot input). + TaprootError(sighash::TaprootError), + /// Unable to determine the output type. + UnknownOutputType, + /// Unable to find key. + KeyNotFound, + /// Attempt to sign an input with the wrong signing algorithm. + WrongSigningAlgorithm, + /// Signing request currently unsupported. + Unsupported, +} + +impl From for SignError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for SignError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::IndexOutOfBounds(ref e) => write_err!(f, "index out of bounds"; e), + Self::InvalidSighashType => write!(f, "invalid sighash type"), + Self::MissingInputUtxo => write!(f, "missing input utxo in PSBT"), + Self::MissingRedeemScript => write!(f, "missing redeem script"), + Self::MissingSpendUtxo => write!(f, "missing spend utxo in PSBT"), + Self::MissingWitnessScript => write!(f, "missing witness script"), + Self::MismatchedAlgoKey => write!(f, "signing algorithm and key type does not match"), + Self::NotEcdsa => write!(f, "attempted to ECDSA sign a non-ECDSA input"), + Self::NotWpkh => write!(f, "the scriptPubkey is not a P2WPKH script"), + Self::SegwitV0Sighash(ref e) => write_err!(f, "SegWit v0 sighash"; e), + Self::P2wpkhSighash(ref e) => write_err!(f, "p2wpkh sighash"; e), + Self::TaprootError(ref e) => write_err!(f, "Taproot sighash"; e), + Self::UnknownOutputType => write!(f, "unable to determine the output type"), + Self::KeyNotFound => write!(f, "unable to find key"), + Self::WrongSigningAlgorithm => + write!(f, "attempt to sign an input with the wrong signing algorithm"), + Self::Unsupported => write!(f, "signing request currently unsupported"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SignError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::SegwitV0Sighash(ref e) => Some(e), + Self::P2wpkhSighash(ref e) => Some(e), + Self::TaprootError(ref e) => Some(e), + Self::IndexOutOfBounds(ref e) => Some(e), + Self::InvalidSighashType + | Self::MissingInputUtxo + | Self::MissingRedeemScript + | Self::MissingSpendUtxo + | Self::MissingWitnessScript + | Self::MismatchedAlgoKey + | Self::NotEcdsa + | Self::NotWpkh + | Self::UnknownOutputType + | Self::KeyNotFound + | Self::WrongSigningAlgorithm + | Self::Unsupported => None, + } + } +} + +impl From for SignError { + fn from(e: sighash::P2wpkhError) -> Self { Self::P2wpkhSighash(e) } +} + +impl From for SignError { + fn from(e: IndexOutOfBoundsError) -> Self { Self::IndexOutOfBounds(e) } +} + +impl From for SignError { + fn from(e: sighash::TaprootError) -> Self { Self::TaprootError(e) } +} + +/// This error is returned when extracting a [`Transaction`] from a [`Psbt`]. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ExtractTxError { + /// The [`FeeRate`] is too high + AbsurdFeeRate { + /// The [`FeeRate`] + fee_rate: FeeRate, + /// The extracted [`Transaction`] (use this to ignore the error) + tx: Transaction, + }, + /// One or more of the inputs lacks amount information (witness_utxo or non_witness_utxo) + MissingInputAmount { + /// The extracted [`Transaction`] (use this to ignore the error) + tx: Transaction, + }, + /// Input amount is less than output amount, and the [`Transaction`] would be invalid. + SendingTooMuch { + /// The original [`Psbt`] is returned untouched. + psbt: Psbt, + }, +} + +impl From for ExtractTxError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for ExtractTxError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::AbsurdFeeRate { fee_rate, .. } => write!( + f, + "an absurdly high fee rate of {} sat/kwu", + fee_rate.to_sat_per_kwu_floor() + ), + Self::MissingInputAmount { .. } => write!( + f, + "one of the inputs lacked amount information (witness_utxo or non_witness_utxo)" + ), + Self::SendingTooMuch { .. } => write!( + f, + "transaction would be invalid due to output amount being greater than input amount." + ), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ExtractTxError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::AbsurdFeeRate { .. } + | Self::MissingInputAmount { .. } + | Self::SendingTooMuch { .. } => None, + } + } +} + +/// Input index out of bounds (actual index, maximum index allowed). +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum IndexOutOfBoundsError { + /// The index is out of bounds for the `psbt.inputs` vector. + Inputs { + /// Attempted index access. + index: usize, + /// Length of the PSBT inputs vector. + length: usize, + }, + /// The index is out of bounds for the `psbt.unsigned_tx.input` vector. + TxInput { + /// Attempted index access. + index: usize, + /// Length of the PSBT's unsigned transaction input vector. + length: usize, + }, +} + +impl From for IndexOutOfBoundsError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for IndexOutOfBoundsError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Inputs { ref index, ref length } => write!( + f, + "index {} is out-of-bounds for PSBT inputs vector length {}", + index, length + ), + Self::TxInput { ref index, ref length } => write!( + f, + "index {} is out-of-bounds for PSBT unsigned tx input vector length {}", + index, length + ), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for IndexOutOfBoundsError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Inputs { .. } | Self::TxInput { .. } => None, + } + } +} + +#[cfg(feature = "base64")] +mod display_from_str { + use core::convert::Infallible; + use core::fmt; + use core::str::FromStr; + + use base64::display::Base64Display; + use base64::prelude::{Engine as _, BASE64_STANDARD}; + use internals::write_err; + + use super::{Error, Psbt}; + + /// Error encountered during PSBT decoding from Base64 string. + #[derive(Debug)] + #[non_exhaustive] + pub enum PsbtParseError { + /// Error in internal PSBT data structure. + PsbtEncoding(Error), + /// Error in PSBT Base64 encoding. + Base64Encoding(::base64::DecodeError), + } + + impl From for PsbtParseError { + fn from(never: Infallible) -> Self { match never {} } + } + + impl fmt::Display for PsbtParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::PsbtEncoding(ref e) => + write_err!(f, "error in internal PSBT data structure"; e), + Self::Base64Encoding(ref e) => write_err!(f, "error in PSBT base64 encoding"; e), + } + } + } + + #[cfg(feature = "std")] + impl std::error::Error for PsbtParseError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::PsbtEncoding(e) => Some(e), + Self::Base64Encoding(e) => Some(e), + } + } + } + + impl fmt::Display for Psbt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", Base64Display::new(&self.serialize(), &BASE64_STANDARD)) + } + } + + impl FromStr for Psbt { + type Err = PsbtParseError; + + fn from_str(s: &str) -> Result { + let data = BASE64_STANDARD.decode(s).map_err(PsbtParseError::Base64Encoding)?; + Self::deserialize(&data).map_err(PsbtParseError::PsbtEncoding) + } + } +} +#[cfg(feature = "base64")] +pub use self::display_from_str::PsbtParseError; + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use hashes::{hash160, ripemd160, sha256}; + use hex::FromHex; + use hex_lit::hex; + #[cfg(all(feature = "rand", feature = "std"))] + use { + crate::bip32::Fingerprint, + crate::locktime, + crate::script::ScriptPubKeyBufExt as _, + crate::witness_version::WitnessVersion, + crate::WitnessProgram, + secp256k1::SecretKey, + }; + + use super::*; + use crate::bip32::{ChildNumber, DerivationPath}; + use crate::locktime::absolute; + use crate::network::NetworkKind; + use crate::psbt::serialize::{Deserialize, Serialize}; + use crate::script::{ + RedeemScriptBuf, ScriptBufExt as _, ScriptPubKeyBuf, ScriptSigBuf, WitnessScriptBuf, + }; + use crate::transaction::{self, OutPoint, TxIn}; + use crate::witness::Witness; + use crate::Sequence; + + #[track_caller] + pub fn hex_psbt(s: &str) -> Result { + let r = Vec::from_hex(s); + match r { + Err(_e) => panic!("unable to parse hex string {}", s), + Ok(v) => Psbt::deserialize(&v), + } + } + + #[track_caller] + fn psbt_with_amounts(input: u64, output: u64) -> Psbt { + Psbt { + unsigned_tx: Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126" + .parse() + .unwrap(), + vout: 0, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + }], + outputs: vec![TxOut { + amount: Amount::from_sat(output).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(), + }], + }, + xpub: Default::default(), + version: 0, + proprietary: BTreeMap::new(), + unknown: BTreeMap::new(), + + inputs: vec![Input { + witness_utxo: Some(TxOut { + amount: Amount::from_sat(input).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587", + ) + .unwrap(), + }), + ..Default::default() + }], + outputs: vec![], + } + } + + #[test] + fn trivial_psbt() { + let psbt = Psbt { + unsigned_tx: Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![], + outputs: vec![], + }, + xpub: Default::default(), + version: 0, + proprietary: BTreeMap::new(), + unknown: BTreeMap::new(), + + inputs: vec![], + outputs: vec![], + }; + assert_eq!(psbt.serialize_hex(), "70736274ff01000a0200000000000000000000"); + } + + #[test] + fn psbt_uncompressed_key() { + let psbt = hex_psbt("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); + assert!(psbt.inputs[0].partial_sigs.len() == 1); + let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; + assert!(!pk.compressed); + } + + #[test] + fn psbt_high_fee_checks() { + let psbt = psbt_with_amounts(Amount::MAX.to_sat(), 1000); + + // We cannot create an expected fee rate to test against because `FeeRate::from_sat_per_mvb` is private. + // Large fee rate errors if we pass in 1 sat/vb so just use this to get the error fee rate returned. + let error_fee_rate = psbt + .clone() + .extract_tx_with_fee_rate_limit(FeeRate::from_sat_per_vb(1)) + .map_err(|e| match e { + ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate, + other => panic!("expected AbsurdFeeRate error, got {other:?}"), + }) + .unwrap_err(); + + // In `internal_extract_tx_with_fee_rate_limit` when we do fee / weight + // we manually saturate to `FeeRate::MAX`. + assert!(psbt.clone().extract_tx_with_fee_rate_limit(FeeRate::MAX).is_ok()); + + // These error because the fee rate is above the limit as expected. + assert_eq!( + psbt.clone().extract_tx().map_err(|e| match e { + ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate, + other => panic!("expected AbsurdFeeRate error, got {other:?}"), + }), + Err(error_fee_rate) + ); + assert_eq!( + psbt.extract_tx_fee_rate_limit().map_err(|e| match e { + ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate, + other => panic!("expected AbsurdFeeRate error, got {other:?}"), + }), + Err(error_fee_rate) + ); + + // No one is using an ~50 BTC fee so if we can handle this + // then the `FeeRate` restrictions are fine for PSBT usage. + let psbt = psbt_with_amounts(Amount::from_btc_u16(50).to_sat(), 1000); // fee = 50 BTC - 1000 sats + assert!(psbt.extract_tx_with_fee_rate_limit(FeeRate::MAX).is_ok()); + + // Testing that extract_tx will error at 25k sat/vbyte (6250000 sat/kwu) + assert_eq!( + psbt_with_amounts(2076001, 1000).extract_tx().map_err(|e| match e { + ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate, + other => panic!("expected AbsurdFeeRate error, got {other:?}"), + }), + Err(FeeRate::from_sat_per_kwu(6250003)) // 6250000 is 25k sat/vbyte + ); + + // Lowering the input satoshis by 1 lowers the sat/kwu by 3 + // Putting it exactly at 25k sat/vbyte + assert!(psbt_with_amounts(2076000, 1000).extract_tx().is_ok()); + } + + #[test] + fn serialize_then_deserialize_output() { + let seed = hex!("000102030405060708090a0b0c0d0e0f"); + + let mut hd_keypaths: BTreeMap = Default::default(); + + let mut sk: Xpriv = Xpriv::new_master(NetworkKind::Main, &seed); + + let fprint = sk.fingerprint(); + + let dpath: Vec = vec![ + ChildNumber::ZERO_NORMAL, + ChildNumber::ONE_NORMAL, + ChildNumber::from_normal_idx(2).unwrap(), + ChildNumber::from_normal_idx(4).unwrap(), + ChildNumber::from_normal_idx(42).unwrap(), + ChildNumber::from_hardened_idx(69).unwrap(), + ChildNumber::from_normal_idx(420).unwrap(), + ChildNumber::from_normal_idx(31337).unwrap(), + ]; + + sk = sk.derive_xpriv(&dpath).unwrap(); + + let pk = Xpub::from_xpriv(&sk); + + hd_keypaths.insert(pk.public_key, (fprint, dpath.into())); + + let expected: Output = Output { + redeem_script: Some( + RedeemScriptBuf::from_hex_no_length_prefix( + "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac", + ) + .unwrap(), + ), + witness_script: Some( + WitnessScriptBuf::from_hex_no_length_prefix( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(), + ), + bip32_derivation: hd_keypaths, + ..Default::default() + }; + + let actual = Output::deserialize(&expected.serialize()).unwrap(); + + assert_eq!(expected, actual); + } + + #[test] + fn serialize_then_deserialize_global() { + let expected = Psbt { + unsigned_tx: Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::from_consensus(1257139), + inputs: vec![TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126" + .parse() + .unwrap(), + vout: 0, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + }], + outputs: vec![ + TxOut { + amount: Amount::from_sat_u32(99_999_699), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix( + "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac", + ) + .unwrap(), + }, + TxOut { + amount: Amount::from_sat_u32(100_000_000), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(), + }, + ], + }, + xpub: Default::default(), + version: 0, + proprietary: Default::default(), + unknown: Default::default(), + inputs: vec![Input::default()], + outputs: vec![Output::default(), Output::default()], + }; + + let actual: Psbt = Psbt::deserialize(&expected.serialize()).unwrap(); + assert_eq!(expected, actual); + } + + #[test] + fn serialize_then_deserialize_psbtkvpair() { + let expected = raw::Pair { + key: raw::Key { type_value: 0u64, key_data: vec![42u8, 69u8] }, + value: vec![69u8, 42u8, 4u8], + }; + + let actual = raw::Pair::deserialize(&expected.serialize()).unwrap(); + + assert_eq!(expected, actual); + } + + #[test] + fn deserialize_and_serialize_psbt_with_two_partial_sigs() { + let hex = "70736274ff0100890200000001207ae985d787dfe6143d5c58fad79cc7105e0e799fcf033b7f2ba17e62d7b3200000000000ffffffff02563d03000000000022002019899534b9a011043c0dd57c3ff9a381c3522c5f27c6a42319085b56ca543a1d6adc020000000000220020618b47a07ebecca4e156edb1b9ea7c24bdee0139fc049237965ffdaf56d5ee73000000000001012b801a0600000000002200201148e93e9315e37dbed2121be5239257af35adc03ffdfc5d914b083afa44dab82202025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee076473044022007e06b362e89912abd4661f47945430739b006a85d1b2a16c01dc1a4bd07acab022061576d7aa834988b7ab94ef21d8eebd996ea59ea20529a19b15f0c9cebe3d8ac01220202b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a473044022002787f926d6817504431ee281183b8119b6845bfaa6befae45e13b6d430c9d2f02202859f149a6cd26ae2f03a107e7f33c7d91730dade305fe077bae677b5d44952a01010547522102b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a21025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee07652ae0001014752210283ef76537f2d58ae3aa3a4bd8ae41c3f230ccadffb1a0bd3ca504d871cff05e7210353d79cc0cb1396f4ce278d005f16d948e02a6aec9ed1109f13747ecb1507b37b52ae00010147522102b3937241777b6665e0d694e52f9c1b188433641df852da6fc42187b5d8a368a321034cdd474f01cc5aa7ff834ad8bcc882a87e854affc775486bc2a9f62e8f49bd7852ae00"; + let psbt = hex_psbt(hex).unwrap(); + assert_eq!(hex, psbt.serialize_hex()); + } + + #[cfg(feature = "serde")] + #[test] + fn serde_psbt() { + //! Create a full PSBT value with various fields filled and make sure it can be JSONized. + use hashes::sha256d; + + use crate::psbt::map::Input; + + // create some values to use in the PSBT + let tx = Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389" + .parse() + .unwrap(), + vout: 1, + }, + script_sig: ScriptSigBuf::from_hex_no_length_prefix( + "160014be18d152a9b012039daf3da7de4f53349eecb985", + ) + .unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[hex!( + "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105" + )]), + }], + outputs: vec![TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587", + ) + .unwrap(), + }], + }; + let unknown: BTreeMap> = + vec![(raw::Key { type_value: 42, key_data: vec![0, 1] }, vec![3, 4, 5])] + .into_iter() + .collect(); + let key_source = ("deadbeef".parse().unwrap(), "0'/1".parse().unwrap()); + let keypaths: BTreeMap = vec![( + "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), + key_source.clone(), + )] + .into_iter() + .collect(); + + let proprietary: BTreeMap> = vec![( + raw::ProprietaryKey { + prefix: "prefx".as_bytes().to_vec(), + subtype: 42, + key: "test_key".as_bytes().to_vec(), + }, + vec![5, 6, 7], + )] + .into_iter() + .collect(); + + let psbt = Psbt { + version: 0, + xpub: { + let xpub: Xpub = + "xpub661MyMwAqRbcGoRVtwfvzZsq2VBJR1LAHfQstHUoxqDorV89vRoMxUZ27kLrraAj6MPi\ + QfrDb27gigC1VS1dBXi5jGpxmMeBXEkKkcXUTg4".parse().unwrap(); + vec![(xpub, key_source)].into_iter().collect() + }, + unsigned_tx: { + let mut unsigned = tx.clone(); + unsigned.inputs[0].previous_output.txid = tx.compute_txid(); + unsigned.inputs[0].script_sig = ScriptSigBuf::new(); + unsigned.inputs[0].witness = Witness::default(); + unsigned + }, + proprietary: proprietary.clone(), + unknown: unknown.clone(), + + inputs: vec![ + Input { + non_witness_utxo: Some(tx), + witness_utxo: Some(TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + }), + sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap()), + redeem_script: Some(vec![0x51].into()), + witness_script: None, + partial_sigs: vec![( + "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), + "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(), + )].into_iter().collect(), + bip32_derivation: keypaths.clone(), + final_script_witness: Some(Witness::from_slice(&[vec![1, 3], vec![5]])), + ripemd160_preimages: vec![(ripemd160::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + sha256_preimages: vec![(sha256::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + hash160_preimages: vec![(hash160::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + hash256_preimages: vec![(sha256d::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + proprietary: proprietary.clone(), + unknown: unknown.clone(), + ..Default::default() + } + ], + outputs: vec![ + Output { + bip32_derivation: keypaths, + proprietary, + unknown, + ..Default::default() + } + ], + }; + let encoded = serde_json::to_string(&psbt).unwrap(); + let decoded: Psbt = serde_json::from_str(&encoded).unwrap(); + assert_eq!(psbt, decoded); + } + + mod bip_vectors { + use super::*; + use crate::psbt::map::Map; + + #[test] + #[should_panic(expected = "InvalidMagic")] + fn invalid_vector_1() { + hex_psbt("0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300").unwrap(); + } + + #[cfg(feature = "base64")] + #[test] + #[should_panic(expected = "InvalidMagic")] + fn invalid_vector_1_base64() { + "AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA==".parse::().unwrap(); + } + + #[test] + #[should_panic(expected = "ConsensusEncoding")] + fn invalid_vector_2() { + hex_psbt("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000") + .unwrap(); + } + + #[cfg(feature = "base64")] + #[test] + #[should_panic(expected = "ConsensusEncoding")] + fn invalid_vector_2_base64() { + "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==".parse::() + .unwrap(); + } + + #[test] + #[should_panic(expected = "UnsignedTxHasScriptSigs")] + fn invalid_vector_3() { + hex_psbt("70736274ff0100fd0a010200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be4000000006a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa88292feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap(); + } + + #[cfg(feature = "base64")] + #[test] + #[should_panic(expected = "UnsignedTxHasScriptSigs")] + fn invalid_vector_3_base64() { + "cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA=".parse::().unwrap(); + } + + #[test] + #[should_panic(expected = "MustHaveUnsignedTx")] + fn invalid_vector_4() { + hex_psbt("70736274ff000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000").unwrap(); + } + + #[cfg(feature = "base64")] + #[test] + #[should_panic(expected = "MustHaveUnsignedTx")] + fn invalid_vector_4_base64() { + "cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==".parse::().unwrap(); + } + + #[test] + #[should_panic(expected = "DuplicateKey(Key { type_value: 0, key_data: [] })")] + fn invalid_vector_5() { + hex_psbt("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000000").unwrap(); + } + + #[cfg(feature = "base64")] + #[test] + #[should_panic(expected = "DuplicateKey(Key { type_value: 0, key_data: [] })")] + fn invalid_vector_5_base64() { + "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQA/AgAAAAH//////////////////////////////////////////wAAAAAA/////wEAAAAAAAAAAANqAQAAAAAAAAAA".parse::().unwrap(); + } + + #[test] + fn valid_vector_1() { + let unserialized = Psbt { + unsigned_tx: Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::from_consensus(1257139), + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), + vout: 0, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + } + ], + outputs: vec![ + TxOut { + amount: Amount::from_sat_u32(99_999_699), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), + }, + TxOut { + amount: Amount::from_sat_u32(100_000_000), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), + }, + ], + }, + xpub: Default::default(), + version: 0, + proprietary: BTreeMap::new(), + unknown: BTreeMap::new(), + + inputs: vec![ + Input { + non_witness_utxo: Some(Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), + vout: 1, + }, + script_sig: ScriptSigBuf::from_hex_no_length_prefix("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").as_slice(), + hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").as_slice(), + ]), + }, + TxIn { + previous_output: OutPoint { + txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(), + vout: 1, + }, + script_sig: ScriptSigBuf::from_hex_no_length_prefix("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").as_slice(), + hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").as_slice(), + ]), + } + ], + outputs: vec![ + TxOut { + amount: Amount::from_sat_u32(200_000_000), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(), + }, + TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + }, + ], + }), + ..Default::default() + }, + ], + outputs: vec![ + Output { + ..Default::default() + }, + Output { + ..Default::default() + }, + ], + }; + + let base16str = "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000"; + + assert_eq!(unserialized.serialize_hex(), base16str); + assert_eq!(unserialized, hex_psbt(base16str).unwrap()); + + #[cfg(feature = "base64")] + { + let base64str = "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA"; + assert_eq!(base64str.parse::().unwrap(), unserialized); + assert_eq!(base64str, unserialized.to_string()); + assert_eq!(base64str.parse::().unwrap(), hex_psbt(base16str).unwrap()); + } + } + + #[test] + fn valid_vector_2() { + let psbt = hex_psbt("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap(); + + assert_eq!(psbt.inputs.len(), 2); + assert_eq!(psbt.outputs.len(), 2); + + assert!(&psbt.inputs[0].final_script_sig.is_some()); + + let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); + let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(); + + assert!(redeem_script.is_p2wpkh()); + assert_eq!( + redeem_script.to_p2sh().unwrap(), + psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey + ); + assert_eq!(redeem_script.to_p2sh().unwrap(), expected_out); + + for output in psbt.outputs { + assert_eq!(output.get_pairs().len(), 0) + } + } + + #[test] + fn valid_vector_3() { + let psbt = hex_psbt("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000").unwrap(); + + assert_eq!(psbt.inputs.len(), 1); + assert_eq!(psbt.outputs.len(), 2); + + let tx_input = &psbt.unsigned_tx.inputs[0]; + let psbt_non_witness_utxo = psbt.inputs[0].non_witness_utxo.as_ref().unwrap(); + + assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.compute_txid()); + assert!(psbt_non_witness_utxo.outputs[tx_input.previous_output.vout as usize] + .script_pubkey + .is_p2pkh()); + assert_eq!( + psbt.inputs[0].sighash_type.as_ref().unwrap().ecdsa_hash_ty().unwrap(), + EcdsaSighashType::All + ); + } + + #[test] + fn valid_vector_4() { + let psbt = hex_psbt("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000").unwrap(); + + assert_eq!(psbt.inputs.len(), 2); + assert_eq!(psbt.outputs.len(), 2); + + assert!(&psbt.inputs[0].final_script_sig.is_none()); + assert!(&psbt.inputs[1].final_script_sig.is_none()); + + let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); + let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(); + + assert!(redeem_script.is_p2wpkh()); + assert_eq!( + redeem_script.to_p2sh().unwrap(), + psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey + ); + assert_eq!(redeem_script.to_p2sh().unwrap(), expected_out); + + for output in psbt.outputs { + assert!(!output.get_pairs().is_empty()) + } + } + + #[test] + fn valid_vector_5() { + let psbt = hex_psbt("70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000").unwrap(); + + assert_eq!(psbt.inputs.len(), 1); + assert_eq!(psbt.outputs.len(), 1); + + assert!(&psbt.inputs[0].final_script_sig.is_none()); + + let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap(); + let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix( + "a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87", + ) + .unwrap(); + + assert!(redeem_script.is_p2wsh()); + assert_eq!( + redeem_script.to_p2sh().unwrap(), + psbt.inputs[0].witness_utxo.as_ref().unwrap().script_pubkey + ); + + assert_eq!(redeem_script.to_p2sh().unwrap(), expected_out); + } + + #[test] + fn valid_vector_6() { + let psbt = hex_psbt("70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000").unwrap(); + + assert_eq!(psbt.inputs.len(), 1); + assert_eq!(psbt.outputs.len(), 1); + + let tx = &psbt.unsigned_tx; + assert_eq!( + tx.compute_txid(), + "75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115".parse().unwrap(), + ); + + let mut unknown: BTreeMap> = BTreeMap::new(); + let key: raw::Key = + raw::Key { type_value: 0x0fu64, key_data: hex!("010203040506070809").to_vec() }; + let value = hex!("0102030405060708090a0b0c0d0e0f").to_vec(); + + unknown.insert(key, value); + + assert_eq!(psbt.inputs[0].unknown, unknown) + } + } + + mod bip_371_vectors { + use super::*; + + #[test] + fn invalid_vectors() { + let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a075701172102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232000000").unwrap_err(); + assert_eq!(err.to_string(), "invalid xonly public key"); + let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011342173bb3d36c074afb716fec6307a069a2e450b995f3c82785945ab8df0e24260dcd703b0cbf34de399184a9481ac2b3586db6601f026a77f7e4938481bc34751701aa000000").unwrap_err(); + #[cfg(feature = "std")] + assert_eq!(err.to_string(), "invalid Taproot signature"); + #[cfg(not(feature = "std"))] + assert_eq!( + err.to_string(), + "invalid Taproot signature: invalid Taproot signature size: 66" + ); + let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err(); + assert_eq!(err.to_string(), "invalid xonly public key"); + let err = hex_psbt("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000001052102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa23200").unwrap_err(); + assert_eq!(err.to_string(), "invalid xonly public key"); + let err = hex_psbt("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07570000220702fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da7560000800100008000000080010000000000000000").unwrap_err(); + assert_eq!(err.to_string(), "invalid xonly public key"); + let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6924214022cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094089756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err(); + #[cfg(feature = "std")] + assert_eq!(err.to_string(), "invalid hash when parsing slice"); + #[cfg(not(feature = "std"))] + assert_eq!( + err.to_string(), + "invalid hash when parsing slice: could not convert slice to array" + ); + let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err(); + #[cfg(feature = "std")] + assert_eq!(err.to_string(), "invalid Taproot signature"); + #[cfg(not(feature = "std"))] + assert_eq!( + err.to_string(), + "invalid Taproot signature: invalid Taproot signature size: 66" + ); + let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err(); + #[cfg(feature = "std")] + assert_eq!(err.to_string(), "invalid Taproot signature"); + #[cfg(not(feature = "std"))] + assert_eq!( + err.to_string(), + "invalid Taproot signature: invalid Taproot signature size: 57" + ); + let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err(); + assert_eq!(err.to_string(), "invalid control block"); + let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926115c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e123202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err(); + assert_eq!(err.to_string(), "invalid control block"); + } + + fn rtt_psbt(psbt: Psbt) { + let enc = Psbt::serialize(&psbt); + let psbt2 = Psbt::deserialize(&enc).unwrap(); + assert_eq!(psbt, psbt2); + } + + #[test] + fn valid_psbt_vectors() { + let psbt = hex_psbt("70736274ff010052020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a01000000160014768e1eeb4cf420866033f80aceff0f9720744969000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232002202036b772a6db74d8753c98a827958de6c78ab3312109f37d3e0304484242ece73d818772b2da7540000800100008000000080000000000000000000").unwrap(); + let internal_key = psbt.inputs[0].tap_internal_key.unwrap(); + assert!(psbt.inputs[0].tap_key_origins.contains_key(&internal_key)); + rtt_psbt(psbt); + + // vector 2 + let psbt = hex_psbt("70736274ff010052020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a01000000160014768e1eeb4cf420866033f80aceff0f9720744969000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011340bb53ec917bad9d906af1ba87181c48b86ace5aae2b53605a725ca74625631476fc6f5baedaf4f2ee0f477f36f58f3970d5b8273b7e497b97af2e3f125c97af342116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232002202036b772a6db74d8753c98a827958de6c78ab3312109f37d3e0304484242ece73d818772b2da7540000800100008000000080000000000000000000").unwrap(); + let internal_key = psbt.inputs[0].tap_internal_key.unwrap(); + assert!(psbt.inputs[0].tap_key_origins.contains_key(&internal_key)); + assert!(psbt.inputs[0].tap_key_sig.is_some()); + rtt_psbt(psbt); + + // vector 3 + let psbt = hex_psbt("70736274ff01005e020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap(); + let internal_key = psbt.outputs[0].tap_internal_key.unwrap(); + assert!(psbt.outputs[0].tap_key_origins.contains_key(&internal_key)); + rtt_psbt(psbt); + + // vector 4 + let psbt = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f823202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc04215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac097c6e6fea5ff714ff5724499990810e406e98aa10f5bf7e5f6784bc1d0a9a6ce23204320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2acc06215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f82320fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca9acc021162cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d23901cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09772b2da7560000800100008002000080000000000000000021164320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b23901115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f8772b2da75600008001000080010000800000000000000000211650929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2116fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca939016f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970772b2da7560000800100008003000080000000000000000001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820f0362e2f75a6f420a5bde3eb221d96ae6720cf25f81890c95b1d775acb515e65000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap(); + assert!(psbt.inputs[0].tap_internal_key.is_some()); + assert!(psbt.inputs[0].tap_merkle_root.is_some()); + assert!(!psbt.inputs[0].tap_key_origins.is_empty()); + assert!(!psbt.inputs[0].tap_scripts.is_empty()); + rtt_psbt(psbt); + + // vector 5 + let psbt = hex_psbt("70736274ff01005e020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a010000002251200a8cbdc86de1ce1c0f9caeb22d6df7ced3683fe423e05d1e402a879341d6f6f5000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2320001052050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac001066f02c02220736e572900fe1252589a2143c8f3c79f71a0412d2353af755e9701c782694a02ac02c02220631c5f3b5832b8fbdebfb19704ceeb323c21f40f7a24f43d68ef0cc26b125969ac01c0222044faa49a0338de488c8dfffecdfb6f329f380bd566ef20c8df6d813eab1c4273ac210744faa49a0338de488c8dfffecdfb6f329f380bd566ef20c8df6d813eab1c42733901f06b798b92a10ed9a9d0bbfd3af173a53b1617da3a4159ca008216cd856b2e0e772b2da75600008001000080010000800000000003000000210750929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2107631c5f3b5832b8fbdebfb19704ceeb323c21f40f7a24f43d68ef0cc26b125969390118ace409889785e0ea70ceebb8e1ca892a7a78eaede0f2e296cf435961a8f4ca772b2da756000080010000800200008000000000030000002107736e572900fe1252589a2143c8f3c79f71a0412d2353af755e9701c782694a02390129a5b4915090162d759afd3fe0f93fa3326056d0b4088cb933cae7826cb8d82c772b2da7560000800100008003000080000000000300000000").unwrap(); + assert!(psbt.outputs[0].tap_internal_key.is_some()); + assert!(!psbt.outputs[0].tap_key_origins.is_empty()); + assert!(psbt.outputs[0].tap_tree.is_some()); + rtt_psbt(psbt); + + // vector 6 + let psbt = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b0940bf818d9757d6ffeb538ba057fb4c1fc4e0f5ef186e765beb564791e02af5fd3d5e2551d4e34e33d86f276b82c99c79aed3f0395a081efcd2cc2c65dd7e693d7941144320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f840e1f1ab6fabfa26b236f21833719dc1d428ab768d80f91f9988d8abef47bfb863bb1f2a529f768c15f00ce34ec283cdc07e88f8428be28f6ef64043c32911811a4114fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca96f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae97040ec1f0379206461c83342285423326708ab031f0da4a253ee45aafa5b8c92034d8b605490f8cd13e00f989989b97e215faa36f12dee3693d2daccf3781c1757f66215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f823202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc04215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac097c6e6fea5ff714ff5724499990810e406e98aa10f5bf7e5f6784bc1d0a9a6ce23204320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2acc06215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f82320fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca9acc021162cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d23901cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09772b2da7560000800100008002000080000000000000000021164320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b23901115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f8772b2da75600008001000080010000800000000000000000211650929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2116fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca939016f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970772b2da7560000800100008003000080000000000000000001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820f0362e2f75a6f420a5bde3eb221d96ae6720cf25f81890c95b1d775acb515e65000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap(); + assert!(psbt.inputs[0].tap_internal_key.is_some()); + assert!(psbt.inputs[0].tap_merkle_root.is_some()); + assert!(!psbt.inputs[0].tap_scripts.is_empty()); + assert!(!psbt.inputs[0].tap_script_sigs.is_empty()); + assert!(!psbt.inputs[0].tap_key_origins.is_empty()); + rtt_psbt(psbt); + } + } + + #[test] + fn invalid_vector_4617() { + let err = hex_psbt("70736274ff01007374ff0103010000000000000000002e2873007374ff0107736205000000000000000000000000000000000006060005feffffff74ff01000a000000000000002cc760008530b38dac0100030500000074ff01070100000000000000000000000000c0316888e006000600050000736274ff00d90001007374ff41030100000000000a0a06002e2873007374ff01070100000000000000000000000000000000ff0000060600050000736274ff01000a0080000000000024c7600005193b1e400700030500000074ff0107010000000000a9c7df3f07000570ed62c76004c3ca95c5f90200010742420a0a000000000000").unwrap_err(); + match err { + Error::IncorrectNonWitnessUtxo { index: 0, input_outpoint, non_witness_utxo_txid } => { + assert_eq!( + input_outpoint, + "00000000000000000000000562730701ff74730073282e000000000000000000:0" + .parse() + .unwrap(), + ); + assert_eq!( + non_witness_utxo_txid, + "9ed45fd3f73b038649bee6e763dbd70868745c48a0d2b0299f42c68f957995f4" + .parse() + .unwrap(), + ); + } + _ => panic!("expected output hash mismatch error, got {}", err), + } + } + + #[test] + fn serialize_and_deserialize_preimage_psbt() { + // create a sha preimage map + let mut sha256_preimages = BTreeMap::new(); + sha256_preimages.insert(sha256::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]); + sha256_preimages.insert(sha256::Hash::hash(&[1u8]), vec![1u8]); + + // same for hash160 + let mut hash160_preimages = BTreeMap::new(); + hash160_preimages.insert(hash160::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]); + hash160_preimages.insert(hash160::Hash::hash(&[1u8]), vec![1u8]); + + // same vector as valid_vector_1 from BIPs with added + let mut unserialized = Psbt { + unsigned_tx: Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::from_consensus(1257139), + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), + vout: 0, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + } + ], + outputs: vec![ + TxOut { + amount: Amount::from_sat_u32(99_999_699), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), + }, + TxOut { + + amount: Amount::from_sat_u32(100_000_000), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), + }, + ], + }, + version: 0, + xpub: Default::default(), + proprietary: Default::default(), + unknown: BTreeMap::new(), + + inputs: vec![ + Input { + non_witness_utxo: Some(Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), + vout: 1, + }, + script_sig: ScriptSigBuf::from_hex_no_length_prefix("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").as_slice(), + hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").as_slice(), + ]), + }, + TxIn { + previous_output: OutPoint { + txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(), + vout: 1, + }, + script_sig: ScriptSigBuf::from_hex_no_length_prefix("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[ + hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").as_slice(), + hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").as_slice(), + ]), + } + ], + outputs: vec![ + TxOut { + amount: Amount::from_sat_u32(200_000_000), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(), + }, + TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + }, + ], + }), + ..Default::default() + }, + ], + outputs: vec![ + Output { + ..Default::default() + }, + Output { + ..Default::default() + }, + ], + }; + unserialized.inputs[0].hash160_preimages = hash160_preimages; + unserialized.inputs[0].sha256_preimages = sha256_preimages; + + let rtt = hex_psbt(&unserialized.serialize_hex()).unwrap(); + assert_eq!(rtt, unserialized); + + // Now add a ripemd160 with incorrect preimage + let mut ripemd160_preimages = BTreeMap::new(); + ripemd160_preimages.insert(ripemd160::Hash::hash(&[17u8]), vec![18u8]); + unserialized.inputs[0].ripemd160_preimages = ripemd160_preimages; + + // Now the roundtrip should fail as the preimage is incorrect. + let rtt: Result = hex_psbt(&unserialized.serialize_hex()); + assert!(rtt.is_err()); + } + + #[test] + fn serialize_and_deserialize_proprietary() { + let mut psbt = hex_psbt("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap(); + psbt.proprietary.insert( + raw::ProprietaryKey { prefix: b"test".to_vec(), subtype: 0u64, key: b"test".to_vec() }, + b"test".to_vec(), + ); + assert!(!psbt.proprietary.is_empty()); + let rtt = hex_psbt(&psbt.serialize_hex()).unwrap(); + assert!(!rtt.proprietary.is_empty()); + } + + // Deserialize MuSig2 PSBT participant keys according to BIP-0373 + #[test] + fn serialize_and_deserialize_musig2_participants() { + // XXX: Does not cover PSBT_IN_MUSIG2_PUB_NONCE, PSBT_IN_MUSIG2_PARTIAL_SIG (yet) + + let expected_in_agg_pk = secp256k1::PublicKey::from_str( + "021401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e00", + ) + .unwrap(); + let expected_in_pubkeys = vec![ + secp256k1::PublicKey::from_str( + "02bebd7a1cef20283444b96e9ce78137e951ce48705390933896311a9abc75736a", + ) + .unwrap(), + secp256k1::PublicKey::from_str( + "0355212dff7b3d7e8126687a62fd0435a3fb4de56d9af9ae23a1c9ca05b349c8e2", + ) + .unwrap(), + ]; + + let expected_out_agg_pk = secp256k1::PublicKey::from_str( + "0364934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba5", + ) + .unwrap(); + + let expected_out_pubkeys = vec![ + secp256k1::PublicKey::from_str( + "02841d69a8b80ae23a8090e6f3765540ea5efd8c287b1307c983a6e2a3a171b525", + ) + .unwrap(), + secp256k1::PublicKey::from_str( + "02bad833849a98cdfb0a0749609ddccab16ad54485ecc67f828df4bdc4f2b90d4c", + ) + .unwrap(), + ]; + + const PSBT_HEX: &str = "70736274ff01005e02000000017b42be5ea467afe0d0571dc4a91bef97ff9605a590c0b8d5892323946414d1810000000000ffffffff01f0b9f50500000000225120bc7e18f55e2c7a28d78cadac1bc72c248372375d269bafe6b315bc40505d07e5000000000001012b00e1f50500000000225120de564ebf8ff7bd9bb41bd88264c04b1713ebb9dc8df36319091d2eabb16cda6221161401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e000500eb4cbe62211655212dff7b3d7e8126687a62fd0435a3fb4de56d9af9ae23a1c9ca05b349c8e20500755abbf92116bebd7a1cef20283444b96e9ce78137e951ce48705390933896311a9abc75736a05002a33dfd90117201401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e00221a021401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e004202bebd7a1cef20283444b96e9ce78137e951ce48705390933896311a9abc75736a0355212dff7b3d7e8126687a62fd0435a3fb4de56d9af9ae23a1c9ca05b349c8e20001052064934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba5210764934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba50500fa4c6afa22080364934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba54202841d69a8b80ae23a8090e6f3765540ea5efd8c287b1307c983a6e2a3a171b52502bad833849a98cdfb0a0749609ddccab16ad54485ecc67f828df4bdc4f2b90d4c00"; + + let psbt = hex_psbt(PSBT_HEX).unwrap(); + + assert_eq!(psbt.inputs[0].musig2_participant_pubkeys.len(), 1); + assert_eq!( + psbt.inputs[0].musig2_participant_pubkeys.iter().next().unwrap(), + (&expected_in_agg_pk, &expected_in_pubkeys) + ); + + assert_eq!(psbt.outputs[0].musig2_participant_pubkeys.len(), 1); + assert_eq!( + psbt.outputs[0].musig2_participant_pubkeys.iter().next().unwrap(), + (&expected_out_agg_pk, &expected_out_pubkeys) + ); + + // Check round trip de/serialization + assert_eq!(psbt.serialize_hex(), PSBT_HEX); + + const PSBT_TRUNCATED_MUSIG_PARTICIPANTS_HEX: &str = "70736274ff01005e0200000001f034711ce319b1db76ce73440f2cb64a7e3a02e75c936b8d8a4958a024ea8d870000000000ffffffff01f0b9f50500000000225120bc7e18f55e2c7a28d78cadac1bc72c248372375d269bafe6b315bc40505d07e5000000000001012b00e1f50500000000225120de564ebf8ff7bd9bb41bd88264c04b1713ebb9dc8df36319091d2eabb16cda6221161401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e000500eb4cbe62211655212dff7b3d7e8126687a62fd0435a3fb4de56d9af9ae23a1c9ca05b349c8e20500755abbf92116bebd7a1cef20283444b96e9ce78137e951ce48705390933896311a9abc75736a05002a33dfd90117201401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e00221a021401301810a46a4e3f39e4603ec228ed301d9f2079767fda758dee7224b32e002a02bebd7a1cef20283444b96e9ce78137e951ce48705390933896311a9abc75736a0355212dff7b3d7e810001052064934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba5210764934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba50500fa4c6afa22080364934a64831bd917a2667b886671650846f021e1c025e4b2bb65e49ab3e7cba52a02841d69a8b80ae23a8090e6f3765540ea5efd8c287b1307c983a6e2a3a171b52502bad833849a98cdfb00"; + + hex_psbt(PSBT_TRUNCATED_MUSIG_PARTICIPANTS_HEX) + .expect_err("Deserializing PSBT with truncated musig participants should error"); + } + + // PSBTs taken from BIP 174 test vectors. + #[test] + fn combine_psbts() { + let mut psbt1 = hex_psbt(include_str!("../../tests/data/psbt1.hex")).unwrap(); + let psbt2 = hex_psbt(include_str!("../../tests/data/psbt2.hex")).unwrap(); + let psbt_combined = hex_psbt(include_str!("../../tests/data/psbt2.hex")).unwrap(); + + psbt1.combine(psbt2).expect("psbt combine to succeed"); + assert_eq!(psbt1, psbt_combined); + } + + #[test] + fn combine_psbts_commutative() { + let mut psbt1 = hex_psbt(include_str!("../../tests/data/psbt1.hex")).unwrap(); + let mut psbt2 = hex_psbt(include_str!("../../tests/data/psbt2.hex")).unwrap(); + + let psbt1_clone = psbt1.clone(); + let psbt2_clone = psbt2.clone(); + + psbt1.combine(psbt2_clone).expect("psbt1 combine to succeed"); + psbt2.combine(psbt1_clone).expect("psbt2 combine to succeed"); + + assert_eq!(psbt1, psbt2); + } + + // https://github.com/rust-bitcoin/rust-bitcoin/issues/3628 + #[test] + fn combine_psbt_fuzz_3628() { + let mut psbt1 = hex_psbt(include_str!("../../tests/data/psbt_fuzz1.hex")).unwrap(); + let psbt2 = hex_psbt(include_str!("../../tests/data/psbt_fuzz2.hex")).unwrap(); + + assert!(matches!( + psbt1.combine(psbt2).unwrap_err(), + Error::CombineInconsistentKeySources(_) + )); + } + + #[cfg(all(feature = "rand", feature = "std"))] + fn gen_keys() -> (PrivateKey, PublicKey) { + use secp256k1::rand; + + let sk = SecretKey::new(&mut rand::rng()); + let priv_key = PrivateKey::new(sk, NetworkKind::Test); + let pk = PublicKey::from_private_key(priv_key); + + (priv_key, pk) + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn get_key_btree_map() { + let (priv_key, pk) = gen_keys(); + + let mut key_map = BTreeMap::new(); + key_map.insert(pk, priv_key); + + let got = key_map.get_key(&KeyRequest::Pubkey(pk)).expect("failed to get key"); + assert_eq!(got.unwrap(), priv_key) + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn pubkey_map_get_key_negates_odd_parity_keys() { + use crate::psbt::{GetKey, KeyRequest}; + + let (mut priv_key, mut pk) = gen_keys(); + let (xonly, parity) = pk.inner.x_only_public_key(); + + let mut pubkey_map: HashMap = HashMap::new(); + + if parity == secp256k1::Parity::Even { + priv_key = PrivateKey { + compressed: priv_key.compressed, + network: priv_key.network, + inner: priv_key.inner.negate(), + }; + pk = priv_key.public_key(); + } + + pubkey_map.insert(pk, priv_key); + + let req_result = pubkey_map.get_key(&KeyRequest::XOnlyPubkey(xonly.into())).unwrap(); + + let retrieved_key = req_result.unwrap(); + + let retrieved_pub_key = retrieved_key.public_key(); + let (retrieved_xonly, retrieved_parity) = retrieved_pub_key.inner.x_only_public_key(); + + assert_eq!(xonly, retrieved_xonly); + assert_eq!( + retrieved_parity, + secp256k1::Parity::Even, + "Key should be normalized to have even parity, even when original had odd parity" + ); + } + + #[test] + fn get_key_xpriv_bip32_parent() { + let seed = hex!("000102030405060708090a0b0c0d0e0f"); + let parent_xpriv: Xpriv = Xpriv::new_master(NetworkKind::Main, &seed); + let path: DerivationPath = "m/1/2/3".parse().unwrap(); + let path_prefix: DerivationPath = "m/1".parse().unwrap(); + + let expected_private_key = + parent_xpriv.derive_xpriv(&path).unwrap().to_private_key(); + + let derived_xpriv = parent_xpriv.derive_xpriv(&path_prefix).unwrap(); + + let derived_key = derived_xpriv + .get_key(&KeyRequest::Bip32((parent_xpriv.fingerprint(), path))) + .unwrap(); + + assert_eq!(derived_key, Some(expected_private_key)); + } + + #[test] + fn fee() { + let output_0_val = Amount::from_sat_u32(99_999_699); + let output_1_val = Amount::from_sat_u32(100_000_000); + let prev_output_val = Amount::from_sat_u32(200_000_000); + + let t = Psbt { + unsigned_tx: Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::from_consensus(1257139), + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), + vout: 0, + }, + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + ..TxIn::EMPTY_COINBASE + } + ], + outputs: vec![ + TxOut { + amount: output_0_val, + script_pubkey: ScriptPubKeyBuf::new() + }, + TxOut { + amount: output_1_val, + script_pubkey: ScriptPubKeyBuf::new() + }, + ], + }, + xpub: Default::default(), + version: 0, + proprietary: BTreeMap::new(), + unknown: BTreeMap::new(), + + inputs: vec![ + Input { + non_witness_utxo: Some(Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), + vout: 1, + }, + sequence: Sequence::MAX, + ..TxIn::EMPTY_COINBASE + }, + TxIn { + previous_output: OutPoint { + txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(), + vout: 1, + }, + sequence: Sequence::MAX, + ..TxIn::EMPTY_COINBASE + } + ], + outputs: vec![ + TxOut { + amount: prev_output_val, + script_pubkey: ScriptPubKeyBuf::new() + }, + TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::new() + }, + ], + }), + ..Default::default() + }, + ], + outputs: vec![ + Output { + ..Default::default() + }, + Output { + ..Default::default() + }, + ], + }; + assert_eq!( + t.fee().expect("fee calculation"), + (prev_output_val - (output_0_val + output_1_val)).unwrap() + ); + // no previous output + let mut t2 = t.clone(); + t2.inputs[0].non_witness_utxo = None; + match t2.fee().unwrap_err() { + Error::MissingUtxo => {} + e => panic!("unexpected error: {:?}", e), + } + // negative fee + let mut t3 = t; + t3.unsigned_tx.outputs[0].amount = prev_output_val; + match t3.fee().unwrap_err() { + Error::NegativeFee => {} + e => panic!("unexpected error: {:?}", e), + } + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn hashmap_can_sign_taproot() { + let (priv_key, pk) = gen_keys(); + let internal_key: XOnlyPublicKey = pk.inner.into(); + + let tx = Transaction { + version: transaction::Version::TWO, + lock_time: locktime::absolute::LockTime::ZERO, + inputs: vec![TxIn::EMPTY_COINBASE], + outputs: vec![TxOut { amount: Amount::ZERO, script_pubkey: ScriptPubKeyBuf::new() }], + }; + + let mut psbt = Psbt::from_unsigned_tx(tx).unwrap(); + psbt.inputs[0].tap_internal_key = Some(internal_key); + psbt.inputs[0].witness_utxo = Some(transaction::TxOut { + amount: Amount::from_sat_u32(10), + script_pubkey: ScriptPubKeyBuf::new_p2tr(internal_key, None), + }); + + let mut key_map: HashMap = HashMap::new(); + key_map.insert(pk, priv_key); + + let key_source = (Fingerprint::default(), DerivationPath::default()); + let mut tap_key_origins = std::collections::BTreeMap::new(); + tap_key_origins.insert(internal_key, (vec![], key_source)); + psbt.inputs[0].tap_key_origins = tap_key_origins; + + let signing_keys = psbt.sign(&key_map).unwrap(); + assert_eq!(signing_keys.len(), 1); + assert_eq!(signing_keys[&0], SigningKeys::Schnorr(vec![internal_key])); + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn xonly_hashmap_can_sign_taproot() { + let (priv_key, pk) = gen_keys(); + let internal_key: XOnlyPublicKey = pk.inner.into(); + + let tx = Transaction { + version: transaction::Version::TWO, + lock_time: locktime::absolute::LockTime::ZERO, + inputs: vec![TxIn::EMPTY_COINBASE], + outputs: vec![TxOut { amount: Amount::ZERO, script_pubkey: ScriptPubKeyBuf::new() }], + }; + + let mut psbt = Psbt::from_unsigned_tx(tx).unwrap(); + psbt.inputs[0].tap_internal_key = Some(internal_key); + psbt.inputs[0].witness_utxo = Some(transaction::TxOut { + amount: Amount::from_sat_u32(10), + script_pubkey: ScriptPubKeyBuf::new_p2tr(internal_key, None), + }); + + let mut xonly_key_map: HashMap = HashMap::new(); + xonly_key_map.insert(internal_key, priv_key); + + let key_source = (Fingerprint::default(), DerivationPath::default()); + let mut tap_key_origins = std::collections::BTreeMap::new(); + tap_key_origins.insert(internal_key, (vec![], key_source)); + psbt.inputs[0].tap_key_origins = tap_key_origins; + + let signing_keys = psbt.sign(&xonly_key_map).unwrap(); + assert_eq!(signing_keys.len(), 1); + assert_eq!(signing_keys[&0], SigningKeys::Schnorr(vec![internal_key])); + } + + #[test] + #[cfg(all(feature = "rand", feature = "std"))] + fn sign_psbt() { + let unsigned_tx = Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn::EMPTY_COINBASE, TxIn::EMPTY_COINBASE], + + outputs: vec![TxOut { amount: Amount::ZERO, script_pubkey: ScriptPubKeyBuf::new() }], + }; + let mut psbt = Psbt::from_unsigned_tx(unsigned_tx).unwrap(); + + let (priv_key, pk) = gen_keys(); + + // key_map implements `GetKey` using KeyRequest::Pubkey. A pubkey key request does not use + // keysource so we use default `KeySource` (fingerprint and derivation path) below. + let mut key_map = BTreeMap::new(); + key_map.insert(pk, priv_key); + + // First input we can spend. See comment above on key_map for why we use defaults here. + let txout_wpkh = TxOut { + amount: Amount::from_sat_u32(10), + script_pubkey: ScriptPubKeyBuf::new_p2wpkh(pk.wpubkey_hash().unwrap()), + }; + psbt.inputs[0].witness_utxo = Some(txout_wpkh); + + let mut map = BTreeMap::new(); + map.insert(pk.inner, (Fingerprint::default(), DerivationPath::default())); + psbt.inputs[0].bip32_derivation = map; + + // Second input is unspendable by us e.g., from another wallet that supports future upgrades. + let unknown_prog = WitnessProgram::new(WitnessVersion::V4, &[0xaa; 34]).unwrap(); + let txout_unknown_future = TxOut { + amount: Amount::from_sat_u32(10), + script_pubkey: ScriptPubKeyBuf::new_witness_program(&unknown_prog), + }; + psbt.inputs[1].witness_utxo = Some(txout_unknown_future); + + let (signing_keys, _) = psbt.sign(&key_map).unwrap_err(); + + assert_eq!(signing_keys.len(), 1); + assert_eq!(signing_keys[&0], SigningKeys::Ecdsa(vec![pk])); + } +} diff --git a/bitcoin/src/psbt/raw.rs b/bitcoin/src/psbt/raw.rs new file mode 100644 index 000000000..91d50590a --- /dev/null +++ b/bitcoin/src/psbt/raw.rs @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Raw PSBT key-value pairs. +//! +//! Raw PSBT key-value pairs as defined at +//! . + +use core::fmt; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use internals::ToU64 as _; +use io::{BufRead, Write}; + +use super::serialize::{Deserialize, Serialize}; +use crate::consensus::encode::{ + self, deserialize, serialize, Decodable, Encodable, ReadExt, WriteExt, MAX_VEC_SIZE, +}; +use crate::prelude::{DisplayHex, Vec}; +use crate::psbt::Error; + +/// A PSBT key in its raw byte form. +/// +/// ` := ` +#[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)] +pub struct Key { + /// The type of this PSBT key. + pub type_value: u64, // Encoded as a compact size. + /// The key data itself in raw byte form. + pub key_data: Vec, +} + +/// A PSBT key-value pair in its raw byte form. +/// ` := ` +#[derive(Debug, PartialEq, Eq)] +pub struct Pair { + /// The key of this key-value pair. + pub key: Key, + /// The value data of this key-value pair in raw byte form. + /// ` := ` + pub value: Vec, +} + +/// Default implementation for proprietary key subtyping +pub type ProprietaryType = u64; + +/// Proprietary keys (i.e. keys starting with 0xFC byte) with their internal +/// structure according to BIP 174. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct ProprietaryKey +where + Subtype: Copy + From + Into, +{ + /// Proprietary type prefix used for grouping together keys under some + /// application and avoid namespace collision + pub prefix: Vec, + /// Custom proprietary subtype + pub subtype: Subtype, + /// Additional key bytes (like serialized public key data etc) + pub key: Vec, +} + +impl fmt::Display for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "type: {:#x}, key: {:x}", self.type_value, self.key_data.as_hex()) + } +} + +impl Key { + pub(crate) fn decode(r: &mut R) -> Result { + let byte_size = r.read_compact_size()?; + + if byte_size == 0 { + return Err(Error::NoMorePairs); + } + + let key_byte_size: u64 = byte_size - 1; + + if key_byte_size > MAX_VEC_SIZE.to_u64() { + return Err(encode::Error::Parse(encode::ParseError::OversizedVectorAllocation { + requested: key_byte_size as usize, + max: MAX_VEC_SIZE, + }) + .into()); + } + + let type_value = r.read_compact_size()?; + + let mut key_data = Vec::with_capacity(key_byte_size as usize); + for _ in 0..key_byte_size { + key_data.push(Decodable::consensus_decode(r)?); + } + + Ok(Self { type_value, key_data }) + } +} + +impl Serialize for Key { + fn serialize(&self) -> Vec { + let mut buf = Vec::new(); + buf.emit_compact_size(self.key_data.len() + 1).expect("in-memory writers don't error"); + + buf.emit_compact_size(self.type_value).expect("in-memory writers don't error"); + + for key in &self.key_data { + key.consensus_encode(&mut buf).expect("in-memory writers don't error"); + } + + buf + } +} + +impl Serialize for Pair { + fn serialize(&self) -> Vec { + let mut buf = Vec::new(); + buf.extend(self.key.serialize()); + // := + self.value.consensus_encode(&mut buf).unwrap(); + buf + } +} + +impl Deserialize for Pair { + fn deserialize(bytes: &[u8]) -> Result { + let mut decoder = bytes; + Self::decode(&mut decoder) + } +} + +impl Pair { + pub(crate) fn decode(r: &mut R) -> Result { + Ok(Self { key: Key::decode(r)?, value: Decodable::consensus_decode(r)? }) + } +} + +impl Encodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = self.prefix.consensus_encode(w)?; + len += w.emit_compact_size(self.subtype.into())?; + w.write_all(&self.key)?; + len += self.key.len(); + Ok(len) + } +} + +impl Decodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ + fn consensus_decode(r: &mut R) -> Result { + let prefix = Vec::::consensus_decode(r)?; + let subtype = Subtype::from(r.read_compact_size()?); + + // The limit is a DOS protection mechanism the exact value is not + // important, 1024 bytes is bigger than any key should be. + let mut key = vec![]; + let _ = io::Read::read_to_limit(r, &mut key, 1024)?; + + Ok(Self { prefix, subtype, key }) + } +} + +impl ProprietaryKey +where + Subtype: Copy + From + Into, +{ + /// Constructs a new full [Key] corresponding to this proprietary key type + pub fn to_key(&self) -> Key { Key { type_value: 0xFC, key_data: serialize(self) } } +} + +impl TryFrom for ProprietaryKey +where + Subtype: Copy + From + Into, +{ + type Error = Error; + + /// Constructs a new [`ProprietaryKey`] from a [`Key`]. + /// + /// # Errors + /// + /// Returns [`Error::InvalidProprietaryKey`] if `key` does not start with `0xFC` byte. + fn try_from(key: Key) -> Result { + if key.type_value != 0xFC { + return Err(Error::InvalidProprietaryKey); + } + + Ok(deserialize(&key.key_data)?) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for ProprietaryKey { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + prefix: Vec::::arbitrary(u)?, + subtype: u64::arbitrary(u)?, + key: Vec::::arbitrary(u)?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Key { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { type_value: u.arbitrary()?, key_data: Vec::::arbitrary(u)? }) + } +} diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs new file mode 100644 index 000000000..8d68df88f --- /dev/null +++ b/bitcoin/src/psbt/serialize.rs @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! PSBT serialization. +//! +//! Traits to serialize PSBT values to and from raw bytes +//! according to the BIP-0174 specification. + +use hashes::{hash160, ripemd160, sha256, sha256d}; +use internals::compact_size; +#[allow(unused)] // MSRV polyfill +use internals::slice::SliceExt; + +use super::map::{Input, Map, Output, PsbtSighashType}; +use crate::bip32::{ChildNumber, Fingerprint, KeySource}; +use crate::consensus::encode::{self, deserialize_partial, serialize, Decodable, Encodable}; +use crate::crypto::key::{PublicKey, XOnlyPublicKey}; +use crate::crypto::{ecdsa, taproot}; +use crate::io::Write; +use crate::prelude::{DisplayHex, String, Vec}; +use crate::psbt::{Error, Psbt}; +use crate::script::ScriptBuf; +use crate::taproot::{ + ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder, +}; +use crate::transaction::{Transaction, TxOut}; +use crate::witness::Witness; + +/// A trait for serializing a value as raw data for insertion into PSBT +/// key-value maps. +pub(crate) trait Serialize { + /// Serializes a value as raw data. + fn serialize(&self) -> Vec; +} + +/// A trait for deserializing a value from raw data in PSBT key-value maps. +pub(crate) trait Deserialize: Sized { + /// Deserializes a value from raw data. + fn deserialize(bytes: &[u8]) -> Result; +} + +impl Psbt { + /// Serializes a value as bytes in hex. + pub fn serialize_hex(&self) -> String { self.serialize().to_lower_hex_string() } + + /// Serializes as raw binary data + pub fn serialize(&self) -> Vec { + let mut buf: Vec = Vec::new(); + self.serialize_to_writer(&mut buf).expect("Writing to Vec can't fail"); + buf + } + + /// Serializes the PSBT into a writer. + pub fn serialize_to_writer(&self, w: &mut impl Write) -> io::Result { + let mut written_len = 0; + + fn write_all(w: &mut impl Write, data: &[u8]) -> io::Result { + w.write_all(data).map(|_| data.len()) + } + + // magic + written_len += write_all(w, b"psbt")?; + // separator + written_len += write_all(w, &[0xff])?; + + written_len += write_all(w, &self.serialize_map())?; + + for i in &self.inputs { + written_len += write_all(w, &i.serialize_map())?; + } + + for i in &self.outputs { + written_len += write_all(w, &i.serialize_map())?; + } + + Ok(written_len) + } + + /// Deserializes a value from raw binary data. + pub fn deserialize(mut bytes: &[u8]) -> Result { + Self::deserialize_from_reader(&mut bytes) + } + + /// Deserializes a value from raw binary data read from a `BufRead` object. + pub fn deserialize_from_reader(r: &mut R) -> Result { + const MAGIC_BYTES: &[u8] = b"psbt"; + + let magic: [u8; 4] = Decodable::consensus_decode(r)?; + if magic != MAGIC_BYTES { + return Err(Error::InvalidMagic); + } + + const PSBT_SEPARATOR: u8 = 0xff_u8; + let separator: u8 = Decodable::consensus_decode(r)?; + if separator != PSBT_SEPARATOR { + return Err(Error::InvalidSeparator); + } + + let mut global = Self::decode_global(r)?; + global.unsigned_tx_checks()?; + + let inputs: Vec = { + let inputs_len: usize = (global.unsigned_tx.inputs).len(); + + let mut inputs: Vec = Vec::with_capacity(inputs_len); + + for i in 0..inputs_len { + let input = Input::decode(r)?; + if let Some(ref tx) = input.non_witness_utxo { + let input_outpoint = global.unsigned_tx.inputs[i].previous_output; + let txid = tx.compute_txid(); + if txid != input_outpoint.txid { + return Err(Error::IncorrectNonWitnessUtxo { + index: i, + input_outpoint, + non_witness_utxo_txid: txid, + }); + } + } + inputs.push(input); + } + + inputs + }; + + let outputs: Vec = { + let outputs_len: usize = (global.unsigned_tx.outputs).len(); + + let mut outputs: Vec = Vec::with_capacity(outputs_len); + + for _ in 0..outputs_len { + outputs.push(Output::decode(r)?); + } + + outputs + }; + + global.inputs = inputs; + global.outputs = outputs; + Ok(global) + } +} +impl_psbt_de_serialize!(Transaction); +impl_psbt_de_serialize!(TxOut); +impl_psbt_de_serialize!(Witness); +impl_psbt_hash_de_serialize!(ripemd160::Hash); +impl_psbt_hash_de_serialize!(sha256::Hash); +impl_psbt_hash_de_serialize!(TapLeafHash); +impl_psbt_hash_de_serialize!(TapNodeHash); +impl_psbt_hash_de_serialize!(hash160::Hash); +impl_psbt_hash_de_serialize!(sha256d::Hash); + +// Taproot +impl_psbt_de_serialize!(Vec); + +impl Serialize for ScriptBuf { + fn serialize(&self) -> Vec { self.to_vec() } +} + +impl Deserialize for ScriptBuf { + fn deserialize(bytes: &[u8]) -> Result { Ok(Self::from(bytes.to_vec())) } +} + +impl Serialize for PublicKey { + fn serialize(&self) -> Vec { + let mut buf = Vec::new(); + self.write_into(&mut buf).expect("vecs don't error"); + buf + } +} + +impl Deserialize for PublicKey { + fn deserialize(bytes: &[u8]) -> Result { + Self::from_slice(bytes).map_err(Error::InvalidPublicKey) + } +} + +impl Serialize for secp256k1::PublicKey { + fn serialize(&self) -> Vec { self.serialize().to_vec() } +} + +impl Deserialize for secp256k1::PublicKey { + fn deserialize(bytes: &[u8]) -> Result { + Self::from_slice(bytes).map_err(Error::InvalidSecp256k1PublicKey) + } +} + +impl Serialize for Vec { + fn serialize(&self) -> Vec { + let mut result: Vec = + Vec::with_capacity(secp256k1::constants::PUBLIC_KEY_SIZE * self.len()); + + for pubkey in self.iter() { + result.extend(Serialize::serialize(pubkey)); + } + + result + } +} + +impl Deserialize for Vec { + fn deserialize(bytes: &[u8]) -> Result { + bytes + .chunks(secp256k1::constants::PUBLIC_KEY_SIZE) + .map(secp256k1::PublicKey::deserialize) + .collect() + } +} + +impl Serialize for ecdsa::Signature { + fn serialize(&self) -> Vec { self.to_vec() } +} + +impl Deserialize for ecdsa::Signature { + fn deserialize(bytes: &[u8]) -> Result { + // NB: Since BIP-0174 says "the signature as would be pushed to the stack from + // a scriptSig or witness" we should ideally use a consensus deserialization and do + // not error on a non-standard values. However, + // + // 1) the current implementation of from_u32_consensus(`flag`) does not preserve + // the sighash byte `flag` mapping all unknown values to EcdsaSighashType::All or + // EcdsaSighashType::AllPlusAnyOneCanPay. Therefore, break the invariant + // EcdsaSig::from_slice(&sl[..]).to_vec = sl. + // + // 2) This would cause to have invalid signatures because the sighash message + // also has a field sighash_u32 (See BIP-0141). For example, when signing with non-standard + // 0x05, the sighash message would have the last field as 0x05u32 while, the verification + // would check the signature assuming sighash_u32 as `0x01`. + Self::from_slice(bytes).map_err(|e| match e { + ecdsa::DecodeError::EmptySignature => Error::InvalidEcdsaSignature(e), + ecdsa::DecodeError::SighashType(err) => Error::NonStandardSighashType(err.0), + ecdsa::DecodeError::Secp256k1(..) => Error::InvalidEcdsaSignature(e), + }) + } +} + +impl Serialize for KeySource { + fn serialize(&self) -> Vec { + let mut rv: Vec = Vec::with_capacity(key_source_len(self)); + + rv.append(&mut self.0.to_byte_array().to_vec()); + + for cnum in &self.1 { + rv.append(&mut serialize(&u32::from(*cnum))) + } + + rv + } +} + +impl Deserialize for KeySource { + fn deserialize(bytes: &[u8]) -> Result { + let (fingerprint, mut d) = + bytes.split_first_chunk::<4>().ok_or(io::Error::from(io::ErrorKind::UnexpectedEof))?; + + let fprint: Fingerprint = fingerprint.into(); + let mut dpath: Vec = Default::default(); + + while !d.is_empty() { + match u32::consensus_decode(&mut d) { + Ok(index) => dpath.push(index.into()), + Err(e) => return Err(e.into()), + } + } + + Ok((fprint, dpath.into())) + } +} + +// partial sigs +impl Serialize for Vec { + fn serialize(&self) -> Vec { self.clone() } +} + +impl Deserialize for Vec { + fn deserialize(bytes: &[u8]) -> Result { Ok(bytes.to_vec()) } +} + +impl Serialize for PsbtSighashType { + fn serialize(&self) -> Vec { serialize(&self.to_u32()) } +} + +impl Deserialize for PsbtSighashType { + fn deserialize(bytes: &[u8]) -> Result { + let raw: u32 = encode::deserialize(bytes)?; + Ok(Self { inner: raw }) + } +} + +// Taproot related ser/deser +impl Serialize for XOnlyPublicKey { + fn serialize(&self) -> Vec { Self::serialize(self).to_vec() } +} + +impl Deserialize for XOnlyPublicKey { + fn deserialize(bytes: &[u8]) -> Result { + Self::from_byte_array(bytes.try_into().map_err(|_| Error::InvalidXOnlyPublicKey)?) + .map_err(|_| Error::InvalidXOnlyPublicKey) + } +} + +impl Serialize for taproot::Signature { + fn serialize(&self) -> Vec { self.to_vec() } +} + +impl Deserialize for taproot::Signature { + fn deserialize(bytes: &[u8]) -> Result { + Self::from_slice(bytes).map_err(|e| match e { + taproot::SigFromSliceError::SighashType(err) => Error::NonStandardSighashType(err.0), + taproot::SigFromSliceError::InvalidSignatureSize(_) => + Error::InvalidTaprootSignature(e), + taproot::SigFromSliceError::Secp256k1(..) => Error::InvalidTaprootSignature(e), + }) + } +} + +impl Serialize for (XOnlyPublicKey, TapLeafHash) { + fn serialize(&self) -> Vec { + let ser_pk = self.0.serialize(); + let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_byte_array().len()); + buf.extend(&ser_pk); + buf.extend(self.1.as_byte_array()); + buf + } +} + +impl Deserialize for (XOnlyPublicKey, TapLeafHash) { + fn deserialize(bytes: &[u8]) -> Result { + if bytes.len() < 32 { + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); + } + let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?; + let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?; + Ok((a, b)) + } +} + +impl Serialize for ControlBlock { + fn serialize(&self) -> Vec { Self::serialize(self) } +} + +impl Deserialize for ControlBlock { + fn deserialize(bytes: &[u8]) -> Result { + Self::decode(bytes).map_err(|_| Error::InvalidControlBlock) + } +} + +// Versioned ScriptBuf +impl Serialize for (ScriptBuf, LeafVersion) { + fn serialize(&self) -> Vec { + let mut buf = Vec::with_capacity(self.0.len() + 1); + buf.extend(self.0.as_bytes()); + buf.push(self.1.to_consensus()); + buf + } +} + +impl Deserialize for (ScriptBuf, LeafVersion) { + fn deserialize(bytes: &[u8]) -> Result { + if bytes.is_empty() { + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); + } + // The last byte is LeafVersion. + let script = ScriptBuf::deserialize(&bytes[..bytes.len() - 1])?; + let leaf_ver = LeafVersion::from_consensus(bytes[bytes.len() - 1]) + .map_err(|_| Error::InvalidLeafVersion)?; + Ok((script, leaf_ver)) + } +} + +impl Serialize for (Vec, KeySource) { + fn serialize(&self) -> Vec { + let mut buf = Vec::with_capacity(32 * self.0.len() + key_source_len(&self.1)); + self.0.consensus_encode(&mut buf).expect("Vecs don't error allocation"); + buf.extend(self.1.serialize()); + buf + } +} + +impl Deserialize for (Vec, KeySource) { + fn deserialize(bytes: &[u8]) -> Result { + let (leafhash_vec, consumed) = deserialize_partial::>(bytes)?; + let key_source = KeySource::deserialize(&bytes[consumed..])?; + Ok((leafhash_vec, key_source)) + } +} + +impl Serialize for TapTree { + fn serialize(&self) -> Vec { + let capacity = self + .script_leaves() + .map(|l| { + l.script().len() + compact_size::encoded_size(l.script().len()) // script version + + 1 // merkle branch + + 1 // leaf version + }) + .sum::(); + let mut buf = Vec::with_capacity(capacity); + for leaf_info in self.script_leaves() { + // # Cast Safety: + // + // TaprootMerkleBranch can only have len at most 128(TAPROOT_CONTROL_MAX_NODE_COUNT). + // safe to cast from usize to u8 + buf.push(leaf_info.merkle_branch().len() as u8); + buf.push(leaf_info.version().to_consensus()); + leaf_info.script().consensus_encode(&mut buf).expect("Vecs don't err"); + } + buf + } +} + +impl Deserialize for TapTree { + fn deserialize(bytes: &[u8]) -> Result { + let mut builder = TaprootBuilder::new(); + let mut bytes_iter = bytes.iter(); + while let Some(depth) = bytes_iter.next() { + let version = bytes_iter.next().ok_or(Error::Taproot("invalid Taproot Builder"))?; + let (script, consumed) = deserialize_partial::>(bytes_iter.as_slice())?; + if consumed > 0 { + bytes_iter.nth(consumed - 1); + } + let leaf_version = + LeafVersion::from_consensus(*version).map_err(|_| Error::InvalidLeafVersion)?; + builder = builder + .add_leaf_with_ver(*depth, script, leaf_version) + .map_err(|_| Error::Taproot("Tree not in DFS order"))?; + } + Self::try_from(builder).map_err(Error::TapTree) + } +} + +// Helper function to compute key source len +fn key_source_len(key_source: &KeySource) -> usize { 4 + 4 * (key_source.1).as_ref().len() } + +#[cfg(test)] +mod tests { + use super::*; + use crate::script::ScriptBufExt as _; + use crate::TapScriptBuf; + + // Composes tree matching a given depth map, filled with dumb script leaves, + // each of which consists of a single push-int op code, with int value + // increased for each consecutive leaf. + pub fn compose_taproot_builder<'map>( + opcode: u8, + depth_map: impl IntoIterator, + ) -> TaprootBuilder { + let mut val = opcode; + let mut builder = TaprootBuilder::new(); + for depth in depth_map { + let script = TapScriptBuf::from_hex_no_length_prefix(&format!("{:02x}", val)).unwrap(); + builder = builder.add_leaf(*depth, script).unwrap(); + let (new_val, _) = val.overflowing_add(1); + val = new_val; + } + builder + } + + #[test] + fn taptree_hidden() { + let dummy_hash = TapNodeHash::from_byte_array([0x12; 32]); + let mut builder = compose_taproot_builder(0x51, &[2, 2, 2]); + builder = builder + .add_leaf_with_ver( + 3, + TapScriptBuf::from_hex_no_length_prefix("b9").unwrap(), + LeafVersion::from_consensus(0xC2).unwrap(), + ) + .unwrap(); + builder = builder.add_hidden_node(3, dummy_hash).unwrap(); + assert!(TapTree::try_from(builder).is_err()); + } + + #[test] + fn taptree_roundtrip() { + let mut builder = compose_taproot_builder(0x51, &[2, 2, 2, 3]); + builder = builder + .add_leaf_with_ver( + 3, + TapScriptBuf::from_hex_no_length_prefix("b9").unwrap(), + LeafVersion::from_consensus(0xC2).unwrap(), + ) + .unwrap(); + let tree = TapTree::try_from(builder).unwrap(); + let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap(); + assert_eq!(tree, tree_prime); + } + + #[test] + fn can_deserialize_non_standard_psbt_sighash_type() { + let non_standard_sighash = [222u8, 0u8, 0u8, 0u8]; // 32 byte value. + let sighash = PsbtSighashType::deserialize(&non_standard_sighash); + assert!(sighash.is_ok()) + } + + #[test] + fn deserialize_xonly_public_key_len() { + assert!(XOnlyPublicKey::deserialize(&[1; 31]).is_err()); + assert!(XOnlyPublicKey::deserialize(&[1; 33]).is_err()); + } + + #[test] + #[should_panic(expected = "InvalidMagic")] + fn invalid_vector_1() { + let hex_psbt = b"0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300"; + Psbt::deserialize(hex_psbt).unwrap(); + } +} diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs new file mode 100644 index 000000000..1e8760b06 --- /dev/null +++ b/bitcoin/src/sign_message.rs @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! A signature. +//! +//! This module provides signature related functions including secp256k1 signature recovery when +//! library is used with the `secp-recovery` feature. + +use hashes::{sha256d, HashEngine}; +#[cfg(feature = "secp-recovery")] +use secp256k1::SecretKey; + +use crate::consensus::encode::WriteExt; + +#[rustfmt::skip] +#[doc(inline)] +#[cfg(feature = "secp-recovery")] +pub use self::message_signing::{MessageSignature, MessageSignatureError}; + +/// The prefix for signed messages using Bitcoin's message signing protocol. +pub const BITCOIN_SIGNED_MSG_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n"; + +#[cfg(feature = "secp-recovery")] +mod message_signing { + use core::convert::Infallible; + use core::fmt; + + use hashes::sha256d; + use internals::write_err; + use secp256k1::ecdsa::{RecoverableSignature, RecoveryId}; + + use crate::address::{Address, AddressType}; + use crate::crypto::key::PublicKey; + + /// An error used for dealing with Bitcoin Signed Messages. + #[derive(Debug, Clone, PartialEq, Eq)] + #[non_exhaustive] + pub enum MessageSignatureError { + /// Signature is expected to be 65 bytes. + InvalidLength, + /// The signature is invalidly constructed. + InvalidEncoding(secp256k1::Error), + /// Invalid base64 encoding. + InvalidBase64, + /// Unsupported Address Type + UnsupportedAddressType(AddressType), + } + + impl From for MessageSignatureError { + fn from(never: Infallible) -> Self { match never {} } + } + + impl fmt::Display for MessageSignatureError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::InvalidLength => write!(f, "length not 65 bytes"), + Self::InvalidEncoding(ref e) => write_err!(f, "invalid encoding"; e), + Self::InvalidBase64 => write!(f, "invalid base64"), + Self::UnsupportedAddressType(ref address_type) => + write!(f, "unsupported address type: {}", address_type), + } + } + } + + #[cfg(feature = "std")] + impl std::error::Error for MessageSignatureError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidEncoding(ref e) => Some(e), + Self::InvalidLength | Self::InvalidBase64 | Self::UnsupportedAddressType(_) => None, + } + } + } + + impl From for MessageSignatureError { + fn from(e: secp256k1::Error) -> Self { + Self::InvalidEncoding(e) + } + } + + /// A signature on a Bitcoin Signed Message. + /// + /// In order to use the `to_base64` and `from_base64` methods, as well as the + /// `fmt::Display` and `str::FromStr` implementations, the `base64` feature + /// must be enabled. + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + pub struct MessageSignature { + /// The inner recoverable signature. + pub signature: RecoverableSignature, + /// Whether or not this signature was created with a compressed key. + pub compressed: bool, + } + + impl MessageSignature { + /// Constructs a new [MessageSignature]. + pub fn new(signature: RecoverableSignature, compressed: bool) -> Self { + Self { signature, compressed } + } + + /// Serializes to bytes. + pub fn serialize(&self) -> [u8; 65] { + let (recid, raw) = self.signature.serialize_compact(); + let mut serialized = [0u8; 65]; + serialized[0] = recid.to_u8() + if self.compressed { 31 } else { 27 }; + serialized[1..].copy_from_slice(&raw[..]); + serialized + } + + /// Constructs a new `MessageSignature` from a fixed-length array. + pub fn from_byte_array(bytes: &[u8; 65]) -> Result { + // We just check this here so we can safely subtract further. + if bytes[0] < 27 { + return Err(secp256k1::Error::InvalidRecoveryId); + }; + let recid = RecoveryId::try_from(((bytes[0] - 27) & 0x03) as i32)?; + Ok(Self { + signature: RecoverableSignature::from_compact(&bytes[1..], recid)?, + compressed: ((bytes[0] - 27) & 0x04) != 0, + }) + } + + /// Constructs a new `MessageSignature` from a byte slice. + #[deprecated(since = "TBD", note = "use `from_byte_array` instead")] + pub fn from_slice(bytes: &[u8]) -> Result { + let byte_array: [u8; 65] = + bytes.try_into().map_err(|_| MessageSignatureError::InvalidLength)?; + Self::from_byte_array(&byte_array).map_err(MessageSignatureError::from) + } + + /// Attempt to recover a public key from the signature and the signed message. + /// + /// To get the message hash from a message, use [super::signed_msg_hash]. + pub fn recover_pubkey( + &self, + msg_hash: sha256d::Hash, + ) -> Result { + let msg = secp256k1::Message::from_digest(msg_hash.to_byte_array()); + let pubkey = self.signature.recover_ecdsa(msg)?; + Ok(PublicKey { inner: pubkey, compressed: self.compressed }) + } + + /// Verifies that the signature signs the message and was signed by the given address. + /// + /// To get the message hash from a message, use [super::signed_msg_hash]. + pub fn is_signed_by_address( + &self, + address: &Address, + msg_hash: sha256d::Hash, + ) -> Result { + match address.address_type() { + Some(AddressType::P2pkh) => { + let pubkey = self.recover_pubkey(msg_hash)?; + Ok(address.pubkey_hash() == Some(pubkey.pubkey_hash())) + } + Some(address_type) => + Err(MessageSignatureError::UnsupportedAddressType(address_type)), + None => Ok(false), + } + } + } + + #[cfg(feature = "base64")] + mod base64_impls { + use base64::prelude::{Engine as _, BASE64_STANDARD}; + + use super::*; + use crate::prelude::String; + + impl MessageSignature { + /// Converts a signature from base64 encoding. + pub fn from_base64(s: &str) -> Result { + if s.len() != 88 { + return Err(MessageSignatureError::InvalidLength); + } + let mut byte_array = [0; 65]; + BASE64_STANDARD + .decode_slice_unchecked(s, &mut byte_array) + .map_err(|_| MessageSignatureError::InvalidBase64)?; + Self::from_byte_array(&byte_array).map_err(MessageSignatureError::from) + } + + /// Converts to base64 encoding. + pub fn to_base64(self) -> String { BASE64_STANDARD.encode(self.serialize()) } + } + + impl fmt::Display for MessageSignature { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let bytes = self.serialize(); + // This avoids the allocation of a String. + write!(f, "{}", base64::display::Base64Display::new(&bytes, &BASE64_STANDARD)) + } + } + + impl core::str::FromStr for MessageSignature { + type Err = MessageSignatureError; + fn from_str(s: &str) -> Result { + Self::from_base64(s) + } + } + } +} + +/// Hash message for signature using Bitcoin's message signing format. +pub fn signed_msg_hash(msg: impl AsRef<[u8]>) -> sha256d::Hash { + let msg_bytes = msg.as_ref(); + let mut engine = sha256d::Hash::engine(); + engine.input(BITCOIN_SIGNED_MSG_PREFIX); + engine.emit_compact_size(msg_bytes.len()).expect("engines don't error"); + engine.input(msg_bytes); + sha256d::Hash::from_engine(engine) +} + +/// Sign message using Bitcoin's message signing format. +#[cfg(feature = "secp-recovery")] +pub fn sign( + msg: impl AsRef<[u8]>, + privkey: SecretKey, +) -> MessageSignature { + use secp256k1::ecdsa::RecoverableSignature; + + let msg_hash = signed_msg_hash(msg); + let msg_to_sign = secp256k1::Message::from_digest(msg_hash.to_byte_array()); + let secp_sig = RecoverableSignature::sign_ecdsa_recoverable(msg_to_sign, &privkey); + MessageSignature { signature: secp_sig, compressed: true } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_signed_msg_hash() { + let hash = signed_msg_hash("test"); + assert_eq!( + hash.to_string(), + "a6f87fe6d58a032c320ff8d1541656f0282c2c7bfcc69d61af4c8e8ed528e49c" + ); + } + + #[test] + #[cfg(all(feature = "secp-recovery", feature = "base64", feature = "rand", feature = "std"))] + fn message_signature() { + use secp256k1::ecdsa::RecoverableSignature; + use crate::{Address, AddressType, Network, NetworkKind}; + + let message = "rust-bitcoin MessageSignature test"; + let msg_hash = super::signed_msg_hash(message); + let msg = secp256k1::Message::from_digest(msg_hash.to_byte_array()); + let privkey = secp256k1::SecretKey::new(&mut secp256k1::rand::rng()); + let secp_sig = RecoverableSignature::sign_ecdsa_recoverable(msg, &privkey); + let signature = super::MessageSignature { signature: secp_sig, compressed: true }; + + assert_eq!(signature.to_string(), super::sign(message, privkey).to_string()); + assert_eq!(signature.to_base64(), signature.to_string()); + let signature2 = &signature.to_string().parse::().unwrap(); + let pubkey = signature2 + .recover_pubkey(msg_hash) + .unwrap() + .try_into() + .expect("compressed was set to true"); + + let p2pkh = Address::p2pkh(pubkey, NetworkKind::Main); + assert_eq!(signature2.is_signed_by_address(&p2pkh, msg_hash), Ok(true)); + let p2wpkh = Address::p2wpkh(pubkey, Network::Bitcoin); + assert_eq!( + signature2.is_signed_by_address(&p2wpkh, msg_hash), + Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2wpkh)) + ); + let p2shwpkh = Address::p2shwpkh(pubkey, NetworkKind::Main); + assert_eq!( + signature2.is_signed_by_address(&p2shwpkh, msg_hash), + Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2sh)) + ); + let p2pkh = Address::p2pkh(pubkey, Network::Bitcoin); + assert_eq!(signature2.is_signed_by_address(&p2pkh, msg_hash), Ok(true)); + + assert_eq!(pubkey.0, secp256k1::PublicKey::from_secret_key(&privkey)); + let signature_base64 = signature.to_base64(); + let signature_round_trip = + super::MessageSignature::from_base64(&signature_base64).expect("message signature"); + assert_eq!(signature, signature_round_trip); + } + + #[test] + #[cfg(all(feature = "secp-recovery", feature = "base64"))] + fn incorrect_message_signature() { + use base64::prelude::{Engine as _, BASE64_STANDARD}; + + use crate::crypto::key::PublicKey; + use crate::{Address, NetworkKind}; + + let message = "a different message from what was signed"; + let msg_hash = super::signed_msg_hash(message); + + // Signature of msg = "rust-bitcoin MessageSignature test" + // Signed with pk "UuOGDsfLPr4HIMKQX0ipjJeRaj1geCq3yPUF2COP5ME=" + let signature_base64 = "IAM2qX24tYx/bdBTIgVLhD8QEAjrPlJpmjB4nZHdRYGIBa4DmVulAcwjPnWe6Q5iEwXH6F0pUCJP/ZeHPWS1h1o="; + let pubkey_base64 = "A1FTfMEntPpAty3qkEo0q2Dc1FEycI10a3jmwEFy+Qr6"; + let signature = + super::MessageSignature::from_base64(signature_base64).expect("message signature"); + + let pubkey = + PublicKey::from_slice(&BASE64_STANDARD.decode(pubkey_base64).expect("base64 string")) + .expect("pubkey slice"); + + let p2pkh = Address::p2pkh(pubkey, NetworkKind::Main); + assert_eq!(signature.is_signed_by_address(&p2pkh, msg_hash), Ok(false)); + } +} diff --git a/bitcoin/src/taproot/merkle_branch/borrowed.rs b/bitcoin/src/taproot/merkle_branch/borrowed.rs new file mode 100644 index 000000000..dea3a5ddf --- /dev/null +++ b/bitcoin/src/taproot/merkle_branch/borrowed.rs @@ -0,0 +1,281 @@ +use core::borrow::{Borrow, BorrowMut}; +use core::slice; + +use internals::slice::SliceExt; +pub use privacy_boundary::TaprootMerkleBranch; + +use super::{ + DecodeError, InvalidMerkleBranchSizeError, InvalidMerkleTreeDepthError, TapNodeHash, + TaprootMerkleBranchBuf, TAPROOT_CONTROL_MAX_NODE_COUNT, TAPROOT_CONTROL_NODE_SIZE, +}; + +/// Makes sure only the allowed conversions are accessible to external code. +mod privacy_boundary { + use super::*; + + internals::transparent_newtype! { + /// The Merkle proof for inclusion of a tree in a Taproot tree hash. + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct TaprootMerkleBranch([TapNodeHash]); + + impl TaprootMerkleBranch { + pub(super) const fn from_hashes_unchecked(hashes: &_) -> &Self; + pub(super) fn from_mut_hashes_unchecked(hashes: &mut _) -> &mut Self; + } + } + + impl TaprootMerkleBranch { + /// Returns a reference to the slice of hashes. + #[inline] + pub const fn as_slice(&self) -> &[TapNodeHash] { &self.0 } + + /// Returns a reference to the mutable slice of hashes. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [TapNodeHash] { &mut self.0 } + } +} + +impl TaprootMerkleBranch { + /// Returns an empty branch. + pub const fn new() -> &'static Self { Self::from_hashes_unchecked(&[]) } + + /// Returns the number of nodes in this Merkle proof. + #[inline] + pub fn len(&self) -> usize { self.as_slice().len() } + + /// Checks if this Merkle proof is empty. + #[inline] + pub fn is_empty(&self) -> bool { self.as_slice().is_empty() } + + /// Constructs an iterator over the node hashes. + #[inline] + pub fn iter(&self) -> core::slice::Iter<'_, TapNodeHash> { self.into_iter() } + + /// Constructs an iterator over the mutable node hashes. + #[inline] + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, TapNodeHash> { self.into_iter() } + + /// Casts `TaprootMerkleBranch` to a byte slice. + pub(crate) fn as_bytes(&self) -> &[u8] { + let ptr = self.as_slice().as_ptr(); + let num_bytes = self.len() * TAPROOT_CONTROL_NODE_SIZE; + // SAFETY: + // The pointer points to memory that's borrowed and the returned slice has the same + // lifetime. The alignment is of the types is the same (as checked in the test), the + // length is within the bounds - as computed above by multiplication. + unsafe { core::slice::from_raw_parts(ptr.cast::(), num_bytes) } + } + + /// Serializes to a writer. + /// + /// # Returns + /// + /// The number of bytes written to the writer. + pub fn encode(&self, writer: &mut Write) -> io::Result { + let bytes = self.as_bytes(); + writer.write_all(bytes)?; + Ok(bytes.len()) + } + + /// Zero-copy decodes `bytes` as Taproot Merkle branch. + /// + /// Note that "decoding" is quite trivial: it only performs appropriate bound checks and casts + /// the reference. + pub fn decode(bytes: &[u8]) -> Result<&Self, DecodeError> { + let (nodes, remainder) = bytes.bitcoin_as_chunks(); + if remainder.is_empty() { + Self::decode_exact(nodes).map_err(Into::into) + } else { + Err(InvalidMerkleBranchSizeError(bytes.len()).into()) + } + } + + /// Decodes a byte slice that is statically known to be multiple of 32. + /// + /// This can be used as a building block for other ways of decoding. + fn decode_exact( + nodes: &[[u8; TAPROOT_CONTROL_NODE_SIZE]], + ) -> Result<&Self, InvalidMerkleTreeDepthError> { + // SAFETY: `TapNodeHash` is `#[repr(transparent)]` and contains a (type which is + // `#[repr(transparent)]` and contains a) `[u8; 32]`. + Self::from_hashes(unsafe { + slice::from_raw_parts(nodes.as_ptr().cast::(), nodes.len()) + }) + } + + fn from_hashes(nodes: &[TapNodeHash]) -> Result<&Self, InvalidMerkleTreeDepthError> { + if nodes.len() <= TAPROOT_CONTROL_MAX_NODE_COUNT { + Ok(Self::from_hashes_unchecked(nodes)) + } else { + Err(InvalidMerkleTreeDepthError(nodes.len())) + } + } +} + +impl Default for &'_ TaprootMerkleBranch { + fn default() -> Self { TaprootMerkleBranch::new() } +} + +impl AsRef for TaprootMerkleBranch { + fn as_ref(&self) -> &Self { self } +} + +impl AsMut for TaprootMerkleBranch { + fn as_mut(&mut self) -> &mut Self { self } +} + +impl AsRef for TaprootMerkleBranchBuf { + fn as_ref(&self) -> &TaprootMerkleBranch { + // TaprootMerkleBranchBuf maintains the invariant that the node count is in range. + TaprootMerkleBranch::from_hashes_unchecked(self.as_slice()) + } +} + +impl AsMut for TaprootMerkleBranchBuf { + fn as_mut(&mut self) -> &mut TaprootMerkleBranch { + // TaprootMerkleBranchBuf maintains the invariant that the node count is in range. + TaprootMerkleBranch::from_mut_hashes_unchecked(self.as_mut_slice()) + } +} + +impl Borrow for TaprootMerkleBranchBuf { + #[inline] + fn borrow(&self) -> &TaprootMerkleBranch { self.as_ref() } +} + +impl BorrowMut for TaprootMerkleBranchBuf { + #[inline] + fn borrow_mut(&mut self) -> &mut TaprootMerkleBranch { self.as_mut() } +} + +impl<'a> TryFrom<&'a [TapNodeHash]> for &'a TaprootMerkleBranch { + type Error = InvalidMerkleTreeDepthError; + + fn try_from(value: &'a [TapNodeHash]) -> Result { + TaprootMerkleBranch::from_hashes(value) + } +} + +macro_rules! impl_from_array { + ($($len:expr),* $(,)?) => { + $( + impl AsRef for [TapNodeHash; $len] { + fn as_ref(&self) -> &TaprootMerkleBranch { + #[allow(unused_comparisons)] + const _: () = { assert!($len <= TAPROOT_CONTROL_MAX_NODE_COUNT) }; + // There's a static check to ensure correct macro usage above. + TaprootMerkleBranch::from_hashes_unchecked(self) + } + } + + impl AsMut for [TapNodeHash; $len] { + fn as_mut(&mut self) -> &mut TaprootMerkleBranch { + #[allow(unused_comparisons)] + const _: () = { assert!($len <= TAPROOT_CONTROL_MAX_NODE_COUNT) }; + // There's a static check to ensure correct macro usage above. + TaprootMerkleBranch::from_mut_hashes_unchecked(self) + } + } + + impl Borrow for [TapNodeHash; $len] { + fn borrow(&self) -> &TaprootMerkleBranch { + self.as_ref() + } + } + + impl BorrowMut for [TapNodeHash; $len] { + fn borrow_mut(&mut self) -> &mut TaprootMerkleBranch { + self.as_mut() + } + } + + impl<'a> From<&'a [TapNodeHash; $len]> for &'a TaprootMerkleBranch { + #[inline] + fn from(branch: &'a [TapNodeHash; $len]) -> Self { + branch.as_ref() + } + } + + impl<'a> From<&'a mut [TapNodeHash; $len]> for &'a mut TaprootMerkleBranch { + #[inline] + fn from(branch: &'a mut [TapNodeHash; $len]) -> Self { + branch.as_mut() + } + } + )* + } +} + +// Implement for all values [0, 128] inclusive. +// +// The reason zero is included is that `TaprootMerkleBranchBuf` doesn't contain the hash of the node +// that's being proven - it's not needed because the script is already right before control block. +impl_from_array!( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128 +); + +impl AsRef<[TapNodeHash]> for TaprootMerkleBranch { + #[inline] + fn as_ref(&self) -> &[TapNodeHash] { self.as_slice() } +} + +impl AsMut<[TapNodeHash]> for TaprootMerkleBranch { + #[inline] + fn as_mut(&mut self) -> &mut [TapNodeHash] { self.as_mut_slice() } +} + +impl Borrow<[TapNodeHash]> for TaprootMerkleBranch { + #[inline] + fn borrow(&self) -> &[TapNodeHash] { self.as_ref() } +} + +impl BorrowMut<[TapNodeHash]> for TaprootMerkleBranch { + #[inline] + fn borrow_mut(&mut self) -> &mut [TapNodeHash] { self.as_mut() } +} + +impl alloc::borrow::ToOwned for TaprootMerkleBranch { + // It could be argued that this should've been a stack-allocated type. + // However such type would be huge and this trait interacts with `Cow`. + // If someone wants to pass it around they're better off just always copying rather than using + // `Cow`. + type Owned = TaprootMerkleBranchBuf; + + fn to_owned(&self) -> Self::Owned { self.into() } +} + +impl<'a> IntoIterator for &'a TaprootMerkleBranch { + type IntoIter = core::slice::Iter<'a, TapNodeHash>; + type Item = &'a TapNodeHash; + + fn into_iter(self) -> Self::IntoIter { self.as_slice().iter() } +} + +impl<'a> IntoIterator for &'a mut TaprootMerkleBranch { + type IntoIter = core::slice::IterMut<'a, TapNodeHash>; + type Item = &'a mut TapNodeHash; + + #[inline] + fn into_iter(self) -> Self::IntoIter { self.as_mut_slice().iter_mut() } +} + +#[cfg(test)] +mod tests { + #[test] + fn alignment() { + assert!( + core::mem::align_of_val(super::TaprootMerkleBranch::new()) + == core::mem::align_of::() + ); + } + + const _: () = { + assert!(core::mem::size_of::() == super::TAPROOT_CONTROL_NODE_SIZE); + assert!(core::mem::align_of::() == core::mem::align_of::()); + }; +} diff --git a/bitcoin/src/taproot/merkle_branch/buf.rs b/bitcoin/src/taproot/merkle_branch/buf.rs new file mode 100644 index 000000000..4655b604b --- /dev/null +++ b/bitcoin/src/taproot/merkle_branch/buf.rs @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Contains `TaprootMerkleBranchBuf` and its associated types. + +use hashes::Hash; + +use super::{ + InvalidMerkleTreeDepthError, TapNodeHash, TaprootError, TaprootMerkleBranch, + TAPROOT_CONTROL_MAX_NODE_COUNT, +}; +use crate::prelude::{Borrow, BorrowMut, Box, Vec}; + +/// The Merkle proof for inclusion of a tree in a Taproot tree hash. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(into = "Vec"))] +#[cfg_attr(feature = "serde", serde(try_from = "Vec"))] +pub struct TaprootMerkleBranchBuf(Vec); + +impl TaprootMerkleBranchBuf { + /// Returns a reference to the slice of hashes. + #[deprecated(since = "0.32.0", note = "use `as_slice` instead")] + #[inline] + pub fn as_inner(&self) -> &[TapNodeHash] { &self.0 } + + /// Returns a reference to the slice of hashes. + #[inline] + pub fn as_slice(&self) -> &[TapNodeHash] { &self.0 } + + /// Returns a mutable reference to the slice of hashes. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [TapNodeHash] { &mut self.0 } + + /// Returns the number of nodes in this Merkle proof. + #[inline] + pub fn len(&self) -> usize { self.0.len() } + + /// Checks if this Merkle proof is empty. + #[inline] + pub fn is_empty(&self) -> bool { self.0.is_empty() } + + /// Decodes bytes from control block. + /// + /// This reads the branch as encoded in the control block: the concatenated 32B byte chunks - + /// one for each hash. + /// + /// # Errors + /// + /// The function returns an error if the number of bytes is not an integer multiple of 32 or + /// if the number of hashes exceeds 128. + pub fn decode(sl: &[u8]) -> Result { + TaprootMerkleBranch::decode(sl).map(alloc::borrow::ToOwned::to_owned).map_err(Into::into) + } + + /// Constructs a new Merkle proof from list of hashes. + /// + /// # Errors + /// + /// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128). + #[inline] + fn from_collection + Into>>( + collection: T, + ) -> Result { + if collection.as_ref().len() > TAPROOT_CONTROL_MAX_NODE_COUNT { + Err(InvalidMerkleTreeDepthError(collection.as_ref().len())) + } else { + Ok(Self(collection.into())) + } + } + + /// Serializes to a writer. + /// + /// # Returns + /// + /// The number of bytes written to the writer. + pub fn encode(&self, writer: &mut Write) -> io::Result { + for hash in self { + writer.write_all(hash.as_ref())?; + } + Ok(self.len() * TapNodeHash::LEN) + } + + /// Serializes `self` as bytes. + pub fn serialize(&self) -> Vec { + self.iter().flat_map(|e| e.as_byte_array()).copied().collect::>() + } + + /// Appends elements to proof. + pub(in super::super) fn push( + &mut self, + h: TapNodeHash, + ) -> Result<(), InvalidMerkleTreeDepthError> { + if self.len() >= TAPROOT_CONTROL_MAX_NODE_COUNT { + Err(InvalidMerkleTreeDepthError(self.0.len())) + } else { + self.0.push(h); + Ok(()) + } + } + + /// Returns the inner list of hashes. + #[deprecated(since = "0.32.0", note = "use `into_vec` instead")] + #[inline] + pub fn into_inner(self) -> Vec { self.0 } + + /// Returns the list of hashes stored in a `Vec`. + #[inline] + pub fn into_vec(self) -> Vec { self.0 } +} + +macro_rules! impl_try_from { + ($from:ty) => { + impl TryFrom<$from> for TaprootMerkleBranchBuf { + type Error = InvalidMerkleTreeDepthError; + + /// Constructs a new Merkle proof from list of hashes. + /// + /// # Errors + /// + /// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128). + #[inline] + fn try_from(v: $from) -> Result { + TaprootMerkleBranchBuf::from_collection(v) + } + } + }; +} +impl_try_from!(&[TapNodeHash]); +impl_try_from!(Vec); +impl_try_from!(Box<[TapNodeHash]>); + +macro_rules! impl_from_array { + ($($len:expr),* $(,)?) => { + $( + impl From<[TapNodeHash; $len]> for TaprootMerkleBranchBuf { + #[inline] + fn from(a: [TapNodeHash; $len]) -> Self { + Self(a.to_vec()) + } + } + )* + } +} +// Implement for all values [0, 128] inclusive. +// +// The reason zero is included is that `TaprootMerkleBranchBuf` doesn't contain the hash of the node +// that's being proven - it's not needed because the script is already right before control block. +impl_from_array!( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128 +); + +impl From for Vec { + #[inline] + fn from(branch: TaprootMerkleBranchBuf) -> Self { branch.0 } +} + +impl IntoIterator for TaprootMerkleBranchBuf { + type IntoIter = IntoIter; + type Item = TapNodeHash; + + #[inline] + fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter()) } +} + +impl<'a> IntoIterator for &'a TaprootMerkleBranchBuf { + type IntoIter = core::slice::Iter<'a, TapNodeHash>; + type Item = &'a TapNodeHash; + + #[inline] + fn into_iter(self) -> Self::IntoIter { self.0.iter() } +} + +impl<'a> IntoIterator for &'a mut TaprootMerkleBranchBuf { + type IntoIter = core::slice::IterMut<'a, TapNodeHash>; + type Item = &'a mut TapNodeHash; + + #[inline] + fn into_iter(self) -> Self::IntoIter { self.0.iter_mut() } +} + +impl core::ops::Deref for TaprootMerkleBranchBuf { + type Target = TaprootMerkleBranch; + + #[inline] + fn deref(&self) -> &Self::Target { self.as_ref() } +} + +impl core::ops::DerefMut for TaprootMerkleBranchBuf { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } +} + +impl AsRef<[TapNodeHash]> for TaprootMerkleBranchBuf { + #[inline] + fn as_ref(&self) -> &[TapNodeHash] { &self.0 } +} + +impl AsMut<[TapNodeHash]> for TaprootMerkleBranchBuf { + #[inline] + fn as_mut(&mut self) -> &mut [TapNodeHash] { &mut self.0 } +} + +impl Borrow<[TapNodeHash]> for TaprootMerkleBranchBuf { + #[inline] + fn borrow(&self) -> &[TapNodeHash] { &self.0 } +} + +impl BorrowMut<[TapNodeHash]> for TaprootMerkleBranchBuf { + #[inline] + fn borrow_mut(&mut self) -> &mut [TapNodeHash] { &mut self.0 } +} + +impl<'a> From<&'a TaprootMerkleBranch> for TaprootMerkleBranchBuf { + fn from(value: &'a TaprootMerkleBranch) -> Self { Self(value.as_slice().into()) } +} + +/// Iterator over node hashes within Taproot Merkle branch. +/// +/// This is created by `into_iter` method on `TaprootMerkleBranchBuf` (via `IntoIterator` trait). +#[derive(Clone, Debug)] +pub struct IntoIter(alloc::vec::IntoIter); + +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + #[inline] + pub fn as_slice(&self) -> &[TapNodeHash] { self.0.as_slice() } + + /// Returns the remaining items of this iterator as a mutable slice. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [TapNodeHash] { self.0.as_mut_slice() } +} + +impl Iterator for IntoIter { + type Item = TapNodeHash; + + #[inline] + fn next(&mut self) -> Option { self.0.next() } + + #[inline] + fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } + + #[inline] + fn nth(&mut self, n: usize) -> Option { self.0.nth(n) } + + #[inline] + #[allow(clippy::double_ended_iterator_last)] // False positive. Using `.last()` on a `vec::IntoIter` is correct. + fn last(self) -> Option { self.0.last() } + + #[inline] + fn count(self) -> usize { self.0.count() } +} + +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { self.0.next_back() } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { self.0.nth_back(n) } +} + +impl ExactSizeIterator for IntoIter {} + +impl core::iter::FusedIterator for IntoIter {} diff --git a/bitcoin/src/taproot/merkle_branch/mod.rs b/bitcoin/src/taproot/merkle_branch/mod.rs new file mode 100644 index 000000000..56a142345 --- /dev/null +++ b/bitcoin/src/taproot/merkle_branch/mod.rs @@ -0,0 +1,71 @@ +//! Contains `TaprootMerkleBranchBuf` and its associated types. + +mod borrowed; +mod buf; + +use core::fmt; + +pub use borrowed::TaprootMerkleBranch; +pub use buf::TaprootMerkleBranchBuf; + +use super::{ + InvalidMerkleBranchSizeError, InvalidMerkleTreeDepthError, TapNodeHash, TaprootError, + TAPROOT_CONTROL_MAX_NODE_COUNT, TAPROOT_CONTROL_NODE_SIZE, +}; + +/// Returned when decoding of merkle branch fails. +#[derive(Debug)] +pub struct DecodeError { + /// Represents the invalid number of bytes. It may be invalid in two ways: it might not be a + /// multiple of 32, in which case it is guaranteed to be wrong for that reason; + /// only if it is a multiple of 32 do we check that it does not exceed 32 * 128, in which case + /// it is wrong for that reason. + /// + /// This error type is used in `Result<&TaprootMerkleBranch, DecodeError>`, so by keeping its + /// size down to a single `usize` (by not using enum) and considering the niche optimization on + /// the *fat reference* `&TaprootMerkleBranch`, the `Result` will have the same size as just + /// `&TaprootMerkleBranch`. + num_bytes: usize, +} + +impl From for DecodeError { + fn from(value: InvalidMerkleBranchSizeError) -> Self { Self { num_bytes: value.0 } } +} + +impl From for DecodeError { + fn from(value: InvalidMerkleTreeDepthError) -> Self { + Self { num_bytes: value.0 * TAPROOT_CONTROL_NODE_SIZE } + } +} + +impl fmt::Display for DecodeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.num_bytes % TAPROOT_CONTROL_NODE_SIZE == 0 { + write!( + f, + "the Merkle branch has {} nodes which is more than the limit {}", + self.num_bytes / TAPROOT_CONTROL_NODE_SIZE, + TAPROOT_CONTROL_MAX_NODE_COUNT + ) + } else { + write!( + f, + "the Merkle branch is {} bytes long which is not an integer multiple of {}", + self.num_bytes, TAPROOT_CONTROL_NODE_SIZE + ) + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeError {} + +impl From for TaprootError { + fn from(value: DecodeError) -> Self { + if value.num_bytes % TAPROOT_CONTROL_NODE_SIZE == 0 { + InvalidMerkleTreeDepthError(value.num_bytes / TAPROOT_CONTROL_NODE_SIZE).into() + } else { + InvalidMerkleBranchSizeError(value.num_bytes).into() + } + } +} diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs new file mode 100644 index 000000000..6e3c63a6e --- /dev/null +++ b/bitcoin/src/taproot/mod.rs @@ -0,0 +1,2087 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Taproot. +//! +//! This module provides support for Taproot tagged hashes. + +pub mod merkle_branch; + +use core::cmp::{Ordering, Reverse}; +use core::convert::Infallible; +use core::fmt; +use core::iter::FusedIterator; + +use hashes::{hash_newtype, sha256t, sha256t_tag, HashEngine}; +use hex::{FromHex, HexToBytesError}; +use internals::array::ArrayExt; +#[allow(unused)] // MSRV polyfill +use internals::slice::SliceExt; +use internals::{impl_to_hex_from_lower_hex, write_err}; +use io::Write; +use secp256k1::Scalar; + +use crate::consensus::Encodable; +use crate::crypto::key::{ + SerializedXOnlyPublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey, +}; +use crate::key::ParseXOnlyPublicKeyError; +use crate::prelude::{BTreeMap, BTreeSet, BinaryHeap, Vec}; +use crate::{TapScript, TapScriptBuf}; + +// Re-export these so downstream only has to use one `taproot` module. +#[rustfmt::skip] +#[doc(inline)] +pub use crate::crypto::taproot::{SerializedSignature, SigFromSliceError, Signature}; +#[doc(inline)] +pub use merkle_branch::TaprootMerkleBranch; +#[doc(inline)] +pub use merkle_branch::TaprootMerkleBranchBuf; + +#[doc(inline)] +pub use crate::XOnlyPublicKey; + +type ControlBlockArrayVec = internals::array_vec::ArrayVec; + +// Taproot test vectors from BIP-0341 state the hashes without any reversing +sha256t_tag! { + pub struct TapLeafTag = hash_str("TapLeaf"); +} + +hash_newtype! { + /// Taproot-tagged hash with tag \"TapLeaf\". + /// + /// This is used for computing tapscript script spend hash. + pub struct TapLeafHash(sha256t::Hash); +} + +hashes::impl_hex_for_newtype!(TapLeafHash); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(TapLeafHash); + +sha256t_tag! { + pub struct TapBranchTag = hash_str("TapBranch"); +} + +hash_newtype! { + /// Tagged hash used in Taproot trees. + /// + /// See BIP-0340 for tagging rules. + #[repr(transparent)] + pub struct TapNodeHash(sha256t::Hash); +} + +hashes::impl_hex_for_newtype!(TapNodeHash); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(TapNodeHash); + +sha256t_tag! { + pub struct TapTweakTag = hash_str("TapTweak"); +} + +hash_newtype! { + /// Taproot-tagged hash with tag \"TapTweak\". + /// + /// This hash type is used while computing the tweaked public key. + pub struct TapTweakHash(sha256t::Hash); +} + +hashes::impl_hex_for_newtype!(TapTweakHash); +#[cfg(feature = "serde")] +hashes::impl_serde_for_newtype!(TapTweakHash); + +impl From for TapNodeHash { + fn from(leaf: TapLeafHash) -> Self { Self::from_byte_array(leaf.to_byte_array()) } +} + +impl TapTweakHash { + /// Constructs a new BIP-0341 [`TapTweakHash`] from key and Merkle root. Produces `H_taptweak(P||R)` where + /// `P` is the internal key and `R` is the Merkle root. + pub fn from_key_and_merkle_root>( + internal_key: K, + merkle_root: Option, + ) -> Self { + let internal_key = internal_key.into(); + let mut eng = sha256t::Hash::::engine(); + // always hash the key + eng.input(&internal_key.serialize()); + if let Some(h) = merkle_root { + eng.input(h.as_ref()); + } else { + // nothing to hash + } + let inner = sha256t::Hash::::from_engine(eng); + Self::from_byte_array(inner.to_byte_array()) + } + + /// Converts a `TapTweakHash` into a `Scalar` ready for use with key tweaking API. + pub fn to_scalar(self) -> Scalar { + // This is statistically extremely unlikely to panic. + Scalar::from_be_bytes(self.to_byte_array()).expect("hash value greater than curve order") + } +} + +impl TapLeafHash { + /// Computes the leaf hash from components. + pub fn from_script(script: &TapScript, ver: LeafVersion) -> Self { + let mut eng = sha256t::Hash::::engine(); + ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error"); + script.consensus_encode(&mut eng).expect("engines don't error"); + let inner = sha256t::Hash::::from_engine(eng); + Self::from_byte_array(inner.to_byte_array()) + } +} + +impl From for TapNodeHash { + fn from(leaf: LeafNode) -> Self { leaf.node_hash() } +} + +impl From<&LeafNode> for TapNodeHash { + fn from(leaf: &LeafNode) -> Self { leaf.node_hash() } +} + +impl TapNodeHash { + /// Computes branch hash given two hashes of the nodes underneath it. + pub fn from_node_hashes(a: Self, b: Self) -> Self { + combine_node_hashes(a, b).0 + } + + /// Assumes the given 32 byte array as hidden [`TapNodeHash`]. + /// + /// Similar to [`TapLeafHash::from_byte_array`], but explicitly conveys that the + /// hash is constructed from a hidden node. This also has better ergonomics + /// because it does not require the caller to import the Hash trait. + pub fn assume_hidden(hash: [u8; 32]) -> Self { Self::from_byte_array(hash) } + + /// Computes the [`TapNodeHash`] from a script and a leaf version. + pub fn from_script(script: &TapScript, ver: LeafVersion) -> Self { + Self::from(TapLeafHash::from_script(script, ver)) + } +} + +/// Computes branch hash given two hashes of the nodes underneath it and returns +/// whether the left node was the one hashed first. +fn combine_node_hashes(a: TapNodeHash, b: TapNodeHash) -> (TapNodeHash, bool) { + let mut eng = sha256t::Hash::::engine(); + if a < b { + eng.input(a.as_ref()); + eng.input(b.as_ref()); + } else { + eng.input(b.as_ref()); + eng.input(a.as_ref()); + }; + let inner = sha256t::Hash::::from_engine(eng); + (TapNodeHash::from_byte_array(inner.to_byte_array()), a < b) +} + +/// Maximum depth of a Taproot tree script spend path. +// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L229 +pub const TAPROOT_CONTROL_MAX_NODE_COUNT: usize = 128; +/// Size of a Taproot control node. +// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L228 +pub const TAPROOT_CONTROL_NODE_SIZE: usize = 32; +/// Tapleaf mask for getting the leaf version from first byte of control block. +// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L225 +pub const TAPROOT_LEAF_MASK: u8 = 0xfe; +/// Tapscript leaf version. +// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L226 +pub const TAPROOT_LEAF_TAPSCRIPT: u8 = 0xc0; +/// Taproot annex prefix. +pub const TAPROOT_ANNEX_PREFIX: u8 = 0x50; +/// Tapscript control base size. +// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L227 +pub const TAPROOT_CONTROL_BASE_SIZE: usize = 33; +/// Tapscript control max size. +// https://github.com/bitcoin/bitcoin/blob/e826b22da252e0599c61d21c98ff89f366b3120f/src/script/interpreter.h#L230 +pub const TAPROOT_CONTROL_MAX_SIZE: usize = + TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT; + +/// The leaf script with its version. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct LeafScript { + /// The version of the script. + pub version: LeafVersion, + /// The script, usually `TapScriptBuf` or `&TapScript`. + pub script: S, +} + +// type alias for versioned tap script corresponding Merkle proof +type ScriptMerkleProofMap = BTreeMap<(TapScriptBuf, LeafVersion), BTreeSet>; + +/// Represents Taproot spending information. +/// +/// Taproot output corresponds to a combination of a single public key condition (known as the +/// internal key), and zero or more general conditions encoded in scripts organized in the form of a +/// binary tree. +/// +/// Taproot can be spent by either: +/// - Spending using the key path i.e., with secret key corresponding to the tweaked `output_key`. +/// - By satisfying any of the scripts in the script spend path. Each script can be satisfied by +/// providing a witness stack consisting of the script's inputs, plus the script itself and the +/// control block. +/// +/// If one or more of the spending conditions consist of just a single key (after aggregation), the +/// most likely key should be made the internal key. See [BIP-0341] for more details on choosing +/// internal keys for a Taproot application. +/// +/// Note: This library currently does not support +/// [annex](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-5). +/// +/// [BIP-0341]: +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TaprootSpendInfo { + /// The BIP-0341 internal key. + internal_key: UntweakedPublicKey, + /// The Merkle root of the script tree (None if there are no scripts). + merkle_root: Option, + /// The sign final output pubkey as per BIP 341. + output_key_parity: secp256k1::Parity, + /// The tweaked output key. + output_key: TweakedPublicKey, + /// Map from (script, leaf_version) to (sets of) [`TaprootMerkleBranchBuf`]. More than one control + /// block for a given script is only possible if it appears in multiple branches of the tree. In + /// all cases, keeping one should be enough for spending funds, but we keep all of the paths so + /// that a full tree can be constructed again from spending data if required. + script_map: ScriptMerkleProofMap, +} + +impl TaprootSpendInfo { + /// Constructs a new [`TaprootSpendInfo`] from a list of scripts (with default script version) and + /// weights of satisfaction for that script. + /// + /// See [`TaprootBuilder::with_huffman_tree`] for more detailed documentation. + pub fn with_huffman_tree( + internal_key: K, + script_weights: I, + ) -> Result + where + I: IntoIterator, + K: Into, + { + let builder = TaprootBuilder::with_huffman_tree(script_weights)?; + Ok(builder.finalize(internal_key).expect("Huffman tree is always complete")) + } + + /// Constructs a new key spend with `internal_key` and `merkle_root`. Provide [`None`] for + /// the `merkle_root` if there is no script path. + /// + /// *Note*: As per BIP-0341 + /// + /// When the Merkle root is [`None`], the output key commits to an unspendable script path + /// instead of having no script path. This is achieved by computing the output key point as + /// `Q = P + int(hashTapTweak(bytes(P)))G`. See also [`TaprootSpendInfo::tap_tweak`]. + /// + /// Refer to BIP 341 footnote ('Why should the output key always have a Taproot commitment, even + /// if there is no script path?') for more details. + pub fn new_key_spend>( + internal_key: K, + merkle_root: Option, + ) -> Self { + let internal_key = internal_key.into(); + let (output_key, parity) = internal_key.tap_tweak(merkle_root); + Self { + internal_key, + merkle_root, + output_key_parity: parity, + output_key, + script_map: BTreeMap::new(), + } + } + + /// Returns the `TapTweakHash` for this [`TaprootSpendInfo`] i.e., the tweak using `internal_key` + /// and `merkle_root`. + pub fn tap_tweak(&self) -> TapTweakHash { + TapTweakHash::from_key_and_merkle_root(self.internal_key, self.merkle_root) + } + + /// Returns the internal key for this [`TaprootSpendInfo`]. + pub fn internal_key(&self) -> UntweakedPublicKey { self.internal_key } + + /// Returns the Merkle root for this [`TaprootSpendInfo`]. + pub fn merkle_root(&self) -> Option { self.merkle_root } + + /// Returns the output key (the key used in script pubkey) for this [`TaprootSpendInfo`]. + pub fn output_key(&self) -> TweakedPublicKey { self.output_key } + + /// Returns the parity of the output key. See also [`TaprootSpendInfo::output_key`]. + pub fn output_key_parity(&self) -> secp256k1::Parity { self.output_key_parity } + + /// Returns a reference to the internal script map. + pub fn script_map(&self) -> &ScriptMerkleProofMap { &self.script_map } + + /// Computes the [`TaprootSpendInfo`] from `internal_key` and `node`. + /// + /// This is useful when you want to manually build a Taproot tree without using + /// [`TaprootBuilder`]. + pub fn from_node_info>( + internal_key: K, + node: NodeInfo, + ) -> Self { + // Create as if it is a key spend path with the given Merkle root + let root_hash = Some(node.hash); + let mut info = Self::new_key_spend(internal_key, root_hash); + + for leaves in node.leaves { + match leaves.leaf { + TapLeaf::Hidden(_) => { + // We don't store any information about hidden nodes in TaprootSpendInfo. + } + TapLeaf::Script(script, ver) => { + let key = (script, ver); + let value = leaves.merkle_branch; + match info.script_map.get_mut(&key) { + None => { + let mut set = BTreeSet::new(); + set.insert(value); + info.script_map.insert(key, set); + } + Some(set) => { + set.insert(value); + } + } + } + } + } + info + } + + /// Constructs a new [`ControlBlock`] for particular script with the given version. + /// + /// # Returns + /// + /// - If there are multiple control blocks possible, returns the shortest one. + /// - If the script is not contained in the [`TaprootSpendInfo`], returns `None`. + pub fn control_block(&self, script_ver: &(TapScriptBuf, LeafVersion)) -> Option { + let merkle_branch_set = self.script_map.get(script_ver)?; + // Choose the smallest one amongst the multiple script maps + let smallest = merkle_branch_set + .iter() + .min_by(|x, y| x.len().cmp(&y.len())) + .expect("Invariant: TapScriptBuf map key must contain non-empty set value"); + Some(ControlBlock { + internal_key: self.internal_key, + output_key_parity: self.output_key_parity, + leaf_version: script_ver.1, + merkle_branch: smallest.clone(), + }) + } +} + +impl From for TapTweakHash { + fn from(spend_info: TaprootSpendInfo) -> Self { spend_info.tap_tweak() } +} + +impl From<&TaprootSpendInfo> for TapTweakHash { + fn from(spend_info: &TaprootSpendInfo) -> Self { spend_info.tap_tweak() } +} + +/// Builder for building Taproot iteratively. Users can specify tap leaf or omitted/hidden branches +/// in a depth-first search (DFS) walk order to construct this tree. +/// +/// See Wikipedia for more details on [DFS](https://en.wikipedia.org/wiki/Depth-first_search). +// Similar to Taproot Builder in Bitcoin Core. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TaprootBuilder { + // The following doc-comment is from Bitcoin Core, but modified for Rust. It describes the + // current state of the builder for a given tree. + // + // For each level in the tree, one NodeInfo object may be present. Branch at index 0 is + // information about the root; further values are for deeper subtrees being explored. + // + // During the construction of [`TapTree`], for every right branch taken to reach the position we're + // currently working on, there will be a `(Some(_))` entry in branch corresponding to the left + // branch at that level. + // + // For example, imagine this tree: - N0 - + // / \ + // N1 N2 + // / \ / \ + // A B C N3 + // / \ + // D E + // + // Initially, branch is empty. After processing leaf A, it would become {None, None, A}. When + // processing leaf B, an entry at level 2 already exists, and it would thus be combined with it + // to produce a level 1 entry, resulting in {None, N1}. Adding C and D takes us to {None, N1, C} + // and {None, N1, C, D} respectively. When E is processed, it is combined with D, and then C, + // and then N1, to produce the root, resulting in {N0}. + // + // This structure allows processing with just O(log n) overhead if the leaves are computed on + // the fly. + // + // As an invariant, there can never be None entries at the end. There can also not be more than + // 128 entries (as that would mean more than 128 levels in the tree). The depth of newly added + // entries will always be at least equal to the current size of branch (otherwise it does not + // correspond to a depth-first traversal of a tree). A branch is only empty if no entries have + // ever been processed. A branch having length 1 corresponds to being done. + branch: Vec>, +} + +impl TaprootBuilder { + /// Constructs a new instance of [`TaprootBuilder`]. + pub fn new() -> Self { Self { branch: vec![] } } + + /// Constructs a new instance of [`TaprootBuilder`] with a capacity hint for `size` elements. + /// + /// The size here should be maximum depth of the tree. + pub fn with_capacity(size: usize) -> Self { + Self { branch: Vec::with_capacity(size) } + } + + /// Constructs a new [`TaprootSpendInfo`] from a list of scripts (with default script version) and + /// weights of satisfaction for that script. + /// + /// The weights represent the probability of each branch being taken. If probabilities/weights + /// for each condition are known, constructing the tree as a Huffman tree is the optimal way to + /// minimize average case satisfaction cost. This function takes as input an iterator of + /// `tuple(u32, TapScriptBuf)` where `u32` represents the satisfaction weights of the branch. For + /// example, [(3, S1), (2, S2), (5, S3)] would construct a [`TapTree`] that has optimal + /// satisfaction weight when probability for S1 is 30%, S2 is 20% and S3 is 50%. + /// + /// # Errors + /// + /// - When the optimal Huffman tree has a depth more than 128. + /// - If the provided list of script weights is empty. + /// + /// # Edge Cases + /// + /// If the script weight calculations overflow, a sub-optimal tree may be generated. This should + /// not happen unless you are dealing with billions of branches with weights close to 2^32. + /// + /// [`TapTree`]: crate::taproot::TapTree + pub fn with_huffman_tree(script_weights: I) -> Result + where + I: IntoIterator, + { + let mut node_weights = BinaryHeap::<(Reverse, NodeInfo)>::new(); + for (p, leaf) in script_weights { + node_weights + .push((Reverse(p), NodeInfo::new_leaf_with_ver(leaf, LeafVersion::TapScript))); + } + if node_weights.is_empty() { + return Err(TaprootBuilderError::EmptyTree); + } + while node_weights.len() > 1 { + // Combine the last two elements and insert a new node + let (p1, s1) = node_weights.pop().expect("len must be at least two"); + let (p2, s2) = node_weights.pop().expect("len must be at least two"); + // Insert the sum of first two in the tree as a new node + // N.B.: p1 + p2 can not practically saturate as you would need to have 2**32 max u32s + // from the input to overflow. However, saturating is a reasonable behavior here as + // Huffman tree construction would treat all such elements as "very likely". + let p = Reverse(p1.0.saturating_add(p2.0)); + node_weights.push((p, NodeInfo::combine(s1, s2)?)); + } + // Every iteration of the loop reduces the node_weights.len() by exactly 1 + // Therefore, the loop will eventually terminate with exactly 1 element + debug_assert_eq!(node_weights.len(), 1); + let node = node_weights.pop().expect("Huffman tree algorithm is broken").1; + Ok(Self { branch: vec![Some(node)] }) + } + + /// Adds a leaf script at `depth` to the builder with script version `ver`. + /// + /// The depth of the root node is 0. + /// + /// # Errors + /// + /// Errors if the leaves are not provided in DFS walk order. + pub fn add_leaf_with_ver( + self, + depth: u8, + script: TapScriptBuf, + ver: LeafVersion, + ) -> Result { + let leaf = NodeInfo::new_leaf_with_ver(script, ver); + self.insert(leaf, depth) + } + + /// Adds a leaf script at `depth` to the builder with default script version. + /// + /// The depth of the root node is 0. + /// + /// See [`TaprootBuilder::add_leaf_with_ver`] for adding a leaf with specific version. + /// + /// # Errors + /// + /// Errors if the leaves are not provided in DFS walk order. + pub fn add_leaf(self, depth: u8, script: TapScriptBuf) -> Result { + self.add_leaf_with_ver(depth, script, LeafVersion::TapScript) + } + + /// Adds a hidden/omitted node at `depth` to the builder. + /// + /// The depth of the root node is 0. + /// + /// # Errors + /// + /// Errors if the leaves are not provided in DFS walk order. + pub fn add_hidden_node( + self, + depth: u8, + hash: TapNodeHash, + ) -> Result { + let node = NodeInfo::new_hidden_node(hash); + self.insert(node, depth) + } + + /// Checks if the builder has finalized building a tree. + pub fn is_finalizable(&self) -> bool { self.branch.len() == 1 && self.branch[0].is_some() } + + /// Converts the builder into a [`NodeInfo`] if the builder is a full tree with possibly + /// hidden nodes + /// + /// # Errors + /// + /// [`IncompleteBuilderError::NotFinalized`] if the builder is not finalized. The builder + /// can be restored by calling [`IncompleteBuilderError::into_builder`] + pub fn try_into_node_info(mut self) -> Result { + if self.branch().len() != 1 { + return Err(IncompleteBuilderError::NotFinalized(self)); + } + Ok(self + .branch + .pop() + .expect("length checked above") + .expect("invariant guarantees node info exists")) + } + + /// Converts the builder into a [`TapTree`] if the builder is a full tree and + /// does not contain any hidden nodes + #[deprecated(since = "TBD", note = "use `try_into_tap_tree()` instead")] + #[doc(hidden)] + pub fn try_into_taptree(self) -> Result { + self.try_into_tap_tree() + } + + /// Converts the builder into a [`TapTree`] if the builder is a full tree and + /// does not contain any hidden nodes. + /// + /// This function finalizes the taproot construction process by validating that the builder + /// is complete, and there are no hidden nodes, which would make the tree incomplete or ambiguous. + /// + /// # Errors + /// + /// Returns [`IncompleteBuilderError::HiddenParts`] if the builder contains any hidden nodes. + pub fn try_into_tap_tree(self) -> Result { + let node = self.try_into_node_info()?; + if node.has_hidden_nodes { + // Reconstruct the builder as it was if it has hidden nodes + return Err(IncompleteBuilderError::HiddenParts(Self { + branch: vec![Some(node)], + })); + } + Ok(TapTree(node)) + } + + /// Checks if the builder has hidden nodes. + pub fn has_hidden_nodes(&self) -> bool { + self.branch.iter().flatten().any(|node| node.has_hidden_nodes) + } + + /// Constructs a new [`TaprootSpendInfo`] with the given internal key. + /// + /// Returns the unmodified builder as Err if the builder is not finalizable. + /// See also [`TaprootBuilder::is_finalizable`] + pub fn finalize>( + mut self, + internal_key: K, + ) -> Result { + let internal_key = internal_key.into(); + match self.branch.len() { + 0 => Ok(TaprootSpendInfo::new_key_spend(internal_key, None)), + 1 => + if let Some(Some(node)) = self.branch.pop() { + Ok(TaprootSpendInfo::from_node_info(internal_key, node)) + } else { + unreachable!("size checked above. Builder guarantees the last element is Some") + }, + _ => Err(self), + } + } + + pub(crate) fn branch(&self) -> &[Option] { &self.branch } + + /// Inserts a leaf at `depth`. + fn insert(mut self, mut node: NodeInfo, mut depth: u8) -> Result { + // early error on invalid depth. Though this will be checked later + // while constructing TaprootMerkleBranch + if depth as usize > TAPROOT_CONTROL_MAX_NODE_COUNT { + return Err(InvalidMerkleTreeDepthError(depth as usize).into()); + } + // We cannot insert a leaf at a lower depth while a deeper branch is unfinished. Doing + // so would mean the add_leaf/add_hidden invocations do not correspond to a DFS traversal of a + // binary tree. + if (depth as usize + 1) < self.branch.len() { + return Err(TaprootBuilderError::NodeNotInDfsOrder); + } + + while self.branch.len() == depth as usize + 1 { + let child = match self.branch.pop() { + None => unreachable!("length of branch checked to be >= 1"), + Some(Some(child)) => child, + // Needs an explicit push to add the None that we just popped. + // Cannot use .last() because of borrow checker issues. + Some(None) => { + self.branch.push(None); + break; + } // Cannot combine further + }; + if depth == 0 { + // We are trying to combine two nodes at root level. + // Can't propagate further up than the root + return Err(TaprootBuilderError::OverCompleteTree); + } + node = NodeInfo::combine(node, child)?; + // Propagate to combine nodes at a lower depth + depth -= 1; + } + + if self.branch.len() < depth as usize + 1 { + // add enough nodes so that we can insert node at depth `depth` + let num_extra_nodes = depth as usize + 1 - self.branch.len(); + self.branch.extend((0..num_extra_nodes).map(|_| None)); + } + // Push the last node to the branch + self.branch[depth as usize] = Some(node); + Ok(self) + } +} + +impl Default for TaprootBuilder { + fn default() -> Self { Self::new() } +} + +/// Error happening when [`TapTree`] is constructed from a [`TaprootBuilder`] +/// having hidden branches or not being finalized. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum IncompleteBuilderError { + /// Indicates an attempt to construct a Taproot tree from a builder containing incomplete branches. + NotFinalized(TaprootBuilder), + /// Indicates an attempt to construct a Taproot tree from a builder containing hidden parts. + HiddenParts(TaprootBuilder), +} + +impl From for IncompleteBuilderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl IncompleteBuilderError { + /// Converts error into the original incomplete [`TaprootBuilder`] instance. + pub fn into_builder(self) -> TaprootBuilder { + match self { + Self::NotFinalized(builder) | Self::HiddenParts(builder) => builder, + } + } +} + +impl core::fmt::Display for IncompleteBuilderError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str(match self { + Self::NotFinalized(_) => + "an attempt to construct a Taproot tree from a builder containing incomplete branches", + Self::HiddenParts(_) => + "an attempt to construct a Taproot tree from a builder containing hidden parts", + }) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for IncompleteBuilderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::NotFinalized(_) | Self::HiddenParts(_) => None, + } + } +} + +/// Error happening when [`TapTree`] is constructed from a [`NodeInfo`] +/// having hidden branches. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum HiddenNodesError { + /// Indicates an attempt to construct a Taproot tree from a builder containing hidden parts. + HiddenParts(NodeInfo), +} + +impl From for HiddenNodesError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl HiddenNodesError { + /// Converts error into the original incomplete [`NodeInfo`] instance. + pub fn into_node_info(self) -> NodeInfo { + match self { + Self::HiddenParts(node_info) => node_info, + } + } +} + +impl core::fmt::Display for HiddenNodesError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str(match self { + Self::HiddenParts(_) => + "an attempt to construct a Taproot tree from a node_info containing hidden parts", + }) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for HiddenNodesError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::HiddenParts(_) => None, + } + } +} + +/// Taproot tree representing a complete binary tree without any hidden nodes. +/// +/// This is in contrast to [`NodeInfo`], which allows hidden nodes. +/// The implementations for Eq, PartialEq and Hash compare the Merkle root of the tree +// +// This is a bug in BIP-0370 that does not specify how to share trees with hidden nodes, +// for which we need a separate type. +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(into = "NodeInfo"))] +#[cfg_attr(feature = "serde", serde(try_from = "NodeInfo"))] +pub struct TapTree(NodeInfo); + +impl From for NodeInfo { + #[inline] + fn from(tree: TapTree) -> Self { tree.into_node_info() } +} + +impl TapTree { + /// Gets the reference to inner [`NodeInfo`] of this tree root. + pub fn node_info(&self) -> &NodeInfo { &self.0 } + + /// Gets the inner [`NodeInfo`] of this tree root. + pub fn into_node_info(self) -> NodeInfo { self.0 } + + /// Returns [`ScriptLeaves<'_>`] iterator for a Taproot script tree, operating in DFS order over + /// tree [`ScriptLeaf`]s. + pub fn script_leaves(&self) -> ScriptLeaves<'_> { + ScriptLeaves { leaf_iter: self.0.leaf_nodes() } + } + + /// Returns the root [`TapNodeHash`] of this tree. + pub fn root_hash(&self) -> TapNodeHash { self.0.hash } +} + +impl TryFrom for TapTree { + type Error = IncompleteBuilderError; + + /// Constructs a new [`TapTree`] from a [`TaprootBuilder`] if it is complete binary tree. + /// + /// # Returns + /// + /// A [`TapTree`] if and only if the `builder` is complete, otherwise return [`IncompleteBuilderError`] + /// error with the content of incomplete `builder` instance. + fn try_from(builder: TaprootBuilder) -> Result { + builder.try_into_tap_tree() + } +} + +impl TryFrom for TapTree { + type Error = HiddenNodesError; + + /// Constructs a new [`TapTree`] from a [`NodeInfo`] if it is complete binary tree. + /// + /// # Returns + /// + /// A [`TapTree`] if and only if the [`NodeInfo`] has no hidden nodes, otherwise return + /// [`HiddenNodesError`] error with the content of incomplete [`NodeInfo`] instance. + fn try_from(node_info: NodeInfo) -> Result { + if node_info.has_hidden_nodes { + Err(HiddenNodesError::HiddenParts(node_info)) + } else { + Ok(Self(node_info)) + } + } +} + +/// Iterator for a Taproot script tree, operating in DFS order yielding [`ScriptLeaf`]. +/// +/// Returned by [`TapTree::script_leaves`]. [`TapTree`] does not allow hidden nodes, +/// so this iterator is guaranteed to yield all known leaves. +pub struct ScriptLeaves<'tree> { + leaf_iter: LeafNodes<'tree>, +} + +impl<'tree> Iterator for ScriptLeaves<'tree> { + type Item = ScriptLeaf<'tree>; + + #[inline] + fn next(&mut self) -> Option { ScriptLeaf::from_leaf_node(self.leaf_iter.next()?) } + + fn size_hint(&self) -> (usize, Option) { self.leaf_iter.size_hint() } +} + +impl ExactSizeIterator for ScriptLeaves<'_> {} + +impl FusedIterator for ScriptLeaves<'_> {} + +impl DoubleEndedIterator for ScriptLeaves<'_> { + #[inline] + fn next_back(&mut self) -> Option { + ScriptLeaf::from_leaf_node(self.leaf_iter.next_back()?) + } +} +/// Iterator for a Taproot script tree, operating in DFS order yielding [`LeafNode`]. +/// +/// Returned by [`NodeInfo::leaf_nodes`]. This can potentially yield hidden nodes. +pub struct LeafNodes<'a> { + leaf_iter: core::slice::Iter<'a, LeafNode>, +} + +impl<'a> Iterator for LeafNodes<'a> { + type Item = &'a LeafNode; + + #[inline] + fn next(&mut self) -> Option { self.leaf_iter.next() } + + fn size_hint(&self) -> (usize, Option) { self.leaf_iter.size_hint() } +} + +impl ExactSizeIterator for LeafNodes<'_> {} + +impl FusedIterator for LeafNodes<'_> {} + +impl DoubleEndedIterator for LeafNodes<'_> { + #[inline] + fn next_back(&mut self) -> Option { self.leaf_iter.next_back() } +} +/// Represents the node information in Taproot tree. In contrast to [`TapTree`], this +/// is allowed to have hidden leaves as children. +/// +/// Helper type used in Merkle tree construction allowing one to build sparse Merkle trees. The node +/// represents part of the tree that has information about all of its descendants. +/// See how [`TaprootBuilder`] works for more details. +/// +/// You can use [`TaprootSpendInfo::from_node_info`] to a get a [`TaprootSpendInfo`] from the Merkle +/// root [`NodeInfo`]. +#[derive(Debug, Clone)] +pub struct NodeInfo { + /// Merkle hash for this node. + pub(crate) hash: TapNodeHash, + /// Information about leaves inside this node. + pub(crate) leaves: Vec, + /// Tracks information on hidden nodes below this node. + pub(crate) has_hidden_nodes: bool, +} + +/// Explicitly implement Ord so future changes to NodeInfo (e.g. adding a new field) won't result in +/// potentially changing addresses out from under users +impl Ord for NodeInfo { + fn cmp(&self, other: &Self) -> Ordering { + match self.hash.cmp(&other.hash) { + Ordering::Equal => match self.leaves.cmp(&other.leaves) { + Ordering::Equal => self.has_hidden_nodes.cmp(&other.has_hidden_nodes), + other => other, + }, + other => other, + } + } +} + +impl PartialOrd for NodeInfo { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} + +impl PartialEq for NodeInfo { + fn eq(&self, other: &Self) -> bool { self.hash.eq(&other.hash) } +} + +impl core::hash::Hash for NodeInfo { + fn hash(&self, state: &mut H) { self.hash.hash(state) } +} + +impl Eq for NodeInfo {} + +impl NodeInfo { + /// Constructs a new [`NodeInfo`] with omitted/hidden info. + pub fn new_hidden_node(hash: TapNodeHash) -> Self { + Self { hash, leaves: vec![], has_hidden_nodes: true } + } + + /// Constructs a new leaf [`NodeInfo`] with given [`TapScriptBuf`] and [`LeafVersion`]. + pub fn new_leaf_with_ver(script: TapScriptBuf, ver: LeafVersion) -> Self { + Self { + hash: TapNodeHash::from_script(&script, ver), + leaves: vec![LeafNode::new_script(script, ver)], + has_hidden_nodes: false, + } + } + + /// Combines two [`NodeInfo`] to create a new parent. + pub fn combine(a: Self, b: Self) -> Result { + let mut all_leaves = Vec::with_capacity(a.leaves.len() + b.leaves.len()); + let (hash, left_first) = combine_node_hashes(a.hash, b.hash); + let (a, b) = if left_first { (a, b) } else { (b, a) }; + for mut a_leaf in a.leaves { + a_leaf.merkle_branch.push(b.hash)?; // add hashing partner + all_leaves.push(a_leaf); + } + for mut b_leaf in b.leaves { + b_leaf.merkle_branch.push(a.hash)?; // add hashing partner + all_leaves.push(b_leaf); + } + Ok(Self { + hash, + leaves: all_leaves, + has_hidden_nodes: a.has_hidden_nodes || b.has_hidden_nodes, + }) + } + + /// Constructs an iterator over all leaves (including hidden leaves) in the tree. + pub fn leaf_nodes(&self) -> LeafNodes<'_> { LeafNodes { leaf_iter: self.leaves.iter() } } + + /// Returns the root [`TapNodeHash`] of this node info. + pub fn node_hash(&self) -> TapNodeHash { self.hash } +} + +impl TryFrom for NodeInfo { + type Error = IncompleteBuilderError; + + fn try_from(builder: TaprootBuilder) -> Result { + builder.try_into_node_info() + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for NodeInfo { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeSeq; + let mut seq = serializer.serialize_seq(Some(self.leaves.len() * 2))?; + for tap_leaf in self.leaves.iter() { + seq.serialize_element(&tap_leaf.merkle_branch().len())?; + seq.serialize_element(&tap_leaf.leaf)?; + } + seq.end() + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for NodeInfo { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct SeqVisitor; + impl<'de> serde::de::Visitor<'de> for SeqVisitor { + type Value = NodeInfo; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Taproot tree in DFS walk order") + } + + fn visit_seq
(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let size = seq + .size_hint() + .map(|x| core::mem::size_of::() * 8 - x.leading_zeros() as usize) + .map(|x| x / 2) // Each leaf is serialized as two elements. + .unwrap_or(0) + .min(TAPROOT_CONTROL_MAX_NODE_COUNT); // no more than 128 nodes + let mut builder = TaprootBuilder::with_capacity(size); + while let Some(depth) = seq.next_element()? { + let tap_leaf: TapLeaf = seq + .next_element()? + .ok_or_else(|| serde::de::Error::custom("missing tap_leaf"))?; + match tap_leaf { + TapLeaf::Script(script, ver) => { + builder = + builder.add_leaf_with_ver(depth, script, ver).map_err(|e| { + serde::de::Error::custom(format!("leaf insertion error: {}", e)) + })?; + } + TapLeaf::Hidden(h) => { + builder = builder.add_hidden_node(depth, h).map_err(|e| { + serde::de::Error::custom(format!( + "hidden node insertion error: {}", + e + )) + })?; + } + } + } + NodeInfo::try_from(builder).map_err(|e| { + serde::de::Error::custom(format!("incomplete Taproot tree: {}", e)) + }) + } + } + + deserializer.deserialize_seq(SeqVisitor) + } +} + +/// Leaf node in a Taproot tree. Can be either hidden or known. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum TapLeaf { + /// A known script + Script(TapScriptBuf, LeafVersion), + /// Hidden Node with the given leaf hash + Hidden(TapNodeHash), +} + +impl TapLeaf { + /// Obtains the hidden leaf hash if the leaf is hidden. + pub fn as_hidden(&self) -> Option<&TapNodeHash> { + if let Self::Hidden(v) = self { + Some(v) + } else { + None + } + } + + /// Obtains a reference to script and version if the leaf is known. + pub fn as_script(&self) -> Option<(&TapScript, LeafVersion)> { + if let Self::Script(script, ver) = self { + Some((script, *ver)) + } else { + None + } + } +} + +/// Store information about Taproot leaf node. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct LeafNode { + /// The [`TapLeaf`] + leaf: TapLeaf, + /// The Merkle proof (hashing partners) to get this node. + merkle_branch: TaprootMerkleBranchBuf, +} + +impl LeafNode { + /// Constructs a new [`ScriptLeaf`] from `script` and `ver` and no Merkle branch. + pub fn new_script(script: TapScriptBuf, ver: LeafVersion) -> Self { + Self { leaf: TapLeaf::Script(script, ver), merkle_branch: Default::default() } + } + + /// Constructs a new [`ScriptLeaf`] from `hash` and no Merkle branch. + pub fn new_hidden(hash: TapNodeHash) -> Self { + Self { leaf: TapLeaf::Hidden(hash), merkle_branch: Default::default() } + } + + /// Returns the depth of this script leaf in the Taproot tree. + #[inline] + pub fn depth(&self) -> u8 { + // Depth is guarded by TAPROOT_CONTROL_MAX_NODE_COUNT. + u8::try_from(self.merkle_branch().len()).expect("depth is guaranteed to fit in a u8") + } + + /// Computes a leaf hash for this [`ScriptLeaf`] if the leaf is known. + /// + /// This [`TapLeafHash`] is useful while signing Taproot script spends. + /// + /// See [`LeafNode::node_hash`] for computing the [`TapNodeHash`] which returns the hidden node + /// hash if the node is hidden. + #[inline] + pub fn leaf_hash(&self) -> Option { + let (script, ver) = self.leaf.as_script()?; + Some(TapLeafHash::from_script(script, ver)) + } + + /// Computes the [`TapNodeHash`] for this [`ScriptLeaf`]. This returns the + /// leaf hash if the leaf is known and the hidden node hash if the leaf is + /// hidden. + /// See also, [`LeafNode::leaf_hash`]. + #[inline] + pub fn node_hash(&self) -> TapNodeHash { + match self.leaf { + TapLeaf::Script(ref script, ver) => TapLeafHash::from_script(script, ver).into(), + TapLeaf::Hidden(ref hash) => *hash, + } + } + + /// Returns reference to the leaf script if the leaf is known. + #[inline] + pub fn script(&self) -> Option<&TapScript> { self.leaf.as_script().map(|x| x.0) } + + /// Returns leaf version of the script if the leaf is known. + #[inline] + pub fn leaf_version(&self) -> Option { self.leaf.as_script().map(|x| x.1) } + + /// Returns reference to the Merkle proof (hashing partners) to get this + /// node in form of [`TaprootMerkleBranch`]. + #[inline] + pub fn merkle_branch(&self) -> &TaprootMerkleBranch { &self.merkle_branch } + + /// Returns a reference to the leaf of this [`ScriptLeaf`]. + #[inline] + pub fn leaf(&self) -> &TapLeaf { &self.leaf } +} + +/// Script leaf node in a Taproot tree along with the Merkle proof to get this node. +/// Returned by [`TapTree::script_leaves`] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ScriptLeaf<'leaf> { + /// The version of the script leaf. + version: LeafVersion, + /// The script. + script: &'leaf TapScript, + /// The Merkle proof (hashing partners) to get this node. + merkle_branch: &'leaf TaprootMerkleBranch, +} + +impl<'leaf> ScriptLeaf<'leaf> { + /// Obtains the version of the script leaf. + pub fn version(&self) -> LeafVersion { self.version } + + /// Obtains a reference to the script inside the leaf. + pub fn script(&self) -> &TapScript { self.script } + + /// Obtains a reference to the Merkle proof of the leaf. + pub fn merkle_branch(&self) -> &TaprootMerkleBranch { self.merkle_branch } + + /// Obtains a script leaf from the leaf node if the leaf is not hidden. + pub fn from_leaf_node(leaf_node: &'leaf LeafNode) -> Option { + let (script, ver) = leaf_node.leaf.as_script()?; + Some(Self { version: ver, script, merkle_branch: &leaf_node.merkle_branch }) + } +} + +/// Control block data structure used in Tapscript satisfaction. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct ControlBlock +where + Branch: ?Sized, +{ + /// The tapleaf version. + pub leaf_version: LeafVersion, + /// The parity of the output key (NOT THE INTERNAL KEY WHICH IS ALWAYS XONLY). + pub output_key_parity: secp256k1::Parity, + /// The internal key. + pub internal_key: Key, + /// The Merkle proof of a script associated with this leaf. + pub merkle_branch: Branch, +} + +impl ControlBlock { + /// Decodes bytes representing a `ControlBlock`. + /// + /// This is an extra witness element that provides the proof that Taproot script pubkey is + /// correctly computed with some specified leaf hash. This is the last element in Taproot + /// witness when spending a output via script path. + /// + /// # Errors + /// + /// - [`TaprootError::InvalidControlBlockSize`] if `sl` is not of size 1 + 32 + 32N for any N >= 0. + /// - [`TaprootError::InvalidTaprootLeafVersion`] if first byte of `sl` is not a valid leaf version. + /// - [`TaprootError::InvalidInternalKey`] if internal key is invalid (first 32 bytes after the parity byte). + /// - [`TaprootError::InvalidMerkleTreeDepth`] if Merkle tree is too deep (more than 128 levels). + pub fn decode(sl: &[u8]) -> Result { + use alloc::borrow::ToOwned; + + let ControlBlock { leaf_version, output_key_parity, internal_key, merkle_branch } = + ControlBlock::<&TaprootMerkleBranch, &SerializedXOnlyPublicKey>::decode_borrowed(sl)?; + + let internal_key = internal_key.to_validated().map_err(TaprootError::InvalidInternalKey)?; + let merkle_branch = merkle_branch.to_owned(); + + Ok(Self { leaf_version, output_key_parity, internal_key, merkle_branch }) + } + + /// Constructs a new [`ControlBlock`] from a hex string. + pub fn from_hex(hex: &str) -> Result { + let vec = Vec::from_hex(hex).map_err(TaprootError::InvalidControlBlockHex)?; + Self::decode(vec.as_slice()) + } +} + +impl ControlBlock { + pub(crate) fn decode_borrowed<'a>(sl: &'a [u8]) -> Result + where + B: From<&'a TaprootMerkleBranch>, + K: From<&'a SerializedXOnlyPublicKey>, + { + let (base, merkle_branch) = sl + .split_first_chunk::() + .ok_or(InvalidControlBlockSizeError(sl.len()))?; + + let (&first, internal_key) = base.split_first(); + + let output_key_parity = match first & 1 { + 0 => secp256k1::Parity::Even, + _ => secp256k1::Parity::Odd, + }; + + let leaf_version = LeafVersion::from_consensus(first & TAPROOT_LEAF_MASK)?; + let internal_key = SerializedXOnlyPublicKey::from_bytes_ref(internal_key).into(); + let merkle_branch = TaprootMerkleBranch::decode(merkle_branch)?.into(); + Ok(Self { leaf_version, output_key_parity, internal_key, merkle_branch }) + } +} + +impl + ?Sized> ControlBlock { + /// Returns the size of control block. Faster and more efficient than calling + /// `Self::serialize().len()`. Can be handy for fee estimation. + pub fn size(&self) -> usize { + TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * self.merkle_branch.as_ref().len() + } + + /// Serializes to a writer. + /// + /// # Returns + /// + /// The number of bytes written to the writer. + pub fn encode(&self, writer: &mut W) -> io::Result { + self.encode_inner(move |bytes| writer.write_all(bytes))?; + Ok(self.size()) + } + + pub(crate) fn encode_to_arrayvec(&self) -> ControlBlockArrayVec { + let mut result = ControlBlockArrayVec::new(); + self.encode_inner(|bytes| -> Result<(), core::convert::Infallible> { + result.extend_from_slice(bytes); + Ok(()) + }) + .unwrap_or_else(|never| match never {}); + result + } + + fn encode_inner(&self, mut write: impl FnMut(&[u8]) -> Result<(), E>) -> Result<(), E> { + let first_byte: u8 = + i32::from(self.output_key_parity) as u8 | self.leaf_version.to_consensus(); + write(&[first_byte])?; + write(&self.internal_key.serialize())?; + write(self.merkle_branch.as_ref().as_bytes())?; + Ok(()) + } + + /// Serializes the control block. + /// + /// This is required when using [`ControlBlock`] as a witness element while spending an output + /// via a script path. This serialization does not include the length prefix. When the + /// serialization returned by this function is later encoded as a witness element the length + /// prefix is added. + pub fn serialize(&self) -> Vec { + let mut buf = Vec::with_capacity(self.size()); + self.encode(&mut buf).expect("writers don't error"); + buf + } + + /// Verifies that a control block is correct proof for a given output key and script. + /// + /// Only checks that script is contained inside the [`TapTree`] described by output key. Full + /// verification must also execute the script with witness data. + pub fn verify_taproot_commitment( + &self, + output_key: XOnlyPublicKey, + script: &TapScript, + ) -> bool { + // compute the script hash + // Initially the curr_hash is the leaf hash + let mut curr_hash = TapNodeHash::from_script(script, self.leaf_version); + // Verify the proof + for elem in self.merkle_branch.as_ref() { + // Recalculate the curr hash as parent hash + curr_hash = TapNodeHash::from_node_hashes(curr_hash, *elem); + } + // compute the taptweak + let tweak = + TapTweakHash::from_key_and_merkle_root(self.internal_key, Some(curr_hash)).to_scalar(); + self.internal_key.tweak_add_check(&output_key, self.output_key_parity, tweak) + } +} + +/// Inner type representing future (non-tapscript) leaf versions. See [`LeafVersion::Future`]. +/// +/// NB: NO PUBLIC CONSTRUCTOR! +/// The only way to construct this is by converting `u8` to [`LeafVersion`] and then extracting it. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct FutureLeafVersion(u8); + +impl FutureLeafVersion { + pub(self) fn from_consensus( + version: u8, + ) -> Result { + match version { + TAPROOT_LEAF_TAPSCRIPT => unreachable!( + "FutureLeafVersion::from_consensus should never be called for 0xC0 value" + ), + TAPROOT_ANNEX_PREFIX => Err(InvalidTaprootLeafVersionError(TAPROOT_ANNEX_PREFIX)), + odd if odd & 0xFE != odd => Err(InvalidTaprootLeafVersionError(odd)), + even => Ok(Self(even)), + } + } + + /// Returns the consensus representation of this [`FutureLeafVersion`]. + #[inline] + pub fn to_consensus(self) -> u8 { self.0 } +} + +impl fmt::Display for FutureLeafVersion { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) } +} + +impl fmt::LowerHex for FutureLeafVersion { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } +} +impl_to_hex_from_lower_hex!(FutureLeafVersion, |_| 2); + +impl fmt::UpperHex for FutureLeafVersion { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } +} + +/// The leaf version for tapleafs. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum LeafVersion { + /// BIP-0342 tapscript. + TapScript, + + /// Future leaf version. + Future(FutureLeafVersion), +} + +impl LeafVersion { + /// Constructs a new [`LeafVersion`] from consensus byte representation. + /// + /// # Errors + /// + /// - If the last bit of the `version` is odd. + /// - If the `version` is 0x50 ([`TAPROOT_ANNEX_PREFIX`]). + pub fn from_consensus(version: u8) -> Result { + match version { + TAPROOT_LEAF_TAPSCRIPT => Ok(Self::TapScript), + TAPROOT_ANNEX_PREFIX => Err(InvalidTaprootLeafVersionError(TAPROOT_ANNEX_PREFIX)), + future => FutureLeafVersion::from_consensus(future).map(LeafVersion::Future), + } + } + + /// Returns the consensus representation of this [`LeafVersion`]. + pub fn to_consensus(self) -> u8 { + match self { + Self::TapScript => TAPROOT_LEAF_TAPSCRIPT, + Self::Future(version) => version.to_consensus(), + } + } +} + +impl fmt::Display for LeafVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match (self, f.alternate()) { + (Self::TapScript, true) => f.write_str("tapscript"), + (Self::TapScript, false) => fmt::Display::fmt(&TAPROOT_LEAF_TAPSCRIPT, f), + (Self::Future(version), true) => write!(f, "future_script_{:#02x}", version.0), + (Self::Future(version), false) => fmt::Display::fmt(version, f), + } + } +} + +impl fmt::LowerHex for LeafVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.to_consensus(), f) + } +} +impl_to_hex_from_lower_hex!(LeafVersion, |_| 2); + +impl fmt::UpperHex for LeafVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::UpperHex::fmt(&self.to_consensus(), f) + } +} + +/// Serializes [`LeafVersion`] as a `u8` using consensus encoding. +#[cfg(feature = "serde")] +impl serde::Serialize for LeafVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u8(self.to_consensus()) + } +} + +/// Deserializes [`LeafVersion`] as a `u8` using consensus encoding. +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for LeafVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct U8Visitor; + impl serde::de::Visitor<'_> for U8Visitor { + type Value = LeafVersion; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a valid consensus-encoded Taproot leaf version") + } + + fn visit_u64(self, value: u64) -> Result + where + E: serde::de::Error, + { + let value = u8::try_from(value).map_err(|_| { + E::invalid_value( + serde::de::Unexpected::Unsigned(value), + &"consensus-encoded leaf version as u8", + ) + })?; + LeafVersion::from_consensus(value).map_err(|_| { + E::invalid_value( + ::serde::de::Unexpected::Unsigned(value as u64), + &"consensus-encoded leaf version as u8", + ) + }) + } + } + + deserializer.deserialize_u8(U8Visitor) + } +} + +/// Detailed error type for Taproot builder. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum TaprootBuilderError { + /// Merkle tree depth must not be more than 128. + InvalidMerkleTreeDepth(InvalidMerkleTreeDepthError), + /// Nodes must be added specified in DFS walk order. + NodeNotInDfsOrder, + /// Two nodes at depth 0 are not allowed. + OverCompleteTree, + /// Called finalize on an empty tree. + EmptyTree, +} + +impl From for TaprootBuilderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for TaprootBuilderError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidMerkleTreeDepth(ref e) => write_err!(f, "invalid Merkle tree depth"; e), + Self::NodeNotInDfsOrder => { + write!(f, "add_leaf/add_hidden must be called in DFS walk order",) + } + Self::OverCompleteTree => write!( + f, + "attempted to create a tree with two nodes at depth 0. There must\ + only be exactly one node at depth 0", + ), + Self::EmptyTree => { + write!(f, "called finalize on an empty tree") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TaprootBuilderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidMerkleTreeDepth(ref e) => Some(e), + Self::NodeNotInDfsOrder | Self::OverCompleteTree | Self::EmptyTree => None, + } + } +} + +impl From for TaprootBuilderError { + fn from(e: InvalidMerkleTreeDepthError) -> Self { Self::InvalidMerkleTreeDepth(e) } +} + +/// Detailed error type for Taproot utilities. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +#[allow(clippy::enum_variant_names)] +pub enum TaprootError { + /// Proof size must be a multiple of 32. + InvalidMerkleBranchSize(InvalidMerkleBranchSizeError), + /// Merkle tree depth must not be more than 128. + InvalidMerkleTreeDepth(InvalidMerkleTreeDepthError), + /// The last bit of tapleaf version must be zero. + InvalidTaprootLeafVersion(InvalidTaprootLeafVersionError), + /// Invalid control block size. + InvalidControlBlockSize(InvalidControlBlockSizeError), + /// Invalid Taproot internal key. + InvalidInternalKey(ParseXOnlyPublicKeyError), + /// Invalid control block hex + InvalidControlBlockHex(HexToBytesError), +} + +impl From for TaprootError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for TaprootError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InvalidMerkleBranchSize(ref e) => write_err!(f, "invalid Merkle branch size"; e), + Self::InvalidMerkleTreeDepth(ref e) => write_err!(f, "invalid Merkle tree depth"; e), + Self::InvalidTaprootLeafVersion(ref e) => + write_err!(f, "invalid Taproot leaf version"; e), + Self::InvalidControlBlockSize(ref e) => write_err!(f, "invalid control block size"; e), + Self::InvalidControlBlockHex(ref e) => write_err!(f, "invalid control block hex"; e), + Self::InvalidInternalKey(ref e) => write_err!(f, "invalid internal x-only key"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TaprootError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::InvalidInternalKey(e) => Some(e), + Self::InvalidTaprootLeafVersion(ref e) => Some(e), + Self::InvalidMerkleTreeDepth(ref e) => Some(e), + Self::InvalidControlBlockHex(ref e) => Some(e), + Self::InvalidMerkleBranchSize(_) | Self::InvalidControlBlockSize(_) => None, + } + } +} + +impl From for TaprootError { + fn from(e: InvalidMerkleBranchSizeError) -> Self { Self::InvalidMerkleBranchSize(e) } +} + +impl From for TaprootError { + fn from(e: InvalidMerkleTreeDepthError) -> Self { Self::InvalidMerkleTreeDepth(e) } +} + +impl From for TaprootError { + fn from(e: InvalidTaprootLeafVersionError) -> Self { Self::InvalidTaprootLeafVersion(e) } +} + +impl From for TaprootError { + fn from(e: InvalidControlBlockSizeError) -> Self { Self::InvalidControlBlockSize(e) } +} + +/// Proof size must be a multiple of 32. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidMerkleBranchSizeError(usize); + +impl InvalidMerkleBranchSizeError { + /// Accessor for the invalid merkle branch size. + pub fn invalid_merkle_branch_size(&self) -> usize { self.0 } +} + +impl From for InvalidMerkleBranchSizeError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for InvalidMerkleBranchSizeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Merkle branch size({}) must be a multiple of {}", + self.0, TAPROOT_CONTROL_NODE_SIZE + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidMerkleBranchSizeError {} + +/// Merkle tree depth must not be more than 128. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidMerkleTreeDepthError(usize); + +impl InvalidMerkleTreeDepthError { + /// Accessor for the invalid merkle tree depth. + pub fn invalid_merkle_tree_depth(&self) -> usize { self.0 } +} + +impl From for InvalidMerkleTreeDepthError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for InvalidMerkleTreeDepthError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Merkle tree depth({}) must be less than {}", + self.0, TAPROOT_CONTROL_MAX_NODE_COUNT + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidMerkleTreeDepthError {} + +/// The last bit of tapleaf version must be zero. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidTaprootLeafVersionError(u8); + +impl InvalidTaprootLeafVersionError { + /// Accessor for the invalid leaf version. + pub fn invalid_leaf_version(&self) -> u8 { self.0 } +} + +impl From for InvalidTaprootLeafVersionError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for InvalidTaprootLeafVersionError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "leaf version({}) must have the least significant bit 0", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidTaprootLeafVersionError {} + +/// Invalid control block size. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct InvalidControlBlockSizeError(usize); + +impl InvalidControlBlockSizeError { + /// Accessor for the invalid control block size. + pub fn invalid_control_block_size(&self) -> usize { self.0 } +} + +impl From for InvalidControlBlockSizeError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for InvalidControlBlockSizeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "Control Block size({}) must be of the form 33 + 32*m where 0 <= m <= {} ", + self.0, TAPROOT_CONTROL_MAX_NODE_COUNT + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidControlBlockSizeError {} + +#[cfg(test)] +mod test { + use hashes::sha256; + use hex::DisplayHex; + + use super::*; + use crate::script::ScriptBufExt as _; + use crate::sighash::TapSighashTag; + use crate::{Address, KnownHrp, ScriptPubKeyBuf}; + extern crate serde_json; + + #[cfg(feature = "serde")] + use { + serde_test::Configure, + serde_test::{assert_tokens, Token}, + }; + + fn tag_engine(tag_name: &str) -> sha256::HashEngine { + let mut engine = sha256::Hash::engine(); + let tag_hash = sha256::Hash::hash(tag_name.as_bytes()); + engine.input(tag_hash.as_ref()); + engine.input(tag_hash.as_ref()); + engine + } + + #[test] + fn midstates() { + use sha256t::{Hash, Tag}; + // test that engine creation roundtrips + assert_eq!(tag_engine("TapLeaf").midstate().unwrap(), TapLeafTag::MIDSTATE); + assert_eq!(tag_engine("TapBranch").midstate().unwrap(), TapBranchTag::MIDSTATE); + assert_eq!(tag_engine("TapTweak").midstate().unwrap(), TapTweakTag::MIDSTATE); + assert_eq!(tag_engine("TapSighash").midstate().unwrap(), TapSighashTag::MIDSTATE); + + // check that hash creation is the same as building into the same engine + fn empty_hash(tag_name: &str) -> [u8; 32] { + let mut e = tag_engine(tag_name); + e.input(&[]); + sha256::Hash::from_engine(e).to_byte_array() + } + assert_eq!(empty_hash("TapLeaf"), Hash::::hash(&[]).to_byte_array()); + assert_eq!(empty_hash("TapBranch"), Hash::::hash(&[]).to_byte_array()); + assert_eq!(empty_hash("TapTweak"), Hash::::hash(&[]).to_byte_array()); + assert_eq!(empty_hash("TapSighash"), Hash::::hash(&[]).to_byte_array()); + } + + #[test] + fn vectors_core() { + //! Test vectors taken from Core + use sha256t::Hash; + + // uninitialized writers + // CHashWriter writer = HasherTapLeaf; + // writer.GetSHA256().GetHex() + assert_eq!( + Hash::::from_engine(Hash::::engine()).to_string(), + "5212c288a377d1f8164962a5a13429f9ba6a7b84e59776a52c6637df2106facb" + ); + assert_eq!( + Hash::::from_engine(Hash::::engine()).to_string(), + "53c373ec4d6f3c53c1f5fb2ff506dcefe1a0ed74874f93fa93c8214cbe9ffddf" + ); + assert_eq!( + Hash::::from_engine(Hash::::engine()).to_string(), + "8aa4229474ab0100b2d6f0687f031d1fc9d8eef92a042ad97d279bff456b15e4" + ); + assert_eq!( + Hash::::from_engine(Hash::::engine()).to_string(), + "dabc11914abcd8072900042a2681e52f8dba99ce82e224f97b5fdb7cd4b9c803" + ); + + // 0-byte + // CHashWriter writer = HasherTapLeaf; + // writer << std::vector{}; + // writer.GetSHA256().GetHex() + // Note that Core writes the 0 length prefix when an empty vector is written. + assert_eq!( + Hash::::hash(&[0]).to_string(), + "ed1382037800c9dd938dd8854f1a8863bcdeb6705069b4b56a66ec22519d5829" + ); + assert_eq!( + Hash::::hash(&[0]).to_string(), + "92534b1960c7e6245af7d5fda2588db04aa6d646abc2b588dab2b69e5645eb1d" + ); + assert_eq!( + Hash::::hash(&[0]).to_string(), + "cd8737b5e6047fc3f16f03e8b9959e3440e1bdf6dd02f7bb899c352ad490ea1e" + ); + assert_eq!( + Hash::::hash(&[0]).to_string(), + "c2fd0de003889a09c4afcf676656a0d8a1fb706313ff7d509afb00c323c010cd" + ); + } + + fn _verify_tap_commitments( + out_spk_hex: &str, + script_hex: &str, + control_block_hex: &str, + ) { + let out_pk = out_spk_hex[4..].parse::().unwrap(); + let out_pk = TweakedPublicKey::dangerous_assume_tweaked(out_pk); + let script = TapScriptBuf::from_hex_no_length_prefix(script_hex).unwrap(); + let control_block = ControlBlock::from_hex(control_block_hex).unwrap(); + assert_eq!(control_block_hex, control_block.serialize().to_lower_hex_string()); + assert!(control_block.verify_taproot_commitment( + out_pk.to_x_only_public_key(), + &script + )); + } + + #[test] + fn control_block_verify() { + // test vectors obtained from printing values in feature_taproot.py from Bitcoin Core + _verify_tap_commitments("51205dc8e62b15e0ebdf44751676be35ba32eed2e84608b290d4061bbff136cd7ba9", "6a", "c1a9d6f66cd4b25004f526bfa873e56942f98e8e492bd79ed6532b966104817c2bda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0641e660d1e5392fb79d64838c2b84faf04b7f5f283c9d8bf83e39e177b64372a0cd22eeab7e093873e851e247714eff762d8a30be699ba4456cfe6491b282e193a071350ae099005a5950d74f73ba13077a57bc478007fb0e4d1099ce9cf3d4"); + _verify_tap_commitments("5120e208c869c40d8827101c5ad3238018de0f3f5183d77a0c53d18ac28ddcbcd8ad", "f4", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f40090ab1f4890d51115998242ebce636efb9ede1b516d9eb8952dc1068e0335306199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4da14e029b1e154a85bfd9139e7aa2720b6070a4ceba8264ca61d5d3ac27aceb9ef4b54cd43c2d1fd5e11b5c2e93cf29b91ea3dc5b832201f02f7473a28c63246"); + _verify_tap_commitments( + "5120567666e7df90e0450bb608e17c01ed3fbcfa5355a5f8273e34e583bfaa70ce09", + "203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ac", + "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400", + ); + _verify_tap_commitments("5120580a19e47269414a55eb86d5d0c6c9b371455d9fd2154412a57dec840df99fe1", "6a", "bca0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f40042ba1bd1c63c03ccff60d4c4d53a653f87909eb3358e7fa45c9d805231fb08c933e1f4e0f9d17f591df1419df7d5b7eb5f744f404c5ef9ecdb1b89b18cafa3a816d8b5dba3205f9a9c05f866d91f40d2793a7586d502cb42f46c7a11f66ad4aa"); + _verify_tap_commitments("5120228b94a4806254a38d6efa8a134c28ebc89546209559dfe40b2b0493bafacc5b", "6a50", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4009c9aed3dfd11ab0e78bf87ef3bf296269dc4b0f7712140386d6980992bab4b45"); + _verify_tap_commitments( + "5120567666e7df90e0450bb608e17c01ed3fbcfa5355a5f8273e34e583bfaa70ce09", + "203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ac", + "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400", + ); + _verify_tap_commitments( + "5120b0a79103c31fe51eea61d2873bad8a25a310da319d7e7a85f825fa7a00ea3f85", + "203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ad51", + "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400", + ); + _verify_tap_commitments("5120f2f62e854a0012aeba78cd4ba4a0832447a5262d4c6eb4f1c95c7914b536fc6c", "6a86", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4009ad3d30479f0689dbdf59a6b840d60ad485b2effbed1825a75ce19a44e460e09056f60ea686d79cfa4fb79f197b2e905ac857a983be4a5a41a4873e865aa950780c0237de279dc063e67deec46ef8e1bc351bf12c4d67a6d568001faf097e797e6ee620f53cfe0f8acaddf2063c39c3577853bb46d61ffcba5a024c3e1216837"); + _verify_tap_commitments("51202a4772070b49bae68b44315032cdbf9c40c7c2f896781b32b931b73dbfb26d7e", "6af8", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4006f183944a14618fc7fe9ceade0f58e43a19d3c3b179ea6c43c29616413b6971c99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4c3462adec78cd04f3cc156bdadec50def99feae0dc6a23664e8a2b0d42d6ca9eb968dfdf46c23af642b2688351904e0a0630e71ffac5bcaba33b9b2c8a7495ec"); + _verify_tap_commitments("5120a32b0b8cfafe0f0f8d5870030ba4d19a8725ad345cb3c8420f86ac4e0dff6207", "4c", "e8a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400615da7ac8d078e5fc7f4690fc2127ba40f0f97cc070ade5b3a7919783d91ef3f13734aab908ae998e57848a01268fe8217d70bc3ee8ea8ceae158ae964a4b5f3af20b50d7019bf47fde210eee5c52f1cfe71cfca78f2d3e7c1fd828c80351525"); + _verify_tap_commitments( + "5120b0a79103c31fe51eea61d2873bad8a25a310da319d7e7a85f825fa7a00ea3f85", + "203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ad51", + "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400", + ); + _verify_tap_commitments("51208678459f1fa0f80e9b89b8ffdcaf46a022bdf60aa45f1fed9a96145edf4ec400", "6a50", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4001eff29e1a89e650076b8d3c56302881d09c9df215774ed99993aaed14acd6615"); + _verify_tap_commitments("5120017316303aed02bcdec424c851c9eacbe192b013139bd9634c4e19b3475b06e1", "61", "02a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f40050462265ca552b23cbb4fe021b474313c8cb87d4a18b3f7bdbeb2b418279ba31fc6509d829cd42336f563363cb3538d78758e0876c71e13012eb2b656eb0edb051a2420a840d5c8c6c762abc7410af2c311f606b20ca2ace56a8139f84b1379a"); + _verify_tap_commitments("5120896d4d5d2236e86c6e9320e86d1a7822e652907cbd508360e8c71aefc127c77d", "61", "14a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4001ab0e9d9a4858a0e69605fe9c5a42d739fbe26fa79650e7074f462b02645f7ea1c91802b298cd91e6b5af57c6a013d93397cd2ecbd5569382cc27becf44ff4fff8960b20f846160c159c58350f6b6072cf1b3daa5185b7a42524fb72cbc252576ae46732b8e31ac24bfa7d72f4c3713e8696f99d8ac6c07e4c820a03f249f144"); + _verify_tap_commitments("512093c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51", "04ffffffff203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ba04feffffff87ab", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400c9a5cd1f6c8a81f5648e39f9810591df1c9a8f1fe97c92e03ecd7c0c016c951983e05473c6e8238cb4c780ea2ce62552b2a3eee068ceffc00517cd7b97e10dad"); + _verify_tap_commitments("5120b28d75a7179de6feb66b8bb0bfa2b2c739d1a41cf7366a1b393804a844db8a28", "61", "c4a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac47039d40fe34d04b4155df7f1be7f2a49253c7e87812ea9e569e683ac27459e652d6503aa32d64734d00adfee8798b2eed28858abf3bd038e8fa58eb7df4a2d9"); + _verify_tap_commitments("512043e4aa733fc6f43c78a31c2b3c192623acf5cc8c01199ebcc4de88067baca83e", "bd4c", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4003f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b8b41ebea96ffd937715d9faeaa6895e6ef3b22919c554b75df12b3371d328023e443d1df50634ecc1cd169803a1e546f0d44304d8fc5056c408e597fed469b8437d6660eaad3cf72e35ba6e5ff7ddd5e293c1e7e813c871df4f46508e9946ec"); + _verify_tap_commitments("5120ee9aecb28f5f35ce1f8b5ec80275ac0f81bca4a21b29b4632fb4bcbef8823e6a", "2021a5981b13be29c9d4ea179ea44a8b773ea8c02d68f6f6eefd98de20d4bd055fac", "c13359c284c196b6e80f0cf1d93b6a397cf7ee722f0427b705bd954b88ada8838bd2622fd0e104fc50aa763b43c6a792d7d117029983abd687223b4344a9402c618bba7f5fc3fa8a57491f6842acde88c1e675ca35caea3b1a69ee2c2d9b10f615"); + _verify_tap_commitments("5120885274df2252b44764dcef53c21f21154e8488b7e79fafbc96b9ebb22ad0200d", "6a50", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4000793597254158918e3369507f2d6fdbef17d18b1028bbb0719450ded0f42c58f"); + _verify_tap_commitments("512066f6f6f91d47674d198a28388e1eb05ec24e6ddbba10f16396b1a80c08675121", "6a50", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400fe92aff70a2e8e2a4f34a913b99612468a41e0f8ecaff9a729a173d11013c27e"); + _verify_tap_commitments("5120868ed9307bd4637491ff03e3aa2c216a08fe213cac8b6cedbb9ab31dbfa6512c", "61", "a2a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa759d4ef857ec8e0bb42d6d31609d3c7e77de3bfa28c38f93393a6ddbabe819ec560ed4f061fbe742a5fd2a648d5209469420434c8753da3fa7067cc2bb4c172a"); + _verify_tap_commitments("5120c1a00a9baa82888fd7d30291135a7eaa9e9966a5f16db2b10460572f8b108d8d", "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5ba0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4007960d7b37dd1361aee34510e77acb4d27ddca17648a17e28475032538c1eb500f5a747f2c0893f79fe153ae918ac3d696de9322aa679aae62051ff5ed83aa502b338bd907346abd4cd9cf06117cb35d55a5a8dd950843522f8de7b5c7fba1804c38b0778d3d76b383f6db6fdf9d6e770da8fffbfa5152c0b8b38129885bcdee6"); + _verify_tap_commitments("5120bb9abeff7286b76dfc61800c548fe2621ff47506e47201a85c543b4a9a96fead", "75203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf47342796ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4003eb5cdc419e0a6a800f34583ce750f387be34879c26f4230991bd61da743ad9d34d288e79397b709ac22ad8cc57645d593af3e15b97a876362117177ab2519c000000000000000000000000000000000000000000000000000000000000000007160c3a48c8b17bc3aeaf01db9e0a96ac47a5a9fa329e046856e7765e89c8a93ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff07feb9aa7cd72c78e66a85414cd19289f8b0ab1415013dc2a007666aa9248ec1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fccc8bea662a9442a94f7ba0643c1d7ee7cc689f3b3506b7c8c99fd3f3b3d7772972dcdf2550cf95b65098aea67f72fef10abdcf1cef9815af8f4c4644b060e0000000000000000000000000000000000000000000000000000000000000000"); + _verify_tap_commitments("5120afddc189ea51094b4cbf463806792e9c8b35dfdc5e01228c78376380d0046b00", "4d09024747703eb9f759ce5ecd839109fecc40974ab16f5173ea390daaa5a78f7abe898165c90990062af998c5dc7989818393158a2c62b7ece727e7f5400d2efd33db8732599f6d1dce6b5b68d2d47317f2de6c9df118f61227f98453225036618aaf058140f2415d134fa69ba041c724ad81387f8c568d12ddc49eb32a71532096181b3f85fd465b8e9a176bb19f45c070baad47a2cc4505414b88c31cb5b0a192b2d2d56c404a37070b04d42c875c4ac351224f5b254f9ad0b820f43cad292d6565f796bf083173e14723f1e543c85a61689ddd5cb6666b240c15c38ce3320bf0c3be9e0322e5ef72366c294d3a2d7e8b8e7db875e7ae814537554f10b91c72b8b413e026bd5d5e917de4b54fa8f43f38771a7f242aa32dcb7ca1b0588dbf54af7ab9455047fbb894cdfdd242166db784276430eb47d4df092a6b8cb160eb982fe7d14a44283bdb4a9861ca65c06fd8b2546cfbfe38bc77f527de1b9bfd2c95a3e283b7b1d1d2b2fa291256a90a7003aefcef47ceabf113865a494af43e96a38b0b00919855eb7722ea2363e0ddfc9c51c08631d01e2a2d56e786b4ff6f1e5d415facc9c2619c285d9ad43001878294157cb025f639fb954271fd1d6173f6bc16535672f6abdd72b0284b4ff3eaf5b7247719d7c39365622610efae6562bef6e08a0b370fba75bb04dbdb90a482d8417e057f8bd021ea6ac32d0d48b08be9f77833b11e5e739960c9837d7583", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400ff698adfda0327f188e2ee35f7aecc0f90c9138a350d450648d968c2b5dd7ef94ddd3ec418dc0d03ee4956feb708d838ed2b20e5a193465a6a1467fd3054e1ea141ea4c4c503a6271e19a090e2a69a24282e3be04c4f98720f7a0eb274d9693d13a8e3c139aa625fa2aefd09854570527f9ac545bda1b689719f5cb715612c07"); + _verify_tap_commitments("5120afddc189ea51094b4cbf463806792e9c8b35dfdc5e01228c78376380d0046b00", "83", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f4007388cda01113397d4cd00bcfbd08fd68c3cfe3a42cbfe3a7651c1d5e6dacf1ad99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4b59764bec92507e4a4c3f01a06f05980163ca10f1c549bfe01f85fa4f109a1295e607f5ed9f1008048474de336f11f67a1fbf2012f58944dede0ab19a3ca81f5"); + _verify_tap_commitments("512093c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51", "04ffffffff203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ba04feffffff87ab", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400c9a5cd1f6c8a81f5648e39f9810591df1c9a8f1fe97c92e03ecd7c0c016c951983e05473c6e8238cb4c780ea2ce62552b2a3eee068ceffc00517cd7b97e10dad"); + } + + #[test] + fn build_huffman_tree() { + let internal_key = "93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51" + .parse::() + .unwrap(); + + let script_weights = [ + (10, TapScriptBuf::from_hex_no_length_prefix("51").unwrap()), // semantics of script don't matter for this test + (20, TapScriptBuf::from_hex_no_length_prefix("52").unwrap()), + (20, TapScriptBuf::from_hex_no_length_prefix("53").unwrap()), + (30, TapScriptBuf::from_hex_no_length_prefix("54").unwrap()), + (19, TapScriptBuf::from_hex_no_length_prefix("55").unwrap()), + ]; + let tree_info = + TaprootSpendInfo::with_huffman_tree(internal_key, script_weights.clone()) + .unwrap(); + + /* The resulting tree should put the scripts into a tree similar + * to the following: + * + * 1 __/\__ + * / \ + * /\ / \ + * 2 54 52 53 /\ + * 3 55 51 + */ + + for (script, length) in [("51", 3), ("52", 2), ("53", 2), ("54", 2), ("55", 3)].iter() { + assert_eq!( + *length, + tree_info + .script_map + .get(&( + TapScriptBuf::from_hex_no_length_prefix(script).unwrap(), + LeafVersion::TapScript + )) + .expect("Present Key") + .iter() + .next() + .expect("Present Path") + .len() + ); + } + + // Obtain the output key + let output_key = tree_info.output_key(); + + // Try to create and verify a control block from each path + for (_weights, script) in script_weights { + let ver_script = (script, LeafVersion::TapScript); + let ctrl_block = tree_info.control_block(&ver_script).unwrap(); + assert!(ctrl_block.verify_taproot_commitment( + output_key.to_x_only_public_key(), + &ver_script.0 + )) + } + } + + #[test] + fn taptree_builder() { + let internal_key = "93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51" + .parse::() + .unwrap(); + + let builder = TaprootBuilder::new(); + // Create a tree as shown below + // For example, imagine this tree: + // A, B , C are at depth 2 and D,E are at 3 + // .... + // / \ + // /\ /\ + // / \ / \ + // A B C / \ + // D E + let a = TapScriptBuf::from_hex_no_length_prefix("51").unwrap(); + let b = TapScriptBuf::from_hex_no_length_prefix("52").unwrap(); + let c = TapScriptBuf::from_hex_no_length_prefix("53").unwrap(); + let d = TapScriptBuf::from_hex_no_length_prefix("54").unwrap(); + let e = TapScriptBuf::from_hex_no_length_prefix("55").unwrap(); + let builder = builder.add_leaf(2, a.clone()).unwrap(); + let builder = builder.add_leaf(2, b.clone()).unwrap(); + let builder = builder.add_leaf(2, c.clone()).unwrap(); + let builder = builder.add_leaf(3, d.clone()).unwrap(); + + // Trying to finalize an incomplete tree returns the Err(builder) + let builder = builder.finalize(internal_key).unwrap_err(); + let builder = builder.add_leaf(3, e.clone()).unwrap(); + + #[cfg(feature = "serde")] + { + let tree = TapTree::try_from(builder.clone()).unwrap(); + // test roundtrip serialization with serde_test + #[rustfmt::skip] + assert_tokens(&tree.readable(), &[ + Token::Seq { len: Some(10) }, + Token::U64(2), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("51"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(2), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("52"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(3), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("55"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(3), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("54"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(2), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("53"), Token::U8(192), Token::TupleVariantEnd, + Token::SeqEnd, + ],); + + let node_info = TapTree::try_from(builder.clone()).unwrap().into_node_info(); + // test roundtrip serialization with serde_test + #[rustfmt::skip] + assert_tokens(&node_info.readable(), &[ + Token::Seq { len: Some(10) }, + Token::U64(2), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("51"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(2), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("52"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(3), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("55"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(3), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("54"), Token::U8(192), Token::TupleVariantEnd, + Token::U64(2), Token::TupleVariant { name: "TapLeaf", variant: "Script", len: 2}, Token::Str("53"), Token::U8(192), Token::TupleVariantEnd, + Token::SeqEnd, + ],); + } + + let tree_info = builder.finalize(internal_key).unwrap(); + let output_key = tree_info.output_key(); + + for script in [a, b, c, d, e] { + let ver_script = (script, LeafVersion::TapScript); + let ctrl_block = tree_info.control_block(&ver_script).unwrap(); + assert!(ctrl_block.verify_taproot_commitment( + output_key.to_x_only_public_key(), + &ver_script.0 + )) + } + } + + #[test] + #[cfg(feature = "serde")] + fn leaf_version_serde() { + let leaf_version = LeafVersion::TapScript; + // use serde_test to test serialization and deserialization + assert_tokens(&leaf_version, &[Token::U8(192)]); + + let json = serde_json::to_string(&leaf_version).unwrap(); + let leaf_version2 = serde_json::from_str(&json).unwrap(); + assert_eq!(leaf_version, leaf_version2); + } + + #[test] + #[cfg(feature = "serde")] + fn merkle_branch_serde() { + let hash1 = TapNodeHash::from_byte_array( + "03ba2a4dcd914fed29a1c630c7e811271b081a0e2f2f52cf1c197583dfd46c1b" + .parse::>() + .unwrap() + .to_byte_array(), + ); + let hash2 = TapNodeHash::from_byte_array( + "8d79dedc2fa0b55167b5d28c61dbad9ce1191a433f3a1a6c8ee291631b2c94c9" + .parse::>() + .unwrap() + .to_byte_array(), + ); + let merkle_branch = TaprootMerkleBranchBuf::from([hash1, hash2]); + // use serde_test to test serialization and deserialization + serde_test::assert_tokens( + &merkle_branch.readable(), + &[ + Token::Seq { len: Some(2) }, + Token::Str("03ba2a4dcd914fed29a1c630c7e811271b081a0e2f2f52cf1c197583dfd46c1b"), + Token::Str("8d79dedc2fa0b55167b5d28c61dbad9ce1191a433f3a1a6c8ee291631b2c94c9"), + Token::SeqEnd, + ], + ); + } + + #[test] + fn bip_341_tests() { + fn process_script_trees( + v: &serde_json::Value, + mut builder: TaprootBuilder, + leaves: &mut Vec<(TapScriptBuf, LeafVersion)>, + depth: u8, + ) -> TaprootBuilder { + if v.is_null() { + // nothing to push + } else if v.is_array() { + for leaf in v.as_array().unwrap() { + builder = process_script_trees(leaf, builder, leaves, depth + 1); + } + } else { + let script = + TapScriptBuf::from_hex_no_length_prefix(v["script"].as_str().unwrap()).unwrap(); + let ver = + LeafVersion::from_consensus(v["leafVersion"].as_u64().unwrap() as u8).unwrap(); + leaves.push((script.clone(), ver)); + builder = builder.add_leaf_with_ver(depth, script, ver).unwrap(); + } + builder + } + + let data = bip_341_read_json(); + // Check the version of data + assert!(data["version"] == 1); + + for arr in data["scriptPubKey"].as_array().unwrap() { + let internal_key = + arr["given"]["internalPubkey"].as_str().unwrap().parse::().unwrap(); + // process the tree + let script_tree = &arr["given"]["scriptTree"]; + let mut merkle_root = None; + if script_tree.is_null() { + assert!(arr["intermediary"]["merkleRoot"].is_null()); + } else { + merkle_root = Some( + arr["intermediary"]["merkleRoot"] + .as_str() + .unwrap() + .parse::() + .unwrap(), + ); + let leaf_hashes = arr["intermediary"]["leafHashes"].as_array().unwrap(); + let ctrl_blks = arr["expected"]["scriptPathControlBlocks"].as_array().unwrap(); + let mut builder = TaprootBuilder::new(); + let mut leaves = vec![]; + builder = process_script_trees(script_tree, builder, &mut leaves, 0); + let spend_info = builder.finalize(internal_key).unwrap(); + for (i, script_ver) in leaves.iter().enumerate() { + let expected_leaf_hash = leaf_hashes[i].as_str().unwrap(); + let expected_ctrl_blk = + ControlBlock::from_hex(ctrl_blks[i].as_str().unwrap()).unwrap(); + + let leaf_hash = TapLeafHash::from_script(&script_ver.0, script_ver.1); + let ctrl_blk = spend_info.control_block(script_ver).unwrap(); + assert_eq!(leaf_hash.to_string(), expected_leaf_hash); + assert_eq!(ctrl_blk, expected_ctrl_blk); + } + } + let expected_output_key = arr["intermediary"]["tweakedPubkey"] + .as_str() + .unwrap() + .parse::() + .unwrap(); + let expected_tweak = + arr["intermediary"]["tweak"].as_str().unwrap().parse::().unwrap(); + let expected_spk = ScriptPubKeyBuf::from_hex_no_length_prefix( + arr["expected"]["scriptPubKey"].as_str().unwrap(), + ) + .unwrap(); + let expected_addr = arr["expected"]["bip350Address"] + .as_str() + .unwrap() + .parse::>() + .unwrap() + .assume_checked(); + + let tweak = TapTweakHash::from_key_and_merkle_root(internal_key, merkle_root); + let (output_key, _parity) = internal_key.tap_tweak(merkle_root); + let addr = Address::p2tr(internal_key, merkle_root, KnownHrp::Mainnet); + let spk = addr.script_pubkey(); + + assert_eq!(expected_output_key, output_key.to_x_only_public_key()); + assert_eq!(expected_tweak, tweak); + assert_eq!(expected_addr, addr); + assert_eq!(expected_spk, spk); + } + } + + fn bip_341_read_json() -> serde_json::Value { + let json_str = include_str!("../../tests/data/bip341_tests.json"); + serde_json::from_str(json_str).expect("JSON was not well-formatted") + } +} diff --git a/bitcoin/tests/bip_174.rs b/bitcoin/tests/bip_174.rs new file mode 100644 index 000000000..edcee7418 --- /dev/null +++ b/bitcoin/tests/bip_174.rs @@ -0,0 +1,467 @@ +//! Tests PSBT integration vectors from BIP 174 +//! defined at + +use std::collections::BTreeMap; + +use bitcoin::amount::{Amount, Denomination}; +use bitcoin::bip32::{Fingerprint, IntoDerivationPath, KeySource, Xpriv, Xpub}; +use bitcoin::consensus::encode::{deserialize, serialize_hex}; +use bitcoin::hex::FromHex; +use bitcoin::opcodes::all::OP_0; +use bitcoin::psbt::{Psbt, PsbtSighashType}; +use bitcoin::script::{PushBytes, ScriptBuf, ScriptBufExt as _}; +use bitcoin::{ + absolute, script, transaction, NetworkKind, OutPoint, PrivateKey, PublicKey, ScriptPubKeyBuf, + ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Witness, +}; + +#[track_caller] +fn hex_psbt(s: &str) -> Psbt { + let v: Vec = Vec::from_hex(s).expect("valid hex digits"); + Psbt::deserialize(&v).expect("valid magic and valid separators") +} + +#[track_caller] +fn hex_script(s: &str) -> ScriptBuf { + ScriptBuf::from_hex_no_length_prefix(s).expect("valid hex digits") +} + +#[test] +fn bip174_psbt_workflow() { + // + // Step 0: Create the extended private key from the test vector data. + // + + let ext_priv = build_extended_private_key(); + let ext_pub = Xpub::from_xpriv(&ext_priv); + let parent_fingerprint = ext_pub.fingerprint(); + + // + // Step 1: The creator. + // + + let tx = create_transaction(); + let psbt = create_psbt(tx); + + // + // Step 2: The first updater. + // + + let psbt = update_psbt(psbt, parent_fingerprint); + + // + // Step 3: The second updater. + // + + let psbt = update_psbt_with_sighash_all(psbt); + + // + // Step 4: The first signer. + // + + // Strings from BIP 174 test vector. + let test_vector = [ + ("cP53pDbR5WtAD8dYAW9hhTjuvvTVaEiQBdrz9XPrgLBeRFiyCbQr", "0h/0h/0h"), // from_priv, into_derivation_path? + ("cR6SXDoyfQrcp4piaiHE97Rsgta9mNhGTen9XeonVgwsh4iSgw6d", "0h/0h/2h"), + ]; + + // We pass the keys to the signer after doing verification to make explicit + // that signer is only using these two keys. + let keys = parse_and_verify_keys(&ext_priv, &test_vector); + let psbt_1 = signer_one_sign(psbt.clone(), keys); + + // + // Step 5: The second signer. + // + + // Strings from BIP 174 test vector. + let test_vector = [ + ("cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", "0h/0h/1h"), + ("cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE", "0h/0h/3h"), + ]; + + let keys = parse_and_verify_keys(&ext_priv, &test_vector); + let psbt_2 = signer_two_sign(psbt, keys); + + // + // Step 6: Combiner the two signed PSBTs. + // + + let combined = combine(psbt_1, psbt_2); + + // + // Step 7: Finalize the PSBT. + // + + let finalized = finalize(combined); + + // + // Step 8: Extract the transaction. + // + + let _tx = extract_transaction(finalized); + + // + // Step 9: Test lexicographical PSBT combiner. + // + // Combine would be done earlier, at Step 6, in typical workflow. + // We define it here to reflect the order of test vectors in BIP 174. + // + + combine_lexicographically(); +} + +/// Attempts to build an extended private key from seed and also directly from a string. +fn build_extended_private_key() -> Xpriv { + // Strings from BIP 174 test vector. + let extended_private_key = "tprv8ZgxMBicQKsPd9TeAdPADNnSyH9SSUUbTVeFszDE23Ki6TBB5nCefAdHkK8Fm3qMQR6sHwA56zqRmKmxnHk37JkiFzvncDqoKmPWubu7hDF"; + let seed = "cUkG8i1RFfWGWy5ziR11zJ5V4U4W3viSFCfyJmZnvQaUsd1xuF3T"; + + let xpriv = extended_private_key.parse::().unwrap(); + + let sk = PrivateKey::from_wif(seed).unwrap(); + let seeded = Xpriv::new_master(NetworkKind::Test, &sk.inner.to_secret_bytes()); + assert_eq!(xpriv, seeded); + + xpriv +} + +/// Creates the initial transaction, called by the PSBT Creator. +fn create_transaction() -> Transaction { + // Strings from BIP 174 test vector. + let output_0 = TvOutput { + amount: "1.49990000", + script_pubkey: "0014d85c2b71d0060b09c9886aeb815e50991dda124d", + }; + let output_1 = TvOutput { + amount: "1.00000000", + script_pubkey: "001400aea9a2e5f0f876a588df5546e8742d1d87008f", + }; + let input_0 = TvInput { + txid: "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858", + index: 0, + }; + let input_1 = TvInput { + txid: "1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83", + index: 1, + }; + struct TvOutput { + amount: &'static str, + script_pubkey: &'static str, + } + struct TvInput { + txid: &'static str, + index: u32, + } + + Transaction { + version: transaction::Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![ + TxIn { + previous_output: OutPoint { + txid: input_0.txid.parse().expect("failed to parse txid"), + vout: input_0.index, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::MAX, // Disable nSequence. + witness: Witness::default(), + }, + TxIn { + previous_output: OutPoint { + txid: input_1.txid.parse().expect("failed to parse txid"), + vout: input_1.index, + }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }, + ], + outputs: vec![ + TxOut { + amount: Amount::from_str_in(output_0.amount, Denomination::Bitcoin) + .expect("failed to parse amount"), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(output_0.script_pubkey) + .expect("failed to parse script"), + }, + TxOut { + amount: Amount::from_str_in(output_1.amount, Denomination::Bitcoin) + .expect("failed to parse amount"), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(output_1.script_pubkey) + .expect("failed to parse script"), + }, + ], + } +} + +/// Creates the initial PSBT, called by the Creator. Verifies against BIP 174 test vector. +#[track_caller] +fn create_psbt(tx: Transaction) -> Psbt { + // String from BIP 174 test vector. + let expected_psbt_hex = include_str!("data/create_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + let psbt = Psbt::from_unsigned_tx(tx).unwrap(); + + assert_eq!(psbt, expected_psbt); + psbt +} + +/// Updates `psbt` according to the BIP, returns the newly updated PSBT. Verifies against BIP 174 test vector. +#[track_caller] +fn update_psbt(mut psbt: Psbt, fingerprint: Fingerprint) -> Psbt { + // Strings from BIP 174 test vector. + let previous_tx_0 = include_str!("data/previous_tx_0_hex"); + let previous_tx_1 = include_str!("data/previous_tx_1_hex"); + + let redeem_script_0 = "5221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae"; + let redeem_script_1 = "00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903"; + let witness_script = "522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae"; + + // Public key and its derivation path (these are the child pubkeys for our `Xpriv`, + // can be verified by deriving the key using this derivation path). + let pk_path = [ + ("029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f", "0h/0h/0h"), + ("02dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7", "0h/0h/1h"), + ("03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc", "0h/0h/2h"), + ("023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73", "0h/0h/3h"), + ("03a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca58771", "0h/0h/4h"), + ("027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b50051096", "0h/0h/5h"), + ]; + + let expected_psbt_hex = include_str!("data/update_1_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + let mut input_0 = psbt.inputs[0].clone(); + + let v = Vec::from_hex(previous_tx_1).unwrap(); + let tx: Transaction = deserialize(&v).unwrap(); + input_0.non_witness_utxo = Some(tx); + input_0.redeem_script = Some(hex_script(redeem_script_0)); + input_0.bip32_derivation = bip32_derivation(fingerprint, &pk_path, vec![0, 1]); + + let mut input_1 = psbt.inputs[1].clone(); + + let v = Vec::from_hex(previous_tx_0).unwrap(); + let tx: Transaction = deserialize(&v).unwrap(); + input_1.witness_utxo = Some(tx.outputs[1].clone()); + + input_1.redeem_script = Some(hex_script(redeem_script_1)); + input_1.witness_script = Some(hex_script(witness_script)); + input_1.bip32_derivation = bip32_derivation(fingerprint, &pk_path, vec![2, 3]); + + psbt.inputs = vec![input_0, input_1]; + + let mut output_0 = psbt.outputs[0].clone(); + output_0.bip32_derivation = bip32_derivation(fingerprint, &pk_path, vec![4]); + + let mut output_1 = psbt.outputs[1].clone(); + output_1.bip32_derivation = bip32_derivation(fingerprint, &pk_path, vec![5]); + + psbt.outputs = vec![output_0, output_1]; + + assert_eq!(psbt, expected_psbt); + psbt +} + +/// `pk_path` holds tuples of `(public_key, derivation_path)`. `indices` is used to access the +/// `pk_path` vector. `fingerprint` is from the parent extended public key. +fn bip32_derivation( + fingerprint: Fingerprint, + pk_path: &[(&str, &str)], + indices: Vec, +) -> BTreeMap { + let mut tree = BTreeMap::new(); + for i in indices { + let pk = pk_path[i].0; + let path = pk_path[i].1; + + let pk = pk.parse::().unwrap(); + let path = path.into_derivation_path().unwrap(); + + tree.insert(pk.inner, (fingerprint, path)); + } + tree +} + +/// Does the second update according to the BIP, returns the newly updated PSBT. Verifies against BIP 174 test vector. +#[track_caller] +fn update_psbt_with_sighash_all(mut psbt: Psbt) -> Psbt { + let expected_psbt_hex = include_str!("data/update_2_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + let ty = "SIGHASH_ALL".parse::().unwrap(); + + let mut input_0 = psbt.inputs[0].clone(); + input_0.sighash_type = Some(ty); + let mut input_1 = psbt.inputs[1].clone(); + input_1.sighash_type = Some(ty); + + psbt.inputs = vec![input_0, input_1]; + + assert_eq!(psbt, expected_psbt); + psbt +} + +/// Verifies the keys in the test vector are valid for the extended private key and derivation path. +fn parse_and_verify_keys( + ext_priv: &Xpriv, + sk_path: &[(&str, &str)], +) -> BTreeMap { + let mut key_map = BTreeMap::new(); + for (secret_key, derivation_path) in sk_path.iter() { + let wif_priv = PrivateKey::from_wif(secret_key).expect("failed to parse key"); + + let path = + derivation_path.into_derivation_path().expect("failed to convert derivation path"); + let derived_priv = + ext_priv.derive_xpriv(&path).expect("derivation path too long").to_private_key(); + assert_eq!(wif_priv, derived_priv); + let derived_pub = derived_priv.public_key(); + key_map.insert(derived_pub, derived_priv); + } + key_map +} + +/// Does the first signing according to the BIP, returns the signed PSBT. Verifies against BIP 174 test vector. +#[track_caller] +fn signer_one_sign(psbt: Psbt, key_map: BTreeMap) -> Psbt { + let expected_psbt_hex = include_str!("data/sign_1_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + let psbt = sign(psbt, key_map); + + assert_eq!(psbt, expected_psbt); + psbt +} + +/// Does the second signing according to the BIP, returns the signed PSBT. Verifies against BIP 174 test vector. +#[track_caller] +fn signer_two_sign(psbt: Psbt, key_map: BTreeMap) -> Psbt { + let expected_psbt_hex = include_str!("data/sign_2_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + let psbt = sign(psbt, key_map); + + assert_eq!(psbt, expected_psbt); + psbt +} + +/// Does the combine according to the BIP, returns the combined PSBT. Verifies against BIP 174 test vector. +#[track_caller] +fn combine(mut this: Psbt, that: Psbt) -> Psbt { + let expected_psbt_hex = include_str!("data/combine_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + this.combine(that).expect("failed to combine PSBTs"); + + assert_eq!(this, expected_psbt); + this +} + +/// Does the finalize step according to the BIP, returns the combined PSBT. Verifies against BIP 174 +/// test vector. +#[track_caller] +fn finalize(psbt: Psbt) -> Psbt { + let expected_psbt_hex = include_str!("data/finalize_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + let psbt = finalize_psbt(psbt); + + assert_eq!(psbt, expected_psbt); + psbt +} + +/// Does the transaction extractor step according to the BIP, returns the combined PSBT. Verifies +/// against BIP 174 test vector. +fn extract_transaction(psbt: Psbt) -> Transaction { + let expected_tx_hex = include_str!("data/extract_tx_hex"); + + let tx = psbt.extract_tx_unchecked_fee_rate(); + + let got = serialize_hex(&tx); + assert_eq!(got, expected_tx_hex); + + tx +} + +/// Combines two PSBTs lexicographically according to the BIP. Verifies against BIP 174 test vector. +#[track_caller] +fn combine_lexicographically() { + let psbt_1_hex = include_str!("data/lex_psbt_1_hex"); + let psbt_2_hex = include_str!("data/lex_psbt_2_hex"); + + let expected_psbt_hex = include_str!("data/lex_combine_psbt_hex"); + let expected_psbt: Psbt = hex_psbt(expected_psbt_hex); + + let v = Vec::from_hex(psbt_1_hex).unwrap(); + let mut psbt_1 = Psbt::deserialize(&v).expect("failed to deserialize psbt 1"); + + let v = Vec::from_hex(psbt_2_hex).unwrap(); + let psbt_2 = Psbt::deserialize(&v).expect("failed to deserialize psbt 2"); + + psbt_1.combine(psbt_2).expect("failed to combine PSBTs"); + + assert_eq!(psbt_1, expected_psbt); +} + +/// Signs `psbt` with `keys` if required. +fn sign(mut psbt: Psbt, keys: BTreeMap) -> Psbt { + psbt.sign(&keys).unwrap(); + psbt +} + +/// Finalizes a PSBT accord to the Input Finalizer role described in BIP 174. +/// This is just a test. For a production-ready PSBT Finalizer, use [rust-miniscript](https://docs.rs/miniscript/latest/miniscript/psbt/trait.PsbtExt.html#tymethod.finalize) +fn finalize_psbt(mut psbt: Psbt) -> Psbt { + // Input 0: legacy UTXO + + let sigs: Vec<_> = psbt.inputs[0].partial_sigs.values().collect(); + let script_sig = script::Builder::new() + .push_opcode(OP_0) // OP_CHECKMULTISIG bug pops +1 value when evaluating so push OP_0. + .push_slice(sigs[0].serialize()) + .push_slice(sigs[1].serialize()) + .push_slice( + <&PushBytes>::try_from(psbt.inputs[0].redeem_script.as_ref().unwrap().as_bytes()) + .unwrap(), + ) + .into_script(); + + psbt.inputs[0].final_script_sig = Some(script_sig); + + psbt.inputs[0].partial_sigs = BTreeMap::new(); + psbt.inputs[0].sighash_type = None; + psbt.inputs[0].redeem_script = None; + psbt.inputs[0].bip32_derivation = BTreeMap::new(); + + // Input 1: SegWit UTXO + + let script_sig = script::Builder::new() + .push_slice( + <&PushBytes>::try_from(psbt.inputs[1].redeem_script.as_ref().unwrap().as_bytes()) + .unwrap(), + ) + .into_script(); + + psbt.inputs[1].final_script_sig = Some(script_sig); + + let script_witness = { + let sigs: Vec<_> = psbt.inputs[1].partial_sigs.values().collect(); + let mut script_witness = Witness::new(); + script_witness.push([]); // Push 0x00 to the stack. + script_witness.push(sigs[1].serialize()); + script_witness.push(sigs[0].serialize()); + script_witness.push(psbt.inputs[1].witness_script.clone().unwrap().as_bytes()); + + script_witness + }; + + psbt.inputs[1].final_script_witness = Some(script_witness); + + psbt.inputs[1].partial_sigs = BTreeMap::new(); + psbt.inputs[1].sighash_type = None; + psbt.inputs[1].redeem_script = None; + psbt.inputs[1].witness_script = None; + psbt.inputs[1].bip32_derivation = BTreeMap::new(); + + psbt +} diff --git a/bitcoin/tests/data/README.md b/bitcoin/tests/data/README.md new file mode 100644 index 000000000..0792fd149 --- /dev/null +++ b/bitcoin/tests/data/README.md @@ -0,0 +1,3 @@ +# Test vector data + +This file contains data (hex strings) taken from BIP test vectors. diff --git a/bitcoin/tests/data/bip341_tests.json b/bitcoin/tests/data/bip341_tests.json new file mode 100644 index 000000000..11261b00b --- /dev/null +++ b/bitcoin/tests/data/bip341_tests.json @@ -0,0 +1,452 @@ +{ + "version": 1, + "scriptPubKey": [ + { + "given": { + "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d", + "scriptTree": null + }, + "intermediary": { + "merkleRoot": null, + "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70", + "tweakedPubkey": "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343" + }, + "expected": { + "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343", + "bip350Address": "bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5" + } + }, + { + "given": { + "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "scriptTree": { + "id": 0, + "script": "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac", + "leafVersion": 192 + } + }, + "intermediary": { + "leafHashes": [ + "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21" + ], + "merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001", + "tweakedPubkey": "147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3" + }, + "expected": { + "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "bip350Address": "bc1pz37fc4cn9ah8anwm4xqqhvxygjf9rjf2resrw8h8w4tmvcs0863sa2e586", + "scriptPathControlBlocks": [ + "c1187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27" + ] + } + }, + { + "given": { + "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820", + "scriptTree": { + "id": 0, + "script": "20b617298552a72ade070667e86ca63b8f5789a9fe8731ef91202a91c9f3459007ac", + "leafVersion": 192 + } + }, + "intermediary": { + "leafHashes": [ + "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b" + ], + "merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b", + "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30", + "tweakedPubkey": "e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e" + }, + "expected": { + "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e", + "bip350Address": "bc1punvppl2stp38f7kwv2u2spltjuvuaayuqsthe34hd2dyy5w4g58qqfuag5", + "scriptPathControlBlocks": [ + "c093478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820" + ] + } + }, + { + "given": { + "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592", + "scriptTree": [ + { + "id": 0, + "script": "20387671353e273264c495656e27e39ba899ea8fee3bb69fb2a680e22093447d48ac", + "leafVersion": 192 + }, + { + "id": 1, + "script": "06424950333431", + "leafVersion": 250 + } + ] + }, + "intermediary": { + "leafHashes": [ + "8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7", + "f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a" + ], + "merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef", + "tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9", + "tweakedPubkey": "712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5" + }, + "expected": { + "scriptPubKey": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5", + "bip350Address": "bc1pwyjywgrd0ffr3tx8laflh6228dj98xkjj8rum0zfpd6h0e930h6saqxrrm", + "scriptPathControlBlocks": [ + "c0ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a", + "faee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf37865928ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7" + ] + } + }, + { + "given": { + "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8", + "scriptTree": [ + { + "id": 0, + "script": "2044b178d64c32c4a05cc4f4d1407268f764c940d20ce97abfd44db5c3592b72fdac", + "leafVersion": 192 + }, + { + "id": 1, + "script": "07546170726f6f74", + "leafVersion": 192 + } + ] + }, + "intermediary": { + "leafHashes": [ + "64512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89", + "2cb2b90daa543b544161530c925f285b06196940d6085ca9474d41dc3822c5cb" + ], + "merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc", + "tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e", + "tweakedPubkey": "77e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220" + }, + "expected": { + "scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220", + "bip350Address": "bc1pwl3s54fzmk0cjnpl3w9af39je7pv5ldg504x5guk2hpecpg2kgsqaqstjq", + "scriptPathControlBlocks": [ + "c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd82cb2b90daa543b544161530c925f285b06196940d6085ca9474d41dc3822c5cb", + "c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd864512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89" + ] + } + }, + { + "given": { + "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f", + "scriptTree": [ + { + "id": 0, + "script": "2072ea6adcf1d371dea8fba1035a09f3d24ed5a059799bae114084130ee5898e69ac", + "leafVersion": 192 + }, + [ + { + "id": 1, + "script": "202352d137f2f3ab38d1eaa976758873377fa5ebb817372c71e2c542313d4abda8ac", + "leafVersion": 192 + }, + { + "id": 2, + "script": "207337c0dd4253cb86f2c43a2351aadd82cccb12a172cd120452b9bb8324f2186aac", + "leafVersion": 192 + } + ] + ] + }, + "intermediary": { + "leafHashes": [ + "2645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817", + "ba982a91d4fc552163cb1c0da03676102d5b7a014304c01f0c77b2b8e888de1c", + "9e31407bffa15fefbf5090b149d53959ecdf3f62b1246780238c24501d5ceaf6" + ], + "merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2", + "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4", + "tweakedPubkey": "91b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605" + }, + "expected": { + "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605", + "bip350Address": "bc1pjxmy65eywgafs5tsunw95ruycpqcqnev6ynxp7jaasylcgtcxczs6n332e", + "scriptPathControlBlocks": [ + "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6fffe578e9ea769027e4f5a3de40732f75a88a6353a09d767ddeb66accef85e553", + "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f9e31407bffa15fefbf5090b149d53959ecdf3f62b1246780238c24501d5ceaf62645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817", + "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6fba982a91d4fc552163cb1c0da03676102d5b7a014304c01f0c77b2b8e888de1c2645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817" + ] + } + }, + { + "given": { + "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d", + "scriptTree": [ + { + "id": 0, + "script": "2071981521ad9fc9036687364118fb6ccd2035b96a423c59c5430e98310a11abe2ac", + "leafVersion": 192 + }, + [ + { + "id": 1, + "script": "20d5094d2dbe9b76e2c245a2b89b6006888952e2faa6a149ae318d69e520617748ac", + "leafVersion": 192 + }, + { + "id": 2, + "script": "20c440b462ad48c7a77f94cd4532d8f2119dcebbd7c9764557e62726419b08ad4cac", + "leafVersion": 192 + } + ] + ] + }, + "intermediary": { + "leafHashes": [ + "f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d", + "737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711", + "d7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7" + ], + "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def", + "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9", + "tweakedPubkey": "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831" + }, + "expected": { + "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831", + "bip350Address": "bc1pw5tf7sqp4f50zka7629jrr036znzew70zxyvvej3zrpf8jg8hqcssyuewe", + "scriptPathControlBlocks": [ + "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d3cd369a528b326bc9d2133cbd2ac21451acb31681a410434672c8e34fe757e91", + "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312dd7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d", + "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d" + ] + } + } + ], + "keyPathSpending": [ + { + "given": { + "rawUnsignedTx": "02000000097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a418420000000000fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0065cd1d", + "utxosSpent": [ + { + "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343", + "amountSats": 420000000 + }, + { + "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3", + "amountSats": 462000000 + }, + { + "scriptPubKey": "76a914751e76e8199196d454941c45d1b3a323f1433bd688ac", + "amountSats": 294000000 + }, + { + "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e", + "amountSats": 504000000 + }, + { + "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605", + "amountSats": 630000000 + }, + { + "scriptPubKey": "00147dd65592d0ab2fe0d0257d571abf032cd9db93dc", + "amountSats": 378000000 + }, + { + "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831", + "amountSats": 672000000 + }, + { + "scriptPubKey": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5", + "amountSats": 546000000 + }, + { + "scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220", + "amountSats": 588000000 + } + ] + }, + "intermediary": { + "hashAmounts": "58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde6", + "hashOutputs": "a2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc5", + "hashPrevouts": "e3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f", + "hashScriptPubkeys": "23ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e21", + "hashSequences": "18959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e" + }, + "inputSpending": [ + { + "given": { + "txinIndex": 0, + "internalPrivkey": "6b973d88838f27366ed61c9ad6367663045cb456e28335c109e30717ae0c6baa", + "merkleRoot": null, + "hashType": 3 + }, + "intermediary": { + "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d", + "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70", + "tweakedPrivkey": "2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9", + "sigMsg": "0003020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0000000000d0418f0e9a36245b9a50ec87f8bf5be5bcae434337b87139c3a5b1f56e33cba0", + "precomputedUsed": [ + "hashAmounts", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "2514a6272f85cfa0f45eb907fcb0d121b808ed37c6ea160a5a9046ed5526d555" + }, + "expected": { + "witness": [ + "ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c03" + ] + } + }, + { + "given": { + "txinIndex": 1, + "internalPrivkey": "1e4da49f6aaf4e5cd175fe08a32bb5cb4863d963921255f33d3bc31e1343907f", + "merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21", + "hashType": 131 + }, + "intermediary": { + "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27", + "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001", + "tweakedPrivkey": "ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080", + "sigMsg": "0083020000000065cd1d00d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd9900000000808f891b00000000225120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3ffffffffffcef8fb4ca7efc5433f591ecfc57391811ce1e186a3793024def5c884cba51d", + "precomputedUsed": [], + "sigHash": "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d" + }, + "expected": { + "witness": [ + "052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83" + ] + } + }, + { + "given": { + "txinIndex": 3, + "internalPrivkey": "d3c7af07da2d54f7a7735d3d0fc4f0a73164db638b2f2f7c43f711f6d4aa7e64", + "merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b", + "hashType": 1 + }, + "intermediary": { + "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820", + "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30", + "tweakedPrivkey": "97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d", + "sigMsg": "0001020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50003000000", + "precomputedUsed": [ + "hashAmounts", + "hashOutputs", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "bf013ea93474aa67815b1b6cc441d23b64fa310911d991e713cd34c7f5d46669" + }, + "expected": { + "witness": [ + "ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a01" + ] + } + }, + { + "given": { + "txinIndex": 4, + "internalPrivkey": "f36bb07a11e469ce941d16b63b11b9b9120a84d9d87cff2c84a8d4affb438f4e", + "merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2", + "hashType": 0 + }, + "intermediary": { + "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f", + "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4", + "tweakedPrivkey": "a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501", + "sigMsg": "0000020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50004000000", + "precomputedUsed": [ + "hashAmounts", + "hashOutputs", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "4f900a0bae3f1446fd48490c2958b5a023228f01661cda3496a11da502a7f7ef" + }, + "expected": { + "witness": [ + "b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f" + ] + } + }, + { + "given": { + "txinIndex": 6, + "internalPrivkey": "415cfe9c15d9cea27d8104d5517c06e9de48e2f986b695e4f5ffebf230e725d8", + "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def", + "hashType": 2 + }, + "intermediary": { + "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d", + "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9", + "tweakedPrivkey": "241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901", + "sigMsg": "0002020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0006000000", + "precomputedUsed": [ + "hashAmounts", + "hashPrevouts", + "hashScriptPubkeys", + "hashSequences" + ], + "sigHash": "15f25c298eb5cdc7eb1d638dd2d45c97c4c59dcaec6679cfc16ad84f30876b85" + }, + "expected": { + "witness": [ + "a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee002" + ] + } + }, + { + "given": { + "txinIndex": 7, + "internalPrivkey": "c7b0e81f0a9a0b0499e112279d718cca98e79a12e2f137c72ae5b213aad0d103", + "merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef", + "hashType": 130 + }, + "intermediary": { + "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592", + "tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9", + "tweakedPrivkey": "65b6000cd2bfa6b7cf736767a8955760e62b6649058cbc970b7c0871d786346b", + "sigMsg": "0082020000000065cd1d00e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf00000000804c8b2000000000225120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5ffffffff", + "precomputedUsed": [], + "sigHash": "cd292de50313804dabe4685e83f923d2969577191a3e1d2882220dca88cbeb10" + }, + "expected": { + "witness": [ + "ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c482" + ] + } + }, + { + "given": { + "txinIndex": 8, + "internalPrivkey": "77863416be0d0665e517e1c375fd6f75839544eca553675ef7fdf4949518ebaa", + "merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc", + "hashType": 129 + }, + "intermediary": { + "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8", + "tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e", + "tweakedPrivkey": "ec18ce6af99f43815db543f47b8af5ff5df3b2cb7315c955aa4a86e8143d2bf5", + "sigMsg": "0081020000000065cd1da2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc500a778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af101000000002b0c230000000022512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220ffffffff", + "precomputedUsed": [ + "hashOutputs" + ], + "sigHash": "cccb739eca6c13a8a89e6e5cd317ffe55669bbda23f2fd37b0f18755e008edd2" + }, + "expected": { + "witness": [ + "bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd981" + ] + } + } + ], + "auxiliary": { + "fullySignedTx": "020000000001097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a41842000000006b4830450221008f3b8f8f0537c420654d2283673a761b7ee2ea3c130753103e08ce79201cf32a022079e7ab904a1980ef1c5890b648c8783f4d10103dd62f740d13daa79e298d50c201210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0141ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c030141052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83000141ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a010140b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f0247304402202b795e4de72646d76eab3f0ab27dfa30b810e856ff3a46c9a702df53bb0d8cc302203ccc4d822edab5f35caddb10af1be93583526ccfbade4b4ead350781e2f8adcd012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f90141a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee0020141ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c4820141bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd9810065cd1d" + } + } + ] +} diff --git a/bitcoin/tests/data/block_13b8a.hex b/bitcoin/tests/data/block_13b8a.hex new file mode 100644 index 000000000..6e83915b0 --- /dev/null +++ b/bitcoin/tests/data/block_13b8a.hex @@ -0,0 +1 @@ +0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac00000000010000000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a493046022100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a914f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089cfcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc597fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f0688ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919fa832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd676f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001ec4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa8621865134a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f758e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d3101000000001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb14a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cfbb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd2000000008b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e55c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f014104979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a02af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fcaf1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7ea6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb580654d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e240014104976c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb6042034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000 \ No newline at end of file diff --git a/bitcoin/tests/data/blockfilters.json b/bitcoin/tests/data/blockfilters.json new file mode 100644 index 000000000..8945296a0 --- /dev/null +++ b/bitcoin/tests/data/blockfilters.json @@ -0,0 +1,13 @@ +[ +["Block Height,Block Hash,Block,[Prev Output Scripts for Block],Previous Basic Header,Basic Filter,Basic Header,Notes"], +[0,"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",[],"0000000000000000000000000000000000000000000000000000000000000000","019dfca8","21584579b7eb08997773e5aeff3a7f932700042d0ed2a6129012b7d7ae81b750","Genesis block"], +[2,"000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820","0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d235340101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0432e7494d010e062f503253482fffffffff0100f2052a010000002321038a7f6ef1c8ca0c588aa53fa860128077c9e6c11e6830f4d7ee4e763a56b7718fac00000000",[],"d7bdac13a59d745b1add0d2ce852f1a0442e8945fc1bf3848d3cbffd88c24fe1","0174a170","186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0",""], +[3,"000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10","0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b60101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0486e7494d0151062f503253482fffffffff0100f2052a01000000232103f6d9ff4c12959445ca5549c811683bf9c88e637b222dd2e0311154c4c85cf423ac00000000",[],"186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0","016cf7a0","8d63aadf5ab7257cb6d2316a57b16f517bff1c6388f124ec4c04af1212729d2a",""], +[15007,"0000000038c44c703bae0f98cdd6bf30922326340a5996cc692aaae8bacf47ad","0100000002394092aa378fe35d7e9ac79c869b975c4de4374cd75eb5484b0e1e00000000eb9b8670abd44ad6c55cee18e3020fb0c6519e7004b01a16e9164867531b67afc33bc94fffff001d123f10050101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e04c33bc94f0115062f503253482fffffffff0100f2052a01000000232103f268e9ae07e0f8cb2f6e901d87c510d650b97230c0365b021df8f467363cafb1ac00000000",[],"18b5c2b0146d2d09d24fb00ff5b52bd0742f36c9e65527abdb9de30c027a4748","013c3710","07384b01311867949e0c046607c66b7a766d338474bb67f66c8ae9dbd454b20e","Tx has non-standard OP_RETURN output followed by opcodes"], +[49291,"0000000018b07dca1b28b4b5a119f6d6e71698ce1ed96f143f54179ce177a19c","02000000abfaf47274223ca2fea22797e44498240e482cb4c2f2baea088962f800000000604b5b52c32305b15d7542071d8b04e750a547500005d4010727694b6e72a776e55d0d51ffff001d211806480201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0d038bc0000102062f503253482fffffffff01a078072a01000000232102971dd6034ed0cf52450b608d196c07d6345184fcb14deb277a6b82d526a6163dac0000000001000000081cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff000000009300493046022100866859c21f306538152e83f115bcfbf59ab4bb34887a88c03483a5dff9895f96022100a6dfd83caa609bf0516debc2bf65c3df91813a4842650a1858b3f61cfa8af249014730440220296d4b818bb037d0f83f9f7111665f49532dfdcbec1e6b784526e9ac4046eaa602204acf3a5cb2695e8404d80bf49ab04828bcbe6fc31d25a2844ced7a8d24afbdff01ffffffff1cefd96060ecb1c4fbe675ad8a4f8bdc61d634c52b3a1c4116dee23749fe80ff020000009400483045022100e87899175991aa008176cb553c6f2badbb5b741f328c9845fcab89f8b18cae2302200acce689896dc82933015e7230e5230d5cff8a1ffe82d334d60162ac2c5b0c9601493046022100994ad29d1e7b03e41731a4316e5f4992f0d9b6e2efc40a1ccd2c949b461175c502210099b69fdc2db00fbba214f16e286f6a49e2d8a0d5ffc6409d87796add475478d601ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272010000009500493046022100a27400ba52fd842ce07398a1de102f710a10c5599545e6c95798934352c2e4df022100f6383b0b14c9f64b6718139f55b6b9494374755b86bae7d63f5d3e583b57255a01493046022100fdf543292f34e1eeb1703b264965339ec4a450ec47585009c606b3edbc5b617b022100a5fbb1c8de8aaaa582988cdb23622838e38de90bebcaab3928d949aa502a65d401ffffffff1e4a6d2d280ea06680d6cf8788ac90344a9c67cca9b06005bbd6d3f6945c8272020000009400493046022100ac626ac3051f875145b4fe4cfe089ea895aac73f65ab837b1ac30f5d875874fa022100bc03e79fa4b7eb707fb735b95ff6613ca33adeaf3a0607cdcead4cfd3b51729801483045022100b720b04a5c5e2f61b7df0fcf334ab6fea167b7aaede5695d3f7c6973496adbf1022043328c4cc1cdc3e5db7bb895ccc37133e960b2fd3ece98350f774596badb387201ffffffff23a8733e349c97d6cd90f520fdd084ba15ce0a395aad03cd51370602bb9e5db3010000004a00483045022100e8556b72c5e9c0da7371913a45861a61c5df434dfd962de7b23848e1a28c86ca02205d41ceda00136267281be0974be132ac4cda1459fe2090ce455619d8b91045e901ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a6000000006a473044022040a1c631554b8b210fbdf2a73f191b2851afb51d5171fb53502a3a040a38d2c0022040d11cf6e7b41fe1b66c3d08f6ada1aee07a047cb77f242b8ecc63812c832c9a012102bcfad931b502761e452962a5976c79158a0f6d307ad31b739611dac6a297c256ffffffff6856d609b881e875a5ee141c235e2a82f6b039f2b9babe82333677a5570285a601000000930048304502205b109df098f7e932fbf71a45869c3f80323974a826ee2770789eae178a21bfc8022100c0e75615e53ee4b6e32b9bb5faa36ac539e9c05fa2ae6b6de5d09c08455c8b9601483045022009fb7d27375c47bea23b24818634df6a54ecf72d52e0c1268fb2a2c84f1885de022100e0ed4f15d62e7f537da0d0f1863498f9c7c0c0a4e00e4679588c8d1a9eb20bb801ffffffffa563c3722b7b39481836d5edfc1461f97335d5d1e9a23ade13680d0e2c1c371f030000006c493046022100ecc38ae2b1565643dc3c0dad5e961a5f0ea09cab28d024f92fa05c922924157e022100ebc166edf6fbe4004c72bfe8cf40130263f98ddff728c8e67b113dbd621906a601210211a4ed241174708c07206601b44a4c1c29e5ad8b1f731c50ca7e1d4b2a06dc1fffffffff02d0223a00000000001976a91445db0b779c0b9fa207f12a8218c94fc77aff504588ac80f0fa02000000000000000000",["5221033423007d8f263819a2e42becaaf5b06f34cb09919e06304349d950668209eaed21021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821021d69e2b68c3960903b702af7829fadcd80bd89b158150c85c4a75b2c8cb9c39452ae","522102a7ae1e0971fc1689bd66d2a7296da3a1662fd21a53c9e38979e0f090a375c12d21022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821022adb62335f41eb4e27056ac37d462cda5ad783fa8e0e526ed79c752475db285d52ae","512103b9d1d0e2b4355ec3cdef7c11a5c0beff9e8b8d8372ab4b4e0aaf30e80173001951ae","76a9149144761ebaccd5b4bbdc2a35453585b5637b2f8588ac","522103f1848b40621c5d48471d9784c8174ca060555891ace6d2b03c58eece946b1a9121020ee5d32b54d429c152fdc7b1db84f2074b0564d35400d89d11870f9273ec140c52ae","76a914f4fa1cc7de742d135ea82c17adf0bb9cf5f4fb8388ac"],"ed47705334f4643892ca46396eb3f4196a5e30880589e4009ef38eae895d4a13","0afbc2920af1b027f31f87b592276eb4c32094bb4d3697021b4c6380","b6d98692cec5145f67585f3434ec3c2b3030182e1cb3ec58b855c5c164dfaaa3","Tx pays to empty output script"], +[180480,"00000000fd3ceb2404ff07a785c7fdcc76619edc8ed61bd25134eaa22084366a","020000006058aa080a655aa991a444bd7d1f2defd9a3bbe68aabb69030cf3b4e00000000d2e826bfd7ef0beaa891a7eedbc92cd6a544a6cb61c7bdaa436762eb2123ef9790f5f552ffff001d0002c90f0501000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0300c102024608062f503253482fffffffff01c0c6072a01000000232102e769e60137a4df6b0df8ebd387cca44c4c57ae74cc0114a8e8317c8f3bfd85e9ac00000000010000000381a0802911a01ffb025c4dea0bc77963e8c1bb46313b71164c53f72f37fe5248010000000151ffffffffc904b267833d215e2128bd9575242232ac2bc311550c7fc1f0ef6f264b40d14c010000000151ffffffffdf0915666649dba81886519c531649b7b02180b4af67d6885e871299e9d5f775000000000151ffffffff0180817dcb00000000232103bb52138972c48a132fc1f637858c5189607dd0f7fe40c4f20f6ad65f2d389ba4ac0000000001000000018da38b434fba82d66052af74fc5e4e94301b114d9bc03f819dc876398404c8b4010000006c493046022100fe738b7580dc5fb5168e51fc61b5aed211125eb71068031009a22d9bbad752c5022100be5086baa384d40bcab0fa586e4f728397388d86e18b66cc417dc4f7fa4f9878012103f233299455134caa2687bdf15cb0becdfb03bd0ff2ff38e65ec6b7834295c34fffffffff022ebc1400000000001976a9147779b7fba1c1e06b717069b80ca170e8b04458a488ac9879c40f000000001976a9142a0307cd925dbb66b534c4db33003dd18c57015788ac0000000001000000026139a62e3422a602de36c873a225c1d3ca5aeee598539ceecb9f0dc8d1ad0f83010000006b483045022100ad9f32b4a0a2ddc19b5a74eba78123e57616f1b3cfd72ce68c03ea35a3dda1f002200dbd22aa6da17213df5e70dfc3b2611d40f70c98ed9626aa5e2cde9d97461f0a012103ddb295d2f1e8319187738fb4b230fdd9aa29d0e01647f69f6d770b9ab24eea90ffffffff983c82c87cf020040d671956525014d5c2b28c6d948c85e1a522362c0059eeae010000006b4830450221009ca544274c786d30a5d5d25e17759201ea16d3aedddf0b9e9721246f7ef6b32e02202cfa5564b6e87dfd9fd98957820e4d4e6238baeb0f65fe305d91506bb13f5f4f012103c99113deac0d5d044e3ac0346abc02501542af8c8d3759f1382c72ff84e704f7ffffffff02c0c62d00000000001976a914ae19d27efe12f5a886dc79af37ad6805db6f922d88ac70ce2000000000001976a9143b8d051d37a07ea1042067e93efe63dbf73920b988ac000000000100000002be566e8cd9933f0c75c4a82c027f7d0c544d5c101d0607ef6ae5d07b98e7f1dc000000006b483045022036a8cdfd5ea7ebc06c2bfb6e4f942bbf9a1caeded41680d11a3a9f5d8284abad022100cacb92a5be3f39e8bc14db1710910ef7b395fa1e18f45d41c28d914fcdde33be012102bf59abf110b5131fae0a3ce1ec379329b4c896a6ae5d443edb68529cc2bc7816ffffffff96cf67645b76ceb23fe922874847456a15feee1655082ff32d25a6bf2c0dfc90000000006a47304402203471ca2001784a5ac0abab583581f2613523da47ec5f53df833c117b5abd81500220618a2847723d57324f2984678db556dbca1a72230fc7e39df04c2239942ba942012102925c9794fd7bb9f8b29e207d5fc491b1150135a21f505041858889fa4edf436fffffffff026c840f00000000001976a914797fb8777d7991d8284d88bfd421ce520f0f843188ac00ca9a3b000000001976a9146d10f3f592699265d10b106eda37c3ce793f7a8588ac00000000",["","","","76a9142903b138c24be9e070b3e73ec495d77a204615e788ac","76a91433a1941fd9a37b9821d376f5a51bd4b52fa50e2888ac","76a914e4374e8155d0865742ca12b8d4d14d41b57d682f88ac","76a914001fa7459a6cfc64bdc178ba7e7a21603bb2568f88ac","76a914f6039952bc2b307aeec5371bfb96b66078ec17f688ac"],"d34ef98386f413769502808d4bac5f20f8dfd5bffc9eedafaa71de0eb1f01489","0db414c859a07e8205876354a210a75042d0463404913d61a8e068e58a3ae2aa080026","c582d51c0ca365e3fcf36c51cb646d7f83a67e867cb4743fd2128e3e022b700c","Tx spends from empty output script"], +[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000",["a914feb8a29635c56d9cd913122f90678756bf23887687","76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac"],"8f13b9a9c85611635b47906c3053ac53cfcec7211455d4cb0d63dc9acc13d472","09027acea61b6cc3fb33f5d52f7d088a6b2f75d234e89ca800","546c574a0472144bcaf9b6aeabf26372ad87c7af7d1ee0dbfae5e099abeae49c","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"], +[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000",[],"fe4d230dbb0f4fec9bed23a5283e08baf996e3f32b93f52c7de1f641ddfd04ad","010c0b40","0965a544743bbfa36f254446e75630c09404b3d164a261892372977538928ed5","Coinbase tx has unparseable output script"], +[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000",["002027a5000c7917f785d8fc6e5a55adfca8717ecb973ebb7743849ff956d896a7ed"],"31d66d516a9eda7de865df29f6ef6cb8e4bf9309e5dac899968a9a62a5df61e3","0385acb4f0fe889ef0","4e6d564c2a2452065c205dd7eb2791124e0c4e0dbb064c410c24968572589dec","Includes witness data"], +[1414221,"0000000000000027b2b3b3381f114f674f481544ff2be37ae3788d7e078383b1","000000204ea88307a7959d8207968f152bedca5a93aefab253f1fb2cfb032a400000000070cebb14ec6dbc27a9dfd066d9849a4d3bac5f674665f73a5fe1de01a022a0c851fda85bf05f4c19a779d1450102000000010000000000000000000000000000000000000000000000000000000000000000ffffffff18034d94154d696e6572476174653030310d000000f238f401ffffffff01c817a804000000000000000000",[],"5e5e12d90693c8e936f01847859404c67482439681928353ca1296982042864e","00","021e8882ef5a0ed932edeebbecfeda1d7ce528ec7b3daa27641acf1189d7b5dc","Empty data"] +] diff --git a/bitcoin/tests/data/combine_psbt_hex b/bitcoin/tests/data/combine_psbt_hex new file mode 100644 index 000000000..47f387017 --- /dev/null +++ b/bitcoin/tests/data/combine_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/create_psbt_hex b/bitcoin/tests/data/create_psbt_hex new file mode 100644 index 000000000..b5ef8d5ed --- /dev/null +++ b/bitcoin/tests/data/create_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000 \ No newline at end of file diff --git a/bitcoin/tests/data/extract_tx_hex b/bitcoin/tests/data/extract_tx_hex new file mode 100644 index 000000000..41c22961f --- /dev/null +++ b/bitcoin/tests/data/extract_tx_hex @@ -0,0 +1 @@ +0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000 \ No newline at end of file diff --git a/bitcoin/tests/data/finalize_psbt_hex b/bitcoin/tests/data/finalize_psbt_hex new file mode 100644 index 000000000..2866b82b7 --- /dev/null +++ b/bitcoin/tests/data/finalize_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/huge_witness.hex b/bitcoin/tests/data/huge_witness.hex new file mode 100644 index 000000000..34aec3a8f --- /dev/null +++ b/bitcoin/tests/data/huge_witness.hex @@ -0,0 +1 @@ +020000000001015d631bf6a5dbb22cdfad0349e54367393e76bfdec3f187207adcfbbc04d92bfe0000000000ffffffff010000000000000000266a24796f75276c6c2072756e20636c6e2e20616e6420796f75276c6c2062652068617070792efe23a10700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015021c11dae61a4a8f841952be3a511502d4f56e889ffa0685aa0098773ea2d4309f62400000000 diff --git a/bitcoin/tests/data/legacy_sighash.json b/bitcoin/tests/data/legacy_sighash.json new file mode 100644 index 000000000..ea7d9fef4 --- /dev/null +++ b/bitcoin/tests/data/legacy_sighash.json @@ -0,0 +1,292 @@ +[ + ["tx, script, input_index, hash_type, expected_sighash"], + ["907c2bc503ade11cc3b04eb2918b6f547b0630ab569273824748c87ea14b0696526c66ba740200000004ab65ababfd1f9bdd4ef073c7afc4ae00da8a66f429c917a0081ad1e1dabce28d373eab81d8628de802000000096aab5253ab52000052ad042b5f25efb33beec9f3364e8a9139e8439d9d7e26529c3c30b6c3fd89f8684cfd68ea0200000009ab53526500636a52ab599ac2fe02a526ed040000000008535300516352515164370e010000000003006300ab2ec229", "", 2, 1864164639, "31af167a6cf3f9d5f6875caa4d31704ceb0eba078d132b78dab52c3b8997317e"], + ["a0aa3126041621a6dea5b800141aa696daf28408959dfb2df96095db9fa425ad3f427f2f6103000000015360290e9c6063fa26912c2e7fb6a0ad80f1c5fea1771d42f12976092e7a85a4229fdb6e890000000001abc109f6e47688ac0e4682988785744602b8c87228fcef0695085edf19088af1a9db126e93000000000665516aac536affffffff8fe53e0806e12dfd05d67ac68f4768fdbe23fc48ace22a5aa8ba04c96d58e2750300000009ac51abac63ab5153650524aa680455ce7b000000000000499e50030000000008636a00ac526563ac5051ee030000000003abacabd2b6fe000000000003516563910fb6b5", "65", 0, -1391424484, "48d6a1bd2cd9eec54eb866fc71209418a950402b5d7e52363bfb75c98e141175"], + ["73107cbd025c22ebc8c3e0a47b2a760739216a528de8d4dab5d45cbeb3051cebae73b01ca10200000007ab6353656a636affffffffe26816dffc670841e6a6c8c61c586da401df1261a330a6c6b3dd9f9a0789bc9e000000000800ac6552ac6aac51ffffffff0174a8f0010000000004ac52515100000000", "5163ac63635151ac", 1, 1190874345, "06e328de263a87b09beabe222a21627a6ea5c7f560030da31610c4611f4a46bc"], + ["50818f4c01b464538b1e7e7f5ae4ed96ad23c68c830e78da9a845bc19b5c3b0b20bb82e5e9030000000763526a63655352ffffffff023b3f9c040000000008630051516a6a5163a83caf01000000000553ab65510000000000", "6aac", 0, 946795545, "746306f322de2b4b58ffe7faae83f6a72433c22f88062cdde881d4dd8a5a4e2d"], + ["a93e93440250f97012d466a6cc24839f572def241c814fe6ae94442cf58ea33eb0fdd9bcc1030000000600636a0065acffffffff5dee3a6e7e5ad6310dea3e5b3ddda1a56bf8de7d3b75889fc024b5e233ec10f80300000007ac53635253ab53ffffffff0160468b04000000000800526a5300ac526a00000000", "ac00636a53", 1, 1773442520, "5c9d3a2ce9365bb72cfabbaa4579c843bb8abf200944612cf8ae4b56a908bcbd"], + ["d3b7421e011f4de0f1cea9ba7458bf3486bee722519efab711a963fa8c100970cf7488b7bb0200000003525352dcd61b300148be5d05000000000000000000", "535251536aac536a", 0, -1960128125, "29aa6d2d752d3310eba20442770ad345b7f6a35f96161ede5f07b33e92053e2a"], + ["04bac8c5033460235919a9c63c42b2db884c7c8f2ed8fcd69ff683a0a2cccd9796346a04050200000003655351fcad3a2c5a7cbadeb4ec7acc9836c3f5c3e776e5c566220f7f965cf194f8ef98efb5e3530200000007526a006552526526a2f55ba5f69699ece76692552b399ba908301907c5763d28a15b08581b23179cb01eac03000000075363ab6a516351073942c2025aa98a05000000000765006aabac65abd7ffa6030000000004516a655200000000", "53ac6365ac526a", 1, 764174870, "bf5fdc314ded2372a0ad078568d76c5064bf2affbde0764c335009e56634481b"], + ["c363a70c01ab174230bbe4afe0c3efa2d7f2feaf179431359adedccf30d1f69efe0c86ed390200000002ab51558648fe0231318b04000000000151662170000000000008ac5300006a63acac00000000", "", 0, 2146479410, "191ab180b0d753763671717d051f138d4866b7cb0d1d4811472e64de595d2c70"], + ["8d437a7304d8772210a923fd81187c425fc28c17a5052571501db05c7e89b11448b36618cd02000000026a6340fec14ad2c9298fde1477f1e8325e5747b61b7e2ff2a549f3d132689560ab6c45dd43c3010000000963ac00ac000051516a447ed907a7efffebeb103988bf5f947fc688aab2c6a7914f48238cf92c337fad4a79348102000000085352ac526a5152517436edf2d80e3ef06725227c970a816b25d0b58d2cd3c187a7af2cea66d6b27ba69bf33a0300000007000063ab526553f3f0d6140386815d030000000003ab6300de138f00000000000900525153515265abac1f87040300000000036aac6500000000", "51", 3, -315779667, "b6632ac53578a741ae8c36d8b69e79f39b89913a2c781cdf1bf47a8c29d997a5"], + ["fd878840031e82fdbe1ad1d745d1185622b0060ac56638290ec4f66b1beef4450817114a2c0000000009516a63ab53650051abffffffff37b7a10322b5418bfd64fb09cd8a27ddf57731aeb1f1f920ffde7cb2dfb6cdb70300000008536a5365ac53515369ecc034f1594690dbe189094dc816d6d57ea75917de764cbf8eccce4632cbabe7e116cd0100000003515352ffffffff035777fc000000000003515200abe9140300000000050063005165bed6d10200000000076300536363ab65195e9110", "635265", 0, 1729787658, "6e3735d37a4b28c45919543aabcb732e7a3e1874db5315abb7cc6b143d62ff10"], + ["a63bc673049c75211aa2c09ecc38e360eaa571435fedd2af1116b5c1fa3d0629c269ecccbf0000000008ac65ab516352ac52ffffffffbf1a76fdda7f451a5f0baff0f9ccd0fe9136444c094bb8c544b1af0fa2774b06010000000463535253ffffffff13d6b7c3ddceef255d680d87181e100864eeb11a5bb6a3528cb0d70d7ee2bbbc02000000056a0052abab951241809623313b198bb520645c15ec96bfcc74a2b0f3db7ad61d455cc32db04afc5cc702000000016309c9ae25014d9473020000000004abab6aac3bb1e803", "", 3, -232881718, "6e48f3da3a4ac07eb4043a232df9f84e110485d7c7669dd114f679c27d15b97e"], + ["4c565efe04e7d32bac03ae358d63140c1cfe95de15e30c5b84f31bb0b65bb542d637f49e0f010000000551abab536348ae32b31c7d3132030a510a1b1aacf7b7c3f19ce8dc49944ef93e5fa5fe2d356b4a73a00100000009abac635163ac00ab514c8bc57b6b844e04555c0a4f4fb426df139475cd2396ae418bc7015820e852f711519bc202000000086a00510000abac52488ff4aec72cbcfcc98759c58e20a8d2d9725aa4a80f83964e69bc4e793a4ff25cd75dc701000000086a52ac6aac5351532ec6b10802463e0200000000000553005265523e08680100000000002f39a6b0", "", 3, 70712784, "c6076b6a45e6fcfba14d3df47a34f6aadbacfba107e95621d8d7c9c0e40518ed"], + ["fd22692802db8ae6ab095aeae3867305a954278f7c076c542f0344b2591789e7e33e4d29f4020000000151ffffffffb9409129cfed9d3226f3b6bab7a2c83f99f48d039100eeb5796f00903b0e5e5e0100000006656552ac63abd226abac0403e649000000000007abab51ac5100ac8035f10000000000095165006a63526a52510d42db030000000007635365ac6a63ab24ef5901000000000453ab6a0000000000", "536a52516aac6a", 1, 309309168, "7ca0f75e6530ec9f80d031fc3513ca4ecd67f20cb38b4dacc6a1d825c3cdbfdb"], + ["a43f85f701ffa54a3cc57177510f3ea28ecb6db0d4431fc79171cad708a6054f6e5b4f89170000000008ac6a006a536551652bebeaa2013e779c05000000000665ac5363635100000000", "ac", 0, 2028978692, "58294f0d7f2e68fe1fd30c01764fe1619bcc7961d68968944a0e263af6550437"], + ["c2b0b99001acfecf7da736de0ffaef8134a9676811602a6299ba5a2563a23bb09e8cbedf9300000000026300ffffffff042997c50300000000045252536a272437030000000007655353ab6363ac663752030000000002ab6a6d5c900000000000066a6a5265abab00000000", "52ac525163515251", 0, -894181723, "8b300032a1915a4ac05cea2f7d44c26f2a08d109a71602636f15866563eaafdc"], + ["82f9f10304c17a9d954cf3380db817814a8c738d2c811f0412284b2c791ec75515f38c4f8c020000000265ab5729ca7db1b79abee66c8a757221f29280d0681355cb522149525f36da760548dbd7080a0100000001510b477bd9ce9ad5bb81c0306273a3a7d051e053f04ecf3a1dbeda543e20601a5755c0cfae030000000451ac656affffffff71141a04134f6c292c2e0d415e6705dfd8dcee892b0d0807828d5aeb7d11f5ef0300000001520b6c6dc802a6f3dd0000000000056aab515163bfb6800300000000015300000000", "", 3, -635779440, "d55ed1e6c53510f2608716c12132a11fb5e662ec67421a513c074537eeccc34b"], + ["2074bad5011847f14df5ea7b4afd80cd56b02b99634893c6e3d5aaad41ca7c8ee8e5098df003000000026a6affffffff018ad59700000000000900ac656a526551635300000000", "65635265", 0, -1804671183, "663c999a52288c9999bff36c9da2f8b78d5c61b8347538f76c164ccba9868d0a"], + ["7100b11302e554d4ef249ee416e7510a485e43b2ba4b8812d8fe5529fe33ea75f36d392c4403000000020000ffffffff3d01a37e075e9a7715a657ae1bdf1e44b46e236ad16fd2f4c74eb9bf370368810000000007636553ac536365ffffffff01db696a0400000000065200ac656aac00000000", "63005151", 0, -1210499507, "b9c3aee8515a4a3b439de1ffc9c156824bda12cb75bfe5bc863164e8fd31bd7a"], + ["02c1017802091d1cb08fec512db7b012fe4220d57a5f15f9e7676358b012786e1209bcff950100000004acab6352ffffffff799bc282724a970a6fea1828984d0aeb0f16b67776fa213cbdc4838a2f1961a3010000000951516a536552ab6aabffffffff016c7b4b03000000000865abac5253ac5352b70195ad", "65655200516a", 0, -241626954, "be567cb47170b34ff81c66c1142cb9d27f9b6898a384d6dfc4fce16b75b6cb14"], + ["4504cb1904c7a4acf375ddae431a74de72d5436efc73312cf8e9921f431267ea6852f9714a01000000066a656a656553a2fbd587c098b3a1c5bd1d6480f730a0d6d9b537966e20efc0e352d971576d0f87df0d6d01000000016321aeec3c4dcc819f1290edb463a737118f39ab5765800547522708c425306ebfca3f396603000000055300ac656a1d09281d05bfac57b5eb17eb3fa81ffcedfbcd3a917f1be0985c944d473d2c34d245eb350300000007656a51525152ac263078d9032f470f0500000000066aac00000052e12da60200000000003488410200000000076365006300ab539981e432", "52536a52526a", 1, -31909119, "f0a2deee7fd8a3a9fad6927e763ded11c940ee47e9e6d410f94fda5001f82e0c"], + ["14bc7c3e03322ec0f1311f4327e93059c996275302554473104f3f7b46ca179bfac9ef753503000000016affffffff9d405eaeffa1ca54d9a05441a296e5cc3a3e32bb8307afaf167f7b57190b07e00300000008abab51ab5263abab45533aa242c61bca90dd15d46079a0ab0841d85df67b29ba87f2393cd764a6997c372b55030000000452005263ffffffff0250f40e02000000000651516a0063630e95ab0000000000046a5151ac00000000", "6a65005151", 0, -1460947095, "aa418d096929394c9147be8818d8c9dafe6d105945ab9cd7ec682df537b5dd79"], + ["a08ff466049fb7619e25502ec22fedfb229eaa1fe275aa0b5a23154b318441bf547989d0510000000005ab5363636affffffff2b0e335cb5383886751cdbd993dc0720817745a6b1c9b8ab3d15547fc9aafd03000000000965656a536a52656a532b53d10584c290d3ac1ab74ab0a19201a4a039cb59dc58719821c024f6bf2eb26322b33f010000000965ac6aac0053ab6353ffffffff048decba6ebbd2db81e416e39dde1f821ba69329725e702bcdea20c5cc0ecc6402000000086363ab5351ac6551466e377b0468c0fa00000000000651ab53ac6a513461c6010000000008636a636365535100eeb3dc010000000006526a52ac516a43f362010000000005000063536500000000", "0063516a", 1, -1158911348, "f6a1ecb50bd7c2594ebecea5a1aa23c905087553e40486dade793c2f127fdfae"], + ["f10a0356031cd569d652dbca8e7a4d36c8da33cdff428d003338602b7764fe2c96c505175b010000000465ac516affffffffbb54563c71136fa944ee20452d78dc87073ac2365ba07e638dce29a5d179da600000000003635152ffffffff9a411d8e2d421b1e6085540ee2809901e590940bbb41532fa38bd7a16b68cc350100000007535251635365636195df1603b61c45010000000002ab65bf6a310400000000026352fcbba10200000000016aa30b7ff0", "5351", 0, 1552495929, "9eb8adf2caecb4bf9ac59d7f46bd20e83258472db2f569ee91aba4cf5ee78e29"], + ["c3325c9b012f659466626ca8f3c61dfd36f34670abc054476b7516a1839ec43cd0870aa0c0000000000753525265005351e7e3f04b0112650500000000000363ac6300000000", "acac", 0, -68961433, "5ca70e727d91b1a42b78488af2ed551642c32d3de4712a51679f60f1456a8647"], + ["b500ca48011ec57c2e5252e5da6432089130603245ffbafb0e4c5ffe6090feb629207eeb0e010000000652ab6a636aab8302c9d2042b44f40500000000015278c05a050000000004ac5251524be080020000000007636aac63ac5252c93a9a04000000000965ab6553636aab5352d91f9ddb", "52005100", 0, -2024394677, "49c8a6940a461cc7225637f1e512cdd174c99f96ec05935a59637ededc77124c"], + ["f52ff64b02ee91adb01f3936cc42e41e1672778962b68cf013293d649536b519bc3271dd2c00000000020065afee11313784849a7c15f44a61cd5fd51ccfcdae707e5896d131b082dc9322a19e12858501000000036aac654e8ca882022deb7c020000000006006a515352abd3defc0000000000016300000000", "63520063", 0, 1130989496, "7f208df9a5507e98c62cebc5c1e2445eb632e95527594929b9577b53363e96f6"], + ["ab7d6f36027a7adc36a5cf7528fe4fb5d94b2c96803a4b38a83a675d7806dda62b380df86a0000000003000000ffffffff5bc00131e29e22057c04be854794b4877dda42e416a7a24706b802ff9da521b20000000007ac6a0065ac52ac957cf45501b9f06501000000000500ac6363ab25f1110b", "00526500536a635253", 0, 911316637, "5fa09d43c8aef6f6fa01c383a69a5a61a609cd06e37dce35a39dc9eae3ddfe6c"], + ["f940888f023dce6360263c850372eb145b864228fdbbb4c1186174fa83aab890ff38f8c9a90300000000ffffffff01e80ccdb081e7bbae1c776531adcbfb77f2e5a7d0e5d0d0e2e6c8758470e85f00000000020053ffffffff03b49088050000000004656a52ab428bd604000000000951630065ab63ac636a0cbacf0400000000070063ac5265ac53d6e16604", "ac63", 0, 39900215, "713ddeeefcfe04929e7b6593c792a4efbae88d2b5280d1f0835d2214eddcbad6"], + ["530ecd0b01ec302d97ef6f1b5a6420b9a239714013e20d39aa3789d191ef623fc215aa8b940200000005ac5351ab6a3823ab8202572eaa04000000000752ab6a51526563fd8a270100000000036a006581a798f0", "525153656a0063", 0, 1784562684, "fe42f73a8742676e640698222b1bd6b9c338ff1ccd766d3d88d7d3c6c6ac987e"], + ["5d781d9303acfcce964f50865ddfddab527ea971aee91234c88e184979985c00b4de15204b0100000003ab6352a009c8ab01f93c8ef2447386c434b4498538f061845862c3f9d5751ad0fce52af442b3a902000000045165ababb909c66b5a3e7c81b3c45396b944be13b8aacfc0204f3f3c105a66fa8fa6402f1b5efddb01000000096a65ac636aacab656ac3c677c402b79fa4050000000004006aab5133e35802000000000751ab635163ab0078c2e025", "6aac51636a6a005265", 0, -882306874, "551ce975d58647f10adefb3e529d9bf9cda34751627ec45e690f135ef0034b95"], + ["a9c57b1a018551bcbc781b256642532bbc09967f1cbe30a227d352a19365d219d3f11649a3030000000451655352b140942203182894030000000006ab00ac6aab654add350400000000003d379505000000000553abacac00e1739d36", "5363", 0, -1069721025, "6da32416deb45a0d720a1dbe6d357886eabc44029dd5db74d50feaffbe763245"], + ["05c4fb94040f5119dc0b10aa9df054871ed23c98c890f1e931a98ffb0683dac45e98619fdc0200000007acab6a525263513e7495651c9794c4d60da835d303eb4ee6e871f8292f6ad0b32e85ef08c9dc7aa4e03c9c010000000500ab52acacfffffffffee953259cf14ced323fe8d567e4c57ba331021a1ef5ac2fa90f7789340d7c550100000007ac6aacac6a6a53ffffffff08d9dc820d00f18998af247319f9de5c0bbd52a475ea587f16101af3afab7c210100000003535363569bca7c0468e34f00000000000863536353ac51ac6584e319010000000006650052ab6a533debea030000000003ac0053ee7070020000000006ac52005253ac00000000", "6351005253", 2, 1386916157, "76c4013c40bfa1481badd9d342b6d4b8118de5ab497995fafbf73144469e5ff0"], + ["ca66ae10049533c2b39f1449791bd6d3f039efe0a121ab7339d39ef05d6dcb200ec3fb2b3b020000000465006a53ffffffff534b8f97f15cc7fb4f4cea9bf798472dc93135cd5b809e4ca7fe4617a61895980100000000ddd83c1dc96f640929dd5e6f1151dab1aa669128591f153310d3993e562cc7725b6ae3d903000000046a52536582f8ccddb8086d8550f09128029e1782c3f2624419abdeaf74ecb24889cc45ac1a64492a0100000002516a4867b41502ee6ccf03000000000752acacab52ab6a4b7ba80000000000075151ab0052536300000000", "6553", 2, -62969257, "8085e904164ab9a8c20f58f0d387f6adb3df85532e11662c03b53c3df8c943cb"], + ["ba646d0b0453999f0c70cb0430d4cab0e2120457bb9128ed002b6e9500e9c7f8d7baa20abe0200000001652a4e42935b21db02b56bf6f08ef4be5adb13c38bc6a0c3187ed7f6197607ba6a2c47bc8a03000000040052516affffffffa55c3cbfc19b1667594ac8681ba5d159514b623d08ed4697f56ce8fcd9ca5b0b00000000096a6a5263ac655263ab66728c2720fdeabdfdf8d9fb2bfe88b295d3b87590e26a1e456bad5991964165f888c03a0200000006630051ac00acffffffff0176fafe0100000000070063acac65515200000000", "63", 1, 2002322280, "9db4e320208185ee70edb4764ee195deca00ba46412d5527d9700c1cf1c3d057"], + ["2ddb8f84039f983b45f64a7a79b74ff939e3b598b38f436def7edd57282d0803c7ef34968d02000000026a537eb00c4187de96e6e397c05f11915270bcc383959877868ba93bac417d9f6ed9f627a7930300000004516551abffffffffacc12f1bb67be3ae9f1d43e55fda8b885340a0df1175392a8bbd9f959ad3605003000000025163ffffffff02ff0f4700000000000070bd99040000000003ac53abf8440b42", "", 2, -393923011, "0133f1a161363b71dfb3a90065c7128c56bd0028b558b610142df79e055ab5c7"], + ["b21fc15403b4bdaa994204444b59323a7b8714dd471bd7f975a4e4b7b48787e720cbd1f5f00000000000ffffffff311533001cb85c98c1d58de0a5fbf27684a69af850d52e22197b0dc941bc6ca9030000000765ab6363ab5351a8ae2c2c7141ece9a4ff75c43b7ea9d94ec79b7e28f63e015ac584d984a526a73fe1e04e0100000007526352536a5365ffffffff02a0a9ea030000000002ab52cfc4f300000000000465525253e8e0f342", "000000", 1, 1305253970, "d1df1f4bba2484cff8a816012bb6ec91c693e8ca69fe85255e0031711081c46a"], + ["f821a042036ad43634d29913b77c0fc87b4af593ac86e9a816a9d83fd18dfcfc84e1e1d57102000000076a63ac52006351ffffffffbcdaf490fc75086109e2f832c8985716b3a624a422cf9412fe6227c10585d21203000000095252abab5352ac526affffffff2efed01a4b73ad46c7f7bc7fa3bc480f8e32d741252f389eaca889a2e9d2007e000000000353ac53ffffffff032ac8b3020000000009636300000063516300d3d9f2040000000006510065ac656aafa5de0000000000066352ab5300ac9042b57d", "525365", 1, 667065611, "0d17a92c8d5041ba09b506ddf9fd48993be389d000aad54f9cc2a44fcc70426b"], + ["d62f183e037e0d52dcf73f9b31f70554bce4f693d36d17552d0e217041e01f15ad3840c838000000000963acac6a6a6a63ab63ffffffffabdfb395b6b4e63e02a763830f536fc09a35ff8a0cf604021c3c751fe4c88f4d0300000006ab63ab65ac53aa4d30de95a2327bccf9039fb1ad976f84e0b4a0936d82e67eafebc108993f1e57d8ae39000000000165ffffffff04364ad30500000000036a005179fd84010000000007ab636aac6363519b9023030000000008510065006563ac6acd2a4a02000000000000000000", "52", 1, 595020383, "da8405db28726dc4e0f82b61b2bfd82b1baa436b4e59300305cc3b090b157504"], + ["44c200a5021238de8de7d80e7cce905606001524e21c8d8627e279335554ca886454d692e6000000000500acac52abbb8d1dc876abb1f514e96b21c6e83f429c66accd961860dc3aed5071e153e556e6cf076d02000000056553526a51870a928d0360a580040000000004516a535290e1e302000000000851ab6a00510065acdd7fc5040000000007515363ab65636abb1ec182", "6363", 0, -785766894, "ed53cc766cf7cb8071cec9752460763b504b2183442328c5a9761eb005c69501"], + ["d682d52d034e9b062544e5f8c60f860c18f029df8b47716cabb6c1b4a4b310a0705e754556020000000400656a0016eeb88eef6924fed207fba7ddd321ff3d84f09902ff958c815a2bf2bb692eb52032c4d803000000076365ac516a520099788831f8c8eb2552389839cfb81a9dc55ecd25367acad4e03cfbb06530f8cccf82802701000000085253655300656a53ffffffff02d543200500000000056a510052ac03978b05000000000700ac51525363acfdc4f784", "", 2, -696035135, "e1a256854099907050cfee7778f2018082e735a1f1a3d91437584850a74c87bb"], + ["e8c0dec5026575ddf31343c20aeeca8770afb33d4e562aa8ee52eeda6b88806fdfd4fe0a97030000000953acabab65ab516552ffffffffdde122c2c3e9708874286465f8105f43019e837746686f442666629088a970e0010000000153ffffffff01f98eee0100000000025251fe87379a", "63", 1, 633826334, "abe441209165d25bc6d8368f2e7e7dc21019056719fef1ace45542aa2ef282e2"], + ["b288c331011c17569293c1e6448e33a64205fc9dc6e35bc756a1ac8b97d18e912ea88dc0770200000007635300ac6aacabfc3c890903a3ccf8040000000004656500ac9c65c9040000000009ab6a6aabab65abac63ac5f7702000000000365005200000000", "526a63", 0, 1574937329, "0dd1bd5c25533bf5f268aa316ce40f97452cca2061f0b126a59094ca5b65f7a0"], + ["6b68ba00023bb4f446365ea04d68d48539aae66f5b04e31e6b38b594d2723ab82d44512460000000000200acffffffff5dfc6febb484fff69c9eeb7c7eb972e91b6d949295571b8235b1da8955f3137b020000000851ac6352516a535325828c8a03365da801000000000800636aabac6551ab0f594d03000000000963ac536365ac63636a45329e010000000005abac53526a00000000", "005151", 0, 1317038910, "42f5ba6f5fe1e00e652a08c46715871dc4b40d89d9799fd7c0ea758f86eab6a7"], + ["046ac25e030a344116489cc48025659a363da60bc36b3a8784df137a93b9afeab91a04c1ed020000000951ab0000526a65ac51ffffffff6c094a03869fde55b9a8c4942a9906683f0a96e2d3e5a03c73614ea3223b2c29020000000500ab636a6affffffff3da7aa5ecef9071600866267674b54af1740c5aeb88a290c459caa257a2683cb0000000004ab6565ab7e2a1b900301b916030000000005abac63656308f4ed03000000000852ab53ac63ac51ac73d620020000000003ab00008deb1285", "6a", 2, 1299505108, "f79e6b776e2592bad45ca328c54abf14050c241d8f822d982c36ea890fd45757"], + ["ff5400dd02fec5beb9a396e1cbedc82bedae09ed44bae60ba9bef2ff375a6858212478844b03000000025253ffffffff01e46c203577a79d1172db715e9cc6316b9cfc59b5e5e4d9199fef201c6f9f0f000000000900ab6552656a5165acffffffff02e8ce62040000000002515312ce3e00000000000251513f119316", "", 0, 1541581667, "1e0da47eedbbb381b0e0debbb76e128d042e02e65b11125e17fd127305fc65cd"], + ["b54bf5ac043b62e97817abb892892269231b9b220ba08bc8dbc570937cd1ea7cdc13d9676c010000000451ab5365a10adb7b35189e1e8c00b86250f769319668189b7993d6bdac012800f1749150415b2deb0200000003655300ffffffff60b9f4fb9a7e17069fd00416d421f804e2ef2f2c67de4ca04e0241b9f9c1cc5d0200000003ab6aacfffffffff048168461cce1d40601b42fbc5c4f904ace0d35654b7cc1937ccf53fe78505a0100000008526563525265abacffffffff01dbf4e6040000000007acac656553636500000000", "63", 2, 882302077, "f5b38b0f06e246e47ce622e5ee27d5512c509f8ac0e39651b3389815eff2ab93"], + ["ebf628b30360bab3fa4f47ce9e0dcbe9ceaf6675350e638baff0c2c197b2419f8e4fb17e16000000000452516365ac4d909a79be207c6e5fb44fbe348acc42fc7fe7ef1d0baa0e4771a3c4a6efdd7e2c118b0100000003acacacffffffffa6166e9101f03975721a3067f1636cc390d72617be72e5c3c4f73057004ee0ee010000000863636a6a516a5252c1b1e82102d8d54500000000000153324c900400000000015308384913", "0063516a51", 1, -1658428367, "eb2d8dea38e9175d4d33df41f4087c6fea038a71572e3bad1ea166353bf22184"], + ["d6a8500303f1507b1221a91adb6462fb62d741b3052e5e7684ea7cd061a5fc0b0e93549fa50100000004acab65acfffffffffdec79bf7e139c428c7cfd4b35435ae94336367c7b5e1f8e9826fcb0ebaaaea30300000000ffffffffd115fdc00713d52c35ea92805414bd57d1e59d0e6d3b79a77ee18a3228278ada020000000453005151ffffffff040231510300000000085100ac6a6a000063c6041c0400000000080000536a6563acac138a0b04000000000263abd25fbe03000000000900656a00656aac510000000000", "ac526aac6a00", 1, -2007972591, "13d12a51598b34851e7066cd93ab8c5212d60c6ed2dae09d91672c10ccd7f87c"], + ["e92492cc01aec4e62df67ea3bc645e2e3f603645b3c5b353e4ae967b562d23d6e043badecd0100000003acab65ffffffff02c7e5ea040000000002ab52e1e584010000000005536365515195d16047", "6551", 0, -424930556, "93c34627f526d73f4bea044392d1a99776b4409f7d3d835f23b03c358f5a61c2"], + ["b28d5f5e015a7f24d5f9e7b04a83cd07277d452e898f78b50aae45393dfb87f94a26ef57720200000008ababac630053ac52ffffffff046475ed040000000008ab5100526363ac65c9834a04000000000251abae26b30100000000040000ac65ceefb900000000000000000000", "ac6551ac6a536553", 0, -1756558188, "5848d93491044d7f21884eef7a244fe7d38886f8ae60df49ce0dfb2a342cd51a"], + ["efb8b09801f647553b91922a5874f8e4bb2ed8ddb3536ed2d2ed0698fac5e0e3a298012391030000000952ac005263ac52006affffffff04cdfa0f050000000007ac53ab51abac65b68d1b02000000000553ab65ac00d057d50000000000016a9e1fda010000000007ac63ac536552ac00000000", "6aac", 0, 1947322973, "603a9b61cd30fcea43ef0a5c18b88ca372690b971b379ee9e01909c336280511"], + ["67761f2a014a16f3940dcb14a22ba5dc057fcffdcd2cf6150b01d516be00ef55ef7eb07a830100000004636a6a51ffffffff01af67bd050000000008526553526300510000000000", "6a00", 0, 1570943676, "079fa62e9d9d7654da8b74b065da3154f3e63c315f25751b4d896733a1d67807"], + ["ec02fbee03120d02fde12574649660c441b40d330439183430c6feb404064d4f507e704f3c0100000000ffffffffe108d99c7a4e5f75cc35c05debb615d52fac6e3240a6964a29c1704d98017fb60200000002ab63fffffffff726ec890038977adfc9dadbeaf5e486d5fcb65dc23acff0dd90b61b8e2773410000000002ac65e9dace55010f881b010000000005ac00ab650000000000", "51ac525152ac6552", 2, -1564046020, "3f988922d8cd11c7adff1a83ce9499019e5ab5f424752d8d361cf1762e04269b"], + ["33b03bf00222c7ca35c2f8870bbdef2a543b70677e413ce50494ac9b22ea673287b6aa55c50000000005ab00006a52ee4d97b527eb0b427e4514ea4a76c81e68c34900a23838d3e57d0edb5410e62eeb8c92b6000000000553ac6aacac42e59e170326245c000000000009656553536aab516aabb1a10603000000000852ab52ab6a516500cc89c802000000000763ac6a63ac516300000000", "", 0, 557416556, "41bead1b073e1e9fee065dd612a617ca0689e8f9d3fed9d0acfa97398ebb404c"], + ["813eda1103ac8159850b4524ef65e4644e0fc30efe57a5db0c0365a30446d518d9b9aa8fdd0000000003656565c2f1e89448b374b8f12055557927d5b33339c52228f7108228149920e0b77ef0bcd69da60000000006abac00ab63ab82cdb7978d28630c5e1dc630f332c4245581f787936f0b1e84d38d33892141974c75b4750300000004ac53ab65ffffffff0137edfb02000000000000000000", "0063", 1, -1948560575, "71dfcd2eb7f2e6473aed47b16a6d5fcbd0af22813d892e9765023151e07771ec"], + ["9e45d9aa0248c16dbd7f435e8c54ae1ad086de50c7b25795a704f3d8e45e1886386c653fbf01000000025352fb4a1acefdd27747b60d1fb79b96d14fb88770c75e0da941b7803a513e6d4c908c6445c7010000000163ffffffff014069a8010000000001520a794fb3", "51ac005363", 1, -719113284, "0d31a221c69bd322ef7193dd7359ddfefec9e0a1521d4a8740326d46e44a5d6a"], + ["c3efabba03cb656f154d1e159aa4a1a4bf9423a50454ebcef07bc3c42a35fb8ad84014864d0000000000d1cc73d260980775650caa272e9103dc6408bdacaddada6b9c67c88ceba6abaa9caa2f7d020000000553536a5265ffffffff9f946e8176d9b11ff854b76efcca0a4c236d29b69fb645ba29d406480427438e01000000066a0065005300ffffffff040419c0010000000003ab6a63cdb5b6010000000009006300ab5352656a63f9fe5e050000000004acac5352611b980100000000086a00acac00006a512d7f0c40", "0053", 0, -59089911, "c503001c16fbff82a99a18d88fe18720af63656fccd8511bca1c3d0d69bd7fc0"], + ["efb55c2e04b21a0c25e0e29f6586be9ef09f2008389e5257ebf2f5251051cdc6a79fce2dac020000000351006affffffffaba73e5b6e6c62048ba5676d18c33ccbcb59866470bb7911ccafb2238cfd493802000000026563ffffffffe62d7cb8658a6eca8a8babeb0f1f4fa535b62f5fc0ec70eb0111174e72bbec5e0300000009abababac516365526affffffffbf568789e681032d3e3be761642f25e46c20322fa80346c1146cb47ac999cf1b0300000000b3dbd55902528828010000000001ab0aac7b0100000000015300000000", "acac52", 3, 1638140535, "e84444d91580da41c8a7dcf6d32229bb106f1be0c811b2292967ead5a96ce9d4"], + ["91d3b21903629209b877b3e1aef09cd59aca6a5a0db9b83e6b3472aceec3bc2109e64ab85a0200000003530065ffffffffca5f92de2f1b7d8478b8261eaf32e5656b9eabbc58dcb2345912e9079a33c4cd010000000700ab65ab00536ad530611da41bbd51a389788c46678a265fe85737b8d317a83a8ff7a839debd18892ae5c80300000007ab6aac65ab51008b86c501038b8a9a05000000000263525b3f7a040000000007ab535353ab00abd4e3ff04000000000665ac51ab65630b7b656f", "6551525151516a00", 2, 499657927, "ef4bd7622eb7b2bbbbdc48663c1bc90e01d5bde90ff4cb946596f781eb420a0c"], + ["ceecfa6c02b7e3345445b82226b15b7a097563fa7d15f3b0c979232b138124b62c0be007890200000009abac51536a63525253ffffffffbae481ccb4f15d94db5ec0d8854c24c1cc8642bd0c6300ede98a91ca13a4539a0200000001ac50b0813d023110f5020000000006acabac526563e2b0d0040000000009656aac0063516a536300000000", "0063526500", 0, -1862053821, "e1600e6df8a6160a79ac32aa40bb4644daa88b5f76c0d7d13bf003327223f70c"], + ["f06f64af04fdcb830464b5efdb3d5ee25869b0744005375481d7b9d7136a0eb8828ad1f0240200000003516563fffffffffd3ba192dabe9c4eb634a1e3079fca4f072ee5ceb4b57deb6ade5527053a92c5000000000165ffffffff39f43401a36ba13a5c6dd7f1190e793933ae32ee3bf3e7bfb967be51e681af760300000009650000536552636a528e34f50b21183952cad945a83d4d56294b55258183e1627d6e8fb3beb8457ec36cadb0630000000005abab530052334a7128014bbfd10100000000085352ab006a63656afc424a7c", "53650051635253ac00", 2, 313255000, "d309da5afd91b7afa257cfd62df3ca9df036b6a9f4b38f5697d1daa1f587312b"], + ["6dfd2f98046b08e7e2ef5fff153e00545faf7076699012993c7a30cb1a50ec528281a9022f030000000152ffffffff1f535e4851920b968e6c437d84d6ecf586984ebddb7d5db6ae035bd02ba222a8010000000651006a53ab51605072acb3e17939fa0737bc3ee43bc393b4acd58451fc4ffeeedc06df9fc649828822d5010000000253525a4955221715f27788d302382112cf60719be9ae159c51f394519bd5f7e70a4f9816c7020200000009526a6a51636aab656a36d3a5ff0445548e0100000000086a6a00516a52655167030b050000000004ac6a63525cfda8030000000000e158200000000000010000000000", "535263ac6a65515153", 3, 585774166, "72b7da10704c3ca7d1deb60c31b718ee12c70dc9dfb9ae3461edce50789fe2ba"], + ["2a45cd1001bf642a2315d4a427eddcc1e2b0209b1c6abd2db81a800c5f1af32812de42032702000000050051525200ffffffff032177db050000000005530051abac49186f000000000004ab6aab00645c0000000000000765655263acabac00000000", "6a65", 0, -1774715722, "6a9ac3f7da4c7735fbc91f728b52ecbd602233208f96ac5592656074a5db118a"], + ["ca816e7802cd43d66b9374cd9bf99a8da09402d69c688d8dcc5283ace8f147e1672b757e020200000005516aabab5240fb06c95c922342279fcd88ba6cd915933e320d7becac03192e0941e0345b79223e89570300000004005151ac353ecb5d0264dfbd010000000005ac6aacababd5d70001000000000752ac53ac6a5151ec257f71", "63ac", 1, 774695685, "cc180c4f797c16a639962e7aec58ec4b209853d842010e4d090895b22e7a7863"], + ["b42b955303942fedd7dc77bbd9040aa0de858afa100f399d63c7f167b7986d6c2377f66a7403000000066aac00525100ffffffff0577d04b64880425a3174055f94191031ad6b4ca6f34f6da9be7c3411d8b51fc000000000300526a6391e1cf0f22e45ef1c44298523b516b3e1249df153590f592fcb5c5fc432dc66f3b57cb03000000046a6aac65ffffffff0393a6c9000000000004516a65aca674ac0400000000046a525352c82c370000000000030053538e577f89", "", 1, -1237094944, "566953eb806d40a9fb684d46c1bf8c69dea86273424d562bd407b9461c8509af"], + ["92c9fe210201e781b72554a0ed5e22507fb02434ddbaa69aff6e74ea8bad656071f1923f3f02000000056a63ac6a514470cef985ba83dcb8eee2044807bedbf0d983ae21286421506ae276142359c8c6a34d68020000000863ac63525265006aa796dd0102ca3f9d05000000000800abab52ab535353cd5c83010000000007ac00525252005322ac75ee", "5165", 0, 97879971, "6e6307cef4f3a9b386f751a6f40acebab12a0e7e17171d2989293cbec7fd45c2"], + ["ccca1d5b01e40fe2c6b3ee24c660252134601dab785b8f55bd6201ffaf2fddc7b3e2192325030000000365535100496d4703b4b66603000000000665535253ac633013240000000000015212d2a502000000000951abac636353636a5337b82426", "0052", 0, -1691630172, "577bf2b3520b40aef44899a20d37833f1cded6b167e4d648fc5abe203e43b649"], + ["bc1a7a3c01691e2d0c4266136f12e391422f93655c71831d90935fbda7e840e50770c61da20000000008635253abac516353ffffffff031f32aa020000000003636563786dbc0200000000003e950f00000000000563516a655184b8a1de", "51536a", 0, -1627072905, "730bc25699b46703d7718fd5f5c34c4b5f00f594a9968ddc247fa7d5175124ed"], + ["076d209e02d904a6c40713c7225d23e7c25d4133c3c3477828f98c7d6dbd68744023dbb66b030000000753ab00536565acffffffff10975f1b8db8861ca94c8cc7c7cff086ddcd83e10b5fffd4fc8f2bdb03f9463c0100000000ffffffff029dff76010000000006526365530051a3be6004000000000000000000", "515253ac65acacac", 1, -1207502445, "66c488603b2bc53f0d22994a1f0f66fb2958203102eba30fe1d37b27a55de7a5"], + ["cac6382d0462375e83b67c7a86c922b569a7473bfced67f17afd96c3cd2d896cf113febf9e0300000003006a53ffffffffaa4913b7eae6821487dd3ca43a514e94dcbbf350f8cc4cafff9c1a88720711b800000000096a6a525300acac6353ffffffff184fc4109c34ea27014cc2c1536ef7ed1821951797a7141ddacdd6e429fae6ff01000000055251655200ffffffff9e7b79b4e6836e290d7b489ead931cba65d1030ccc06f20bd4ca46a40195b33c030000000008f6bc8304a09a2704000000000563655353511dbc73050000000000cf34c500000000000091f76e0000000000085200ab00005100abd07208cb", "0063656a", 2, -1488731031, "bf078519fa87b79f40abc38f1831731422722c59f88d86775535f209cb41b9b1"], + ["1711146502c1a0b82eaa7893976fefe0fb758c3f0e560447cef6e1bde11e42de91a125f71c030000000015bd8c04703b4030496c7461482481f290c623be3e76ad23d57a955807c9e851aaaa20270300000000d04abaf20326dcb7030000000001632225350400000000075263ac00520063dddad9020000000000af23d148", "52520053510063", 0, 1852122830, "e33d5ee08c0f3c130a44d7ce29606450271b676f4a80c52ab9ffab00cecf67f8"], + ["22d81c740469695a6a83a9a4824f77ecff8804d020df23713990afce2b72591ed7de98500502000000065352526a6a6affffffff90dc85e118379b1005d7bbc7d2b8b0bab104dad7eaa49ff5bead892f17d8c3ba010000000665656300ab51ffffffff965193879e1d5628b52005d8560a35a2ba57a7f19201a4045b7cbab85133311d0200000003ac005348af21a13f9b4e0ad90ed20bf84e4740c8a9d7129632590349afc03799414b76fd6e826200000000025353ffffffff04a0d40d04000000000060702700000000000652655151516ad31f1502000000000365ac0069a1ac0500000000095100655300ab53525100000000", "51636a52ac", 0, -1644680765, "add7f5da27262f13da6a1e2cc2feafdc809bd66a67fb8ae2a6f5e6be95373b6f"], + ["a27dcbc801e3475174a183586082e0914c314bc9d79d1570f29b54591e5e0dff07fbb45a7f0000000004ac53ab51ffffffff027347f5020000000005535351ab63d0e5c9030000000009ac65ab6a63515200ab7cd632ed", "ac63636553", 0, -686435306, "883a6ea3b2cc53fe8a803c229106366ca14d25ffbab9fef8367340f65b201da6"], + ["0728c606014c1fd6005ccf878196ba71a54e86cc8c53d6db500c3cc0ac369a26fac6fcbc210000000005ab53ac5365ba9668290182d7870100000000066a000053655100000000", "65", 0, 1789961588, "ab6baa6da3b2bc853868d166f8996ad31d63ef981179f9104f49968fd61c8427"], + ["ed3bb93802ddbd08cb030ef60a2247f715a0226de390c9c1a81d52e83f8674879065b5f87d0300000003ab6552ffffffff04d2c5e60a21fb6da8de20bf206db43b720e2a24ce26779bca25584c3f765d1e0200000008ab656a6aacab00ab6e946ded025a811d04000000000951abac6352ac00ab5143cfa3030000000005635200636a00000000", "5352ac650065535300", 1, -668727133, "e9995065e1fddef72a796eef5274de62012249660dc9d233a4f24e02a2979c87"], + ["59f4629d030fa5d115c33e8d55a79ea3cba8c209821f979ed0e285299a9c72a73c5bba00150200000002636affffffffd8aca2176df3f7a96d0dc4ee3d24e6cecde1582323eec2ebef9a11f8162f17ac0000000007ab6565acab6553ffffffffeebc10af4f99c7a21cbc1d1074bd9f0ee032482a71800f44f26ee67491208e0403000000065352ac656351ffffffff0434e955040000000004ab515152caf2b305000000000365ac007b1473030000000003ab530033da970500000000060051536a5253bb08ab51", "", 2, 396340944, "0e9c47973ef2c292b2252c623f465bbb92046fe0b893eebf4e1c9e02cb01c397"], + ["33a98004029d262f951881b20a8d746c8c707ea802cd2c8b02a33b7e907c58699f97e42be80100000007ac53536552abacdee04cc01d205fd8a3687fdf265b064d42ab38046d76c736aad8865ca210824b7c622ecf02000000070065006a536a6affffffff01431c5d010000000000270d48ee", "", 1, 921554116, "ff9d7394002f3f196ea25472ea6c46f753bd879a7244795157bb7235c9322902"], + ["aac18f2b02b144ed481557c53f2146ae523f24fcde40f3445ab0193b6b276c315dc2894d2300000000075165650000636a233526947dbffc76aec7db1e1baa6868ad4799c76e14794dcbaaec9e713a83967f6a65170200000005abac6551ab27d518be01b652a30000000000015300000000", "52ac5353", 1, 1559377136, "59fc2959bb7bb24576cc8a237961ed95bbb900679d94da6567734c4390cb6ef5"], + ["5ab79881033555b65fe58c928883f70ce7057426fbdd5c67d7260da0fe8b1b9e6a2674cb850300000009ac516aac6aac006a6affffffffa5be9223b43c2b1a4d120b5c5b6ec0484f637952a3252181d0f8e813e76e11580200000000e4b5ceb8118cb77215bbeedc9a076a4d087bb9cd1473ea32368b71daeeeacc451ec209010000000005acac5153aced7dc34e02bc5d11030000000005ac5363006a54185803000000000552ab00636a00000000", "5100", 1, 1927062711, "e9f53d531c12cce1c50abed4ac521a372b4449b6a12f9327c80020df6bff66c0"], + ["6c2c8fac0124b0b7d4b610c3c5b91dee32b7c927ac71abdf2d008990ca1ac40de0dfd530660300000006ababac5253656bd7eada01d847ec000000000004ac52006af4232ec8", "6a6a6a0051", 0, -340809707, "fb51eb9d7e47d32ff2086205214f90c7c139e08c257a64829ae4d2b301071c6a"], + ["0e803682024f79337b25c98f276d412bc27e56a300aa422c42994004790cee213008ff1b8303000000080051ac65ac655165f421a331892b19a44c9f88413d057fea03c3c4a6c7de4911fe6fe79cf2e9b3b10184b1910200000005525163630096cb1c670398277204000000000253acf7d5d502000000000963536a6a636a5363ab381092020000000002ac6a911ccf32", "6565", 1, -1492094009, "f0672638a0e568a919e9d8a9cbd7c0189a3e132940beeb52f111a89dcc2daa2c"], + ["7d71669d03022f9dd90edac323cde9e56354c6804c6b8e687e9ae699f46805aafb8bcaa636000000000253abffffffff698a5fdd3d7f2b8b000c68333e4dd58fa8045b3e2f689b889beeb3156cecdb490300000009525353abab0051acabc53f0aa821cdd69b473ec6e6cf45cf9b38996e1c8f52c27878a01ec8bb02e8cb31ad24e500000000055353ab0052ffffffff0447a23401000000000565ab53ab5133aaa0030000000006515163656563057d110300000000056a6aacac52cf13b5000000000003526a5100000000", "6a6a51", 1, -1349253507, "722efdd69a7d51d3d77bed0ac5544502da67e475ea5857cd5af6bdf640a69945"], + ["9ff618e60136f8e6bb7eabaaac7d6e2535f5fba95854be6d2726f986eaa9537cb283c701ff02000000026a65ffffffff012d1c0905000000000865ab00ac6a516a652f9ad240", "51515253635351ac", 0, 1571304387, "659cd3203095d4a8672646add7d77831a1926fc5b66128801979939383695a79"], + ["09adb2e90175ca0e816326ae2dce7750c1b27941b16f6278023dbc294632ab97977852a09d030000000465ab006affffffff027739cf0100000000075151ab63ac65ab8a5bb601000000000653ac5151520011313cdc", "ac", 0, -76831756, "478ee06501b4965b40bdba6cbaad9b779b38555a970912bb791b86b7191c54bc"], + ["fd22ebaa03bd588ad16795bea7d4aa7f7d48df163d75ea3afebe7017ce2f350f6a0c1cb0bb00000000086aabac5153526363ffffffff488e0bb22e26a565d77ba07178d17d8f85702630ee665ec35d152fa05af3bda10200000004515163abffffffffeb21035849e85ad84b2805e1069a91bb36c425dc9c212d9bae50a95b6bfde1200300000001ab5df262fd02b69848040000000008ab6363636a6363ace23bf2010000000007655263635253534348c1da", "006353526563516a00", 0, -1491036196, "92364ba3c7a85d4e88885b8cb9b520dd81fc29e9d2b750d0790690e9c1246673"], + ["b04154610363fdade55ceb6942d5e5a723323863b48a0cb04fdcf56210717955763f56b08d0300000009ac526a525151635151ffffffff93a176e76151a9eabdd7af00ef2af72f9e7af5ecb0aa4d45d00618f394cdd03c030000000074d818b332ebe05dc24c44d776cf9d275c61f471cc01efce12fd5a16464157f1842c65cb00000000066a0000ac6352d3c4134f01d8a1c0030000000005520000005200000000", "5200656a656351", 2, -9757957, "6e3e5ba77f760b6b5b5557b13043f1262418f3dd2ce7f0298b012811fc8ad5bc"], + ["94533db7015e70e8df715066efa69dbb9c3a42ff733367c18c22ff070392f988f3b93920820000000006535363636300ce4dac3e03169af80300000000080065ac6a53ac65ac39c050020000000006abacab6aacac708a02050000000005ac5251520000000000", "6553", 0, -360458507, "5418cf059b5f15774836edd93571e0eed3855ba67b2b08c99dccab69dc87d3e9"], + ["c8597ada04f59836f06c224a2640b79f3a8a7b41ef3efa2602592ddda38e7597da6c639fee0300000009005251635351acabacffffffff4c518f347ee694884b9d4072c9e916b1a1f0a7fc74a1c90c63fdf8e5a185b6ae02000000007113af55afb41af7518ea6146786c7c726641c68c8829a52925e8d4afd07d8945f68e7230300000008ab00ab65ab650063ffffffffc28e46d7598312c420e11dfaae12add68b4d85adb182ae5b28f8340185394b63000000000165ffffffff04dbabb7010000000000ee2f6000000000000852ab6500ab6a51acb62a27000000000009ac53515300ac006a6345fb7505000000000752516a0051636a00000000", "", 3, 15199787, "0d66003aff5bf78cf492ecbc8fd40c92891acd58d0a271be9062e035897f317e"], + ["c33028b301d5093e1e8397270d75a0b009b2a6509a01861061ab022ca122a6ba935b8513320200000000ffffffff013bcf5a0500000000015200000000", "", 0, -513413204, "6b1459536f51482f5dbf42d7e561896557461e1e3b6bf67871e2b51faae2832c"], + ["43b2727901a7dd06dd2abf690a1ccedc0b0739cb551200796669d9a25f24f71d8d101379f50300000000ffffffff0418e031040000000000863d770000000000085352ac526563ac5174929e040000000004ac65ac00ec31ac0100000000066a51ababab5300000000", "65", 0, -492874289, "154ff7a9f0875edcfb9f8657a0b98dd9600fabee3c43eb88af37cf99286d516c"], + ["fe6ddf3a02657e42a7496ef170b4a8caf245b925b91c7840fd28e4a22c03cb459cb498b8d603000000065263656a650071ce6bf8d905106f9f1faf6488164f3decac65bf3c5afe1dcee20e6bc3cb6d052561985a030000000163295b117601343dbb0000000000026563dba521df", "", 1, -1696179931, "d9684685c99ce48f398fb467a91a1a59629a850c429046fb3071f1fa9a5fe816"], + ["c61523ef0129bb3952533cbf22ed797fa2088f307837dd0be1849f20decf709cf98c6f032f03000000026563c0f1d378044338310400000000066363516a5165a14fcb0400000000095163536a6a00ab53657271d60200000000001d953f0500000000010000000000", "53516353005153", 0, 1141615707, "7e975a72db5adaa3c48d525d9c28ac11cf116d0f8b16ce08f735ad75a80aec66"], + ["ba3dac6c0182562b0a26d475fe1e36315f0913b6869bdad0ecf21f1339a5fcbccd32056c840200000000ffffffff04300351050000000000220ed405000000000851abac636565ac53dbbd19020000000007636363ac6a52acbb005a0500000000016abd0c78a8", "63006a635151005352", 0, 1359658828, "47bc8ab070273e1f4a0789c37b45569a6e16f3f3092d1ce94dddc3c34a28f9f4"], + ["ac27e7f5025fc877d1d99f7fc18dd4cadbafa50e34e1676748cc89c202f93abf36ed46362101000000036300abffffffff958cd5381962b765e14d87fc9524d751e4752dd66471f973ed38b9d562e525620100000003006500ffffffff02b67120050000000004ac51516adc330c0300000000015200000000", "656352", 1, 15049991, "f3374253d64ac264055bdbcc32e27426416bd595b7c7915936c70f839e504010"], + ["7e50207303146d1f7ad62843ae8017737a698498d4b9118c7a89bb02e8370307fa4fada41d000000000753006300005152b7afefc85674b1104ba33ef2bf37c6ed26316badbc0b4aa6cb8b00722da4f82ff3555a6c020000000900ac656363ac51ac52ffffffff93fab89973bd322c5d7ad7e2b929315453e5f7ada3072a36d8e33ca8bebee6e0020000000300acab930da52b04384b04000000000004650052ac435e380200000000076a6a515263ab6aa9494705000000000600ab6a525252af8ba90100000000096565acab526353536a279b17ad", "acac005263536aac63", 1, -34754133, "4e6357da0057fb7ff79da2cc0f20c5df27ff8b2f8af4c1709e6530459f7972b0"], + ["5a59e0b9040654a3596d6dab8146462363cd6549898c26e2476b1f6ae42915f73fd9aedfda00000000036363abffffffff9ac9e9ca90be0187be2214251ff08ba118e6bf5e2fd1ba55229d24e50a510d53010000000165ffffffff41d42d799ac4104644969937522873c0834cc2fcdab7cdbecd84d213c0e96fd60000000000ffffffffd838db2c1a4f30e2eaa7876ef778470f8729fcf258ad228b388df2488709f8410300000000fdf2ace002ceb6d903000000000265654c1310040000000003ac00657e91c0ec", "536a63ac", 0, 82144555, "98ccde2dc14d14f5d8b1eeea5364bd18fc84560fec2fcea8de4d88b49c00695e"], + ["156ebc8202065d0b114984ee98c097600c75c859bfee13af75dc93f57c313a877efb09f230010000000463536a51ffffffff81114e8a697be3ead948b43b5005770dd87ffb1d5ccd4089fa6c8b33d3029e9c03000000066a5251656351ffffffff01a87f140000000000050000ac51ac00000000", "00", 0, -362221092, "a903c84d8c5e71134d1ab6dc1e21ac307c4c1a32c90c90f556f257b8a0ec1bf5"], + ["6d97a9a5029220e04f4ccc342d8394c751282c328bf1c132167fc05551d4ca4da4795f6d4e02000000076a0052ab525165ffffffff9516a205e555fa2a16b73e6db6c223a9e759a7e09c9a149a8f376c0a7233fa1b0100000007acab51ab63ac6affffffff04868aed04000000000652ac65ac536a396edf01000000000044386c0000000000076aab5363655200894d48010000000001ab8ebefc23", "6351526aac51", 1, 1943666485, "f0bd4ca8e97203b9b4e86bc24bdc8a1a726db5e99b91000a14519dc83fc55c29"], + ["05921d7c048cf26f76c1219d0237c226454c2a713c18bf152acc83c8b0647a94b13477c07f0300000003ac526afffffffff2f494453afa0cabffd1ba0a626c56f90681087a5c1bd81d6adeb89184b27b7402000000036a6352ffffffff0ad10e2d3ce355481d1b215030820da411d3f571c3f15e8daf22fe15342fed04000000000095f29f7b93ff814a9836f54dc6852ec414e9c4e16a506636715f569151559100ccfec1d100000000055263656a53ffffffff04f4ffef010000000008ac6a6aabacabab6a0e6689040000000006ab536a5352abe364d005000000000965536363655251ab53807e00010000000004526aab63f18003e3", "6363ac51", 3, -375891099, "001b0b176f0451dfe2d9787b42097ceb62c70d324e925ead4c58b09eebdf7f67"], + ["b9b44d9f04b9f15e787d7704e6797d51bc46382190c36d8845ec68dfd63ee64cf7a467b21e00000000096aac00530052ab636aba1bcb110a80c5cbe073f12c739e3b20836aa217a4507648d133a8eedd3f02cb55c132b203000000076a000063526352b1c288e3a9ff1f2da603f230b32ef7c0d402bdcf652545e2322ac01d725d75f5024048ad0100000000ffffffffffd882d963be559569c94febc0ef241801d09dc69527c9490210f098ed8203c700000000056a006300ab9109298d01719d9a0300000000066a52ab006365d7894c5b", "ac6351650063636a", 3, -622355349, "ac87b1b93a6baab6b2c6624f10e8ebf6849b0378ef9660a3329073e8f5553c8d"], + ["ff60473b02574f46d3e49814c484081d1adb9b15367ba8487291fc6714fd6e3383d5b335f001000000026a6ae0b82da3dc77e5030db23d77b58c3c20fa0b70aa7d341a0f95f3f72912165d751afd57230300000008ac536563516a6363ffffffff04f86c0200000000000553acab636ab13111000000000003510065f0d3f305000000000951ab516a65516aabab730a3a010000000002515200000000", "ac6a", 1, 1895032314, "0767e09bba8cd66d55915677a1c781acd5054f530d5cf6de2d34320d6c467d80"], + ["f218026204f4f4fc3d3bd0eada07c57b88570d544a0436ae9f8b753792c0c239810bb30fbc0200000002536affffffff8a468928d6ec4cc10aa0f73047697970e99fa64ae8a3b4dca7551deb0b639149010000000851ab520052650051ffffffffa98dc5df357289c9f6873d0f5afcb5b030d629e8f23aa082cf06ec9a95f3b0cf0000000000ffffffffea2c2850c5107705fd380d6f29b03f533482fd036db88739122aac9eff04e0aa010000000365536a03bd37db034ac4c4020000000007515152655200ac33b27705000000000151efb71e0000000000007b65425b", "515151", 3, -1772252043, "de35c84a58f2458c33f564b9e58bc57c3e028d629f961ad1b3c10ee020166e5a"], + ["48e7d42103b260b27577b70530d1ac2fed2551e9dd607cbcf66dca34bb8c03862cf8f5fd5401000000075151526aacab00ffffffff1e3d3b841552f7c6a83ee379d9d66636836673ce0b0eda95af8f2d2523c91813030000000665acac006365ffffffff388b3c386cd8c9ef67c83f3eaddc79f1ff910342602c9152ffe8003bce51b28b0100000008636363006a636a52ffffffff04b8f67703000000000852005353ac6552520cef720200000000085151ab6352ab00ab5096d6030000000005516a005100662582020000000001ac6c137280", "6a65", 1, 1513618429, "e2fa3e1976aed82c0987ab30d4542da2cb1cffc2f73be13480132da8c8558d5c"], + ["91ebc4cf01bc1e068d958d72ee6e954b196f1d85b3faf75a521b88a78021c543a06e056279000000000265ab7c12df0503832121030000000000cc41a6010000000005ab5263516540a951050000000006ab63ab65acac00000000", "526a0065636a6a6aac", 0, -614046478, "7de4ba875b2e584a7b658818c112e51ee5e86226f5a80e5f6b15528c86400573"], + ["3cd4474201be7a6c25403bf00ca62e2aa8f8f4f700154e1bb4d18c66f7bb7f9b975649f0dc0100000006535151535153ffffffff01febbeb000000000006005151006aac00000000", "", 0, -1674687131, "6b77ca70cc452cc89acb83b69857cda98efbfc221688fe816ef4cb4faf152f86"], + ["92fc95f00307a6b3e2572e228011b9c9ed41e58ddbaefe3b139343dbfb3b34182e9fcdc3f50200000002acab847bf1935fde8bcfe41c7dd99683289292770e7f163ad09deff0e0665ed473cd2b56b0f40300000006516551ab6351294dab312dd87b9327ce2e95eb44b712cfae0e50fda15b07816c8282e8365b643390eaab01000000026aacffffffff016e0b6b040000000001ac00000000", "650065acac005300", 2, -1885164012, "bd7d26bb3a98fc8c90c972500618bf894cb1b4fe37bf5481ff60eef439d3b970"], + ["4db591ab018adcef5f4f3f2060e41f7829ce3a07ea41d681e8cb70a0e37685561e4767ac3b0000000005000052acabd280e63601ae6ef20000000000036a636326c908f7", "ac6a51526300630052", 0, 862877446, "355ccaf30697c9c5b966e619a554d3323d7494c3ea280a9b0dfb73f953f5c1cb"], + ["c80abebd042cfec3f5c1958ee6970d2b4586e0abec8305e1d99eb9ee69ecc6c2cbd76374380000000007ac53006300ac510acee933b44817db79320df8094af039fd82111c7726da3b33269d3820123694d849ee5001000000056a65ab526562699bea8530dc916f5d61f0babea709dac578774e8a4dcd9c640ec3aceb6cb2443f24f302000000020063ea780e9e57d1e4245c1e5df19b4582f1bf704049c5654f426d783069bcc039f2d8fa659f030000000851ab53635200006a8d00de0b03654e8500000000000463ab635178ebbb0400000000055100636aab239f1d030000000006ab006300536500000000", "6565ac515100", 3, 1460851377, "b35bb1b72d02fab866ed6bbbea9726ab32d968d33a776686df3ac16aa445871e"], + ["0337b2d5043eb6949a76d6632b8bb393efc7fe26130d7409ef248576708e2d7f9d0ced9d3102000000075352636a5163007034384dfa200f52160690fea6ce6c82a475c0ef1caf5c9e5a39f8f9ddc1c8297a5aa0eb02000000026a51ffffffff38e536298799631550f793357795d432fb2d4231f4effa183c4e2f61a816bcf0030000000463ac5300706f1cd3454344e521fde05b59b96e875c8295294da5d81d6cc7efcfe8128f150aa54d6503000000008f4a98c704c1561600000000000072cfa6000000000000e43def01000000000100cf31cc0500000000066365526a6500cbaa8e2e", "", 3, 2029506437, "7615b4a7b3be865633a31e346bc3db0bcc410502c8358a65b8127089d81b01f8"], + ["cbc79b10020b15d605680a24ee11d8098ad94ae5203cb6b0589e432832e20c27b72a926af20300000006ab65516a53acbb854f3146e55c508ece25fa3d99dbfde641a58ed88c051a8a51f3dacdffb1afb827814b02000000026352c43e6ef30302410a020000000000ff4bd90100000000065100ab63000008aa8e0400000000095265526565ac5365abc52c8a77", "53526aac0051", 0, 202662340, "984efe0d8d12e43827b9e4b27e97b3777ece930fd1f589d616c6f9b71dab710e"], + ["4e8594d803b1d0a26911a2bcdd46d7cbc987b7095a763885b1a97ca9cbb747d32c5ab9aa91030000000353ac53a0cc4b215e07f1d648b6eeb5cdbe9fa32b07400aa773b9696f582cebfd9930ade067b2b200000000060065abab6500fc99833216b8e27a02defd9be47fafae4e4a97f52a9d2a210d08148d2a4e5d02730bcd460100000004516351ac37ce3ae1033baa55040000000006006a636a63acc63c990400000000025265eb1919030000000005656a6a516a00000000", "", 1, -75217178, "04c5ee48514cd033b82a28e336c4d051074f477ef2675ce0ce4bafe565ee9049"], + ["44e1a2b4010762af23d2027864c784e34ef322b6e24c70308a28c8f2157d90d17b99cd94a401000000085163656565006300ffffffff0198233d020000000002000000000000", "52525153656365", 0, 1119696980, "d9096de94d70c6337da6202e6e588166f31bff5d51bb5adc9468594559d65695"], + ["44ca65b901259245abd50a745037b17eb51d9ce1f41aa7056b4888285f48c6f26cb97b7a25020000000552636363abffffffff047820350400000000040053acab14f3e603000000000652635100ab630ce66c03000000000001bdc704000000000765650065ac51ac3e886381", "51", 0, -263340864, "ed5622ac642d11f90e68c0feea6a2fe36d880ecae6b8c0d89c4ea4b3d162bd90"], + ["cfa147d2017fe84122122b4dda2f0d6318e59e60a7207a2d00737b5d89694d480a2c26324b0000000006006351526552ffffffff0456b5b804000000000800516aab525363ab166633000000000004655363ab254c0e02000000000952ab6a6a00ab525151097c1b020000000009656a52ac6300530065ad0d6e50", "6a535165ac6a536500", 0, -574683184, "f926d4036eac7f019a2b0b65356c4ee2fe50e089dd7a70f1843a9f7bc6997b35"], + ["91c5d5f6022fea6f230cc4ae446ce040d8313071c5ac1749c82982cc1988c94cb1738aa48503000000016a19e204f30cb45dd29e68ff4ae160da037e5fc93538e21a11b92d9dd51cf0b5efacba4dd70000000005656a6aac51ffffffff03db126905000000000953006a53ab6563636a36a273030000000006656a52656552b03ede00000000000352516500000000", "530052526a00", 1, 1437328441, "255c125b60ee85f4718b2972174c83588ee214958c3627f51f13b5fb56c8c317"], + ["03f20dc202c886907b607e278731ebc5d7373c348c8c66cac167560f19b341b782dfb634cb03000000076a51ac6aab63abea3e8de7adb9f599c9caba95aa3fa852e947fc88ed97ee50e0a0ec0d14d164f44c0115c10100000004ab5153516fdd679e0414edbd000000000005ac636a53512021f2040000000007006a0051536a52c73db2050000000005525265ac5369046e000000000003ab006a1ef7bd1e", "52656a", 0, 1360223035, "5a0a05e32ce4cd0558aabd5d79cd5fcbffa95c07137506e875a9afcba4bef5a2"], + ["d9611140036881b61e01627078512bc3378386e1d4761f959d480fdb9d9710bebddba2079d020000000763536aab5153ab819271b41e228f5b04daa1d4e72c8e1955230accd790640b81783cfc165116a9f535a74c000000000163ffffffffa2e7bb9a28e810624c251ff5ba6b0f07a356ac082048cf9f39ec036bba3d431a02000000076a000000ac65acffffffff01678a820000000000085363515153ac635100000000", "535353", 2, -82213851, "52b9e0778206af68998cbc4ebdaad5a9469e04d0a0a6cef251abfdbb74e2f031"], + ["98b3a0bf034233afdcf0df9d46ac65be84ef839e58ee9fa59f32daaa7d684b6bdac30081c60200000007636351acabababffffffffc71cf82ded4d1593e5825618dc1d5752ae30560ecfaa07f192731d68ea768d0f0100000006650052636563f3a2888deb5ddd161430177ce298242c1a86844619bc60ca2590d98243b5385bc52a5b8f00000000095365acacab520052ac50d4722801c3b8a60300000000035165517e563b65", "51", 1, -168940690, "b6b684e2d2ecec8a8dce4ed3fc1147f8b2e45732444222aa8f52d860c2a27a9d"], + ["97be4f7702dc20b087a1fdd533c7de762a3f2867a8f439bddf0dcec9a374dfd0276f9c55cc0300000000cdfb1dbe6582499569127bda6ca4aaff02c132dc73e15dcd91d73da77e92a32a13d1a0ba0200000002ab51ffffffff048cfbe202000000000900516351515363ac535128ce0100000000076aac5365ab6aabc84e8302000000000863536a53ab6a6552f051230500000000066aac535153510848d813", "ac51", 0, 229541474, "e5da9a416ea883be1f8b8b2d178463633f19de3fa82ae25d44ffb531e35bdbc8"], + ["085b6e04040b5bff81e29b646f0ed4a45e05890a8d32780c49d09643e69cdccb5bd81357670100000001abffffffffa5c981fe758307648e783217e3b4349e31a557602225e237f62b636ec26df1a80300000004650052ab4792e1da2930cc90822a8d2a0a91ea343317bce5356b6aa8aae6c3956076aa33a5351a9c0300000004abac5265e27ddbcd472a2f13325cc6be40049d53f3e266ac082172f17f6df817db1936d9ff48c02b000000000152ffffffff021aa7670500000000085353635163ab51ac14d584000000000001aca4d136cc", "6a525300536352536a", 0, -1398925877, "41ecca1e8152ec55074f4c39f8f2a7204dda48e9ec1e7f99d5e7e4044d159d43"], + ["eec32fff03c6a18b12cd7b60b7bdc2dd74a08977e53fdd756000af221228fe736bd9c42d870100000007005353ac515265ffffffff037929791a188e9980e8b9cc154ad1b0d05fb322932501698195ab5b219488fc02000000070063510065ab6a0bfc176aa7e84f771ea3d45a6b9c24887ceea715a0ff10ede63db8f089e97d927075b4f1000000000551abab63abffffffff02eb933c000000000000262c420000000000036563632549c2b6", "6352", 2, 1480445874, "ff8a4016dfdd918f53a45d3a1f62b12c407cd147d68ca5c92b7520e12c353ff5"], + ["3ab70f4604e8fc7f9de395ec3e4c3de0d560212e84a63f8d75333b604237aa52a10da17196000000000763526a6553ac63a25de6fd66563d71471716fe59087be0dde98e969e2b359282cf11f82f14b00f1c0ac70f02000000050052516aacdffed6bb6889a13e46956f4b8af20752f10185838fd4654e3191bf49579c961f5597c36c0100000005ac636363abc3a1785bae5b8a1b4be5d0cbfadc240b4f7acaa7dfed6a66e852835df5eb9ac3c553766801000000036a65630733b7530218569602000000000952006a6a6a51acab52777f06030000000007ac0063530052abc08267c9", "000000536aac0000", 1, 1919096509, "df1c87cf3ba70e754d19618a39fdbd2970def0c1bfc4576260cba5f025b87532"], + ["bdb6b4d704af0b7234ced671c04ba57421aba7ead0a117d925d7ebd6ca078ec6e7b93eea6600000000026565ffffffff3270f5ad8f46495d69b9d71d4ab0238cbf86cc4908927fbb70a71fa3043108e6010000000700516a65655152ffffffff6085a0fdc03ae8567d0562c584e8bfe13a1bd1094c518690ebcb2b7c6ce5f04502000000095251530052536a53aba576a37f2c516aad9911f687fe83d0ae7983686b6269b4dd54701cb5ce9ec91f0e6828390300000000ffffffff04cc76cc020000000002656a01ffb702000000000253ab534610040000000009acab006565516a00521f55f5040000000000389dfee9", "6a525165", 0, 1336204763, "71c294523c48fd7747eebefbf3ca06e25db7b36bff6d95b41c522fecb264a919"], + ["54258edd017d22b274fbf0317555aaf11318affef5a5f0ae45a43d9ca4aa652c6e85f8a040010000000953ac65ab5251656500ffffffff03321d450000000000085265526a51526a529ede8b030000000003635151ce6065020000000001534c56ec1b", "acac", 0, 2094130012, "110d90fea9470dfe6c5048f45c3af5e8cc0cb77dd58fd13d338268e1c24b1ccc"], + ["ce0d322e04f0ffc7774218b251530a7b64ebefca55c90db3d0624c0ff4b3f03f918e8cf6f60300000003656500ffffffff9cce943872da8d8af29022d0b6321af5fefc004a281d07b598b95f6dcc07b1830200000007abab515351acab8d926410e69d76b7e584aad1470a97b14b9c879c8b43f9a9238e52a2c2fefc2001c56af8010000000400ab5253cd2cd1fe192ce3a93b5478af82fa250c27064df82ba416dfb0debf4f0eb307a746b6928901000000096500abacac6a0063514214524502947efc0200000000035251652c40340100000000096a6aab52000052656a5231c54c", "51", 2, -2090320538, "0322ca570446869ec7ec6ad66d9838cff95405002d474c0d3c17708c7ee039c6"], + ["233cd90b043916fc41eb870c64543f0111fb31f3c486dc72457689dea58f75c16ae59e9eb2000000000500536a6a6affffffff9ae30de76be7cd57fb81220fce78d74a13b2dbcad4d023f3cadb3c9a0e45a3ce000000000965ac6353ac5165515130834512dfb293f87cb1879d8d1b20ebad9d7d3d5c3e399a291ce86a3b4d30e4e32368a9020000000453005165ffffffff26d84ae93eb58c81158c9b3c3cbc24a84614d731094f38d0eea8686dec02824d0300000005636a65abacf02c784001a0bd5d03000000000900655351ab65ac516a416ef503", "", 1, -295106477, "b79f31c289e95d9dadec48ebf88e27c1d920661e50d090e422957f90ff94cb6e"], + ["9200e26b03ff36bc4bf908143de5f97d4d02358db642bd5a8541e6ff709c420d1482d471b70000000008abab65536a636553ffffffff61ba6d15f5453b5079fb494af4c48de713a0c3e7f6454d7450074a2a80cb6d880300000007ac6a00ab5165515dfb7574fbce822892c2acb5d978188b1d65f969e4fe874b08db4c791d176113272a5cc10100000000ffffffff0420958d000000000009ac63516a0063516353dd885505000000000465ac00007b79e901000000000066d8bf010000000005525252006a00000000", "ac5152", 0, 2089531339, "89ec7fab7cfe7d8d7d96956613c49dc48bf295269cfb4ea44f7333d88c170e62"], + ["45f335ba01ce2073a8b0273884eb5b48f56df474fc3dff310d9706a8ac7202cf5ac188272103000000025363ffffffff049d859502000000000365ab6a8e98b1030000000002ac51f3a80603000000000752535151ac00000306e30300000000020051b58b2b3a", "", 0, 1899564574, "78e01310a228f645c23a2ad0acbb8d91cedff4ecdf7ca997662c6031eb702b11"], + ["94083c840288d40a6983faca876d452f7c52a07de9268ad892e70a81e150d602a773c175ad03000000007ec3637d7e1103e2e7e0c61896cbbf8d7e205b2ecc93dd0d6d7527d39cdbf6d335789f660300000000ffffffff019e1f7b03000000000800ac0051acac0053539cb363", "", 1, -183614058, "a17b66d6bb427f42653d08207a22b02353dd19ccf2c7de6a9a3a2bdb7c49c9e7"], + ["30e0d4d20493d0cd0e640b757c9c47a823120e012b3b64c9c1890f9a087ae4f2001ca22a61010000000152f8f05468303b8fcfaad1fb60534a08fe90daa79bff51675472528ebe1438b6f60e7f60c10100000009526aab6551ac510053ffffffffaaab73957ea2133e32329795221ed44548a0d3a54d1cf9c96827e7cffd1706df0200000009ab00526a005265526affffffffd19a6fe54352015bf170119742821696f64083b5f14fb5c7d1b5a721a3d7786801000000085265abababac53abffffffff020f39bd030000000004ab6aac52049f6c050000000004ab52516aba5b4c60", "6a6365516a6a655253", 0, -624256405, "8e221a6c4bf81ca0d8a0464562674dcd14a76a32a4b7baf99450dd9195d411e6"], + ["5c0ac112032d6885b7a9071d3c5f493aa16c610a4a57228b2491258c38de8302014276e8be030000000300ab6a17468315215262ad5c7393bb5e0c5a6429fd1911f78f6f72dafbbbb78f3149a5073e24740300000003ac5100ffffffff33c7a14a062bdea1be3c9c8e973f54ade53fe4a69dcb5ab019df5f3345050be00100000008ac63655163526aab428defc0033ec36203000000000765516365536a00ae55b2000000000002ab53f4c0080400000000095265516a536563536a00000000", "6a005151006a", 2, 272749594, "91082410630337a5d89ff19145097090f25d4a20bdd657b4b953927b2f62c73b"], + ["e3683329026720010b08d4bec0faa244f159ae10aa582252dd0f3f80046a4e145207d54d31000000000852acac52656aacac3aaf2a5017438ad6adfa3f9d05f53ebed9ceb1b10d809d507bcf75e0604254a8259fc29c020000000653526552ab51f926e52c04b44918030000000000f7679c0100000000090000525152005365539e3f48050000000009516500ab635363ab008396c905000000000253650591024f", "6a6365", 0, 908746924, "458aec3b5089a585b6bad9f99fd37a2b443dc5a2eefac2b7e8c5b06705efc9db"], + ["00b20fd104dd59705b84d67441019fa26c4c3dec5fd3b50eca1aa549e750ef9ddb774dcabe000000000651ac656aac65ffffffff52d4246f2db568fc9eea143e4d260c698a319f0d0670f84c9c83341204fde48b0200000000ffffffffb8aeabb85d3bcbc67b132f1fd815b451ea12dcf7fc169c1bc2e2cf433eb6777a03000000086a51ac6aab6563acd510d209f413da2cf036a31b0def1e4dcd8115abf2e511afbcccb5ddf41d9702f28c52900100000006ac52ab6a0065ffffffff039c8276000000000008ab53655200656a52401561010000000003acab0082b7160100000000035100ab00000000", "535265", 1, -947367579, "3212c6d6dd8d9d3b2ac959dec11f4638ccde9be6ed5d36955769294e23343da0"], + ["624d28cb02c8747915e9af2b13c79b417eb34d2fa2a73547897770ace08c6dd9de528848d3030000000651ab63abab533c69d3f9b75b6ef8ed2df50c2210fd0bf4e889c42477d58682f711cbaece1a626194bb85030000000765acab53ac5353ffffffff018cc280040000000009abacabac52636352ac6859409e", "ac51ac", 1, 1005144875, "919144aada50db8675b7f9a6849c9d263b86450570293a03c245bd1e3095e292"], + ["8f28471d02f7d41b2e70e9b4c804f2d90d23fb24d53426fa746bcdcfffea864925bdeabe3e0200000001acffffffff76d1d35d04db0e64d65810c808fe40168f8d1f2143902a1cc551034fd193be0e0000000001acffffffff048a5565000000000005005151516afafb610400000000045263ac53648bb30500000000086363516a6a5165513245de01000000000000000000", "6a0053510053", 1, -1525137460, "305fc8ff5dc04ebd9b6448b03c9a3d945a11567206c8d5214666b30ec6d0d6cc"], + ["10ec50d7046b8b40e4222a3c6449490ebe41513aad2eca7848284a08f3069f3352c2a9954f0000000009526aac656352acac53ffffffff0d979f236155aa972472d43ee6f8ce22a2d052c740f10b59211454ff22cb7fd00200000007acacacab63ab53ffffffffbbf97ebde8969b35725b2e240092a986a2cbfd58de48c4475fe077bdd493a20c010000000663ab5365ababffffffff4600722d33b8dba300d3ad037bcfc6038b1db8abfe8008a15a1de2da2264007302000000035351ac6dbdafaf020d0ccf04000000000663ab6a51ab6ae06e5e0200000000036aabab00000000", "", 0, -1658960232, "2420dd722e229eccafae8508e7b8d75c6920bfdb3b5bac7cb8e23419480637c2"], + ["43559290038f32fda86580dd8a4bc4422db88dd22a626b8bd4f10f1c9dd325c8dc49bf479f01000000026351ffffffff401339530e1ed3ffe996578a17c3ec9d6fccb0723dd63e7b3f39e2c44b976b7b0300000006ab6a65656a51ffffffff6fb9ba041c96b886482009f56c09c22e7b0d33091f2ac5418d05708951816ce7000000000551ac525100ffffffff020921e40500000000035365533986f40500000000016a00000000", "52ac51", 0, 1769771809, "02040283ef2291d8e1f79bb71bdabe7c1546c40d7ed615c375643000a8b9600d"], + ["35b6fc06047ebad04783a5167ab5fc9878a00c4eb5e7d70ef297c33d5abd5137a2dea9912402000000036aacacffffffff21dc291763419a584bdb3ed4f6f8c60b218aaa5b99784e4ba8acfec04993e50c03000000046a00ac6affffffff69e04d77e4b662a82db71a68dd72ef0af48ca5bebdcb40f5edf0caf591bb41020200000000b5db78a16d93f5f24d7d932f93a29bb4b784febd0cbb1943f90216dc80bba15a0567684b000000000853ab52ab5100006a1be2208a02f6bdc103000000000265ab8550ea04000000000365636a00000000", "", 0, -1114114836, "1c8655969b241e717b841526f87e6bd68b2329905ba3fc9e9f72526c0b3ea20c"], + ["f35befbc03faf8c25cc4bc0b92f6239f477e663b44b83065c9cb7cf231243032cf367ce3130000000005ab65526a517c4c334149a9c9edc39e29276a4b3ffbbab337de7908ea6f88af331228bd90086a6900ba020000000151279d19950d2fe81979b72ce3a33c6d82ebb92f9a2e164b6471ac857f3bbd3c0ea213b542010000000953ab51635363520065052657c20300a9ba04000000000452636a6a0516ea020000000008535253656365ababcfdd3f01000000000865ac516aac00530000000000", "", 2, -99793521, "c834a5485e68dc13edb6c79948784712122440d7fa5bbaa5cd2fc3d4dac8185d"], + ["d3da18520216601acf885414538ce2fb4d910997eeb91582cac42eb6982c9381589587794f0300000000fffffffff1b1c9880356852e10cf41c02e928748dd8fae2e988be4e1c4cb32d0bfaea6f7000000000465ab6aabffffffff02fb0d69050000000002ababeda8580500000000085163526565ac52522b913c95", "ac", 1, -1247973017, "99b32b5679d91e0f9cdd6737afeb07459806e5acd7630c6a3b9ab5d550d0c003"], + ["8218eb740229c695c252e3630fc6257c42624f974bc856b7af8208df643a6c520ef681bfd00000000002510066f30f270a09b2b420e274c14d07430008e7886ec621ba45665057120afce58befca96010300000004525153ab84c380a9015d96100000000000076a5300acac526500000000", "ac005263", 0, -1855679695, "5071f8acf96aea41c7518bd1b5b6bbe16258b529df0c03f9e374b83c66b742c6"], + ["1123e7010240310013c74e5def60d8e14dd67aedff5a57d07a24abc84d933483431b8cf8ea0300000003530051fc6775ff1a23c627a2e605dd2560e84e27f4208300071e90f4589e762ad9c9fe8d0da95e020000000465655200ffffffff04251598030000000004ab65ab639d28d90400000000096563636aacac525153474df801000000000851525165ac51006a75e23b040000000000e5bd3a4a", "6363636565", 0, -467124448, "9cb0dd04e9fe287b112e94a1647590d27e8b164ca13c4fe70c610fd13f82c2fd"], + ["3b937e05032b8895d2f4945cb7e3679be2fbd15311e2414f4184706dbfc0558cf7de7b4d000000000001638b91a12668a3c3ce349788c961c26aa893c862f1e630f18d80e7843686b6e1e6fc396310000000000852635353ab65ac51eeb09dd1c9605391258ee6f74b9ae17b5e8c2ef010dc721c5433dcdc6e93a1593e3b6d1700000000085365ac6553526351ffffffff0308b18e04000000000253acb6dd00040000000008536aac5153ac516ab0a88201000000000500ac006500804e3ff2", "", 0, 416167343, "595a3c02254564634e8085283ec4ea7c23808da97ce9c5da7aecd7b553e7fd7f"], + ["a48f27ca047997470da74c8ee086ddad82f36d9c22e790bd6f8603ee6e27ad4d3174ea875403000000095153ac636aab6aacabffffffffefc936294e468d2c9a99e09909ba599978a8c0891ad47dc00ba424761627cef202000000056a51630053ffffffff304cae7ed2d3dbb4f2fbd679da442aed06221ffda9aee460a28ceec5a9399f4e0200000000f5bddf82c9c25fc29c5729274c1ff0b43934303e5f595ce86316fc66ad263b96ca46ab8d0100000003536500d7cf226b0146b00c04000000000200ac5c2014ce", "515100636563", 0, 1991799059, "9c051a7092fe17fa62b1720bc2c4cb2ffc1527d9fb0b006d2e142bb8fe07bf3c"], + ["180cd53101c5074cf0b7f089d139e837fe49932791f73fa2342bd823c6df6a2f72fe6dba1303000000076a6a63ac53acabffffffff03853bc1020000000007ac526a6a6a6a003c4a8903000000000453515163a0fbbd030000000005ab656a5253253d64cf", "ac65", 0, -1548453970, "4d8efb3b99b9064d2f6be33b194a903ffabb9d0e7baa97a48fcec038072aac06"], + ["c21ec8b60376c47e057f2c71caa90269888d0ffd5c46a471649144a920d0b409e56f190b700000000008acac6a526a536365ffffffff5d315d9da8bf643a9ba11299450b1f87272e6030fdb0c8adc04e6c1bfc87de9a0000000000ea43a9a142e5830c96b0ce827663af36b23b0277244658f8f606e95384574b91750b8e940000000007516a63ac0063acffffffff023c61be0400000000055165ab5263313cc8020000000006006a53526551ed8c3d56", "6a", 1, 1160627414, "a638cc17fd91f4b1e77877e8d82448c84b2a4e100df1373f779de7ad32695112"], + ["b8fd394001ed255f49ad491fecc990b7f38688e9c837ccbc7714ddbbf5404f42524e68c18f0000000007ab6353535363ab081e15ee02706f7d050000000008515200535351526364c7ec040000000005636a53acac9206cbe1", "655352ac", 0, -1251578838, "8e0697d8cd8a9ccea837fd798cc6c5ed29f6fbd1892ee9bcb6c944772778af19"], + ["e42a76740264677829e30ed610864160c7f97232c16528fe5610fc08814b21c34eefcea69d010000000653006a6a0052ffffffff647046cf44f217d040e6a8ff3f295312ab4dd5a0df231c66968ad1c6d8f4428000000000025352ffffffff0199a7f900000000000000000000", "655263006a005163", 1, 1122505713, "7cda43f1ff9191c646c56a4e29b1a8c6cb3f7b331da6883ef2f0480a515d0861"], + ["a2dfa4690214c1ab25331815a5128f143219de51a47abdc7ce2d367e683eeb93960a31af9f010000000363636affffffff8be0628abb1861b078fcc19c236bc4cc726fa49068b88ad170adb2a97862e7460200000004ac655363ffffffff0441f11103000000000153dbab0c000000000009ab53ac5365526aab63abbb95050000000004ab52516a29a029040000000003ac526a00000000", "6a52ac63", 1, -1302210567, "913060c7454e6c80f5ba3835454b54db2188e37dc4ce72a16b37d11a430b3d23"], + ["9dbc591f04521670af83fb3bb591c5d4da99206f5d38e020289f7db95414390dddbbeb56680100000004ac5100acffffffffb6a40b5e29d5e459f8e72d39f800089529f0889006cad3d734011991da8ef09d0100000009526a5100acab536a515fc427436df97cc51dc8497642ffc868857ee245314d28b356bd70adba671bd6071301fc0000000000ffffffff487efde2f620566a9b017b2e6e6d42525e4070f73a602f85c6dfd58304518db30000000005516353006a8d8090180244904a0200000000046a65656ab1e9c203000000000451ab63aba06a5449", "", 0, -1414953913, "bae189eb3d64aedbc28a6c28f6c0ccbd58472caaf0cf45a5aabae3e031dd1fea"], + ["1345fb2c04bb21a35ae33a3f9f295bece34650308a9d8984a989dfe4c977790b0c21ff9a7f0000000006ac52ac6a0053ffffffff7baee9e8717d81d375a43b691e91579be53875350dfe23ba0058ea950029fcb7020000000753ab53ab63ab52ffffffff684b6b3828dfb4c8a92043b49b8cb15dd3a7c98b978da1d314dce5b9570dadd202000000086353ab6a5200ac63d1a8647bf667ceb2eae7ec75569ca249fbfd5d1b582acfbd7e1fcf5886121fca699c011d0100000003ac006affffffff049b1eb00300000000001e46dc0100000000080065ab6a6a630065ca95b40300000000030051520c8499010000000006ab6aac526a6500000000", "53526aac636300", 2, 1809978100, "cfeaa36790bc398783d4ca45e6354e1ea52ee74e005df7f9ebd10a680e9607bf"], + ["7d75dc8f011e5f9f7313ba6aedef8dbe10d0a471aca88bbfc0c4a448ce424a2c5580cda1560300000003ab5152ffffffff01997f8e0200000000096552ac6a65656563530d93bbcc", "00656a6563", 0, 1414485913, "ec91eda1149f75bffb97612569a78855498c5d5386d473752a2c81454f297fa7"], + ["1459179504b69f01c066e8ade5e124c748ae5652566b34ed673eea38568c483a5a4c4836ca0100000008ac5352006563656affffffff5d4e037880ab1975ce95ea378d2874dcd49d5e01e1cdbfae3343a01f383fa35800000000095251ac52ac6aac6500ffffffff7de3ae7d97373b7f2aeb4c55137b5e947b2d5fb325e892530cb589bc4f92abd503000000086563ac53ab520052ffffffffb4db36a32d6e543ef49f4bafde46053cb85b2a6c4f0e19fa0860d9083901a1190300000003ab51531bbcfe5504a6dbda040000000008536a5365abac6500d660c80300000000096565abab6a53536a6a54e84e010000000003acac52df2ccf0500000000025351220c857e", "", 2, 1879181631, "3aad18a209fab8db44954eb55fd3cc7689b5ec9c77373a4d5f4dae8f7ae58d14"], + ["cabb1b06045a895e6dcfc0c1e971e94130c46feace286759f69a16d298c8b0f6fd0afef8f20300000004ac006352ffffffffa299f5edac903072bfb7d29b663c1dd1345c2a33546a508ba5cf17aab911234602000000056a65515365ffffffff89a20dc2ee0524b361231092a070ace03343b162e7162479c96b757739c8394a0300000002abab92ec524daf73fabee63f95c1b79fa8b84e92d0e8bac57295e1d0adc55dc7af5534ebea410200000001534d70e79b04674f6f00000000000600abacab53517d60cc0200000000035265ab96c51d040000000004ac6300ac62a787050000000008006a516563ab63639e2e7ff7", "6551ac6351ac", 3, 1942663262, "d0c4a780e4e0bc22e2f231e23f01c9d536b09f6e5be51c123d218e906ec518be"], + ["8b96d7a30132f6005b5bd33ea82aa325e2bcb441f46f63b5fca159ac7094499f380f6b7e2e00000000076aacabac6300acffffffff0158056700000000000465005100c319e6d0", "52006a", 0, -1100733473, "fb4bd26a91b5cf225dd3f170eb09bad0eac314bc1e74503cc2a3f376833f183e"], + ["112191b7013cfbe18a175eaf09af7a43cbac2c396f3695bbe050e1e5f4250603056d60910e02000000001c8a5bba03738a22010000000005525352656a77a149010000000002510003b52302000000000351ac52722be8e6", "65ac6565", 0, -1847972737, "8e795aeef18f510d117dfa2b9f4a2bd2e2847a343205276cedd2ba14548fd63f"], + ["ce6e1a9e04b4c746318424705ea69517e5e0343357d131ad55d071562d0b6ebfedafd6cb840100000003656553ffffffff67bd2fa78e2f52d9f8900c58b84c27ef9d7679f67a0a6f78645ce61b883fb8de000000000100d699a56b9861d99be2838e8504884af4d30b909b1911639dd0c5ad47c557a0773155d4d303000000046a5151abffffffff9fdb84b77c326921a8266854f7bbd5a71305b54385e747fe41af8a397e78b7fa010000000863acac6a51ab00ac0d2e9b9d049b8173010000000007ac53526a650063ba9b7e010000000008526a00525263acac0ab3fd030000000000ea8a0303000000000200aca61a97b9", "", 1, -1276952681, "b6ed4a3721be3c3c7305a5128c9d418efa58e419580cec0d83f133a93e3a22c5"], + ["2f7353dd02e395b0a4d16da0f7472db618857cd3de5b9e2789232952a9b154d249102245fd030000000151617fd88f103280b85b0a198198e438e7cab1a4c92ba58409709997cc7a65a619eb9eec3c0200000003636aabffffffff0397481c0200000000045300636a0dc97803000000000009d389030000000003ac6a53134007bb", "0000536552526a", 0, -1912746174, "30c4cd4bd6b291f7e9489cc4b4440a083f93a7664ea1f93e77a9597dab8ded9c"], + ["89e7928c04363cb520eff4465251fd8e41550cbd0d2cdf18c456a0be3d634382abcfd4a2130200000006ac516a6a656355042a796061ed72db52ae47d1607b1ceef6ca6aea3b7eea48e7e02429f382b378c4e51901000000085351ab6352ab5252ffffffff53631cbda79b40183000d6ede011c778f70147dc6fa1aed3395d4ce9f7a8e69701000000096a6553ab52516a52abad0de418d80afe059aab5da73237e0beb60af4ac490c3394c12d66665d1bac13bdf29aa8000000000153f2b59ab6027a33eb040000000007005351ac5100ac88b941030000000003ab0052e1e8a143", "63656a", 0, 1258533326, "b575a04b0bb56e38bbf26e1a396a76b99fb09db01527651673a073a75f0a7a34"], + ["ca356e2004bea08ec2dd2df203dc275765dc3f6073f55c46513a588a7abcc4cbde2ff011c7020000000553525100003aefec4860ef5d6c1c6be93e13bd2d2a40c6fb7361694136a7620b020ecbaca9413bcd2a030000000965ac00536352535100ace4289e00e97caaea741f2b89c1143060011a1f93090dc230bee3f05e34fbd8d8b6c399010000000365526affffffff48fc444238bda7a757cb6a98cb89fb44338829d3e24e46a60a36d4e24ba05d9002000000026a53ffffffff03d70b440200000000056a6a526aac853c97010000000002515335552202000000000351635300000000", "0052", 3, -528192467, "fc93cc056c70d5e033933d730965f36ad81ef64f1762e57f0bc5506c5b507e24"], + ["82d4fa65017958d53e562fac073df233ab154bd0cf6e5a18f57f4badea8200b217975e31030200000004636aab51ac0891a204227cc9050000000006635200655365bfef8802000000000865650051635252acfc2d09050000000006ab65ac51516380195e030000000007ac52525352510063d50572", "53", 0, -713567171, "e095003ca82af89738c1863f0f5488ec56a96fb81ea7df334f9344fcb1d0cf40"], + ["75f6949503e0e47dd70426ef32002d6cdb564a45abedc1575425a18a8828bf385fa8e808e600000000036aabab82f9fd14e9647d7a1b5284e6c55169c8bd228a7ea335987cef0195841e83da45ec28aa2e0300000002516350dc6fe239d150efdb1b51aa288fe85f9b9f741c72956c11d9dcd176889963d699abd63f0000000001ab429a63f502777d20010000000007abac52ac516a53d081d9020000000003acac630c3cc3a8", "535152516551510000", 1, 973814968, "c6ec1b7cb5c16a1bfd8a3790db227d2acc836300534564252b57bd66acf95092"], + ["e86a24bc03e4fae784cdf81b24d120348cb5e52d937cd9055402fdba7e43281e482e77a1c100000000046363006affffffffa5447e9bdcdab22bd20d88b19795d4c8fb263fbbf7ce8f4f9a85f865953a6325020000000663ac53535253ffffffff9f8b693bc84e0101fc73748e0513a8cecdc264270d8a4ee1a1b6717607ee1eaa00000000026a513417bf980158d82c020000000009005253005351acac5200000000", "6353516365536a6a", 2, -563792735, "508129278ef07b43112ac32faf00170ad38a500eed97615a860fd58baaad174b"], + ["536bc5e60232eb60954587667d6bcdd19a49048d67a027383cc0c2a29a48b960dc38c5a0370300000005ac636300abffffffff8f1cfc102f39b1c9348a2195d496e602c77d9f57e0769dabde7eaaedf9c69e250100000006acabab6a6351ffffffff0432f56f0400000000046a5365517fd54b0400000000035265539484e4050000000003536a5376dc25020000000008ac536aab6aab536ab978e686", "ac0051006a006a006a", 0, -273074082, "f151f1ec305f698d9fdce18ea292b145a58d931f1518cf2a4c83484d9a429638"], + ["fab796ee03f737f07669160d1f1c8bf0800041157e3ac7961fea33a293f976d79ce49c02ab0200000003ac5252eb097ea1a6d1a7ae9dace338505ba559e579a1ee98a2e9ad96f30696d6337adcda5a85f403000000096500abab656a6a656396d5d41a9b11f571d91e4242ddc0cf2420eca796ad4882ef1251e84e42b930398ec69dd80100000005526551ac6a8e5d0de804f763bb0400000000015288271a010000000001acf2bf2905000000000300ab51c9641500000000000952655363636365ac5100000000", "00ac536552", 0, -1854521113, "f3bbab70b759fe6cfae1bf349ce10716dbc64f6e9b32916904be4386eb461f1f"], + ["f2b539a401e4e8402869d5e1502dbc3156dbce93583f516a4947b333260d5af1a34810c6a00200000003525363ffffffff01d305e2000000000005acab535200a265fe77", "", 0, -1435650456, "41617b27321a830c712638dbb156dae23d4ef181c7a06728ccbf3153ec53d7dd"], + ["9f10b1d8033aee81ac04d84ceee0c03416a784d1017a2af8f8a34d2f56b767aea28ff88c8f02000000025352ffffffff748cb29843bea8e9c44ed5ff258df1faf55fbb9146870b8d76454786c4549de100000000016a5ba089417305424d05112c0ca445bc7107339083e7da15e430050d578f034ec0c589223b0200000007abac53ac6565abffffffff025a4ecd010000000006636563ab65ab40d2700000000000056a6553526333fa296c", "", 0, -395044364, "20fd0eee5b5716d6cbc0ddf852614b686e7a1534693570809f6719b6fcb0a626"], + ["ff2ecc09041b4cf5abb7b760e910b775268abee2792c7f21cc5301dd3fecc1b4233ee70a2c0200000009acac5300006a51526affffffffeb39c195a5426afff38379fc85369771e4933587218ef4968f3f05c51d6b7c92000000000165453a5f039b8dbef7c1ffdc70ac383b481f72f99f52b0b3a5903c825c45cfa5d2c0642cd50200000001654b5038e6c49daea8c0a9ac8611cfe904fc206dad03a41fb4e5b1d6d85b1ecad73ecd4c0102000000096a51000053ab656565bdb5548302cc719200000000000452655265214a3603000000000300ab6a00000000", "52516a006a63", 1, -2113289251, "37ed6fae36fcb3360c69cac8b359daa62230fc1419b2cf992a32d8f3e079dcff"], + ["70a8577804e553e462a859375957db68cfdf724d68caeacf08995e80d7fa93db7ebc04519d02000000045352ab53619f4f2a428109c5fcf9fee634a2ab92f4a09dc01a5015e8ecb3fc0d9279c4a77fb27e900000000006ab6a51006a6affffffff3ed1a0a0d03f25c5e8d279bb5d931b7eb7e99c8203306a6c310db113419a69ad010000000565516300abffffffff6bf668d4ff5005ef73a1b0c51f32e8235e67ab31fe019bf131e1382050b39a630000000004536a6563ffffffff02faf0bb00000000000163cf2b4b05000000000752ac635363acac15ab369f", "ac", 0, -1175809030, "1c9d6816c20865849078f9777544b5ddf37c8620fe7bd1618e4b72fb72dddca1"], + ["a3604e5304caa5a6ba3c257c20b45dcd468f2c732a8ca59016e77b6476ac741ce8b16ca8360200000004acac6553ffffffff695e7006495517e0b79bd4770f955040610e74d35f01e41c9932ab8ccfa3b55d0300000007ac5253515365acffffffff6153120efc5d73cd959d72566fc829a4eb00b3ef1a5bd3559677fb5aae116e38000000000400abab52c29e7abd06ff98372a3a06227386609adc7665a602e511cadcb06377cc6ac0b8f63d4fdb03000000055100acabacffffffff04209073050000000009ab5163ac525253ab6514462e05000000000952abacab636300656a20672c0400000000025153b276990000000000056565ab6a5300000000", "5351", 0, 1460890590, "249c4513a49076c6618aabf736dfd5ae2172be4311844a62cf313950b4ba94be"], + ["c6a72ed403313b7d027f6864e705ec6b5fa52eb99169f8ea7cd884f5cdb830a150cebade870100000009ac63ab516565ab6a51ffffffff398d5838735ff43c390ca418593dbe43f3445ba69394a6d665b5dc3b4769b5d700000000075265acab515365ffffffff7ee5616a1ee105fd18189806a477300e2a9cf836bf8035464e8192a0d785eea3030000000700ac6a51516a52ffffffff018075fd0000000000015100000000", "005251acac5252", 2, -656067295, "2cc1c7514fdc512fd45ca7ba4f7be8a9fe6d3318328bc1a61ae6e7675047e654"], + ["93c12cc30270fc4370c960665b8f774e07942a627c83e58e860e38bd6b0aa2cb7a2c1e060901000000036300abffffffff4d9b618035f9175f564837f733a2b108c0f462f28818093372eec070d9f0a5440300000001acffffffff039c2137020000000001525500990100000000055265ab636a07980e0300000000005ba0e9d1", "656a5100", 1, 18954182, "6beca0e0388f824ca33bf3589087a3c8ad0857f9fe7b7609ae3704bef0eb83e2"], + ["97bddc63015f1767619d56598ad0eb5c7e9f880b24a928fea1e040e95429c930c1dc653bdb0100000008ac53acac00005152aaa94eb90235ed10040000000000287bdd0400000000016a8077673a", "acac6a536352655252", 0, -813649781, "5990b139451847343c9bb89cdba0e6daee6850b60e5b7ea505b04efba15f5d92"], + ["cc3c9dd303637839fb727270261d8e9ddb8a21b7f6cbdcf07015ba1e5cf01dc3c3a327745d0300000000d2d7804fe20a9fca9659a0e49f258800304580499e8753046276062f69dbbde85d17cd2201000000096352536a520000acabffffffffbc75dfa9b5f81f3552e4143e08f485dfb97ae6187330e6cd6752de6c21bdfd21030000000600ab53650063ffffffff0313d0140400000000096565515253526aacac167f0a040000000008acab00535263536a9a52f8030000000006abab5151ab63f75b66f2", "6a635353636a65ac65", 1, 377286607, "dbc7935d718328d23d73f8a6dc4f53a267b8d4d9816d0091f33823bd1f0233e9"], + ["236f91b702b8ffea3b890700b6f91af713480769dda5a085ae219c8737ebae90ff25915a3203000000056300ac6300811a6a10230f12c9faa28dae5be2ebe93f37c06a79e76214feba49bb017fb25305ff84eb020000000100ffffffff041e351703000000000351ac004ff53e050000000003ab53636c1460010000000000cb55f701000000000651520051ab0000000000", "acac636a6aac5300", 0, 406448919, "793a3d3c37f6494fab79ff10c16702de002f63e34be25dd8561f424b0ea938c4"], + ["c47d5ad60485cb2f7a825587b95ea665a593769191382852f3514a486d7a7a11d220b62c54000000000663655253acab8c3cf32b0285b040e50dcf6987ddf7c385b3665048ad2f9317b9e0c5ba0405d8fde4129b00000000095251ab00ac65635300ffffffff549fe963ee410d6435bb2ed3042a7c294d0c7382a83edefba8582a2064af3265000000000152fffffffff7737a85e0e94c2d19cd1cde47328ece04b3e33cd60f24a8a345da7f2a96a6d0000000000865ab6a0051656aab28ff30d5049613ea020000000005ac51000063f06df1050000000008ac63516aabac5153afef5901000000000700656500655253688bc00000000000086aab5352526a53521ff1d5ff", "51ac52", 2, -1296011911, "0c1fd44476ff28bf603ad4f306e8b6c7f0135a441dc3194a6f227cb54598642a"], + ["0b43f122032f182366541e7ee18562eb5f39bc7a8e5e0d3c398f7e306e551cdef773941918030000000863006351ac51acabffffffffae586660c8ff43355b685dfa8676a370799865fbc4b641c5a962f0849a13d8250100000005abab63acabffffffff0b2b6b800d8e77807cf130de6286b237717957658443674df047a2ab18e413860100000008ab6aac655200ab63ffffffff04f1dbca03000000000800635253ab656a52a6eefd0300000000036365655d8ca90200000000005a0d530400000000015300000000", "65ac65acac", 0, 351448685, "86f26e23822afd1bdfc9fff92840fc1e60089f12f54439e3ab9e5167d0361dcf"], + ["af1c4ab301ec462f76ee69ba419b1b2557b7ded639f3442a3522d4f9170b2d6859765c3df402000000016affffffff01a5ca6c000000000008ab52536aab00005300000000", "6a6351", 0, 110304602, "e88ed2eea9143f2517b15c03db00767eb01a5ce12193b99b964a35700607e5f4"], + ["0bfd34210451c92cdfa02125a62ba365448e11ff1db3fb8bc84f1c7e5615da40233a8cd368010000000252ac9a070cd88dec5cf9aed1eab10d19529720e12c52d3a21b92c6fdb589d056908e43ea910e0200000009ac516a52656a6a5165ffffffffc3edcca8d2f61f34a5296c405c5f6bc58276416c720c956ff277f1fb81541ddd00000000030063abffffffff811247905cdfc973d179c03014c01e37d44e78f087233444dfdce1d1389d97c302000000065163000063ab1724a26e02ca37c902000000000851ab53525352ac529012a90100000000085200525253535353fa32575b", "5352ac6351", 1, -1087700448, "b8f1e1f35e3e1368bd17008c756e59cced216b3c699bcd7bebdb5b6c8eec4697"], + ["467a3e7602e6d1a7a531106791845ec3908a29b833598e41f610ef83d02a7da3a1900bf2960000000005ab6a636353ffffffff031db6dac6f0bafafe723b9199420217ad2c94221b6880654f2b35114f44b1df010000000965ab52636a63ac6352ffffffff02b3b95c0100000000026300703216030000000001ab3261c0aa", "6a", 0, 2110869267, "3078b1d1a7713c6d101c64afe35adfae0977a5ab4c7e07a0b170b041258adbf2"], + ["8713bc4f01b411149d575ebae575f5dd7e456198d61d238695df459dd9b86c4e3b2734b62e0300000004abac6363ffffffff03b58049050000000002ac653c714c04000000000953656a005151526a527b5a9e03000000000652ac5100525300000000", "52", 0, -647281251, "0e0bed1bf2ff255aef6e5c587f879ae0be6222ab33bd75ee365ec6fbb8acbe38"], + ["b5a7df6102107beded33ae7f1dec0531d4829dff7477260925aa2cba54119b7a07d92d5a1d02000000046a516a52803b625c334c1d2107a326538a3db92c6c6ae3f7c3516cd90a09b619ec6f58d10e77bd6703000000056563006a63ffffffff0117484b03000000000853acab52526a65abc1b548a1", "ac006a525100", 0, 2074359913, "680336db57347d8183b8898cd27a83f1ba5884155aeae5ce20b4840b75e12871"], + ["49eb2178020a04fca08612c34959fd41447319c190fb7ffed9f71c235aa77bec28703aa1820200000003ac6353abaff326071f07ec6b77fb651af06e8e8bd171068ec96b52ed584de1d71437fed186aecf0300000001acffffffff03da3dbe02000000000652ac63ac6aab8f3b680400000000096a536a65636a53516a5175470100000000016500000000", "6a536365", 0, 1283691249, "c670219a93234929f662ecb9aa148a85a2d281e83f4e53d10509461cdea47979"], + ["0f96cea9019b4b3233c0485d5b1bad770c246fe8d4a58fb24c3b7dfdb3b0fd90ea4e8e947f0300000006006a5163515303571e1e01906956030000000005ab635353abadc0fbbe", "acac", 0, -1491469027, "716a8180e417228f769dcb49e0491e3fda63badf3d5ea0ceeac7970d483dd7e2"], + ["148e68480196eb52529af8e83e14127cbfdbd4a174e60a86ac2d86eac9665f46f4447cf7aa01000000045200ac538f8f871401cf240c0300000000065252ab52656a5266cf61", "", 0, -344314825, "eacc47c5a53734d6ae3aedbc6a7c0a75a1565310851b29ef0342dc4745ceb607"], + ["6c7913f902aa3f5f939dd1615114ce961beda7c1e0dd195be36a2f0d9d047c28ac62738c3a020000000453abac00ffffffff477bf2c5b5c6733881447ac1ecaff3a6f80d7016eee3513f382ad7f554015b970100000007ab6563acab5152ffffffff04e58fe1040000000009ab00526aabab526553e59790010000000002ab525a834b03000000000035fdaf0200000000086551ac65515200ab00000000", "63ac53", 1, 1285478169, "1536da582a0b6de017862445e91ba14181bd6bf953f4de2f46b040d351a747c9"], + ["3320f6730132f830c4681d0cae542188e4177cad5d526fae84565c60ceb5c0118e844f90bd030000000163ffffffff0257ec5a040000000005525251ac6538344d000000000002515200000000", "5352656a53ac516a65", 0, 788050308, "3afacaca0ef6be9d39e71d7b1b118994f99e4ea5973c9107ca687d28d8eba485"], + ["c13aa4b702eedd7cde09d0416e649a890d40e675aa9b5b6d6912686e20e9b9e10dbd40abb1000000000863ab6353515351ac11d24dc4cc22ded7cdbc13edd3f87bd4b226eda3e4408853a57bcd1becf2df2a1671fd1600000000045165516affffffff01baea300100000000076aab52ab53005300000000", "0065", 0, -1195908377, "241a23e7b1982d5f78917ed97a8678087acbbffe7f624b81df78a5fe5e41e754"], + ["a2692fff03b2387f5bacd5640c86ba7df574a0ee9ed7f66f22c73cccaef3907eae791cbd230200000004536363abffffffff4d9fe7e5b375de88ba48925d9b2005447a69ea2e00495a96eafb2f144ad475b40000000008000053000052636537259bee3cedd3dcc07c8f423739690c590dc195274a7d398fa196af37f3e9b4a1413f810000000006ac63acac52abffffffff04c65fe60200000000075151536365ab657236fc020000000009005263ab00656a6a5195b8b6030000000007ac5165636aac6a7d7b66010000000002acab00000000", "51", 2, -826546582, "925037c7dc7625f3f12dc83904755a37016560de8e1cdd153c88270a7201cf15"], + ["2c5b003201b88654ac2d02ff6762446cb5a4af77586f05e65ee5d54680cea13291efcf930d0100000005ab536a006a37423d2504100367000000000004536a515335149800000000000152166aeb03000000000452510063226c8e03000000000000000000", "635251", 0, 1060344799, "7e058ca5dd07640e4aae7dea731cfb7d7fef1bfd0d6d7b6ce109d041f4ca2a31"], + ["f981b9e104acb93b9a7e2375080f3ea0e7a94ce54cd8fb25c57992fa8042bdf4378572859f0100000002630008604febba7e4837da77084d5d1b81965e0ea0deb6d61278b6be8627b0d9a2ecd7aeb06a0300000005ac5353536a42af3ef15ce7a2cd60482fc0d191c4236e66b4b48c9018d7dbe4db820f5925aad0e8b52a0300000008ab0063510052516301863715efc8608bf69c0343f18fb81a8b0c720898a3563eca8fe630736c0440a179129d03000000086aac6a52ac6a63ac44fec4c00408320a03000000000062c21c030000000007ac6a655263006553835f0100000000015303cd60000000000005535263536558b596e0", "00", 0, -2140385880, "49870a961263354c9baf108c6979b28261f99b374e97605baa532d9fa3848797"], + ["c4b702e502f1a54f235224f0e6de961d2e53b506ab45b9a40805d1dacd35148f0acf24ca5e00000000085200ac65ac53acabf34ba6099135658460de9d9b433b84a8562032723635baf21ca1db561dce1c13a06f4407000000000851ac006a63516aabffffffff02a853a603000000000163d17a67030000000005ab63006a5200000000", "ac5363515153", 1, 480734903, "5c46f7ac3d6460af0da28468fcc5b3c87f2b9093d0f837954b7c8174b4d7b6e7"], + ["9b83f78704f492b9b353a3faad8d93f688e885030c274856e4037818848b99e490afef27770200000000ffffffff36b60675a5888c0ef4d9e11744ecd90d9fe9e6d8abb4cff5666c898fdce98d9e00000000056aab656352596370fca7a7c139752971e169a1af3e67d7656fc4fc7fd3b98408e607c2f2c836c9f27c030000000653ac51ab6300a0761de7e158947f401b3595b7dc0fe7b75fa9c833d13f1af57b9206e4012de0c41b8124030000000953656a53ab53510052242e5f5601bf83b301000000000465516a6300000000", "63515200ac656365", 3, -150879312, "9cf05990421ea853782e4a2c67118e03434629e7d52ab3f1d55c37cf7d72cdc4"], + ["f492a9da04f80b679708c01224f68203d5ea2668b1f442ebba16b1aa4301d2fe5b4e2568f3010000000953005351525263ab65ffffffff93b34c3f37d4a66df255b514419105b56d7d60c24bf395415eda3d3d8aa5cd0101000000020065ffffffff9dba34dabdc4f1643b372b6b77fdf2b482b33ed425914bb4b1a61e4fad33cf390000000002ab52ffffffffbbf3dc82f397ef3ee902c5146c8a80d9a1344fa6e38b7abce0f157be7adaefae0000000009515351005365006a51ffffffff021359ba010000000000403fea0200000000095200ac6353abac635300000000", "00ac51acacac", 0, -2115078404, "fd44fc98639ca32c927929196fc3f3594578f4c4bd248156a25c04a65bf3a9f3"], + ["2f73e0b304f154d3a00fde2fdd40e791295e28d6cb76af9c0fd8547acf3771a02e3a92ba37030000000852ac6351ab6565639aa95467b065cec61b6e7dc4d6192b5536a7c569315fb43f470078b31ed22a55dab8265f02000000080065636a6aab6a53ffffffff9e3addbff52b2aaf9fe49c67017395198a9b71f0aa668c5cb354d06c295a691a0100000000ffffffff45c2b4019abaf05c5e484df982a4a07459204d1343a6ee5badade358141f8f990300000007ac516a6aacac6308655cd601f3bc2f0000000000015200000000", "", 0, -2082053939, "9a95e692e1f78efd3e46bb98f178a1e3a0ef60bd0301d9f064c0e5703dc879c2"], + ["5a60b9b503553f3c099f775db56af3456330f1e44e67355c4ab290d22764b9144a7b5f959003000000030052acbd63e0564decc8659aa53868be48c1bfcda0a8c9857b0db32a217bc8b46d9e7323fe9649020000000553ac6551abd0ecf806211db989bead96c09c7f3ec5f73c1411d3329d47d12f9e46678f09bac0dc383e0200000000ffffffff01494bb202000000000500516551ac00000000", "ac", 0, 1169947809, "62a36c6e8da037202fa8aeae03e533665376d5a4e0a854fc4624a75ec52e4eb1"], + ["e3649aa40405e6ffe377dbb1bbbb672a40d8424c430fa6512c6165273a2b9b6afa9949ec430200000007630052ab655153a365f62f2792fa90c784efe3f0981134d72aac0b1e1578097132c7f0406671457c332b84020000000353ab6ad780f40cf51be22bb4ff755434779c7f1def4999e4f289d2bd23d142f36b66fbe5cfbb4b01000000076a5252abac52ab1430ffdc67127c9c0fc97dcd4b578dab64f4fb9550d2b59d599773962077a563e8b6732c02000000016affffffff04cb2687000000000002ab636e320904000000000252acf70e9401000000000100dc3393050000000006ab0063536aacbc231765", "65520053", 3, -2016196547, "f64f805f0ff7f237359fa6b0e58085f3c766d1859003332223444fd29144112a"], + ["4c4be7540344050e3044f0f1d628039a334a7c1f7b4573469cfea46101d6888bb6161fe9710200000000ffffffffac85a4fdad641d8e28523f78cf5b0f4dc74e6c5d903c10b358dd13a5a1fd8a06000000000163e0ae75d05616b72467b691dc207fe2e65ea35e2eadb7e06ea442b2adb9715f212c0924f10200000000ffffffff0194ddfe02000000000265ac00000000", "00006500", 1, -479922562, "d66924d49f03a6960d3ca479f3415d638c45889ce9ab05e25b65ac260b51d634"], + ["202c18eb012bc0a987e69e205aea63f0f0c089f96dd8f0e9fcde199f2f37892b1d4e6da90302000000055352ac6565ffffffff0257e5450100000000025300ad257203000000000000000000", "520052ac6a005265", 0, 168054797, "502967a6f999f7ee25610a443caf8653dda288e6d644a77537bcc115a8a29894"], + ["32fa0b0804e6ea101e137665a041cc2350b794e59bf42d9b09088b01cde806ec1bbea077df0200000008515153650000006506a11c55904258fa418e57b88b12724b81153260d3f4c9f080439789a391ab147aabb0fa0000000007000052ac51ab510986f2a15c0d5e05d20dc876dd2dafa435276d53da7b47c393f20900e55f163b97ce0b800000000008ab526a520065636a8087df7d4d9c985fb42308fb09dce704650719140aa6050e8955fa5d2ea46b464a333f870000000009636300636a6565006affffffff01994a0d040000000002536500000000", "516563530065", 2, -163068286, "f58637277d2bc42e18358dc55f7e87e7043f5e33f4ce1fc974e715ef0d3d1c2a"], + ["ae23424d040cd884ebfb9a815d8f17176980ab8015285e03fdde899449f4ae71e04275e9a80100000007ab006553530053ffffffff018e06db6af519dadc5280c07791c0fd33251500955e43fe4ac747a4df5c54df020000000251ac330e977c0fec6149a1768e0d312fdb53ed9953a3737d7b5d06aad4d86e9970346a4feeb5030000000951ab51ac6563ab526a67cabc431ee3d8111224d5ecdbb7d717aa8fe82ce4a63842c9bd1aa848f111910e5ae1eb0100000004ac515300bfb7e0d7048acddc030000000009636a5253636a655363a3428e040000000001525b99c6050000000004655265ab717e6e020000000000d99011eb", "ac6a6a516565", 1, -716251549, "b098eb9aff1bbd375c70a0cbb9497882ab51f3abfebbf4e1f8d74c0739dc7717"], + ["030f44fc01b4a9267335a95677bd190c1c12655e64df74addc53b753641259af1a54146baa020000000152e004b56c04ba11780300000000026a53f125f001000000000251acd2cc7c03000000000763536563655363c9b9e50500000000015200000000", "ac", 0, -1351818298, "19dd32190ed2a37be22f0224a9b55b91e37290577c6c346d36d32774db0219a3"], + ["c05f448f02817740b30652c5681a3b128322f9dc97d166bd4402d39c37c0b14506d8adb5890300000003536353ffffffffa188b430357055ba291c648f951cd2f9b28a2e76353bef391b71a889ba68d5fc02000000056565526a6affffffff02745f73010000000001ab3ec34c0400000000036aac5200000000", "516551510053", 0, -267877178, "3a1c6742d4c374f061b1ebe330b1e169a113a19792a1fdde979b53e094cc4a3c"], + ["163ba45703dd8c2c5a1c1f8b806afdc710a2a8fc40c0138e2d83e329e0e02a9b6c837ff6b8000000000700655151ab6a522b48b8f134eb1a7e6f5a6fa319ce9d11b36327ba427b7d65ead3b4a6a69f85cda8bbcd22030000000563656552acffffffffdbcf4955232bd11eef0cc6954f3f6279675b2956b9bcc24f08c360894027a60201000000066500006500abffffffff04d0ce9d0200000000008380650000000000015233f360040000000003006aabedcf0801000000000000000000", "000065006500ac", 0, 216965323, "9afe3f4978df6a86e9a8ebd62ef6a9d48a2203f02629349f1864ef2b8b92fd55"], + ["fe647f950311bf8f3a4d90afd7517df306e04a344d2b2a2fea368935faf11fa6882505890d0000000005ab5100516affffffff43c140947d9778718919c49c0535667fc6cc727f5876851cb8f7b6460710c7f60100000000ffffffffce4aa5d90d7ab93cbec2e9626a435afcf2a68dd693c15b0e1ece81a9fcbe025e0300000000ffffffff02f34806020000000002515262e54403000000000965635151ac655363636de5ce24", "6a005100ac516351", 2, 989643518, "818a7ceaf963f52b5c48a7f01681ac6653c26b63a9f491856f090d9d60f2ffe3"], + ["cef7316804c3e77fe67fc6207a1ea6ae6eb06b3bf1b3a4010a45ae5c7ad677bb8a4ebd16d90200000009ac536a5152ac5263005301ab8a0da2b3e0654d31a30264f9356ba1851c820a403be2948d35cafc7f9fe67a06960300000006526a63636a53ffffffffbada0d85465199fa4232c6e4222df790470c5b7afd54704595a48eedd7a4916b030000000865ab63ac006a006ab28dba4ad55e58b5375053f78b8cdf4879f723ea4068aed3dd4138766cb4d80aab0aff3d0300000003ac6a00ffffffff010f5dd6010000000006ab006aab51ab00000000", "", 1, 889284257, "d0f32a6db43378af84b063a6706d614e2d647031cf066997c48c04de3b493a94"], + ["7b3ff28004ba3c7590ed6e36f45453ebb3f16636fe716acb2418bb2963df596a50ed954d2e03000000065251515265abffffffff706ee16e32e22179400c9841013971645dabf63a3a6d2d5feb42f83aa468983e030000000653ac51ac5152ffffffffa03a16e5e5de65dfa848b9a64ee8bf8656cc1f96b06a15d35bd5f3d32629876e020000000043c1a3965448b3b46f0f0689f1368f3b2981208a368ec5c30defb35595ef9cf95ffd10e902000000036aac65253a5bbe042e907204000000000800006565656352634203b4020000000002656336b3b7010000000001ab7a063f0100000000026500a233cb76", "006551636a53ac5251", 1, -1144216171, "68c7bd717b399b1ee33a6562a916825a2fed3019cdf4920418bb72ffd7403c8c"], + ["1be8ee5604a9937ebecffc832155d9ba7860d0ca451eaced58ca3688945a31d93420c27c460100000006abac5300535288b65458af2f17cbbf7c5fbcdcfb334ffd84c1510d5500dc7d25a43c36679b702e850f7c0200000003005300ffffffff7c237281cb859653eb5bb0a66dbb7aeb2ac11d99ba9ed0f12c766a8ae2a2157203000000086aabac526365acabfffffffff09d3d6639849f442a6a52ad10a5d0e4cb1f4a6b22a98a8f442f60280c9e5be80200000007ab00ab6565ab52ffffffff0398fe83030000000005526aababacbdd6ec010000000005535252ab6a82c1e6040000000001652b71c40c", "6563526353656351", 2, -853634888, "0d936cceda2f56c7bb87d90a7b508f6208577014ff280910a710580357df25f3"], + ["9e0f99c504fbca858c209c6d9371ddd78985be1ab52845db0720af9ae5e2664d352f5037d4010000000552ac53636affffffff0e0ce866bc3f5b0a49748f597c18fa47a2483b8a94cef1d7295d9a5d36d31ae7030000000663515263ac635bb5d1698325164cdd3f7f3f7831635a3588f26d47cc30bf0fefd56cd87dc4e84f162ab702000000036a6365ffffffff85c2b1a61de4bcbd1d5332d5f59f338dd5e8accbc466fd860f96eef1f54c28ec030000000165ffffffff04f5cabd010000000007000052ac526563c18f1502000000000465510051dc9157050000000008655363ac525253ac506bb600000000000865656a53ab63006a00000000", "006a6a0052", 0, 1186324483, "2f9b7348600336512686e7271c53015d1cb096ab1a5e0bce49acd35bceb42bc8"], + ["11ce51f90164b4b54b9278f0337d95c50d16f6828fcb641df9c7a041a2b274aa70b1250f2b0000000008ab6a6a65006551524c9fe7f604af44be050000000005525365006521f79a0300000000015306bb4e04000000000265ac99611a05000000000765acab656500006dc866d0", "", 0, -1710478768, "cfa4b7573559b3b199478880c8013fa713ca81ca8754a3fd68a6d7ee6147dc5a"], + ["86bc233e02ba3c647e356558e7252481a7769491fb46e883dd547a4ce9898fc9a1ca1b77790000000006ab5351abab51f0c1d09c37696d5c7c257788f5dff5583f4700687bcb7d4acfb48521dc953659e325fa390300000003acac5280f29523027225af03000000000963abac0065ab65acab7e59d90400000000016549dac846", "53006aac52acac", 0, 711159875, "880330ccde00991503ea598a6dfd81135c6cda9d317820352781417f89134d85"], + ["beac155d03a853bf18cd5c490bb2a245b3b2a501a3ce5967945b0bf388fec2ba9f04c03d68030000000012fe96283aec4d3aafed8f888b0f1534bd903f9cd1af86a7e64006a2fa0d2d30711af770010000000163ffffffffd963a19d19a292104b9021c535d3e302925543fb3b5ed39fb2124ee23a9db00302000000056500ac63acffffffff01ad67f503000000000300ac5189f78db2", "53536a636500", 2, 748992863, "bde3dd0575164d7ece3b5783ce0783ffddb7df98f178fe6468683230314f285a"], + ["489ebbf10478e260ba88c0168bd7509a651b36aaee983e400c7063da39c93bf28100011f280100000004abab63ab2fc856f05f59b257a4445253e0d91b6dffe32302d520ac8e7f6f2467f7f6b4b65f2f59e903000000096353abacab6351656affffffff0122d9480db6c45a2c6fd68b7bc57246edffbf6330c39ccd36aa3aa45ec108fc030000000265ab9a7e78a69aadd6b030b12602dff0739bbc346b466c7c0129b34f50ae1f61e634e11e9f3d0000000006516a53525100ffffffff011271070000000000086563ab6353536352c4dd0e2c", "", 0, -293358504, "4eba3055bc2b58765593ec6e11775cea4b6493d8f785e28d01e2d5470ea71575"], + ["6911195d04f449e8eade3bc49fd09b6fb4b7b7ec86529918b8593a9f6c34c2f2d301ec378b000000000263ab49162266af054643505b572c24ff6f8e4c920e601b23b3c42095881857d00caf56b28acd030000000565525200ac3ac4d24cb59ee8cfec0950312dcdcc14d1b360ab343e834004a5628d629642422f3c5acc02000000035100accf99b663e3c74787aba1272129a34130668a877cc6516bfb7574af9fa6d07f9b4197303400000000085351ab5152635252ffffffff042b3c95000000000000ff92330200000000046a5252ab884a2402000000000853530065520063000d78be03000000000953abab52ab53ac65aba72cb34b", "6a", 2, -637739405, "6b80d74eb0e7ee59d14f06f30ba7d72a48d3a8ff2d68d3b99e770dec23e9284f"], + ["746347cf03faa548f4c0b9d2bd96504d2e780292730f690bf0475b188493fb67ca58dcca4f0000000002005336e3521bfb94c254058e852a32fc4cf50d99f9cc7215f7c632b251922104f638aa0b9d080100000008656aac5351635251ffffffff4da22a678bb5bb3ad1a29f97f6f7e5b5de11bb80bcf2f7bb96b67b9f1ac44d09030000000365ababffffffff036f02b30000000000076353ab6aac63ac50b72a050000000002acaba8abf804000000000663006a6a6353797eb999", "acac5100", 1, -1484493812, "164c32a263f357e385bd744619b91c3f9e3ce6c256d6a827d6defcbdff38fa75"], + ["e17149010239dd33f847bf1f57896db60e955117d8cf013e7553fae6baa9acd3d0f1412ad90200000006516500516500cb7b32a8a67d58dddfb6ceb5897e75ef1c1ff812d8cd73875856487826dec4a4e2d2422a0100000004ac525365196dbb69039229270400000000070000535351636a8b7596020000000006ab51ac52655131e99d040000000003516551ee437f5c", "ac656a53", 1, 1102662601, "8858bb47a042243f369f27d9ab4a9cd6216adeac1c1ac413ed0890e46f23d3f3"], + ["144971940223597a2d1dec49c7d4ec557e4f4bd207428618bafa3c96c411752d494249e1fb0100000004526a5151ffffffff340a545b1080d4f7e2225ff1c9831f283a7d4ca4d3d0a29d12e07d86d6826f7f0200000003006553ffffffff03c36965000000000000dfa9af00000000000451636aac7f7d140300000000016300000000", "", 1, -108117779, "c84fcaf9d779df736a26cc3cabd04d0e61150d4d5472dd5358d6626e610be57f"], + ["2aee6b9a02172a8288e02fac654520c9dd9ab93cf514d73163701f4788b4caeeb9297d2e250300000004ab6363008fb36695528d7482710ea2926412f877a3b20acae31e9d3091406bfa6b62ebf9d9d2a6470100000009535165536a63520065ffffffff03f7b560050000000003acab6a9a8338050000000000206ce90000000000056552516a5100000000", "5252", 1, -1102319963, "fa4676c374ae3a417124b4c970d1ed3319dc3ac91fb36efca1aa9ed981a8aa1b"], + ["9554595203ad5d687f34474685425c1919e3d2cd05cf2dac89d5f33cd3963e5bb43f8706480100000000ffffffff9de2539c2fe3000d59afbd376cb46cefa8bd01dbc43938ff6089b63d68acdc2b02000000096553655251536a6500fffffffff9695e4016cd4dfeb5f7dadf00968e6a409ef048f81922cec231efed4ac78f5d010000000763abab6a5365006caaf0070162cc640200000000045163ab5100000000", "", 0, -1105256289, "e8e10ed162b1a43bfd23bd06b74a6c2f138b8dc1ab094ffb2fa11d5b22869bee"], + ["04f51f2a0484cba53d63de1cb0efdcb222999cdf2dd9d19b3542a896ca96e23a643dfc45f00200000007acac53510063002b091fd0bfc0cfb386edf7b9e694f1927d7a3cf4e1d2ce937c1e01610313729ef6419ae7030000000165a3372a913c59b8b3da458335dc1714805c0db98992fd0d93f16a7f28c55dc747fe66a5b503000000095351ab65ab52536351ffffffff5650b318b3e236802a4e41ed9bc0a19c32b7aa3f9b2cda1178f84499963a0cde000000000165ffffffff0383954f04000000000553ac536363a8fc90030000000000a2e315000000000005acab00ab5100000000", "0053", 2, -1424653648, "a5bc0356f56b2b41a2314ec05bee7b91ef57f1074bcd2efc4da442222269d1a3"], + ["53dc1a88046531c7b57a35f4d9adf101d068bf8d63fbbedaf4741dba8bc5e92c8725def571030000000453655251fcdf116a226b3ec240739c4c7493800e4edfe67275234e371a227721eac43d3d9ecaf1b50300000003ac0052ffffffff2c9279ffeea4718d167e9499bd067600715c14484e373ef93ae4a31d2f5671ab0000000009516553ac636a6a65001977752eeba95a8f16b88c571a459c2f2a204e23d48cc7090e4f4cc35846ca7fc0a455ce00000000055165ac0063188143f80205972902000000000765ac63ac516353c7b6a50000000000036a510000000000", "655351536a", 0, 103806788, "b276584d3514e5b4e058167c41dc02915b9d97f6795936a51f40e894ed8508bc"], + ["5a06cb4602dcfc85f49b8d14513f33c48f67146f2ee44959bbca092788e6823b2719f3160b0200000001ab3c013f2518035b9ea635f9a1c74ec1a3fb7496a160f46aae2e09bfc5cd5111a0f20969e003000000015158c89ab7049f20d6010000000008ac6a52abac53515349765e00000000000300ab638292630100000000045351ab0086da09010000000006656a6365525300000000", "526a63", 1, 1502936586, "bdfaff8a4e775379c5dc26e024968efa805f923de53fa8272dd53ec582afa0c5"], + ["ca9d84fa0129011e1bf27d7cb71819650b59fb292b053d625c6f02b0339249b498ff7fd4b601000000025352ffffffff032173a0040000000008525253abab5152639473bb030000000009005153526a53535151d085bd0000000000086a5365ab5165655300000000", "005152ac51", 0, 580353445, "c629d93b02037f40aa110e46d903edb34107f64806aa0c418d435926feef68b8"], + ["e3cdbfb4014d90ae6a4401e85f7ac717adc2c035858bf6ff48979dd399d155bce1f150daea0300000002ac51a67a0d39017f6c71040000000005535200535200000000", "", 0, -1899950911, "c1c7df8206e661d593f6455db1d61a364a249407f88e99ecad05346e495b38d7"], + ["b2b6b9ab0283d9d73eeae3d847f41439cd88279c166aa805e44f8243adeb3b09e584efb1df00000000026300ffffffff7dfe653bd67ca094f8dab51007c6adaced09de2af745e175b9714ca1f5c68d050000000003ac6500aa8e596903fd3f3204000000000553ac6a6a533a2e210500000000075253acabab526392d0ee020000000008520065635200ab5200000000", "65acacac65005365", 0, 28298553, "39c2aaa2496212b3ab120ab7d7f37c5e852bfe38d20f5226413a2268663eeae8"], + ["4314339e01de40faabcb1b970245a7f19eedbc17c507dac86cf986c2973715035cf95736ae0200000007abababababab65bde67b900151510b04000000000853ac00655200535300000000", "52", 0, 399070095, "47585dc25469d04ff3a60939d0a03779e3e81a411bf0ca18b91bb925ebd30718"], + ["f063171b03e1830fdc1d685a30a377537363ccafdc68b42bf2e3acb908dac61ee24b37595c020000000765ac5100ab6aacf447bc8e037b89d6cadd62d960cc442d5ced901d188867b5122b42a862929ce45e7b628d010000000253aba009a1ba42b00f1490b0b857052820976c675f335491cda838fb7934d5eea0257684a2a202000000001e83cf2401a7f777030000000008ab6553526a53526a00000000", "", 2, 1984790332, "c19caada8e71535e29a86fa29cfd9b74a0c7412003fc722a121005e461e01636"], + ["cf7bdc250249e22cbe23baf6b648328d31773ea0e771b3b76a48b4748d7fbd390e88a004d30000000003ac536a4ab8cce0e097136c90b2037f231b7fde2063017facd40ed4e5896da7ad00e9c71dd70ae600000000096a0063516352525365ffffffff01b71e3e00000000000300536a00000000", "", 1, 546970113, "6a815ba155270af102322c882f26d22da11c5330a751f520807936b320b9af5d"], + ["ac7a125a0269d35f5dbdab9948c48674616e7507413cd10e1acebeaf85b369cd8c88301b7c030000000963656aac6a530053abffffffffed94c39a582e1a46ce4c6bffda2ccdb16cda485f3a0d94b06206066da12aecfe010000000752abab63536363ef71dcfb02ee07fa0400000000016a6908c802000000000751656a6551abac688c2c2d", "6a6351526551", 0, 858400684, "552ff97d7924f51cda6d1b94be53483153ef725cc0a3a107adbef220c753f9a6"], + ["3a1f454a03a4591e46cf1f7605a3a130b631bf4dfd81bd2443dc4fac1e0a224e74112884fe0000000005516aac6a53a87e78b55548601ffc941f91d75eab263aa79cd498c88c37fdf275a64feff89fc1710efe03000000016a39d7ef6f2a52c00378b4f8f8301853b61c54792c0f1c4e2cd18a08cb97a7668caa008d970200000002656affffffff017642b20100000000096a63535253abac6a6528271998", "51", 2, 1459585400, "e9a7f21fc2d38be7be47095fbc8f1bf8923660aa4d71df6d797ae0ba5ca4d5b0"], + ["6269e0fa0173e76e89657ca495913f1b86af5b8f1c1586bcd6c960aede9bc759718dfd5044000000000352ac530e2c7bd90219849b000000000007ab00ab6a53006319f281000000000007ab00515165ac5200000000", "6a", 0, -2039568300, "62094f98234a05bf1b9c7078c5275ed085656856fb5bdfd1b48090e86b53dd85"], + ["eb2bc00604815b9ced1c604960d54beea4a3a74b5c0035d4a8b6bfec5d0c9108f143c0e99a0000000000ffffffff22645b6e8da5f11d90e5130fd0a0df8cf79829b2647957471d881c2372c527d8010000000263acffffffff1179dbaf17404109f706ae27ad7ba61e860346f63f0c81cb235d2b05d14f2c1003000000025300264cb23aaffdc4d6fa8ec0bb94eff3a2e50a83418a8e9473a16aaa4ef8b855625ed77ef40100000003ac51acf8414ad404dd328901000000000652526500006ab6261c000000000002526a72a4c9020000000006ac526500656586d2e7000000000006656aac00ac5279cd8908", "51", 1, -399279379, "d37532e7b2b8e7db5c7c534197600397ebcc15a750e3af07a3e2d2e4f84b024f"], + ["eba8b0de04ac276293c272d0d3636e81400b1aaa60db5f11561480592f99e6f6fa13ad387002000000070053acab536563bebb23d66fd17d98271b182019864a90e60a54f5a615e40b643a54f8408fa8512cfac927030000000963ac6a6aabac65ababffffffff890a72192bc01255058314f376bab1dc72b5fea104c154a15d6faee75dfa5dba020000000100592b3559b0085387ac7575c05b29b1f35d9a2c26a0c27903cc0f43e7e6e37d5a60d8305a030000000252abffffffff0126518f05000000000000000000", "005300635252635351", 1, 664344756, "26dc2cba4bd5334e5c0b3a520b44cc1640c6b923d10e576062f1197171724097"], + ["185cda1a01ecf7a8a8c28466725b60431545fc7a3367ab68e34d486e8ea85ee3128e0d8384000000000465ac63abec88b7bb031c56eb04000000000965636a51005252006a7c78d5040000000007acac63abac51ac3024a40500000000086300526a51abac51464c0e8c", "0065535265515352", 0, 1594558917, "b5280b9610c0625a65b36a8c2402a95019a7bbb9dd3de77f7c3cb1d82c3263ba"], + ["92c9fb780138abc472e589d5b59489303f234acc838ca66ffcdf0164517a8679bb622a4267020000000153468e373d04de03fa020000000009ac006a5265ab5163006af649050000000007515153006a00658ceb59030000000001ac36afa0020000000009ab53006351ab51000000000000", "6a", 0, 2059357502, "e2358dfb51831ee81d7b0bc602a65287d6cd2dbfacf55106e2bf597e22a4b573"], + ["6f62138301436f33a00b84a26a0457ccbfc0f82403288b9cbae39986b34357cb2ff9b889b302000000045253655335a7ff6701bac9960400000000086552ab656352635200000000", "6aac51", 0, 1444414211, "502a2435fd02898d2ff3ab08a3c19078414b32ec9b73d64a944834efc9dae10c"], + ["9981143a040a88c2484ac3abe053849e72d04862120f424f373753161997dd40505dcb4783030000000700536365536565a2e10da3f4b1c1ad049d97b33f0ae0ea48c5d7c30cc8810e144ad93be97789706a5ead180100000003636a00ffffffffbdcbac84c4bcc87f03d0ad83fbe13b369d7e42ddb3aecf40870a37e814ad8bb5010000000963536a5100636a53abffffffff883609905a80e34202101544f69b58a0b4576fb7391e12a769f890eef90ffb72020000000651656352526affffffff04243660000000000004ab5352534a9ce001000000000863656363ab6a53652df19d030000000003ac65acedc51700000000000000000000", "ac6300acac", 2, 293672388, "7ba99b289c04718a7283f150d831175ed6303081e191a0608ea81f78926c5bdf"], + ["49f7d0b6037bba276e910ad3cd74966c7b3bc197ffbcfefd6108d6587006947e97789835ea0300000008526a52006a650053ffffffff8d7b6c07cd10f4c4010eac7946f61aff7fb5f3920bdf3467e939e58a1d4100ab03000000076aac63ac535351ffffffff8f48c3ba2d52ad67fbcdc90d8778f3c8a3894e3c35b9730562d7176b81af23c80100000003ab5265ffffffff0301e3ef0300000000046a525353e899ac0500000000075153ab6a65abac259bea0400000000007b739972", "53516aacac6aac", 1, 955403557, "5d366a7f4346ae18aeb7c9fc4dab5af71173184aa20ed22fcb4ea8511ad25449"], + ["58a4fed801fbd8d92db9dfcb2e26b6ff10b120204243fee954d7dcb3b4b9b53380e7bb8fb60100000003006351ffffffff02a0795b050000000006536351ac6aac2718d00200000000075151acabac515354d21ba1", "005363515351", 0, -1322430665, "bbee941bbad950424bf40e3623457db47f60ed29deaa43c99dec702317cb3326"], + ["17fad0d303da0d764fedf9f2887a91ea625331b28704940f41e39adf3903d8e75683ef6d46020000000151ffffffffff376eea4e880bcf0f03d33999104aafed2b3daf4907950bb06496af6b51720a020000000900636a63525253525196521684f3b08497bad2c660b00b43a6a517edc58217876eb5e478aa3b5fda0f29ee1bea00000000046aacab6affffffff03dde8e2050000000007ac5365ac51516a14772e000000000005630000abacbbb360010000000006ab5251ab656a50f180f0", "0053", 0, -1043701251, "a3bdf8771c8990971bff9b4e7d59b7829b067ed0b8d3ac1ec203429811384668"], + ["5a2257df03554550b774e677f348939b37f8e765a212e566ce6b60b4ea8fed4c9504b7f7d1000000000653655265ab5258b67bb931df15b041177cf9599b0604160b79e30f3d7a594e7826bae2c29700f6d8f8f40300000005515300ac6a159cf8808a41f504eb5c2e0e8a9279f3801a5b5d7bc6a70515fbf1c5edc875bb4c9ffac500000000050063510052ffffffff0422a90105000000000965006a650000516a006417d2020000000006526363ab00524d969d0100000000035153acc4f077040000000005ac5200636500000000", "6a52", 1, -1482463464, "37b794b05d0687c9b93d5917ab068f6b2f0e38406ff04e7154d104fc1fb14cdc"], + ["e0032ad601269154b3fa72d3888a3151da0aed32fb2e1a15b3ae7bee57c3ddcffff76a1321010000000100110d93ae03f5bd080100000000075263516a6551002871e60100000000046a005252eaa753040000000004ab6aab526e325c71", "630052", 0, -1857873018, "ea117348e94de86381bb8ad1c7f93b8c623f0272104341701bb54e6cb433596c"], + ["014b2a5304d46764817aca180dca50f5ab25f2e0d5749f21bb74a2f8bf6b8b7b3fa8189cb7030000000965ac5165ab6a51ac6360ecd91e8abc7e700a4c36c1a708a494c94bb20cbe695c408543146566ab22be43beae9103000000045163ab00ffffffffffa48066012829629a9ec06ccd4905a05df0e2b745b966f6a269c9c8e13451fc00000000026565ffffffffc40ccadc21e65fe8a4b1e072f4994738ccaf4881ae6fede2a2844d7da4d199ab02000000065152ab536aabffffffff01b6e054030000000004515352ab3e063432", "", 0, 1056459916, "a7aff48f3b8aeb7a4bfe2e6017c80a84168487a69b69e46681e0d0d8e63a84b6"], + ["1201ab5d04f89f07c0077abd009762e59db4bb0d86048383ba9e1dad2c9c2ad96ef660e6d00200000007ab6a65ac5200652466fa5143ab13d55886b6cdc3d0f226f47ec1c3020c1c6e32602cd3428aceab544ef43e00000000086a6a6a526a6a5263ffffffffd5be0b0be13ab75001243749c839d779716f46687e2e9978bd6c9e2fe457ee48020000000365abab1e1bac0f72005cf638f71a3df2e3bbc0fa35bf00f32d9c7dc9c39a5e8909f7d53170c8ae0200000008ab6a51516363516affffffff02f0a6210500000000036300ac867356010000000009acab65ac6353536a659356d367", "ac53535252", 0, 917543338, "418acc156c2bc76a5d7baa58db29f1b4cf6c266c9222ed167ef5b4d47f0e0f41"], + ["344fa11e01c19c4dd232c77742f0dd0aeb3695f18f76da627628741d0ee362b0ea1fb3a2180200000007635151005100529bab25af01937c1f0500000000055153ab53656e7630af", "6351005163ac51", 0, -629732125, "228ca52a0a376fe0527a61cfa8da6d7baf87486bba92d49dfd3899cac8a1034f"], + ["b2fda1950191358a2b855f5626a0ebc830ab625bea7480f09f9cd3b388102e35c0f303124c030000000565ac65ab53ffffffff03f9c5ec04000000000765ab51516551650e2b9f0500000000045365525284e8f6040000000001ac00000000", "ac51655253", 0, 1433027632, "d2fa7e13c34cecda5105156bd2424c9b84ee0a07162642b0706f83243ff811a8"], + ["a4a6bbd201aa5d882957ac94f2c74d4747ae32d69fdc765add4acc2b68abd1bdb8ee333d6e0300000008516a6552515152abffffffff02c353cb040000000007ac6351ab51536588bd320500000000066552525253ac00000000", "", 0, 1702060459, "499da7d74032388f820645191ac3c8d20f9dba8e8ded7fa3a5401ea2942392a1"], + ["83a583d204d926f2ee587a83dd526cf1e25a44bb668e45370798f91a2907d184f7cddcbbc7030000000700ab6565536a539f71d3776300dffdfa0cdd1c3784c9a1f773e34041ca400193612341a9c42df64e3f550e01000000050052515251ffffffff52dab2034ab0648553a1bb8fc4e924b2c89ed97c18dfc8a63e248b454035564b01000000015139ab54708c7d4d2c2886290f08a5221cf69592a810fd1979d7b63d35c271961e710424fd0300000005ac65ac5251ffffffff01168f7c030000000000a85e5fb0", "6a536353656a00", 0, 179595345, "5350a31ac954a0b49931239d0ecafbf34d035a537fd0c545816b8fdc355e9961"], + ["ffd35d51042f290108fcb6ea49a560ba0a6560f9181da7453a55dfdbdfe672dc800b39e7320200000006630065516a65f2166db2e3827f44457e86dddfd27a8af3a19074e216348daa0204717d61825f198ec0030100000006ab51abab00abffffffffdf41807adb7dff7db9f14d95fd6dc4e65f8402c002d009a3f1ddedf6f4895fc8030000000500ab006a65a5a848345052f860620abd5fcd074195548ce3bd0839fa9ad8642ed80627bf43a0d47dbd010000000765ab006a656a53b38cdd6502a186da05000000000765ab00ab006a53527c0e0100000000085365ab51acacac52534bd1b1", "6a635253ac0000", 0, 1095082149, "3c05473a816621a3613f0e903faa1a1e44891dd40862b029e41fc520776350fa"], + ["6c9a4b98013c8f1cae1b1df9f0f2de518d0c50206a0ab871603ac682155504c0e0ce946f460100000000ffffffff04e9266305000000000753535100ac6aacded39e04000000000365ac6ab93ccd010000000002515397bf3d050000000003ab636300000000", "63520052ac656353", 0, -352633155, "936eff8cdfd771be24124da87c7b24feb48da7cbc2c25fb5ba13d1a23255d902"], + ["c4b80f850323022205b3e1582f1ed097911a81be593471a8dce93d5c3a7bded92ef6c7c1260100000002006affffffff70294d62f37c3da7c5eae5d67dce6e1b28fedd7316d03f4f48e1829f78a88ae801000000096a5200530000516351f6b7b544f7c39189d3a2106ca58ce4130605328ce7795204be592a90acd81bef517d6f170200000000ffffffff012ab8080000000000075100006365006335454c1e", "53ac6a536aacac", 0, -1124103895, "06277201504e6bf8b8c94136fad81b6e3dadacb9d4a2c21a8e10017bfa929e0e"], + ["8ab69ed50351b47b6e04ac05e12320984a63801716739ed7a940b3429c9c9fed44d3398ad40300000006536a516a52638171ef3a46a2adb8025a4884b453889bc457d63499971307a7e834b0e76eec69c943038a0300000000ffffffff566bb96f94904ed8d43d9d44a4a6301073cef2c011bf5a12a89bedbaa03e4724030000000265acb606affd01edea38050000000008515252516aacac6300000000", "65000000006365ac53", 0, -1338942849, "7912573937824058103cb921a59a7f910a854bf2682f4116a393a2045045a8c3"], + ["2484991e047f1cf3cfe38eab071f915fe86ebd45d111463b315217bf9481daf0e0d10902a402000000006e71a424eb1347ffa638363604c0d5eccbc90447ff371e000bf52fc743ec832851bb564a0100000001abffffffffef7d014fad3ae7927948edbbb3afe247c1bcbe7c4c8f5d6cf97c799696412612020000000851536a5353006a001dfee0d7a0dd46ada63b925709e141863f7338f34f7aebde85d39268ae21b77c3068c01d0000000008535151ab00636563ffffffff018478070200000000095200635365ac52ab5341b08cd3", "", 3, 265623923, "24cb420a53b4f8bb477f7cbb293caabfd2fc47cc400ce37dbbab07f92d3a9575"], + ["54839ef9026f65db30fc9cfcb71f5f84d7bb3c48731ab9d63351a1b3c7bc1e7da22bbd508e0300000000442ad138f170e446d427d1f64040016032f36d8325c3b2f7a4078766bdd8fb106e52e8d20000000003656500ffffffff02219aa101000000000851ababac52ab00659646bd02000000000552acacabac24c394a5", "ac", 0, 906807497, "69264faadcd1a581f7000570a239a0a26b82f2ad40374c5b9c1f58730514de96"], + ["5036d7080434eb4eef93efda86b9131b0b4c6a0c421e1e5feb099a28ff9dd8477728639f77030000000951516aab535152ab5391429be9cce85d9f3d358c5605cf8c3666f034af42740e94d495e28b9aaa1001ba0c87580300000008006552ab00ab006affffffffd838978e10c0c78f1cd0a0830d6815f38cdcc631408649c32a25170099669daa0000000002acab8984227e804ad268b5b367285edcdf102d382d027789250a2c0641892b480c21bf84e3fb0100000000b518041e023d8653010000000001004040fb0100000000080051ac5200636a6300000000", "52ac", 0, 366357656, "bd0e88829afa6bdc1e192bb8b2d9d14db69298a4d81d464cbd34df0302c634c6"], + ["9ad5ccf503fa4facf6a27b538bc910cce83c118d6dfd82f3fb1b8ae364a1aff4dcefabd38f03000000096365655263ac655300807c48130c5937190a996105a69a8eba585e0bd32fadfc57d24029cbed6446d30ebc1f100100000004000053650f0ccfca1356768df7f9210cbf078a53c72e0712736d9a7a238e0115faac0ca383f219d0010000000600ab536552002799982b0221b8280000000000000c41320000000000086552ac6365636a6595f233a3", "6a5152", 2, 553208588, "f99c29a79f1d73d2a69c59abbb5798e987639e36d4c44125d8dc78a94ddcfb13"], + ["669538a204047214ce058aed6a07ca5ad4866c821c41ac1642c7d63ed0054f84677077a84f030000000853abacab6a655353ffffffff70c2a071c115282924e3cb678b13800c1d29b6a028b3c989a598c491bc7c76c5030000000752ac52ac5163ac80420e8a6e43d39af0163271580df6b936237f15de998e9589ec39fe717553d415ac02a4030000000463635153184ad8a5a4e69a8969f71288c331aff3c2b7d1b677d2ebafad47234840454b624bf7ac1d03000000056a63abab63df38c24a02fbc63a040000000002ab535ec3dc050000000002536500000000", "635153", 3, -190399351, "9615541884dfb1feeb08073a6a6aa73ef694bc5076e52187fdf4138a369f94d9"], + ["972128b904e7b673517e96e98d80c0c8ceceae76e2f5c126d63da77ffd7893fb53308bb2da0300000006ac6552ab52acffffffff4cac767c797d297c079a93d06dc8569f016b4bf7a7d79b605c526e1d36a40e2202000000095365ab636aac6a6a6a69928d2eddc836133a690cfb72ec2d3115bf50fb3b0d10708fa5d2ebb09b4810c426a1db01000000060052526300001e8e89585da7e77b2dd2e30625887f0660accdf29e53a614d23cf698e6fc8ab03310e87700000000076a520051acac6555231ddb0330ec2d03000000000200abfaf457040000000004ab6a6352bdc42400000000000153d6dd2f04", "", 0, 209234698, "4a92fec1eb03f5bd754ee9bfd70707dc4420cc13737374f4675f48529be518e4"], + ["5374f0c603d727f63006078bd6c3dce48bd5d0a4b6ea00a47e5832292d86af258ea0825c260000000009655353636352526a6af2221067297d42a9f8933dfe07f61a574048ff9d3a44a3535cd8eb7de79fb7c45b6f47320200000003ac006affffffff153d917c447d367e75693c5591e0abf4c94bbdd88a98ab8ad7f75bfe69a08c470200000005ac65516365ffffffff037b5b7b000000000001515dc4d904000000000004bb26010000000004536a6aac00000000", "516552516352ac", 2, 328538756, "8bb7a0129eaf4b8fc23e911c531b9b7637a21ab11a246352c6c053ff6e93fcb6"], + ["c441132102cc82101b6f31c1025066ab089f28108c95f18fa67db179610247086350c163bd010000000651525263ab00ffffffff9b8d56b1f16746f075249b215bdb3516cbbe190fef6292c75b1ad8a8988897c3000000000751ab6553abab00ffffffff02f9078b000000000009ab0053ac51ac00ab51c0422105000000000651006563525200000000", "ac51", 0, -197051790, "55acd8293ed0be6792150a3d7ced6c5ccd153ca7daf09cee035c1b0dac92bb96"], + ["8bff9d170419fa6d556c65fa227a185fe066efc1decf8a1c490bc5cbb9f742d68da2ab7f320100000007ab000053525365a7a43a80ab9593b9e8b6130a7849603b14b5c9397a190008d89d362250c3a2257504eb810200000007acabacac00ab51ee141be418f003e75b127fd3883dbf4e8c3f6cd05ca4afcaac52edd25dd3027ae70a62a00000000008ac52526a5200536affffffffb8058f4e1d7f220a1d1fa17e96d81dfb9a304a2de4e004250c9a576963a586ae0300000005abacac5363b9bc856c039c01d804000000000951656aac53005365acb0724e00000000000565abab63acea7c7a0000000000036a00ac00000000", "6565", 1, -1349282084, "2b822737c2affeefae13451d7c9db22ff98e06490005aba57013f6b9bbc97250"], + ["0e1633b4041c50f656e882a53fde964e7f0c853b0ada0964fc89ae124a2b7ffc5bc97ea6230100000006ac6aacacabacffffffff2e35f4dfcad2d53ea1c8ada8041d13ea6c65880860d96a14835b025f76b1fbd9000000000351515121270867ef6bf63a91adbaf790a43465c61a096acc5a776b8e5215d4e5cd1492e611f761000000000600ac6aab5265ffffffff63b5fc39bcac83ca80ac36124abafc5caee608f9f63a12479b68473bd4bae769000000000965ac52acac5263acabffffffff0163153e020000000008ab005165ab65515300000000", "6a6aac00", 0, -968477862, "20732d5073805419f275c53784e78db45e53332ee618a9fcf60a3417a6e2ca69"], + ["2b052c24022369e956a8d318e38780ef73b487ba6a8f674a56bdb80a9a63634c6110fb5154010000000251acffffffff48fe138fb7fdaa014d67044bc05940f4127e70c113c6744fbd13f8d51d45143e01000000005710db3804e01aa9030000000008acac6a516a5152abfd55aa01000000000751ab510000ac636d6026010000000000b97da9000000000000fddf3b53", "006552", 0, 595461670, "685d67d84755906d67a007a7d4fa311519467b9bdc6a351913246a41e082a29f"], + ["7888b71403f6d522e414d4ca2e12786247acf3e78f1918f6d727d081a79813d129ee8befce0100000009ab516a6353ab6365abffffffff4a882791bf6400fda7a8209fb2c83c6eef51831bdf0f5dacde648859090797ec030000000153ffffffffbb08957d59fa15303b681bad19ccf670d7d913697a2f4f51584bf85fcf91f1f30200000008526565ac52ac63acffffffff0227c0e8050000000001ac361dc801000000000800515165ab00ab0000000000", "656a", 2, 1869281295, "f43378a0b7822ad672773944884e866d7a46579ee34f9afc17b20afc1f6cf197"], + ["cc4dda57047bd0ca6806243a6a4b108f7ced43d8042a1acaa28083c9160911cf47eab910c40200000007526a0000ab6a63e4154e581fcf52567836c9a455e8b41b162a78c85906ccc1c2b2b300b4c69caaaa2ba0230300000008ab5152ac5100ab65ffffffff69696b523ed4bd41ecd4d65b4af73c9cf77edf0e066138712a8e60a04614ea1c0300000004ab6a000016c9045c7df7836e05ac4b2e397e2dd72a5708f4a8bf6d2bc36adc5af3cacefcf074b8b403000000065352ac5252acffffffff01d7e380050000000000cf4e699a", "525163656351", 1, -776533694, "ff18c5bffd086e00917c2234f880034d24e7ea2d1e1933a28973d134ca9e35d2"], + ["b7877f82019c832707a60cf14fba44cfa254d787501fdd676bd58c744f6e951dbba0b3b77f0200000009ac515263ac53525300a5a36e500148f89c0500000000085265ac6a6a65acab00000000", "6563", 0, -1785108415, "cb6e4322955af12eb29613c70e1a00ddbb559c887ba844df0bcdebed736dffbd"], + ["aeb14046045a28cc59f244c2347134d3434faaf980961019a084f7547218785a2bd03916f3000000000165f852e6104304955bda5fa0b75826ee176211acc4a78209816bbb4419feff984377b2352200000000003a94a5032df1e0d60390715b4b188c330e4bb7b995f07cdef11ced9d17ee0f60bb7ffc8e0100000002516513e343a5c1dc1c80cd4561e9dddad22391a2dbf9c8d2b6048e519343ca1925a9c6f0800a020000000665516365ac513180144a0290db27000000000006ab655151ab5138b187010000000007ab5363abac516a9e5cd98a", "53ac", 0, 478591320, "e8d89a302ae626898d4775d103867a8d9e81f4fd387af07212adab99946311ef"], + ["57a5a04c0278c8c8e243d2df4bb716f81d41ac41e2df153e7096f5682380c4f441888d9d260300000004ab63ab6afdbe4203525dff42a7b1e628fe22bccaa5edbb34d8ab02faff198e085580ea5fcdb0c61b0000000002ac6affffffff03375e6c05000000000663ab516a6a513cb6260400000000007ca328020000000006516a636a52ab94701cc7", "0053ac5152", 0, -550925626, "b7ca991ab2e20d0158168df2d3dd842a57ab4a3b67cca8f45b07c4b7d1d11126"], + ["7e27c42d0279c1a05eeb9b9faedcc9be0cab6303bde351a19e5cbb26dd0d594b9d74f40d2b020000000200518c8689a08a01e862d5c4dcb294a2331912ff11c13785be7dce3092f154a005624970f84e0200000000500cf5a601e74c1f0000000000076aab52636a6a5200000000", "6500006a5351", 0, 449533391, "535ba819d74770d4d613ee19369001576f98837e18e1777b8246238ff2381dd0"], + ["2b3470dd028083910117f86614cdcfb459ee56d876572510be4df24c72e8f58c70d5f5948b03000000066aab65635265da2c3aac9d42c9baafd4b655c2f3efc181784d8cba5418e053482132ee798408ba43ccf90300000000ffffffff047dda4703000000000765516a52ac53009384a603000000000651636a63ab6a8cf57a03000000000352ab6a8cf6a405000000000952636a6a6565525100661e09cb", "ac520063ac6a6a52", 1, 1405647183, "9b360c3310d55c845ef537125662b9fe56840c72136891274e9fedfef56f9bb5"], + ["3a5644a9010f199f253f858d65782d3caec0ac64c3262b56893022b9796086275c9d4d097b02000000009d168f7603a67b30050000000007ac51536a0053acd9d88a050000000007655363535263ab3cf1f403000000000352ac6a00000000", "005363536565acac6a", 0, -1383947195, "6390ab0963cf611e0cea35a71dc958b494b084e6fd71d22217fdc5524787ade6"], + ["bda1ff6804a3c228b7a12799a4c20917301dd501c67847d35da497533a606701ad31bf9d5e0300000001ac16a6c5d03cf516cd7364e4cbbf5aeccd62f8fd03cb6675883a0636a7daeb650423cb1291010000000500656553ac4a63c30b6a835606909c9efbae1b2597e9db020c5ecfc0642da6dc583fba4e84167539a8020000000865525353515200acffffffff990807720a5803c305b7da08a9f24b92abe343c42ac9e917a84e1f335aad785d00000000026a52ffffffff04981f20030000000001ab8c762200000000000253ab690b9605000000000151ce88b301000000000753526a6a51006500000000", "000052ac52530000", 1, -1809193140, "5299b0fb7fc16f40a5d6b337e71fcd1eb04d2600aefd22c06fe9c71fe0b0ba54"], + ["db4904e6026b6dd8d898f278c6428a176410d1ffbde75a4fa37cda12263108ccd4ca6137440100000007656a0000515263ffffffff1db7d5005c1c40da0ed17b74cf6b2a6ee2c33c9e0bacda76c0da2017dcac2fc70200000004abab6a53ffffffff0454cf2103000000000153463aef000000000009ab6a630065ab52636387e0ed050000000000e8d16f05000000000352ac63e4521b22", "", 1, 1027042424, "48315a95e49277ab6a2d561ee4626820b7bab919eea372b6bf4e9931ab221d04"], + ["dca31ad10461ead74751e83d9a81dcee08db778d3d79ad9a6d079cfdb93919ac1b0b61871102000000086500525365ab51ac7f7e9aed78e1ef8d213d40a1c50145403d196019985c837ffe83836222fe3e5955e177e70100000006525152525300ffffffff5e98482883cc08a6fe946f674cca479822f0576a43bf4113de9cbf414ca628060100000006ac53516a5253ffffffff07490b0b898198ec16c23b75d606e14fa16aa3107ef9818594f72d5776805ec502000000036a0052ffffffff01932a2803000000000865ab6551ac6a516a2687aa06", "635300ac", 2, -1880362326, "74d6a2fa7866fd8b74b2e34693e2d6fd690410384b7afdcd6461b1ae71d265ce"], + ["e14e1a9f0442ab44dfc5f6d945ad1ff8a376bc966aad5515421e96ddbe49e529614995cafc03000000055165515165fffffffff97582b8290e5a5cfeb2b0f018882dbe1b43f60b7f45e4dd21dbd3a8b0cfca3b0200000000daa267726fe075db282d694b9fee7d6216d17a8c1f00b2229085495c5dc5b260c8f8cd5d000000000363ac6affffffffaab083d22d0465471c896a438c6ac3abf4d383ae79420617a8e0ba8b9baa872b010000000963526563ac5363ababd948b5ce022113440200000000076a636552006a53229017040000000000e6f62ac8", "526353636a65", 3, -485265025, "1bc8ad76f9b7c366c5d052dc479d6a8a2015566d3a42e93ab12f727692c89d65"], + ["69df842a04c1410bfca10896467ce664cfa31c681a5dac10106b34d4b9d4d6d0dc1eac01c1000000000551536a5165269835ca4ad7268667b16d0a2df154ec81e304290d5ed69e0069b43f8c89e673328005e200000000076a5153006aacabffffffffc9314bd80b176488f3d634360fcba90c3a659e74a52e100ac91d3897072e3509010000000765abac51636363ffffffff0e0768b13f10f0fbd2fa3f68e4b4841809b3b5ba0e53987c3aaffcf09eee12bf0300000008ac535263526a53ac514f4c2402da8fab0400000000001ef15201000000000451526a52d0ec9aca", "525365ac52", 1, 313967049, "a72a760b361af41832d2c667c7488dc9702091918d11e344afc234a4aea3ec44"], + ["e4fec9f10378a95199c1dd23c6228732c9de0d7997bf1c83918a5cfd36012476c0c3cba24002000000085165536500ac0000ad08ab93fb49d77d12a7ccdbb596bc5110876451b53a79fdce43104ff1c316ad63501de801000000046a6352ab76af9908463444aeecd32516a04dd5803e02680ed7f16307242a794024d93287595250f4000000000089807279041a82e603000000000200521429100200000000055253636a63f20b940400000000004049ed04000000000500ab5265ab43dfaf7d", "6563526aac", 2, -1923470368, "32f3c012eca9a823bebb9b282240aec40ca65df9f38da43b1dcfa0cac0c0df7e"], + ["4000d3600100b7a3ff5b41ec8d6ccdc8b2775ad034765bad505192f05d1f55d2bc39d0cbe10100000007ab5165ac6a5163ffffffff034949150100000000026a6a92c9f6000000000008ab6553ab6aab635200e697040000000007636a5353525365237ae7d2", "52000063", 0, -880046683, "c76146f68f43037289aaeb2bacf47408cddc0fb326b350eb4f5ef6f0f8564793"], + ["eabc0aa701fe489c0e4e6222d72b52f083166b49d63ad1410fb98caed027b6a71c02ab830c03000000075253ab63530065ffffffff01a5dc0b05000000000253533e820177", "", 0, 954499283, "1d849b92eedb9bf26bd4ced52ce9cb0595164295b0526842ab1096001fcd31b1"], + ["d48d55d304aad0139783b44789a771539d052db565379f668def5084daba0dfd348f7dcf6b00000000006826f59e5ffba0dd0ccbac89c1e2d69a346531d7f995dea2ca6d7e6d9225d81aec257c6003000000096a655200ac656552acffffffffa188ffbd5365cae844c8e0dea6213c4d1b2407274ae287b769ab0bf293e049eb0300000005ac6a6aab51ad1c407c5b116ca8f65ed496b476183f85f072c5f8a0193a4273e2015b1cc288bf03e9e2030000000252abffffffff04076f44040000000006655353abab53be6500050000000003ac65ac3c15040500000000095100ab536353516a52ed3aba04000000000900ac53ab53636aabac00000000", "5253526563acac", 2, -1506108646, "bbee17c8582514744bab5df50012c94b0db4aff5984d2e13a8d09421674404e2"], + ["9746f45b039bfe723258fdb6be77eb85917af808211eb9d43b15475ee0b01253d33fc3bfc502000000065163006a655312b12562dc9c54e11299210266428632a7d0ee31d04dfc7375dcad2da6e9c11947ced0e000000000009074095a5ac4df057554566dd04740c61490e1d3826000ad9d8f777a93373c8dddc4918a00000000025351ffffffff01287564030000000004636a00ab00000000", "52", 2, -1380411075, "84af1623366c4db68d81f452b86346832344734492b9c23fbb89015e516c60b2"], + ["df0a32ae01c4672fd1abd0b2623aae0a1a8256028df57e532f9a472d1a9ceb194267b6ee190200000009536a6a51516a525251b545f9e803469a2302000000000465526500810631040000000000441f5b050000000006530051006aaceb183c76", "536a635252ac6a", 0, 1601138113, "9a0435996cc58bdba09643927fe48c1fc908d491a050abbef8daec87f323c58f"], + ["b1c0b71804dff30812b92eefb533ac77c4b9fdb9ab2f77120a76128d7da43ad70c20bbfb990200000002536392693e6001bc59411aebf15a3dc62a6566ec71a302141b0c730a3ecc8de5d76538b30f55010000000665535252ac514b740c6271fb9fe69fdf82bf98b459a7faa8a3b62f3af34943ad55df4881e0d93d3ce0ac0200000000c4158866eb9fb73da252102d1e64a3ce611b52e873533be43e6883137d0aaa0f63966f060000000001abffffffff04a605b604000000000851006a656a630052f49a0300000000000252515a94e1050000000009abac65ab0052abab00fd8dd002000000000651535163526a2566852d", "ac5363", 0, -1718831517, "b0dc030661783dd9939e4bf1a6dfcba809da2017e1b315a6312e5942d714cf05"], + ["3657e4260304ccdc19936e47bdf058d36167ee3d4eb145c52b224eff04c9eb5d1b4e434dfc0000000001ab58aefe57707c66328d3cceef2e6f56ab6b7465e587410c5f73555a513ace2b232793a74400000000036a006522e69d3a785b61ad41a635d59b3a06b2780a92173f85f8ed428491d0aaa436619baa9c4501000000046351abab2609629902eb7793050000000000a1b967040000000003525353a34d6192", "516a", 0, -1761874713, "0a2ff41f6d155d8d0e37cd9438f3b270df9f9214cda8e95c76d5a239ca189df2"], + ["a0eb6dc402994e493c787b45d1f946d267b09c596c5edde043e620ce3d59e95b2b5b93d43002000000096a5252526aac63ab6555694287a279e29ee491c177a801cd685b8744a2eab83824255a3bcd08fc0e3ea13fb8820000000009abab6365ab52ab0063ffffffff029e424a040000000008acab53ab516a636a23830f0400000000016adf49c1f9", "ac0065ac6500005252", 1, 669294500, "e05e3d383631a7ed1b78210c13c2eb26564e5577db7ddfcea2583c7c014091d4"], + ["6e67c0d3027701ef71082204c85ed63c700ef1400c65efb62ce3580d187fb348376a23e9710200000001655b91369d3155ba916a0bc6fe4f5d94cad461d899bb8aaac3699a755838bfc229d6828920010000000765536353526a52ffffffff04c0c792000000000005650052535372f79e000000000001527fc0ee010000000005ac5300ab65d1b3e902000000000251aba942b278", "6a5151", 0, 1741407676, "e657e2c8ec4ebc769ddd3198a83267b47d4f2a419fc737e813812acefad92ff7"], + ["8f53639901f1d643e01fc631f632b7a16e831d846a0184cdcda289b8fa7767f0c292eb221a00000000046a53abacffffffff037a2daa01000000000553ac6a6a51eac349020000000005ac526552638421b3040000000007006a005100ac63048a1492", "ac65", 0, 1033685559, "da86c260d42a692358f46893d6f91563985d86eeb9ea9e21cd38c2d8ffcfcc4d"], + ["b3cad3a7041c2c17d90a2cd994f6c37307753fa3635e9ef05ab8b1ff121ca11239a0902e700300000009ab635300006aac5163ffffffffcec91722c7468156dce4664f3c783afef147f0e6f80739c83b5f09d5a09a57040200000004516a6552ffffffff969d1c6daf8ef53a70b7cdf1b4102fb3240055a8eaeaed2489617cd84cfd56cf020000000352ab53ffffffff46598b6579494a77b593681c33422a99559b9993d77ca2fa97833508b0c169f80200000009655300655365516351ffffffff04d7ddf800000000000853536a65ac6351ab09f3420300000000056aab65abac33589d04000000000952656a65655151acac944d6f0400000000006a8004ba", "005165", 1, 1035865506, "fe1dc9e8554deecf8f50c417c670b839cc9d650722ebaaf36572418756075d58"], + ["cf781855040a755f5ba85eef93837236b34a5d3daeb2dbbdcf58bb811828d806ed05754ab8010000000351ac53ffffffffda1e264727cf55c67f06ebcc56dfe7fa12ac2a994fecd0180ce09ee15c480f7d00000000096351516a51acac00ab53dd49ff9f334befd6d6f87f1a832cddfd826a90b78fd8cf19a52cb8287788af94e939d6020000000700525251ac526310d54a7e8900ed633f0f6f0841145aae7ee0cbbb1e2a0cae724ee4558dbabfdc58ba6855010000000552536a53abfd1b101102c51f910500000000096300656a525252656a300bee010000000009ac52005263635151abe19235c9", "53005365", 2, 1422854188, "d5981bd4467817c1330da72ddb8760d6c2556cd809264b2d85e6d274609fc3a3"] +] diff --git a/bitcoin/tests/data/lex_combine_psbt_hex b/bitcoin/tests/data/lex_combine_psbt_hex new file mode 100644 index 000000000..9ee710b6a --- /dev/null +++ b/bitcoin/tests/data/lex_combine_psbt_hex @@ -0,0 +1 @@ +70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a0100000000000af00102030405060708090f0102030405060708090a0b0c0d0e0f0af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f0af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f0af00102030405060708100f0102030405060708090a0b0c0d0e0f00 \ No newline at end of file diff --git a/bitcoin/tests/data/lex_psbt_1_hex b/bitcoin/tests/data/lex_psbt_1_hex new file mode 100644 index 000000000..a125c5298 --- /dev/null +++ b/bitcoin/tests/data/lex_psbt_1_hex @@ -0,0 +1 @@ +70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a0100000000000af00102030405060708090f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f00 \ No newline at end of file diff --git a/bitcoin/tests/data/lex_psbt_2_hex b/bitcoin/tests/data/lex_psbt_2_hex new file mode 100644 index 000000000..766c7eee1 --- /dev/null +++ b/bitcoin/tests/data/lex_psbt_2_hex @@ -0,0 +1 @@ +70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a0100000000000af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708100f0102030405060708090a0b0c0d0e0f00 \ No newline at end of file diff --git a/bitcoin/tests/data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw b/bitcoin/tests/data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw new file mode 100644 index 000000000..f195623c3 Binary files /dev/null and b/bitcoin/tests/data/mainnet_block_000000000000000000000c835b2adcaedc20fdf6ee440009c249452c726dafae.raw differ diff --git a/bitcoin/tests/data/merkle_block.hex b/bitcoin/tests/data/merkle_block.hex new file mode 100644 index 000000000..c9a32c9a5 --- /dev/null +++ b/bitcoin/tests/data/merkle_block.hex @@ -0,0 +1 @@ +0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930900000005fac7708a6e81b2a986dea60db2663840ed141130848162eb1bd1dee54f309a1b2ee1e12587e497ada70d9bd10d31e83f0a924825b96cb8d04e8936d793fb60db7ad8b910d0c7ba2369bc7f18bb53d80e1869ba2c32274996cebe1ae264bc0e2289189ff0316cdc10511da71da757e553cada9f3b5b1434f3923673adb57d83caac392c38af156d6fc30b55fad4112df2b95531e68114e9ad10011e72f7b7cfdb025700 \ No newline at end of file diff --git a/bitcoin/tests/data/previous_tx_0_hex b/bitcoin/tests/data/previous_tx_0_hex new file mode 100644 index 000000000..ce2089453 --- /dev/null +++ b/bitcoin/tests/data/previous_tx_0_hex @@ -0,0 +1 @@ +0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000 \ No newline at end of file diff --git a/bitcoin/tests/data/previous_tx_1_hex b/bitcoin/tests/data/previous_tx_1_hex new file mode 100644 index 000000000..9297523e3 --- /dev/null +++ b/bitcoin/tests/data/previous_tx_1_hex @@ -0,0 +1 @@ +0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000 \ No newline at end of file diff --git a/bitcoin/tests/data/psbt1.hex b/bitcoin/tests/data/psbt1.hex new file mode 100644 index 000000000..3bcb9179a --- /dev/null +++ b/bitcoin/tests/data/psbt1.hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/psbt2.hex b/bitcoin/tests/data/psbt2.hex new file mode 100644 index 000000000..47f387017 --- /dev/null +++ b/bitcoin/tests/data/psbt2.hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/psbt_combined.hex b/bitcoin/tests/data/psbt_combined.hex new file mode 100644 index 000000000..47f387017 --- /dev/null +++ b/bitcoin/tests/data/psbt_combined.hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/psbt_fuzz1.hex b/bitcoin/tests/data/psbt_fuzz1.hex new file mode 100644 index 000000000..dd3c9b7ed --- /dev/null +++ b/bitcoin/tests/data/psbt_fuzz1.hex @@ -0,0 +1 @@ +70736274ff01000a000000ff0000000074ff4f010488b21eff02000001004a92244992244902030203030303030303030303030303030303030303030303030303030303030303f4000000000000000a000208ffffffff08080804000000000000000c080808000b0000000000010000 \ No newline at end of file diff --git a/bitcoin/tests/data/psbt_fuzz2.hex b/bitcoin/tests/data/psbt_fuzz2.hex new file mode 100644 index 000000000..8a33cf01c --- /dev/null +++ b/bitcoin/tests/data/psbt_fuzz2.hex @@ -0,0 +1 @@ +70736274ff01000a000000ff0000000074ff4f010488b21eff02000001004a92244992244902030203030303030303030303030303030303030303030303030303030303030303f4000000000000000a000208ffffffff080808040000000000000008000000000000001000 \ No newline at end of file diff --git a/bitcoin/tests/data/serde/README.md b/bitcoin/tests/data/serde/README.md new file mode 100644 index 000000000..4d4a905a6 --- /dev/null +++ b/bitcoin/tests/data/serde/README.md @@ -0,0 +1,11 @@ +# Serialization input/output + +Files here contain hex strings and binary data representing types used for +regression testing. + +- `*_hex`: consensus encoded types represented as hex strings +- `*_ser`: consensus encoded types represented as binary data +- `*_bincode`: types serialized with `serde` as bincode + +We consensus deserialize, `serde` serialize, then check against the expected data +to verify no `serde` regressions have been introduced. diff --git a/bitcoin/tests/data/serde/absolute_lock_time_blocks_bincode b/bitcoin/tests/data/serde/absolute_lock_time_blocks_bincode new file mode 100644 index 000000000..ab7c85f50 Binary files /dev/null and b/bitcoin/tests/data/serde/absolute_lock_time_blocks_bincode differ diff --git a/bitcoin/tests/data/serde/absolute_lock_time_seconds_bincode b/bitcoin/tests/data/serde/absolute_lock_time_seconds_bincode new file mode 100644 index 000000000..0d59b0c9f --- /dev/null +++ b/bitcoin/tests/data/serde/absolute_lock_time_seconds_bincode @@ -0,0 +1 @@ +PÉb \ No newline at end of file diff --git a/bitcoin/tests/data/serde/address_bincode b/bitcoin/tests/data/serde/address_bincode new file mode 100644 index 000000000..5a1c100d3 Binary files /dev/null and b/bitcoin/tests/data/serde/address_bincode differ diff --git a/bitcoin/tests/data/serde/child_number_bincode b/bitcoin/tests/data/serde/child_number_bincode new file mode 100644 index 000000000..c9902e4a9 --- /dev/null +++ b/bitcoin/tests/data/serde/child_number_bincode @@ -0,0 +1 @@ +ï¾­Þ \ No newline at end of file diff --git a/bitcoin/tests/data/serde/control_block_bincode b/bitcoin/tests/data/serde/control_block_bincode new file mode 100644 index 000000000..02f9b8ca7 Binary files /dev/null and b/bitcoin/tests/data/serde/control_block_bincode differ diff --git a/bitcoin/tests/data/serde/control_block_hex b/bitcoin/tests/data/serde/control_block_hex new file mode 100644 index 000000000..b1ddcda5e --- /dev/null +++ b/bitcoin/tests/data/serde/control_block_hex @@ -0,0 +1 @@ +c1a9d6f66cd4b25004f526bfa873e56942f98e8e492bd79ed6532b966104817c2bda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0641e660d1e5392fb79d64838c2b84faf04b7f5f283c9d8bf83e39e177b64372a0cd22eeab7e093873e851e247714eff762d8a30be699ba4456cfe6491b282e193a071350ae099005a5950d74f73ba13077a57bc478007fb0e4d1099ce9cf3d4 diff --git a/bitcoin/tests/data/serde/ecdsa_sig_bincode b/bitcoin/tests/data/serde/ecdsa_sig_bincode new file mode 100644 index 000000000..3136dc701 Binary files /dev/null and b/bitcoin/tests/data/serde/ecdsa_sig_bincode differ diff --git a/bitcoin/tests/data/serde/ecdsa_sig_hex b/bitcoin/tests/data/serde/ecdsa_sig_hex new file mode 100644 index 000000000..a435e3dfc --- /dev/null +++ b/bitcoin/tests/data/serde/ecdsa_sig_hex @@ -0,0 +1 @@ +3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45 diff --git a/bitcoin/tests/data/serde/extended_priv_key b/bitcoin/tests/data/serde/extended_priv_key new file mode 100644 index 000000000..7e84345f6 --- /dev/null +++ b/bitcoin/tests/data/serde/extended_priv_key @@ -0,0 +1 @@ +xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi diff --git a/bitcoin/tests/data/serde/extended_priv_key_bincode b/bitcoin/tests/data/serde/extended_priv_key_bincode new file mode 100644 index 000000000..a4331025e Binary files /dev/null and b/bitcoin/tests/data/serde/extended_priv_key_bincode differ diff --git a/bitcoin/tests/data/serde/extended_pub_key b/bitcoin/tests/data/serde/extended_pub_key new file mode 100644 index 000000000..da2268765 --- /dev/null +++ b/bitcoin/tests/data/serde/extended_pub_key @@ -0,0 +1 @@ +xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8 diff --git a/bitcoin/tests/data/serde/extended_pub_key_bincode b/bitcoin/tests/data/serde/extended_pub_key_bincode new file mode 100644 index 000000000..096623fda Binary files /dev/null and b/bitcoin/tests/data/serde/extended_pub_key_bincode differ diff --git a/bitcoin/tests/data/serde/out_point_bincode b/bitcoin/tests/data/serde/out_point_bincode new file mode 100644 index 000000000..6e8c0a517 Binary files /dev/null and b/bitcoin/tests/data/serde/out_point_bincode differ diff --git a/bitcoin/tests/data/serde/private_key_bincode b/bitcoin/tests/data/serde/private_key_bincode new file mode 100644 index 000000000..827f5d7ff Binary files /dev/null and b/bitcoin/tests/data/serde/private_key_bincode differ diff --git a/bitcoin/tests/data/serde/psbt_base64.json b/bitcoin/tests/data/serde/psbt_base64.json new file mode 100644 index 000000000..d05155177 --- /dev/null +++ b/bitcoin/tests/data/serde/psbt_base64.json @@ -0,0 +1 @@ +"cHNidP8BAFMBAAAAATkUkZZWjQ4TAMqaOkez2dl2+5yBsfd38qS6x8fkjesmAQAAAAD/////AXL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAAAAAE8BBIiyHgAAAAAAAAAAAIc9/4HAL1JWI/0f5RZ+rDpVoEnePTFLtC7iJ//tN9UIAzmjYBMwFZfa70H75ZOgLMUT0LVVJ+wt8QUOLo/0nIXCDN6tvu8AAACAAQAAABD8BXByZWZ4KnRlc3Rfa2V5AwUGBwMJAAEDAwQFAAEAjwEAAAAAAQGJo8ceq00g4Dcbu6TMaY+ilclGOvouOX+FM8y2L5Vn5QEAAAAXFgAUvhjRUqmwEgOdrz2n3k9TNJ7suYX/////AXL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUAAAAAAQEgcv74TiwAAAAXqRQzlyW6Ie/WKsdTqbzQZ9bHpqOdBYciAgM5iA3JI5S3NV49BDn6KDwx3nWQgS6gEcQkXAZ0poXog0cwRAIgT2fir7dhQtRPrliiSV0zo0GdqibNDbjQTzRStjKJrA8CIBB2Kp+2fpTMXK2QJvbcmf9/Bw9CeNMPvH0Mhp3TjH/nAQEDBIMAAAABBAFRIgYDOYgNySOUtzVePQQ5+ig8Md51kIEuoBHEJFwGdKaF6IMM3q2+7wAAAIABAAAAAQgGAgIBAwEFFQoYn3yLGjhv/o7tkbODDHp7zR53jAIBAiELoShx/uIQ+4YZKR6uoZRYHL0lMeSyN1nSJfaAaSP2MiICAQIVDBXMSeGRy8Ug2RlEYApct3r2qjKRAgECIQ12pWrO2RXSUT3NhMLDeLLoqlzWMrW3HKLyrFsOOmSb2wIBAhD8BXByZWZ4KnRlc3Rfa2V5AwUGBwMJAAEDAwQFACICAzmIDckjlLc1Xj0EOfooPDHedZCBLqARxCRcBnSmheiDDN6tvu8AAACAAQAAABD8BXByZWZ4KnRlc3Rfa2V5AwUGBwMJAAEDAwQFAA==" \ No newline at end of file diff --git a/bitcoin/tests/data/serde/psbt_bincode b/bitcoin/tests/data/serde/psbt_bincode new file mode 100644 index 000000000..0423835c0 Binary files /dev/null and b/bitcoin/tests/data/serde/psbt_bincode differ diff --git a/bitcoin/tests/data/serde/public_key_bincode b/bitcoin/tests/data/serde/public_key_bincode new file mode 100644 index 000000000..472a282c1 Binary files /dev/null and b/bitcoin/tests/data/serde/public_key_bincode differ diff --git a/bitcoin/tests/data/serde/public_key_hex b/bitcoin/tests/data/serde/public_key_hex new file mode 100644 index 000000000..4c6541bcd --- /dev/null +++ b/bitcoin/tests/data/serde/public_key_hex @@ -0,0 +1 @@ +042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133 diff --git a/bitcoin/tests/data/serde/relative_lock_time_blocks_bincode b/bitcoin/tests/data/serde/relative_lock_time_blocks_bincode new file mode 100644 index 000000000..167e25d50 Binary files /dev/null and b/bitcoin/tests/data/serde/relative_lock_time_blocks_bincode differ diff --git a/bitcoin/tests/data/serde/relative_lock_time_seconds_bincode b/bitcoin/tests/data/serde/relative_lock_time_seconds_bincode new file mode 100644 index 000000000..53442e8bb Binary files /dev/null and b/bitcoin/tests/data/serde/relative_lock_time_seconds_bincode differ diff --git a/bitcoin/tests/data/serde/script_bincode b/bitcoin/tests/data/serde/script_bincode new file mode 100644 index 000000000..5bf932f61 Binary files /dev/null and b/bitcoin/tests/data/serde/script_bincode differ diff --git a/bitcoin/tests/data/serde/taproot_sig_bincode b/bitcoin/tests/data/serde/taproot_sig_bincode new file mode 100644 index 000000000..01f28cee7 Binary files /dev/null and b/bitcoin/tests/data/serde/taproot_sig_bincode differ diff --git a/bitcoin/tests/data/serde/taproot_sig_hex b/bitcoin/tests/data/serde/taproot_sig_hex new file mode 100644 index 000000000..9ab24dd5b --- /dev/null +++ b/bitcoin/tests/data/serde/taproot_sig_hex @@ -0,0 +1 @@ +6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8 diff --git a/bitcoin/tests/data/serde/taptree_bincode b/bitcoin/tests/data/serde/taptree_bincode new file mode 100644 index 000000000..51979bfa8 Binary files /dev/null and b/bitcoin/tests/data/serde/taptree_bincode differ diff --git a/bitcoin/tests/data/serde/transaction_ser b/bitcoin/tests/data/serde/transaction_ser new file mode 100644 index 000000000..b3112cd15 Binary files /dev/null and b/bitcoin/tests/data/serde/transaction_ser differ diff --git a/bitcoin/tests/data/serde/txin_ser b/bitcoin/tests/data/serde/txin_ser new file mode 100644 index 000000000..f2c5f3a6d Binary files /dev/null and b/bitcoin/tests/data/serde/txin_ser differ diff --git a/bitcoin/tests/data/serde/u256_bincode b/bitcoin/tests/data/serde/u256_bincode new file mode 100644 index 000000000..e91e8a928 Binary files /dev/null and b/bitcoin/tests/data/serde/u256_bincode differ diff --git a/bitcoin/tests/data/serde/uint128_bincode b/bitcoin/tests/data/serde/uint128_bincode new file mode 100644 index 000000000..24087dd3c Binary files /dev/null and b/bitcoin/tests/data/serde/uint128_bincode differ diff --git a/bitcoin/tests/data/serde/uint256_bincode b/bitcoin/tests/data/serde/uint256_bincode new file mode 100644 index 000000000..6fe1e0320 Binary files /dev/null and b/bitcoin/tests/data/serde/uint256_bincode differ diff --git a/bitcoin/tests/data/serde/witness_bincode b/bitcoin/tests/data/serde/witness_bincode new file mode 100644 index 000000000..e7d43be0f Binary files /dev/null and b/bitcoin/tests/data/serde/witness_bincode differ diff --git a/bitcoin/tests/data/sign_1_psbt_hex b/bitcoin/tests/data/sign_1_psbt_hex new file mode 100644 index 000000000..3bcb9179a --- /dev/null +++ b/bitcoin/tests/data/sign_1_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/sign_2_psbt_hex b/bitcoin/tests/data/sign_2_psbt_hex new file mode 100644 index 000000000..70231338d --- /dev/null +++ b/bitcoin/tests/data/sign_2_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw b/bitcoin/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw new file mode 100644 index 000000000..45376bad3 Binary files /dev/null and b/bitcoin/tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw differ diff --git a/bitcoin/tests/data/update_1_psbt_hex b/bitcoin/tests/data/update_1_psbt_hex new file mode 100644 index 000000000..705d70d04 --- /dev/null +++ b/bitcoin/tests/data/update_1_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88701042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/data/update_2_psbt_hex b/bitcoin/tests/data/update_2_psbt_hex new file mode 100644 index 000000000..31fbd54f7 --- /dev/null +++ b/bitcoin/tests/data/update_2_psbt_hex @@ -0,0 +1 @@ +70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000 \ No newline at end of file diff --git a/bitcoin/tests/network.rs b/bitcoin/tests/network.rs new file mode 100644 index 000000000..2b2727217 --- /dev/null +++ b/bitcoin/tests/network.rs @@ -0,0 +1,65 @@ +//! Tests what a user can do when pattern matching on `Network` and associated types. + +use bitcoin::network::{Network, NetworkKind, TestnetVersion}; + +#[test] +fn can_match_exhaustively_on_network() { + // Returns true if `n` is mainnet. + fn is_mainnet(n: Network) -> bool { matches!(n, Network::Bitcoin) } + + assert!(is_mainnet(Network::Bitcoin)); +} + +#[test] +fn can_match_exhaustively_on_testnet() { + // Returns true if `n` is any testnet. + fn is_testnet(n: Network) -> bool { matches!(n, Network::Testnet(_)) } + + assert!(is_testnet(Network::Testnet(TestnetVersion::V3))); +} + +#[test] +fn can_use_network_kind() { + // Returns true if `n` is any mainnet. + fn is_mainnet(n: Network) -> bool { NetworkKind::from(n).is_mainnet() } + + // Returns true if `n` is a any testnet. + fn is_testnet(n: Network) -> bool { !NetworkKind::from(n).is_mainnet() } + + assert!(is_mainnet(Network::Bitcoin)); + assert!(!is_testnet(Network::Bitcoin)); + + assert!(is_testnet(Network::Testnet(TestnetVersion::V3))); + assert!(!is_mainnet(Network::Testnet(TestnetVersion::V3))); +} + +#[test] +fn can_not_match_exhaustively_on_testnet_version() { + // Returns true if `n` is testnet version 3. + fn is_testnet_v3(n: Network) -> bool { + match n { + Network::Testnet(TestnetVersion::V3) => true, + Network::Testnet(TestnetVersion::V4) => false, + // Catchall because of `non_exhaustive` attribute. + Network::Testnet(_) => false, + _ => false, + } + } + + assert!(is_testnet_v3(Network::Testnet(TestnetVersion::V3))); +} + +#[test] +fn can_match_on_testnet_version_3_only() { + // Returns true if `n` is testnet version 3. + fn is_testnet_v3(n: Network) -> bool { + match n { + Network::Testnet(TestnetVersion::V3) => true, + // Catchall because its logically correct to do so. + Network::Testnet(_) => false, + _ => false, + } + } + + assert!(is_testnet_v3(Network::Testnet(TestnetVersion::V3))); +} diff --git a/bitcoin/tests/psbt-sign-taproot.rs b/bitcoin/tests/psbt-sign-taproot.rs new file mode 100644 index 000000000..bd21a112d --- /dev/null +++ b/bitcoin/tests/psbt-sign-taproot.rs @@ -0,0 +1,356 @@ +//! This test is excluded when the `rand` feature is enabled because Schnorr signatures use +//! auxiliary randomness, making them non-deterministic and incompatible with hardcoded test vectors. +#![cfg(all(feature = "std", not(feature = "rand")))] + +use std::collections::BTreeMap; + +use bitcoin::bip32::{DerivationPath, Fingerprint}; +use bitcoin::consensus::encode::serialize_hex; +use bitcoin::opcodes::all::OP_CHECKSIG; +use bitcoin::psbt::{GetKey, Input, KeyRequest, PsbtSighashType, SignError}; +use bitcoin::script::TapScriptExt as _; +use bitcoin::taproot::{LeafVersion, TaprootBuilder, TaprootSpendInfo}; +use bitcoin::transaction::Version; +use bitcoin::{ + absolute, script, Address, Amount, Network, OutPoint, PrivateKey, Psbt, ScriptSigBuf, Sequence, + TapScriptBuf, Transaction, TxIn, TxOut, Witness, XOnlyPublicKey, +}; +use secp256k1::Keypair; + +#[test] +fn psbt_sign_taproot() { + struct Keystore { + sk: PrivateKey, + mfp: Fingerprint, + } + + impl GetKey for Keystore { + type Error = SignError; + fn get_key( + &self, + key_request: &KeyRequest, + ) -> Result, Self::Error> { + match key_request { + KeyRequest::Bip32((mfp, _)) => + if *mfp == self.mfp { + Ok(Some(self.sk)) + } else { + Err(SignError::KeyNotFound) + }, + _ => Err(SignError::KeyNotFound), + } + } + } + + let sk_path = [ + ("dff1c8c2c016a572914b4c5adb8791d62b4768ae9d0a61be8ab94cf5038d7d90", "m/86'/1'/0'/0/0"), + ("1ede31b0e7e47c2afc65ffd158b1b1b9d3b752bba8fd117dc8b9e944a390e8d9", "m/86'/1'/0'/0/1"), + ("1fb777f1a6fb9b76724551f8bc8ad91b77f33b8c456d65d746035391d724922a", "m/86'/1'/0'/0/2"), + ]; + let mfp = "73c5da0a"; + + // + // Step 0: Create P2TR address. + // + + // Create three basic scripts to test script path spend. + let script1 = create_basic_single_sig_script(sk_path[0].0); // m/86'/1'/0'/0/0 + let script2 = create_basic_single_sig_script(sk_path[1].0); // m/86'/1'/0'/0/1 + let script3 = create_basic_single_sig_script(sk_path[2].0); // m/86'/1'/0'/0/2 + + // Just use one of the secret keys for the key path spend. + let kp = sk_path[2].0.parse::().expect("failed to create keypair"); + + let internal_key = kp.x_only_public_key().0; // Ignore the parity. + + let tree = + create_taproot_tree(script1, script2.clone(), script3, internal_key); + + let address = create_p2tr_address(tree.clone()); + assert_eq!( + "tb1pytee2mxz0f4fkrsqqws2lsgnkp8nrw2atjkjy2n9gahggsphr0gszaxxmv", + address.to_string() + ); + + // m/86'/1'/0'/0/7 + let to_address = "tb1pyfv094rr0vk28lf8v9yx3veaacdzg26ztqk4ga84zucqqhafnn5q9my9rz"; + let to_address = to_address.parse::>().unwrap().assume_checked(); + + // key path spend + { + // + // Step 1: create psbt for key path spend. + // + let mut psbt_key_path_spend = + create_psbt_for_taproot_key_path_spend(address, to_address, tree.clone()); + + // + // Step 2: sign psbt. + // + let keystore = Keystore { + mfp: mfp.parse::().unwrap(), + sk: PrivateKey::new(kp.secret_key(), Network::Testnet(bitcoin::TestnetVersion::V3)), + }; + let _ = psbt_key_path_spend.sign(&keystore); + + let sig = "92864dc9e56b6260ecbd54ec16b94bb597a2e6be7cca0de89d75e17921e0e1528cba32dd04217175c237e1835b5db1c8b384401718514f9443dce933c6ba9c87"; + assert_eq!(sig, psbt_key_path_spend.inputs[0].tap_key_sig.unwrap().signature.to_string()); + + // + // Step 3: finalize psbt. + // + let final_psbt = finalize_psbt_for_key_path_spend(psbt_key_path_spend); + let tx = final_psbt.extract_tx().unwrap(); + + let tx_id = "5306516f2032d9f34c9f2f6d2b1b8ad2486ef1ba196d8d8d780e59773e48ad6d"; + assert_eq!(tx_id, tx.compute_txid().to_string()); + + let tx_bytes = "020000000001013aee4d6b51da574900e56d173041115bd1e1d01d4697a845784cf716a10c98060000000000ffffffff0100190000000000002251202258f2d4637b2ca3fd27614868b33dee1a242b42582d5474f51730005fa99ce8014092864dc9e56b6260ecbd54ec16b94bb597a2e6be7cca0de89d75e17921e0e1528cba32dd04217175c237e1835b5db1c8b384401718514f9443dce933c6ba9c8700000000"; + let tx_hex = serialize_hex(&tx); + assert_eq!(tx_bytes, tx_hex); + } + + // script path spend + { + // use private key of path "m/86'/1'/0'/0/1" as signing key + let kp = sk_path[1].0.parse::().expect("failed to create keypair"); + let x_only_pubkey = kp.x_only_public_key().0; + let signing_key_path = sk_path[1].1; + + let keystore = Keystore { + mfp: mfp.parse::().unwrap(), + sk: PrivateKey::new(kp.secret_key(), Network::Testnet(bitcoin::TestnetVersion::V3)), + }; + + // + // Step 1: create psbt for script path spend. + // + let mut psbt_script_path_spend = create_psbt_for_taproot_script_path_spend( + address, + to_address, + tree, + x_only_pubkey, + signing_key_path, + script2.clone(), + ); + + // + // Step 2: sign psbt. + // + let _ = psbt_script_path_spend.sign(&keystore); + + let sig = "9c1466e1631a58c55fcb8642ce5f7896314f4b565d92c5c80b17aa9abf56d22e0b5e5dcbcfe836bbd7d409491f58aa9e1f68a491ef8f05eef62fb50ffac85727"; + assert_eq!( + sig, + psbt_script_path_spend.inputs[0] + .tap_script_sigs + .get(&(x_only_pubkey.into(), script2.tapscript_leaf_hash())) + .unwrap() + .signature + .to_string() + ); + + // + // Step 3: finalize psbt. + // + let final_psbt = finalize_psbt_for_script_path_spend(psbt_script_path_spend); + let tx = final_psbt.extract_tx().unwrap(); + + let tx_id = "a51f723beffc810248809355ba9c9e4b39c6e55c08429f0aeaa79b73f18bc2a6"; + assert_eq!(tx_id, tx.compute_txid().to_string()); + + let tx_hex = serialize_hex(&tx); + let tx_bytes = "0200000000010176a3c94a6b21d742e8ca192130ad10fdfc4c83510cb6baba8572a5fc70677c9d0000000000ffffffff0170170000000000002251202258f2d4637b2ca3fd27614868b33dee1a242b42582d5474f51730005fa99ce803419c1466e1631a58c55fcb8642ce5f7896314f4b565d92c5c80b17aa9abf56d22e0b5e5dcbcfe836bbd7d409491f58aa9e1f68a491ef8f05eef62fb50ffac857270122203058679f6d60b87ef921d98a2a9a1f1e0779dae27bedbd1cdb2f147a07835ac9ac61c1b68df382cad577d8304d5a8e640c3cb42d77c10016ab754caa4d6e68b6cb296d9b9d92a717ebeba858f75182936f0da5a7aecc434b0eebb2dc8a6af5409422ccf87f124e735a592a8ff390a68f6f05469ba8422e246dc78b0b57cd1576ffa98c00000000"; + assert_eq!(tx_bytes, tx_hex); + } +} + +fn create_basic_single_sig_script(sk: &str) -> TapScriptBuf { + let kp = sk.parse::().expect("failed to create keypair"); + let x_only_pubkey = kp.x_only_public_key().0; + script::Builder::new() + .push_slice(x_only_pubkey.serialize()) + .push_opcode(OP_CHECKSIG) + .into_script() +} + +fn create_taproot_tree>( + script1: TapScriptBuf, + script2: TapScriptBuf, + script3: TapScriptBuf, + internal_key: K, +) -> TaprootSpendInfo { + let internal_key = internal_key.into(); + let builder = TaprootBuilder::new(); + let builder = builder.add_leaf(2, script1).unwrap(); + let builder = builder.add_leaf(2, script2).unwrap(); + let builder = builder.add_leaf(1, script3).unwrap(); + builder.finalize(internal_key).unwrap() +} + +fn create_p2tr_address(tree: TaprootSpendInfo) -> Address { + let output_key = tree.output_key(); + Address::p2tr_tweaked(output_key, Network::Testnet(bitcoin::TestnetVersion::V3)) +} + +fn create_psbt_for_taproot_key_path_spend( + from_address: Address, + to_address: Address, + tree: TaprootSpendInfo, +) -> Psbt { + let send_amount = 6400; + let out_puts = vec![TxOut { + amount: Amount::from_sat(send_amount).unwrap(), + script_pubkey: to_address.script_pubkey(), + }]; + let prev_tx_id = "06980ca116f74c7845a897461dd0e1d15b114130176de5004957da516b4dee3a"; + + let transaction = Transaction { + version: Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { txid: prev_tx_id.parse().unwrap(), vout: 0 }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence(0xFFFFFFFF), // Ignore nSequence. + witness: Witness::default(), + }], + outputs: out_puts, + }; + + let mut psbt = Psbt::from_unsigned_tx(transaction).unwrap(); + + let mfp = "73c5da0a"; + let internal_key_path = "m/86'/1'/0'/0/2"; + + let mut origins = BTreeMap::new(); + origins.insert( + tree.internal_key(), + ( + vec![], + ( + mfp.parse::().unwrap(), + internal_key_path.parse::().unwrap(), + ), + ), + ); + + let utxo_amount = 6588; + let mut input = Input { + witness_utxo: { + let script_pubkey = from_address.script_pubkey(); + Some(TxOut { amount: Amount::from_sat(utxo_amount).unwrap(), script_pubkey }) + }, + tap_key_origins: origins, + ..Default::default() + }; + let ty = "SIGHASH_DEFAULT".parse::().unwrap(); + input.sighash_type = Some(ty); + input.tap_internal_key = Some(tree.internal_key()); + input.tap_merkle_root = tree.merkle_root(); + psbt.inputs = vec![input]; + psbt +} + +fn finalize_psbt_for_key_path_spend(mut psbt: Psbt) -> Psbt { + psbt.inputs.iter_mut().for_each(|input| { + let mut script_witness: Witness = Witness::new(); + script_witness.push(input.tap_key_sig.unwrap().to_vec()); + input.final_script_witness = Some(script_witness); + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + }); + psbt +} + +fn create_psbt_for_taproot_script_path_spend>( + from_address: Address, + to_address: Address, + tree: TaprootSpendInfo, + x_only_pubkey_of_signing_key: K, + signing_key_path: &str, + use_script: TapScriptBuf, +) -> Psbt { + let x_only_pubkey_of_signing_key = x_only_pubkey_of_signing_key.into(); + let utxo_amount = 6280; + let send_amount = 6000; + let mfp = "73c5da0a"; + + let out_puts = vec![TxOut { + amount: Amount::from_sat(send_amount).unwrap(), + script_pubkey: to_address.script_pubkey(), + }]; + let prev_tx_id = "9d7c6770fca57285babab60c51834cfcfd10ad302119cae842d7216b4ac9a376"; + let transaction = Transaction { + version: Version::TWO, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { txid: prev_tx_id.parse().unwrap(), vout: 0 }, + script_sig: ScriptSigBuf::new(), + sequence: Sequence(0xFFFFFFFF), // Ignore nSequence. + witness: Witness::default(), + }], + outputs: out_puts, + }; + + let mut psbt = Psbt::from_unsigned_tx(transaction).unwrap(); + + let mut origins = BTreeMap::new(); + origins.insert( + x_only_pubkey_of_signing_key, + ( + vec![use_script.tapscript_leaf_hash()], + ( + mfp.parse::().unwrap(), + signing_key_path.parse::().unwrap(), + ), + ), + ); + + let mut tap_scripts = BTreeMap::new(); + tap_scripts.insert( + tree.control_block(&(use_script.clone(), LeafVersion::TapScript)).unwrap(), + (use_script, LeafVersion::TapScript), + ); + + let mut input = Input { + witness_utxo: { + let script_pubkey = from_address.script_pubkey(); + Some(TxOut { amount: Amount::from_sat(utxo_amount).unwrap(), script_pubkey }) + }, + tap_key_origins: origins, + tap_scripts, + ..Default::default() + }; + let ty = "SIGHASH_ALL".parse::().unwrap(); + input.sighash_type = Some(ty); + input.tap_internal_key = Some(tree.internal_key()); + input.tap_merkle_root = tree.merkle_root(); + psbt.inputs = vec![input]; + psbt +} + +fn finalize_psbt_for_script_path_spend(mut psbt: Psbt) -> Psbt { + psbt.inputs.iter_mut().for_each(|input| { + let mut script_witness: Witness = Witness::new(); + for (_, signature) in input.tap_script_sigs.iter() { + script_witness.push(signature.to_vec()); + } + for (control_block, (script, _)) in input.tap_scripts.iter() { + script_witness.push(script.to_vec()); + script_witness.push(control_block.serialize()); + } + input.final_script_witness = Some(script_witness); + input.partial_sigs = BTreeMap::new(); + input.sighash_type = None; + input.redeem_script = None; + input.witness_script = None; + input.bip32_derivation = BTreeMap::new(); + input.tap_script_sigs = BTreeMap::new(); + input.tap_scripts = BTreeMap::new(); + input.tap_key_sig = None; + }); + psbt +} diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs new file mode 100644 index 000000000..213555a39 --- /dev/null +++ b/bitcoin/tests/serde.rs @@ -0,0 +1,364 @@ +//! Regression tests for _most_ types that implement `serde::Serialize`. +//! +//! For remaining types see: ./serde_opcodes.rs +//! +//! If you find a type defined in `rust-bitcoin` that implements `Serialize` and does _not_ have a +//! regression test please add it. +//! +//! Types/tests were found using, and are ordered by, the output of: `git grep -l Serialize`. +//! + +// To create a file with the expected serialized data do something like: +// +// use std::fs::File; +// use std::io::Write; +// let script = WitnessScriptBuf::from(vec![0u8, 1u8, 2u8]); +// let got = serialize(&script).unwrap(); +// let mut file = File::create("/tmp/script_bincode").unwrap(); +// file.write_all(&got).unwrap(); + +#![cfg(feature = "serde")] + +use std::collections::BTreeMap; + +use bincode::serialize; +use bitcoin::bip32::{ChildNumber, KeySource, Xpriv, Xpub}; +use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; +use bitcoin::hex::FromHex; +use bitcoin::locktime::{absolute, relative}; +use bitcoin::psbt::{raw, Input, Output, Psbt, PsbtSighashType}; +use bitcoin::script::ScriptBufExt as _; +use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; +use bitcoin::taproot::{self, ControlBlock, LeafVersion, TapTree, TaprootBuilder}; +use bitcoin::witness::Witness; +use bitcoin::{ + ecdsa, transaction, Address, Amount, NetworkKind, OutPoint, PrivateKey, PublicKey, + ScriptPubKeyBuf, ScriptSigBuf, Sequence, TapScriptBuf, Target, Transaction, TxIn, TxOut, Txid, + Work, +}; + +#[test] +fn serde_regression_absolute_lock_time_height() { + let t = absolute::LockTime::from_height(741521).expect("valid height"); + + let got = serialize(&t).unwrap(); + let want = include_bytes!("data/serde/absolute_lock_time_blocks_bincode") as &[_]; + assert_eq!(got, want); +} + +#[test] +fn serde_regression_absolute_lock_time_time() { + let seconds: u32 = 1653195600; // May 22nd, 5am UTC. + let t = absolute::LockTime::from_mtp(seconds).expect("valid time"); + + let got = serialize(&t).unwrap(); + let want = include_bytes!("data/serde/absolute_lock_time_seconds_bincode") as &[_]; + assert_eq!(got, want); +} + +#[test] +fn serde_regression_relative_lock_time_height() { + let t = relative::LockTime::from(relative::Height::from(0xCAFE_u16)); + + let got = serialize(&t).unwrap(); + let want = include_bytes!("data/serde/relative_lock_time_blocks_bincode") as &[_]; + assert_eq!(got, want); +} + +#[test] +fn serde_regression_relative_lock_time_time() { + let t = relative::LockTime::from(relative::Time::from_512_second_intervals(0xFACE_u16)); + + let got = serialize(&t).unwrap(); + let want = include_bytes!("data/serde/relative_lock_time_seconds_bincode") as &[_]; + assert_eq!(got, want); +} + +#[test] +fn serde_regression_script() { + let script = ScriptSigBuf::from(vec![0u8, 1u8, 2u8]); + + let got = serialize(&script).unwrap(); + let want = include_bytes!("data/serde/script_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_out_point() { + let out_point = OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389" + .parse::() + .unwrap(), + vout: 1, + }; + + let got = serialize(&out_point).unwrap(); + let want = include_bytes!("data/serde/out_point_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_witness() { + let w0 = Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105") + .unwrap(); + let w1 = Vec::from_hex("000000").unwrap(); + let vec = [w0, w1]; + let witness = Witness::from_slice(&vec); + + let got = serialize(&witness).unwrap(); + let want = include_bytes!("data/serde/witness_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_address() { + let s = include_str!("data/serde/public_key_hex"); + let pk = s.trim().parse::().unwrap(); + let addr = Address::p2pkh(pk, NetworkKind::Main); + + let got = serialize(&addr).unwrap(); + let want = include_bytes!("data/serde/address_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_extended_priv_key() { + let s = include_str!("data/serde/extended_priv_key"); + let key = s.trim().parse::().unwrap(); + + let got = serialize(&key).unwrap(); + let want = include_bytes!("data/serde/extended_priv_key_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_extended_pub_key() { + let s = include_str!("data/serde/extended_pub_key"); + let key = s.trim().parse::().unwrap(); + + let got = serialize(&key).unwrap(); + let want = include_bytes!("data/serde/extended_pub_key_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_ecdsa_sig() { + let s = include_str!("data/serde/ecdsa_sig_hex"); + let sig = ecdsa::Signature { + signature: s.trim().parse::().unwrap(), + sighash_type: EcdsaSighashType::All, + }; + + let got = serialize(&sig).unwrap(); + let want = include_bytes!("data/serde/ecdsa_sig_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_control_block() { + let s = include_str!("data/serde/control_block_hex"); + let block = ControlBlock::decode(&Vec::::from_hex(s.trim()).unwrap()).unwrap(); + + let got = serialize(&block).unwrap(); + let want = include_bytes!("data/serde/control_block_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_child_number() { + let num = ChildNumber::Normal { index: 0xDEADBEEF }; + + let got = serialize(&num).unwrap(); + let want = include_bytes!("data/serde/child_number_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_private_key() { + let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); + + let got = serialize(&sk).unwrap(); + let want = include_bytes!("data/serde/private_key_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_public_key() { + let s = include_str!("data/serde/public_key_hex"); + let pk = s.trim().parse::().unwrap(); + + let got = serialize(&pk).unwrap(); + let want = include_bytes!("data/serde/public_key_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_psbt() { + let tx = Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + inputs: vec![TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389" + .parse::() + .unwrap(), + vout: 1, + }, + script_sig: ScriptSigBuf::from_hex_no_length_prefix( + "160014be18d152a9b012039daf3da7de4f53349eecb985", + ) + .unwrap(), + sequence: Sequence::from_consensus(4294967295), + witness: Witness::from_slice(&[Vec::from_hex( + "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105", + ) + .unwrap()]), + }], + outputs: vec![TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix( + "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587", + ) + .unwrap(), + }], + }; + let unknown: BTreeMap> = + vec![(raw::Key { type_value: 9, key_data: vec![0, 1] }, vec![3, 4, 5])] + .into_iter() + .collect(); + let key_source = ("deadbeef".parse().unwrap(), "0'/1".parse().unwrap()); + let keypaths: BTreeMap = vec![( + "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), + key_source.clone(), + )] + .into_iter() + .collect(); + + let proprietary: BTreeMap> = vec![( + raw::ProprietaryKey { + prefix: "prefx".as_bytes().to_vec(), + subtype: 42, + key: "test_key".as_bytes().to_vec(), + }, + vec![5, 6, 7], + )] + .into_iter() + .collect(); + + let psbt = Psbt { + version: 0, + xpub: { + let s = include_str!("data/serde/extended_pub_key"); + let xpub = s.trim().parse::().unwrap(); + vec![(xpub, key_source)].into_iter().collect() + }, + unsigned_tx: { + let mut unsigned = tx.clone(); + unsigned.inputs[0].previous_output.txid = tx.compute_txid(); + unsigned.inputs[0].script_sig = ScriptSigBuf::new(); + unsigned.inputs[0].witness = Witness::default(); + unsigned + }, + proprietary: proprietary.clone(), + unknown: unknown.clone(), + + inputs: vec![Input { + non_witness_utxo: Some(tx), + witness_utxo: Some(TxOut { + amount: Amount::from_sat(190_303_501_938).unwrap(), + script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + }), + sighash_type: Some(PsbtSighashType::from("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap())), + redeem_script: Some(vec![0x51].into()), + witness_script: None, + partial_sigs: vec![( + "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), + "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(), + )].into_iter().collect(), + bip32_derivation: keypaths.clone().into_iter().collect(), + final_script_witness: Some(Witness::from_slice(&[vec![1, 3], vec![5]])), + ripemd160_preimages: vec![(ripemd160::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + sha256_preimages: vec![(sha256::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + hash160_preimages: vec![(hash160::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + hash256_preimages: vec![(sha256d::Hash::hash(&[1, 2]), vec![1, 2])].into_iter().collect(), + proprietary: proprietary.clone(), + unknown: unknown.clone(), + ..Default::default() + }], + outputs: vec![Output { + bip32_derivation: keypaths.into_iter().collect(), + proprietary, + unknown, + ..Default::default() + }], + }; + + // Sanity, check we can roundtrip BIP-0174 serialize. + let serialized = psbt.serialize(); + Psbt::deserialize(&serialized).unwrap(); + + let got = serialize(&psbt).unwrap(); + let want = include_bytes!("data/serde/psbt_bincode") as &[_]; + assert_eq!(got, want); + + let got = serde_json::to_string(&psbt).unwrap(); + let want = include_str!("data/serde/psbt_base64.json"); + assert_eq!(got, want); +} + +#[test] +fn serde_regression_taproot_sig() { + let s = include_str!("data/serde/taproot_sig_hex"); + let sig = taproot::Signature { + signature: s.trim().parse::().unwrap(), + sighash_type: TapSighashType::All, + }; + + let got = serialize(&sig).unwrap(); + let want = include_bytes!("data/serde/taproot_sig_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_taptree() { + let ver = LeafVersion::from_consensus(0).unwrap(); + let script = TapScriptBuf::from(vec![0u8, 1u8, 2u8]); + let mut builder = TaprootBuilder::new().add_leaf_with_ver(1, script.clone(), ver).unwrap(); + builder = builder.add_leaf(1, script).unwrap(); + let tree = TapTree::try_from(builder).unwrap(); + + let got = serialize(&tree).unwrap(); + let want = include_bytes!("data/serde/taptree_bincode") as &[_]; + assert_eq!(got, want) +} + +// Used to get a 256 bit integer as a byte array. +fn le_bytes() -> [u8; 32] { + let x: u128 = 0xDEAD_BEEF_CAFE_BABE_DEAD_BEEF_CAFE_BABE; + let y: u128 = 0xCAFE_DEAD_BABE_BEEF_CAFE_DEAD_BABE_BEEF; + + let mut bytes = [0_u8; 32]; + + bytes[..16].copy_from_slice(&x.to_le_bytes()); + bytes[16..].copy_from_slice(&y.to_le_bytes()); + + bytes +} + +#[test] +fn serde_regression_work() { + let work = Work::from_le_bytes(le_bytes()); + + let got = serialize(&work).unwrap(); + let want = include_bytes!("data/serde/u256_bincode") as &[_]; + assert_eq!(got, want) +} + +#[test] +fn serde_regression_target() { + let target = Target::from_le_bytes(le_bytes()); + + let got = serialize(&target).unwrap(); + let want = include_bytes!("data/serde/u256_bincode") as &[_]; + assert_eq!(got, want) +} diff --git a/bitcoin/tests/serde_opcodes.rs b/bitcoin/tests/serde_opcodes.rs new file mode 100644 index 000000000..a94d3f96c --- /dev/null +++ b/bitcoin/tests/serde_opcodes.rs @@ -0,0 +1,280 @@ +//! serde regression tests for blockdata::opcodes module. +//! + +#![cfg(feature = "serde")] + +extern crate bitcoin; +extern crate serde_json; + +macro_rules! test_opcodes { + ($($op:ident),* $(,)+) => { + $( + let op = bitcoin::opcodes::all::$op; + let want = concat!("\"", stringify!($op), "\""); + let got = ::serde_json::to_string(&op).unwrap(); + assert_eq!(got, want); + )* + } +} + +#[test] +fn serde_regression_opcodes() { + test_opcodes! { + OP_PUSHBYTES_0, + OP_PUSHBYTES_1, + OP_PUSHBYTES_2, + OP_PUSHBYTES_3, + OP_PUSHBYTES_4, + OP_PUSHBYTES_5, + OP_PUSHBYTES_6, + OP_PUSHBYTES_7, + OP_PUSHBYTES_8, + OP_PUSHBYTES_9, + OP_PUSHBYTES_10, + OP_PUSHBYTES_11, + OP_PUSHBYTES_12, + OP_PUSHBYTES_13, + OP_PUSHBYTES_14, + OP_PUSHBYTES_15, + OP_PUSHBYTES_16, + OP_PUSHBYTES_17, + OP_PUSHBYTES_18, + OP_PUSHBYTES_19, + OP_PUSHBYTES_20, + OP_PUSHBYTES_21, + OP_PUSHBYTES_22, + OP_PUSHBYTES_23, + OP_PUSHBYTES_24, + OP_PUSHBYTES_25, + OP_PUSHBYTES_26, + OP_PUSHBYTES_27, + OP_PUSHBYTES_28, + OP_PUSHBYTES_29, + OP_PUSHBYTES_30, + OP_PUSHBYTES_31, + OP_PUSHBYTES_32, + OP_PUSHBYTES_33, + OP_PUSHBYTES_34, + OP_PUSHBYTES_35, + OP_PUSHBYTES_36, + OP_PUSHBYTES_37, + OP_PUSHBYTES_38, + OP_PUSHBYTES_39, + OP_PUSHBYTES_40, + OP_PUSHBYTES_41, + OP_PUSHBYTES_42, + OP_PUSHBYTES_43, + OP_PUSHBYTES_44, + OP_PUSHBYTES_45, + OP_PUSHBYTES_46, + OP_PUSHBYTES_47, + OP_PUSHBYTES_48, + OP_PUSHBYTES_49, + OP_PUSHBYTES_50, + OP_PUSHBYTES_51, + OP_PUSHBYTES_52, + OP_PUSHBYTES_53, + OP_PUSHBYTES_54, + OP_PUSHBYTES_55, + OP_PUSHBYTES_56, + OP_PUSHBYTES_57, + OP_PUSHBYTES_58, + OP_PUSHBYTES_59, + OP_PUSHBYTES_60, + OP_PUSHBYTES_61, + OP_PUSHBYTES_62, + OP_PUSHBYTES_63, + OP_PUSHBYTES_64, + OP_PUSHBYTES_65, + OP_PUSHBYTES_66, + OP_PUSHBYTES_67, + OP_PUSHBYTES_68, + OP_PUSHBYTES_69, + OP_PUSHBYTES_70, + OP_PUSHBYTES_71, + OP_PUSHBYTES_72, + OP_PUSHBYTES_73, + OP_PUSHBYTES_74, + OP_PUSHBYTES_75, + OP_PUSHDATA1, + OP_PUSHDATA2, + OP_PUSHDATA4, + OP_1NEGATE, + OP_RESERVED, + OP_1, + OP_2, + OP_3, + OP_4, + OP_5, + OP_6, + OP_7, + OP_8, + OP_9, + OP_10, + OP_11, + OP_12, + OP_13, + OP_14, + OP_15, + OP_16, + OP_NOP, + OP_VER, + OP_IF, + OP_NOTIF, + OP_VERIF, + OP_VERNOTIF, + OP_ELSE, + OP_ENDIF, + OP_VERIFY, + OP_RETURN, + OP_TOALTSTACK, + OP_FROMALTSTACK, + OP_2DROP, + OP_2DUP, + OP_3DUP, + OP_2OVER, + OP_2ROT, + OP_2SWAP, + OP_IFDUP, + OP_DEPTH, + OP_DROP, + OP_DUP, + OP_NIP, + OP_OVER, + OP_PICK, + OP_ROLL, + OP_ROT, + OP_SWAP, + OP_TUCK, + OP_CAT, + OP_SUBSTR, + OP_LEFT, + OP_RIGHT, + OP_SIZE, + OP_INVERT, + OP_AND, + OP_OR, + OP_XOR, + OP_EQUAL, + OP_EQUALVERIFY, + OP_RESERVED1, + OP_RESERVED2, + OP_1ADD, + OP_1SUB, + OP_2MUL, + OP_2DIV, + OP_NEGATE, + OP_ABS, + OP_NOT, + OP_0NOTEQUAL, + OP_ADD, + OP_SUB, + OP_MUL, + OP_DIV, + OP_MOD, + OP_LSHIFT, + OP_RSHIFT, + OP_BOOLAND, + OP_BOOLOR, + OP_NUMEQUAL, + OP_NUMEQUALVERIFY, + OP_NUMNOTEQUAL, + OP_LESSTHAN, + OP_GREATERTHAN, + OP_LESSTHANOREQUAL, + OP_GREATERTHANOREQUAL, + OP_MIN, + OP_MAX, + OP_WITHIN, + OP_RIPEMD160, + OP_SHA1, + OP_SHA256, + OP_HASH160, + OP_HASH256, + OP_CODESEPARATOR, + OP_CHECKSIG, + OP_CHECKSIGVERIFY, + OP_CHECKMULTISIG, + OP_CHECKMULTISIGVERIFY, + OP_NOP1, + OP_CLTV, + OP_CSV, + OP_NOP4, + OP_NOP5, + OP_NOP6, + OP_NOP7, + OP_NOP8, + OP_NOP9, + OP_NOP10, + OP_CHECKSIGADD, + OP_RETURN_187, + OP_RETURN_188, + OP_RETURN_189, + OP_RETURN_190, + OP_RETURN_191, + OP_RETURN_192, + OP_RETURN_193, + OP_RETURN_194, + OP_RETURN_195, + OP_RETURN_196, + OP_RETURN_197, + OP_RETURN_198, + OP_RETURN_199, + OP_RETURN_200, + OP_RETURN_201, + OP_RETURN_202, + OP_RETURN_203, + OP_RETURN_204, + OP_RETURN_205, + OP_RETURN_206, + OP_RETURN_207, + OP_RETURN_208, + OP_RETURN_209, + OP_RETURN_210, + OP_RETURN_211, + OP_RETURN_212, + OP_RETURN_213, + OP_RETURN_214, + OP_RETURN_215, + OP_RETURN_216, + OP_RETURN_217, + OP_RETURN_218, + OP_RETURN_219, + OP_RETURN_220, + OP_RETURN_221, + OP_RETURN_222, + OP_RETURN_223, + OP_RETURN_224, + OP_RETURN_225, + OP_RETURN_226, + OP_RETURN_227, + OP_RETURN_228, + OP_RETURN_229, + OP_RETURN_230, + OP_RETURN_231, + OP_RETURN_232, + OP_RETURN_233, + OP_RETURN_234, + OP_RETURN_235, + OP_RETURN_236, + OP_RETURN_237, + OP_RETURN_238, + OP_RETURN_239, + OP_RETURN_240, + OP_RETURN_241, + OP_RETURN_242, + OP_RETURN_243, + OP_RETURN_244, + OP_RETURN_245, + OP_RETURN_246, + OP_RETURN_247, + OP_RETURN_248, + OP_RETURN_249, + OP_RETURN_250, + OP_RETURN_251, + OP_RETURN_252, + OP_RETURN_253, + OP_RETURN_254, + OP_INVALIDOPCODE, + } +} diff --git a/chacha20_poly1305/CHANGELOG.md b/chacha20_poly1305/CHANGELOG.md new file mode 100644 index 000000000..7b7a6e926 --- /dev/null +++ b/chacha20_poly1305/CHANGELOG.md @@ -0,0 +1,11 @@ +# 0.1.2 - 2025-05-15 + +* Fixed a bug which was doubling the amount of work, performance should be improved [#4083](https://github.com/rust-bitcoin/rust-bitcoin/pull/4083). + +# 0.1.1 - 2024-11-07 + +* The crate is now `no_std`. + +# 0.1.0 - 2024-10-28 + +* Initial release to create the chacha20-poly1305 crate. diff --git a/chacha20_poly1305/Cargo.toml b/chacha20_poly1305/Cargo.toml new file mode 100644 index 000000000..8abd82a81 --- /dev/null +++ b/chacha20_poly1305/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "chacha20-poly1305" +version = "0.1.2" +authors = ["Nick Johnson ", "Robert Netzke "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin/" +description = "The ChaCha20 stream cipher and Poly1305 MAC based AEAD." +categories = ["cryptography"] +keywords = ["crypto", "encryption"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] + +[dev-dependencies] +hex = { package = "hex-conservative", version = "0.3.0", default-features = false, features = ["alloc"] } + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(bench)'] } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/chacha20_poly1305/README.md b/chacha20_poly1305/README.md new file mode 100644 index 000000000..7789b0cbf --- /dev/null +++ b/chacha20_poly1305/README.md @@ -0,0 +1,5 @@ +# ChaCha20-Poly1305 + +An authenticated encryption with associated data (AEAD) algorithm implemented with the ChaCha20 stream cipher and the Poly1305 message authentication code (MAC). + +This implementation is maintained by the rust-bitcoin community and has a focus on a bare-bones API suitable for the bitcoin ecosystem. diff --git a/chacha20_poly1305/contrib/extra_lints.sh b/chacha20_poly1305/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/chacha20_poly1305/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/chacha20_poly1305/contrib/test_vars.sh b/chacha20_poly1305/contrib/test_vars.sh new file mode 100644 index 000000000..7aeb1eccd --- /dev/null +++ b/chacha20_poly1305/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc" + +# Run these examples. +EXAMPLES="" diff --git a/chacha20_poly1305/src/chacha20.rs b/chacha20_poly1305/src/chacha20.rs new file mode 100644 index 000000000..13c4f5f40 --- /dev/null +++ b/chacha20_poly1305/src/chacha20.rs @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The ChaCha20 stream cipher from RFC8439. + +use core::ops::BitXor; + +/// The first four words (32-bit) of the ChaCha stream cipher state are constants. +const WORD_1: u32 = 0x61707865; +const WORD_2: u32 = 0x3320646e; +const WORD_3: u32 = 0x79622d32; +const WORD_4: u32 = 0x6b206574; + +/// The cipher's block size is 64 bytes. +const CHACHA_BLOCKSIZE: usize = 64; + +/// A 256-bit secret key shared by the parties communicating. +#[derive(Clone, Copy)] +pub struct Key([u8; 32]); + +impl Key { + /// Constructs a new key. + pub const fn new(key: [u8; 32]) -> Self { Self(key) } +} + +/// A 96-bit initialization vector (IV), or nonce. +#[derive(Clone, Copy)] +pub struct Nonce([u8; 12]); + +impl Nonce { + /// Constructs a new nonce. + pub const fn new(nonce: [u8; 12]) -> Self { Self(nonce) } +} + +// Const validation trait for compile time check with max of 3. +trait UpTo3 {} + +impl UpTo3<0> for () {} +impl UpTo3<1> for () {} +impl UpTo3<2> for () {} +impl UpTo3<3> for () {} + +/// A SIMD-friendly structure which holds 25% of the cipher state. +/// +/// The cipher's quarter round function is the bulk of its work +/// and there are large performance gains to be had if the function +/// leverages SIMD instructions on architectures which support them. Because +/// the algorithm allows for the cipher's state to be operated on in +/// parallel (each round only touches a quarter of the state), then theoretically +/// the parallel SIMD instructions should be used. But sometimes the +/// compiler needs a few hints to ensure it recognizes a "vectorizable" function. +/// That is the goal of this type, which clearly breaks the state up into four +/// chunks and exposes functions which align with SIMD lanes. +/// +/// This type is attempting to be as close as possible to the experimental [`core::simd::u32x4`] +/// which at this time is feature gated and well beyond the project's MSRV. But ideally +/// an easy transition can be made in the future. +/// +/// A few SIMD relevant design choices: +/// * Heavy use of inline functions to help the compiler recognize vectorizable sections. +/// * For-each loops are easy for the compiler to recognize as vectorizable. +/// * The type is a based on an array instead of tuple since the heterogeneous +/// nature of tuples can confuse the compiler into thinking it is not vectorizable. +/// +/// In the future, a "blacklist" for the alignment option might be useful to +/// disable it on architectures which definitely do not support SIMD in order to avoid +/// needless memory inefficiencies. +#[derive(Clone, Copy, PartialEq)] +struct U32x4([u32; 4]); + +impl U32x4 { + #[inline(always)] + fn wrapping_add(self, rhs: Self) -> Self { + let mut result = [0u32; 4]; + (0..4).for_each(|i| { + result[i] = self.0[i].wrapping_add(rhs.0[i]); + }); + Self(result) + } + + #[inline(always)] + fn rotate_left(self, n: u32) -> Self { + let mut result = [0u32; 4]; + (0..4).for_each(|i| { + result[i] = self.0[i].rotate_left(n); + }); + Self(result) + } + + #[inline(always)] + fn rotate_elements_left(self) -> Self + where + (): UpTo3, + { + match N { + 1 => Self([self.0[1], self.0[2], self.0[3], self.0[0]]), + 2 => Self([self.0[2], self.0[3], self.0[0], self.0[1]]), + 3 => Self([self.0[3], self.0[0], self.0[1], self.0[2]]), + _ => self, // Rotate by 0 is a no-op. + } + } + + #[inline(always)] + fn rotate_elements_right(self) -> Self + where + (): UpTo3, + { + match N { + 1 => Self([self.0[3], self.0[0], self.0[1], self.0[2]]), + 2 => Self([self.0[2], self.0[3], self.0[0], self.0[1]]), + 3 => Self([self.0[1], self.0[2], self.0[3], self.0[0]]), + _ => self, // Rotate by 0 is a no-op. + } + } + + #[inline(always)] + fn to_le_bytes(self) -> [u8; 16] { + let mut bytes = [0u8; 16]; + (0..4).for_each(|i| { + bytes[i * 4..(i + 1) * 4].copy_from_slice(&self.0[i].to_le_bytes()); + }); + bytes + } +} + +impl BitXor for U32x4 { + type Output = Self; + + #[inline(always)] + fn bitxor(self, rhs: Self) -> Self { + let mut result = [0u32; 4]; + (0..4).for_each(|i| { + result[i] = self.0[i] ^ rhs.0[i]; + }); + Self(result) + } +} + +/// The 512-bit cipher state is chunk'd up into 16 32-bit words. +/// +/// The 16 words can be visualized as a 4x4 matrix: +/// +/// 0 1 2 3 +/// 4 5 6 7 +/// 8 9 10 11 +/// 12 13 14 15 +#[derive(Clone, Copy, PartialEq)] +struct State { + matrix: [U32x4; 4], +} + +impl State { + /// New prepared state. + const fn new(key: Key, nonce: Nonce, count: u32) -> Self { + // Hardcoding indexes to keep the function const. + let k0 = u32::from_le_bytes([key.0[0], key.0[1], key.0[2], key.0[3]]); + let k1 = u32::from_le_bytes([key.0[4], key.0[5], key.0[6], key.0[7]]); + let k2 = u32::from_le_bytes([key.0[8], key.0[9], key.0[10], key.0[11]]); + let k3 = u32::from_le_bytes([key.0[12], key.0[13], key.0[14], key.0[15]]); + let k4 = u32::from_le_bytes([key.0[16], key.0[17], key.0[18], key.0[19]]); + let k5 = u32::from_le_bytes([key.0[20], key.0[21], key.0[22], key.0[23]]); + let k6 = u32::from_le_bytes([key.0[24], key.0[25], key.0[26], key.0[27]]); + let k7 = u32::from_le_bytes([key.0[28], key.0[29], key.0[30], key.0[31]]); + + let n0 = u32::from_le_bytes([nonce.0[0], nonce.0[1], nonce.0[2], nonce.0[3]]); + let n1 = u32::from_le_bytes([nonce.0[4], nonce.0[5], nonce.0[6], nonce.0[7]]); + let n2 = u32::from_le_bytes([nonce.0[8], nonce.0[9], nonce.0[10], nonce.0[11]]); + + Self { + matrix: [ + U32x4([WORD_1, WORD_2, WORD_3, WORD_4]), + U32x4([k0, k1, k2, k3]), + U32x4([k4, k5, k6, k7]), + U32x4([count, n0, n1, n2]), + ], + } + } + + /// Four quarter rounds performed on the entire state of the cipher in a vectorized SIMD friendly fashion. + #[inline(always)] + fn quarter_round(a: U32x4, b: U32x4, c: U32x4, d: U32x4) -> [U32x4; 4] { + let a = a.wrapping_add(b); + let d = d.bitxor(a).rotate_left(16); + + let c = c.wrapping_add(d); + let b = b.bitxor(c).rotate_left(12); + + let a = a.wrapping_add(b); + let d = d.bitxor(a).rotate_left(8); + + let c = c.wrapping_add(d); + let b = b.bitxor(c).rotate_left(7); + + [a, b, c, d] + } + + /// Performs a round on "columns" and then "diagonals" of the state. + /// + /// The column quarter rounds are made up of indexes: `[0,4,8,12]`, `[1,5,9,13]`, `[2,6,10,14]`, `[3,7,11,15]`. + /// The diagonals quarter rounds are made up of indexes: `[0,5,10,15]`, `[1,6,11,12]`, `[2,7,8,13]`, `[3,4,9,14]`. + /// + /// The underlying quarter_round function is vectorized using the + /// u32x4 type in order to perform 4 quarter round functions at the same time. + /// This is a little more difficult to read, but it gives the compiler + /// a strong hint to use the performant SIMD instructions. + #[inline(always)] + fn double_round(state: [U32x4; 4]) -> [U32x4; 4] { + let [mut a, mut b, mut c, mut d] = state; + + // Column round. + [a, b, c, d] = Self::quarter_round(a, b, c, d); + + // Diagonal round (with rotations). + b = b.rotate_elements_left::<1>(); + c = c.rotate_elements_left::<2>(); + d = d.rotate_elements_left::<3>(); + [a, b, c, d] = Self::quarter_round(a, b, c, d); + // Rotate the words back into their normal positions. + b = b.rotate_elements_right::<1>(); + c = c.rotate_elements_right::<2>(); + d = d.rotate_elements_right::<3>(); + + [a, b, c, d] + } + + /// Transforms the state by performing the ChaCha block function. + #[inline(always)] + fn chacha_block(&mut self) { + let mut working_state = self.matrix; + + for _ in 0..10 { + working_state = Self::double_round(working_state); + } + + // Add the working state to the original state. + (0..4).for_each(|i| { + self.matrix[i] = working_state[i].wrapping_add(self.matrix[i]); + }); + } + + /// Expose the 512-bit state as a byte stream. + #[inline(always)] + fn keystream(&self) -> [u8; 64] { + let mut keystream = [0u8; 64]; + for i in 0..4 { + keystream[i * 16..(i + 1) * 16].copy_from_slice(&self.matrix[i].to_le_bytes()); + } + keystream + } +} + +/// The ChaCha20 stream cipher from RFC8439. +/// +/// The 20-round IETF version uses a 96-bit nonce and 32-bit block counter. This is the +/// variant used in the Bitcoin ecosystem, including BIP-0324. +pub struct ChaCha20 { + /// Secret key shared by the parties communicating. + key: Key, + /// A key and nonce pair should only be used once. + nonce: Nonce, + /// Internal block index of keystream. + block_count: u32, + /// Internal byte offset index of the block_count. + seek_offset_bytes: usize, +} + +impl ChaCha20 { + /// Make a new instance of ChaCha20 from an index in the keystream. + pub const fn new(key: Key, nonce: Nonce, seek: u32) -> Self { + let block_count = seek / 64; + let seek_offset_bytes = (seek % 64) as usize; + Self { key, nonce, block_count, seek_offset_bytes } + } + + /// Make a new instance of ChaCha20 from a block in the keystream. + pub const fn new_from_block(key: Key, nonce: Nonce, block: u32) -> Self { + Self { key, nonce, block_count: block, seek_offset_bytes: 0 } + } + + /// Gets the keystream for a specific block. + #[inline(always)] + fn keystream_at_block(&self, block: u32) -> [u8; 64] { + let mut state = State::new(self.key, self.nonce, block); + state.chacha_block(); + state.keystream() + } + + /// Apply the keystream to a buffer updating the cipher block state as necessary. + pub fn apply_keystream(&mut self, buffer: &mut [u8]) { + // If we have an initial offset, handle the first partial block to get back to alignment. + let remaining_buffer = if self.seek_offset_bytes != 0 { + let bytes_until_aligned = 64 - self.seek_offset_bytes; + let bytes_to_process = buffer.len().min(bytes_until_aligned); + + let keystream = self.keystream_at_block(self.block_count); + for (buffer_byte, keystream_byte) in + buffer[..bytes_to_process].iter_mut().zip(&keystream[self.seek_offset_bytes..]) + { + *buffer_byte ^= *keystream_byte; + } + + if bytes_to_process < bytes_until_aligned { + self.seek_offset_bytes += bytes_to_process; + return; + } + + self.block_count += 1; + self.seek_offset_bytes = 0; + &mut buffer[bytes_to_process..] + } else { + buffer + }; + + // Process full blocks. + let mut chunks = remaining_buffer.chunks_exact_mut(CHACHA_BLOCKSIZE); + for chunk in &mut chunks { + let keystream = self.keystream_at_block(self.block_count); + for (buffer_byte, keystream_byte) in chunk.iter_mut().zip(keystream.iter()) { + *buffer_byte ^= *keystream_byte; + } + self.block_count += 1; + } + + // Handle any remaining bytes as partial block. + let remainder = chunks.into_remainder(); + if !remainder.is_empty() { + let keystream = self.keystream_at_block(self.block_count); + for (buffer_byte, keystream_byte) in remainder.iter_mut().zip(keystream.iter()) { + *buffer_byte ^= *keystream_byte; + } + self.seek_offset_bytes = remainder.len(); + } + } + + /// Gets the keystream for specified block. + pub fn get_keystream(&self, block: u32) -> [u8; 64] { self.keystream_at_block(block) } + + /// Updates the index of the keystream to the given byte. + pub fn seek(&mut self, seek: u32) { + self.block_count = seek / 64; + self.seek_offset_bytes = (seek % 64) as usize; + } + + /// Updates the index of the keystream to a block. + pub fn block(&mut self, block: u32) { + self.block_count = block; + self.seek_offset_bytes = 0; + } +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +mod tests { + use alloc::vec::Vec; + + use hex::prelude::*; + + use super::*; + + #[test] + fn chacha_block() { + let mut state = State { + matrix: [ + U32x4([0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]), + U32x4([0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c]), + U32x4([0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c]), + U32x4([0x00000001, 0x09000000, 0x4a000000, 0x00000000]), + ], + }; + state.chacha_block(); + + let expected = [ + U32x4([0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3]), + U32x4([0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3]), + U32x4([0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9]), + U32x4([0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2]), + ]; + + for (actual, expected) in state.matrix.iter().zip(expected.iter()) { + assert_eq!(actual.0, expected.0); + } + } + + #[test] + fn prepare_state() { + let key = + Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + .try_into() + .unwrap()); + let nonce = Nonce(Vec::from_hex("000000090000004a00000000").unwrap().try_into().unwrap()); + let count = 1; + let state = State::new(key, nonce, count); + assert_eq!(state.matrix[1].0[0].to_be_bytes().to_lower_hex_string(), "03020100"); + assert_eq!(state.matrix[2].0[2].to_be_bytes().to_lower_hex_string(), "1b1a1918"); + assert_eq!(state.matrix[3].0[2].to_be_bytes().to_lower_hex_string(), "4a000000"); + assert_eq!(state.matrix[3].0[3].to_be_bytes().to_lower_hex_string(), "00000000"); + assert_eq!(state.matrix[3].0[0].to_be_bytes().to_lower_hex_string(), "00000001"); + } + + #[test] + fn small_plaintext() { + let key = + Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + .try_into() + .unwrap()); + let nonce = Nonce(Vec::from_hex("000000090000004a00000000").unwrap().try_into().unwrap()); + let count = 1; + let mut chacha = ChaCha20::new(key, nonce, count); + let mut binding = [8; 3]; + chacha.apply_keystream(&mut binding[..]); + let mut chacha = ChaCha20::new(key, nonce, count); + chacha.apply_keystream(&mut binding[..]); + assert_eq!([8; 3], binding); + } + + #[test] + fn modulo_64() { + let key = + Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + .try_into() + .unwrap()); + let nonce = Nonce(Vec::from_hex("000000090000004a00000000").unwrap().try_into().unwrap()); + let count = 1; + let mut chacha = ChaCha20::new(key, nonce, count); + let mut binding = [8; 64]; + chacha.apply_keystream(&mut binding[..]); + let mut chacha = ChaCha20::new(key, nonce, count); + chacha.apply_keystream(&mut binding[..]); + assert_eq!([8; 64], binding); + } + + #[test] + fn rfc_standard() { + let key = + Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + .try_into() + .unwrap()); + let nonce = Nonce(Vec::from_hex("000000000000004a00000000").unwrap().try_into().unwrap()); + let count = 64; + let mut chacha = ChaCha20::new(key, nonce, count); + let mut binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + let to = binding; + chacha.apply_keystream(&mut binding[..]); + assert_eq!(binding[..], Vec::from_hex("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d").unwrap()); + let mut chacha = ChaCha20::new(key, nonce, count); + chacha.apply_keystream(&mut binding[..]); + let binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + assert_eq!(binding, to); + } + + #[test] + fn new_from_block() { + let key = + Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + .try_into() + .unwrap()); + let nonce = Nonce(Vec::from_hex("000000000000004a00000000").unwrap().try_into().unwrap()); + let block: u32 = 1; + let mut chacha = ChaCha20::new_from_block(key, nonce, block); + let mut binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + let to = binding; + chacha.apply_keystream(&mut binding[..]); + assert_eq!(binding[..], Vec::from_hex("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d").unwrap()); + chacha.block(block); + chacha.apply_keystream(&mut binding[..]); + let binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + assert_eq!(binding, to); + } + + #[test] + fn multiple_partial_applies() { + let key = + Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") + .unwrap() + .try_into() + .unwrap()); + let nonce = Nonce(Vec::from_hex("000000000000004a00000000").unwrap().try_into().unwrap()); + + // Create two instances, one for a full single pass and one for chunked partial calls. + let mut chacha_full = ChaCha20::new(key, nonce, 0); + let mut chacha_chunked = ChaCha20::new(key, nonce, 0); + + // Test data that crosses block boundaries. + let mut full_buffer = [0u8; 100]; + let mut chunked_buffer = [0u8; 100]; + for (i, byte) in full_buffer.iter_mut().enumerate() { + *byte = i as u8; + } + chunked_buffer.copy_from_slice(&full_buffer); + + // Apply keystream to full buffer. + chacha_full.apply_keystream(&mut full_buffer); + // Apply keystream in multiple calls to chunked buffer. + chacha_chunked.apply_keystream(&mut chunked_buffer[..30]); // Partial block + chacha_chunked.apply_keystream(&mut chunked_buffer[30..82]); // Cross block boundary + chacha_chunked.apply_keystream(&mut chunked_buffer[82..]); // End with partial block + + assert_eq!(full_buffer, chunked_buffer); + } +} diff --git a/chacha20_poly1305/src/lib.rs b/chacha20_poly1305/src/lib.rs new file mode 100644 index 000000000..88283d4b1 --- /dev/null +++ b/chacha20_poly1305/src/lib.rs @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! ChaCha20 - Poly1305 +//! +//! Combine the ChaCha20 stream cipher with the Poly1305 message authentication code +//! to form an authenticated encryption with additional data (AEAD) algorithm. + +#![no_std] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +pub mod chacha20; +pub mod poly1305; + +use core::fmt; + +use chacha20::ChaCha20; +use poly1305::Poly1305; + +pub use self::chacha20::{Key, Nonce}; + +/// Zero array for padding slices. +const ZEROES: [u8; 16] = [0u8; 16]; + +/// Errors encrypting and decrypting messages with ChaCha20 and Poly1305 authentication tags. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Error { + /// Additional data showing up when it is not expected. + UnauthenticatedAdditionalData, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::UnauthenticatedAdditionalData => write!(f, "Unauthenticated aad."), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::UnauthenticatedAdditionalData => None, + } + } +} + +/// Encrypt and decrypt content along with an authentication tag. +pub struct ChaCha20Poly1305 { + key: Key, + nonce: Nonce, +} + +impl ChaCha20Poly1305 { + /// Make a new instance of a ChaCha20Poly1305 AEAD. + pub const fn new(key: Key, nonce: Nonce) -> Self { Self { key, nonce } } + + /// Encrypt content in place and return the Poly1305 16-byte authentication tag. + /// + /// # Parameters + /// + /// - `content` - the plaintext to be encrypted in place. + /// - `aad` - the optional metadata covered by the authentication tag. + /// + /// # Returns + /// + /// The 16-byte authentication tag. + pub fn encrypt(self, content: &mut [u8], aad: Option<&[u8]>) -> [u8; 16] { + let mut chacha = ChaCha20::new_from_block(self.key, self.nonce, 1); + chacha.apply_keystream(content); + let keystream = chacha.get_keystream(0); + let mut poly = + Poly1305::new(keystream[..32].try_into().expect("slicing produces 32-byte slice")); + let aad = aad.unwrap_or(&[]); + // AAD and ciphertext are padded if not 16-byte aligned. + poly.input(aad); + let aad_overflow = aad.len() % 16; + if aad_overflow > 0 { + poly.input(&ZEROES[0..(16 - aad_overflow)]); + } + + poly.input(content); + let text_overflow = content.len() % 16; + if text_overflow > 0 { + poly.input(&ZEROES[0..(16 - text_overflow)]); + } + + let len_buffer = encode_lengths(aad.len() as u64, content.len() as u64); + poly.input(&len_buffer); + poly.tag() + } + + /// Decrypt the ciphertext in place if authentication tag is correct. + /// + /// # Parameters + /// + /// - `content` - Ciphertext to be decrypted in place. + /// - `tag` - 16-byte authentication tag. + /// - `aad` - Optional metadata covered by the authentication tag. + pub fn decrypt( + self, + content: &mut [u8], + tag: [u8; 16], + aad: Option<&[u8]>, + ) -> Result<(), Error> { + let chacha = ChaCha20::new_from_block(self.key, self.nonce, 0); + let keystream = chacha.get_keystream(0); + let mut poly = + Poly1305::new(keystream[..32].try_into().expect("slicing produces 32-byte slice")); + let aad = aad.unwrap_or(&[]); + poly.input(aad); + // AAD and ciphertext are padded if not 16-byte aligned. + let aad_overflow = aad.len() % 16; + if aad_overflow > 0 { + poly.input(&ZEROES[0..(16 - aad_overflow)]); + } + poly.input(content); + let msg_overflow = content.len() % 16; + if msg_overflow > 0 { + poly.input(&ZEROES[0..(16 - msg_overflow)]); + } + + let len_buffer = encode_lengths(aad.len() as u64, content.len() as u64); + poly.input(&len_buffer); + let derived_tag = poly.tag(); + if derived_tag == tag { + let mut chacha = ChaCha20::new_from_block(self.key, self.nonce, 1); + chacha.apply_keystream(content); + Ok(()) + } else { + Err(Error::UnauthenticatedAdditionalData) + } + } +} + +/// AAD and content lengths are each encoded in 8-bytes. +fn encode_lengths(aad_len: u64, content_len: u64) -> [u8; 16] { + let aad_len_bytes = aad_len.to_le_bytes(); + let content_len_bytes = content_len.to_le_bytes(); + let mut len_buffer = [0u8; 16]; + let (aad_len_buffer, content_len_buffer) = len_buffer.split_at_mut(8); + aad_len_buffer.copy_from_slice(&aad_len_bytes[..]); + content_len_buffer.copy_from_slice(&content_len_bytes[..]); + + len_buffer +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +mod tests { + use alloc::vec::Vec; + + use hex::prelude::*; + + use super::*; + + #[test] + fn rfc7539() { + let mut message = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + let aad = Vec::from_hex("50515253c0c1c2c3c4c5c6c7").unwrap(); + let key = Key::new( + Vec::from_hex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") + .unwrap() + .try_into() + .unwrap(), + ); + let nonce = + Nonce::new(Vec::from_hex("070000004041424344454647").unwrap().try_into().unwrap()); + let cipher = ChaCha20Poly1305::new(key, nonce); + let tag = cipher.encrypt(&mut message, Some(&aad)); + + let mut buffer = [0u8; 130]; + buffer[..message.len()].copy_from_slice(&message); + buffer[message.len()..].copy_from_slice(&tag); + + assert_eq!(&buffer.to_lower_hex_string(), "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691"); + } +} diff --git a/chacha20_poly1305/src/poly1305.rs b/chacha20_poly1305/src/poly1305.rs new file mode 100644 index 000000000..cf560bd0b --- /dev/null +++ b/chacha20_poly1305/src/poly1305.rs @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Poly1305 one-time message authenticator from RFC8439. +//! +//! Heavily inspired by the ["Donna"](https://github.com/floodyberry/poly1305-donna/blob/master/poly1305-donna-32.h) implementation in C +//! and Loup Vaillant's [Poly1305 design article](https://loup-vaillant.fr/tutorials/poly1305-design). + +/// 2^26 for the 26-bit limbs. +const BITMASK: u32 = 0x03ffffff; +/// Number is encoded in five 26-bit limbs. +const CARRY: u32 = 26; + +/// Poly1305 authenticator takes a 32-byte one-time key and a message and produces a 16-byte tag. +/// +/// 64-bit constant time multiplication and addition implementation. +pub struct Poly1305 { + /// r part of the secret key. + r: [u32; 5], + /// s part of the secret key. + s: [u32; 4], + /// State used to create tag. + acc: [u32; 5], + /// Leftovers between adds. + leftovers: [u8; 16], + /// Track relevant leftover bytes. + leftovers_len: usize, +} + +impl Poly1305 { + /// Initializes authenticator with a 32-byte one-time secret key. + pub const fn new(key: [u8; 32]) -> Self { + // Taken from Donna. Assigns r to a 26-bit 5-limb number while simultaneously 'clamping' r. + let r0 = u32::from_le_bytes([key[0], key[1], key[2], key[3]]) & 0x3ffffff; + let r1 = (u32::from_le_bytes([key[3], key[4], key[5], key[6]]) >> 2) & 0x03ffff03; + let r2 = (u32::from_le_bytes([key[6], key[7], key[8], key[9]]) >> 4) & 0x03ffc0ff; + let r3 = (u32::from_le_bytes([key[9], key[10], key[11], key[12]]) >> 6) & 0x03f03fff; + let r4 = (u32::from_le_bytes([key[12], key[13], key[14], key[15]]) >> 8) & 0x000fffff; + + let s0 = u32::from_le_bytes([key[16], key[17], key[18], key[19]]); + let s1 = u32::from_le_bytes([key[20], key[21], key[22], key[23]]); + let s2 = u32::from_le_bytes([key[24], key[25], key[26], key[27]]); + let s3 = u32::from_le_bytes([key[28], key[29], key[30], key[31]]); + + Self { + r: [r0, r1, r2, r3, r4], + s: [s0, s1, s2, s3], + acc: [0; 5], + leftovers: [0; 16], + leftovers_len: 0, + } + } + + /// Adds message to be authenticated, can be called multiple times before creating tag. + pub fn input(&mut self, message: &[u8]) { + // Process previous leftovers if the message is long enough to fill the leftovers buffer. If + // the message is too short then it will just be added to the leftovers at the end. Now if there + // are no leftovers, but the message can fill the buffer, it will process that buffer and + // process the rest of the message later on. + let fill = + if self.leftovers_len + message.len() >= 16 { 16 - self.leftovers_len } else { 0 }; + + if fill > 0 { + self.leftovers[self.leftovers_len..].copy_from_slice(&message[0..fill]); + + let msg_slice = prepare_padded_message_slice(&self.leftovers, false); + for (i, b) in msg_slice.iter().enumerate() { + self.acc[i] += *b; + } + self.r_times_a(); + self.leftovers_len = 0; + } + + // Remove prefix already processed in leftovers. + let remaining_message = &message[fill..]; + + // Add message to accumulator. + let mut i = 0; + while i < remaining_message.len() / 16 { + let msg_slice = + prepare_padded_message_slice(&remaining_message[i * 16..(i + 1) * 16], false); + for (i, b) in msg_slice.iter().enumerate() { + self.acc[i] += *b; + } + self.r_times_a(); + i += 1; + } + + // Save any leftovers. + if remaining_message.len() % 16 > 0 { + let message_index = remaining_message.len() - (remaining_message.len() % 16); + let new_len = self.leftovers_len + remaining_message.len() % 16; + self.leftovers[self.leftovers_len..new_len] + .copy_from_slice(&remaining_message[message_index..]); + self.leftovers_len = new_len; + } + } + + /// Generates authentication tag. + pub fn tag(mut self) -> [u8; 16] { + // Add any remaining leftovers to accumulator. + if self.leftovers_len > 0 { + let msg_slice = + prepare_padded_message_slice(&self.leftovers[..self.leftovers_len], true); + for (i, b) in msg_slice.iter().enumerate() { + self.acc[i] += *b; + } + self.r_times_a(); + self.leftovers_len = 0; + } + + // Carry and mask. + for i in 1..4 { + self.acc[i + 1] += self.acc[i] >> CARRY; + } + self.acc[0] += (self.acc[4] >> CARRY) * 5; + self.acc[1] += self.acc[0] >> CARRY; + for i in 0..self.acc.len() { + self.acc[i] &= BITMASK; + } + // Reduce. + let mut t = self.acc; + t[0] += 5; + t[4] = t[4].wrapping_sub(1 << CARRY); + for i in 0..3 { + t[i + 1] += t[i] >> CARRY; + } + t[4] = t[4].wrapping_add(t[3] >> CARRY); + for t in t.iter_mut().take(4) { + *t &= BITMASK; + } + // Convert acc to a 4 item array. + let mask = (t[4] >> 31).wrapping_sub(1); + for (i, t) in t.iter().enumerate().take(self.acc.len()) { + self.acc[i] = t & mask | self.acc[i] & !mask; + } + // Voodoo from donna to convert to [u32; 4]. + let a0 = self.acc[0] | (self.acc[1] << 26); + let a1 = (self.acc[1] >> 6) | (self.acc[2] << 20); + let a2 = (self.acc[2] >> 12) | (self.acc[3] << 14); + let a3 = (self.acc[3] >> 18) | (self.acc[4] << 8); + let a = [a0, a1, a2, a3]; + // a + s + let mut tag: [u64; 4] = [0; 4]; + for i in 0..4 { + tag[i] = a[i] as u64 + self.s[i] as u64; + } + + // Carry. + for i in 0..3 { + tag[i + 1] += tag[i] >> 32; + } + + // Return the 16 least significant bytes. + let mut ret: [u8; 16] = [0; 16]; + for i in 0..tag.len() { + let bytes = (tag[i] as u32).to_le_bytes(); + ret[i * 4..(i + 1) * 4].copy_from_slice(&bytes); + } + ret + } + + fn r_times_a(&mut self) { + // Multiply and reduce. + // While this looks complicated, it is a variation of schoolbook multiplication, + // described well in an article here: https://loup-vaillant.fr/tutorials/poly1305-design + let mut t = [0; 5]; + for i in 0..5 { + for (j, t) in t.iter_mut().enumerate() { + let modulus: u64 = if i > j { 5 } else { 1 }; + let start = (5 - i) % 5; + *t += modulus * self.r[i] as u64 * self.acc[(start + j) % 5] as u64; + } + } + // Carry. + for i in 0..4 { + t[i + 1] += t[i] >> CARRY; + } + // Mask. + for (i, t) in t.iter().enumerate().take(self.acc.len()) { + self.acc[i] = *t as u32 & BITMASK; + } + // Carry and mask first limb. + self.acc[0] += (t[4] >> CARRY) as u32 * 5; + self.acc[1] += self.acc[0] >> CARRY; + self.acc[0] &= BITMASK; + } +} + +// Encode 16-byte (tag sized), unless is_last flag set to true, piece of message into 5 26-bit limbs. +fn prepare_padded_message_slice(msg: &[u8], is_last: bool) -> [u32; 5] { + let hi_bit: u32 = if is_last { 0 } else { 1 << 24 }; + let mut fmt_msg = [0u8; 17]; + fmt_msg[..msg.len()].copy_from_slice(msg); + // Tack on a 1-byte so messages with buncha zeroes at the end don't have the same MAC. + fmt_msg[msg.len()] = 0x01; + // Encode number in five 26-bit limbs. + let m0 = u32::from_le_bytes(fmt_msg[0..4].try_into().expect("Valid subset of 32.")) & BITMASK; + let m1 = + (u32::from_le_bytes(fmt_msg[3..7].try_into().expect("Valid subset of 32.")) >> 2) & BITMASK; + let m2 = (u32::from_le_bytes(fmt_msg[6..10].try_into().expect("Valid subset of 32.")) >> 4) + & BITMASK; + let m3 = (u32::from_le_bytes(fmt_msg[9..13].try_into().expect("Valid subset of 32.")) >> 6) + & BITMASK; + let m4 = (u32::from_le_bytes(fmt_msg[12..16].try_into().expect("Valid subset of 32.")) >> 8) + | hi_bit; + [m0, m1, m2, m3, m4] +} + +fn _print_acc(num: &[u32; 5]) { + let a0 = num[0] | (num[1] << 26); + let a1 = (num[1] >> 6) | (num[2] << 20); + let a2 = (num[2] >> 12) | (num[3] << 14); + let a3 = (num[3] >> 18) | (num[4] << 8); + let a = [a0, a1, a2, a3]; + let mut ret: [u8; 16] = [0; 16]; + for i in 0..a.len() { + let bytes = a[i].to_le_bytes(); + ret[i * 4..(i + 1) * 4].copy_from_slice(&bytes); + } + ret.reverse(); +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +mod tests { + use alloc::vec::Vec; + + use hex::prelude::*; + + use super::*; + + #[test] + fn rfc7539() { + let key = Vec::from_hex("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b") + .unwrap() + .as_slice() + .try_into() + .unwrap(); + let mut poly = Poly1305::new(key); + let message = b"Cryptographic Forum Research Group"; + poly.input(message); + let tag = poly.tag(); + assert_eq!("a8061dc1305136c6c22b8baf0c0127a9", tag.to_lower_hex_string()); + } +} diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 000000000..70f47d05f --- /dev/null +++ b/clippy.toml @@ -0,0 +1,4 @@ +msrv = "1.74.0" +too-many-arguments-threshold = 13 +avoid-breaking-exported-api = false +doc-valid-idents = ["SegWit", "OpenSSL"] diff --git a/consensus_encoding/CHANGELOG.md b/consensus_encoding/CHANGELOG.md new file mode 100644 index 000000000..1b05876b4 --- /dev/null +++ b/consensus_encoding/CHANGELOG.md @@ -0,0 +1,30 @@ +# 1.0.0 - 2025-10-10 + +This changelog is a rolling description of everything that will eventually end up in `v1.0`. + +This was truly a team effort, notably @nyonson and @jrakibi. Also please note that many of the ideas +and a bunch of the code, pulled out of a draft PR by @kixunil. Initial implementation was put up by +@apoelstra, then the crew hacked on it while we all reviewed. Good effort team. Also it should be +noted that Kix was pushing for this work for a long time and we all resisted doing it. Now he is not +around but the work got done. Props to him for many of the ideas. + +- Fix `consensus-encoding` package name [#5090](https://github.com/rust-bitcoin/rust-bitcoin/pull/5090) +- Introduce pull encoding and use it for blockhash computation [#4912](https://github.com/rust-bitcoin/rust-bitcoin/pull/4912) +- Implement `SliceEncoder` [#4982](https://github.com/rust-bitcoin/rust-bitcoin/pull/4982) +- Add decoder I/O drivers [#5030](https://github.com/rust-bitcoin/rust-bitcoin/pull/5030) +- Tag composers with inline [#5037](https://github.com/rust-bitcoin/rust-bitcoin/pull/5037) +- Clean up encoders unit tests and fix empty `SliceEncoder` [#5039](https://github.com/rust-bitcoin/rust-bitcoin/pull/5039) +- Add encoder composition unit tests [#5045](https://github.com/rust-bitcoin/rust-bitcoin/pull/5045) +- Implement additional decoders [#5057](https://github.com/rust-bitcoin/rust-bitcoin/pull/5057) +- Add `CompactSizeEncoder` and refactor `WitnessEncoder` [#5086](https://github.com/rust-bitcoin/rust-bitcoin/pull/5086) +- Add `new()` constructor to `CompactSizeDecoder` [#5089](https://github.com/rust-bitcoin/rust-bitcoin/pull/5089) +- Remove `prefix_read` field [#5079](https://github.com/rust-bitcoin/rust-bitcoin/pull/5079) +- Remove length prefix from the `BytesEncoder` [#5103](https://github.com/rust-bitcoin/rust-bitcoin/pull/5103) +- Remove length prefix from `SliceEncoder` [#5108](https://github.com/rust-bitcoin/rust-bitcoin/pull/5108) +- Rename `min_bytes_needed` to `read_limit` [#5107](https://github.com/rust-bitcoin/rust-bitcoin/pull/5107) +- Remove transitioning state [#5130](https://github.com/rust-bitcoin/rust-bitcoin/pull/5130) +- Composite decoder errors [#5131](https://github.com/rust-bitcoin/rust-bitcoin/pull/5131) + +## 0.0.0 - Placeholder release + +Empty crate to reserve the name on crates.io \ No newline at end of file diff --git a/consensus_encoding/Cargo.toml b/consensus_encoding/Cargo.toml new file mode 100644 index 000000000..31a5028e1 --- /dev/null +++ b/consensus_encoding/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "bitcoin-consensus-encoding" +version = "1.0.0-rc.2" +authors = ["Andrew Poelstra ", "Nick Johnson ", "Tobin C. Harding "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin/" +description = "Consensus encoding and decoding" +categories = ["cryptography::cryptocurrencies"] +keywords = ["bitcoin", "no-std"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc", "internals/std"] +alloc = ["internals/alloc"] + +[dependencies] +internals = { package = "bitcoin-internals", path = "../internals", version = "0.4.0" } + +[dev-dependencies] +hex = { package = "hex-conservative", version = "0.3.0" } + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[[example]] +name = "encoder" +required-features = ["alloc"] + +[lints] +workspace = true diff --git a/consensus_encoding/README.md b/consensus_encoding/README.md new file mode 100644 index 000000000..63f6b3cda --- /dev/null +++ b/consensus_encoding/README.md @@ -0,0 +1,3 @@ +# Bitcoin Consensus Encoding + +This crate provides traits that can be used to encode/decode objects in a consensus-consistent way. diff --git a/consensus_encoding/contrib/extra_lints.sh b/consensus_encoding/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/consensus_encoding/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/consensus_encoding/contrib/test_vars.sh b/consensus_encoding/contrib/test_vars.sh new file mode 100644 index 000000000..b7f171731 --- /dev/null +++ b/consensus_encoding/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc" + +# Run these examples. +EXAMPLES="encoder:alloc" diff --git a/consensus_encoding/examples/encoder.rs b/consensus_encoding/examples/encoder.rs new file mode 100644 index 000000000..9bd8127fd --- /dev/null +++ b/consensus_encoding/examples/encoder.rs @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Example of creating an encoder that encodes a slice of encodable objects. + +use bitcoin_consensus_encoding as encoding; +use encoding::{ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encodable, Encoder2, SliceEncoder}; + +fn main() { + let v = vec![Inner::new(0xcafe_babe), Inner::new(0xdead_beef)]; + let b = vec![0xab, 0xcd]; + + let adt = Adt::new(v, b); + let encoded = encoding::encode_to_vec(&adt); + + let want = [0x02, 0xca, 0xfe, 0xba, 0xbe, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xcd]; + assert_eq!(encoded, want); +} + +/// Some abstract data type. +struct Adt { + v: Vec, + b: Vec, +} + +impl Adt { + /// Constructs a new `Adt`. + pub fn new(v: Vec, b: Vec) -> Self { Self { v, b } } +} + +encoding::encoder_newtype! { + /// The encoder for the [`Adt`] type. + pub struct AdtEncoder<'e>(Encoder2>, BytesEncoder<'e>>); +} + +impl Encodable for Adt { + type Encoder<'a> + = AdtEncoder<'a> + where + Self: 'a; + + fn encoder(&self) -> Self::Encoder<'_> { + let a = Encoder2::new( + CompactSizeEncoder::new(self.v.len()), + SliceEncoder::without_length_prefix(&self.v), + ); + let b = BytesEncoder::without_length_prefix(self.b.as_ref()); + + AdtEncoder(Encoder2::new(a, b)) + } +} + +/// A simple data type to use as list item. +#[derive(Debug, Default, Clone)] +pub struct Inner(u32); + +impl Inner { + /// Constructs a new `Inner`. + pub fn new(x: u32) -> Self { Self(x) } + + /// Returns some meaningful 4 byte array for this type. + pub fn to_array(&self) -> [u8; 4] { self.0.to_be_bytes() } +} + +encoding::encoder_newtype! { + /// The encoder for the [`Inner`] type. + pub struct InnerEncoder(ArrayEncoder<4>); +} + +impl Encodable for Inner { + type Encoder<'e> = InnerEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + InnerEncoder(ArrayEncoder::without_length_prefix(self.to_array())) + } +} diff --git a/consensus_encoding/src/decode/decoders.rs b/consensus_encoding/src/decode/decoders.rs new file mode 100644 index 000000000..0e9d0a077 --- /dev/null +++ b/consensus_encoding/src/decode/decoders.rs @@ -0,0 +1,1431 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Primitive decoders. + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +#[cfg(feature = "alloc")] +use core::convert::Infallible; +use core::{fmt, mem}; + +use internals::write_err; + +#[cfg(feature = "alloc")] +use super::Decodable; +use super::Decoder; + +/// Maximum size, in bytes, of a vector we are allowed to decode. +#[cfg(feature = "alloc")] +const MAX_VEC_SIZE: u64 = 4_000_000; + +/// Maximum amount of memory (in bytes) to allocate at once when deserializing vectors. +#[cfg(feature = "alloc")] +const MAX_VECTOR_ALLOCATE: usize = 1_000_000; + +/// A decoder that decodes a byte vector. +/// +/// The encoding is expected to start with the number of encoded bytes (length prefix). +#[cfg(feature = "alloc")] +pub struct ByteVecDecoder { + prefix_decoder: Option, + buffer: Vec, + bytes_expected: usize, + bytes_written: usize, +} + +#[cfg(feature = "alloc")] +impl ByteVecDecoder { + /// Constructs a new byte decoder. + pub const fn new() -> Self { + Self { + prefix_decoder: Some(CompactSizeDecoder::new()), + buffer: Vec::new(), + bytes_expected: 0, + bytes_written: 0, + } + } + + /// Reserves capacity for byte vectors in batches. + /// + /// Reserves up to `MAX_VECTOR_ALLOCATE` bytes when the buffer has no remaining capacity. + /// + /// Documentation adapted from Bitcoin Core: + /// + /// > For `DoS` prevention, do not blindly allocate as much as the stream claims to contain. + /// > Instead, allocate in ~1 MB batches, so that an attacker actually needs to provide X MB of + /// > data to make us allocate X+1 MB of memory. + /// + /// ref: + fn reserve(&mut self) { + if self.buffer.len() == self.buffer.capacity() { + let bytes_remaining = self.bytes_expected - self.bytes_written; + let batch_size = bytes_remaining.min(MAX_VECTOR_ALLOCATE); + self.buffer.reserve_exact(batch_size); + } + } +} + +#[cfg(feature = "alloc")] +impl Default for ByteVecDecoder { + fn default() -> Self { Self::new() } +} + +#[cfg(feature = "alloc")] +impl Decoder for ByteVecDecoder { + type Output = Vec; + type Error = ByteVecDecoderError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + use {ByteVecDecoderError as E, ByteVecDecoderErrorInner as Inner}; + + if let Some(mut decoder) = self.prefix_decoder.take() { + if decoder.push_bytes(bytes).map_err(|e| E(Inner::LengthPrefixDecode(e)))? { + self.prefix_decoder = Some(decoder); + return Ok(true); + } + let length = decoder.end().map_err(|e| E(Inner::LengthPrefixDecode(e)))?; + + self.prefix_decoder = None; + self.bytes_expected = + cast_to_usize_if_valid(length).map_err(|e| E(Inner::LengthPrefixInvalid(e)))?; + + // For DoS prevention, let's not allocate all memory upfront. + } + + self.reserve(); + + let remaining = self.bytes_expected - self.bytes_written; + let available_capacity = self.buffer.capacity() - self.buffer.len(); + let copy_len = bytes.len().min(remaining).min(available_capacity); + + self.buffer.extend_from_slice(&bytes[..copy_len]); + self.bytes_written += copy_len; + *bytes = &bytes[copy_len..]; + + // Return true if we still need more data. + Ok(self.bytes_written < self.bytes_expected) + } + + fn end(self) -> Result { + use {ByteVecDecoderError as E, ByteVecDecoderErrorInner as Inner}; + + if self.bytes_written == self.bytes_expected { + Ok(self.buffer) + } else { + Err(E(Inner::UnexpectedEof(UnexpectedEofError { + missing: self.bytes_expected - self.bytes_written, + }))) + } + } + + fn read_limit(&self) -> usize { + if let Some(prefix_decoder) = &self.prefix_decoder { + prefix_decoder.read_limit() + } else { + self.bytes_expected - self.bytes_written + } + } +} + +/// A decoder that decodes a vector of `T`s. +/// +/// The decoding is expected to start with expected number of items in the vector. +#[cfg(feature = "alloc")] +pub struct VecDecoder { + prefix_decoder: Option, + length: usize, + buffer: Vec, + decoder: Option<::Decoder>, +} + +#[cfg(feature = "alloc")] +impl VecDecoder { + /// Constructs a new byte decoder. + pub const fn new() -> Self { + Self { + prefix_decoder: Some(CompactSizeDecoder::new()), + length: 0, + buffer: Vec::new(), + decoder: None, + } + } + + /// Reserves capacity for typed vectors in batches. + /// + /// Calculates how many elements of type `T` fit within `MAX_VECTOR_ALLOCATE` bytes and reserves + /// up to that amount when the buffer reaches capacity. + /// + /// Documentation adapted from Bitcoin Core: + /// + /// > For `DoS` prevention, do not blindly allocate as much as the stream claims to contain. + /// > Instead, allocate in ~1 MB batches, so that an attacker actually needs to provide X MB of + /// > data to make us allocate X+1 MB of memory. + /// + /// ref: + fn reserve(&mut self) { + if self.buffer.len() == self.buffer.capacity() { + let elements_remaining = self.length - self.buffer.len(); + let element_size = mem::size_of::().max(1); + let batch_elements = MAX_VECTOR_ALLOCATE / element_size; + let elements_to_reserve = elements_remaining.min(batch_elements); + self.buffer.reserve_exact(elements_to_reserve); + } + } +} + +#[cfg(feature = "alloc")] +impl Default for VecDecoder { + fn default() -> Self { Self::new() } +} + +#[cfg(feature = "alloc")] +impl Decoder for VecDecoder { + type Output = Vec; + type Error = VecDecoderError<<::Decoder as Decoder>::Error>; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + use {VecDecoderError as E, VecDecoderErrorInner as Inner}; + + if let Some(mut decoder) = self.prefix_decoder.take() { + if decoder.push_bytes(bytes).map_err(|e| E(Inner::LengthPrefixDecode(e)))? { + self.prefix_decoder = Some(decoder); + return Ok(true); + } + let length = decoder.end().map_err(|e| E(Inner::LengthPrefixDecode(e)))?; + if length == 0 { + return Ok(false); + } + + self.prefix_decoder = None; + self.length = + cast_to_usize_if_valid(length).map_err(|e| E(Inner::LengthPrefixInvalid(e)))?; + + // For DoS prevention, let's not allocate all memory upfront. + } + + while !bytes.is_empty() { + self.reserve(); + + let mut decoder = self.decoder.take().unwrap_or_else(T::decoder); + + if decoder.push_bytes(bytes).map_err(|e| E(Inner::Item(e)))? { + self.decoder = Some(decoder); + return Ok(true); + } + let item = decoder.end().map_err(|e| E(Inner::Item(e)))?; + self.buffer.push(item); + + if self.buffer.len() == self.length { + return Ok(false); + } + } + + if self.buffer.len() == self.length { + Ok(false) + } else { + Ok(true) + } + } + + fn end(self) -> Result { + use VecDecoderErrorInner as E; + + if self.buffer.len() == self.length { + Ok(self.buffer) + } else { + Err(VecDecoderError(E::UnexpectedEof(UnexpectedEofError { + missing: self.length - self.buffer.len(), + }))) + } + } + + fn read_limit(&self) -> usize { + if let Some(prefix_decoder) = &self.prefix_decoder { + prefix_decoder.read_limit() + } else if let Some(decoder) = &self.decoder { + decoder.read_limit() + } else if self.buffer.len() == self.length { + // Totally done. + 0 + } else { + let items_left_to_decode = self.length - self.buffer.len(); + let decoder = T::decoder(); + // This could be inaccurate (eg 1 for a `ByteVecDecoder`) but its the best we can do. + let limit_per_decoder = decoder.read_limit(); + items_left_to_decode * limit_per_decoder + } + } +} + +/// Cast a decoded length prefix to a `usize`. +/// +/// Consensus encoded vectors can be up to 4,000,000 bytes long. +/// +/// This is a theoretical max since block size is 4 meg wu and minimum vector element is one byte. +/// +/// # Errors +/// +/// Errors if `n` is greater than 4,000,000 or won't fit in a `usize`. +#[cfg(feature = "alloc")] +pub fn cast_to_usize_if_valid(n: u64) -> Result { + if n > MAX_VEC_SIZE { + return Err(LengthPrefixExceedsMaxError { value: n }); + } + + usize::try_from(n).map_err(|_| LengthPrefixExceedsMaxError { value: n }) +} + +/// A decoder that expects exactly N bytes and returns them as an array. +pub struct ArrayDecoder { + buffer: [u8; N], + bytes_written: usize, +} + +impl ArrayDecoder { + /// Constructs a new array decoder that expects exactly N bytes. + pub const fn new() -> Self { Self { buffer: [0; N], bytes_written: 0 } } +} + +impl Default for ArrayDecoder { + fn default() -> Self { Self::new() } +} + +impl Decoder for ArrayDecoder { + type Output = [u8; N]; + type Error = UnexpectedEofError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + let remaining_space = N - self.bytes_written; + let copy_len = bytes.len().min(remaining_space); + + if copy_len > 0 { + self.buffer[self.bytes_written..self.bytes_written + copy_len] + .copy_from_slice(&bytes[..copy_len]); + self.bytes_written += copy_len; + // Advance the slice reference to consume the bytes. + *bytes = &bytes[copy_len..]; + } + + // Return true if we still need more data. + Ok(self.bytes_written < N) + } + + #[inline] + fn end(self) -> Result { + if self.bytes_written == N { + Ok(self.buffer) + } else { + Err(UnexpectedEofError { missing: N - self.bytes_written }) + } + } + + #[inline] + fn read_limit(&self) -> usize { N - self.bytes_written } +} + +/// A decoder which wraps two inner decoders and returns the output of both. +pub struct Decoder2 +where + A: Decoder, + B: Decoder, +{ + state: Decoder2State, +} + +enum Decoder2State { + /// Decoding the first decoder, with second decoder waiting. + First(A, B), + /// Decoding the second decoder, with the first result stored. + Second(A::Output, B), + /// Decoder has failed and cannot be used again. + Errored, +} + +impl Decoder2 +where + A: Decoder, + B: Decoder, +{ + /// Constructs a new composite decoder. + pub const fn new(first: A, second: B) -> Self { Self { state: Decoder2State::First(first, second) } } +} + +impl Decoder for Decoder2 +where + A: Decoder, + B: Decoder, +{ + type Output = (A::Output, B::Output); + type Error = Decoder2Error; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + loop { + match &mut self.state { + Decoder2State::First(first_decoder, _) => { + if first_decoder.push_bytes(bytes).map_err(Decoder2Error::First)? { + // First decoder wants more data. + return Ok(true); + } + + // First decoder is complete, transition to second. + // If the first decoder fails, the composite decoder + // remains in an Errored state. + match mem::replace(&mut self.state, Decoder2State::Errored) { + Decoder2State::First(first, second) => { + let first_result = first.end().map_err(Decoder2Error::First)?; + self.state = Decoder2State::Second(first_result, second); + } + _ => unreachable!("we know we're in First state"), + } + } + Decoder2State::Second(_, second_decoder) => { + return second_decoder.push_bytes(bytes).map_err(|error| { + self.state = Decoder2State::Errored; + Decoder2Error::Second(error) + }); + } + Decoder2State::Errored => { + panic!("use of failed decoder"); + } + } + } + } + + #[inline] + fn end(self) -> Result { + match self.state { + Decoder2State::First(first_decoder, second_decoder) => { + // This branch is most likely an error since the decoder + // never got to the second one. But letting the error bubble + // up naturally from the child decoders. + let first_result = first_decoder.end().map_err(Decoder2Error::First)?; + let second_result = second_decoder.end().map_err(Decoder2Error::Second)?; + Ok((first_result, second_result)) + } + Decoder2State::Second(first_result, second_decoder) => { + let second_result = second_decoder.end().map_err(Decoder2Error::Second)?; + Ok((first_result, second_result)) + } + Decoder2State::Errored => { + panic!("use of failed decoder"); + } + } + } + + #[inline] + fn read_limit(&self) -> usize { + match &self.state { + Decoder2State::First(first_decoder, second_decoder) => + first_decoder.read_limit() + second_decoder.read_limit(), + Decoder2State::Second(_, second_decoder) => second_decoder.read_limit(), + Decoder2State::Errored => 0, + } + } +} + +/// A decoder which decodes three objects, one after the other. +pub struct Decoder3 +where + A: Decoder, + B: Decoder, + C: Decoder, +{ + inner: Decoder2, C>, +} + +impl Decoder3 +where + A: Decoder, + B: Decoder, + C: Decoder, +{ + /// Constructs a new composite decoder. + pub const fn new(dec_1: A, dec_2: B, dec_3: C) -> Self { + Self { inner: Decoder2::new(Decoder2::new(dec_1, dec_2), dec_3) } + } +} + +impl Decoder for Decoder3 +where + A: Decoder, + B: Decoder, + C: Decoder, +{ + type Output = (A::Output, B::Output, C::Output); + type Error = Decoder3Error; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(|error| match error { + Decoder2Error::First(Decoder2Error::First(a)) => Decoder3Error::First(a), + Decoder2Error::First(Decoder2Error::Second(b)) => Decoder3Error::Second(b), + Decoder2Error::Second(c) => Decoder3Error::Third(c), + }) + } + + #[inline] + fn end(self) -> Result { + let result = self.inner.end().map_err(|error| match error { + Decoder2Error::First(Decoder2Error::First(a)) => Decoder3Error::First(a), + Decoder2Error::First(Decoder2Error::Second(b)) => Decoder3Error::Second(b), + Decoder2Error::Second(c) => Decoder3Error::Third(c), + })?; + + let ((first, second), third) = result; + Ok((first, second, third)) + } + + #[inline] + fn read_limit(&self) -> usize { self.inner.read_limit() } +} + +/// A decoder which decodes four objects, one after the other. +pub struct Decoder4 +where + A: Decoder, + B: Decoder, + C: Decoder, + D: Decoder, +{ + inner: Decoder2, Decoder2>, +} + +impl Decoder4 +where + A: Decoder, + B: Decoder, + C: Decoder, + D: Decoder, +{ + /// Constructs a new composite decoder. + pub const fn new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self { + Self { inner: Decoder2::new(Decoder2::new(dec_1, dec_2), Decoder2::new(dec_3, dec_4)) } + } +} + +impl Decoder for Decoder4 +where + A: Decoder, + B: Decoder, + C: Decoder, + D: Decoder, +{ + type Output = (A::Output, B::Output, C::Output, D::Output); + type Error = Decoder4Error; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(|error| match error { + Decoder2Error::First(Decoder2Error::First(a)) => Decoder4Error::First(a), + Decoder2Error::First(Decoder2Error::Second(b)) => Decoder4Error::Second(b), + Decoder2Error::Second(Decoder2Error::First(c)) => Decoder4Error::Third(c), + Decoder2Error::Second(Decoder2Error::Second(d)) => Decoder4Error::Fourth(d), + }) + } + + #[inline] + fn end(self) -> Result { + let result = self.inner.end().map_err(|error| match error { + Decoder2Error::First(Decoder2Error::First(a)) => Decoder4Error::First(a), + Decoder2Error::First(Decoder2Error::Second(b)) => Decoder4Error::Second(b), + Decoder2Error::Second(Decoder2Error::First(c)) => Decoder4Error::Third(c), + Decoder2Error::Second(Decoder2Error::Second(d)) => Decoder4Error::Fourth(d), + })?; + + let ((first, second), (third, fourth)) = result; + Ok((first, second, third, fourth)) + } + + #[inline] + fn read_limit(&self) -> usize { self.inner.read_limit() } +} + +/// A decoder which decodes six objects, one after the other. +#[allow(clippy::type_complexity)] // Nested composition is easier than flattened alternatives. +pub struct Decoder6 +where + A: Decoder, + B: Decoder, + C: Decoder, + D: Decoder, + E: Decoder, + F: Decoder, +{ + inner: Decoder2, Decoder3>, +} + +impl Decoder6 +where + A: Decoder, + B: Decoder, + C: Decoder, + D: Decoder, + E: Decoder, + F: Decoder, +{ + /// Constructs a new composite decoder. + pub const fn new(dec_1: A, dec_2: B, dec_3: C, dec_4: D, dec_5: E, dec_6: F) -> Self { + Self { + inner: Decoder2::new( + Decoder3::new(dec_1, dec_2, dec_3), + Decoder3::new(dec_4, dec_5, dec_6), + ), + } + } +} + +impl Decoder for Decoder6 +where + A: Decoder, + B: Decoder, + C: Decoder, + D: Decoder, + E: Decoder, + F: Decoder, +{ + type Output = (A::Output, B::Output, C::Output, D::Output, E::Output, F::Output); + type Error = Decoder6Error; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(|error| match error { + Decoder2Error::First(Decoder3Error::First(a)) => Decoder6Error::First(a), + Decoder2Error::First(Decoder3Error::Second(b)) => Decoder6Error::Second(b), + Decoder2Error::First(Decoder3Error::Third(c)) => Decoder6Error::Third(c), + Decoder2Error::Second(Decoder3Error::First(d)) => Decoder6Error::Fourth(d), + Decoder2Error::Second(Decoder3Error::Second(e)) => Decoder6Error::Fifth(e), + Decoder2Error::Second(Decoder3Error::Third(f)) => Decoder6Error::Sixth(f), + }) + } + + #[inline] + fn end(self) -> Result { + let result = self.inner.end().map_err(|error| match error { + Decoder2Error::First(Decoder3Error::First(a)) => Decoder6Error::First(a), + Decoder2Error::First(Decoder3Error::Second(b)) => Decoder6Error::Second(b), + Decoder2Error::First(Decoder3Error::Third(c)) => Decoder6Error::Third(c), + Decoder2Error::Second(Decoder3Error::First(d)) => Decoder6Error::Fourth(d), + Decoder2Error::Second(Decoder3Error::Second(e)) => Decoder6Error::Fifth(e), + Decoder2Error::Second(Decoder3Error::Third(f)) => Decoder6Error::Sixth(f), + })?; + + let ((first, second, third), (fourth, fifth, sixth)) = result; + Ok((first, second, third, fourth, fifth, sixth)) + } + + #[inline] + fn read_limit(&self) -> usize { self.inner.read_limit() } +} + +/// Decodes a compact size encoded integer. +/// +/// For more information about decoder see the documentation of the [`Decoder`] trait. +#[derive(Debug, Clone)] +pub struct CompactSizeDecoder { + buf: internals::array_vec::ArrayVec, +} + +impl CompactSizeDecoder { + /// Constructs a new compact size decoder. + pub const fn new() -> Self { Self { buf: internals::array_vec::ArrayVec::new() } } +} + +impl Default for CompactSizeDecoder { + fn default() -> Self { Self::new() } +} + +impl Decoder for CompactSizeDecoder { + type Output = u64; + type Error = CompactSizeDecoderError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + if bytes.is_empty() { + return Ok(true); + } + + if self.buf.is_empty() { + self.buf.push(bytes[0]); + *bytes = &bytes[1..]; + } + let len = match self.buf[0] { + 0xFF => 9, + 0xFE => 5, + 0xFD => 3, + _ => 1, + }; + let to_copy = bytes.len().min(len - self.buf.len()); + self.buf.extend_from_slice(&bytes[..to_copy]); + *bytes = &bytes[to_copy..]; + + Ok(self.buf.len() != len) + } + + fn end(self) -> Result { + use CompactSizeDecoderErrorInner as E; + + fn arr(slice: &[u8]) -> Result<[u8; N], CompactSizeDecoderError> { + slice.try_into().map_err(|_| { + CompactSizeDecoderError(E::UnexpectedEof { required: N, received: slice.len() }) + }) + } + + let (first, payload) = self + .buf + .split_first() + .ok_or(CompactSizeDecoderError(E::UnexpectedEof { required: 1, received: 0 }))?; + + match *first { + 0xFF => { + let x = u64::from_le_bytes(arr(payload)?); + if x < 0x100_000_000 { + Err(CompactSizeDecoderError(E::NonMinimal { value: x })) + } else { + Ok(x) + } + } + 0xFE => { + let x = u32::from_le_bytes(arr(payload)?); + if x < 0x10000 { + Err(CompactSizeDecoderError(E::NonMinimal { value: x.into() })) + } else { + Ok(x.into()) + } + } + 0xFD => { + let x = u16::from_le_bytes(arr(payload)?); + if x < 0xFD { + Err(CompactSizeDecoderError(E::NonMinimal { value: x.into() })) + } else { + Ok(x.into()) + } + } + n => Ok(n.into()), + } + } + + fn read_limit(&self) -> usize { + match self.buf.len() { + 0 => 1, + already_read => match self.buf[0] { + 0xFF => 9_usize.saturating_sub(already_read), + 0xFE => 5_usize.saturating_sub(already_read), + 0xFD => 3_usize.saturating_sub(already_read), + _ => 0, + }, + } + } +} + +/// An error consensus decoding a compact size encoded integer. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CompactSizeDecoderError(CompactSizeDecoderErrorInner); + +#[derive(Debug, Clone, PartialEq, Eq)] +enum CompactSizeDecoderErrorInner { + /// Returned when the decoder reaches end of stream (EOF). + UnexpectedEof { + /// How many bytes were required. + required: usize, + /// How many bytes were received. + received: usize, + }, + /// Returned when the encoding is not minimal + NonMinimal { + /// The encoded value. + value: u64, + }, +} + +impl fmt::Display for CompactSizeDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use CompactSizeDecoderErrorInner as E; + + match self.0 { + E::UnexpectedEof { required: 1, received: 0 } => { + write!(f, "required at least one byte but the input is empty") + } + E::UnexpectedEof { required, received: 0 } => { + write!(f, "required at least {} bytes but the input is empty", required) + } + E::UnexpectedEof { required, received } => write!( + f, + "required at least {} bytes but only {} bytes were received", + required, received + ), + E::NonMinimal { value } => write!(f, "the value {} was not encoded minimally", value), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for CompactSizeDecoderError {} + +/// The error returned by the [`ByteVecDecoder`]. +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ByteVecDecoderError(ByteVecDecoderErrorInner); + +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +enum ByteVecDecoderErrorInner { + /// Error decoding the byte vector length prefix. + LengthPrefixDecode(CompactSizeDecoderError), + /// Length prefix exceeds 4,000,000. + LengthPrefixInvalid(LengthPrefixExceedsMaxError), + /// Not enough bytes given to decoder. + UnexpectedEof(UnexpectedEofError), +} + +#[cfg(feature = "alloc")] +impl From for ByteVecDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +#[cfg(feature = "alloc")] +impl fmt::Display for ByteVecDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ByteVecDecoderErrorInner as E; + + match self.0 { + E::LengthPrefixDecode(ref e) => write_err!(f, "byte vec decoder error"; e), + E::LengthPrefixInvalid(ref e) => write_err!(f, "byte vec decoder error"; e), + E::UnexpectedEof(ref e) => write_err!(f, "byte vec decoder error"; e), + } + } +} + +#[cfg(all(feature = "std", feature = "alloc"))] +impl std::error::Error for ByteVecDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use ByteVecDecoderErrorInner as E; + + match self.0 { + E::LengthPrefixDecode(ref e) => Some(e), + E::LengthPrefixInvalid(ref e) => Some(e), + E::UnexpectedEof(ref e) => Some(e), + } + } +} + +/// The error returned by the [`VecDecoder`]. +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct VecDecoderError(VecDecoderErrorInner); + +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +enum VecDecoderErrorInner { + /// Error decoding the vector length prefix. + LengthPrefixDecode(CompactSizeDecoderError), + /// Length prefix exceeds 4,000,000. + LengthPrefixInvalid(LengthPrefixExceedsMaxError), + /// Error while decoding an item. + Item(Err), + /// Not enough bytes given to decoder. + UnexpectedEof(UnexpectedEofError), +} + +#[cfg(feature = "alloc")] +impl From for VecDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +#[cfg(feature = "alloc")] +impl fmt::Display for VecDecoderError +where + Err: fmt::Display + fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use VecDecoderErrorInner as E; + + match self.0 { + E::LengthPrefixDecode(ref e) => write_err!(f, "vec decoder error"; e), + E::LengthPrefixInvalid(ref e) => write_err!(f, "vec decoder error"; e), + E::Item(ref e) => write_err!(f, "vec decoder error"; e), + E::UnexpectedEof(ref e) => write_err!(f, "vec decoder error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for VecDecoderError +where + Err: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use VecDecoderErrorInner as E; + + match self.0 { + E::LengthPrefixDecode(ref e) => Some(e), + E::LengthPrefixInvalid(ref e) => Some(e), + E::Item(ref e) => Some(e), + E::UnexpectedEof(ref e) => Some(e), + } + } +} + +/// Length prefix exceeds max value (4,000,000). +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LengthPrefixExceedsMaxError { + /// Decoded value of the compact encoded length prefix. + value: u64, +} + +#[cfg(feature = "alloc")] +impl core::fmt::Display for LengthPrefixExceedsMaxError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let max = match mem::size_of::() { + 1 => u32::from(u8::MAX), + 2 => u32::from(u16::MAX), + _ => 4_000_000, + }; + + write!(f, "length prefix {} exceeds max value {}", self.value, max) + } +} + +#[cfg(all(feature = "std", feature = "alloc"))] +impl std::error::Error for LengthPrefixExceedsMaxError {} + +/// Not enough bytes given to decoder. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UnexpectedEofError { + /// Number of bytes missing to complete decoder. + missing: usize, +} + +impl fmt::Display for UnexpectedEofError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "not enough bytes for decoder, {} more bytes required", self.missing) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnexpectedEofError {} + +/// Error type for [`Decoder2`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Decoder2Error { + /// Error from the first decoder. + First(A), + /// Error from the second decoder. + Second(B), +} + +impl fmt::Display for Decoder2Error +where + A: fmt::Display, + B: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::First(ref e) => write_err!(f, "first decoder error"; e), + Self::Second(ref e) => write_err!(f, "second decoder error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Decoder2Error +where + A: std::error::Error + 'static, + B: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::First(ref e) => Some(e), + Self::Second(ref e) => Some(e), + } + } +} + +/// Error type for [`Decoder3`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Decoder3Error { + /// Error from the first decoder. + First(A), + /// Error from the second decoder. + Second(B), + /// Error from the third decoder. + Third(C), +} + +impl fmt::Display for Decoder3Error +where + A: fmt::Display, + B: fmt::Display, + C: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::First(ref e) => write_err!(f, "first decoder error"; e), + Self::Second(ref e) => write_err!(f, "second decoder error"; e), + Self::Third(ref e) => write_err!(f, "third decoder error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Decoder3Error +where + A: std::error::Error + 'static, + B: std::error::Error + 'static, + C: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::First(ref e) => Some(e), + Self::Second(ref e) => Some(e), + Self::Third(ref e) => Some(e), + } + } +} + +/// Error type for [`Decoder4`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Decoder4Error { + /// Error from the first decoder. + First(A), + /// Error from the second decoder. + Second(B), + /// Error from the third decoder. + Third(C), + /// Error from the fourth decoder. + Fourth(D), +} + +impl fmt::Display for Decoder4Error +where + A: fmt::Display, + B: fmt::Display, + C: fmt::Display, + D: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::First(ref e) => write_err!(f, "first decoder error"; e), + Self::Second(ref e) => write_err!(f, "second decoder error"; e), + Self::Third(ref e) => write_err!(f, "third decoder error"; e), + Self::Fourth(ref e) => write_err!(f, "fourth decoder error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Decoder4Error +where + A: std::error::Error + 'static, + B: std::error::Error + 'static, + C: std::error::Error + 'static, + D: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::First(ref e) => Some(e), + Self::Second(ref e) => Some(e), + Self::Third(ref e) => Some(e), + Self::Fourth(ref e) => Some(e), + } + } +} + +/// Error type for [`Decoder6`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Decoder6Error { + /// Error from the first decoder. + First(A), + /// Error from the second decoder. + Second(B), + /// Error from the third decoder. + Third(C), + /// Error from the fourth decoder. + Fourth(D), + /// Error from the fifth decoder. + Fifth(E), + /// Error from the sixth decoder. + Sixth(F), +} + +impl fmt::Display for Decoder6Error +where + A: fmt::Display, + B: fmt::Display, + C: fmt::Display, + D: fmt::Display, + E: fmt::Display, + F: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::First(ref e) => write_err!(f, "first decoder error"; e), + Self::Second(ref e) => write_err!(f, "second decoder error"; e), + Self::Third(ref e) => write_err!(f, "third decoder error"; e), + Self::Fourth(ref e) => write_err!(f, "fourth decoder error"; e), + Self::Fifth(ref e) => write_err!(f, "fifth decoder error"; e), + Self::Sixth(ref e) => write_err!(f, "sixth decoder error"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Decoder6Error +where + A: std::error::Error + 'static, + B: std::error::Error + 'static, + C: std::error::Error + 'static, + D: std::error::Error + 'static, + E: std::error::Error + 'static, + F: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::First(ref e) => Some(e), + Self::Second(ref e) => Some(e), + Self::Third(ref e) => Some(e), + Self::Fourth(ref e) => Some(e), + Self::Fifth(ref e) => Some(e), + Self::Sixth(ref e) => Some(e), + } + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "alloc")] + use alloc::vec; + #[cfg(feature = "alloc")] + use alloc::vec::Vec; + #[cfg(feature = "alloc")] + use core::iter; + #[cfg(feature = "std")] + use std::io::Cursor; + + use super::*; + + // Stress test the push_bytes impl by passing in a single byte slice repeatedly. + macro_rules! check_decode_one_byte_at_a_time { + ($decoder:ident $($test_name:ident, $want:expr, $array:expr);* $(;)?) => { + $( + #[test] + #[allow(non_snake_case)] + fn $test_name() { + let mut decoder = $decoder::default(); + + for (i, _) in $array.iter().enumerate() { + if i < $array.len() - 1 { + let mut p = &$array[i..i+1]; + assert!(decoder.push_bytes(&mut p).unwrap()); + } else { + // last byte: `push_bytes` should return false since no more bytes required. + let mut p = &$array[i..]; + assert!(!decoder.push_bytes(&mut p).unwrap()); + } + } + + let got = decoder.end().unwrap(); + assert_eq!(got, $want); + } + )* + + } + } + + check_decode_one_byte_at_a_time! { + CompactSizeDecoder + decode_compact_size_0x10, 0x10, [0x10]; + decode_compact_size_0xFC, 0xFC, [0xFC]; + decode_compact_size_0xFD, 0xFD, [0xFD, 0xFD, 0x00]; + decode_compact_size_0x100, 0x100, [0xFD, 0x00, 0x01]; + decode_compact_size_0xFFF, 0x0FFF, [0xFD, 0xFF, 0x0F]; + decode_compact_size_0x0F0F_0F0F, 0x0F0F_0F0F, [0xFE, 0xF, 0xF, 0xF, 0xF]; + decode_compact_size_0xF0F0_F0F0_F0E0, 0xF0F0_F0F0_F0E0, [0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0]; + } + + #[test] + #[cfg(feature = "alloc")] + fn compact_size_zero() { + // Zero (eg for an empty vector) with a couple of arbitrary extra bytes. + let encoded = alloc::vec![0x00, 0xFF, 0xFF]; + + let mut slice = encoded.as_slice(); + let mut decoder = CompactSizeDecoder::new(); + assert!(!decoder.push_bytes(&mut slice).unwrap()); + + let got = decoder.end().unwrap(); + assert_eq!(got, 0); + } + + #[cfg(feature = "alloc")] + fn two_fifty_six_bytes_encoded() -> Vec { + let data = [0xff; 256]; + let mut v = Vec::with_capacity(259); + + v.extend_from_slice(&[0xFD, 0x00, 0x01]); // 256 encoded as a compact size. + v.extend_from_slice(&data); + v + } + + #[cfg(feature = "alloc")] + check_decode_one_byte_at_a_time! { + ByteVecDecoder + decode_byte_vec, alloc::vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef], + [0x08, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; + decode_byte_vec_multi_byte_length_prefix, [0xff; 256], two_fifty_six_bytes_encoded(); + } + + #[test] + #[cfg(feature = "alloc")] + fn byte_vec_decoder_reserves_in_batches() { + // A small number of extra bytes so we extend exactly by the remainder + // instead of another full batch. + let tail_length: usize = 11; + + let total_len = MAX_VECTOR_ALLOCATE + tail_length; + let total_len_le = u32::try_from(total_len).expect("total_len fits u32").to_le_bytes(); + let mut decoder = ByteVecDecoder::new(); + + let mut prefix = vec![0xFE]; // total_len_le is a compact size of four bytes. + prefix.extend_from_slice(&total_len_le); + prefix.push(0xAA); + let mut prefix_slice = prefix.as_slice(); + decoder.push_bytes(&mut prefix_slice).expect("length plus first element"); + assert!(prefix_slice.is_empty()); + + assert_eq!(decoder.buffer.capacity(), MAX_VECTOR_ALLOCATE); + assert_eq!(decoder.buffer.len(), 1); + assert_eq!(decoder.buffer[0], 0xAA); + + let fill = vec![0xBB; MAX_VECTOR_ALLOCATE - 1]; + let mut fill_slice = fill.as_slice(); + decoder.push_bytes(&mut fill_slice).expect("fills to batch boundary, full capacity"); + assert!(fill_slice.is_empty()); + + assert_eq!(decoder.buffer.capacity(), MAX_VECTOR_ALLOCATE); + assert_eq!(decoder.buffer.len(), MAX_VECTOR_ALLOCATE); + assert_eq!(decoder.buffer[MAX_VECTOR_ALLOCATE - 1], 0xBB); + + let mut tail = vec![0xCC]; + tail.extend([0xDD].repeat(tail_length - 1)); + let mut tail_slice = tail.as_slice(); + decoder.push_bytes(&mut tail_slice).expect("fills the remaining bytes"); + assert!(tail_slice.is_empty()); + + assert_eq!(decoder.buffer.capacity(), MAX_VECTOR_ALLOCATE + tail_length); + assert_eq!(decoder.buffer.len(), total_len); + assert_eq!(decoder.buffer[MAX_VECTOR_ALLOCATE], 0xCC); + + let result = decoder.end().unwrap(); + assert_eq!(result.len(), total_len); + assert_eq!(result[total_len - 1 ], 0xDD); + } + + #[cfg(feature = "alloc")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub struct Inner(u32); + + /// The decoder for the [`Inner`] type. + #[cfg(feature = "alloc")] + pub struct InnerDecoder(ArrayDecoder<4>); + + #[cfg(feature = "alloc")] + impl Decoder for InnerDecoder { + type Output = Inner; + type Error = UnexpectedEofError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.0.push_bytes(bytes) + } + + fn end(self) -> Result { + let n = u32::from_le_bytes(self.0.end()?); + Ok(Inner(n)) + } + + fn read_limit(&self) -> usize { self.0.read_limit() } + } + + #[cfg(feature = "alloc")] + impl Decodable for Inner { + type Decoder = InnerDecoder; + fn decoder() -> Self::Decoder { InnerDecoder(ArrayDecoder::<4>::new()) } + } + + #[cfg(feature = "alloc")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub struct Test(Vec); + + /// The decoder for the [`Test`] type. + #[cfg(feature = "alloc")] + #[derive(Default)] + pub struct TestDecoder(VecDecoder); + + #[cfg(feature = "alloc")] + impl Decoder for TestDecoder { + type Output = Test; + type Error = VecDecoderError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.0.push_bytes(bytes) + } + + fn end(self) -> Result { + let v = self.0.end()?; + Ok(Test(v)) + } + + fn read_limit(&self) -> usize { self.0.read_limit() } + } + + #[cfg(feature = "alloc")] + impl Decodable for Test { + type Decoder = TestDecoder; + fn decoder() -> Self::Decoder { TestDecoder(VecDecoder::new()) } + } + + #[test] + #[cfg(feature = "alloc")] + fn vec_decoder_empty() { + // Empty with a couple of arbitrary extra bytes. + let encoded = vec![0x00, 0xFF, 0xFF]; + + let mut slice = encoded.as_slice(); + let mut decoder = Test::decoder(); + assert!(!decoder.push_bytes(&mut slice).unwrap()); + + let got = decoder.end().unwrap(); + let want = Test(vec![]); + + assert_eq!(got, want); + } + + #[test] + #[cfg(feature = "alloc")] + fn vec_decoder_one_item() { + let encoded = vec![0x01, 0xEF, 0xBE, 0xAD, 0xDE]; + + let mut slice = encoded.as_slice(); + let mut decoder = Test::decoder(); + decoder.push_bytes(&mut slice).unwrap(); + + let got = decoder.end().unwrap(); + let want = Test(vec![Inner(0xDEAD_BEEF)]); + + assert_eq!(got, want); + } + + #[test] + #[cfg(feature = "alloc")] + fn vec_decoder_two_items() { + let encoded = vec![0x02, 0xEF, 0xBE, 0xAD, 0xDE, 0xBE, 0xBA, 0xFE, 0xCA]; + + let mut slice = encoded.as_slice(); + let mut decoder = Test::decoder(); + decoder.push_bytes(&mut slice).unwrap(); + + let got = decoder.end().unwrap(); + let want = Test(vec![Inner(0xDEAD_BEEF), Inner(0xCAFE_BABE)]); + + assert_eq!(got, want); + } + + #[test] + #[cfg(feature = "alloc")] + fn vec_decoder_reserves_in_batches() { + // A small number of extra elements so we extend exactly by the remainder + // instead of another full batch. + let tail_length: usize = 11; + + let element_size = core::mem::size_of::(); + let batch_length = MAX_VECTOR_ALLOCATE / element_size; + assert!(batch_length > 1); + let total_len = batch_length + tail_length; + let total_len_le = u32::try_from(total_len).expect("total_len fits u32").to_le_bytes(); + let mut decoder = Test::decoder(); + + let mut prefix = vec![0xFE]; // total_len_le is a compact size of four bytes. + prefix.extend_from_slice(&total_len_le); + prefix.extend_from_slice(&0xAA_u32.to_le_bytes()); + let mut prefix_slice = prefix.as_slice(); + decoder.push_bytes(&mut prefix_slice).expect("length plus first element"); + assert!(prefix_slice.is_empty()); + + assert_eq!(decoder.0.buffer.capacity(), batch_length); + assert_eq!(decoder.0.buffer.len(), 1); + assert_eq!(decoder.0.buffer[0], Inner(0xAA)); + + let fill = 0xBB_u32.to_le_bytes().repeat(batch_length - 1); + let mut fill_slice = fill.as_slice(); + decoder.push_bytes(&mut fill_slice).expect("fills to batch boundary, full capacity"); + assert!(fill_slice.is_empty()); + + assert_eq!(decoder.0.buffer.capacity(), batch_length); + assert_eq!(decoder.0.buffer.len(), batch_length); + assert_eq!(decoder.0.buffer[batch_length - 1], Inner(0xBB)); + + let mut tail = 0xCC_u32.to_le_bytes().to_vec(); + tail.extend(0xDD_u32.to_le_bytes().repeat(tail_length - 1)); + let mut tail_slice = tail.as_slice(); + decoder.push_bytes(&mut tail_slice).expect("fills the remaining bytes"); + assert!(tail_slice.is_empty()); + + assert_eq!(decoder.0.buffer.capacity(), batch_length + tail_length); + assert_eq!(decoder.0.buffer.len(), total_len); + assert_eq!(decoder.0.buffer[batch_length], Inner(0xCC)); + + let Test(result) = decoder.end().unwrap(); + assert_eq!(result.len(), total_len); + assert_eq!(result[total_len - 1 ], Inner(0xDD)); + } + + #[cfg(feature = "alloc")] + fn two_fifty_six_elements() -> Test { + Test(iter::repeat(Inner(0xDEAD_BEEF)).take(256).collect()) + } + + #[cfg(feature = "alloc")] + fn two_fifty_six_elements_encoded() -> Vec { + [0xFD, 0x00, 0x01] // 256 encoded as a compact size. + .into_iter() + .chain(iter::repeat(0xDEAD_BEEF_u32.to_le_bytes()).take(256).flatten()) + .collect() + } + + #[cfg(feature = "alloc")] + check_decode_one_byte_at_a_time! { + TestDecoder + decode_vec, Test(vec![Inner(0xDEAD_BEEF), Inner(0xCAFE_BABE)]), + vec![0x02, 0xEF, 0xBE, 0xAD, 0xDE, 0xBE, 0xBA, 0xFE, 0xCA]; + decode_vec_multi_byte_length_prefix, two_fifty_six_elements(), two_fifty_six_elements_encoded(); + } + + #[test] + #[cfg(feature = "alloc")] + fn vec_decoder_one_item_plus_more_data() { + // One u32 plus some other bytes. + let encoded = vec![0x01, 0xEF, 0xBE, 0xAD, 0xDE, 0xff, 0xff, 0xff, 0xff]; + + let mut slice = encoded.as_slice(); + + let mut decoder = Test::decoder(); + decoder.push_bytes(&mut slice).unwrap(); + + let got = decoder.end().unwrap(); + let want = Test(vec![Inner(0xDEAD_BEEF)]); + + assert_eq!(got, want); + } + + #[cfg(feature = "std")] + #[test] + fn decode_vec_from_read_unbuffered_success() { + let encoded = [0x01, 0xEF, 0xBE, 0xAD, 0xDE, 0xff, 0xff, 0xff, 0xff]; + let mut cursor = Cursor::new(&encoded); + + let got = crate::decode_from_read_unbuffered::(&mut cursor).unwrap(); + assert_eq!(cursor.position(), 5); + + let want = Test(vec![Inner(0xDEAD_BEEF)]); + assert_eq!(got, want); + } +} diff --git a/consensus_encoding/src/decode/mod.rs b/consensus_encoding/src/decode/mod.rs new file mode 100644 index 000000000..e1d3e7053 --- /dev/null +++ b/consensus_encoding/src/decode/mod.rs @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Consensus Decoding Traits + +pub mod decoders; + +/// A Bitcoin object which can be consensus-decoded using a push decoder. +/// +/// To decode something, create a [`Self::Decoder`] and push byte slices +/// into it with [`Decoder::push_bytes`], then call [`Decoder::end`] to get the result. +pub trait Decodable { + /// Associated decoder for the type. + type Decoder: Decoder; + /// Constructs a "default decoder" for the type. + fn decoder() -> Self::Decoder; +} + +/// A push decoder for a consensus-decodable object. +pub trait Decoder: Sized { + /// The type that this decoder produces when decoding is complete. + type Output; + /// The error type that this decoder can produce. + type Error; + + /// Push bytes into the decoder, consuming as much as possible. + /// + /// The slice reference will be advanced to point to the unconsumed portion. + /// Returns `Ok(true)` if more bytes are needed to complete decoding, + /// `Ok(false)` if the decoder is ready to finalize with [`Self::end`], + /// or `Err(error)` if parsing failed. + /// + /// # Errors + /// + /// Returns an error if the provided bytes are invalid or malformed according + /// to the decoder's validation rules. Insufficient data (needing more + /// bytes) is *not* an error for this method, the decoder will simply consume + /// what it can and return `true` to indicate more data is needed. + /// + /// # Panics + /// + /// May panic if called after a previous call to [`Self::push_bytes`] errored. + #[must_use = "must check result to avoid panics on subsequent calls"] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result; + + /// Complete the decoding process and return the final result. + /// + /// This consumes the decoder and should be called when no more input + /// data is available. + /// + /// # Errors + /// + /// Returns an error if the decoder has not received sufficient data to + /// complete decoding, or if the accumulated data is invalid when considered + /// as a complete object. + /// + /// # Panics + /// + /// May panic if called after a previous call to [`Self::push_bytes`] errored. + #[must_use = "must check result to avoid panics on subsequent calls"] + fn end(self) -> Result; + + /// Returns the maximum number of bytes this decoder can consume without over-reading. + /// + /// Returns 0 if the decoder is complete and ready to finalize with [`Self::end`]. + /// This is used by [`decode_from_read_unbuffered`] to optimize read sizes, + /// avoiding both inefficient under-reads and unnecessary over-reads. + fn read_limit(&self) -> usize; +} + +/// Decodes an object from a byte slice. +/// +/// # Errors +/// +/// Returns an error if the decoder encounters an error while +/// parsing the data, including insufficient data. +pub fn decode_from_slice(bytes: &[u8]) -> Result::Error> +where + T: Decodable, +{ + let mut decoder = T::decoder(); + let mut remaining = bytes; + + while !remaining.is_empty() { + if !decoder.push_bytes(&mut remaining)? { + break; + } + } + + decoder.end() +} + +/// Decodes an object from a buffered reader. +/// +/// # Performance +/// +/// For unbuffered readers (like [`std::fs::File`] or [`std::net::TcpStream`]), +/// consider wrapping your reader with [`std::io::BufReader`] in order to use +/// this function. This avoids frequent small reads, which can significantly +/// impact performance. +/// +/// # Errors +/// +/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing +/// the data, or [`ReadError::Io`] if an I/O error occurs while reading. +#[cfg(feature = "std")] +pub fn decode_from_read(mut reader: R) -> Result::Error>> +where + T: Decodable, + R: std::io::BufRead, +{ + let mut decoder = T::decoder(); + + loop { + let mut buffer = match reader.fill_buf() { + Ok(buffer) => buffer, + // Auto retry read for non-fatal error. + Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue, + Err(error) => return Err(ReadError::Io(error)), + }; + + if buffer.is_empty() { + // EOF, but still try to finalize the decoder. + return decoder.end().map_err(ReadError::Decode); + } + + let original_len = buffer.len(); + let need_more = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?; + let consumed = original_len - buffer.len(); + reader.consume(consumed); + + if !need_more { + return decoder.end().map_err(ReadError::Decode); + } + } +} + +/// Decodes an object from an unbuffered reader using a fixed-size buffer. +/// +/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. +/// This function is only needed when you have an unbuffered reader which you +/// cannot wrap. It will probably have worse performance. +/// +/// # Buffer +/// +/// Uses a fixed 4KB (4096 bytes) stack-allocated buffer that is reused across +/// read operations. This size is a good balance between memory usage and +/// system call efficiency for most use cases. +/// +/// For different buffer sizes, use [`decode_from_read_unbuffered_with`]. +/// +/// # Errors +/// +/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing +/// the data, or [`ReadError::Io`] if an I/O error occurs while reading. +#[cfg(feature = "std")] +pub fn decode_from_read_unbuffered( + reader: R, +) -> Result::Error>> +where + T: Decodable, + R: std::io::Read, +{ + decode_from_read_unbuffered_with::(reader) +} + +/// Decodes an object from an unbuffered reader using a custom-sized buffer. +/// +/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. +/// This function is only needed when you have an unbuffered reader which you +/// cannot wrap. It will probably have worse performance. +/// +/// # Buffer +/// +/// The `BUFFER_SIZE` parameter controls the intermediate buffer size used for +/// reading. The buffer is allocated on the stack (not heap) and reused across +/// read operations. Larger buffers reduce the number of system calls, but use +/// more memory. +/// +/// # Errors +/// +/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing +/// the data, or [`ReadError::Io`] if an I/O error occurs while reading. +#[cfg(feature = "std")] +pub fn decode_from_read_unbuffered_with( + mut reader: R, +) -> Result::Error>> +where + T: Decodable, + R: std::io::Read, +{ + let mut decoder = T::decoder(); + let mut buffer = [0u8; BUFFER_SIZE]; + + while decoder.read_limit() > 0 { + // Only read what we need, up to buffer size. + let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)]; + match reader.read(clamped_buffer) { + Ok(0) => { + // EOF, but still try to finalize the decoder. + return decoder.end().map_err(ReadError::Decode); + } + Ok(bytes_read) => { + if !decoder + .push_bytes(&mut &clamped_buffer[..bytes_read]) + .map_err(ReadError::Decode)? + { + return decoder.end().map_err(ReadError::Decode); + } + } + Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => { + // Auto retry read for non-fatal error. + } + Err(e) => return Err(ReadError::Io(e)), + } + } + + decoder.end().map_err(ReadError::Decode) +} + +/// An error that can occur when reading and decoding from a buffered reader. +#[cfg(feature = "std")] +#[derive(Debug)] +pub enum ReadError { + /// An I/O error occurred while reading from the reader. + Io(std::io::Error), + /// The decoder encountered an error while parsing the data. + Decode(D), +} + +#[cfg(feature = "std")] +impl core::fmt::Display for ReadError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Io(e) => write!(f, "I/O error: {}", e), + Self::Decode(e) => write!(f, "decode error: {}", e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ReadError +where + D: core::fmt::Debug + core::fmt::Display + std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Io(e) => Some(e), + Self::Decode(e) => Some(e), + } + } +} + +#[cfg(feature = "std")] +impl From for ReadError { + fn from(e: std::io::Error) -> Self { Self::Io(e) } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "std")] + use alloc::vec::Vec; + #[cfg(feature = "std")] + use std::io::{Cursor, Read}; + + use super::*; + use crate::decode::decoders::{ArrayDecoder, UnexpectedEofError}; + + #[derive(Debug, PartialEq)] + struct TestArray([u8; 4]); + + impl Decodable for TestArray { + type Decoder = TestArrayDecoder; + fn decoder() -> Self::Decoder { TestArrayDecoder { inner: ArrayDecoder::new() } } + } + + struct TestArrayDecoder { + inner: ArrayDecoder<4>, + } + + impl Decoder for TestArrayDecoder { + type Output = TestArray; + type Error = UnexpectedEofError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes) + } + + fn end(self) -> Result { self.inner.end().map(TestArray) } + + fn read_limit(&self) -> usize { self.inner.read_limit() } + } + + #[test] + fn decode_from_slice_success() { + let data = [1, 2, 3, 4]; + let result: Result = decode_from_slice(&data); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + fn decode_from_slice_unexpected_eof() { + let data = [1, 2, 3]; + let result: Result = decode_from_slice(&data); + assert!(result.is_err()); + } + + #[test] + fn decode_from_slice_extra_data() { + let data = [1, 2, 3, 4, 5]; + let result: Result = decode_from_slice(&data); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_extra_data() { + let data = [1, 2, 3, 4, 5, 6]; + let mut cursor = Cursor::new(&data); + let result: Result = decode_from_read(&mut cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_success() { + let data = [1, 2, 3, 4]; + let cursor = Cursor::new(&data); + let result: Result = decode_from_read(cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_unexpected_eof() { + let data = [1, 2, 3]; + let cursor = Cursor::new(&data); + let result: Result = decode_from_read(cursor); + assert!(matches!(result, Err(ReadError::Decode(_)))); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_trait_object() { + let data = [1, 2, 3, 4]; + let mut cursor = Cursor::new(&data); + // Test that we can pass a trait object (&mut dyn BufRead implements BufRead). + let reader: &mut dyn std::io::BufRead = &mut cursor; + let result: Result = decode_from_read(reader); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_by_reference() { + let data = [1, 2, 3, 4]; + let mut cursor = Cursor::new(&data); + // Test that we can pass by reference (&mut T implements BufRead when T: BufRead). + let result: Result = decode_from_read(&mut cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + + let mut buf = Vec::new(); + let _ = cursor.read_to_end(&mut buf); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_unbuffered_success() { + let data = [1, 2, 3, 4]; + let cursor = Cursor::new(&data); + let result: Result = decode_from_read_unbuffered(cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_unbuffered_unexpected_eof() { + let data = [1, 2, 3]; + let cursor = Cursor::new(&data); + let result: Result = decode_from_read_unbuffered(cursor); + assert!(matches!(result, Err(ReadError::Decode(_)))); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_unbuffered_empty() { + let data = []; + let cursor = Cursor::new(&data); + let result: Result = decode_from_read_unbuffered(cursor); + assert!(matches!(result, Err(ReadError::Decode(_)))); + } + + #[test] + #[cfg(feature = "std")] + fn decode_from_read_unbuffered_extra_data() { + let data = [1, 2, 3, 4, 5, 6]; + let cursor = Cursor::new(&data); + let result: Result = decode_from_read_unbuffered(cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } +} diff --git a/consensus_encoding/src/encode/encoders.rs b/consensus_encoding/src/encode/encoders.rs new file mode 100644 index 000000000..1d20bd2ce --- /dev/null +++ b/consensus_encoding/src/encode/encoders.rs @@ -0,0 +1,632 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Collection of "standard encoders". +//! +//! These encoders should not be used directly. Instead, when implementing the +//! [`super::Encodable`] trait on a type, you should define a newtype around one +//! or more of these encoders, and pass through the [`Encoder`] implementation +//! to your newtype. This avoids leaking encoding implementation details to the +//! users of your type. +//! +//! For implementing these newtypes, we provide the [`encoder_newtype`] macro. +//! + +use internals::array_vec::ArrayVec; +use internals::compact_size; + +use super::{Encodable, Encoder}; + +/// The maximum length of a compact size encoding. +const SIZE: usize = 9; + +/// An encoder for a single byte slice. +pub struct BytesEncoder<'sl> { + sl: Option<&'sl [u8]>, +} + +impl<'sl> BytesEncoder<'sl> { + /// Constructs a byte encoder which encodes the given byte slice, with no length prefix. + pub const fn without_length_prefix(sl: &'sl [u8]) -> Self { Self { sl: Some(sl) } } +} + +impl Encoder for BytesEncoder<'_> { + fn current_chunk(&self) -> &[u8] { self.sl.unwrap_or_default() } + + fn advance(&mut self) -> bool { + self.sl = None; + false + } +} + +/// An encoder for a single array. +pub struct ArrayEncoder { + arr: Option<[u8; N]>, +} + +impl ArrayEncoder { + /// Constructs an encoder which encodes the array with no length prefix. + pub const fn without_length_prefix(arr: [u8; N]) -> Self { Self { arr: Some(arr) } } +} + +impl Encoder for ArrayEncoder { + #[inline] + fn current_chunk(&self) -> &[u8] { self.arr.as_ref().map(|x| &x[..]).unwrap_or_default() } + + #[inline] + fn advance(&mut self) -> bool { + self.arr = None; + false + } +} + +/// An encoder for a list of encodable types. +pub struct SliceEncoder<'e, T: Encodable> { + /// The list of references to the objects we are encoding. + sl: &'e [T], + /// Encoder for the current object being encoded. + cur_enc: Option>, +} + +impl<'e, T: Encodable> SliceEncoder<'e, T> { + /// Constructs an encoder which encodes the slice _without_ adding the length prefix. + /// + /// To encode with a length prefix consider using the `Encoder2`. + /// + /// E.g, `Encoder2>`. + pub fn without_length_prefix(sl: &'e [T]) -> Self { + // In this `map` call we cannot remove the closure. Seems to be a bug in the compiler. + // Perhaps https://github.com/rust-lang/rust/issues/102540 which is 3 years old with + // no replies or even an acknowledgement. We will not bother filing our own issue. + Self { sl, cur_enc: sl.first().map(|x| T::encoder(x)) } + } +} + +impl Encoder for SliceEncoder<'_, T> { + fn current_chunk(&self) -> &[u8] { + // `advance` sets `cur_enc` to `None` once the slice encoder is completely exhausted. + self.cur_enc.as_ref().map(T::Encoder::current_chunk).unwrap_or_default() + } + + fn advance(&mut self) -> bool { + let Some(cur) = self.cur_enc.as_mut() else { + return false; + }; + + loop { + // On subsequent calls, attempt to advance the current encoder and return + // success if this succeeds. + if cur.advance() { + return true; + } + // self.sl guaranteed to be non-empty if cur is non-None. + self.sl = &self.sl[1..]; + + // If advancing the current encoder failed, attempt to move to the next encoder. + if let Some(x) = self.sl.first() { + *cur = x.encoder(); + if !cur.current_chunk().is_empty() { + return true; + } + } else { + self.cur_enc = None; // shortcut the next call to advance() + return false; + } + } + } +} + +/// An encoder which encodes two objects, one after the other. +pub struct Encoder2 { + enc_idx: usize, + enc_1: A, + enc_2: B, +} + +impl Encoder2 { + /// Constructs a new composite encoder. + pub const fn new(enc_1: A, enc_2: B) -> Self { Self { enc_idx: 0, enc_1, enc_2 } } +} + +impl Encoder for Encoder2 { + #[inline] + fn current_chunk(&self) -> &[u8] { + if self.enc_idx == 0 { + self.enc_1.current_chunk() + } else { + self.enc_2.current_chunk() + } + } + + #[inline] + fn advance(&mut self) -> bool { + if self.enc_idx == 0 { + if !self.enc_1.advance() { + self.enc_idx += 1; + } + true + } else { + self.enc_2.advance() + } + } +} + +// For now we implement every higher encoder by composing Encoder2s, because +// I'm lazy and this is trivial both to write and to review. For efficiency, we +// should eventually unroll all of these. There are only a couple of them. The +// unrolled versions should be macro-izable, if we want to do that. + +/// An encoder which encodes three objects, one after the other. +pub struct Encoder3 { + inner: Encoder2, C>, +} + +impl Encoder3 { + /// Constructs a new composite encoder. + pub const fn new(enc_1: A, enc_2: B, enc_3: C) -> Self { + Self { inner: Encoder2::new(Encoder2::new(enc_1, enc_2), enc_3) } + } +} + +impl Encoder for Encoder3 { + #[inline] + fn current_chunk(&self) -> &[u8] { self.inner.current_chunk() } + #[inline] + fn advance(&mut self) -> bool { self.inner.advance() } +} + +/// An encoder which encodes four objects, one after the other. +pub struct Encoder4 { + inner: Encoder2, Encoder2>, +} + +impl Encoder4 { + /// Constructs a new composite encoder. + pub const fn new(enc_1: A, enc_2: B, enc_3: C, enc_4: D) -> Self { + Self { inner: Encoder2::new(Encoder2::new(enc_1, enc_2), Encoder2::new(enc_3, enc_4)) } + } +} + +impl Encoder for Encoder4 { + #[inline] + fn current_chunk(&self) -> &[u8] { self.inner.current_chunk() } + #[inline] + fn advance(&mut self) -> bool { self.inner.advance() } +} + +/// An encoder which encodes six objects, one after the other. +pub struct Encoder6 { + inner: Encoder2, Encoder3>, +} + +impl Encoder6 { + /// Constructs a new composite encoder. + pub const fn new(enc_1: A, enc_2: B, enc_3: C, enc_4: D, enc_5: E, enc_6: F) -> Self { + Self { + inner: Encoder2::new( + Encoder3::new(enc_1, enc_2, enc_3), + Encoder3::new(enc_4, enc_5, enc_6), + ), + } + } +} + +impl Encoder + for Encoder6 +{ + #[inline] + fn current_chunk(&self) -> &[u8] { self.inner.current_chunk() } + #[inline] + fn advance(&mut self) -> bool { self.inner.advance() } +} + +/// Encoder for a compact size encoded integer. +pub struct CompactSizeEncoder { + buf: Option>, +} + +impl CompactSizeEncoder { + /// Constructs a new `CompactSizeEncoder`. + /// + /// Encodings are defined only for the range of u64. On systems where usize is + /// larger than u64, it will be possible to call this method with out-of-range + /// values. In such cases we will ignore the passed value and encode [`u64::MAX`]. + /// But even on such exotic systems, we expect users to pass the length of an + /// in-memory object, meaning that such large values are impossible to obtain. + pub fn new(value: usize) -> Self { + let enc_value = value.try_into().unwrap_or(u64::MAX); + Self { buf: Some(compact_size::encode(enc_value)) } + } +} + +impl Encoder for CompactSizeEncoder { + #[inline] + fn current_chunk(&self) -> &[u8] { self.buf.as_ref().map(|b| &b[..]).unwrap_or_default() } + + #[inline] + fn advance(&mut self) -> bool { + self.buf = None; + false + } +} + +#[cfg(test)] +mod tests { + use super::*; + + struct TestBytes<'a>(&'a [u8]); + + impl Encodable for TestBytes<'_> { + type Encoder<'s> + = BytesEncoder<'s> + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { BytesEncoder::without_length_prefix(self.0) } + } + + struct TestArray([u8; N]); + + impl Encodable for TestArray { + type Encoder<'s> + = ArrayEncoder + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { ArrayEncoder::without_length_prefix(self.0) } + } + + #[test] + fn encode_array_with_data() { + // Should have one chunk with the array data, then exhausted. + let test_array = TestArray([1u8, 2, 3, 4]); + let mut encoder = test_array.encoder(); + assert_eq!(encoder.current_chunk(), &[1u8, 2, 3, 4][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_empty_array() { + // Empty array should have one empty chunk, then exhausted. + let test_array = TestArray([]); + let mut encoder = test_array.encoder(); + assert!(encoder.current_chunk().is_empty()); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_byte_slice_without_prefix() { + // Should have one chunk with the byte data, then exhausted. + let obj = [1u8, 2, 3]; + let test_bytes = TestBytes(&obj); + let mut encoder = test_bytes.encoder(); + + assert_eq!(encoder.current_chunk(), &[1u8, 2, 3][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_empty_byte_slice_without_prefix() { + // Should have one empty chunk, then exhausted. + let obj = []; + let test_bytes = TestBytes(&obj); + let mut encoder = test_bytes.encoder(); + + assert!(encoder.current_chunk().is_empty()); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_slice_with_elements() { + // Should have the element chunks, then exhausted. + let slice = &[TestArray([0x34, 0x12, 0x00, 0x00]), TestArray([0x78, 0x56, 0x00, 0x00])]; + let mut encoder = SliceEncoder::without_length_prefix(slice); + + assert_eq!(encoder.current_chunk(), &[0x34, 0x12, 0x00, 0x00][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x78, 0x56, 0x00, 0x00][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_empty_slice() { + // Should immediately be exhausted. + let slice: &[TestArray<4>] = &[]; + let mut encoder = SliceEncoder::without_length_prefix(slice); + + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_slice_with_zero_sized_arrays() { + // Should have empty array chunks, then exhausted. + let slice = &[TestArray([]), TestArray([])]; + let mut encoder = SliceEncoder::without_length_prefix(slice); + + assert!(encoder.current_chunk().is_empty()); + // The slice advanced is optimized to skip over empty chunks. + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_two_arrays() { + // Should encode first array, then second array, then exhausted. + let enc1 = TestArray([1u8, 2]).encoder(); + let enc2 = TestArray([3u8, 4]).encoder(); + let mut encoder = Encoder2::new(enc1, enc2); + + assert_eq!(encoder.current_chunk(), &[1u8, 2][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[3u8, 4][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_two_empty_arrays() { + // Should encode first empty array, then second empty array, then exhausted. + let enc1 = TestArray([]).encoder(); + let enc2 = TestArray([]).encoder(); + let mut encoder = Encoder2::new(enc1, enc2); + + assert!(encoder.current_chunk().is_empty()); + assert!(encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_three_arrays() { + // Should encode three arrays in sequence, then exhausted. + let enc1 = TestArray([1u8]).encoder(); + let enc2 = TestArray([2u8, 3u8]).encoder(); + let enc3 = TestArray([4u8, 5u8, 6u8]).encoder(); + let mut encoder = Encoder3::new(enc1, enc2, enc3); + + assert_eq!(encoder.current_chunk(), &[1u8][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[2u8, 3u8][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[4u8, 5u8, 6u8][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_four_arrays() { + // Should encode four arrays in sequence, then exhausted. + let enc1 = TestArray([0x10]).encoder(); + let enc2 = TestArray([0x20]).encoder(); + let enc3 = TestArray([0x30]).encoder(); + let enc4 = TestArray([0x40]).encoder(); + let mut encoder = Encoder4::new(enc1, enc2, enc3, enc4); + + assert_eq!(encoder.current_chunk(), &[0x10][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x20][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x30][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x40][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_six_arrays() { + // Should encode six arrays in sequence, then exhausted. + let enc1 = TestArray([0x01]).encoder(); + let enc2 = TestArray([0x02]).encoder(); + let enc3 = TestArray([0x03]).encoder(); + let enc4 = TestArray([0x04]).encoder(); + let enc5 = TestArray([0x05]).encoder(); + let enc6 = TestArray([0x06]).encoder(); + let mut encoder = Encoder6::new(enc1, enc2, enc3, enc4, enc5, enc6); + + assert_eq!(encoder.current_chunk(), &[0x01][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x02][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x03][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x04][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x05][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x06][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_mixed_composition_with_byte_slices() { + // Should encode byte slice, then array, then exhausted. + let enc1 = TestBytes(&[0xFF, 0xEE]).encoder(); + let enc2 = TestArray([0xDD, 0xCC]).encoder(); + let mut encoder = Encoder2::new(enc1, enc2); + + assert_eq!(encoder.current_chunk(), &[0xFF, 0xEE][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0xDD, 0xCC][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_nested_composition() { + // Should encode empty array, single byte array, then three byte array, then exhausted. + let enc1 = TestArray([]).encoder(); + let enc2 = TestArray([0x42]).encoder(); + let enc3 = TestArray([0x43, 0x44, 0x45]).encoder(); + let mut encoder = Encoder3::new(enc1, enc2, enc3); + + assert!(encoder.current_chunk().is_empty()); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x42][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x43, 0x44, 0x45][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_slice_with_array_composition() { + // Should encode slice elements, then array, then exhausted. + let slice = &[TestArray([0x10, 0x11]), TestArray([0x12, 0x13])]; + let slice_enc = SliceEncoder::without_length_prefix(slice); + let array_enc = TestArray([0x20, 0x21]).encoder(); + let mut encoder = Encoder2::new(slice_enc, array_enc); + + assert_eq!(encoder.current_chunk(), &[0x10, 0x11][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x12, 0x13][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x20, 0x21][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_array_with_slice_composition() { + // Should encode header array, then slice elements, then exhausted. + let header = TestArray([0xFF, 0xFE]).encoder(); + let slice = &[TestArray([0x01]), TestArray([0x02]), TestArray([0x03])]; + let slice_enc = SliceEncoder::without_length_prefix(slice); + let mut encoder = Encoder2::new(header, slice_enc); + + assert_eq!(encoder.current_chunk(), &[0xFF, 0xFE][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x01][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x02][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x03][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_multiple_slices_composition() { + // Should encode three slices in sequence, then exhausted. + let slice1 = &[TestArray([0xA1]), TestArray([0xA2])]; + let slice2: &[TestArray<1>] = &[]; + let slice3 = &[TestArray([0xC1]), TestArray([0xC2]), TestArray([0xC3])]; + + let enc1 = SliceEncoder::without_length_prefix(slice1); + let enc2 = SliceEncoder::without_length_prefix(slice2); + let enc3 = SliceEncoder::without_length_prefix(slice3); + let mut encoder = Encoder3::new(enc1, enc2, enc3); + + assert_eq!(encoder.current_chunk(), &[0xA1][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0xA2][..]); + + // Skip the empty slice + assert!(encoder.advance()); + + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0xC1][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0xC2][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0xC3][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + + #[test] + fn encode_complex_nested_structure() { + // Should encode header, slice with elements, and footer with prefix, then exhausted. + let header = TestBytes(&[0xDE, 0xAD]).encoder(); + let data_slice = &[TestArray([0x01, 0x02]), TestArray([0x03, 0x04])]; + let slice_enc = SliceEncoder::without_length_prefix(data_slice); + let footer = TestBytes(&[0xBE, 0xEF]).encoder(); + let mut encoder = Encoder3::new(header, slice_enc, footer); + + assert_eq!(encoder.current_chunk(), &[0xDE, 0xAD][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x01, 0x02][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0x03, 0x04][..]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[0xBE, 0xEF][..]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + } + #[test] + fn encode_compact_size() { + // 1-byte + let mut e = CompactSizeEncoder::new(0x10usize); + assert_eq!(e.current_chunk(), &[0x10][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + + let mut e = CompactSizeEncoder::new(0xFCusize); + assert_eq!(e.current_chunk(), &[0xFC][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + + // 0xFD + u16 + let mut e = CompactSizeEncoder::new(0x00FDusize); + assert_eq!(e.current_chunk(), &[0xFD, 0xFD, 0x00][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + + let mut e = CompactSizeEncoder::new(0x0FFFusize); + assert_eq!(e.current_chunk(), &[0xFD, 0xFF, 0x0F][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + + // 0xFE + u32 + let mut e = CompactSizeEncoder::new(0x0001_0000usize); + assert_eq!(e.current_chunk(), &[0xFE, 0x00, 0x00, 0x01, 0x00][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + + let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fusize); + assert_eq!(e.current_chunk(), &[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + + // 0xFF + u64 + // This test only runs on systems with >= 64 bit usize. + if core::mem::size_of::() >= 8 { + let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64 as usize); + assert_eq!(e.current_chunk(), &[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + } + + // > u64::MAX encodes as u64::MAX. + // This test only runs on systems with > 64 bit usize. + if core::mem::size_of::() > 8 { + let mut e = CompactSizeEncoder::new((u128::from(u64::MAX) + 5) as usize); + assert_eq!(e.current_chunk(), &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]); + assert!(!e.advance()); + assert!(e.current_chunk().is_empty()); + } + } + + #[test] + fn iter_encoder() { + let test_array = TestArray([1u8, 2, 3, 4]); + let mut iter = crate::EncodableByteIter::new(&test_array); + let mut byte = iter.next().unwrap(); + assert_eq!(byte, 1u8); + byte = iter.next().unwrap(); + assert_eq!(byte, 2u8); + byte = iter.next().unwrap(); + assert_eq!(byte, 3u8); + byte = iter.next().unwrap(); + assert_eq!(byte, 4u8); + let none = iter.next(); + assert_eq!(none, None); + } +} diff --git a/consensus_encoding/src/encode/mod.rs b/consensus_encoding/src/encode/mod.rs new file mode 100644 index 000000000..aef04e207 --- /dev/null +++ b/consensus_encoding/src/encode/mod.rs @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Consensus Encoding Traits + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +pub mod encoders; + +/// A Bitcoin object which can be consensus-encoded. +/// +/// To encode something, use the [`Self::encoder`] method to obtain a +/// [`Self::Encoder`], which will behave like an iterator yielding +/// byte slices. +pub trait Encodable { + /// The encoder associated with this type. Conceptually, the encoder is like + /// an iterator which yields byte slices. + type Encoder<'s>: Encoder + where + Self: 's; + + /// Constructs a "default encoder" for the type. + fn encoder(&self) -> Self::Encoder<'_>; +} + +/// An encoder for a consensus-encodable object. +pub trait Encoder { + /// Yields the current encoded byteslice. + /// + /// Will always return the same value until [`Self::advance`] is called. May return an empty + /// list. + fn current_chunk(&self) -> &[u8]; + + /// Moves the encoder to its next state. + /// + /// Does not need to be called when the encoder is first created. (In fact, if it + /// is called, this will discard the first chunk of encoded data.) + /// + /// # Returns + /// + /// - `true` if the encoder has advanced to a new state and [`Self::current_chunk`] will return new data. + /// - `false` if the encoder is exhausted and has no more states. + fn advance(&mut self) -> bool; +} + +/// Implements a newtype around an encoder which implements the +/// [`Encoder`] trait by forwarding to the wrapped encoder. +#[macro_export] +macro_rules! encoder_newtype{ + ( + $(#[$($struct_attr:tt)*])* + pub struct $name:ident$(<$lt:lifetime>)?($encoder:ty); + ) => { + $(#[$($struct_attr)*])* + pub struct $name$(<$lt>)?($encoder); + + impl$(<$lt>)? $crate::Encoder for $name$(<$lt>)? { + #[inline] + fn current_chunk(&self) -> &[u8] { self.0.current_chunk() } + + #[inline] + fn advance(&mut self) -> bool { self.0.advance() } + } + } +} + +/// Yields bytes from any [`Encodable`] instance. +pub struct EncodableByteIter<'s, T: Encodable + 's> { + enc: T::Encoder<'s>, + position: usize, +} + +impl<'s, T: Encodable + 's> EncodableByteIter<'s, T> { + /// Constructs a new byte iterator around a provided encodable. + pub fn new(encodable: &'s T) -> Self { + Self { enc: encodable.encoder(), position: 0 } + } +} + +impl<'s, T: Encodable + 's> Iterator for EncodableByteIter<'s, T> { + type Item = u8; + + fn next(&mut self) -> Option { + loop { + if let Some(b) = self.enc.current_chunk().get(self.position) { + self.position += 1; + return Some(*b); + } else if !self.enc.advance() { + return None; + } + self.position = 0; + } + } +} + +/// Encodes an object into a vector. +#[cfg(feature = "alloc")] +pub fn encode_to_vec(object: &T) -> Vec +where + T: Encodable + ?Sized, +{ + let mut encoder = object.encoder(); + let mut vec = Vec::new(); + loop { + vec.extend_from_slice(encoder.current_chunk()); + if !encoder.advance() { + break; + } + } + vec +} + +/// Encodes an object to a standard I/O writer. +/// +/// # Performance +/// +/// This method writes data in potentially small chunks based on the encoder's +/// internal chunking strategy. For optimal performance with unbuffered writers +/// (like [`std::fs::File`] or [`std::net::TcpStream`]), consider wrapping your +/// writer with [`std::io::BufWriter`]. +/// +/// # Errors +/// +/// Returns any I/O error encountered while writing to the writer. +#[cfg(feature = "std")] +pub fn encode_to_writer(object: &T, mut writer: W) -> Result<(), std::io::Error> +where + T: Encodable + ?Sized, + W: std::io::Write, +{ + let mut encoder = object.encoder(); + loop { + writer.write_all(encoder.current_chunk())?; + if !encoder.advance() { + break; + } + } + Ok(()) +} + +impl Encoder for Option { + fn current_chunk(&self) -> &[u8] { + match self { + Some(encoder) => encoder.current_chunk(), + None => &[], + } + } + + fn advance(&mut self) -> bool { + match self { + Some(encoder) => encoder.advance(), + None => false, + } + } +} diff --git a/consensus_encoding/src/lib.rs b/consensus_encoding/src/lib.rs new file mode 100644 index 000000000..965636a84 --- /dev/null +++ b/consensus_encoding/src/lib.rs @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! # Rust Bitcoin - consensus encoding and decoding +//! +//! This library provides traits that can be used to encode/decode objects in a +//! consensus-consistent way. +//! + +#![no_std] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +mod decode; +mod encode; + +#[cfg(feature = "alloc")] +pub use self::decode::decoders::{ + cast_to_usize_if_valid, ByteVecDecoder, ByteVecDecoderError, LengthPrefixExceedsMaxError, + VecDecoder, VecDecoderError, +}; +pub use self::decode::decoders::{ + ArrayDecoder, CompactSizeDecoder, CompactSizeDecoderError, Decoder2, Decoder2Error, Decoder3, + Decoder3Error, Decoder4, Decoder4Error, Decoder6, Decoder6Error, UnexpectedEofError, +}; +#[cfg(feature = "std")] +pub use self::decode::{ + decode_from_read, decode_from_read_unbuffered, decode_from_read_unbuffered_with, ReadError, +}; +pub use self::decode::{decode_from_slice, Decodable, Decoder}; +#[cfg(feature = "alloc")] +pub use self::encode::encode_to_vec; +#[cfg(feature = "std")] +pub use self::encode::encode_to_writer; +pub use self::encode::encoders::{ + ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encoder2, Encoder3, Encoder4, Encoder6, + SliceEncoder, +}; +pub use self::encode::{Encodable, Encoder, EncodableByteIter}; diff --git a/consensus_encoding/tests/composition.rs b/consensus_encoding/tests/composition.rs new file mode 100644 index 000000000..9b180ac87 --- /dev/null +++ b/consensus_encoding/tests/composition.rs @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Test composition of encoders and decoders. + +use bitcoin_consensus_encoding::{ + ArrayDecoder, ArrayEncoder, BytesEncoder, Decodable, Decoder, Decoder2, Decoder2Error, + Decoder6, Encodable, Encoder, Encoder2, Encoder3, Encoder6, UnexpectedEofError, +}; + +const EMPTY: &[u8] = &[]; + +// A simple composite type that encodes as [4 bytes] + [2 bytes]. +#[derive(Debug, PartialEq, Eq)] +struct CompositeData { + first: [u8; 4], + second: [u8; 2], +} + +impl Encodable for CompositeData { + type Encoder<'e> = Encoder2, ArrayEncoder<2>>; + + fn encoder(&self) -> Self::Encoder<'_> { + Encoder2::new( + ArrayEncoder::without_length_prefix(self.first), + ArrayEncoder::without_length_prefix(self.second), + ) + } +} + +/// A unified error type for [`CompositeDataDecoder`]. +#[derive(Debug, Clone, PartialEq, Eq)] +enum CompositeError { + Eof(UnexpectedEofError), +} + +impl From for CompositeError { + fn from(eof: UnexpectedEofError) -> Self { Self::Eof(eof) } +} + +impl core::fmt::Display for CompositeError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Eof(eof) => write!(f, "Composite error: {}", eof), + } + } +} + +/// A wrapper decoder that converts the tuple output to [`CompositeData`]. +struct CompositeDataDecoder { + inner: Decoder2, ArrayDecoder<2>>, +} + +impl CompositeDataDecoder { + fn new() -> Self { + Self { inner: Decoder2::new(ArrayDecoder::<4>::new(), ArrayDecoder::<2>::new()) } + } +} + +impl Decoder for CompositeDataDecoder { + type Output = CompositeData; + type Error = CompositeError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(|error| match error { + Decoder2Error::First(e) | Decoder2Error::Second(e) => CompositeError::Eof(e), + }) + } + + fn end(self) -> Result { + let (first, second) = self.inner.end().map_err(|error| match error { + Decoder2Error::First(e) | Decoder2Error::Second(e) => CompositeError::Eof(e), + })?; + Ok(CompositeData { first, second }) + } + + fn read_limit(&self) -> usize { self.inner.read_limit() } +} + +impl Decodable for CompositeData { + type Decoder = CompositeDataDecoder; + + fn decoder() -> Self::Decoder { CompositeDataDecoder::new() } +} + +#[test] +fn composition_chain() { + let original = CompositeData { first: [0x01, 0x02, 0x03, 0x04], second: [0x05, 0x06] }; + // Encode using the pull encoder. + let mut encoder = original.encoder(); + let mut encoded_bytes = Vec::new(); + loop { + encoded_bytes.extend_from_slice(encoder.current_chunk()); + if !encoder.advance() { + break; + } + } + // Decode using the push decoder. + let mut decoder = CompositeData::decoder(); + let mut bytes = &encoded_bytes[..]; + let needs_more = decoder.push_bytes(&mut bytes).unwrap(); + assert!(!needs_more, "CompositeData decoder should be ready to end"); + assert_eq!(bytes, EMPTY); + let decoded = decoder.end().unwrap(); + assert_eq!(original, decoded); +} + +#[test] +fn composition_nested() { + let data = b"abcdef"; + let mut encoder6 = Encoder6::new( + ArrayEncoder::without_length_prefix([data[0]]), + ArrayEncoder::without_length_prefix([data[1]]), + ArrayEncoder::without_length_prefix([data[2]]), + ArrayEncoder::without_length_prefix([data[3]]), + ArrayEncoder::without_length_prefix([data[4]]), + ArrayEncoder::without_length_prefix([data[5]]), + ); + + let mut encoded_bytes = Vec::new(); + loop { + encoded_bytes.extend_from_slice(encoder6.current_chunk()); + if !encoder6.advance() { + break; + } + } + assert_eq!(encoded_bytes, data); + + let mut decoder6: Decoder6<_, _, _, _, _, _> = Decoder6::new( + ArrayDecoder::<1>::new(), + ArrayDecoder::<1>::new(), + ArrayDecoder::<1>::new(), + ArrayDecoder::<1>::new(), + ArrayDecoder::<1>::new(), + ArrayDecoder::<1>::new(), + ); + let mut bytes = &encoded_bytes[..]; + let needs_more = decoder6.push_bytes(&mut bytes).unwrap(); + assert!(!needs_more, "Decoder6 should be ready to end"); + assert_eq!(bytes, EMPTY); + let (first, second, third, fourth, fifth, sixth) = decoder6.end().unwrap(); + assert_eq!(first, [data[0]]); + assert_eq!(second, [data[1]]); + assert_eq!(third, [data[2]]); + assert_eq!(fourth, [data[3]]); + assert_eq!(fifth, [data[4]]); + assert_eq!(sixth, [data[5]]); +} + +#[test] +fn composition_extra_bytes() { + // Test that Decoder2 consumes exactly what it needs and leaves extra bytes unconsumed. + let mut decoder2: Decoder2<_, _> = + Decoder2::new(ArrayDecoder::<2>::new(), ArrayDecoder::<3>::new()); + let mut bytes = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08][..]; + let original_len = bytes.len(); + + let needs_more = decoder2.push_bytes(&mut bytes).unwrap(); + assert!(!needs_more, "Decoder2 should be ready to end after consuming all needed bytes"); + + let consumed = original_len - bytes.len(); + assert_eq!(consumed, 5, "Decoder2 should consume exactly 5 bytes"); + assert_eq!(bytes.len(), 3, "3 bytes should remain unconsumed"); + assert_eq!(bytes, &[0x06, 0x07, 0x08], "Remaining bytes should be the last 3"); + + let (first, second) = decoder2.end().unwrap(); + assert_eq!(first, [0x01, 0x02], "First decoder should get first 2 bytes"); + assert_eq!(second, [0x03, 0x04, 0x05], "Second decoder should get next 3 bytes"); +} + +#[test] +#[allow(clippy::too_many_lines)] +fn composition_error_unification() { + // Demonstrates how decoders unify error types into + // a single target error type through `From` conversions. + + /// Error for the lower level decoders. + #[derive(Debug, Clone, PartialEq, Eq)] + enum NestedError { + BadChecksum, + UnexpectedEof(UnexpectedEofError), + } + + impl From for NestedError { + fn from(eof: UnexpectedEofError) -> Self { Self::UnexpectedEof(eof) } + } + + /// Error for top level encoder. + #[derive(Debug, Clone, PartialEq, Eq)] + enum TopLevelError { + UnexpectedEof(UnexpectedEofError), + Validation(NestedError), + } + + impl From for TopLevelError { + fn from(eof: UnexpectedEofError) -> Self { Self::UnexpectedEof(eof) } + } + + impl From for TopLevelError { + fn from(err: NestedError) -> Self { + match err { + NestedError::UnexpectedEof(eof) => Self::UnexpectedEof(eof), + NestedError::BadChecksum => Self::Validation(err), + } + } + } + + /// A test composite decoder. + struct HeaderDecoder { + inner: Decoder2, ArrayDecoder<1>>, + } + + impl HeaderDecoder { + fn new() -> Self { + Self { inner: Decoder2::new(ArrayDecoder::<1>::new(), ArrayDecoder::<1>::new()) } + } + } + + impl Decoder for HeaderDecoder { + type Output = ([u8; 1], [u8; 1]); + type Error = NestedError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(|error| match error { + Decoder2Error::First(e) | Decoder2Error::Second(e) => NestedError::from(e), + }) + } + + fn end(self) -> Result { + let (first, second) = self.inner.end().map_err(|error| match error { + Decoder2Error::First(e) | Decoder2Error::Second(e) => NestedError::from(e), + })?; + Ok((first, second)) + } + + fn read_limit(&self) -> usize { self.inner.read_limit() } + } + + /// Another test composite decoder. + struct PayloadDecoder { + inner: ArrayDecoder<4>, + } + + impl PayloadDecoder { + fn new() -> Self { Self { inner: ArrayDecoder::<4>::new() } } + } + + impl Decoder for PayloadDecoder { + type Output = [u8; 4]; + type Error = TopLevelError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + Ok(self.inner.push_bytes(bytes)?) + } + + fn end(self) -> Result { + let result = self.inner.end()?; + Ok(result) + } + + fn read_limit(&self) -> usize { self.inner.read_limit() } + } + + /// A decoder which can fail. + struct FailingDecoder { + inner: ArrayDecoder<1>, + should_fail: bool, + } + + impl FailingDecoder { + fn new(should_fail: bool) -> Self { Self { inner: ArrayDecoder::<1>::new(), should_fail } } + } + + impl Decoder for FailingDecoder { + type Output = [u8; 1]; + type Error = NestedError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(NestedError::from) + } + + fn end(self) -> Result { + if self.should_fail { + Err(NestedError::BadChecksum) + } else { + self.inner.end().map_err(NestedError::from) + } + } + + fn read_limit(&self) -> usize { self.inner.read_limit() } + } + + // A multi-layer, nested, decoder structure with a unified top level error type. + let mut nested_decoder = Decoder6::new( + HeaderDecoder::new(), + PayloadDecoder::new(), + ArrayDecoder::<1>::new(), + HeaderDecoder::new(), + PayloadDecoder::new(), + ArrayDecoder::<2>::new(), + ); + + let test_data = b"abcdefghijklmno"; + let mut bytes = &test_data[..]; + let push_result = nested_decoder.push_bytes(&mut bytes); + assert!(push_result.is_ok(), "push_bytes should succeed, got error: {:?}", push_result.err()); + let end_result = nested_decoder.end(); + assert!(end_result.is_ok(), "end should succeed, got error: {:?}", end_result.err()); + + // Test error during decoding. + let mut failing_decoder: Decoder2> = + Decoder2::new(FailingDecoder::new(true), ArrayDecoder::<1>::new()); + let test_data = b"ab"; + let mut bytes = &test_data[..]; + let push_result = failing_decoder.push_bytes(&mut bytes); + assert!(push_result.is_err(), "push_bytes should fail when first decoder fails in end()"); + assert!( + matches!(push_result.as_ref().unwrap_err(), Decoder2Error::First(NestedError::BadChecksum)), + "Expected Decoder2Error::First(NestedError::BadChecksum), got {:?}", + push_result.unwrap_err() + ); +} + +#[test] +fn empty_encoders() { + let bytes = [0x01, 2, 3, 4]; + let mut encoder = Encoder3::new( + BytesEncoder::without_length_prefix(&bytes[..2]), + BytesEncoder::without_length_prefix(&[]), + BytesEncoder::without_length_prefix(&bytes[2..]), + ); + + assert_eq!(encoder.current_chunk(), &[1, 2][..]); + assert!(encoder.advance()); + + // Still have to advance over empty slice. + assert!(encoder.current_chunk().is_empty()); + assert!(encoder.advance()); + + assert_eq!(encoder.current_chunk(), &[3, 4][..]); + assert!(!encoder.advance()); + + // Exhausted. + assert!(encoder.current_chunk().is_empty()); +} diff --git a/consensus_encoding/tests/decode.rs b/consensus_encoding/tests/decode.rs new file mode 100644 index 000000000..a5edc98d3 --- /dev/null +++ b/consensus_encoding/tests/decode.rs @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Integration tests for decode module. + +use bitcoin_consensus_encoding::{ + ArrayDecoder, CompactSizeDecoder, Decoder, Decoder2, UnexpectedEofError, +}; + +const EMPTY: &[u8] = &[]; + +#[test] +fn decode_array_excess_data_ignored() { + let mut decoder = ArrayDecoder::<4>::new(); + let mut data = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(!needs_more, "ArrayDecoder should be complete after consuming all needed bytes"); + assert_eq!(data, &[0x05, 0x06]); + let result = decoder.end().unwrap(); + assert_eq!(result, [0x01, 0x02, 0x03, 0x04]); +} + +#[test] +fn decode_array_streaming_behavior() { + let mut decoder = ArrayDecoder::<4>::new(); + + let mut data = &[0x01][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(needs_more, "ArrayDecoder should need more data after 1 byte"); + assert_eq!(data, EMPTY); + + let mut data = &[0x02, 0x03][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(needs_more, "ArrayDecoder should need more data after 3 bytes"); + assert_eq!(data, EMPTY); + + let mut data = &[0x04, 0x05, 0x06][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(!needs_more, "ArrayDecoder should be complete after 4 bytes"); + assert_eq!(data, &[0x05, 0x06]); + + let result = decoder.end().unwrap(); + assert_eq!(result, [0x01, 0x02, 0x03, 0x04]); +} + +#[test] +fn decode_array_insufficient_data_error() { + let mut decoder = ArrayDecoder::<5>::new(); + let mut data = &[0xAA, 0xBB][..]; + + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(needs_more, "ArrayDecoder should need more data after 2 bytes for 5-byte array"); + assert_eq!(data, EMPTY); + + let err = decoder.end().unwrap_err(); + assert!(matches!(err, UnexpectedEofError { .. })); +} + +#[test] +fn decode_array_zero_size() { + // Test zero-sized array decoder which doesn't consume any bytes. + let mut decoder = ArrayDecoder::<0>::new(); + let mut data = &[0x01, 0x02, 0x03][..]; + + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(!needs_more, "zero-sized ArrayDecoder should not need data"); + assert_eq!(data, &[0x01, 0x02, 0x03]); + let result = decoder.end().unwrap(); + assert_eq!(result, [0u8; 0]); + + // read_limit should be 0. + let decoder = ArrayDecoder::<0>::new(); + assert_eq!(decoder.read_limit(), 0); +} + +#[test] +fn decode_array_empty_slice_push() { + // Test pushing empty slices to ArrayDecoder. + let mut decoder = ArrayDecoder::<3>::new(); + let mut empty_data = &[][..]; + + let needs_more = decoder.push_bytes(&mut empty_data).unwrap(); + assert!(needs_more, "decoder should still need data after empty push"); + assert_eq!(empty_data, &[0u8; 0]); + assert_eq!(decoder.read_limit(), 3); +} + +#[test] +fn decode_decoder2_state_transitions() { + // Test the state transition point boundry in Decoder2. + let mut decoder: Decoder2, ArrayDecoder<3>> = + Decoder2::new(ArrayDecoder::<2>::new(), ArrayDecoder::<3>::new()); + + assert_eq!(decoder.read_limit(), 5); + let mut data = &[0x01, 0x02][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(needs_more, "should need more data for second decoder"); + assert_eq!(data.len(), 0, "all data should be consumed"); + + assert_eq!(decoder.read_limit(), 3); + let mut more_data = &[0x03, 0x04, 0x05][..]; + let needs_more = decoder.push_bytes(&mut more_data).unwrap(); + assert!(!needs_more, "should not need more data after completing both decoders"); + assert_eq!(more_data.len(), 0, "all data should be consumed"); + + assert_eq!(decoder.read_limit(), 0); + let (first_result, second_result) = decoder.end().unwrap(); + assert_eq!(first_result, [0x01, 0x02]); + assert_eq!(second_result, [0x03, 0x04, 0x05]); +} + +#[test] +fn decode_decoder2_read_limit_with_exhausted() { + // Test read_limit calculation when first decoder needs 0 bytes. + let decoder1: Decoder2, ArrayDecoder<5>> = + Decoder2::new(ArrayDecoder::<0>::new(), ArrayDecoder::<5>::new()); + assert_eq!(decoder1.read_limit(), 5); + + let mut decoder2: Decoder2, ArrayDecoder<3>> = + Decoder2::new(ArrayDecoder::<2>::new(), ArrayDecoder::<3>::new()); + let mut data = &[0x01, 0x02][..]; + let needs_more = decoder2.push_bytes(&mut data).unwrap(); + assert!(needs_more, "should need more data for second decoder"); + assert_eq!(data.len(), 0, "all data should be consumed"); + assert_eq!(decoder2.read_limit(), 3); +} + +#[test] +fn decode_compact_size_read_limit_transitions() { + // Test read_limit behavior during compact size decoding. + let mut decoder = CompactSizeDecoder::default(); + + assert_eq!(decoder.read_limit(), 1); + let mut data = &[0xFD][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(needs_more, "should need more data after seeing 0xFD"); + assert_eq!(data.len(), 0, "all data should be consumed"); + + assert_eq!(decoder.read_limit(), 2); + let mut data = &[0x00][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(needs_more, "should still need one more byte"); + assert_eq!(data.len(), 0, "all data should be consumed"); + assert_eq!(decoder.read_limit(), 1); + + let mut data = &[0x01][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(!needs_more, "should not need more data"); + assert_eq!(data.len(), 0, "all data should be consumed"); + assert_eq!(decoder.read_limit(), 0); + + let result = decoder.end().unwrap(); + assert_eq!(result, 256); +} + +#[test] +fn decode_compact_size_single_byte_read_limit() { + // Test read_limit for single-byte compact size. + let mut decoder = CompactSizeDecoder::default(); + + assert_eq!(decoder.read_limit(), 1); + let mut data = &[0x42][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(!needs_more, "single-byte value should be complete"); + assert_eq!(data.len(), 0, "all data should be consumed"); + assert_eq!(decoder.read_limit(), 0); + let result = decoder.end().unwrap(); + assert_eq!(result, 66); +} + +#[test] +#[cfg(feature = "alloc")] +fn decode_cast_to_usize_boundary_conditions() { + // Test the 4MB boundary and some edge cases. + use bitcoin_consensus_encoding::cast_to_usize_if_valid; + + assert!(cast_to_usize_if_valid(4_000_000).is_ok()); + assert!(cast_to_usize_if_valid(4_000_001).is_err()); + assert!(cast_to_usize_if_valid(u64::MAX).is_err()); + assert_eq!(cast_to_usize_if_valid(0).unwrap(), 0); +} + +#[test] +#[cfg(feature = "alloc")] +fn decode_byte_vec_decoder_empty() { + // Test decoding empty byte vector, with length prefix of 0. + use bitcoin_consensus_encoding::{ByteVecDecoder, Decoder}; + + let mut decoder = ByteVecDecoder::new(); + let mut data = &[0x00][..]; + let needs_more = decoder.push_bytes(&mut data).unwrap(); + assert!(!needs_more, "decoder should not need more data for empty vector"); + assert_eq!(data.len(), 0, "all data should be consumed"); + assert_eq!(decoder.read_limit(), 0); + let result = decoder.end().unwrap(); + assert!(result.is_empty()); +} + +#[test] +#[cfg(feature = "alloc")] +fn decode_byte_vec_decoder_does_not_overconsume() { + use bitcoin_consensus_encoding::ByteVecDecoder; + + let mut decoder = ByteVecDecoder::new(); + let mut data = &[0x02, 0xAA, 0xBB, 0xCC, 0xDD][..]; + assert!(!decoder.push_bytes(&mut data).unwrap()); + assert_eq!(data, &[0xCC, 0xDD][..]); + assert_eq!(decoder.end().unwrap(), vec![0xAA, 0xBB]); +} + +#[test] +#[cfg(feature = "alloc")] +fn decode_byte_vec_decoder_does_not_overconsume_on_second_chunk() { + use bitcoin_consensus_encoding::ByteVecDecoder; + + // First chunk prefix declares 4 payload bytes and provides the first one. + let mut first_chunk: &[u8] = &[0x04, 0xAA]; + // Second chunk provides the remaining 3 payload bytes plus two trailing bytes. + let mut second_chunk: &[u8] = &[0xBB, 0xCC, 0xDD, 0x11, 0x22]; + + let mut decoder = ByteVecDecoder::new(); + + assert!(decoder.push_bytes(&mut first_chunk).unwrap()); + assert!(first_chunk.is_empty()); + + let needs_more = decoder.push_bytes(&mut second_chunk).unwrap(); + assert!(!needs_more); + assert_eq!(second_chunk, &[0x11, 0x22][..]); + + let decoded_vec = decoder.end().unwrap(); + assert_eq!(decoded_vec, vec![0xAA, 0xBB, 0xCC, 0xDD]); +} diff --git a/consensus_encoding/tests/encode.rs b/consensus_encoding/tests/encode.rs new file mode 100644 index 000000000..f86b63ba6 --- /dev/null +++ b/consensus_encoding/tests/encode.rs @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Tests for encoder free functions. + +#[cfg(feature = "std")] +use std::io::{Cursor, Write}; + +use bitcoin_consensus_encoding::{ + ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encoder, Encoder2, +}; +#[cfg(feature = "alloc")] +use bitcoin_consensus_encoding::{Encodable, SliceEncoder}; + +// Simple test type that implements Encodable. +#[cfg(feature = "alloc")] +struct TestData(u32); + +#[cfg(feature = "alloc")] +impl Encodable for TestData { + type Encoder<'s> + = ArrayEncoder<4> + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { + ArrayEncoder::without_length_prefix(self.0.to_le_bytes()) + } +} + +// Test with a type that creates an empty encoder. +#[cfg(feature = "alloc")] +struct EmptyData; + +#[cfg(feature = "alloc")] +impl Encodable for EmptyData { + type Encoder<'s> + = ArrayEncoder<0> + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { ArrayEncoder::without_length_prefix([]) } +} + +#[test] +#[cfg(feature = "std")] +fn encode_std_writer() { + let data = TestData(0x1234_5678); + + let mut cursor = Cursor::new(Vec::new()); + bitcoin_consensus_encoding::encode_to_writer(&data, &mut cursor).unwrap(); + + let result = cursor.into_inner(); + assert_eq!(result, vec![0x78, 0x56, 0x34, 0x12]); +} + +#[test] +#[cfg(feature = "alloc")] +fn encode_vec() { + let data = TestData(0xDEAD_BEEF); + let vec = bitcoin_consensus_encoding::encode_to_vec(&data); + assert_eq!(vec, vec![0xEF, 0xBE, 0xAD, 0xDE]); +} + +#[test] +#[cfg(feature = "alloc")] +fn encode_vec_empty_data() { + let data = EmptyData; + let result = bitcoin_consensus_encoding::encode_to_vec(&data); + assert!(result.is_empty()); +} + +#[test] +#[cfg(feature = "std")] +fn encode_std_writer_empty_data() { + let data = EmptyData; + let mut cursor = Cursor::new(Vec::new()); + bitcoin_consensus_encoding::encode_to_writer(&data, &mut cursor).unwrap(); + + let result = cursor.into_inner(); + assert!(result.is_empty()); +} + +#[test] +#[cfg(feature = "std")] +fn encode_std_writer_io_error() { + // Test writer that always fails. + struct FailingWriter; + + impl Write for FailingWriter { + fn write(&mut self, _buf: &[u8]) -> std::io::Result { + Err(std::io::Error::other("test error")) + } + + fn flush(&mut self) -> std::io::Result<()> { Ok(()) } + } + + let data = TestData(0x1234_5678); + let mut writer = FailingWriter; + + let result = bitcoin_consensus_encoding::encode_to_writer(&data, &mut writer); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err().kind(), std::io::ErrorKind::Other); +} + +#[test] +fn encode_newtype_lifetime_flexibility() { + // Test that the encoder_newtype macro allows different lifetime names. + + bitcoin_consensus_encoding::encoder_newtype! { + pub struct CustomEncoder<'data>(BytesEncoder<'data>); + } + bitcoin_consensus_encoding::encoder_newtype! { + pub struct NoLifetimeEncoder(ArrayEncoder<4>); + } + + let test_data = b"hello world"; + let custom_encoder = CustomEncoder(BytesEncoder::without_length_prefix(test_data)); + let no_lifetime_encoder = NoLifetimeEncoder(ArrayEncoder::without_length_prefix([1, 2, 3, 4])); + + assert_eq!(custom_encoder.current_chunk(), test_data.as_slice()); + assert_eq!(no_lifetime_encoder.current_chunk(), &[1, 2, 3, 4][..]); +} + +#[cfg(feature = "alloc")] +#[test] +fn encode_slice_encoder_mixed_empty_and_data() { + // Test SliceEncoder behavior with mixed empty and non-empty elements. + struct TestBytes(Vec); + + impl Encodable for TestBytes { + type Encoder<'s> + = BytesEncoder<'s> + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { BytesEncoder::without_length_prefix(&self.0) } + } + + let slice = &[TestBytes(vec![]), TestBytes(vec![1, 2]), TestBytes(vec![]), TestBytes(vec![3])]; + + let mut encoder = SliceEncoder::without_length_prefix(slice); + + assert!(encoder.current_chunk().is_empty()); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[1, 2]); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[3]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); +} + +#[test] +fn encode_compact_size_boundary_values() { + // Test CompactSizeEncoder with boundary values. + let mut encoder = CompactSizeEncoder::new(252usize); + assert_eq!(encoder.current_chunk(), &[252]); + assert!(!encoder.advance()); + + let mut encoder = CompactSizeEncoder::new(253usize); + assert_eq!(encoder.current_chunk(), &[0xFD, 253, 0]); + assert!(!encoder.advance()); + + let mut encoder = CompactSizeEncoder::new(0x10000usize); + assert_eq!(encoder.current_chunk(), &[0xFE, 0, 0, 1, 0]); + assert!(!encoder.advance()); + + let mut encoder = CompactSizeEncoder::new(0usize); + assert_eq!(encoder.current_chunk(), &[0]); + assert!(!encoder.advance()); +} + +#[test] +fn encode_encoder2_with_first_empty_encoder() { + // Test Encoder2 when first encoder produces no data. + let enc1 = ArrayEncoder::<0>::without_length_prefix([]); + let enc2 = ArrayEncoder::<3>::without_length_prefix([1, 2, 3]); + + let mut encoder = Encoder2::new(enc1, enc2); + + assert!(encoder.current_chunk().is_empty()); + assert!(encoder.advance()); + assert_eq!(encoder.current_chunk(), &[1, 2, 3]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); +} + +#[test] +fn encode_encoder_advance_multiple_times_when_exhausted() { + // Test that calling advance() multiple times on exhausted encoder is safe. + let mut encoder = ArrayEncoder::<2>::without_length_prefix([10, 20]); + + assert_eq!(encoder.current_chunk(), &[10, 20]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); + assert!(!encoder.advance()); + assert!(!encoder.advance()); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); +} + +#[test] +fn encode_option_encoder_some() { + use bitcoin_consensus_encoding::Encoder; + + let mut encoder = Some(ArrayEncoder::<3>::without_length_prefix([1, 2, 3])); + assert_eq!(encoder.current_chunk(), &[1, 2, 3]); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); +} + +#[test] +fn encode_option_encoder_none() { + use bitcoin_consensus_encoding::Encoder; + + let mut encoder: Option> = None; + assert!(encoder.current_chunk().is_empty()); + assert!(!encoder.advance()); + assert!(encoder.current_chunk().is_empty()); +} diff --git a/consensus_encoding/tests/iter.rs b/consensus_encoding/tests/iter.rs new file mode 100644 index 000000000..1e105aa2c --- /dev/null +++ b/consensus_encoding/tests/iter.rs @@ -0,0 +1,59 @@ +use hex::BytesToHexIter; + +use bitcoin_consensus_encoding::{Encodable, ArrayEncoder, Encoder2, EncodableByteIter}; + +struct TestArray([u8; N]); + +impl Encodable for TestArray { + type Encoder<'s> + = ArrayEncoder + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { ArrayEncoder::without_length_prefix(self.0) } +} + +struct TestCatArray([u8; N], [u8; M]); + +impl Encodable for TestCatArray { + type Encoder<'s> + = Encoder2, ArrayEncoder> + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { Encoder2::new( + ArrayEncoder::without_length_prefix(self.0), + ArrayEncoder::without_length_prefix(self.1), + ) + } +} + +#[test] +fn hex_iter() { + let data = TestArray([255u8, 240, 9, 135]); + let byte_iter = EncodableByteIter::new(&data); + let mut iter = BytesToHexIter::new(byte_iter, hex::Case::Upper); + + let expect_str = "FFF00987"; + for byte in expect_str.chars() { + let iter_byte = iter.next().unwrap(); + assert_eq!(iter_byte, byte); + } + let none = iter.next(); + assert_eq!(none, None); +} + +#[test] +fn hex_iter_cat_encoder() { + let data = TestCatArray([222u8, 173], [190u8, 239]); + let byte_iter = EncodableByteIter::new(&data); + let mut iter = BytesToHexIter::new(byte_iter, hex::Case::Lower); + + let expect_str = "deadbeef"; + for byte in expect_str.chars() { + let iter_byte = iter.next().unwrap(); + assert_eq!(iter_byte, byte); + } + let none = iter.next(); + assert_eq!(none, None); +} diff --git a/consensus_encoding/tests/wrappers.rs b/consensus_encoding/tests/wrappers.rs new file mode 100644 index 000000000..674c022b9 --- /dev/null +++ b/consensus_encoding/tests/wrappers.rs @@ -0,0 +1,134 @@ +//! Test using wrapper types as we expect the lib to be used. + +#![cfg(feature = "std")] + +use bitcoin_consensus_encoding as encoding; +use encoding::{ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encodable, Encoder2, SliceEncoder}; + +encoding::encoder_newtype! { + /// An encoder that uses an inner `ArrayEncoder`. + pub struct TestArrayEncoder(ArrayEncoder<4>); +} + +encoding::encoder_newtype! { + /// An encoder that uses an inner `BytesEncoder`. + pub struct TestBytesEncoder<'e>(BytesEncoder<'e>); +} + +#[test] +fn array_encoder() { + #[derive(Debug, Default, Clone)] + pub struct Test(u32); + + impl Encodable for Test { + type Encoder<'e> = TestArrayEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + TestArrayEncoder(ArrayEncoder::without_length_prefix(self.0.to_le_bytes())) + } + } + + let t = Test(0xcafe_babe); // Encodes using an array. + + let want = [0xbe, 0xba, 0xfe, 0xca]; + let got = encoding::encode_to_vec(&t); + + assert_eq!(got, want); +} + +#[test] +fn bytes_encoder_without_length_prefix() { + #[derive(Debug, Default, Clone)] + pub struct Test(Vec); + + impl Encodable for Test { + type Encoder<'e> + = TestBytesEncoder<'e> + where + Self: 'e; + + fn encoder(&self) -> Self::Encoder<'_> { + TestBytesEncoder(BytesEncoder::without_length_prefix(self.0.as_ref())) + } + } + + let t = Test(vec![0xca, 0xfe]); + + let want = [0xca, 0xfe]; + let got = encoding::encode_to_vec(&t); + + assert_eq!(got, want); +} + +#[test] +fn two_encoder() { + #[derive(Debug, Default, Clone)] + pub struct Test { + a: Vec, + b: Vec, + } + + impl Encodable for Test { + type Encoder<'e> = Encoder2, TestBytesEncoder<'e>>; + + fn encoder(&self) -> Self::Encoder<'_> { + let a = TestBytesEncoder(BytesEncoder::without_length_prefix(self.a.as_ref())); + let b = TestBytesEncoder(BytesEncoder::without_length_prefix(self.b.as_ref())); + + Encoder2::new(a, b) + } + } + + let t = Test { a: vec![0xca, 0xfe], b: (vec![0xba, 0xbe]) }; + + let want = [0xca, 0xfe, 0xba, 0xbe]; + let got = encoding::encode_to_vec(&t); + + assert_eq!(got, want); +} + +#[test] +fn slice_encoder() { + #[derive(Debug, Default, Clone)] + pub struct Test(Vec); + + encoding::encoder_newtype! { + /// An encoder that uses an inner `SliceEncoder`. + pub struct TestEncoder<'e>(Encoder2>); + } + + impl Encodable for Test { + type Encoder<'a> + = TestEncoder<'a> + where + Self: 'a; + + fn encoder(&self) -> Self::Encoder<'_> { + TestEncoder(Encoder2::new( + CompactSizeEncoder::new(self.0.len()), + SliceEncoder::without_length_prefix(&self.0), + )) + } + } + + #[derive(Debug, Default, Clone)] + pub struct Inner(u32); + + encoding::encoder_newtype! { + /// The encoder for the [`Inner`] type. + pub struct InnerArrayEncoder(ArrayEncoder<4>); + } + + impl Encodable for Inner { + type Encoder<'e> = InnerArrayEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + // Big-endian to make reading the test assertion easier. + InnerArrayEncoder(ArrayEncoder::without_length_prefix(self.0.to_be_bytes())) + } + } + + let t = Test(vec![Inner(0xcafe_babe), Inner(0xdead_beef)]); + let encoded = encoding::encode_to_vec(&t); + + let want = [0x02, 0xca, 0xfe, 0xba, 0xbe, 0xde, 0xad, 0xbe, 0xef]; + assert_eq!(encoded, want); +} diff --git a/contrib/api.sh b/contrib/api.sh new file mode 100755 index 000000000..03bfe1203 --- /dev/null +++ b/contrib/api.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +# +# Script for querying the API. +# +# Shellcheck can't search dynamic paths +# shellcheck source=/dev/null + +set -euo pipefail + +file="" # File name of the all-features API text file. +crate_full_name="" # Full crate name using underscores e.g., `bitcoin_primitives`. +crate="" # Short name e.g., `primitives`. + +# Set to false to turn off verbose output. +flag_verbose=false + +usage() { + cat <]+>)?(?=\(|;| |$)' "$file" | sed "s/^${crate_full_name}:://" +} + +# Print all public structs and enums excluding error types. +structs_and_enums_no_err() { + grep -oP 'pub (struct|enum) \K[\w:]+(?:<[^>]+>)?(?=\(|;| |$)' "$file" | sed "s/^${crate_full_name}:://" | grep -v Error +} + +# Print all public traits. +traits() { + grep -oP '^pub trait \K[\w:]+' "$file" | sed "s/^${crate_full_name}:://" | sed 's/:$//' +} + +# Check all the commands we use are present in the current environment. +check_required_commands() { + need_cmd grep +} + +say() { + echo "api: $1" +} + +say_err() { + say "$1" >&2 +} + +verbose_say() { + if [ "$flag_verbose" = true ]; then + say "$1" + fi +} + +err() { + echo "$1" >&2 + exit 1 +} + +need_cmd() { + if ! command -v "$1" > /dev/null 2>&1 + then err "need '$1' (command not found)" + fi +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/check-for-api-changes.sh b/contrib/check-for-api-changes.sh new file mode 100755 index 000000000..99f7b4307 --- /dev/null +++ b/contrib/check-for-api-changes.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# Checks the public API of crates, exits with non-zero if there are currently +# changes to the public API not already committed to in the various api/*.txt +# files. + +set -euo pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) +API_DIR="$REPO_DIR/api" + +NIGHTLY=$(cat "$REPO_DIR/nightly-version") +# Our docs have broken intra doc links if all features are not enabled. +RUSTDOCFLAGS="-A rustdoc::broken_intra_doc_links" + +# `sort -n -u` doesn't work for some reason. +SORT="sort --numeric-sort" + +# Sort order is affected by locale. See `man sort`. +# > Set LC_ALL=C to get the traditional sort order that uses native byte values. +export LC_ALL=C + +main() { + need_nightly + need_cargo_public_api + + # If script is running in CI the recent lock file is copied into place + # already by the github action job. Locally be kind to the environment. + if [ "${GITHUB_ACTIONS:-}" != "true" ]; then + [ -f "Cargo.lock" ] && mv Cargo.lock Cargo.lock.tmp + cp Cargo-recent.lock Cargo.lock + fi + + # Just check crates that are stabilising. + generate_api_files "consensus_encoding" + generate_api_files "units" + generate_api_files "primitives" + + [ -f "Cargo.lock.tmp" ] && mv Cargo.lock.tmp Cargo.lock + + check_for_changes +} + +# Uses `CARGO` to generate API files in the specified crate. +# +# Files: +# +# - no-features.txt +# - alloc-only.txt +# - all-features.txt +generate_api_files() { + local crate=$1 + pushd "$REPO_DIR/$crate" > /dev/null + + run_cargo --no-default-features | $SORT | uniq > "$API_DIR/$crate/no-features.txt" + run_cargo --no-default-features --features=alloc | $SORT | uniq > "$API_DIR/$crate/alloc-only.txt" + run_cargo_all_features | $SORT | uniq > "$API_DIR/$crate/all-features.txt" + + popd > /dev/null +} + +# Check if there are changes (dirty git index) to the `api/` directory. +check_for_changes() { + pushd "$REPO_DIR" > /dev/null + + if [[ $(git status --porcelain api) ]]; then + git diff --color=always + echo + err "You have introduced changes to the public API, commit the changes to api/ currently in your working directory" + else + echo "No changes to the current public API" + fi + + popd > /dev/null +} + +# Run cargo when --all-features is not used. +run_cargo() { + RUSTDOCFLAGS="$RUSTDOCFLAGS" cargo +"$NIGHTLY" --locked public-api --simplified "$@" +} + +# Run cargo with all features enabled. +run_cargo_all_features() { + cargo +"$NIGHTLY" --locked public-api --simplified --all-features +} + +need_nightly() { + cargo_ver=$(cargo +"$NIGHTLY" --version) + if echo "$cargo_ver" | grep -q -v nightly; then + err "Need a nightly compiler; have $cargo_ver" + fi +} + +need_cargo_public_api() { + if command -v cargo-public-api > /dev/null; then + return + fi + err "cargo-public-api is not installed; please run 'cargo +nightly install cargo-public-api --locked'" +} + +err() { + echo "$1" >&2 + exit 1 +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/check-for-policy-violations.sh b/contrib/check-for-policy-violations.sh new file mode 100755 index 000000000..c9b9be442 --- /dev/null +++ b/contrib/check-for-policy-violations.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Check if PR abides by our policy. + +set -euo pipefail + +# When running script locally the name used for the `github.com/rust-bitcoin/rust-bitcoin` remote. +REMOTE="upstream" + +main() { + check_required_commands + + if low_level_import_usage; then + err "Please do not import directly from low level crates, import using 'use crate::' instead" + fi +} + +# Enforces import policy. +# +# See `./policy.md` section: `### On re-exports`. +# Greps patch for imports that violate the policy, returns true if an +# violations are found. +low_level_import_usage() { + local crates=("units" "primitives") + local found_violation=false + local violations; + + # Determine the base branch - common CI environment variables. + local base_branch="$REMOTE/master" + if [[ -n "${GITHUB_BASE_REF:-}" ]]; then + base_branch="$GITHUB_BASE_REF" + elif [[ -n "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-}" ]]; then + base_branch="$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" + fi + + for crate in "${crates[@]}"; do + violations=$(git diff "$base_branch"...HEAD -- '*.rs' | grep "^+" | grep -E "use ${crate}::" | grep -v "pub use ${crate}::" || true) + if [[ -n "$violations" ]]; then + say_err "invalid import statement: '${violations:1}'" + found_violation=true + fi + done + + $found_violation +} + +# Check all the commands we use are present in the current environment. +check_required_commands() { + need_cmd grep + need_cmd git +} + +say() { + echo "policy: $1" +} + +say_err() { + say "$1" >&2 +} + +err() { + echo "$1" >&2 + exit 1 +} + +need_cmd() { + if ! command -v "$1" > /dev/null 2>&1 + then err "need '$1' (command not found)" + fi +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/check-semver-feature.sh b/contrib/check-semver-feature.sh new file mode 100755 index 000000000..46839d677 --- /dev/null +++ b/contrib/check-semver-feature.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env bash +# +# Checks semver compatibility between the `--no-features` and `all-features`. +# This is important since it tests for the presence of non-additive cargo features. +# +# Under the hood uses cargo semver-checks to check for breaking changes. +# We cannot use it directly since it only supports checking against published +# crates. +# That's the intended use case for cargo semver-checks: +# you run before publishing a new version of a crate to check semver breaks. +# Here we are hacking it by first generating JSON files from cargo doc +# and then using those files to check for breaking changes with +# cargo semver-checks. + +set -euo pipefail + +# These are the hardcoded flags that cargo semver-checks uses +# under the hood to invoke rustdoc. +RUSTDOCFLAGS="-Z unstable-options --document-private-items --document-hidden-items --output-format=json --cap-lints=allow" + +main() { + # Generate JSON files for no-features and all-features + # 1. bitcoin + generate_json_files_all_features "bitcoin" + generate_json_files_no_default_features "bitcoin" + + # 2. base58ck + generate_json_files_all_features "base58ck" + generate_json_files_no_default_features "base58ck" + + # 3. bitcoin_hashes + generate_json_files_all_features "bitcoin_hashes" + generate_json_files_no_default_features "bitcoin_hashes" + + # 4. bitcoin-units + generate_json_files_all_features "bitcoin-units" + generate_json_files_no_default_features "bitcoin-units" + + # 5. bitcoin-io + generate_json_files_all_features "bitcoin-io" + generate_json_files_no_default_features "bitcoin-io" + + # Check for API semver non-additive cargo features on all the generated JSON files above. + run_cargo_semver_check "bitcoin" + run_cargo_semver_check "base58ck" + run_cargo_semver_check "bitcoin_hashes" + run_cargo_semver_check "bitcoin-units" + run_cargo_semver_check "bitcoin-io" + + # Invoke cargo semver-checks to check for non-additive cargo features + # in all generated files. + check_for_non_additive_cargo_features +} + +# Run cargo doc with the cargo semver-checks rustdoc flags. +# We don't care about dependencies. +run_cargo_doc() { + RUSTDOCFLAGS="$RUSTDOCFLAGS" RUSTC_BOOTSTRAP=1 cargo doc --no-deps "$@" +} + +# Run cargo semver-check +run_cargo_semver_check() { + local crate="$1" + + echo "Running cargo semver-checks for $crate" + # Hack to not fail on errors. + # This is necessary since cargo semver-checks will fail if the + # semver check fails. + # We check that manually later. + set +e + cargo semver-checks -v --baseline-rustdoc "$crate-no-default-features.json" --current-rustdoc "$crate-all-features.json" > "$crate--additive-features.txt" 2>&1 + set -e +} + +# The following function uses cargo doc to generate JSON files that +# cargo semver-checks can use. +# - no-default-features: generate JSON doc files with no default features. +generate_json_files_no_default_features() { + local crate="$1" + + echo "Running cargo doc no-default-features for $crate" + run_cargo_doc --no-default-features -p "$crate" + + # replace _ for - in crate name. + # This is necessary since some crates have - in their name + # which will be converted to _ in the output file by cargo doc. + mv "target/doc/${crate//-/_}.json" "$crate-no-default-features.json" +} +# - all-features: generate JSON doc files with all features. +generate_json_files_all_features() { + local crate="$1" + + echo "Running cargo doc all-features for $crate" + run_cargo_doc --all-features -p "$crate" + + # replace _ for - in crate name. + # This is necessary since some crates have - in their name + # which will be converted to _ in the output file by cargo doc. + mv -v "target/doc/${crate//-/_}.json" "$crate-all-features.json" +} + +# Check if there are non-additive cargo features. +# We loop through all the generated files and check if there is a FAIL +# in the cargo semver-checks output. +# If we detect a fail, we create an empty file non-additive-cargo. +# If the following CI step finds this file, it will add: +# 1. a comment on the PR. +# 2. a label to the PR. +check_for_non_additive_cargo_features() { + for file in *additive-features.txt; do + echo "Checking $file" + if grep -q "FAIL" "$file"; then + echo "You have introduced non-additive cargo features" + echo "FAIL found in $file" + cat "$file" + # flag it as a breaking change + # Handle the case where FAIL is found + touch non-additive-cargo + fi + done + if ! [ -f non-additive-cargo ]; then + echo "No non-additive cargo features found" + else + err "Non-additive cargo features found" + fi +} + +err() { + echo "$1" >&2 + exit 1 +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/check-semver-pr.sh b/contrib/check-semver-pr.sh new file mode 100755 index 000000000..4c83b1f1f --- /dev/null +++ b/contrib/check-semver-pr.sh @@ -0,0 +1,193 @@ +#!/usr/bin/env bash +# +# Checks semver compatibility between the current and target branches. +# Under the hood uses cargo semver-checks to check for breaking changes. +# We cannot use it directly since it only supports checking against published +# crates. +# That's the intended use case for cargo semver-checks: +# you run before publishing a new version of a crate to check semver breaks. +# Here we are hacking it by first generating JSON files from cargo doc +# and then using those files to check for breaking changes with +# cargo semver-checks. + +set -euo pipefail + +# These are the hardcoded flags that cargo semver-checks uses +# under the hood to invoke rustdoc. +RUSTDOCFLAGS="-Z unstable-options --document-private-items --document-hidden-items --output-format=json --cap-lints=allow" + +# These will be set to the commit SHA from the PR's target branch +# GitHub Actions CI. +# NOTE: if running locally this will be set to master. +if [ -n "${GITHUB_BASE_REF+x}" ]; then + TARGET_COMMIT=$GITHUB_BASE_REF # running on CI +else + TARGET_COMMIT=$(git rev-parse master) # running locally +fi + +main() { + # On current commit: + # 1. bitcoin: all-features and no-default-features. + generate_json_files_all_features "bitcoin" "current" + generate_json_files_no_default_features "bitcoin" "current" + + # 2. base58ck: all-features and no-default-features. + generate_json_files_all_features "base58ck" "current" + generate_json_files_no_default_features "base58ck" "current" + + # 3. bitcoin_hashes: all-features, no-default-features and alloc feature. + generate_json_files_all_features "bitcoin_hashes" "current" + generate_json_files_no_default_features "bitcoin_hashes" "current" + generate_json_files_features_alloc "bitcoin_hashes" "current" + + # 4. bitcoin-units: all-features, no-default-features and alloc feature. + generate_json_files_all_features "bitcoin-units" "current" + generate_json_files_no_default_features "bitcoin-units" "current" + generate_json_files_features_alloc "bitcoin-units" "current" + + # 5. bitcoin-io: all-features, no-default-features and alloc feature. + generate_json_files_all_features "bitcoin-io" "current" + generate_json_files_no_default_features "bitcoin-io" "current" + generate_json_files_features_alloc "bitcoin-io" "current" + + + # Switch to target commit. + echo "Checking out target commit at $TARGET_COMMIT" + git checkout "$TARGET_COMMIT" + + # On target commit: + # 1. bitcoin: all-features and no-default-features. + generate_json_files_all_features "bitcoin" "master" + generate_json_files_no_default_features "bitcoin" "master" + + # 2. base58ck: all-features and no-default-features. + generate_json_files_all_features "base58ck" "master" + generate_json_files_no_default_features "base58ck" "master" + + # 3. bitcoin_hashes: all-features, no-default-features and alloc feature. + generate_json_files_all_features "bitcoin_hashes" "master" + generate_json_files_no_default_features "bitcoin_hashes" "master" + generate_json_files_features_alloc "bitcoin_hashes" "master" + + # 4. bitcoin-units: all-features, no-default-features and alloc feature. + generate_json_files_all_features "bitcoin-units" "master" + generate_json_files_no_default_features "bitcoin-units" "master" + generate_json_files_features_alloc "bitcoin-units" "master" + + # 5. bitcoin-io: all-features, no-default-features and alloc feature. + generate_json_files_all_features "bitcoin-io" "master" + generate_json_files_no_default_features "bitcoin-io" "master" + generate_json_files_features_alloc "bitcoin-io" "master" + + # Check for API semver breaks on all the generated JSON files above. + run_cargo_semver_check "bitcoin" "all-features" + run_cargo_semver_check "bitcoin" "no-default-features" + run_cargo_semver_check "base58ck" "all-features" + run_cargo_semver_check "base58ck" "no-default-features" + run_cargo_semver_check "bitcoin_hashes" "all-features" + run_cargo_semver_check "bitcoin_hashes" "no-default-features" + run_cargo_semver_check "bitcoin_hashes" "alloc" + run_cargo_semver_check "bitcoin-units" "all-features" + run_cargo_semver_check "bitcoin-units" "no-default-features" + run_cargo_semver_check "bitcoin-units" "alloc" + run_cargo_semver_check "bitcoin-io" "all-features" + run_cargo_semver_check "bitcoin-io" "no-default-features" + run_cargo_semver_check "bitcoin-io" "alloc" + + # Invoke cargo semver-checks to check for breaking changes + # in all generated files. + check_for_breaking_changes +} + +# Run cargo doc with the cargo semver-checks rustdoc flags. +# We don't care about dependencies. +run_cargo_doc() { + RUSTDOCFLAGS="$RUSTDOCFLAGS" RUSTC_BOOTSTRAP=1 cargo doc --no-deps "$@" +} + +# Run cargo semver-check +run_cargo_semver_check() { + local crate="$1" + local variant="$2" + + echo "Running cargo semver-checks for $crate $variant" + # Hack to not fail on errors. + # This is necessary since cargo semver-checks will fail if the + # semver check fails. + # We check that manually later. + set +e + cargo semver-checks -v --baseline-rustdoc "$crate-master-$variant.json" --current-rustdoc "$crate-current-$variant.json" > "$crate-$variant-semver.txt" 2>&1 + set -e +} + +# The following function uses cargo doc to generate JSON files that +# cargo semver-checks can use. +# - no-default-features: generate JSON doc files with no default features. +generate_json_files_no_default_features() { + local crate="$1" + local version="$2" + + echo "Running cargo doc no-default-features for $crate $version" + run_cargo_doc --no-default-features -p "$crate" + + # replace _ for - in crate name. + # This is necessary since some crates have - in their name + # which will be converted to _ in the output file by cargo doc. + mv "target/doc/${crate//-/_}.json" "$crate-$version-no-default-features.json" +} +# - all-features: generate JSON doc files with all features. +generate_json_files_all_features() { + local crate="$1" + local version="$2" + + echo "Running cargo doc all-features for $crate $version" + run_cargo_doc --all-features -p "$crate" + + # replace _ for - in crate name. + # This is necessary since some crates have - in their name + # which will be converted to _ in the output file by cargo doc. + mv -v "target/doc/${crate//-/_}.json" "$crate-$version-all-features.json" +} +# - alloc: generate JSON doc files with the alloc feature. +generate_json_files_features_alloc() { + local crate="$1" + local version="$2" + + echo "Running cargo doc --features alloc for $crate $version" + run_cargo_doc --no-default-features --features alloc -p "$crate" + + # replace _ for - in crate name. + # This is necessary since some crates have - in their name + # which will be converted to _ in the output file by cargo doc. + mv -v "target/doc/${crate//-/_}.json" "$crate-$version-alloc.json" +} + +# Check if there are breaking changes. +# We loop through all the generated files and check if there is a FAIL +# in the cargo semver-checks output. +# If we detect a fail, we create an empty file semver-break. +# If the following CI step finds this file, it will add: +# 1. a comment on the PR. +# 2. a label to the PR. +check_for_breaking_changes() { + for file in *semver.txt; do + echo "Checking $file" + if grep -q "FAIL" "$file"; then + echo "You have introduced changes to the public API" + echo "FAIL found in $file" + cat "$file" + # flag it as a breaking change + # Handle the case where FAIL is found + touch semver-break + fi + done + if ! [ -f semver-break ]; then + echo "No breaking changes found" + fi +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/copy-githooks.sh b/contrib/copy-githooks.sh new file mode 100755 index 000000000..13632db55 --- /dev/null +++ b/contrib/copy-githooks.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -euo pipefail + +GIT_DIR=$(git rev-parse --git-common-dir) +HOOKS_DIR=$(git config --get core.hooksPath || echo "$GIT_DIR/hooks") + +remove_githooks() { + for hook in githooks/* + do + bn=$(basename "$hook") + echo "Removing githook $bn" + rm "$HOOKS_DIR/$bn" + done + exit 0 +} + +add_githooks() { + mkdir -p "$HOOKS_DIR" + cp -i githooks/* "$HOOKS_DIR" + exit 0 +} + +while getopts "r" flag; do + case $flag in + r) remove_githooks + ;; + *) exit 1 + ;; + esac +done + +add_githooks # Copy githooks by default (no options provided) diff --git a/contrib/crates.sh b/contrib/crates.sh new file mode 100644 index 000000000..a4fa95e2c --- /dev/null +++ b/contrib/crates.sh @@ -0,0 +1,16 @@ +# Sourced by `rust-bitcoin-maintainer-tools/ci/run_task.sh`. +# +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +REPO_DIR=$(git rev-parse --show-toplevel) + +# Generates the crates list based on cargo workspace metadata. +function generate_crates_list() { + cargo metadata --no-deps --format-version 1 | jq -j -r '.packages | map(.manifest_path | rtrimstr("/Cargo.toml") | ltrimstr("'"$REPO_DIR"'/")) | join(" ")' +} + +CRATES=$(generate_crates_list) diff --git a/contrib/ensure-maintainer-tools.sh b/contrib/ensure-maintainer-tools.sh new file mode 100755 index 000000000..fdb145520 --- /dev/null +++ b/contrib/ensure-maintainer-tools.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# +# Ensure maintainer tools are available locally for CI task execution. + +set -euo pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) +MAINTAINER_TOOLS_REF=$(cat "$REPO_DIR/maintainer-tools-version") + +cd "$REPO_DIR" + +if [ ! -d ".maintainer-tools" ]; then + echo "Fetching maintainer tools..." + git clone "https://github.com/rust-bitcoin/rust-bitcoin-maintainer-tools.git" ".maintainer-tools" + cd ".maintainer-tools" + git checkout "$MAINTAINER_TOOLS_REF" +else + cd ".maintainer-tools" + CURRENT_REF=$(git rev-parse HEAD) + if [ "$CURRENT_REF" != "$MAINTAINER_TOOLS_REF" ]; then + echo "Updating maintainer tools to $MAINTAINER_TOOLS_REF" + git fetch + git checkout "$MAINTAINER_TOOLS_REF" + fi +fi + +if ! command -v jq >/dev/null 2>&1; then + echo "Error: jq is required for maintainer tools but not found in PATH" >&2 + echo "Please install jq or ensure it's available in your environment" >&2 + exit 1 +fi diff --git a/contrib/gen-dep-tree.sh b/contrib/gen-dep-tree.sh new file mode 100755 index 000000000..e50b87a0b --- /dev/null +++ b/contrib/gen-dep-tree.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# +# Generate dependency tree for all workspace packages except fuzz. +set -euo pipefail + +exec cargo tree \ + --workspace \ + --exclude bitcoin-fuzz \ + --all-features \ + --edges=no-dev,no-build \ + --format='{lib}' \ + --no-dedupe \ + --prune=serde_json \ + --prune=rand \ + --prune=bincode \ + --prune=serde diff --git a/contrib/gen_label_config.sh b/contrib/gen_label_config.sh new file mode 100755 index 000000000..85ad9a93f --- /dev/null +++ b/contrib/gen_label_config.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Generates the label configuration using crates in the repository. +# The label configuration is appended to the labeler config file. + +config=.github/labeler.yml + +# Define a default value for SCAN_DIR if not set +: "${SCAN_DIR:=.}" + +if [ "${1:-default}" != "--force" ] && ! git diff --exit-code "$config"; +then + echo "Error: $config is not committed." + echo "Refusing to overwrite it to prevent disaster." + echo "Run the script with --force to override this." + exit 1 +fi + +excluded_crates="fuzz|dep_test" + +CRATES="$(cd "$SCAN_DIR" && cargo metadata --no-deps --format-version 1 | jq -j -r '.packages | map(.manifest_path | rtrimstr("/Cargo.toml") | ltrimstr("'"$PWD"'/")) | join(" ")')" + +for crate in $CRATES; +do + if echo "$crate" | grep -qE "$excluded_crates"; + then + continue + fi + + { + echo "C-$crate:" + echo " - changed-files:" + echo " - any-glob-to-any-file: $crate/**" + } >> "$config" +done diff --git a/contrib/generate-bitcoin-re-export-test.sh b/contrib/generate-bitcoin-re-export-test.sh new file mode 100755 index 000000000..1314d93d6 --- /dev/null +++ b/contrib/generate-bitcoin-re-export-test.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +# +# Script for generating a Rust test file that verifies all bitcoin_primitives +# items are re-exported in the `bitcoin` crate. +# +# The script parses api/primitives/all-features.txt and generates use statements +# that will fail to compile if any re-exports are missing. + +set -euo pipefail + +api_file="./api/primitives/all-features.txt" +output_file="./bitcoin/tests/check-re-exports.rs" + +usage() { + cat < "$temp_file" <<'EOF' +// SPDX-License-Identifier: CC0-1.0 + +//! Test that all public types and modules from bitcoin_primitives are re-exported in the bitcoin crate. +//! +//! This test is automatically generated by contrib/generate-bitcoin-re-export-test.sh +//! Any compilation error indicates a missing re-export. + +#![allow(dead_code)] +#![allow(unused_imports)] +// No benefit in running this test without features enabled. +#[cfg(not(feature = "arbitrary"))] +compile_error!("arbitrary feature needs to be enabled"); + +#[test] +fn check_all_bitcoin_primitives_items_are_reexported() { + // This test will fail to compile if any bitcoin_primitives item is not re-exported in the bitcoin crate. + +EOF + + # Extract and convert all pub items + local use_statements=() + local seen_items=() + + while IFS= read -r line; do + local path="" + + # Extract pub enum + if [[ "$line" =~ pub\ enum\ (bitcoin_primitives::[^[:space:]]+) ]]; then + path="${BASH_REMATCH[1]}" + # Extract pub struct + elif [[ "$line" =~ pub\ struct\ (bitcoin_primitives::[^[:space:]\(]+) ]]; then + path="${BASH_REMATCH[1]}" + # Extract pub mod + elif [[ "$line" =~ ^pub\ mod\ (bitcoin_primitives::[^[:space:]]+)$ ]]; then + path="${BASH_REMATCH[1]}" + fi + + if [[ -n "$path" ]]; then + # Remove generic type parameters (e.g., ) + path="${path%%<*}" + + if [[ "$path" == *Encoder* ]] || [[ $path == *Decoder* ]]; then + continue + fi + + # Convert bitcoin_primitives:: to bitcoin:: + local bitcoin_path="${path//bitcoin_primitives::/bitcoin::}" + + # Skip if we've already seen this item + if [[ " ${seen_items[*]} " != *" $bitcoin_path "* ]]; then + seen_items+=("$bitcoin_path") + use_statements+=(" use $bitcoin_path as _;") + fi + fi + done < "$api_file" + + # Sort use statements and add to file + printf '%s\n' "${use_statements[@]}" | sort >> "$temp_file" + + # Add closing brace + echo "}" >> "$temp_file" + + # Move temp file to final location + mv "$temp_file" "$output_file" +} + +check_required_files() { + if [[ ! -f "$api_file" ]]; then + err "Required file not found: $api_file" + fi + + local output_dir + output_dir=$(dirname "$output_file") + if [[ ! -d "$output_dir" ]]; then + err "Output directory not found: $output_dir" + fi +} + +check_required_commands() { + need_cmd grep + need_cmd sort + need_cmd mktemp +} + +say() { + echo "generate-bitcoin-re-export-test: $1" +} + +say_err() { + say "$1" >&2 +} + +err() { + echo "$1" >&2 + exit 1 +} + +need_cmd() { + if ! command -v "$1" > /dev/null 2>&1 + then err "need '$1' (command not found)" + fi +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/generate-primitives-re-export-test.sh b/contrib/generate-primitives-re-export-test.sh new file mode 100755 index 000000000..ca138eadf --- /dev/null +++ b/contrib/generate-primitives-re-export-test.sh @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +# +# Script for generating a Rust test file that verifies all bitcoin_units items +# are re-exported in bitcoin_primitives. +# +# The script parses api/units/all-features.txt and generates use statements +# that will fail to compile if any re-exports are missing. + +set -euo pipefail + +api_file="./api/units/all-features.txt" +output_file="./primitives/tests/check-re-exports.rs" + +usage() { + cat < "$temp_file" <<'EOF' +// SPDX-License-Identifier: CC0-1.0 + +//! Test that all public types and modules from bitcoin_units are re-exported in bitcoin_primitives. +//! +//! This test is automatically generated by contrib/generate-primitives-re-export-test.sh +//! Any compilation error indicates a missing re-export. + +#![allow(dead_code)] +#![allow(unused_imports)] +// No benefit in running this test without features enabled. +#[cfg(not(feature = "alloc"))] +compile_error!("alloc feature needs to be enabled"); +#[cfg(not(feature = "hex"))] +compile_error!("hex feature needs to be enabled"); +#[cfg(not(feature = "arbitrary"))] +compile_error!("arbitrary feature needs to be enabled"); + +#[test] +fn check_all_bitcoin_units_items_are_reexported() { + // This test will fail to compile if any bitcoin_units item is not re-exported in bitcoin_primitives + +EOF + + # Extract and convert all pub items + local use_statements=() + local seen_items=() + + while IFS= read -r line; do + local path="" + + # Extract pub enum + if [[ "$line" =~ pub\ enum\ (bitcoin_units::[^[:space:]]+) ]]; then + path="${BASH_REMATCH[1]}" + # Extract pub struct + elif [[ "$line" =~ pub\ struct\ (bitcoin_units::[^[:space:]\(]+) ]]; then + path="${BASH_REMATCH[1]}" + # Extract pub mod + elif [[ "$line" =~ ^pub\ mod\ (bitcoin_units::[^[:space:]]+)$ ]]; then + path="${BASH_REMATCH[1]}" + fi + + if [[ -n "$path" ]]; then + # Remove generic type parameters (e.g., ) + path="${path%%<*}" + + # Convert bitcoin_units:: to bitcoin_primitives:: + local primitives_path="${path//bitcoin_units::/bitcoin_primitives::}" + + # Skip if we've already seen this item + if [[ " ${seen_items[*]} " != *" $primitives_path "* ]]; then + seen_items+=("$primitives_path") + use_statements+=(" use $primitives_path as _;") + fi + fi + done < "$api_file" + + # Sort use statements and add to file + printf '%s\n' "${use_statements[@]}" | sort >> "$temp_file" + + # Add closing brace + echo "}" >> "$temp_file" + + # Move temp file to final location + mv "$temp_file" "$output_file" +} + +check_required_files() { + if [[ ! -f "$api_file" ]]; then + err "Required file not found: $api_file" + fi + + local output_dir + output_dir=$(dirname "$output_file") + if [[ ! -d "$output_dir" ]]; then + err "Output directory not found: $output_dir" + fi +} + +check_required_commands() { + need_cmd grep + need_cmd sort + need_cmd mktemp +} + +say() { + echo "generate-primitives-re-export-test: $1" +} + +say_err() { + say "$1" >&2 +} + +err() { + echo "$1" >&2 + exit 1 +} + +need_cmd() { + if ! command -v "$1" > /dev/null 2>&1 + then err "need '$1' (command not found)" + fi +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/contrib/release.sh b/contrib/release.sh new file mode 100755 index 000000000..73abdd01f --- /dev/null +++ b/contrib/release.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# +# Check that we can publish crates in their current form if there are changes on top of the tip of +# master that imply that we are about to do a release. +# +# disable follow sourced files. +# shellcheck disable=SC1091 + +set -euox pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) + +# Sets CRATES to be a list of all crates in the repo. +. "$REPO_DIR"/contrib/test_vars.sh + +main () { + for crate in $CRATES; do + if release_changes "$crate"; then + echo "$crate has changes implying this is a release PR, checking if we can publish ..." + + # Check if there is any mention of TBD which means the + # next version number should be filled in. + if grep -qr "since = \"TBD" "./$crate"; then + echo Version number needs to be filled in following places: + grep -r "since = \"TBD" "./$crate" + exit 1 + fi + + # Then try to dry-run cargo publish + publish_dry_run "$crate" + fi + done +} + +# Returns 0 if crate ($1) contains changes since tip of master that imply this patch set is done in +# preparation for releasing the crate. + +release_changes() { + local crate=$1 + set +e + + git log --patch --reverse master.. -- "$crate"/Cargo.toml | grep -E '\+version =' + local exit_code=$? + + set -e + return $exit_code +} + +# Do a dry run publish to crates.io using the correct package name for crate ($1). +# We use `set -e` so this will fail the script if the dry-run fails. +publish_dry_run() { + local crate=$1 + if [ "$crate" == "bitcoin" ]; then + cargo publish -p "bitcoin" --dry-run + elif [ "$crate" == "hashes" ]; then + cargo publish -p "bitcoin_hashes" --dry-run + elif [ "$crate" == "internals" ]; then + cargo publish -p "bitcoin-internals" --dry-run + elif [ "$crate" == "units" ]; then + cargo publish -p "bitcoin-units" --dry-run + fi +} + +# +# Main script. +# +main "$@" diff --git a/contrib/test-miri.sh b/contrib/test-miri.sh new file mode 100755 index 000000000..5e979a6f4 --- /dev/null +++ b/contrib/test-miri.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -euox pipefail + +cd "$(dirname "$0")/.." + +. contrib/test_vars.sh + +target_features="$(rustc --print target-features | awk '{ if ($1 == "") { exit 0 } if (NR != 1 && $1 != "crt-static" && $1 != "soft-float") { if (NR == 2) { printf "+%s", $1 } else { printf ",+%s", $1 } } }')" + +for crate in $CRATES; +do + # The secp256k1 crate cannot be miri-checked because of FFI, so we have to exclude it + if cargo tree --manifest-path "$crate/Cargo.toml" | grep -q secp256k1; + then + echo "$crate depends on secp256k1, skipping..." >&2 + continue + fi + # Running miri is expensive and not needed for crates that don't contain unsafe + if RUSTFLAGS="-C target-feature=$target_features -F unsafe-code" cargo check -q --all-features --target x86_64-unknown-linux-gnu 2>/dev/null; + then + echo "No unsafe code in $crate, skipping..." >&2 + continue + fi + + RUSTFLAGS="-C target-feature=$target_features" RUSTDOCFLAGS="-C target-feature=$target_features" MIRIFLAGS=-Zmiri-backtrace=full cargo miri test --manifest-path "$crate/Cargo.toml" --all-features --target x86_64-unknown-linux-gnu +done diff --git a/contrib/test_vars.sh b/contrib/test_vars.sh new file mode 100644 index 000000000..3943aac65 --- /dev/null +++ b/contrib/test_vars.sh @@ -0,0 +1,13 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# +# Used by labeler.yaml +# +# Not to be confused with the per crate `test_vars.sh` used by +# `rust-bitcoin-maintainer-tools-run_task.sh`. +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +CRATES="$(cargo metadata --no-deps --format-version 1 | jq -j -r '.packages | map(.manifest_path | rtrimstr("/Cargo.toml") | ltrimstr("'"$PWD"'/")) | join(" ")')" +DEPS="recent minimal" diff --git a/contrib/update-lock-files.sh b/contrib/update-lock-files.sh new file mode 100755 index 000000000..6d73aae93 --- /dev/null +++ b/contrib/update-lock-files.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# +# Update the minimal and recent lock files. + +set -euo pipefail + +NIGHTLY=$(cat nightly-version) + +# The `direct-minimal-versions` and `minimal-versions` dependency +# resolution strategy flags each have a little quirk. `direct-minimal-versions` +# allows transitive versions to upgrade, so we are not testing against +# the actual minimum tree. `minimal-versions` allows the direct dependency +# versions to resolve upward due to transitive requirements, so we are +# not testing the manifest's versions. Combo'd together though, we +# can get the best of both worlds to ensure the actual minimum dependencies +# listed in the crate manifests build. + +# Check that all explicit direct dependency versions are not lying, +# as in, they are not being bumped up by transitive dependency constraints. +rm -f Cargo.lock && cargo +"$NIGHTLY" check --all-features -Z direct-minimal-versions +# Now that our own direct dependency versions can be trusted, check +# against the lowest versions of the dependency tree which still +# satisfy constraints. Use this as the minimal version lock file. +rm -f Cargo.lock && cargo +"$NIGHTLY" check --all-features -Z minimal-versions +cp -f Cargo.lock Cargo-minimal.lock + +# Conservatively bump of recent dependencies. +cp -f Cargo-recent.lock Cargo.lock +cargo check --all-features +cp -f Cargo.lock Cargo-recent.lock diff --git a/contrib/whitelist_deps.sh b/contrib/whitelist_deps.sh new file mode 100644 index 000000000..cb4a22b13 --- /dev/null +++ b/contrib/whitelist_deps.sh @@ -0,0 +1,10 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# - hashes because of secp v0.30 +# - io because of hashes +# - hex because 1.0 only has decoding +DUPLICATE_DEPS=("bitcoin_hashes" "hex-conservative" "bitcoin-io") diff --git a/crypto/CHANGELOG.md b/crypto/CHANGELOG.md new file mode 100644 index 000000000..4ac809f05 --- /dev/null +++ b/crypto/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.0.0 - Initial dummy release + +- Empty crate to reserve the name on crates.io diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml new file mode 100644 index 000000000..548c9b993 --- /dev/null +++ b/crypto/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "bitcoin-crypto" +version = "0.0.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +description = "Crypto support for the rust-bitcoin ecosystem" +categories = ["cryptography::cryptocurrencies"] +keywords = ["bitcoin", "types"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc"] +alloc = [] + +[dependencies] + +[dev-dependencies] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/crypto/README.md b/crypto/README.md new file mode 100644 index 000000000..f1e74122a --- /dev/null +++ b/crypto/README.md @@ -0,0 +1,3 @@ +# Cryptography + +Types and logic required to support cryptography i.e., bitcoin keys. diff --git a/crypto/contrib/extra_lints.sh b/crypto/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/crypto/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/crypto/contrib/test_vars.sh b/crypto/contrib/test_vars.sh new file mode 100644 index 000000000..92dc09406 --- /dev/null +++ b/crypto/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc" + +# Run these examples. +EXAMPLES="" diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs new file mode 100644 index 000000000..0d98f783a --- /dev/null +++ b/crypto/src/lib.rs @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Cryptography support for the rust-bitcoin ecosystem. + +// NB: This crate is empty if `alloc` is not enabled. +#![cfg(feature = "alloc")] +#![no_std] +// Experimental features we need. +#![doc(test(attr(warn(unused))))] +// Coding conventions. +#![warn(deprecated_in_future)] +#![warn(missing_docs)] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..9d90c1bc7 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,13 @@ +# rust-bitcoin documentation + +This directory holds documentation for the `rust-bitcoin` repository and potentially various other +directly related crates from the `rust-bitcoin` GitHub organisation (e.g. `rust-secp256k1`). + +In general, PR discussions on source code should be about the technical content of changes. To debate +whether a change should be made at all, or the strategy for making changes, it is better to first PR to +the `docs/` tree. If a PR discussion veers into this sort of strategic discussion, the PR should be put on +hold and a PR made to the `docs/` tree or in the Discussions section to debate it before moving forward. + +## Dependency tree + +The `./dep-tree` file was generated using `just gen-dep-tree`. diff --git a/docs/addresses.md b/docs/addresses.md new file mode 100644 index 000000000..f55b57989 --- /dev/null +++ b/docs/addresses.md @@ -0,0 +1,3 @@ +# Split out an address crate + +Split the `address` module out into its own crate. diff --git a/docs/adr/0001_consensus_encoding.md b/docs/adr/0001_consensus_encoding.md new file mode 100644 index 000000000..48bb1553a --- /dev/null +++ b/docs/adr/0001_consensus_encoding.md @@ -0,0 +1,151 @@ +# consensus_encoding crate for sans-I/O + +* Status: accepted +* Authors: Andrew Poelstra +* Date: 2025-09-06 +* Targeted modules: `consensus_encoding`, `primitives`, `units` +* Associated tickets/PRs: #4912 + +## Context and Problem Statement + +The rust-bitcoin project needs a way to perform consensus encoding/decoding operations without depending on std. The existing consensus encoding approach is somewhat tied to the `std::io` interfaces, but in order to make it no-std compatible, the `bitcoin-io` crate was introduced with "bridges" to the std I/O traits. But despite the best efforts of the bridges, there is still a lot of caller friction. Plus there is a requirement to always deal with I/O errors even in non-I/O contexts (e.g. hashing an encoding). + +Is there a way to better support encoding in no-std, std, non-I/O, and even async contexts? + +## Decision Drivers + +* Support no_std environments. +* Reduce API friction. +* Eliminate I/O errors in non-I/O contexts. + +## Considered Options + +#### Option 1: Roll with the existing bitcoin-io crate + +The crate has its pain points, but it gets the job done. + +**Pros:** + +* Maintains existing API surface. + +**Cons:** + +* Pain points for the general `std::io` case and error handling remain. +* The interface would be tied to the v1.0.0 release of the `primitives` and `units` crates, requiring maintenance support for a very long time. + +#### Option 2: Adopt the push_decode crate + +Martin HabovÅ¡tiak wrote a general purpose sans-I/O encoding/decoding crate, [`push_decode`], which satisfies the technical requirements. + +**Pros:** + +* Already written. +* Removes ties to std I/O and I/O errors. + +**Cons:** + +* Is general purpose, so has a few layers of abstraction and complexity not required in the bitcoin domain. + +#### Option 3: Create dedicated consensus_encoding crate + +Extract consensus encoding/decoding logic into a new crate which is sans-I/O and focused only on the bitcoin domain. + +**Pros:** + +* Removes ties to std I/O and I/O errors. +* Interface is tailored for the bitcoin domain. + +**Cons:** + +* Requires most amount of new code to write and maintain. + +## Decision Outcome + +Option #3, dedicated `consensus_encoding` crate. While it is new code, it is heavily based on [`push_decode`] and slimmed down to just what is required in the workspace. It supports no-std, std, non-I/O, and could support async contexts. It should be relatively cheap to maintain given the limited domain. + +## Technical Design + +The `consensus_encoding` crate provides traits and utilities for encoding and decoding Bitcoin data types in a consensus-consistent way. This crate implements a **sans-I/O** architecture, designed to work efficiently in `no_std` environments while supporting both synchronous and asynchronous I/O when needed. + +The implementation is heavily based on the more general [`push_decode`] crate written by Martin HabovÅ¡tiak. But where `push_decode` is flexible to handle many different encoding scenarios, `consensus_encoding` has been slimmed down to only handle what is required by the Bitcoin ecosystem. + +Sans-I/O architecture separates data codecs from I/O operations. Instead of reading directly from `io::Read` traits or writing to `io::Write` traits, the core types work with byte slices and provide iterator-like interfaces for consuming data. Same codec logic works for sync I/O, async I/O, or other use cases such as hash engines. So unlike traditional "pull decoders" that read data on-demand, this crate uses a "push" approach where *decoders* consume data in chunks and maintain internal state. The *caller* drives the process by managing buffers and I/O to push bytes into the decoder. And on the other side, *encoders* produce data in chunks which a caller pulls in order to write to a sink. + +Encoding is generally infallible (e.g. encoding to `Vec` never fails). Decoding on the other hand has to deal with many failure scenarios due to not owning the bytes it's consuming. This complicates the interface as decoders provide specific errors for failure modes (`UnexpectedEof`, `InvalidData`, etc.). But I/O errors are handled by the caller functions, keeping the core codec logic I/O-agnostic. + +### Encoders + +```rust +pub trait Encodable { + type Encoder<'s>: Encoder + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_>; +} + +pub trait Encoder { + fn current_chunk(&self) -> &[u8]; + fn advance(&mut self) -> bool; +} +``` + +A Bitcoin type implements `Encodable` in order to produce `Encoder` instances for its type. So for example a `Transaction` type is made `Encodable` and linked to a `TransactionEncoder` type which implements `Encoder`. The `Encodable` trait makes use of Rust's [Generic Associated Type (GAT)] feature which ties `Encoder` lifetimes to the instance of the type they are encoding. This allows the encoder to avoid any copy or clones of bytes, instead referencing them directly, which is often powerful in the Bitcoin context where bytes are already in encoded form. + +Once a caller has an `Encoder` instance, it pulls bytes out with calls to `Encoder::current_chunk`. The caller bounces between `Encoder::current_chunk` and `Encoder::advance` until the encoder is exhausted which is signaled by `Encoder::advance` returning `false`. While we considered making these a single method, the "immutable accessor method plus mutable advance state method" greatly simplifies lifetime management when encoders are combined. And encoder composition is very common in Bitcoin types which are generally composed internally of other Bitcoin types. + +### Decoders + +```rust +pub trait Decodable { + type Decoder: Decoder; + fn decoder() -> Self::Decoder; +} + +pub trait Decoder: Sized { + type Output; + type Error; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result; + fn end(self) -> Result; + fn read_limit(&self) -> usize; +} +``` + +Similar to encoding, Bitcoin types implement `Decodable` in order to generate `Decoder`s. Unlike encoding, no GAT is required since the decoder is taking ownership of the bytes. + +The caller interface is significantly more complex than encoding since `Decoder`s are fallible, so both `Decoder::push_bytes` and `Decoder::end` return a `Result`. A caller pushes bytes through `Decoder::push_bytes` until it returns `false`. That is the signal for the caller to now consume the `Decoder` with `Decoder::end` and get the output type. The `bytes` parameter of `Decoder::push_bytes` is mutable to allow the decoder to "consume" bytes by advancing the slice. Any un-used bytes remain in the `bytes` buffer. + +The `Decoder::read_limit` method has no encoding parallel. It is another complexity due to decoders not having a priori knowledge about the amount of bytes they will be dealing with. But this helper function supplies hints to callers which allows them to better manage their buffer for the decoder, avoiding both inefficient under-reads and unnecessary over-reads. + +### Callers + +Library consumers can always define callers for their specific needs (e.g. async), but callers for the most common use cases are provided by the crate as free functions. Here are the signatures of the provided callers which obviously connect codecs to the standard library I/O. + +```rust +#[cfg(feature = "std")] +pub fn encode_to_writer(object: &T, mut writer: W) -> Result<(), std::io::Error> +where + T: Encodable + ?Sized, + W: std::io::Write, +{} + +#[cfg(feature = "std")] +pub fn decode_from_read(mut reader: R) -> Result::Error>> +where + T: Decodable, + R: std::io::BufRead, +{} +``` + +The keen eye will catch how the decode caller requires the use of a `std::io::BufRead` instead of just `std::io::Read`. While the crate also supports `std::io::Read`, `std::io::BufRead` mitigates a lot of the complexity for decoder buffer management and will almost always be more performant. + +## Links + +* Initial implementation in [#4912]. +* First release in [#5160]. + +[#4912]: +[#5160]: +[`push_decode`]: +[Generic Associated Type (GAT)]: diff --git a/docs/adr/template.md b/docs/adr/template.md new file mode 100644 index 000000000..e17f97942 --- /dev/null +++ b/docs/adr/template.md @@ -0,0 +1,56 @@ +# [short title of solved problem and solution] + +* Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-1234] +* Authors: [list everyone who authored the decision] +* Date: [YYYY-MM-DD when the decision was last updated] +* Targeted modules: [which crate or module does this change target] +* Associated tickets/PRs: [PR/issue links] + +## Context and Problem Statement + +[Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.] + +## Decision Drivers + +* [driver 1, e.g., a force, facing concern, …] +* [driver 2, e.g., a force, facing concern, …] +* … + +## Considered Options + +#### [Option 1] + +[example | description | pointer to more information | …] + +**Pros:** + +* Good, because [argument …] + +**Cons:** + +* Bad, because [argument …] + +#### [Option 2] +... + +#### [Option 3] +... + +## Decision Outcome + +Chosen option: "[option 1]", because [justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force force | … | comes out best (see below)]. + +### Positive Consequences + +* [e.g., improvement of quality attribute satisfaction, follow-up decisions required, …] +* … + +### Negative Consequences + +* [e.g., compromising quality attribute, follow-up decisions required, …] +* … + +## Links + +* [Link type] [Link to ADR] +* … diff --git a/docs/bip-32.md b/docs/bip-32.md new file mode 100644 index 000000000..8f6f501af --- /dev/null +++ b/docs/bip-32.md @@ -0,0 +1,19 @@ +# BIP-0032 and BIP-0380 + +The current module has not been patched much in the last 5 years and the rest of the code base has +stylistically changed quite a bit. + +* Re-write the BIP-0032 API +* Add support for BIP-0380 + +See [BIP-0032 super issue](https://github.com/rust-bitcoin/rust-bitcoin/issues/4770). + + +## Notes + +If you see some design issue missing, feel free to PR to update this file, or to post to the super +issue for discussion. But don't assume that we will be able to find anything in the super issue +later [0] ; anything actionable that comes out of the super issue should be posted to this doc for +posterity. + +- [0] GitHub issues are notoriously difficult to read when they get a lot of discussion. diff --git a/docs/crates.md b/docs/crates.md new file mode 100644 index 000000000..628a2e0d3 --- /dev/null +++ b/docs/crates.md @@ -0,0 +1,48 @@ +# rust-bitcoin stack of crates + +The `rust-bitcoin` project is in the, very long, process of crate +smashing. The original single `rust-bitcoin` crate has already been +broken into a number of pieces and this work is ongoing. Both current +and future crates are documented here. Future crates typically have an +entry in [roadmap.md] and likely also a file of their own. + +## Current crates + +- `addresses`: **Empty** placeholder (see future crates below). +- `base58`: Bitcoin base58 encoding and decoding (for pre-segwit addresses). +- `bitcoin`: The `rust-bitcoin` crate. +- `chacha20_poly1305`: ChaCha20 stream cipher with the Poly1305 MAC. +- `consensus_encoding`: Consensus encoding and decoding. +- `crypto`: Cryptography support for the rust-bitcoin ecosystem. +- `hashes`: Rust Bitcoin hashes library. +- `internals`: Used internally by crates in this repo. +- `io`: Rust Bitcoin I/O library (to support `no_std`). +- `p2p`: Rust Bitcoin peer to peer message types. +- `primitives`: Rust Bitcoin primitive types. +- `units`: Rust Bitcoin unit types. + +### Crates in our stack but in different repositories + +A few crates are in different repositories, primarily because they were either started by different +people or they have a (slightly) different set of maintainers and/or merge policy. + +- `secp256k1`: https://github.com/rust-bitcoin/rust-secp256k1 +- `bech32`: https://github.com/rust-bitcoin/rust-bech32 +- `hex-conservative`: https://github.com/rust-bitcoin/hex-conservative +- `miniscript`: https://github.com/rust-bitcoin/rust-miniscript + +## Future crates + +- `addresses`: Bitcoin addresses (see [addresses.md]) +- `bip-32`: BIP-0032 (and maybe BIP-0380) support (see [bip-32.md]) +- `psbt`: PSBTv2 support (see [psbt.md]) +- `keys`/`crypto`: Cryptography stuff or maybe just keys (see [keys.md]) + +## Re-export policy + +See `./policy.md`. + +[addresses.md]: ./addresses.md +[bip-32.md]: ./bip-32.md +[keys.md]: ./keys.md +[psbt.md]: ./psbt.md diff --git a/docs/crypto.md b/docs/crypto.md new file mode 100644 index 000000000..03f554656 --- /dev/null +++ b/docs/crypto.md @@ -0,0 +1,65 @@ +# Bitcoin keys / Bitcoin crypto + +Either `bitcoin-keys` and just have keys in it or `bitcoin-crypto` and +have the other stuff from `bitcoin::crypto` in it. + +## `secp256k1` + +Both `bitcoin-keys` and `bitcoin-crypto` would depend on `secp256k1`. + +Other things that use secp directly or indirectly through keys/crypto: + +- `addresses` (for keys only) +- `bip-32` (for keys only) +- `psbt` for keys and signing +- Taproot script extension methods +- `bitcoin::taproot` module (uses secp directly) +- `bitcoin::sign_message` module (uses secp directly) + +Taproot stuff is quite entangled in various places throughout the +codebase which in turn entangles secp. + +## Keys + +Public and private keys. + +The reason for splitting this out is so that other crates can depend on keys without depending on +`bitcoin` e.g., `addresses`. + +(Note plural for crate name and singular for current module name, in line with what we did for +`address` module and `addresses` crate.) + +Current public types in `bitcoin::crypto::key`: + +- `XOnlyPublicKey` +- `PublicKey` +- `SortKey` +- `PubkeyHash` +- `WPubkeyHash` +- `CompressedPublicKey` +- `PrivateKey` +- `TweakedPublicKey` +- `TweakedKeypair` +- `SerializedXOnlyPublicKey` +- Various error types +- `TapTweak` trait + +### Current obvious complications + +Looking at `bitcoin::crypto::key` there are some obvious things that will need fixing. + +#### `NetworkKind` + +Currently we are using `bitcoin::network::NetworkKind` in `PrivateKey`. + +- Used to get the first byte of WIF format +- Passed to functions that create addresses e.g., `Address::p2pkh(key, network)` + +#### `ScriptBuf` + +Possibly ok if we have a dependency on `primitives`. Only used for scriptcode. + +#### Taproot stuff + +`TapNodeHash` and `TapTweakHash` are used to implement the `TapTweak` trait on `UntweakedPublickey` +and `UntweakedKeypair`. diff --git a/docs/dep-tree b/docs/dep-tree new file mode 100644 index 000000000..7f69bb0f0 --- /dev/null +++ b/docs/dep-tree @@ -0,0 +1,200 @@ +base58ck +├── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +└── bitcoin_hashes + ├── bitcoin_internals + │ └── hex_conservative + │ └── arrayvec + └── hex_conservative + └── arrayvec + +bitcoin +├── arbitrary +├── base58ck +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── bitcoin_hashes +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +├── base64 +├── bech32 +├── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_io +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── bitcoin_hashes +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_primitives +│ ├── arbitrary +│ ├── arrayvec +│ ├── bitcoin_consensus_encoding +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── bitcoin_hashes +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── hex_conservative +│ │ └── arrayvec +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ ├── bitcoin_units +│ │ ├── arbitrary +│ │ ├── bitcoin_consensus_encoding +│ │ │ ├── bitcoin_internals +│ │ │ │ └── hex_conservative +│ │ │ │ └── arrayvec +│ │ │ └── bitcoin_hashes +│ │ │ ├── bitcoin_internals +│ │ │ │ └── hex_conservative +│ │ │ │ └── arrayvec +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ ├── bitcoin_hashes +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_units +│ ├── arbitrary +│ ├── bitcoin_consensus_encoding +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── bitcoin_hashes +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_hashes +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +├── bitcoinconsensus +├── hex_conservative +│ └── arrayvec +└── secp256k1 + ├── bitcoin_hashes + │ ├── bitcoin_io + │ └── hex_conservative + │ └── arrayvec + └── secp256k1_sys + +bitcoin_addresses + +bitcoin_consensus_encoding +├── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +└── bitcoin_hashes + ├── bitcoin_internals + │ └── hex_conservative + │ └── arrayvec + └── hex_conservative + └── arrayvec + +bitcoin_internals +└── hex_conservative + └── arrayvec + +bitcoin_io +├── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +└── bitcoin_hashes + ├── bitcoin_internals + │ └── hex_conservative + │ └── arrayvec + └── hex_conservative + └── arrayvec + +bitcoin_primitives +├── arbitrary +├── arrayvec +├── bitcoin_consensus_encoding +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── bitcoin_hashes +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_units +│ ├── arbitrary +│ ├── bitcoin_consensus_encoding +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── bitcoin_hashes +│ │ ├── bitcoin_internals +│ │ │ └── hex_conservative +│ │ │ └── arrayvec +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +├── bitcoin_hashes +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +└── hex_conservative + └── arrayvec + +bitcoin_units +├── arbitrary +├── bitcoin_consensus_encoding +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── bitcoin_hashes +│ ├── bitcoin_internals +│ │ └── hex_conservative +│ │ └── arrayvec +│ └── hex_conservative +│ └── arrayvec +└── bitcoin_internals + └── hex_conservative + └── arrayvec + +bitcoin_hashes +├── bitcoin_internals +│ └── hex_conservative +│ └── arrayvec +└── hex_conservative + └── arrayvec + +chacha20_poly1305 diff --git a/docs/dependencies.md b/docs/dependencies.md new file mode 100644 index 000000000..113dbb230 --- /dev/null +++ b/docs/dependencies.md @@ -0,0 +1,39 @@ +# Policy on adding dependencies + +TL;DR We are averse to adding dependencies, there needs to be a strong case for it. + +Applies to any crate in the `rust-bitcoin` repository. When adding functionality one can add a +dependency or NIH it. When evaluating a dependency we consider: + +* Maintainers are reputable and know idiomatic Rust well-enough +* Maintainers respond to bug reports quickly +* Idiomatic API, well documented, ideally stable or close to stable +* Conservative MSRV - hard requirement for mandatory dependencies +* Reasonable performance +* Good test coverage, CI, fuzzing, clippy, miri (if applicable) +* No reckless `unsafe` (see below). +* Maintainer responds well to code quality PRs (refactors) + +These requirements apply recursively and the total dependency tree must not contain significantly +more code than what is required to implement the desired feature. + +### Reckless unsafe + +Reckless `unsafe` is defined as having any of these properties: + +- Large complicated chunks of `unsafe` (whole module containing `unsafe` is an `unsafe` chunk!). +- (private) function not marked `unsafe` when it can UB depending on arguments (`actix-web` flamewar). +- Code that can be written without `unsafe` while staying equally fast thanks to compiler optimizations. +- Missing safe abstractions. + +### What this means + +In practice, any dependencies that fail the above sanity checks are rejected out of hand. + +After that, discussion becomes about these more nuanced topics: + +* Whether the benefit is too niche/special-case. +* Possible past MSRV disagreements with the maintainers. +* Where we have our own unsafe code and wonder whether we should outsource the responsibility or not + (e.g. `ArrayVec`) + diff --git a/docs/keys.md b/docs/keys.md new file mode 100644 index 000000000..7c1401cdb --- /dev/null +++ b/docs/keys.md @@ -0,0 +1,64 @@ +# Bitcoin keys / Bitcoin crypto + +Either `bitcoin-keys` and just have keys in it or `bitcoin-crypto` and +have the other stuff from `bitcoin::crypto` in it. + +For now we use term 'keys', above is an open question. + +## On `secp256k1` + +Both `bitcoin-keys` and `bitcoin-crypto` would depend on `secp256k1`. + +Other things that use secp directly or indirectly through keys/crypto: + +- `addresses` (for keys only) +- `bip-32` (for keys only) +- `psbt` for keys and signing +- Taproot script extension methods +- `bitcoin::taproot` module (uses secp directly) +- `bitcoin::sign_message` module (uses secp directly) + +## Related to keys + +Public and private keys. + +The reason for splitting this out is so that other crates can depend on keys without depending on +`bitcoin` e.g., `addresses`. + +(Note plural for crate name and singular for current module name, in line with what we did for +`address` module and `addresses` crate.) + +Current public types in `bitcoin::crypto::key`: + +- `XOnlyPublicKey` +- `PublicKey` +- `SortKey` +- `PubkeyHash` +- `WPubkeyHash` +- `CompressedPublicKey` +- `PrivateKey` +- `TweakedPublicKey` +- `TweakedKeypair` +- `SerializedXOnlyPublicKey` +- Various error types +- `TapTweak` trait + +### Current obvious complications + +Looking at `bitcoin::crypto::key` there are some obvious things that will need fixing. + +#### `NetworkKind` + +Currently we are using `bitcoin::network::NetworkKind` in `PrivateKey`. + +- Used to get the first byte of WIF format +- Passed to functions that create addresses e.g., `Address::p2pkh(key, network)` + +#### `ScriptBuf` + +Possibly ok if we have a dependency on `primitives`. Only used for scriptcode. + +#### Taproot stuff + +`TapNodeHash` and `TapTweakHash` are used to implement the `TapTweak` trait on `UntweakedPublickey` +and `UntweakedKeypair`. diff --git a/docs/policy.md b/docs/policy.md new file mode 100644 index 000000000..9b6b73323 --- /dev/null +++ b/docs/policy.md @@ -0,0 +1,374 @@ +# Coding policy for the rust-bitcoin repository + +We have various `rust-bitcoin` specific coding styles and conventions that are +grouped here loosely under the term 'policy'. These are things we try to adhere +to but that you should not need to worry too much about if you are a new +contributor. Think of this as a place to collect group knowledge that exists in +the various PRs over the last few years. + +## Import statements + +We use the following style for import statements, see +(https://github.com/rust-bitcoin/rust-bitcoin/discussions/2088) for the discussion that led to this. + +```rust +// Modules first, as they are part of the project's structure. +pub mod aa_this; +mod bb_private; +pub mod cc_that; + +// Private imports, rustfmt will sort and merge them correctly. +use crate::aa_this::{This, That}; +use crate::bb_that; + +// Public re-exports. +#[rustfmt::skip] // Keeps public re-exports separate, because of this we have to sort manually. +pub use { + crate::aa_aa_this, + crate::bb_bb::That, +} + +// Avoid wildcard imports, except for 3 rules: + +// Rule 1 - test modules. +#[cfg(test)] +mod tests { + use super::*; // OK +} + +// Rule 2 - enum variants. +use LockTime::*; // OK + +// Rule 3 - opcodes. +use opcodes::all::*; // OK + +// Finally here is an example where we don't allow wildcard imports: +use crate::prelude::*; // *NOT* OK +use crate::prelude::{DisplayHex, String, Vec} // OK +``` + +## Re-exports + +Types should _not_ be re-exported unless it is _really_ helpful. I.e., we considered re-exporting +types from modules where they appear in the public API but decided against it. + +### pub extern crates + +Any crate `foo` which exposes a type from crate `bar` MUST publicly re-export `bar` crate at the +root. + + +For example: + +```rust +/// Re-export the `hex-conservative` crate. +pub extern crate hex; +``` + +Note, can use this exact doc format. + +### Special treatment of `bitcoin`, `primitives`, `units` + +`bitcoin`, `primitives`, and `units` should each be a superset of the crates below. + +E.g for any `units::Foo`, there will be a `primitives::Foo`, and `bitcoin::Foo`. This goes for all +types and modules. + +For these three crates: + +- Non-error re-exports use `doc(inline)`. +- Error re-exports use `doc(no_inline)`. +- Error types that are directly in the API are re-exported. +- Other error types are available in an `error` module. + +For example in `units`: + +```rust + +pub mod foo { + // SomeError is 'directly' in the API but FooError is not. + pub use self::error::SomeError; + + /// A FooBar type. + pub struct FooBar { ... }; + + /// Some function. + pub fn some_function() -> SomeError { + // Example error logic + SomeError::Foo(FooError { ... }) + } + + pub mod error { + /// Example error used 'directly' in the public API. + pub enum SomeError { ... }; + + /// Abstracts the details of a foo-related error. + pub struct FooError { ... }; + } +} +``` + +Then in `primitives` (and in `bitcoin`) in `lib.rs`: + +```rust +#[doc(inline)] +pub use units::{foo, FooBar}; +#[doc(no_inline)] +pub use units::foo::SomeError; +``` + +### Usage of re-exports + +As part of the attempt to mirror the `units` and `primitives`, and `bitcoin` APIs, in this codebase, +policy is to use types from the highest crate available i.e `use crate::Foo` not `units::Foo`. + +This is enforced by CI. + +## Return `Self` + +Use `Self` as the return type instead of naming the type. When constructing the return value use +`Self` or the type name, whichever you prefer. + +```rust +/// A counter that is always smaller than 100. +pub struct Counter(u32); + +impl Counter { + /// Constructs a new `Counter`. + pub fn new() -> Self { Self(0) } + + /// Returns a counter if it is possible to create one from x. + pub fn maybe(x: u32) -> Option { + match x { + x if x >= 100 => None, + c => Some(Counter(c)), + } + } +} + +impl TryFrom for Counter { + type Error = TooBigError; + + fn try_from(x: u32) -> Result { + if x >= 100 { + return Err(TooBigError); + } + Ok(Counter(x)) + } +} +``` + +When constructing the return value for error enums use `Self`. + +```rust +impl From for LongDescriptiveError { + fn from(e: foo::Error) -> Self { Self::Foo(e) } +} +``` + +## Errors + +Return as much context as possible with errors e.g., if an error was encountered parsing a string +include the string in the returned error type. If a function consumes costly-to-compute input +(allocations are also considered costly) it should return the input back in the error type. + +More specifically an error should + +- be `non_exhaustive` unless we _really_ never want to change it. +- have private fields unless we are very confident they won't change. +- derive `Debug, Clone, PartialEq, Eq` (and `Copy` if and only if not `non_exhaustive`). +- implement Display using `write_err!()` macro if a variant contains an inner error source. +- have `Error` suffix on error types (structs and enums). +- not have `Error` suffix on enum variants. +- call `internals::impl_from_infallible!`. +- implement `std::error::Error` if they are public (feature gated on "std"). +- have messages in lower case, except for proper nouns and variable names. + +```rust +/// Documentation for the `Error` type. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] // Add liberally; if the error type may ever have new variants added. +pub enum Error { + /// Documentation for variant A. + A, + /// Documentation for variant B. + B, +} + +internals::impl_from_infallible!(Error); + +``` + +All errors that live in an `error` module (eg, `foo/error.rs`) and appear in a public function in +`foo` module should be available from `foo` i.e., should be re-exported from `foo/mod.rs`. + +## `expect` messages + +With respect to `expect` messages, they should follow the +[Rust standard library guidelines](https://doc.rust-lang.org/std/option/enum.Option.html#recommended-message-style). +More specifically, `expect` messages should be used to describe the reason +you expect the operation to succeed. +For example, this `expect` message clearly states why the operation should succeed: + +```rust +/// Serializes the public key to bytes. +pub fn to_bytes(self) -> Vec { + let mut buf = Vec::new(); + self.write_into(&mut buf).expect("vecs don't error"); + buf +} +``` + +Also note that `expect` messages, as with all error messages, should be lower +case, except for proper nouns and variable names. + +
+The details on why we chose this style + +According to the [Rust standard library](https://doc.rust-lang.org/std/error/index.html#common-message-styles), +there are two common styles for how to write `expect` messages: + +- using the message to present information to users encountering a panic + ("expect as error message"); and +- using the message to present information to developers debugging the panic + ("expect as precondition"). + +We opted to use the "expect as precondition" since it clearly states why the +operation should succeed. +This may be better for communicating with developers, since they are the target +audience for the error message and `rust-bitcoin`. + +If you want to know more about the decision error messages and expect messages, +please check: + +- https://github.com/rust-bitcoin/rust-bitcoin/issues/2913 +- https://github.com/rust-bitcoin/rust-bitcoin/issues/3053 +- https://github.com/rust-bitcoin/rust-bitcoin/pull/3019 +
+ +## Rustdocs + +Be liberal with references to BIPs or other documentation; the aim is that devs can learn about +Bitcoin by hacking on this codebase as opposed to having to learn about Bitcoin first and then start +hacking on this codebase. Consider the following format, not all sections will be required for all types. + + +```rust +/// The Bitcoin foobar. +/// +/// Contains all the data used when passing a foobar around the Bitcoin network. +/// +///
+/// FooBar Original Design +/// +/// The foobar was introduced in Bitcoin x.y.z to increase the amount of foo in bar. +/// +///
+/// +/// ### Relevant BIPs +/// +/// * [BIP-XXXX - FooBar in Bitcoin](https://github.com/bitcoin/bips/blob/master/bip-xxxx.mediawiki) +pub struct FooBar { + /// The version in use. + pub version: Version +} +``` + +Do use rustdoc subheadings. Do put an empty newline below each heading e.g., + +```rust +impl FooBar { + /// Constructs a `FooBar` from a [`Baz`]. + /// + /// # Errors + /// + /// Returns an error if `Baz` is not ... + /// + /// # Panics + /// + /// If the `Baz`, converted to a `usize`, is out of bounds. + pub fn from_baz(baz: Baz) -> Result { + ... + } +} +``` + +Note usage of third person instead of imperative. + +Good: `/// Calculates the distance to the moon.` +Bad: `/// Calculate the distance to the moon.` + +Add Panics section if any input to the function can trigger a panic. + +Generally we prefer to have non-panicking APIs but it is impractical in some cases. If you're not +sure, feel free to ask. If we determine panicking is more practical it must be documented. Internal +panics that could theoretically occur because of bugs in our code must not be documented. + +Example code within the rustdocs should compile and lint with `just lint` without any errors or +warnings. + +### Links + +We favour links at the bottom of the docs section: + +```rust + /// it is a real Taproot script spend (and not some other kind of output contrived + /// to have a Taproot-shaped witness). See [BIP-0341] in particular footnote 7, for + /// more information. + /// + /// [BIP-0341]: +``` + +## Derives + +We try to use standard set of derives if it makes sense: + +``` +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum Foo { + Bar, + Baz, +} +``` + +For types that should not form a total or partial order, or that technically do but it does not +make sense to compare them, we use the `Ordered` trait from the +[`ordered`](https://crates.io/crates/ordered) crate. See `absolute::LockTime` for an example. + +For error types you likely want to use `#[derive(Debug, Clone, PartialEq, Eq)]`. + +See [Errors](#errors) section. + + +## Attributes + +- `#[track_caller]`: Used on functions that panic on invalid arguments + (see https://rustc-dev-guide.rust-lang.org/backend/implicit-caller-location.html) + +- `#[cfg(rust_v_1_60)]`: Used to guard code that should only be built in if the toolchain is + compatible. These configuration conditionals are set at build time in `bitcoin/build.rs`. New + version attributes may be added as needed. + + +## BIP References + +When referring to Bitcoin Improvement Proposals (BIPs) in documentation, comments, and error messages, use the standardized notation `BIP-XXXX` where `XXXX` is the 4-digit BIP number with leading zeros. + +### Examples + +- Correct: `BIP-0032`, `BIP-0341`, `BIP-0014` +- Incorrect: `BIP32`, `BIP 341`, `Bip14`, `bip_341` + +### Exceptions + +Module names, function names, variable names, and file names must keep their existing lowercase/underscore format. Do not rename them to match the formal BIP style: +- Module names: `bip32`, `bip152` (keep lowercase) +- Function names: `bip32_derivation`, `bip_341_tests` (keep existing format) + +## Licensing + +We use SPDX license tags, all files should start with + +``` +// SPDX-License-Identifier: CC0-1.0 +``` diff --git a/docs/primitives.md b/docs/primitives.md new file mode 100644 index 000000000..98a169dcd --- /dev/null +++ b/docs/primitives.md @@ -0,0 +1,57 @@ +# primitives 1.0.0 + +Design considerations and TODOs for the `bitcoin-primitives 1.0.0` release. + +## TODOs + +### consensus encoding + +GitHub discussion: https://github.com/rust-bitcoin/rust-bitcoin/discussions/4856 + +Pull encoding done in: https://github.com/rust-bitcoin/rust-bitcoin/pull/4912 + +### Remove `hashes` from the public API. + +Required due to [C-STABLE](https://rust-lang.github.io/api-guidelines/necessities.html#c-stable). + +Currently `hashes` shows up in the public API in all of our hash wrapper types. This can be seen by +grepping the API text files introduced in +[#4792](https://github.com/rust-bitcoin/rust-bitcoin/issues/4792) + +The wrapper types are: + +```bash +$ grep hashes api/primitives/all-features.txt | grep impl | awk '{print $NF}' + +bitcoin_primitives::block::BlockHash +bitcoin_primitives::block::WitnessCommitment +bitcoin_primitives::merkle_tree::TxMerkleNode +bitcoin_primitives::merkle_tree::WitnessMerkleNode +bitcoin_primitives::script::ScriptHash +bitcoin_primitives::script::WScriptHash +bitcoin_primitives::transaction::Ntxid +bitcoin_primitives::transaction::Txid +bitcoin_primitives::transaction::Wtxid +``` + +Using `Txid` as an example, `hashes` appears in the following places: + +```bash +$ grep hashes api/primitives/all-features.txt | grep Txid + +impl bitcoin_hashes::Hash for bitcoin_primitives::transaction::Txid +pub const fn bitcoin_primitives::transaction::Txid::as_byte_array(&self) -> &::Bytes +pub const fn bitcoin_primitives::transaction::Txid::from_byte_array(bytes: ::Bytes) -> Self +pub const fn bitcoin_primitives::transaction::Txid::to_byte_array(self) -> ::Bytes +pub type bitcoin_primitives::transaction::Txid::Bytes = ::Bytes +``` + +All these come from the `hash_newtype` macro. + +Usage of `hash_newtype` in `bitcoin` (i.e. other usage outside of `primitives`): + +- `bip158::{FilterHash, FilterHeader}` +- `bip32::XKeyIdentifier` +- `crypto::key::{PubkeyHash, WPubkeyHash}` +- `crypto::sighash::{LegacySighash, SegwitV0Sighash}` +- `taproot::{TapLeafHash, TapNodeHash, TapTweakHash}` diff --git a/docs/psbt.md b/docs/psbt.md new file mode 100644 index 000000000..6dbbf8504 --- /dev/null +++ b/docs/psbt.md @@ -0,0 +1,8 @@ +# PSBT + +We would like to enable support for PSBTv2, not necessarily add support to `rust-bitcoin`. +Potentially we want to split out the current PSBTv1 into a separate crate. The serialization logic +likely stays in `rust-bitcoin`. There are various attempts at this in flight but mostly stale. + +* Initial support in `rust-bitcoin`: [#3507](https://github.com/rust-bitcoin/rust-bitcoin/pull/3507) +* Initial PSBTV2 impl: https://github.com/tcharding/rust-psbt diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 000000000..d30afe2fa --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,28 @@ +# `rust-bitcoin` repository roadmap + +* ~Release `units v1.0.0-rc.0`~ +* Create `bitcoin-consensus-encoding` `v0.1.0` (see [#4782]) +* Release `bitcoin-consensus-encoding` `v1.0.0-rc.0` +* Release `primitives v1.0.0-rc.0` + * Implement script tagging + * Add support for consensus encoding to `primitives` +* Release `bitcoin v0.33.0-rc.0` +* Split out an address crate (see [addresses.md]) +* BIP-0032 and BIP-0380 (see [bip-32.md]) +* PSBTv2 (see [psbt.md]) +* Split out a crypto/keys crate. Includes discussion of `secp256k1`. See [crypto.md] +* Make it possible for `bitcoin` to depend on `miniscript` (see [#2882]) + - Requires [bip-32.md] and [psbt.md] +* Disentangle and stabilize Taproot stuff (see [taproot.md]) + +## RC cycle + +We want to do a long release candidate cycle to give time for downstream testing and feedback on the +API of the 1.0 crates. At a minimum this will be 6 months from the release `primitives-1.0-rc.0`. + +[addresses.md]: ./addresses.md +[bip-32.md]: ./bip-32.md +[crypto.md]: ./crypto.md +[psbt.md]: ./psbt.md +[taproot.md]: ./taproot.md +[#2882]: diff --git a/docs/supported-versions.md b/docs/supported-versions.md new file mode 100644 index 000000000..3f6c49ac0 --- /dev/null +++ b/docs/supported-versions.md @@ -0,0 +1,58 @@ +# Supported versions + +List of crates, their versions that we still actively maintain, and the dependency versions. + +## Bitcoin LTS versions + +- `v0.30` (Security and bug fixes only) +- `v0.31` (Security and bug fixes only) +- `v0.32` + +`v0.32` is the version most of the eccosystem is on. It is actively maintained. This means: + +1. Will backport anything that is easy enough if requested and if possible within semver rules. +2. May attempt more involved backport work if we deem it important enough. +3. Backport deprecations where possible as the API is developed to assist upgrade path. +4. Security and bug fixes, obviously. + +(1) includes new features developed on `master`, so contributors are welcome to contribute a new +feature with the explicit aim of then backporting it to `0.32`. + +## Dependency version map + +The LTS `bitcoin` releases and dependency versions (of crates in this repository). + +- `bitcoin 0.30` + -> `bitcoin-private 0.1` + -> `hashes 0.12` + +- `bitcoin 0.31` + -> `internals 0.2` + -> `hashes 0.13` + +- `bitcoin 0.32` + -> `base58ck 0.1` + -> `internals 0.3` + -> `io 0.1` + -> `units 0.1` + -> `hashes 0.14` + +Currently in development: + +- `bitcoin 0.33-rc.x` + -> `hashes 0.17` + -> `io 0.2` + -> `internals 0.4` + -> `primitives-1.0.0-rc.x` + -> `units-1.0.0-rc.x` + -> (transitively `consensus-encoding 1.0.0-rc.x`) + +Once the RC cycle is done: + +- `bitcoin 0.33` + -> `hashes 0.17` + -> `io 0.2` + -> `internals 0.4` + -> `primitives-1.0.0` + -> `units-1.0.0` + -> `consensus-encoding 1.0.0` diff --git a/docs/taproot.md b/docs/taproot.md new file mode 100644 index 000000000..13c845283 --- /dev/null +++ b/docs/taproot.md @@ -0,0 +1,14 @@ +# Taproot + +The `Taproot` code was left in `bitcoin` during the creation of +`primitives` because it is not as close to stable. + +Furthermore the Taproot stuff is quite entangled in various places +throughout the codebase which in turn entangles the `secp256k1` +dependency. + +We likely need to tease apart the Taproot stuff and disentangle the +bits we aren't yet willing to stabilize. Because of the entanglement +this effects various other crates (`psbt`, `crypto`) as well as the +stabilization efforts of script extension methods. + diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 000000000..572e03bdf --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ + +target +corpus +artifacts diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 000000000..4c6ee387d --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,148 @@ +[package] +name = "bitcoin-fuzz" +edition = "2021" +rust-version = "1.74.0" +version = "0.0.1" +authors = ["Generated by fuzz/generate-files.sh"] +publish = false + +[package.metadata] +cargo-fuzz = true + +[dependencies] +honggfuzz = { version = "0.5.58", default-features = false } +bitcoin = { path = "../bitcoin", features = [ "serde", "arbitrary" ] } +p2p = { path = "../p2p", package = "bitcoin-p2p-messages", features = ["arbitrary"] } +bitcoin_consensus_encoding = { path = "../consensus_encoding", package = "bitcoin-consensus-encoding" } +arbitrary = { version = "1.4.1" } + +serde = { version = "1.0.195", features = [ "derive" ] } +serde_json = "1.0.68" +standard_test = "0.1.0" + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(fuzzing)'] } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" + +[[bin]] +name = "bitcoin_arbitrary_block" +path = "fuzz_targets/bitcoin/arbitrary_block.rs" + +[[bin]] +name = "bitcoin_arbitrary_script" +path = "fuzz_targets/bitcoin/arbitrary_script.rs" + +[[bin]] +name = "bitcoin_arbitrary_transaction" +path = "fuzz_targets/bitcoin/arbitrary_transaction.rs" + +[[bin]] +name = "bitcoin_arbitrary_witness" +path = "fuzz_targets/bitcoin/arbitrary_witness.rs" + +[[bin]] +name = "bitcoin_deserialize_block" +path = "fuzz_targets/bitcoin/deserialize_block.rs" + +[[bin]] +name = "bitcoin_deserialize_prefilled_transaction" +path = "fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs" + +[[bin]] +name = "bitcoin_deserialize_psbt" +path = "fuzz_targets/bitcoin/deserialize_psbt.rs" + +[[bin]] +name = "bitcoin_deserialize_script" +path = "fuzz_targets/bitcoin/deserialize_script.rs" + +[[bin]] +name = "bitcoin_deserialize_transaction" +path = "fuzz_targets/bitcoin/deserialize_transaction.rs" + +[[bin]] +name = "bitcoin_deserialize_witness" +path = "fuzz_targets/bitcoin/deserialize_witness.rs" + +[[bin]] +name = "bitcoin_parse_address" +path = "fuzz_targets/bitcoin/parse_address.rs" + +[[bin]] +name = "bitcoin_parse_outpoint" +path = "fuzz_targets/bitcoin/parse_outpoint.rs" + +[[bin]] +name = "bitcoin_script_bytes_to_asm_fmt" +path = "fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs" + +[[bin]] +name = "consensus_encoding_decode_array" +path = "fuzz_targets/consensus_encoding/decode_array.rs" + +[[bin]] +name = "consensus_encoding_decode_byte_vec" +path = "fuzz_targets/consensus_encoding/decode_byte_vec.rs" + +[[bin]] +name = "consensus_encoding_decode_compact_size" +path = "fuzz_targets/consensus_encoding/decode_compact_size.rs" + +[[bin]] +name = "consensus_encoding_decode_decoder2" +path = "fuzz_targets/consensus_encoding/decode_decoder2.rs" + +[[bin]] +name = "hashes_json" +path = "fuzz_targets/hashes/json.rs" + +[[bin]] +name = "hashes_ripemd160" +path = "fuzz_targets/hashes/ripemd160.rs" + +[[bin]] +name = "hashes_sha1" +path = "fuzz_targets/hashes/sha1.rs" + +[[bin]] +name = "hashes_sha256" +path = "fuzz_targets/hashes/sha256.rs" + +[[bin]] +name = "hashes_sha512" +path = "fuzz_targets/hashes/sha512.rs" + +[[bin]] +name = "hashes_sha512_256" +path = "fuzz_targets/hashes/sha512_256.rs" + +[[bin]] +name = "p2p_arbitrary_addrv2" +path = "fuzz_targets/p2p/arbitrary_addrv2.rs" + +[[bin]] +name = "p2p_deserialize_addrv2" +path = "fuzz_targets/p2p/deserialize_addrv2.rs" + +[[bin]] +name = "p2p_deserialize_raw_net_msg" +path = "fuzz_targets/p2p/deserialize_raw_net_msg.rs" + +[[bin]] +name = "units_arbitrary_weight" +path = "fuzz_targets/units/arbitrary_weight.rs" + +[[bin]] +name = "units_parse_amount" +path = "fuzz_targets/units/parse_amount.rs" + +[[bin]] +name = "units_parse_int" +path = "fuzz_targets/units/parse_int.rs" + +[[bin]] +name = "units_standard_checks" +path = "fuzz_targets/units/standard_checks.rs" diff --git a/fuzz/README.md b/fuzz/README.md new file mode 100644 index 000000000..38b7d8547 --- /dev/null +++ b/fuzz/README.md @@ -0,0 +1,132 @@ +# Fuzzing + +`bitcoin` and `bitcoin_hashes` have fuzzing harnesses setup for use with +honggfuzz. + +To run the fuzz-tests as in CI -- briefly fuzzing every target -- simply +run + +```bash +./fuzz.sh +``` + +in this directory. + +To build honggfuzz, you must have libunwind on your system, as well as +libopcodes and libbfd from binutils **2.38** on your system. The most +recently-released binutils 2.39 has changed their API in a breaking way. + +On Nix, you can obtain these libraries by running + +```bash +nix-shell -p libopcodes_2_38 -p libunwind +``` + +and then run `fuzz.sh` as above. + +## Fuzzing with weak cryptography + +You may wish to replace the hashing and signing code with broken crypto, +which will be faster and enable the fuzzer to do otherwise impossible +things such as forging signatures or finding preimages to hashes. + +Doing so may result in spurious bug reports since the broken crypto does +not respect the encoding or algebraic invariants upheld by the real crypto. We +would like to improve this but it's a nontrivial problem -- though not +beyond the abilities of a motivated student with a few months of time. +Please let us know if you are interested in taking this on! + +Meanwhile, to use the broken crypto, simply compile (and run the fuzzing +scripts) with + +```bash +RUSTFLAGS="--cfg=hashes_fuzz --cfg=secp256k1_fuzz" +``` + +which will replace the hashing library with broken hashes, and the +`secp256k1` library with broken cryptography. + +Needless to say, NEVER COMPILE REAL CODE WITH THESE FLAGS because if a +fuzzer can break your crypto, so can anybody. + +## Long-term fuzzing + +To see the full list of targets, the most straightforward way is to run + +```bash +source ./fuzz-util.sh +listTargetNames +``` + +To run each of them for an hour, run + +```bash +./cycle.sh +``` + +To run a single fuzztest indefinitely, run + +```bash +HFUZZ_BUILD_ARGS='--features honggfuzz_fuzz' cargo hfuzz run +``` + +This script uses the `chrt` utility to try to reduce the priority of the +jobs. If you would like to run for longer, the most straightforward way +is to edit `cycle.sh` before starting. To run the fuzz-tests in parallel, +you will need to implement a custom harness. + +## Adding fuzz tests + +All fuzz tests can be found in the `fuzz_target/` directory. Adding a new +one is as simple as copying an existing one and editing the `do_test` +function to do what you want. + +If your test clearly belongs to a specific crate, please put it in that +crate's directory. Otherwise you can put it directly in `fuzz_target/`. + +If you need to add dependencies, edit the file `generate-files.sh` to add +it to the generated `Cargo.toml`. + +Once you've added a fuzztest, regenerate the `Cargo.toml` and CI job by +running + +```bash +./generate-files.sh +``` + +Then to test your fuzztest, run + +```bash +./fuzz.sh +``` + +If it is working, you will see a rapid stream of data for many seconds +(you can hit Ctrl+C to stop it early). If not, you should quickly see +an error. + +## Reproducing Failures + +If a fuzztest fails, it will exit with a summary which looks something like + +```text +... + fuzzTarget : hfuzz_target/x86_64-unknown-linux-gnu/release/hashes_sha256 +CRASH: +DESCRIPTION: +ORIG_FNAME: 00000000000000000000000000000000.00000000.honggfuzz.cov +FUZZ_FNAME: hfuzz_workspace/hashes_sha256/SIGABRT.PC.7ffff7c8abc7.STACK.18826d9b64.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz +... +===================================================================== +fff400610004 +``` + +The final line is a hex-encoded version of the input that caused the crash. You +can test this directly by editing the `duplicate_crash` test to copy/paste the +hex output into the call to `extend_vec_from_hex`. Then run the test with + +```bash +cargo test +``` + +Note that if you set your `RUSTFLAGS` while fuzzing (see above) you must make +sure they are set the same way when running `cargo test`. diff --git a/fuzz/cycle.sh b/fuzz/cycle.sh new file mode 100755 index 000000000..c642157d5 --- /dev/null +++ b/fuzz/cycle.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +# Continuously cycle over fuzz targets running each for 1 hour. +# It uses chrt SCHED_IDLE so that other process takes priority. +# +# For hfuzz options see https://github.com/google/honggfuzz/blob/master/docs/USAGE.md + +set -euo pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) +# can't find the file because of the ENV var +# shellcheck source=/dev/null +source "$REPO_DIR/fuzz/fuzz-util.sh" + +while : +do + for targetFile in $(listTargetFiles); do + targetName=$(targetFileToName "$targetFile") + echo "Fuzzing target $targetName ($targetFile)" + + # fuzz for one hour + HFUZZ_RUN_ARGS='--run_time 3600' chrt -i 0 cargo hfuzz run "$targetName" + # minimize the corpus + HFUZZ_RUN_ARGS="-i hfuzz_workspace/$targetName/input/ -P -M" chrt -i 0 cargo hfuzz run "$targetName" + done +done + diff --git a/fuzz/fuzz-util.sh b/fuzz/fuzz-util.sh new file mode 100755 index 000000000..df53addeb --- /dev/null +++ b/fuzz/fuzz-util.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +# Sort order is affected by locale. See `man sort`. +# > Set LC_ALL=C to get the traditional sort order that uses native byte values. +export LC_ALL=C + +REPO_DIR=$(git rev-parse --show-toplevel) + +listTargetFiles() { + pushd "$REPO_DIR/fuzz" > /dev/null || exit 1 + find fuzz_targets/ -type f -name "*.rs" | sort + popd > /dev/null || exit 1 +} + +targetFileToName() { + echo "$1" \ + | sed 's/^fuzz_targets\///' \ + | sed 's/\.rs$//' \ + | sed 's/\//_/g' \ + | sed 's/^_//g' +} + +listTargetNames() { + for target in $(listTargetFiles); do + targetFileToName "$target" + done +} + +# Utility function to avoid CI failures on Windows +checkWindowsFiles() { + incorrectFilenames=$(find . -type f -name "*,*" -o -name "*:*" -o -name "*<*" -o -name "*>*" -o -name "*|*" -o -name "*\?*" -o -name "*\**" -o -name "*\"*" | wc -l) + if [ "$incorrectFilenames" -gt 0 ]; then + echo "Bailing early because there is a Windows-incompatible filename in the tree." + exit 2 + fi +} + +# Checks whether a fuzz case outputs some report, and dumps it in hex +checkReport() { + reportFile="hfuzz_workspace/$1/HONGGFUZZ.REPORT.TXT" + if [ -f "$reportFile" ]; then + cat "$reportFile" + for CASE in "hfuzz_workspace/$1/SIG"*; do + xxd -p -c10000 < "$CASE" + done + exit 1 + fi +} diff --git a/fuzz/fuzz.sh b/fuzz/fuzz.sh new file mode 100755 index 000000000..897b29a00 --- /dev/null +++ b/fuzz/fuzz.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euox pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) + +# can't find the file because of the ENV var +# shellcheck source=/dev/null +source "$REPO_DIR/fuzz/fuzz-util.sh" + +# Check that input files are correct Windows file names +checkWindowsFiles + +if [ -z "${1:-}" ]; then + targetFiles="$(listTargetFiles)" +else + targetFiles=fuzz_targets/"$1".rs +fi + +cargo --version +rustc --version + +# Testing +cargo install --force honggfuzz --no-default-features +for targetFile in $targetFiles; do + targetName=$(targetFileToName "$targetFile") + echo "Fuzzing target $targetName ($targetFile)" + if [ -d "hfuzz_input/$targetName" ]; then + HFUZZ_INPUT_ARGS="-f hfuzz_input/$targetName/input" + else + HFUZZ_INPUT_ARGS="" + fi + HFUZZ_RUN_ARGS="--run_time 3600 --exit_upon_crash -v $HFUZZ_INPUT_ARGS" cargo hfuzz run "$targetName" + + checkReport "$targetName" +done diff --git a/fuzz/fuzz_targets/bitcoin/arbitrary_block.rs b/fuzz/fuzz_targets/bitcoin/arbitrary_block.rs new file mode 100644 index 000000000..6c66bbc61 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/arbitrary_block.rs @@ -0,0 +1,64 @@ +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::block::{self, Block, BlockCheckedExt as _}; +use bitcoin::consensus::{deserialize, serialize}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + let b = Block::arbitrary(&mut u); + + if let Ok(block) = b { + let serialized = serialize(&block); + + // Manually call all compute functions with unchecked block data. + let (header, transactions) = block.clone().into_parts(); + block::compute_merkle_root(&transactions); + // Use 32-byte zero array as witness_reserved_value per BIP-0141 requirement. + block.compute_witness_commitment(&[0u8; 32]); + block::compute_witness_root(&transactions); + + if let Ok(block) = Block::new_checked(header, transactions) { + let _ = block.bip34_block_height(); + block.block_hash(); + block.weight(); + } + + let deserialized: Result = deserialize(serialized.as_slice()); + assert_eq!(deserialized.unwrap(), block); + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/arbitrary_script.rs b/fuzz/fuzz_targets/bitcoin/arbitrary_script.rs new file mode 100644 index 000000000..4fd4dc07c --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/arbitrary_script.rs @@ -0,0 +1,84 @@ +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::address::Address; +use bitcoin::consensus::serialize; +use bitcoin::script::{self, ScriptBuf, ScriptExt as _, ScriptPubKeyExt as _}; +use bitcoin::Network; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + let s = ScriptBuf::arbitrary(&mut u); + + if let Ok(script_buf) = s { + let serialized = serialize(&script_buf); + let _: Result, script::Error> = + script_buf.instructions().collect(); + + let _ = script_buf.to_string(); + let _ = script_buf.count_sigops(); + let _ = script_buf.count_sigops_legacy(); + let _ = script_buf.minimal_non_dust(); + let _ = script_buf.minimal_non_dust_custom(u.arbitrary().expect("valid arbitrary FeeRate")); + + let mut builder = script::Builder::new(); + for instruction in script_buf.instructions_minimal() { + if instruction.is_err() { + return; + } + match instruction.ok().unwrap() { + script::Instruction::Op(op) => { + builder = builder.push_opcode(op); + } + script::Instruction::PushBytes(bytes) => { + // While we enforce the minimality rule for minimal PUSHDATA opcodes, we don't + // enforce the minimality of numbers since we don't have a script engine + // to determine if the number is getting fed into a numeric opcode, which is + // when the minimality of numbers is required. + builder = builder.push_slice_non_minimal(bytes) + } + } + } + assert_eq!(builder.into_script(), script_buf); + assert_eq!(serialized, &serialize(&script_buf)[..]); + + // Check if valid address and if that address roundtrips. + if let Ok(addr) = Address::from_script(&script_buf, Network::Bitcoin) { + assert_eq!(addr.script_pubkey(), script_buf); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/arbitrary_transaction.rs b/fuzz/fuzz_targets/bitcoin/arbitrary_transaction.rs new file mode 100644 index 000000000..be1005dfe --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/arbitrary_transaction.rs @@ -0,0 +1,67 @@ +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::consensus::{deserialize, serialize}; +use bitcoin::transaction::TransactionExt as _; +use bitcoin::Transaction; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + let t = Transaction::arbitrary(&mut u); + + if let Ok(mut tx) = t { + let serialized = serialize(&tx); + let deserialized: Result = deserialize(serialized.as_slice()); + assert_eq!(deserialized.unwrap(), tx); + + let len = serialized.len(); + let calculated_weight = tx.weight().to_wu() as usize; + for input in &mut tx.inputs { + input.witness = bitcoin::witness::Witness::default(); + } + let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len(); + // For 0-input transactions, `no_witness_len` will be incorrect because + // we serialize as SegWit even after "stripping the witnesses". We need + // to drop two bytes (i.e. eight weight). Similarly, calculated_weight is + // incorrect and needs 2 wu removing for the marker/flag bytes. + if tx.inputs.is_empty() { + assert_eq!(no_witness_len * 3 + len - 8, calculated_weight - 2); + } else { + assert_eq!(no_witness_len * 3 + len, calculated_weight); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/arbitrary_witness.rs b/fuzz/fuzz_targets/bitcoin/arbitrary_witness.rs new file mode 100644 index 000000000..f4308ed77 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/arbitrary_witness.rs @@ -0,0 +1,58 @@ +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::blockdata::witness::WitnessExt; +use bitcoin::consensus::{deserialize, serialize}; +use bitcoin::Witness; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + + if let Ok(mut witness) = Witness::arbitrary(&mut u) { + let serialized = serialize(&witness); + + let _ = witness.witness_script(); + let _ = witness.taproot_leaf_script(); + + let deserialized: Result = deserialize(serialized.as_slice()); + assert_eq!(deserialized.unwrap(), witness); + + if let Ok(element_bytes) = Vec::::arbitrary(&mut u) { + witness.push(element_bytes.as_slice()); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_block.rs b/fuzz/fuzz_targets/bitcoin/deserialize_block.rs new file mode 100644 index 000000000..c9725106f --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/deserialize_block.rs @@ -0,0 +1,48 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let block_result: Result = bitcoin::consensus::encode::deserialize(data); + + match block_result { + Err(_) => {} + Ok(block) => { + let ser = bitcoin::consensus::encode::serialize(&block); + assert_eq!(&ser[..], data); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("000700000001000000010000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs b/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs new file mode 100644 index 000000000..948f77ef8 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/deserialize_prefilled_transaction.rs @@ -0,0 +1,50 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + // We already fuzz Transactions in `./deserialize_transaction.rs`. + let tx_result: Result = + bitcoin::consensus::encode::deserialize(data); + + match tx_result { + Err(_) => {} + Ok(tx) => { + let ser = bitcoin::consensus::encode::serialize(&tx); + assert_eq!(&ser[..], data); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs b/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs new file mode 100644 index 000000000..7b36cf697 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/deserialize_psbt.rs @@ -0,0 +1,62 @@ +use bitcoin_fuzz::fuzz_utils::consume_random_bytes; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut new_data = data; + let bytes = consume_random_bytes(&mut new_data); + let psbt: Result = bitcoin::psbt::Psbt::deserialize(bytes); + match psbt { + Err(_) => {} + Ok(mut psbt) => { + let ser = bitcoin::psbt::Psbt::serialize(&psbt); + let deser = bitcoin::psbt::Psbt::deserialize(&ser).unwrap(); + // Since the fuzz data could order psbt fields differently, we compare to our deser/ser instead of data + assert_eq!(ser, bitcoin::psbt::Psbt::serialize(&deser)); + + let new_bytes = consume_random_bytes(&mut new_data); + let psbt_b: Result = + bitcoin::psbt::Psbt::deserialize(new_bytes); + match psbt_b { + Err(_) => {} + Ok(mut psbt_b) => { + assert_eq!(psbt_b.combine(psbt.clone()).is_ok(), psbt.combine(psbt_b).is_ok()); + } + } + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs new file mode 100644 index 000000000..407d03c74 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs @@ -0,0 +1,49 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let script_result: Result = + bitcoin::consensus::encode::deserialize(data); + + match script_result { + Err(_) => {} + Ok(script) => { + let ser = bitcoin::consensus::encode::serialize(&script); + assert_eq!(&ser[..], data); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs b/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs new file mode 100644 index 000000000..340b596bd --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/deserialize_transaction.rs @@ -0,0 +1,48 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let tx_result: Result = bitcoin::consensus::encode::deserialize(data); + + match tx_result { + Err(_) => {} + Ok(tx) => { + let ser = bitcoin::consensus::encode::serialize(&tx); + assert_eq!(&ser[..], data); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs b/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs new file mode 100644 index 000000000..ecc59b9e6 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/deserialize_witness.rs @@ -0,0 +1,49 @@ +use bitcoin::witness::Witness; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let witness_result: Result = bitcoin::consensus::encode::deserialize(data); + + match witness_result { + Err(_) => {} + Ok(witness) => { + let ser = bitcoin::consensus::encode::serialize(&witness); + assert_eq!(&ser[..], data); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/parse_address.rs b/fuzz/fuzz_targets/bitcoin/parse_address.rs new file mode 100644 index 000000000..c862524af --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/parse_address.rs @@ -0,0 +1,45 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let data_str = String::from_utf8_lossy(data); + let addr = match data_str.parse::>() { + Ok(addr) => addr.assume_checked(), + Err(_) => return, + }; + assert_eq!(addr.to_string(), data_str); +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/parse_outpoint.rs b/fuzz/fuzz_targets/bitcoin/parse_outpoint.rs new file mode 100644 index 000000000..8d9fffec9 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/parse_outpoint.rs @@ -0,0 +1,75 @@ +use bitcoin::consensus::encode; +use bitcoin::transaction::OutPoint; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let lowercase: Vec = data + .iter() + .map(|c| match *c { + b'A' => b'a', + b'B' => b'b', + b'C' => b'c', + b'D' => b'd', + b'E' => b'e', + b'F' => b'f', + x => x, + }) + .collect(); + let data_str = match String::from_utf8(lowercase) { + Err(_) => return, + Ok(s) => s, + }; + match data_str.parse::() { + Ok(op) => { + assert_eq!(op.to_string().as_bytes(), data_str.as_bytes()); + } + Err(_) => { + // If we can't deserialize as a string, try consensus deserializing + let res: Result = encode::deserialize(data); + if let Ok(deser) = res { + let ser = encode::serialize(&deser); + assert_eq!(ser, data); + let string = deser.to_string(); + match string.parse::() { + Ok(destring) => assert_eq!(destring, deser), + Err(_) => panic!(), + } + } + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs b/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs new file mode 100644 index 000000000..07b4d1f81 --- /dev/null +++ b/fuzz/fuzz_targets/bitcoin/script_bytes_to_asm_fmt.rs @@ -0,0 +1,53 @@ +use std::fmt::{self, Write as _}; + +use honggfuzz::fuzz; + +// faster than String, we don't need to actually produce the value, just check absence of panics +struct NullWriter; + +impl fmt::Write for NullWriter { + fn write_str(&mut self, _s: &str) -> fmt::Result { Ok(()) } + + fn write_char(&mut self, _c: char) -> fmt::Result { Ok(()) } +} + +fn do_test(data: &[u8]) { + let mut writer = NullWriter; + let script = bitcoin::WitnessScript::from_bytes(data); + write!(writer, "{script}").unwrap(); +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/consensus_encoding/decode_array.rs b/fuzz/fuzz_targets/consensus_encoding/decode_array.rs new file mode 100644 index 000000000..d99453864 --- /dev/null +++ b/fuzz/fuzz_targets/consensus_encoding/decode_array.rs @@ -0,0 +1,85 @@ +use bitcoin_consensus_encoding::{ArrayDecoder, Decoder}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + test_array_decoder::<1>(data); + test_array_decoder::<2>(data); + test_array_decoder::<4>(data); + test_array_decoder::<8>(data); + test_array_decoder::<16>(data); + test_array_decoder::<32>(data); +} + +fn test_array_decoder(data: &[u8]) { + let mut decoder = ArrayDecoder::::new(); + let mut remaining = data; + let push_result = decoder.push_bytes(&mut remaining); + + match push_result { + Err(_) => { + // Expected for invalid data or other parsing errors. + } + Ok(needs_more) => { + if needs_more { + // Decoder needs more data, but we've given it all we have + // This should result in an error when we call end(). + let end_result = decoder.end(); + assert!( + end_result.is_err(), + "decoder should error when insufficient data provided" + ); + } else { + let end_result = decoder.end(); + match end_result { + Err(_) => { + // Unexpected, but could happen due to internal state issues. + } + Ok(array) => { + // Verify the array has the expected size. + assert_eq!(array.len(), N); + // Verify the array contains the expected data from input. + if data.len() >= N { + assert_eq!(&array[..], &data[..N]); + assert_eq!(&data[N..], remaining); + } + } + } + } + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("deadbeef", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/consensus_encoding/decode_byte_vec.rs b/fuzz/fuzz_targets/consensus_encoding/decode_byte_vec.rs new file mode 100644 index 000000000..6119cbb43 --- /dev/null +++ b/fuzz/fuzz_targets/consensus_encoding/decode_byte_vec.rs @@ -0,0 +1,74 @@ +use bitcoin_consensus_encoding::{ByteVecDecoder, Decoder}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut decoder = ByteVecDecoder::new(); + let mut remaining = data; + let push_result = decoder.push_bytes(&mut remaining); + + match push_result { + Err(_) => { + // Expected for invalid data or allocation limits. + } + Ok(needs_more) => { + if needs_more { + // Decoder needs more data, but we've given it all we have + // This should result in an error when we call end(). + let end_result = decoder.end(); + assert!( + end_result.is_err(), + "decoder should error when insufficient data provided" + ); + } else { + let end_result = decoder.end(); + match end_result { + Err(_) => { + // Could happen for invalid compact size formats. + } + Ok(vec) => { + // Validate that result makes sense, can't produce more data than input and 32MB limit. + assert!(vec.len() <= data.len()); + if !vec.is_empty() { + assert!(vec.len() <= 0x02000000); + } + } + } + } + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("03010203", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/consensus_encoding/decode_compact_size.rs b/fuzz/fuzz_targets/consensus_encoding/decode_compact_size.rs new file mode 100644 index 000000000..a357fe046 --- /dev/null +++ b/fuzz/fuzz_targets/consensus_encoding/decode_compact_size.rs @@ -0,0 +1,84 @@ +use bitcoin_consensus_encoding::{CompactSizeDecoder, Decoder}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut decoder = CompactSizeDecoder::new(); + let mut remaining = data; + let push_result = decoder.push_bytes(&mut remaining); + + match push_result { + Err(_) => { + // Expected for invalid compact size encodings. + } + Ok(needs_more) => { + if needs_more { + // Decoder needs more data, but we've given it all we have + // This should result in an error when we call end(). + let end_result = decoder.end(); + assert!( + end_result.is_err(), + "decoder should error when insufficient data provided" + ); + } else { + let end_result = decoder.end(); + match end_result { + Err(_) => { + // Could happen for invalid compact size formats. + } + Ok(value) => { + // Verify the value is reasonable based on encoding size. + let consumed = data.len() - remaining.len(); + assert!((1..=9).contains(&consumed)); + + match consumed { + 1 => assert!(value < 0xFD), + 3 => assert!((0xFD..=0xFFFF).contains(&value)), + 5 => assert!((0x10000..=0xFFFFFFFF).contains(&value)), + 9 => assert!(value >= 0x100000000), + _ => panic!("invalid compact size encoding length: {}", consumed), + } + + if data.len() >= consumed { + assert_eq!(&data[consumed..], remaining); + } + } + } + } + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("fd0000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/consensus_encoding/decode_decoder2.rs b/fuzz/fuzz_targets/consensus_encoding/decode_decoder2.rs new file mode 100644 index 000000000..774b3000d --- /dev/null +++ b/fuzz/fuzz_targets/consensus_encoding/decode_decoder2.rs @@ -0,0 +1,75 @@ +use bitcoin_consensus_encoding::{ArrayDecoder, Decoder, Decoder2}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut decoder = Decoder2::new(ArrayDecoder::<2>::new(), ArrayDecoder::<3>::new()); + let mut remaining = data; + + let push_result = decoder.push_bytes(&mut remaining); + + match push_result { + Err(_) => { + // Expected for invalid data + } + Ok(needs_more) => { + if needs_more { + let end_result = decoder.end(); + assert!( + end_result.is_err(), + "decoder should error when insufficient data provided" + ); + } else { + let end_result = decoder.end(); + match end_result { + Err(_) => { + // Unexpected for array decoders with sufficient data. + } + Ok((first_array, second_array)) => { + assert_eq!(first_array.len(), 2); + assert_eq!(second_array.len(), 3); + if data.len() >= 5 { + assert_eq!(&data[5..], remaining); + assert_eq!(&first_array[..], &data[..2]); + assert_eq!(&second_array[..], &data[2..5]); + } + } + } + } + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("0102030405", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/json.rs b/fuzz/fuzz_targets/hashes/json.rs new file mode 100644 index 000000000..2513f2e2e --- /dev/null +++ b/fuzz/fuzz_targets/hashes/json.rs @@ -0,0 +1,56 @@ +use bitcoin::hashes::{ripemd160, sha1, sha256d, sha512, Hmac}; +use honggfuzz::fuzz; +use serde::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +struct Hmacs { + sha1: Hmac, + sha512: Hmac, +} + +#[derive(Deserialize, Serialize)] +struct Main { + hmacs: Hmacs, + ripemd: ripemd160::Hash, + sha2d: sha256d::Hash, +} + +fn do_test(data: &[u8]) { + if let Ok(m) = serde_json::from_slice::
(data) { + let vec = serde_json::to_vec(&m).unwrap(); + assert_eq!(data, &vec[..]); + } +} + +fn main() { + loop { + fuzz!(|d| { do_test(d) }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/ripemd160.rs b/fuzz/fuzz_targets/hashes/ripemd160.rs new file mode 100644 index 000000000..a75ec547f --- /dev/null +++ b/fuzz/fuzz_targets/hashes/ripemd160.rs @@ -0,0 +1,44 @@ +use bitcoin::hashes::{ripemd160, HashEngine}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut engine = ripemd160::Hash::engine(); + engine.input(data); + let eng_hash = ripemd160::Hash::from_engine(engine); + + let hash = ripemd160::Hash::hash(data); + assert_eq!(hash.as_byte_array(), eng_hash.as_byte_array()); +} + +fn main() { + loop { + fuzz!(|d| { do_test(d) }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/sha1.rs b/fuzz/fuzz_targets/hashes/sha1.rs new file mode 100644 index 000000000..0b9ab541c --- /dev/null +++ b/fuzz/fuzz_targets/hashes/sha1.rs @@ -0,0 +1,44 @@ +use bitcoin::hashes::{sha1, HashEngine}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut engine = sha1::Hash::engine(); + engine.input(data); + let eng_hash = sha1::Hash::from_engine(engine); + + let hash = sha1::Hash::hash(data); + assert_eq!(hash.as_byte_array(), eng_hash.as_byte_array()); +} + +fn main() { + loop { + fuzz!(|d| { do_test(d) }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/sha256.rs b/fuzz/fuzz_targets/hashes/sha256.rs new file mode 100644 index 000000000..57cb1a262 --- /dev/null +++ b/fuzz/fuzz_targets/hashes/sha256.rs @@ -0,0 +1,44 @@ +use bitcoin::hashes::{sha256, HashEngine}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut engine = sha256::Hash::engine(); + engine.input(data); + let eng_hash = sha256::Hash::from_engine(engine); + + let hash = sha256::Hash::hash(data); + assert_eq!(hash.as_byte_array(), eng_hash.as_byte_array()); +} + +fn main() { + loop { + fuzz!(|d| { do_test(d) }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("fff400610004", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/sha512.rs b/fuzz/fuzz_targets/hashes/sha512.rs new file mode 100644 index 000000000..c5cd3e5eb --- /dev/null +++ b/fuzz/fuzz_targets/hashes/sha512.rs @@ -0,0 +1,44 @@ +use bitcoin::hashes::{sha512, HashEngine}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut engine = sha512::Hash::engine(); + engine.input(data); + let eng_hash = sha512::Hash::from_engine(engine); + + let hash = sha512::Hash::hash(data); + assert_eq!(hash.as_byte_array(), eng_hash.as_byte_array()); +} + +fn main() { + loop { + fuzz!(|d| { do_test(d) }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/hashes/sha512_256.rs b/fuzz/fuzz_targets/hashes/sha512_256.rs new file mode 100644 index 000000000..60d85bec0 --- /dev/null +++ b/fuzz/fuzz_targets/hashes/sha512_256.rs @@ -0,0 +1,44 @@ +use bitcoin::hashes::{sha512_256, HashEngine}; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut engine = sha512_256::Hash::engine(); + engine.input(data); + let eng_hash = sha512_256::Hash::from_engine(engine); + + let hash = sha512_256::Hash::hash(data); + assert_eq!(hash.as_byte_array(), eng_hash.as_byte_array()); +} + +fn main() { + loop { + fuzz!(|d| { do_test(d) }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/p2p/arbitrary_addrv2.rs b/fuzz/fuzz_targets/p2p/arbitrary_addrv2.rs new file mode 100644 index 000000000..31f4fa56c --- /dev/null +++ b/fuzz/fuzz_targets/p2p/arbitrary_addrv2.rs @@ -0,0 +1,72 @@ +use std::convert::TryFrom; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + +use arbitrary::{Arbitrary, Unstructured}; +use honggfuzz::fuzz; +use p2p::address::AddrV2; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + let a = AddrV2::arbitrary(&mut u); + + if let Ok(addr_v2) = a { + if let Ok(ip_addr) = IpAddr::try_from(addr_v2.clone()) { + let round_trip: AddrV2 = AddrV2::from(ip_addr); + assert_eq!( + addr_v2, round_trip, + "AddrV2 -> IpAddr -> AddrV2 should round-trip correctly" + ); + } + + if let Ok(ip_addr) = Ipv4Addr::try_from(addr_v2.clone()) { + let round_trip: AddrV2 = AddrV2::from(ip_addr); + assert_eq!( + addr_v2, round_trip, + "AddrV2 -> Ipv4Addr -> AddrV2 should round-trip correctly" + ); + } + + if let Ok(ip_addr) = Ipv6Addr::try_from(addr_v2.clone()) { + let round_trip: AddrV2 = AddrV2::from(ip_addr); + assert_eq!( + addr_v2, round_trip, + "AddrV2 -> Ipv6Addr -> AddrV2 should round-trip correctly" + ); + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/p2p/deserialize_addrv2.rs b/fuzz/fuzz_targets/p2p/deserialize_addrv2.rs new file mode 100644 index 000000000..6f4577dcd --- /dev/null +++ b/fuzz/fuzz_targets/p2p/deserialize_addrv2.rs @@ -0,0 +1,40 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let _: Result = bitcoin::consensus::encode::deserialize(data); +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/p2p/deserialize_raw_net_msg.rs b/fuzz/fuzz_targets/p2p/deserialize_raw_net_msg.rs new file mode 100644 index 000000000..635a4a7a0 --- /dev/null +++ b/fuzz/fuzz_targets/p2p/deserialize_raw_net_msg.rs @@ -0,0 +1,41 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let _: Result = + bitcoin::consensus::encode::deserialize(data); +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/units/arbitrary_weight.rs b/fuzz/fuzz_targets/units/arbitrary_weight.rs new file mode 100644 index 000000000..93ce2d82d --- /dev/null +++ b/fuzz/fuzz_targets/units/arbitrary_weight.rs @@ -0,0 +1,87 @@ +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::Weight; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + let w = Weight::arbitrary(&mut u); + + if let Ok(weight) = w { + weight.to_wu(); + weight.to_kwu_ceil(); + weight.to_kwu_floor(); + weight.to_vbytes_ceil(); + weight.to_vbytes_floor(); + + // Operations that take u64 as the rhs + for operation in [Weight::checked_mul, Weight::checked_div] { + if let Ok(val) = u.arbitrary() { + let _ = operation(weight, val); + } else { + return; + } + } + + // Operations that take Weight as the rhs + for operation in [Weight::checked_add, Weight::checked_sub] { + if let Ok(val) = u.arbitrary() { + let _ = operation(weight, val); + } else { + return; + } + } + } + + // Constructors that return a Weight + for constructor in [Weight::from_wu] { + if let Ok(val) = u.arbitrary() { + constructor(val); + } else { + return; + } + } + + // Constructors that return an Option + for constructor in [Weight::from_vb, Weight::from_kwu] { + if let Ok(val) = u.arbitrary() { + constructor(val); + } else { + return; + } + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/units/parse_amount.rs b/fuzz/fuzz_targets/units/parse_amount.rs new file mode 100644 index 000000000..61553a3dd --- /dev/null +++ b/fuzz/fuzz_targets/units/parse_amount.rs @@ -0,0 +1,62 @@ +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let data_str = String::from_utf8_lossy(data); + + // signed + let samt = match data_str.parse::() { + Ok(amt) => amt, + Err(_) => return, + }; + let samt_roundtrip = match samt.to_string().parse::() { + Ok(amt) => amt, + Err(_) => return, + }; + assert_eq!(samt, samt_roundtrip); + + // unsigned + let amt = match data_str.parse::() { + Ok(amt) => amt, + Err(_) => return, + }; + let amt_roundtrip = match amt.to_string().parse::() { + Ok(amt) => amt, + Err(_) => return, + }; + assert_eq!(amt, amt_roundtrip); +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/units/parse_int.rs b/fuzz/fuzz_targets/units/parse_int.rs new file mode 100644 index 000000000..7d3e826f1 --- /dev/null +++ b/fuzz/fuzz_targets/units/parse_int.rs @@ -0,0 +1,106 @@ +use arbitrary::Unstructured; +use bitcoin::parse_int; +use honggfuzz::fuzz; + +fn do_test(data: &[u8]) { + let mut u = Unstructured::new(data); + + if let Ok(s) = u.arbitrary::<&str>() { + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + let _ = parse_int::int_from_str::(s); + + let _ = parse_int::hex_remove_prefix(s); + + if parse_int::hex_u32_prefixed(s).is_ok() { + assert!(parse_int::hex_u32(s).is_ok()); + assert!(parse_int::hex_u32_unprefixed(s).is_err()); + } + + if parse_int::hex_u32_unprefixed(s).is_ok() { + assert!(parse_int::hex_u32(s).is_ok()); + assert!(parse_int::hex_u32_prefixed(s).is_err()); + } + + if parse_int::hex_u128_prefixed(s).is_ok() { + assert!(parse_int::hex_u128(s).is_ok()); + assert!(parse_int::hex_u128_unprefixed(s).is_err()); + } + + if parse_int::hex_u128_unprefixed(s).is_ok() { + assert!(parse_int::hex_u128(s).is_ok()); + assert!(parse_int::hex_u128_prefixed(s).is_err()); + } + } + + if let Ok(s) = u.arbitrary::() { + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s.clone()); + let _ = parse_int::int_from_string::(s); + } + + if let Ok(s) = u.arbitrary::>() { + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s.clone()); + let _ = parse_int::int_from_box::(s); + } +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/units/standard_checks.rs b/fuzz/fuzz_targets/units/standard_checks.rs new file mode 100644 index 000000000..933ab6336 --- /dev/null +++ b/fuzz/fuzz_targets/units/standard_checks.rs @@ -0,0 +1,136 @@ +use bitcoin::{ + Amount, + BlockHeight, + BlockHeightInterval, + BlockMtp, + BlockMtpInterval, + BlockTime, + FeeRate, + Sequence, + SignedAmount, + Weight, + absolute::{ + Height, + MedianTimePast + }, + relative::{ + NumberOfBlocks, + NumberOf512Seconds + } +}; +use standard_test::StandardChecks as _; +use honggfuzz::fuzz; + +/// Implements the traits on the wrapper type $ty. Intended only to be called from inside wrap_for_checks! +macro_rules! _impl_traits_on_wrapper { + ($ty:ident$(, $default:expr)?) => { + impl<'a> arbitrary::Arbitrary<'a> for $ty { + fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { + Ok(Self(super::$ty::arbitrary(u)?)) + } + } + + impl core::ops::Deref for $ty { + type Target = super::$ty; + + fn deref(&self) -> &Self::Target { &self.0 } + } + + $( + impl Default for $ty { + fn default() -> $ty { Self($default) } + } + )? + + standard_checks!($ty); + }; +} + +/// Create a wrapper type for a foreign type so that we can use standard_checks! on it from here. +macro_rules! wrap_for_checks { + ($ty:ident) => { + #[derive(Default)] + pub(crate) struct $ty (super::$ty); + + _impl_traits_on_wrapper!($ty); + }; + ($ty:ident, $default:expr) => { + pub(crate) struct $ty (super::$ty); + + _impl_traits_on_wrapper!($ty, $default); + }; +} + + +mod fuzz { + use standard_test::standard_checks; + + wrap_for_checks!(Amount); + wrap_for_checks!(BlockHeightInterval); + wrap_for_checks!(BlockMtpInterval); + wrap_for_checks!(NumberOf512Seconds); + wrap_for_checks!(NumberOfBlocks); + wrap_for_checks!(Sequence); + wrap_for_checks!(SignedAmount); + + // Structs that need defaults + wrap_for_checks!(BlockHeight, super::BlockHeight::MIN); + wrap_for_checks!(BlockMtp, super::BlockMtp::from_u32(1_742_979_600)); // 26 Mar 2025 9:00 UTC + wrap_for_checks!(BlockTime, super::BlockTime::from(1_742_979_600)); // 26 Mar 2025 9:00 UTC + wrap_for_checks!(FeeRate, super::FeeRate::BROADCAST_MIN); + wrap_for_checks!(Height, super::Height::MIN); + wrap_for_checks!(MedianTimePast, super::MedianTimePast::MIN); + wrap_for_checks!(Weight, super::Weight::MIN_TRANSACTION); +} + +fn do_test(data: &[u8]) { + fuzz::Amount::one_iteration(data); + fuzz::BlockHeight::one_iteration(data); + fuzz::BlockHeightInterval::one_iteration(data); + fuzz::BlockMtp::one_iteration(data); + fuzz::BlockMtpInterval::one_iteration(data); + fuzz::BlockTime::one_iteration(data); + fuzz::FeeRate::one_iteration(data); + fuzz::Height::one_iteration(data); + fuzz::NumberOf512Seconds::one_iteration(data); + fuzz::NumberOfBlocks::one_iteration(data); + fuzz::MedianTimePast::one_iteration(data); + fuzz::Sequence::one_iteration(data); + fuzz::SignedAmount::one_iteration(data); + fuzz::Weight::one_iteration(data); +} + +fn main() { + loop { + fuzz!(|data| { + do_test(data); + }); + } +} + +#[cfg(all(test, fuzzing))] +mod tests { + fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + let mut b = 0; + for (idx, c) in hex.as_bytes().iter().enumerate() { + b <<= 4; + match *c { + b'A'..=b'F' => b |= c - b'A' + 10, + b'a'..=b'f' => b |= c - b'a' + 10, + b'0'..=b'9' => b |= c - b'0', + _ => panic!("Bad hex"), + } + if (idx & 1) == 1 { + out.push(b); + b = 0; + } + } + } + + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00000000", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/generate-files.sh b/fuzz/generate-files.sh new file mode 100755 index 000000000..4d4382376 --- /dev/null +++ b/fuzz/generate-files.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash + +set -euo pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) + +# can't find the file because of the ENV var +# shellcheck source=/dev/null +source "$REPO_DIR/fuzz/fuzz-util.sh" + +# 1. Generate fuzz/Cargo.toml +cat > "$REPO_DIR/fuzz/Cargo.toml" <> "$REPO_DIR/fuzz/Cargo.toml" < "$REPO_DIR/.github/workflows/cron-daily-fuzz.yml" <executed_\${{ matrix.fuzz_target }} + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: executed_\${{ matrix.fuzz_target }} + path: executed_\${{ matrix.fuzz_target }} + + verify-execution: + if: \${{ !github.event.act }} + needs: fuzz + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + - name: Display structure of downloaded files + run: ls -R + - run: find executed_* -type f -exec cat {} + | sort > executed + - run: source ./fuzz/fuzz-util.sh && listTargetNames | sort | diff - executed +EOF + diff --git a/fuzz/hfuzz_input/deserialize_address/input/18b6e222b04bbd45df9508b64b8e47d5.00000014.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/18b6e222b04bbd45df9508b64b8e47d5.00000014.honggfuzz.cov new file mode 100644 index 000000000..47522b224 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/18b6e222b04bbd45df9508b64b8e47d5.00000014.honggfuzz.cov @@ -0,0 +1 @@ +tb1218755mmmmmmlmmm9 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/2418838742eb837088ce87020b701357.0000000e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/2418838742eb837088ce87020b701357.0000000e.honggfuzz.cov new file mode 100644 index 000000000..e737eff2d --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/2418838742eb837088ce87020b701357.0000000e.honggfuzz.cov @@ -0,0 +1 @@ +tb1q1qÇtb1f§qo \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/4c268893957d293ecb031b7a493d5517.0000000b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/4c268893957d293ecb031b7a493d5517.0000000b.honggfuzz.cov new file mode 100644 index 000000000..e9f83e117 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/4c268893957d293ecb031b7a493d5517.0000000b.honggfuzz.cov @@ -0,0 +1 @@ +tb1270kt564 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/642cd2ab1075cc9dcbf11d4517132cff.0000000d.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/642cd2ab1075cc9dcbf11d4517132cff.0000000d.honggfuzz.cov new file mode 100644 index 000000000..ac4642114 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/642cd2ab1075cc9dcbf11d4517132cff.0000000d.honggfuzz.cov @@ -0,0 +1 @@ +BC1A[01z--546 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/733c9c9c9cb000002c9c9c9cc3100000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/733c9c9c9cb000002c9c9c9cc3100000.00000005.honggfuzz.cov new file mode 100644 index 000000000..313377fe1 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/733c9c9c9cb000002c9c9c9cc3100000.00000005.honggfuzz.cov @@ -0,0 +1 @@ +1111W \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/804ca76c67dac27d3fa9842a5fbf0acb.00000012.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/804ca76c67dac27d3fa9842a5fbf0acb.00000012.honggfuzz.cov new file mode 100644 index 000000000..1fde608ae --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/804ca76c67dac27d3fa9842a5fbf0acb.00000012.honggfuzz.cov @@ -0,0 +1 @@ +BC1-81003971758255 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/a4611c9c91300000211c9c9194400000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/a4611c9c91300000211c9c9194400000.00000005.honggfuzz.cov new file mode 100644 index 000000000..b11bf94e4 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/a4611c9c91300000211c9c9194400000.00000005.honggfuzz.cov @@ -0,0 +1 @@ +9119Ü \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/c7b1f1e233cb62b7663a33abe7722ab8.0000000e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/c7b1f1e233cb62b7663a33abe7722ab8.0000000e.honggfuzz.cov new file mode 100644 index 000000000..023c84a6f --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/c7b1f1e233cb62b7663a33abe7722ab8.0000000e.honggfuzz.cov @@ -0,0 +1 @@ +bc1{)2€31cc€Ù \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/dddf9577343cbfd614aa48444fdc440d.0000000b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/dddf9577343cbfd614aa48444fdc440d.0000000b.honggfuzz.cov new file mode 100644 index 000000000..f537ffc7f --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/dddf9577343cbfd614aa48444fdc440d.0000000b.honggfuzz.cov @@ -0,0 +1 @@ +BC1ß…Ò?÷~€: \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/ebdf1f0999769e0dd97c488f9e1629c3.0000000b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/ebdf1f0999769e0dd97c488f9e1629c3.0000000b.honggfuzz.cov new file mode 100644 index 000000000..71d1602cc --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/ebdf1f0999769e0dd97c488f9e1629c3.0000000b.honggfuzz.cov @@ -0,0 +1 @@ +BC1A2Qð€: \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/fea481ecdefcdebf030efcdefcc12454.00000008.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/fea481ecdefcdebf030efcdefcc12454.00000008.honggfuzz.cov new file mode 100644 index 000000000..1eef598f7 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/fea481ecdefcdebf030efcdefcc12454.00000008.honggfuzz.cov @@ -0,0 +1 @@ +BC1C1T­Ü \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000000_orig-15cad1ae8551b96348bc3115fa7ebe63.0000000e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000000_orig-15cad1ae8551b96348bc3115fa7ebe63.0000000e.honggfuzz.cov new file mode 100644 index 000000000..38eef5ea1 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000000_orig-15cad1ae8551b96348bc3115fa7ebe63.0000000e.honggfuzz.cov @@ -0,0 +1 @@ +BC10VWWW0VWWWy \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000001_orig-215f74c65c586d0f6697654f73f1590f.0000001d.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000001_orig-215f74c65c586d0f6697654f73f1590f.0000001d.honggfuzz.cov new file mode 100644 index 000000000..2eb06a846 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000001_orig-215f74c65c586d0f6697654f73f1590f.0000001d.honggfuzz.cov @@ -0,0 +1 @@ +BC1MMMMMMMMMMMMMMMMMMMMMMMMM6 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000002_orig-2cc7e6ae50991ecc4678fc57c3fec235.00000025.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000002_orig-2cc7e6ae50991ecc4678fc57c3fec235.00000025.honggfuzz.cov new file mode 100644 index 000000000..0b9b9f7de Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_address/input/id-000002_orig-2cc7e6ae50991ecc4678fc57c3fec235.00000025.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000003_orig-2ce88960000000005938fcb000000000.00000003.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000003_orig-2ce88960000000005938fcb000000000.00000003.honggfuzz.cov new file mode 100644 index 000000000..1e3b8048d --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000003_orig-2ce88960000000005938fcb000000000.00000003.honggfuzz.cov @@ -0,0 +1 @@ +bc1 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000006_orig-70b17afe56c3a7b354b7c3b6c80a2bb9.0000002b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000006_orig-70b17afe56c3a7b354b7c3b6c80a2bb9.0000002b.honggfuzz.cov new file mode 100644 index 000000000..50f90afa1 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000006_orig-70b17afe56c3a7b354b7c3b6c80a2bb9.0000002b.honggfuzz.cov @@ -0,0 +1 @@ +tb1118755mmmmmmmmmm9264mmmmmmm932772648 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000007_orig-728beb87e91000002957ebebb2a00000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000007_orig-728beb87e91000002957ebebb2a00000.00000005.honggfuzz.cov new file mode 100644 index 000000000..e3f2b85d6 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000007_orig-728beb87e91000002957ebebb2a00000.00000005.honggfuzz.cov @@ -0,0 +1 @@ +7t44V \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000008_orig-2c9c9c9cb00000002c9c9c9cb0000000.00000004.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000008_orig-2c9c9c9cb00000002c9c9c9cb0000000.00000004.honggfuzz.cov new file mode 100644 index 000000000..d1d06ad36 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000008_orig-2c9c9c9cb00000002c9c9c9cb0000000.00000004.honggfuzz.cov @@ -0,0 +1 @@ +1111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000011_orig-9c3c1fb7a5a5a5a5a60c3c7aa5a5a5a5.0000000b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000011_orig-9c3c1fb7a5a5a5a5a60c3c7aa5a5a5a5.0000000b.honggfuzz.cov new file mode 100644 index 000000000..7570bc6c8 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000011_orig-9c3c1fb7a5a5a5a5a60c3c7aa5a5a5a5.0000000b.honggfuzz.cov @@ -0,0 +1 @@ +zSSSSSSSSSS \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000013_orig-c5a6dff88d6d9cded749fcdd9d288fec.00000009.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000013_orig-c5a6dff88d6d9cded749fcdd9d288fec.00000009.honggfuzz.cov new file mode 100644 index 000000000..51b44f072 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000013_orig-c5a6dff88d6d9cded749fcdd9d288fec.00000009.honggfuzz.cov @@ -0,0 +1 @@ +BC1A063-+ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000014_orig-c609787c4d59cd6ad2d9fe413e542b60.000018a8.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000014_orig-c609787c4d59cd6ad2d9fe413e542b60.000018a8.honggfuzz.cov new file mode 100644 index 000000000..db8baf7e3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_address/input/id-000014_orig-c609787c4d59cd6ad2d9fe413e542b60.000018a8.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000016_orig-cedfa000000000005f6e800000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000016_orig-cedfa000000000005f6e800000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..453c08683 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000016_orig-cedfa000000000005f6e800000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +f˜ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000017_orig-cfe7500000000000d79f300000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000017_orig-cfe7500000000000d79f300000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..23e49af41 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000017_orig-cfe7500000000000d79f300000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +‹™ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000018_orig-e9b51c311bb9ce0d748f29409e19cbbb.0000000b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000018_orig-e9b51c311bb9ce0d748f29409e19cbbb.0000000b.honggfuzz.cov new file mode 100644 index 000000000..b4039d289 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000018_orig-e9b51c311bb9ce0d748f29409e19cbbb.0000000b.honggfuzz.cov @@ -0,0 +1 @@ +BC1A2Z4Y8J9 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000019_orig-7b300000000000007b30000000000000.00000001.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000019_orig-7b300000000000007b30000000000000.00000001.honggfuzz.cov new file mode 100644 index 000000000..24de910c1 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000019_orig-7b300000000000007b30000000000000.00000001.honggfuzz.cov @@ -0,0 +1 @@ +Y \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000019_orig-eaaab62c6d65ea2889ce9e10f05d9924.0000000f.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000019_orig-eaaab62c6d65ea2889ce9e10f05d9924.0000000f.honggfuzz.cov new file mode 100644 index 000000000..6ea20ec86 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000019_orig-eaaab62c6d65ea2889ce9e10f05d9924.0000000f.honggfuzz.cov @@ -0,0 +1 @@ +tb1p25316484708 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000021_orig-efa9a6552efcc1b41f947711ecde356c.0000000a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000021_orig-efa9a6552efcc1b41f947711ecde356c.0000000a.honggfuzz.cov new file mode 100644 index 000000000..d4b1cd947 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000021_orig-efa9a6552efcc1b41f947711ecde356c.0000000a.honggfuzz.cov @@ -0,0 +1 @@ +BCRT1C¬1¬¯ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000022_orig-cb1917e940dd2cde31ebfc9d50d957a3.00000009.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000022_orig-cb1917e940dd2cde31ebfc9d50d957a3.00000009.honggfuzz.cov new file mode 100644 index 000000000..178f2cd6c --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000022_orig-cb1917e940dd2cde31ebfc9d50d957a3.00000009.honggfuzz.cov @@ -0,0 +1 @@ +BC10m7tK! \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000025_orig-46367000000000004636700000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000025_orig-46367000000000004636700000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..9fe6dde42 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000025_orig-46367000000000004636700000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +uu \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000026_orig-2b5a40ad2cdebf606f0efc9d201a4bc0.00000007.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000026_orig-2b5a40ad2cdebf606f0efc9d201a4bc0.00000007.honggfuzz.cov new file mode 100644 index 000000000..3b87260bb --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000026_orig-2b5a40ad2cdebf606f0efc9d201a4bc0.00000007.honggfuzz.cov @@ -0,0 +1 @@ +BC108ò4 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000028_orig-2cdf11c00000000071af4cb000000000.00000003.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000028_orig-2cdf11c00000000071af4cb000000000.00000003.honggfuzz.cov new file mode 100644 index 000000000..2898eb86b --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000028_orig-2cdf11c00000000071af4cb000000000.00000003.honggfuzz.cov @@ -0,0 +1 @@ +TB1 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000028_orig-e3a0a0acdebf60006f0efc90a0638000.00000006.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000028_orig-e3a0a0acdebf60006f0efc90a0638000.00000006.honggfuzz.cov new file mode 100644 index 000000000..5447026c7 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000028_orig-e3a0a0acdebf60006f0efc90a0638000.00000006.honggfuzz.cov @@ -0,0 +1 @@ +BC188¨ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000029_orig-2ce927c00000000047994cb000000000.00000003.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000029_orig-2ce927c00000000047994cb000000000.00000003.honggfuzz.cov new file mode 100644 index 000000000..91cde8bba --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000029_orig-2ce927c00000000047994cb000000000.00000003.honggfuzz.cov @@ -0,0 +1 @@ +tb1 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000029_orig-e4299c9c9c9c9c9ce4299c9c9c9c9c9c.00000009.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000029_orig-e4299c9c9c9c9c9ce4299c9c9c9c9c9c.00000009.honggfuzz.cov new file mode 100644 index 000000000..4d7eaaf89 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000029_orig-e4299c9c9c9c9c9ce4299c9c9c9c9c9c.00000009.honggfuzz.cov @@ -0,0 +1 @@ +111111111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000030_orig-37df2d30000000004d5f57b000000000.00000003.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000030_orig-37df2d30000000004d5f57b000000000.00000003.honggfuzz.cov new file mode 100644 index 000000000..c08840a98 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000030_orig-37df2d30000000004d5f57b000000000.00000003.honggfuzz.cov @@ -0,0 +1 @@ +yB! \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000031_orig-41736041414141414173604141414141.00000019.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000031_orig-41736041414141414173604141414141.00000019.honggfuzz.cov new file mode 100644 index 000000000..7b467a2f2 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000031_orig-41736041414141414173604141414141.00000019.honggfuzz.cov @@ -0,0 +1 @@ +1111111111111111111111111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000032_orig-583f57782266bf0cf61b913df4fa7b99.00000011.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000032_orig-583f57782266bf0cf61b913df4fa7b99.00000011.honggfuzz.cov new file mode 100644 index 000000000..5d6c77dcb --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000032_orig-583f57782266bf0cf61b913df4fa7b99.00000011.honggfuzz.cov @@ -0,0 +1 @@ +BC1-7111544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000036_orig-d7796363633d2cde4deafc9d73636363.00000009.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_address/input/id-000036_orig-d7796363633d2cde4deafc9d73636363.00000009.honggfuzz.cov new file mode 100644 index 000000000..8d04c982d --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000036_orig-d7796363633d2cde4deafc9d73636363.00000009.honggfuzz.cov @@ -0,0 +1 @@ +BC10WWWW4 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000039_orig-id-000033_src-000004_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000039_orig-id-000033_src-000004_op-havoc_rep-2 new file mode 100644 index 000000000..a86b9ee04 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000039_orig-id-000033_src-000004_op-havoc_rep-2 @@ -0,0 +1 @@ +o161 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000040_orig-id-000034_src-000004_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000040_orig-id-000034_src-000004_op-havoc_rep-2 new file mode 100644 index 000000000..2cf65cf5c --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000040_orig-id-000034_src-000004_op-havoc_rep-2 @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000041_orig-id-000034_src-000004_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_address/input/id-000041_orig-id-000034_src-000004_op-havoc_rep-64 new file mode 100644 index 000000000..6a9534301 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_address/input/id-000041_orig-id-000034_src-000004_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000043_orig-id-000042_src-000004_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000043_orig-id-000042_src-000004_op-havoc_rep-2 new file mode 100644 index 000000000..9d07aa0df --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000043_orig-id-000042_src-000004_op-havoc_rep-2 @@ -0,0 +1 @@ +111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000044_orig-id-000042_src-000004_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_address/input/id-000044_orig-id-000042_src-000004_op-havoc_rep-64 new file mode 100644 index 000000000..47e8930a5 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000044_orig-id-000042_src-000004_op-havoc_rep-64 @@ -0,0 +1 @@ +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000045_orig-id-000044_src-000004_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_address/input/id-000045_orig-id-000044_src-000004_op-havoc_rep-4 new file mode 100644 index 000000000..b8471521b --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000045_orig-id-000044_src-000004_op-havoc_rep-4 @@ -0,0 +1 @@ +11YYYYYYYYYYYY1961 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000046_orig-id-000045_src-000004_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000046_orig-id-000045_src-000004_op-havoc_rep-2 new file mode 100644 index 000000000..f6de2994c --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000046_orig-id-000045_src-000004_op-havoc_rep-2 @@ -0,0 +1 @@ +1Y666161 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000046_src-000004_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000046_src-000004_op-havoc_rep-2 new file mode 100644 index 000000000..d769ca0f0 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000046_src-000004_op-havoc_rep-2 @@ -0,0 +1 @@ +11111111111111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000047_src-000004+000012_op-splice_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000047_src-000004+000012_op-splice_rep-2 new file mode 100644 index 000000000..db111c5bc --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000047_src-000004+000012_op-splice_rep-2 @@ -0,0 +1 @@ +BC1-71110837GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGWGGGG \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000058_sync-deserialize_address_0_src-000050 b/fuzz/hfuzz_input/deserialize_address/input/id-000058_sync-deserialize_address_0_src-000050 new file mode 100644 index 000000000..7153628ea --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000058_sync-deserialize_address_0_src-000050 @@ -0,0 +1 @@ +1111111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000059_sync-deserialize_address_0_src-000057 b/fuzz/hfuzz_input/deserialize_address/input/id-000059_sync-deserialize_address_0_src-000057 new file mode 100644 index 000000000..db218e2df --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000059_sync-deserialize_address_0_src-000057 @@ -0,0 +1 @@ +BC1-711154444444444444444444444444444E083dU \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000062_sync-deserialize_address_0_src-000059 b/fuzz/hfuzz_input/deserialize_address/input/id-000062_sync-deserialize_address_0_src-000059 new file mode 100644 index 000000000..e5c5a1596 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000062_sync-deserialize_address_0_src-000059 @@ -0,0 +1 @@ +BC1C1;71;711-7111544E083'1-71115111111O1111144E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000062_sync-deserialize_address_master_src-000062 b/fuzz/hfuzz_input/deserialize_address/input/id-000062_sync-deserialize_address_master_src-000062 new file mode 100644 index 000000000..43db9efb3 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000062_sync-deserialize_address_master_src-000062 @@ -0,0 +1 @@ +11111111111111111111111111111111111111111111 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000063_sync-deserialize_address_master_src-000044 b/fuzz/hfuzz_input/deserialize_address/input/id-000063_sync-deserialize_address_master_src-000044 new file mode 100644 index 000000000..a1c2f1159 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000063_sync-deserialize_address_master_src-000044 @@ -0,0 +1 @@ +11111161 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000064_sync-deserialize_address_0_src-000044 b/fuzz/hfuzz_input/deserialize_address/input/id-000064_sync-deserialize_address_0_src-000044 new file mode 100644 index 000000000..807f50e86 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000064_sync-deserialize_address_0_src-000044 @@ -0,0 +1 @@ +BC1-71115(4E0831-7111544E0837U7U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000064_sync-deserialize_address_0_src-000060 b/fuzz/hfuzz_input/deserialize_address/input/id-000064_sync-deserialize_address_0_src-000060 new file mode 100644 index 000000000..a1c58eaa0 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000064_sync-deserialize_address_0_src-000060 @@ -0,0 +1 @@ +BC1C11111111111111111111111111~~~~~~~~~~~~~~~~~1111E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000065_sync-deserialize_address_master_src-000067 b/fuzz/hfuzz_input/deserialize_address/input/id-000065_sync-deserialize_address_master_src-000067 new file mode 100644 index 000000000..b43b6c790 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000065_sync-deserialize_address_master_src-000067 @@ -0,0 +1 @@ +BC111544E083'1-711154C1;71@711-7111544E083'1-7111544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000068_src-000004_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_address/input/id-000068_src-000004_op-flip1_pos-3 new file mode 100644 index 000000000..921a12bc6 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000068_src-000004_op-flip1_pos-3 @@ -0,0 +1 @@ +tb1r70kt564 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000069_src-000004_op-flip2_pos-3 b/fuzz/hfuzz_input/deserialize_address/input/id-000069_src-000004_op-flip2_pos-3 new file mode 100644 index 000000000..04ef632c1 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000069_src-000004_op-flip2_pos-3 @@ -0,0 +1 @@ +tb1170kt564 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000069_src-000050_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_address/input/id-000069_src-000050_op-havoc_rep-8 new file mode 100644 index 000000000..dbe88ee75 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000069_src-000050_op-havoc_rep-8 @@ -0,0 +1 @@ +BC1C1;XXXXXXXXXXXXXXXXXXXXXXXXAXXX114E544E0<544E7111544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000070_src-000050_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_address/input/id-000070_src-000050_op-havoc_rep-4 new file mode 100644 index 000000000..191d1c2a4 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000070_src-000050_op-havoc_rep-4 @@ -0,0 +1 @@ +BC1C1;71;711-7111544E083'711-711154-7117'11-71115440837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000070_sync-deserialize_address_0_src-000062 b/fuzz/hfuzz_input/deserialize_address/input/id-000070_sync-deserialize_address_0_src-000062 new file mode 100644 index 000000000..17b540af3 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000070_sync-deserialize_address_0_src-000062 @@ -0,0 +1 @@ +BC11544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000071_src-000050_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000071_src-000050_op-havoc_rep-2 new file mode 100644 index 000000000..780288f64 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000071_src-000050_op-havoc_rep-2 @@ -0,0 +1 @@ +BC1C1;71;711-7111544E083'1-7111544E08377-7111544E0837UU \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000072_src-000004_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_address/input/id-000072_src-000004_op-havoc_rep-64 new file mode 100644 index 000000000..8fdd954df --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000072_src-000004_op-havoc_rep-64 @@ -0,0 +1 @@ +22 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000072_src-000051_op-flip2_pos-22 b/fuzz/hfuzz_input/deserialize_address/input/id-000072_src-000051_op-flip2_pos-22 new file mode 100644 index 000000000..360f2710e --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000072_src-000051_op-flip2_pos-22 @@ -0,0 +1 @@ +BC1-3711LLLLLLLLLLLLLL,LLLLLLLLLLLLLLLLL1544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000074_src-000004_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000074_src-000004_op-havoc_rep-2 new file mode 100644 index 000000000..788662445 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000074_src-000004_op-havoc_rep-2 @@ -0,0 +1 @@ +tb127kkkkkkkkkkkkkkkkkkkkkkkkkkkkkk0kt56 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000074_sync-deserialize_address_0_src-000064 b/fuzz/hfuzz_input/deserialize_address/input/id-000074_sync-deserialize_address_0_src-000064 new file mode 100644 index 000000000..6ff36f144 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000074_sync-deserialize_address_0_src-000064 @@ -0,0 +1 @@ +BC1C1;71;711-44E083'1-711154SA0837111544E083'1-7111544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000075_src-000004_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_address/input/id-000075_src-000004_op-havoc_rep-64 new file mode 100644 index 000000000..e53a470f2 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000075_src-000004_op-havoc_rep-64 @@ -0,0 +1 @@ +hhhhhhhhhhhhhhhhRhhhhhhhThhhhhhhhhhhhhhRhhhhhhhh \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000075_sync-deserialize_address_0_src-000049 b/fuzz/hfuzz_input/deserialize_address/input/id-000075_sync-deserialize_address_0_src-000049 new file mode 100644 index 000000000..8f1a03bae --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000075_sync-deserialize_address_0_src-000049 @@ -0,0 +1 @@ +BC1EC1-7111544E0A37+111544E0A37U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000076_src-000061_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_address/input/id-000076_src-000061_op-havoc_rep-8 new file mode 100644 index 000000000..433cfc426 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000076_src-000061_op-havoc_rep-8 @@ -0,0 +1 @@ +BC1C1;71;.11-7111544-7*1'1-7*115C17*1'1-7*115C1CA;71;1C1;71;711-711-7111514E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000077_src-000006_op-flip1_pos-30 b/fuzz/hfuzz_input/deserialize_address/input/id-000077_src-000006_op-flip1_pos-30 new file mode 100644 index 000000000..a797ed623 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000077_src-000006_op-flip1_pos-30 @@ -0,0 +1 @@ +tb1118755mmmmmmmmmm9264mmmmmmm132772648 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000077_sync-deserialize_address_0_src-000043 b/fuzz/hfuzz_input/deserialize_address/input/id-000077_sync-deserialize_address_0_src-000043 new file mode 100644 index 000000000..93a18cdd9 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000077_sync-deserialize_address_0_src-000043 @@ -0,0 +1 @@ +BC1C1;71;711-710154C1C1;71;711-4E083'1-7111544E0837U \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000080_src-000006_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000080_src-000006_op-havoc_rep-2 new file mode 100644 index 000000000..537c3b831 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_address/input/id-000080_src-000006_op-havoc_rep-2 @@ -0,0 +1 @@ +tb1118755mmmnmmmmmm9264mmb1mmmmm93277264 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000082_src-000010_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_address/input/id-000082_src-000010_op-havoc_rep-4 new file mode 100644 index 000000000..002172109 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_address/input/id-000082_src-000010_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_address/input/id-000090_src-000081_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_address/input/id-000090_src-000081_op-havoc_rep-2 new file mode 100644 index 000000000..e69de29bb diff --git a/fuzz/hfuzz_input/deserialize_block/input/26c81c03b9651108489c94e7f7d9ec83.0000187a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/26c81c03b9651108489c94e7f7d9ec83.0000187a.honggfuzz.cov new file mode 100644 index 000000000..9aa63b053 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/26c81c03b9651108489c94e7f7d9ec83.0000187a.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/82b6ca2032c4fae9f860fb7f02607f0f.0000005e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/82b6ca2032c4fae9f860fb7f02607f0f.0000005e.honggfuzz.cov new file mode 100644 index 000000000..d4228a326 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/82b6ca2032c4fae9f860fb7f02607f0f.0000005e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/e4313771686c7664845b7c29b1a259ce.00001e39.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/e4313771686c7664845b7c29b1a259ce.00001e39.honggfuzz.cov new file mode 100644 index 000000000..82b7fa536 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/e4313771686c7664845b7c29b1a259ce.00001e39.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/ea8e157df43da4453ccdb7b706da2fcd.0000012c.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/ea8e157df43da4453ccdb7b706da2fcd.0000012c.honggfuzz.cov new file mode 100644 index 000000000..bb5baad68 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/ea8e157df43da4453ccdb7b706da2fcd.0000012c.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/eaa84c843e28389940ee87aef0bf42c8.0000005e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/eaa84c843e28389940ee87aef0bf42c8.0000005e.honggfuzz.cov new file mode 100644 index 000000000..9716078cf Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/eaa84c843e28389940ee87aef0bf42c8.0000005e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000000_orig-00000000000000000000000000000000.00000014.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000000_orig-00000000000000000000000000000000.00000014.honggfuzz.cov new file mode 100644 index 000000000..df879cf49 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000000_orig-00000000000000000000000000000000.00000014.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000000_orig-0000747a210d0000e395529a00000000.0000000d.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000000_orig-0000747a210d0000e395529a00000000.0000000d.honggfuzz.cov new file mode 100644 index 000000000..cc777282f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000000_orig-0000747a210d0000e395529a00000000.0000000d.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000002_orig-30de67eb614e23eae7a8524998830ae5.0000104e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000002_orig-30de67eb614e23eae7a8524998830ae5.0000104e.honggfuzz.cov new file mode 100644 index 000000000..9339aa6bc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000002_orig-30de67eb614e23eae7a8524998830ae5.0000104e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000003_orig-3e4c1ecfa88e7688176bafdc1cdef3ac.00000068.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000003_orig-3e4c1ecfa88e7688176bafdc1cdef3ac.00000068.honggfuzz.cov new file mode 100644 index 000000000..f2d3ecfff Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000003_orig-3e4c1ecfa88e7688176bafdc1cdef3ac.00000068.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000004_orig-46ef0efd9258e206e3f01d38fab33e5d.0000049a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000004_orig-46ef0efd9258e206e3f01d38fab33e5d.0000049a.honggfuzz.cov new file mode 100644 index 000000000..920368ead Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000004_orig-46ef0efd9258e206e3f01d38fab33e5d.0000049a.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000006_orig-55c3be8d8490c27b9016b8cf573000d5.00000050.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000006_orig-55c3be8d8490c27b9016b8cf573000d5.00000050.honggfuzz.cov new file mode 100644 index 000000000..2a09bb15a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000006_orig-55c3be8d8490c27b9016b8cf573000d5.00000050.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000007_orig-58d699335b5b36233d1bdf0cedad7f63.00001175.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000007_orig-58d699335b5b36233d1bdf0cedad7f63.00001175.honggfuzz.cov new file mode 100644 index 000000000..218ad0c93 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000007_orig-58d699335b5b36233d1bdf0cedad7f63.00001175.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000007_orig-d7112b3552db4a545d8693c4b4ca38ee.00000347.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000007_orig-d7112b3552db4a545d8693c4b4ca38ee.00000347.honggfuzz.cov new file mode 100644 index 000000000..4ba8e76d6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000007_orig-d7112b3552db4a545d8693c4b4ca38ee.00000347.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000008_orig-59d7733b7ce0acb6d1a8c01a2a733c0f.000009c1.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000008_orig-59d7733b7ce0acb6d1a8c01a2a733c0f.000009c1.honggfuzz.cov new file mode 100644 index 000000000..58c62dc9d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000008_orig-59d7733b7ce0acb6d1a8c01a2a733c0f.000009c1.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000009_orig-5a049d1bda43f22cd02347f6759f8d49.00000171.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000009_orig-5a049d1bda43f22cd02347f6759f8d49.00000171.honggfuzz.cov new file mode 100644 index 000000000..ffeea9522 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000009_orig-5a049d1bda43f22cd02347f6759f8d49.00000171.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000010_orig-799478dd7f44436e43f6a2ce9dd5d500.00000280.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000010_orig-799478dd7f44436e43f6a2ce9dd5d500.00000280.honggfuzz.cov new file mode 100644 index 000000000..447993c1e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000010_orig-799478dd7f44436e43f6a2ce9dd5d500.00000280.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000012_orig-33158c5168501211b85e51eb858552d0.00000052.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000012_orig-33158c5168501211b85e51eb858552d0.00000052.honggfuzz.cov new file mode 100644 index 000000000..c97f74721 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000012_orig-33158c5168501211b85e51eb858552d0.00000052.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000013_orig-834b231ba86ecc35458b98ab40242765.00000090.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000013_orig-834b231ba86ecc35458b98ab40242765.00000090.honggfuzz.cov new file mode 100644 index 000000000..0acea8076 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000013_orig-834b231ba86ecc35458b98ab40242765.00000090.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000013_orig-92acdfa148ead2580273b028376c833f.00001118.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000013_orig-92acdfa148ead2580273b028376c833f.00001118.honggfuzz.cov new file mode 100644 index 000000000..02e82c453 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000013_orig-92acdfa148ead2580273b028376c833f.00001118.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000014_orig-8a6caa161bbf8b62f1155509f47c1925.000001c9.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000014_orig-8a6caa161bbf8b62f1155509f47c1925.000001c9.honggfuzz.cov new file mode 100644 index 000000000..6be56fcd3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000014_orig-8a6caa161bbf8b62f1155509f47c1925.000001c9.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000014_orig-b195ff73ae6af70b8dd960d5e2497074.00000051.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000014_orig-b195ff73ae6af70b8dd960d5e2497074.00000051.honggfuzz.cov new file mode 100644 index 000000000..1124ba175 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000014_orig-b195ff73ae6af70b8dd960d5e2497074.00000051.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000015_orig-9997f28c8f839e94f08803b89546af85.000003d5.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000015_orig-9997f28c8f839e94f08803b89546af85.000003d5.honggfuzz.cov new file mode 100644 index 000000000..8b99b76f0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000015_orig-9997f28c8f839e94f08803b89546af85.000003d5.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000016_orig-9fee7269e42f7a1cbc932c4b11ebe638.00000cb1.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000016_orig-9fee7269e42f7a1cbc932c4b11ebe638.00000cb1.honggfuzz.cov new file mode 100644 index 000000000..0b6600f1e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000016_orig-9fee7269e42f7a1cbc932c4b11ebe638.00000cb1.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000017_orig-a544d559857d49e138d25cf41c61568e.0000007c.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000017_orig-a544d559857d49e138d25cf41c61568e.0000007c.honggfuzz.cov new file mode 100644 index 000000000..5b2881be2 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000017_orig-a544d559857d49e138d25cf41c61568e.0000007c.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000018_orig-b01ceea7151583100c9651148b73a82d.00000483.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000018_orig-b01ceea7151583100c9651148b73a82d.00000483.honggfuzz.cov new file mode 100644 index 000000000..3b721680e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000018_orig-b01ceea7151583100c9651148b73a82d.00000483.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000018_orig-d3a15597bf83b134239874b31cc9164c.00003ffa.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000018_orig-d3a15597bf83b134239874b31cc9164c.00003ffa.honggfuzz.cov new file mode 100644 index 000000000..73f396902 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000018_orig-d3a15597bf83b134239874b31cc9164c.00003ffa.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000019_orig-b63ddcefe10c51a93b8b39474c2da11b.0000005e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000019_orig-b63ddcefe10c51a93b8b39474c2da11b.0000005e.honggfuzz.cov new file mode 100644 index 000000000..7b0ed899f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000019_orig-b63ddcefe10c51a93b8b39474c2da11b.0000005e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000020_orig-be9377d826f57b92ecccd35ed7653e78.000001c9.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000020_orig-be9377d826f57b92ecccd35ed7653e78.000001c9.honggfuzz.cov new file mode 100644 index 000000000..c40560b89 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000020_orig-be9377d826f57b92ecccd35ed7653e78.000001c9.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000022_orig-d26c7af7d0ff524953bcb2e8bc3c634e.0000191b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000022_orig-d26c7af7d0ff524953bcb2e8bc3c634e.0000191b.honggfuzz.cov new file mode 100644 index 000000000..75370b535 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000022_orig-d26c7af7d0ff524953bcb2e8bc3c634e.0000191b.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000024_orig-e7dbfe989e635dd6d2ffcc74e82004b9.00001cea.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000024_orig-e7dbfe989e635dd6d2ffcc74e82004b9.00001cea.honggfuzz.cov new file mode 100644 index 000000000..373162caf Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000024_orig-e7dbfe989e635dd6d2ffcc74e82004b9.00001cea.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000025_orig-e7e475510d47fd1b20e16d8b69a0bd06.00000051.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000025_orig-e7e475510d47fd1b20e16d8b69a0bd06.00000051.honggfuzz.cov new file mode 100644 index 000000000..0774c36b4 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000025_orig-e7e475510d47fd1b20e16d8b69a0bd06.00000051.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000027_orig-f8b26d87f49e288cd46df1ba44f91982.0000008e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000027_orig-f8b26d87f49e288cd46df1ba44f91982.0000008e.honggfuzz.cov new file mode 100644 index 000000000..fbfbeb7bb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000027_orig-f8b26d87f49e288cd46df1ba44f91982.0000008e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000028_orig-587e6b698644e3adef93f9d0d26be075.000001bc.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000028_orig-587e6b698644e3adef93f9d0d26be075.000001bc.honggfuzz.cov new file mode 100644 index 000000000..67015a1fe Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000028_orig-587e6b698644e3adef93f9d0d26be075.000001bc.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000029_orig-2f7cea00ffbe06e68c4c802bc457e84b.00000051.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000029_orig-2f7cea00ffbe06e68c4c802bc457e84b.00000051.honggfuzz.cov new file mode 100644 index 000000000..5699696e9 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000029_orig-2f7cea00ffbe06e68c4c802bc457e84b.00000051.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000030_orig-288c2c66482153a0d9aae05f1e9a69ea.0000005b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000030_orig-288c2c66482153a0d9aae05f1e9a69ea.0000005b.honggfuzz.cov new file mode 100644 index 000000000..5cf9355b1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000030_orig-288c2c66482153a0d9aae05f1e9a69ea.0000005b.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000030_orig-69f287152d5409a5671ba4a0e75e9fd2.000010b0.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000030_orig-69f287152d5409a5671ba4a0e75e9fd2.000010b0.honggfuzz.cov new file mode 100644 index 000000000..df1a19d5b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000030_orig-69f287152d5409a5671ba4a0e75e9fd2.000010b0.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000032_orig-6be09244078a2cdb4b52e2703192aa1c.00000936.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000032_orig-6be09244078a2cdb4b52e2703192aa1c.00000936.honggfuzz.cov new file mode 100644 index 000000000..36c10bb03 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000032_orig-6be09244078a2cdb4b52e2703192aa1c.00000936.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000033_orig-898de0b89c0c21032e788e06f6b9ccc6.0000049e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000033_orig-898de0b89c0c21032e788e06f6b9ccc6.0000049e.honggfuzz.cov new file mode 100644 index 000000000..babe844e2 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000033_orig-898de0b89c0c21032e788e06f6b9ccc6.0000049e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000034_orig-fb4c2bb2b57f2e8f482d6b2ca2c638ab.00000146.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000034_orig-fb4c2bb2b57f2e8f482d6b2ca2c638ab.00000146.honggfuzz.cov new file mode 100644 index 000000000..8b73c947d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000034_orig-fb4c2bb2b57f2e8f482d6b2ca2c638ab.00000146.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000036_orig-ee35e81370e627fcc08f5f4eca611c52.00004f36.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000036_orig-ee35e81370e627fcc08f5f4eca611c52.00004f36.honggfuzz.cov new file mode 100644 index 000000000..e22376871 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000036_orig-ee35e81370e627fcc08f5f4eca611c52.00004f36.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000037_orig-d8c72638fcfeed2b490ad59971eba5cb.00000089.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000037_orig-d8c72638fcfeed2b490ad59971eba5cb.00000089.honggfuzz.cov new file mode 100644 index 000000000..850d80693 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000037_orig-d8c72638fcfeed2b490ad59971eba5cb.00000089.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000039_orig-dca36c2c9dfc4aac2055199abf343c9a.0000006d.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000039_orig-dca36c2c9dfc4aac2055199abf343c9a.0000006d.honggfuzz.cov new file mode 100644 index 000000000..8f4003e87 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000039_orig-dca36c2c9dfc4aac2055199abf343c9a.0000006d.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000041_orig-4182ee40e8b9db920aa463251cc10b72.00000071.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000041_orig-4182ee40e8b9db920aa463251cc10b72.00000071.honggfuzz.cov new file mode 100644 index 000000000..f2075a143 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000041_orig-4182ee40e8b9db920aa463251cc10b72.00000071.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000042_orig-fc696eda9366e8dd2b74ee38afc9b112.00000080.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000042_orig-fc696eda9366e8dd2b74ee38afc9b112.00000080.honggfuzz.cov new file mode 100644 index 000000000..9ba81982a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000042_orig-fc696eda9366e8dd2b74ee38afc9b112.00000080.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000043_orig-21056c56ff512f3827c6e58a4798aef1.0000132e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000043_orig-21056c56ff512f3827c6e58a4798aef1.0000132e.honggfuzz.cov new file mode 100644 index 000000000..85c1db506 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000043_orig-21056c56ff512f3827c6e58a4798aef1.0000132e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000044_orig-3bb95a79c18a48d6fc2cae5619513e47.00000024.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000044_orig-3bb95a79c18a48d6fc2cae5619513e47.00000024.honggfuzz.cov new file mode 100644 index 000000000..508043816 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000044_orig-3bb95a79c18a48d6fc2cae5619513e47.00000024.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000047_orig-bbbb8044701289e467497ea8f3ace4fc.0000020a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000047_orig-bbbb8044701289e467497ea8f3ace4fc.0000020a.honggfuzz.cov new file mode 100644 index 000000000..833397680 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000047_orig-bbbb8044701289e467497ea8f3ace4fc.0000020a.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000049_orig-3f61d605dff91d3eaf012548db3e06f1.0000005a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000049_orig-3f61d605dff91d3eaf012548db3e06f1.0000005a.honggfuzz.cov new file mode 100644 index 000000000..bae158400 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000049_orig-3f61d605dff91d3eaf012548db3e06f1.0000005a.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000051_orig-739a844f27d4b10bd9a07dbdfc6860a8.0000005e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000051_orig-739a844f27d4b10bd9a07dbdfc6860a8.0000005e.honggfuzz.cov new file mode 100644 index 000000000..6087bb1d7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000051_orig-739a844f27d4b10bd9a07dbdfc6860a8.0000005e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000052_orig-e4fd180890e317061b581cf656ccdcb5.0000005b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000052_orig-e4fd180890e317061b581cf656ccdcb5.0000005b.honggfuzz.cov new file mode 100644 index 000000000..a4e864ddb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000052_orig-e4fd180890e317061b581cf656ccdcb5.0000005b.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000053_orig-e7ffc69d40729bdbf8ea9eaa0ad83f5e.00000045.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000053_orig-e7ffc69d40729bdbf8ea9eaa0ad83f5e.00000045.honggfuzz.cov new file mode 100644 index 000000000..03338d3ed Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000053_orig-e7ffc69d40729bdbf8ea9eaa0ad83f5e.00000045.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000054_orig-eaa3d259ac214000f33500515ca91269.00000009.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000054_orig-eaa3d259ac214000f33500515ca91269.00000009.honggfuzz.cov new file mode 100644 index 000000000..c8192f9a5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000054_orig-eaa3d259ac214000f33500515ca91269.00000009.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000055_orig-25eef38783e131a71c589706915e229f.0000004c.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000055_orig-25eef38783e131a71c589706915e229f.0000004c.honggfuzz.cov new file mode 100644 index 000000000..d85802828 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000055_orig-25eef38783e131a71c589706915e229f.0000004c.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000056_orig-2e488cd421b08e308e3001d40c988e60.00000007.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000056_orig-2e488cd421b08e308e3001d40c988e60.00000007.honggfuzz.cov new file mode 100644 index 000000000..988cb4efc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000056_orig-2e488cd421b08e308e3001d40c988e60.00000007.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000059_orig-eea8d9411c998c1179d61d182d7ee35f.0000132e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000059_orig-eea8d9411c998c1179d61d182d7ee35f.0000132e.honggfuzz.cov new file mode 100644 index 000000000..af4147a91 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000059_orig-eea8d9411c998c1179d61d182d7ee35f.0000132e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000060_orig-4f40ec4f600000006fdc801fe0000000.00000004.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000060_orig-4f40ec4f600000006fdc801fe0000000.00000004.honggfuzz.cov new file mode 100644 index 000000000..367a0b303 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_block/input/id-000060_orig-4f40ec4f600000006fdc801fe0000000.00000004.honggfuzz.cov @@ -0,0 +1 @@ +BÎÛz \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000071_orig-id-000107_src-000105_op-flip1_pos-435 b/fuzz/hfuzz_input/deserialize_block/input/id-000071_orig-id-000107_src-000105_op-flip1_pos-435 new file mode 100644 index 000000000..1380b8f7e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000071_orig-id-000107_src-000105_op-flip1_pos-435 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000073_orig-id-000112_src-000012_op-flip1_pos-1599 b/fuzz/hfuzz_input/deserialize_block/input/id-000073_orig-id-000112_src-000012_op-flip1_pos-1599 new file mode 100644 index 000000000..5916b2506 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000073_orig-id-000112_src-000012_op-flip1_pos-1599 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000076_orig-fd80063f8fa2254c3ea9ef2a9d29a71e.00000048.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/id-000076_orig-fd80063f8fa2254c3ea9ef2a9d29a71e.00000048.honggfuzz.cov new file mode 100644 index 000000000..a52c68845 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000076_orig-fd80063f8fa2254c3ea9ef2a9d29a71e.00000048.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000076_orig-id-000115_src-000101_op-arith8_pos-1139_val--19 b/fuzz/hfuzz_input/deserialize_block/input/id-000076_orig-id-000115_src-000101_op-arith8_pos-1139_val--19 new file mode 100644 index 000000000..7b04e457b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000076_orig-id-000115_src-000101_op-arith8_pos-1139_val--19 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000081_src-000003_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_block/input/id-000081_src-000003_op-havoc_rep-64 new file mode 100644 index 000000000..cc6d95ba5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000081_src-000003_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000082_src-000003_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_block/input/id-000082_src-000003_op-havoc_rep-8 new file mode 100644 index 000000000..814767037 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000082_src-000003_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000083_src-000003_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_block/input/id-000083_src-000003_op-havoc_rep-32 new file mode 100644 index 000000000..fd3f95de7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000083_src-000003_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000087_orig-id-000101_src-000005_op-int16_pos-97_val-+1024 b/fuzz/hfuzz_input/deserialize_block/input/id-000087_orig-id-000101_src-000005_op-int16_pos-97_val-+1024 new file mode 100644 index 000000000..810293676 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000087_orig-id-000101_src-000005_op-int16_pos-97_val-+1024 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000095_orig-tx_id-000095_src-000000+000033_op-splice_rep-128 b/fuzz/hfuzz_input/deserialize_block/input/id-000095_orig-tx_id-000095_src-000000+000033_op-splice_rep-128 new file mode 100644 index 000000000..07c1df4d0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000095_orig-tx_id-000095_src-000000+000033_op-splice_rep-128 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000096_orig-id-000157_src-000113_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_block/input/id-000096_orig-id-000157_src-000113_op-havoc_rep-32 new file mode 100644 index 000000000..fc9a72bba Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000096_orig-id-000157_src-000113_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000096_orig-tx_id-000097_src-000000+000010_op-splice_rep-64 b/fuzz/hfuzz_input/deserialize_block/input/id-000096_orig-tx_id-000097_src-000000+000010_op-splice_rep-64 new file mode 100644 index 000000000..872a5a8ae Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000096_orig-tx_id-000097_src-000000+000010_op-splice_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000097_src-000005_op-arith8_pos-3343_val--22 b/fuzz/hfuzz_input/deserialize_block/input/id-000097_src-000005_op-arith8_pos-3343_val--22 new file mode 100644 index 000000000..28082c430 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000097_src-000005_op-arith8_pos-3343_val--22 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000098_orig-tx_id-000166_sync-deserialize_transaction_master_src-000136 b/fuzz/hfuzz_input/deserialize_block/input/id-000098_orig-tx_id-000166_sync-deserialize_transaction_master_src-000136 new file mode 100644 index 000000000..5dc1e7002 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000098_orig-tx_id-000166_sync-deserialize_transaction_master_src-000136 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000098_src-000021_op-flip1_pos-3143 b/fuzz/hfuzz_input/deserialize_block/input/id-000098_src-000021_op-flip1_pos-3143 new file mode 100644 index 000000000..8e1b68455 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000098_src-000021_op-flip1_pos-3143 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000101_orig-tx_id-000188_sync-deserialize_transaction_master_src-000172 b/fuzz/hfuzz_input/deserialize_block/input/id-000101_orig-tx_id-000188_sync-deserialize_transaction_master_src-000172 new file mode 100644 index 000000000..8063b047d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000101_orig-tx_id-000188_sync-deserialize_transaction_master_src-000172 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000102_orig-tx_id-000190_sync-deserialize_transaction_master_src-000171 b/fuzz/hfuzz_input/deserialize_block/input/id-000102_orig-tx_id-000190_sync-deserialize_transaction_master_src-000171 new file mode 100644 index 000000000..d98b88ca0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000102_orig-tx_id-000190_sync-deserialize_transaction_master_src-000171 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000104_src-000005_op-int32_pos-3524_val-+16 b/fuzz/hfuzz_input/deserialize_block/input/id-000104_src-000005_op-int32_pos-3524_val-+16 new file mode 100644 index 000000000..3c9c4fcd8 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000104_src-000005_op-int32_pos-3524_val-+16 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000105_src-000008_op-flip1_pos-1160 b/fuzz/hfuzz_input/deserialize_block/input/id-000105_src-000008_op-flip1_pos-1160 new file mode 100644 index 000000000..9e97236af Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000105_src-000008_op-flip1_pos-1160 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000106_orig-tx_id-000202_src-000173_op-arith8_pos-178_val--2 b/fuzz/hfuzz_input/deserialize_block/input/id-000106_orig-tx_id-000202_src-000173_op-arith8_pos-178_val--2 new file mode 100644 index 000000000..7abd725e6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000106_orig-tx_id-000202_src-000173_op-arith8_pos-178_val--2 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000108_orig-tx_id-000223_sync-deserialize_transaction_2_src-000214 b/fuzz/hfuzz_input/deserialize_block/input/id-000108_orig-tx_id-000223_sync-deserialize_transaction_2_src-000214 new file mode 100644 index 000000000..89c231b40 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000108_orig-tx_id-000223_sync-deserialize_transaction_2_src-000214 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000110_src-000002_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_block/input/id-000110_src-000002_op-havoc_rep-4 new file mode 100644 index 000000000..1372e581b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000110_src-000002_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000111_src-000002_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_block/input/id-000111_src-000002_op-havoc_rep-32 new file mode 100644 index 000000000..ad161e278 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000111_src-000002_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000113_src-000002_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_block/input/id-000113_src-000002_op-havoc_rep-16 new file mode 100644 index 000000000..067e7a40f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000113_src-000002_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000113_sync-deserialize_block_2_src-000112 b/fuzz/hfuzz_input/deserialize_block/input/id-000113_sync-deserialize_block_2_src-000112 new file mode 100644 index 000000000..281ae3a11 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000113_sync-deserialize_block_2_src-000112 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000114_src-000005_op-flip4_pos-263 b/fuzz/hfuzz_input/deserialize_block/input/id-000114_src-000005_op-flip4_pos-263 new file mode 100644 index 000000000..4a4eba116 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000114_src-000005_op-flip4_pos-263 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000116_src-000031+000101_op-splice_rep-16 b/fuzz/hfuzz_input/deserialize_block/input/id-000116_src-000031+000101_op-splice_rep-16 new file mode 100644 index 000000000..bde24285f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000116_src-000031+000101_op-splice_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000116_src-000059_op-flip1_pos-157 b/fuzz/hfuzz_input/deserialize_block/input/id-000116_src-000059_op-flip1_pos-157 new file mode 100644 index 000000000..c0b0d9ba0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000116_src-000059_op-flip1_pos-157 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000117_src-000059_op-flip4_pos-157 b/fuzz/hfuzz_input/deserialize_block/input/id-000117_src-000059_op-flip4_pos-157 new file mode 100644 index 000000000..eecb7ee5f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000117_src-000059_op-flip4_pos-157 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000118_src-000018_op-flip1_pos-134 b/fuzz/hfuzz_input/deserialize_block/input/id-000118_src-000018_op-flip1_pos-134 new file mode 100644 index 000000000..dc0f08083 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000118_src-000018_op-flip1_pos-134 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000119_src-000082_op-flip1_pos-443 b/fuzz/hfuzz_input/deserialize_block/input/id-000119_src-000082_op-flip1_pos-443 new file mode 100644 index 000000000..e2e1946c3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000119_src-000082_op-flip1_pos-443 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000120_src-000029_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_block/input/id-000120_src-000029_op-havoc_rep-64 new file mode 100644 index 000000000..4e303edb4 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000120_src-000029_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000121_src-000077_op-arith8_pos-7636_val--18 b/fuzz/hfuzz_input/deserialize_block/input/id-000121_src-000077_op-arith8_pos-7636_val--18 new file mode 100644 index 000000000..c1cc2047e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000121_src-000077_op-arith8_pos-7636_val--18 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000121_src-000115_op-int16_pos-24501_val-+256 b/fuzz/hfuzz_input/deserialize_block/input/id-000121_src-000115_op-int16_pos-24501_val-+256 new file mode 100644 index 000000000..3034e6ec2 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000121_src-000115_op-int16_pos-24501_val-+256 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000122_src-000064_op-arith8_pos-95_val--2 b/fuzz/hfuzz_input/deserialize_block/input/id-000122_src-000064_op-arith8_pos-95_val--2 new file mode 100644 index 000000000..7cc1fe2d7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000122_src-000064_op-arith8_pos-95_val--2 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000124_src-000118_op-int16_pos-2599_val-+256 b/fuzz/hfuzz_input/deserialize_block/input/id-000124_src-000118_op-int16_pos-2599_val-+256 new file mode 100644 index 000000000..bcc4a9ad5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000124_src-000118_op-int16_pos-2599_val-+256 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000125_src-000080_op-flip2_pos-411 b/fuzz/hfuzz_input/deserialize_block/input/id-000125_src-000080_op-flip2_pos-411 new file mode 100644 index 000000000..4619c1201 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000125_src-000080_op-flip2_pos-411 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000126_src-000018+000077_op-splice_rep-8 b/fuzz/hfuzz_input/deserialize_block/input/id-000126_src-000018+000077_op-splice_rep-8 new file mode 100644 index 000000000..daa1bd75d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000126_src-000018+000077_op-splice_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000126_src-000085_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_block/input/id-000126_src-000085_op-havoc_rep-8 new file mode 100644 index 000000000..f8bd62071 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000126_src-000085_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000128_src-000108_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_block/input/id-000128_src-000108_op-havoc_rep-32 new file mode 100644 index 000000000..681438cd5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000128_src-000108_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000129_src-000128_op-flip1_pos-1977 b/fuzz/hfuzz_input/deserialize_block/input/id-000129_src-000128_op-flip1_pos-1977 new file mode 100644 index 000000000..d91e8a5aa Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000129_src-000128_op-flip1_pos-1977 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000132_src-000131_op-flip1_pos-7872 b/fuzz/hfuzz_input/deserialize_block/input/id-000132_src-000131_op-flip1_pos-7872 new file mode 100644 index 000000000..4d42c5b36 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000132_src-000131_op-flip1_pos-7872 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000134_src-000005+000128_op-splice_rep-4 b/fuzz/hfuzz_input/deserialize_block/input/id-000134_src-000005+000128_op-splice_rep-4 new file mode 100644 index 000000000..cd4c3ce43 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000134_src-000005+000128_op-splice_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000135_src-000134_op-flip8_pos-972 b/fuzz/hfuzz_input/deserialize_block/input/id-000135_src-000134_op-flip8_pos-972 new file mode 100644 index 000000000..7331dea6f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000135_src-000134_op-flip8_pos-972 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000136_src-000134_op-arith8_pos-972_val--2 b/fuzz/hfuzz_input/deserialize_block/input/id-000136_src-000134_op-arith8_pos-972_val--2 new file mode 100644 index 000000000..9585fcb5f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000136_src-000134_op-arith8_pos-972_val--2 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000137_src-000035+000128_op-splice_rep-4 b/fuzz/hfuzz_input/deserialize_block/input/id-000137_src-000035+000128_op-splice_rep-4 new file mode 100644 index 000000000..0057a42ea Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000137_src-000035+000128_op-splice_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000155_src-000087_op-flip2_pos-126 b/fuzz/hfuzz_input/deserialize_block/input/id-000155_src-000087_op-flip2_pos-126 new file mode 100644 index 000000000..e69de29bb diff --git a/fuzz/hfuzz_input/deserialize_block/input/id-000159_src-000113_op-havoc_rep-128 b/fuzz/hfuzz_input/deserialize_block/input/id-000159_src-000113_op-havoc_rep-128 new file mode 100644 index 000000000..55fb2c19a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/id-000159_src-000113_op-havoc_rep-128 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000008_orig-363987a6ffb736444cc2a3b45a01b0c1.000000aa.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000008_orig-363987a6ffb736444cc2a3b45a01b0c1.000000aa.honggfuzz.cov new file mode 100644 index 000000000..45d515004 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000008_orig-363987a6ffb736444cc2a3b45a01b0c1.000000aa.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000009_orig-8530f6c85f51e01782b6e9d970a22f7f.000013b1.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000009_orig-8530f6c85f51e01782b6e9d970a22f7f.000013b1.honggfuzz.cov new file mode 100644 index 000000000..55bf2297c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000009_orig-8530f6c85f51e01782b6e9d970a22f7f.000013b1.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000015_orig-a7114a6c122f99cbbed5448562b7a513.000000aa.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000015_orig-a7114a6c122f99cbbed5448562b7a513.000000aa.honggfuzz.cov new file mode 100644 index 000000000..ab1dbfc67 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000015_orig-a7114a6c122f99cbbed5448562b7a513.000000aa.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000016_orig-003baefb49000000999bfe5b80000000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000016_orig-003baefb49000000999bfe5b80000000.00000005.honggfuzz.cov new file mode 100644 index 000000000..ca69ca1cc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000016_orig-003baefb49000000999bfe5b80000000.00000005.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000076_src-000000_op-havoc_rep-128 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000076_src-000000_op-havoc_rep-128 new file mode 100644 index 000000000..3ef74f4dc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000076_src-000000_op-havoc_rep-128 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000077_src-000000_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000077_src-000000_op-havoc_rep-64 new file mode 100644 index 000000000..148689323 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000077_src-000000_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000080_src-000000_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000080_src-000000_op-havoc_rep-32 new file mode 100644 index 000000000..929601766 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000080_src-000000_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000084_src-000000+000044_op-splice_rep-8 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000084_src-000000+000044_op-splice_rep-8 new file mode 100644 index 000000000..f6493451d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000084_src-000000+000044_op-splice_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000121_src-000000+000033_op-splice_rep-8 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000121_src-000000+000033_op-splice_rep-8 new file mode 100644 index 000000000..67510b933 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000121_src-000000+000033_op-splice_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000176_sync-deserialize_transaction_2_src-000163 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000176_sync-deserialize_transaction_2_src-000163 new file mode 100644 index 000000000..8470d35d3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000176_sync-deserialize_transaction_2_src-000163 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000176_sync-deserialize_transaction_master_src-000128 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000176_sync-deserialize_transaction_master_src-000128 new file mode 100644 index 000000000..3c3ae9f9b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000176_sync-deserialize_transaction_master_src-000128 differ diff --git a/fuzz/hfuzz_input/deserialize_block/input/tx_id-000202_sync-deserialize_transaction_master_src-000162 b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000202_sync-deserialize_transaction_master_src-000162 new file mode 100644 index 000000000..904c365fe Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_block/input/tx_id-000202_sync-deserialize_transaction_master_src-000162 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/8958f2684d1268b44ba177926907375c.00001102.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/8958f2684d1268b44ba177926907375c.00001102.honggfuzz.cov new file mode 100644 index 000000000..893679a03 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/8958f2684d1268b44ba177926907375c.00001102.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/b1d2a3debe7a2e7c4c6a3c36c0233963.00000096.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/b1d2a3debe7a2e7c4c6a3c36c0233963.00000096.honggfuzz.cov new file mode 100644 index 000000000..15ee84406 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/b1d2a3debe7a2e7c4c6a3c36c0233963.00000096.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/c9d1399a00c0eed06ceb68cac5f8cf8f.00000067.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/c9d1399a00c0eed06ceb68cac5f8cf8f.00000067.honggfuzz.cov new file mode 100644 index 000000000..021d7edee Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/c9d1399a00c0eed06ceb68cac5f8cf8f.00000067.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/dc2ac020c3f058e2e5809bbfae424566.00000a1f.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/dc2ac020c3f058e2e5809bbfae424566.00000a1f.honggfuzz.cov new file mode 100644 index 000000000..e55c4cd2d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/dc2ac020c3f058e2e5809bbfae424566.00000a1f.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/df690781d9f3e503665a2b0af684b9d0.00001102.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/df690781d9f3e503665a2b0af684b9d0.00001102.honggfuzz.cov new file mode 100644 index 000000000..abc563edc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/df690781d9f3e503665a2b0af684b9d0.00001102.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/e1482fe1b587e0b695d0087a84fb020c.000010c3.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/e1482fe1b587e0b695d0087a84fb020c.000010c3.honggfuzz.cov new file mode 100644 index 000000000..c2451529c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/e1482fe1b587e0b695d0087a84fb020c.000010c3.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/e543b8016347700007a3416803854000.00000006.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/e543b8016347700007a3416803854000.00000006.honggfuzz.cov new file mode 100644 index 000000000..cdc39efcb --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/e543b8016347700007a3416803854000.00000006.honggfuzz.cov @@ -0,0 +1 @@ +Œ€¬ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000009_orig-02bc0dcc52d8198fdf1e3fd228c1f412.00000096.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000009_orig-02bc0dcc52d8198fdf1e3fd228c1f412.00000096.honggfuzz.cov new file mode 100644 index 000000000..fc9958e7d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000009_orig-02bc0dcc52d8198fdf1e3fd228c1f412.00000096.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000018_orig-6421b0000000000001d4200000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000018_orig-6421b0000000000001d4200000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..dc0456f65 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000018_orig-6421b0000000000001d4200000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +N \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000020_orig-6591b0000000000001d5900000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000020_orig-6591b0000000000001d5900000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..dda2a32f4 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000020_orig-6591b0000000000001d5900000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +O \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000021_orig-66f1b0000000000001d6f00000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000021_orig-66f1b0000000000001d6f00000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..3f2cac2bc --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000021_orig-66f1b0000000000001d6f00000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +M \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000022_orig-6741b0000000000001d7400000000000.00000002.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000022_orig-6741b0000000000001d7400000000000.00000002.honggfuzz.cov new file mode 100644 index 000000000..2171a7495 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000022_orig-6741b0000000000001d7400000000000.00000002.honggfuzz.cov @@ -0,0 +1 @@ +L \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000023_orig-694551f1b1b770000771b1a11529a000.00000006.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000023_orig-694551f1b1b770000771b1a11529a000.00000006.honggfuzz.cov new file mode 100644 index 000000000..6be1741c3 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000023_orig-694551f1b1b770000771b1a11529a000.00000006.honggfuzz.cov @@ -0,0 +1 @@ +¬F \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000035_orig-adf692b94a4f7a7231ceeda52eee8351.00002000.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000035_orig-adf692b94a4f7a7231ceeda52eee8351.00002000.honggfuzz.cov new file mode 100644 index 000000000..1de2f7a73 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000035_orig-adf692b94a4f7a7231ceeda52eee8351.00002000.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000041_orig-dc3e82e673cab9a788ad4e0c6739dcf3.000003d0.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000041_orig-dc3e82e673cab9a788ad4e0c6739dcf3.000003d0.honggfuzz.cov new file mode 100644 index 000000000..295703152 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000041_orig-dc3e82e673cab9a788ad4e0c6739dcf3.000003d0.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000042_orig-dd15d52ef0000808403307a6e07bf584.0000084d.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000042_orig-dd15d52ef0000808403307a6e07bf584.0000084d.honggfuzz.cov new file mode 100644 index 000000000..3125d7117 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000042_orig-dd15d52ef0000808403307a6e07bf584.0000084d.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000050_orig-9160b19ef1200000910e61f021200000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000050_orig-9160b19ef1200000910e61f021200000.00000005.honggfuzz.cov new file mode 100644 index 000000000..7e0506df5 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000050_orig-9160b19ef1200000910e61f021200000.00000005.honggfuzz.cov @@ -0,0 +1 @@ +þ2qþ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000051_orig-00000000000000000000000000000000.00000001.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000051_orig-00000000000000000000000000000000.00000001.honggfuzz.cov new file mode 100644 index 000000000..f76dd238a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000051_orig-00000000000000000000000000000000.00000001.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000052_orig-00b125700000000085c1a00000000000.00000003.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000052_orig-00b125700000000085c1a00000000000.00000003.honggfuzz.cov new file mode 100644 index 000000000..88a97b1bf Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000052_orig-00b125700000000085c1a00000000000.00000003.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000053_orig-90900000000000009090000000000000.00000001.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000053_orig-90900000000000009090000000000000.00000001.honggfuzz.cov new file mode 100644 index 000000000..ce542efaa --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000053_orig-90900000000000009090000000000000.00000001.honggfuzz.cov @@ -0,0 +1 @@ +ÿ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000054_orig-91200000000000009120000000000000.00000001.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000054_orig-91200000000000009120000000000000.00000001.honggfuzz.cov new file mode 100644 index 000000000..050ac90ec --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000054_orig-91200000000000009120000000000000.00000001.honggfuzz.cov @@ -0,0 +1 @@ +þ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000055_orig-93f000000000000093f0000000000000.00000001.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000055_orig-93f000000000000093f0000000000000.00000001.honggfuzz.cov new file mode 100644 index 000000000..39e8d6602 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000055_orig-93f000000000000093f0000000000000.00000001.honggfuzz.cov @@ -0,0 +1 @@ +ý \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000056_orig-b518ccc0e0000000e05c88c5b0000000.00000004.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_script/input/id-000056_orig-b518ccc0e0000000e05c88c5b0000000.00000004.honggfuzz.cov new file mode 100644 index 000000000..322cd7d9d --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000056_orig-b518ccc0e0000000e05c88c5b0000000.00000004.honggfuzz.cov @@ -0,0 +1 @@ +ªÎÕÁ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000057_orig-id-000016_src-000000_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_script/input/id-000057_orig-id-000016_src-000000_op-havoc_rep-32 new file mode 100644 index 000000000..9d022ae46 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000057_orig-id-000016_src-000000_op-havoc_rep-32 @@ -0,0 +1 @@ +¹¹¹ÉÄ›À¹@¹¹¹Ó¹¹¹¹¹¹ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000058_orig-id-000026_src-000011_op-int16_pos-2_val-+0 b/fuzz/hfuzz_input/deserialize_script/input/id-000058_orig-id-000026_src-000011_op-int16_pos-2_val-+0 new file mode 100644 index 000000000..9380fb482 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000058_orig-id-000026_src-000011_op-int16_pos-2_val-+0 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000065_src-000000_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000065_src-000000_op-havoc_rep-2 new file mode 100644 index 000000000..0f57f0b0f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000065_src-000000_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000066_src-000000_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000066_src-000000_op-havoc_rep-4 new file mode 100644 index 000000000..a236d0767 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000066_src-000000_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000067_src-000000_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_script/input/id-000067_src-000000_op-havoc_rep-64 new file mode 100644 index 000000000..dcfc20cce --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000067_src-000000_op-havoc_rep-64 @@ -0,0 +1 @@ +*³³³³³³³³³³³³³³³³³³³³³³³³³ZZZ³³³³³³³³³³³ZZ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000068_src-000000_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000068_src-000000_op-havoc_rep-4 new file mode 100644 index 000000000..f4bba8218 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000068_src-000000_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000072_src-000001_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000072_src-000001_op-havoc_rep-2 new file mode 100644 index 000000000..0aa43d6d7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000072_src-000001_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000073_src-000002_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000073_src-000002_op-havoc_rep-8 new file mode 100644 index 000000000..b8bf64e36 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000073_src-000002_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000075_src-000004_op-flip4_pos-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000075_src-000004_op-flip4_pos-4 new file mode 100644 index 000000000..b2ed8d48e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000075_src-000004_op-flip4_pos-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000076_src-000007_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000076_src-000007_op-havoc_rep-4 new file mode 100644 index 000000000..8e069f466 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000076_src-000007_op-havoc_rep-4 @@ -0,0 +1 @@ +ƒƒ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000079_src-000009_op-arith8_pos-65_val--34 b/fuzz/hfuzz_input/deserialize_script/input/id-000079_src-000009_op-arith8_pos-65_val--34 new file mode 100644 index 000000000..c2bff35dc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000079_src-000009_op-arith8_pos-65_val--34 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000081_src-000009_op-int16_pos-65_val-be-+100 b/fuzz/hfuzz_input/deserialize_script/input/id-000081_src-000009_op-int16_pos-65_val-be-+100 new file mode 100644 index 000000000..440181f0c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000081_src-000009_op-int16_pos-65_val-be-+100 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000084_src-000009_op-int32_pos-1_val-be-+1 b/fuzz/hfuzz_input/deserialize_script/input/id-000084_src-000009_op-int32_pos-1_val-be-+1 new file mode 100644 index 000000000..50f308781 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000084_src-000009_op-int32_pos-1_val-be-+1 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000085_src-000009_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000085_src-000009_op-havoc_rep-8 new file mode 100644 index 000000000..bdaba2fe9 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000085_src-000009_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000087_src-000011_op-flip2_pos-5 b/fuzz/hfuzz_input/deserialize_script/input/id-000087_src-000011_op-flip2_pos-5 new file mode 100644 index 000000000..47fdf9612 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000087_src-000011_op-flip2_pos-5 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000088_src-000011_op-flip2_pos-6 b/fuzz/hfuzz_input/deserialize_script/input/id-000088_src-000011_op-flip2_pos-6 new file mode 100644 index 000000000..540032347 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000088_src-000011_op-flip2_pos-6 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000094_src-000011_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000094_src-000011_op-havoc_rep-2 new file mode 100644 index 000000000..ced12c21a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000094_src-000011_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000095_src-000011_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000095_src-000011_op-havoc_rep-2 new file mode 100644 index 000000000..16b5133ec Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000095_src-000011_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000097_src-000013_op-flip1_pos-1 b/fuzz/hfuzz_input/deserialize_script/input/id-000097_src-000013_op-flip1_pos-1 new file mode 100644 index 000000000..ea237a6d8 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000097_src-000013_op-flip1_pos-1 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000102_src-000013_op-flip1_pos-1791 b/fuzz/hfuzz_input/deserialize_script/input/id-000102_src-000013_op-flip1_pos-1791 new file mode 100644 index 000000000..9b7a7c172 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000102_src-000013_op-flip1_pos-1791 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000103_src-000013_op-flip1_pos-2155 b/fuzz/hfuzz_input/deserialize_script/input/id-000103_src-000013_op-flip1_pos-2155 new file mode 100644 index 000000000..5402bdbfb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000103_src-000013_op-flip1_pos-2155 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000111_src-000013_op-flip32_pos-2400 b/fuzz/hfuzz_input/deserialize_script/input/id-000111_src-000013_op-flip32_pos-2400 new file mode 100644 index 000000000..c1d0c4a91 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000111_src-000013_op-flip32_pos-2400 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000118_src-000013_op-arith8_pos-974_val-+18 b/fuzz/hfuzz_input/deserialize_script/input/id-000118_src-000013_op-arith8_pos-974_val-+18 new file mode 100644 index 000000000..95931cb77 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000118_src-000013_op-arith8_pos-974_val-+18 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000120_src-000013_op-arith8_pos-3822_val-+28 b/fuzz/hfuzz_input/deserialize_script/input/id-000120_src-000013_op-arith8_pos-3822_val-+28 new file mode 100644 index 000000000..be952a0e7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000120_src-000013_op-arith8_pos-3822_val-+28 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000121_src-000013_op-arith8_pos-3837_val-+20 b/fuzz/hfuzz_input/deserialize_script/input/id-000121_src-000013_op-arith8_pos-3837_val-+20 new file mode 100644 index 000000000..506a0dbbc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000121_src-000013_op-arith8_pos-3837_val-+20 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000125_src-000013_op-int16_pos-3820_val-+1 b/fuzz/hfuzz_input/deserialize_script/input/id-000125_src-000013_op-int16_pos-3820_val-+1 new file mode 100644 index 000000000..9e0d7b4b0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000125_src-000013_op-int16_pos-3820_val-+1 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000129_src-000019_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000129_src-000019_op-havoc_rep-2 new file mode 100644 index 000000000..40201bc53 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000129_src-000019_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000131_src-000019_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000131_src-000019_op-havoc_rep-4 new file mode 100644 index 000000000..425f6aca6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000131_src-000019_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000133_src-000019_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_script/input/id-000133_src-000019_op-havoc_rep-32 new file mode 100644 index 000000000..2b5822493 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000133_src-000019_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000134_src-000019_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000134_src-000019_op-havoc_rep-4 new file mode 100644 index 000000000..4b778111a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000134_src-000019_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000137_src-000019_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000137_src-000019_op-havoc_rep-8 new file mode 100644 index 000000000..48ac34d4a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000137_src-000019_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000139_src-000019_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000139_src-000019_op-havoc_rep-8 new file mode 100644 index 000000000..2e4f86b08 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000139_src-000019_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000140_src-000019_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000140_src-000019_op-havoc_rep-4 new file mode 100644 index 000000000..3a6a36ecb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000140_src-000019_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000141_src-000019_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000141_src-000019_op-havoc_rep-4 new file mode 100644 index 000000000..6095cc882 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000141_src-000019_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000143_src-000019_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000143_src-000019_op-havoc_rep-4 new file mode 100644 index 000000000..3977a92f6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000143_src-000019_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000144_src-000019_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000144_src-000019_op-havoc_rep-2 new file mode 100644 index 000000000..b8fba79eb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000144_src-000019_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000145_src-000019_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000145_src-000019_op-havoc_rep-8 new file mode 100644 index 000000000..4efc091d3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000145_src-000019_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000146_src-000019_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000146_src-000019_op-havoc_rep-8 new file mode 100644 index 000000000..8f4463245 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000146_src-000019_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000148_src-000019_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000148_src-000019_op-havoc_rep-8 new file mode 100644 index 000000000..eabe95546 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000148_src-000019_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000150_src-000019_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000150_src-000019_op-havoc_rep-16 new file mode 100644 index 000000000..cd1948a58 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000150_src-000019_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000151_src-000019_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000151_src-000019_op-havoc_rep-4 new file mode 100644 index 000000000..7f36e0756 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000151_src-000019_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000152_src-000024_op-flip2_pos-97 b/fuzz/hfuzz_input/deserialize_script/input/id-000152_src-000024_op-flip2_pos-97 new file mode 100644 index 000000000..a77b6d3c9 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000152_src-000024_op-flip2_pos-97 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000154_src-000024_op-flip2_pos-1124 b/fuzz/hfuzz_input/deserialize_script/input/id-000154_src-000024_op-flip2_pos-1124 new file mode 100644 index 000000000..840225771 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000154_src-000024_op-flip2_pos-1124 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000155_src-000024_op-flip2_pos-1606 b/fuzz/hfuzz_input/deserialize_script/input/id-000155_src-000024_op-flip2_pos-1606 new file mode 100644 index 000000000..5ac8669df Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000155_src-000024_op-flip2_pos-1606 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000161_src-000041_op-arith8_pos-0_val-+12 b/fuzz/hfuzz_input/deserialize_script/input/id-000161_src-000041_op-arith8_pos-0_val-+12 new file mode 100644 index 000000000..4eb0bb7db Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000161_src-000041_op-arith8_pos-0_val-+12 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000163_src-000046_op-flip1_pos-2164 b/fuzz/hfuzz_input/deserialize_script/input/id-000163_src-000046_op-flip1_pos-2164 new file mode 100644 index 000000000..4c59d6da0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000163_src-000046_op-flip1_pos-2164 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000165_src-000046_op-flip2_pos-494 b/fuzz/hfuzz_input/deserialize_script/input/id-000165_src-000046_op-flip2_pos-494 new file mode 100644 index 000000000..7f9605095 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000165_src-000046_op-flip2_pos-494 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000167_src-000046_op-flip2_pos-1025 b/fuzz/hfuzz_input/deserialize_script/input/id-000167_src-000046_op-flip2_pos-1025 new file mode 100644 index 000000000..32aa6e2a2 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000167_src-000046_op-flip2_pos-1025 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000170_src-000046_op-arith8_pos-3_val--17 b/fuzz/hfuzz_input/deserialize_script/input/id-000170_src-000046_op-arith8_pos-3_val--17 new file mode 100644 index 000000000..7965b65d7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000170_src-000046_op-arith8_pos-3_val--17 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000173_src-000046_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000173_src-000046_op-havoc_rep-16 new file mode 100644 index 000000000..6c5cbe4d5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000173_src-000046_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000174_src-000091_op-arith8_pos-6_val--24 b/fuzz/hfuzz_input/deserialize_script/input/id-000174_src-000091_op-arith8_pos-6_val--24 new file mode 100644 index 000000000..b73cae786 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000174_src-000091_op-arith8_pos-6_val--24 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000175_src-000091_op-arith8_pos-6_val--25 b/fuzz/hfuzz_input/deserialize_script/input/id-000175_src-000091_op-arith8_pos-6_val--25 new file mode 100644 index 000000000..33e610587 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000175_src-000091_op-arith8_pos-6_val--25 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000176_src-000123_op-flip1_pos-36 b/fuzz/hfuzz_input/deserialize_script/input/id-000176_src-000123_op-flip1_pos-36 new file mode 100644 index 000000000..289c300a4 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000176_src-000123_op-flip1_pos-36 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000177_src-000123_op-flip1_pos-1025 b/fuzz/hfuzz_input/deserialize_script/input/id-000177_src-000123_op-flip1_pos-1025 new file mode 100644 index 000000000..794715232 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000177_src-000123_op-flip1_pos-1025 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000179_src-000135_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000179_src-000135_op-flip1_pos-3 new file mode 100644 index 000000000..de8961935 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000179_src-000135_op-flip1_pos-3 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000180_src-000135_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_script/input/id-000180_src-000135_op-havoc_rep-64 new file mode 100644 index 000000000..b92e799cc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000180_src-000135_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000181_src-000159_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_script/input/id-000181_src-000159_op-havoc_rep-64 new file mode 100644 index 000000000..b35466cb5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000181_src-000159_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000182_src-000166_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000182_src-000166_op-flip1_pos-3 new file mode 100644 index 000000000..fd9248365 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000182_src-000166_op-flip1_pos-3 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000185_src-000183_op-flip1_pos-3694 b/fuzz/hfuzz_input/deserialize_script/input/id-000185_src-000183_op-flip1_pos-3694 new file mode 100644 index 000000000..2b72a66cb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000185_src-000183_op-flip1_pos-3694 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000186_src-000185_op-flip4_pos-278 b/fuzz/hfuzz_input/deserialize_script/input/id-000186_src-000185_op-flip4_pos-278 new file mode 100644 index 000000000..1abbf4c99 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000186_src-000185_op-flip4_pos-278 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000187_src-000026_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000187_src-000026_op-havoc_rep-8 new file mode 100644 index 000000000..f10d76ea2 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000187_src-000026_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000188_src-000026_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000188_src-000026_op-havoc_rep-4 new file mode 100644 index 000000000..5d5cdf7b6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000188_src-000026_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000189_src-000026_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000189_src-000026_op-havoc_rep-2 new file mode 100644 index 000000000..cc7e0b660 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000189_src-000026_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000190_src-000026_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000190_src-000026_op-havoc_rep-16 new file mode 100644 index 000000000..7170eda09 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000190_src-000026_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000191_src-000026_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000191_src-000026_op-havoc_rep-4 new file mode 100644 index 000000000..a1d4ce7de Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000191_src-000026_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000192_src-000026_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000192_src-000026_op-havoc_rep-8 new file mode 100644 index 000000000..7bc6b28bc Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000192_src-000026_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000193_src-000026_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000193_src-000026_op-havoc_rep-2 new file mode 100644 index 000000000..d11265dea Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000193_src-000026_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000194_src-000026_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000194_src-000026_op-havoc_rep-16 new file mode 100644 index 000000000..cfc2c8d61 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000194_src-000026_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000195_src-000026_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_script/input/id-000195_src-000026_op-havoc_rep-64 new file mode 100644 index 000000000..9865edf50 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000195_src-000026_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000197_src-000026_op-havoc_rep-128 b/fuzz/hfuzz_input/deserialize_script/input/id-000197_src-000026_op-havoc_rep-128 new file mode 100644 index 000000000..63c2d7364 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000197_src-000026_op-havoc_rep-128 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000200_src-000026_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000200_src-000026_op-havoc_rep-4 new file mode 100644 index 000000000..aaeed459b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000200_src-000026_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000202_src-000037_op-flip1_pos-1249 b/fuzz/hfuzz_input/deserialize_script/input/id-000202_src-000037_op-flip1_pos-1249 new file mode 100644 index 000000000..ee4391e54 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000202_src-000037_op-flip1_pos-1249 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000203_src-000037_op-flip4_pos-2342 b/fuzz/hfuzz_input/deserialize_script/input/id-000203_src-000037_op-flip4_pos-2342 new file mode 100644 index 000000000..d9942674f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000203_src-000037_op-flip4_pos-2342 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000204_src-000138_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000204_src-000138_op-flip1_pos-3 new file mode 100644 index 000000000..dc2e2f7c2 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000204_src-000138_op-flip1_pos-3 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000205_src-000138_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000205_src-000138_op-havoc_rep-4 new file mode 100644 index 000000000..5d1e99a57 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000205_src-000138_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000206_src-000138_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000206_src-000138_op-havoc_rep-8 new file mode 100644 index 000000000..c585b8cc1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000206_src-000138_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000210_src-000069_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000210_src-000069_op-havoc_rep-16 new file mode 100644 index 000000000..8e358f4bf Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000210_src-000069_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000216_src-000069_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000216_src-000069_op-havoc_rep-2 new file mode 100644 index 000000000..d6261ad0a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000216_src-000069_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000218_src-000069_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000218_src-000069_op-havoc_rep-8 new file mode 100644 index 000000000..83d9ee022 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000218_src-000069_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000219_src-000069_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000219_src-000069_op-havoc_rep-4 new file mode 100644 index 000000000..15376d1c6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000219_src-000069_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000220_src-000069_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000220_src-000069_op-havoc_rep-2 new file mode 100644 index 000000000..e4c545253 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000220_src-000069_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000222_src-000099_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000222_src-000099_op-havoc_rep-8 new file mode 100644 index 000000000..a463d2423 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000222_src-000099_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000223_src-000113_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000223_src-000113_op-havoc_rep-8 new file mode 100644 index 000000000..0742ec52e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000223_src-000113_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000225_src-000142_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000225_src-000142_op-flip1_pos-3 new file mode 100644 index 000000000..619e399d1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000225_src-000142_op-flip1_pos-3 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000226_src-000142_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000226_src-000142_op-havoc_rep-4 new file mode 100644 index 000000000..2eead9818 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000226_src-000142_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000227_src-000167_op-flip1_pos-1844 b/fuzz/hfuzz_input/deserialize_script/input/id-000227_src-000167_op-flip1_pos-1844 new file mode 100644 index 000000000..281a6ce53 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000227_src-000167_op-flip1_pos-1844 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000230_src-000189_op-flip2_pos-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000230_src-000189_op-flip2_pos-2 new file mode 100644 index 000000000..e89986dfa Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000230_src-000189_op-flip2_pos-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000232_src-000196_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000232_src-000196_op-havoc_rep-4 new file mode 100644 index 000000000..e7cf08fd1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000232_src-000196_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000234_src-000203_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000234_src-000203_op-havoc_rep-16 new file mode 100644 index 000000000..2859d864e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000234_src-000203_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000235_src-000211_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000235_src-000211_op-havoc_rep-2 new file mode 100644 index 000000000..b1bf64a5e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000235_src-000211_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000237_src-000211_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000237_src-000211_op-havoc_rep-8 new file mode 100644 index 000000000..d0fb0dc90 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000237_src-000211_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000238_src-000211_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000238_src-000211_op-havoc_rep-16 new file mode 100644 index 000000000..7660e36ee Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000238_src-000211_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000239_src-000211_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000239_src-000211_op-havoc_rep-8 new file mode 100644 index 000000000..846a49606 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000239_src-000211_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000240_src-000211_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_script/input/id-000240_src-000211_op-havoc_rep-64 new file mode 100644 index 000000000..e51e81ab6 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000240_src-000211_op-havoc_rep-64 @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaa}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?aaaaaaaaaaaaaaaa \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000241_src-000215_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000241_src-000215_op-havoc_rep-16 new file mode 100644 index 000000000..07e8128c1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000241_src-000215_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000242_src-000215_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000242_src-000215_op-havoc_rep-8 new file mode 100644 index 000000000..461a5ca0d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000242_src-000215_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000243_src-000215_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000243_src-000215_op-havoc_rep-4 new file mode 100644 index 000000000..ec1301c25 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000243_src-000215_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000244_src-000215_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000244_src-000215_op-havoc_rep-2 new file mode 100644 index 000000000..81e5eea39 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_script/input/id-000244_src-000215_op-havoc_rep-2 @@ -0,0 +1 @@ +ffŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ‹ŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽŽ~~~~~~~~~~~~~~~~~~~~~~~~ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000245_src-000215_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000245_src-000215_op-havoc_rep-4 new file mode 100644 index 000000000..300fa626e Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000245_src-000215_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000246_src-000215_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000246_src-000215_op-havoc_rep-8 new file mode 100644 index 000000000..5f18b3377 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000246_src-000215_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000248_src-000216_op-flip1_pos-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000248_src-000216_op-flip1_pos-2 new file mode 100644 index 000000000..9f0dbf4ce Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000248_src-000216_op-flip1_pos-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000250_src-000236_op-flip32_pos-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000250_src-000236_op-flip32_pos-4 new file mode 100644 index 000000000..4ae17bd26 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000250_src-000236_op-flip32_pos-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000251_src-000238_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000251_src-000238_op-havoc_rep-2 new file mode 100644 index 000000000..5ed880d38 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000251_src-000238_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000252_src-000156_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000252_src-000156_op-havoc_rep-8 new file mode 100644 index 000000000..f6cccdf66 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000252_src-000156_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000253_src-000241_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000253_src-000241_op-havoc_rep-2 new file mode 100644 index 000000000..c782df1b5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000253_src-000241_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000254_src-000206_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000254_src-000206_op-havoc_rep-4 new file mode 100644 index 000000000..ef86319ea Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000254_src-000206_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000255_src-000229_op-flip1_pos-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000255_src-000229_op-flip1_pos-4 new file mode 100644 index 000000000..ee4175dd6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000255_src-000229_op-flip1_pos-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000256_src-000237_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000256_src-000237_op-havoc_rep-8 new file mode 100644 index 000000000..2fe528c04 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000256_src-000237_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000257_src-000255_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_script/input/id-000257_src-000255_op-havoc_rep-16 new file mode 100644 index 000000000..63379c988 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000257_src-000255_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000258_src-000126_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_script/input/id-000258_src-000126_op-havoc_rep-8 new file mode 100644 index 000000000..7a272c765 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000258_src-000126_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000259_src-000172_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000259_src-000172_op-flip1_pos-3 new file mode 100644 index 000000000..400b58e3b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000259_src-000172_op-flip1_pos-3 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000260_src-000254_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000260_src-000254_op-flip1_pos-3 new file mode 100644 index 000000000..a0ca9bd09 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000260_src-000254_op-flip1_pos-3 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000261_src-000254_op-flip1_pos-46 b/fuzz/hfuzz_input/deserialize_script/input/id-000261_src-000254_op-flip1_pos-46 new file mode 100644 index 000000000..c8d44bf79 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000261_src-000254_op-flip1_pos-46 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000262_src-000232_op-flip2_pos-100 b/fuzz/hfuzz_input/deserialize_script/input/id-000262_src-000232_op-flip2_pos-100 new file mode 100644 index 000000000..98300c67c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000262_src-000232_op-flip2_pos-100 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000263_src-000258_op-flip1_pos-4249 b/fuzz/hfuzz_input/deserialize_script/input/id-000263_src-000258_op-flip1_pos-4249 new file mode 100644 index 000000000..fa28ca850 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000263_src-000258_op-flip1_pos-4249 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000265_src-000264_op-flip1_pos-4249 b/fuzz/hfuzz_input/deserialize_script/input/id-000265_src-000264_op-flip1_pos-4249 new file mode 100644 index 000000000..284037c78 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000265_src-000264_op-flip1_pos-4249 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000267_src-000266_op-flip1_pos-4249 b/fuzz/hfuzz_input/deserialize_script/input/id-000267_src-000266_op-flip1_pos-4249 new file mode 100644 index 000000000..b45ec4add Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000267_src-000266_op-flip1_pos-4249 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000269_src-000085_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000269_src-000085_op-havoc_rep-4 new file mode 100644 index 000000000..3c68f2261 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000269_src-000085_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000271_src-000262_op-flip2_pos-102 b/fuzz/hfuzz_input/deserialize_script/input/id-000271_src-000262_op-flip2_pos-102 new file mode 100644 index 000000000..594e6d969 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000271_src-000262_op-flip2_pos-102 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000272_src-000270_op-arith8_pos-4249_val-+14 b/fuzz/hfuzz_input/deserialize_script/input/id-000272_src-000270_op-arith8_pos-4249_val-+14 new file mode 100644 index 000000000..52b76d753 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000272_src-000270_op-arith8_pos-4249_val-+14 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000273_src-000272_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_script/input/id-000273_src-000272_op-havoc_rep-4 new file mode 100644 index 000000000..d593ad310 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000273_src-000272_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000275_src-000274_op-flip1_pos-3 b/fuzz/hfuzz_input/deserialize_script/input/id-000275_src-000274_op-flip1_pos-3 new file mode 100644 index 000000000..e69de29bb diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000276_src-000274_op-flip1_pos-271 b/fuzz/hfuzz_input/deserialize_script/input/id-000276_src-000274_op-flip1_pos-271 new file mode 100644 index 000000000..463a47d3f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000276_src-000274_op-flip1_pos-271 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000277_src-000274_op-flip1_pos-386 b/fuzz/hfuzz_input/deserialize_script/input/id-000277_src-000274_op-flip1_pos-386 new file mode 100644 index 000000000..8ed3436a1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000277_src-000274_op-flip1_pos-386 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000278_src-000181_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000278_src-000181_op-havoc_rep-2 new file mode 100644 index 000000000..05b265ac5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000278_src-000181_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_script/input/id-000279_src-000278_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_script/input/id-000279_src-000278_op-havoc_rep-2 new file mode 100644 index 000000000..316ece27a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_script/input/id-000279_src-000278_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/2d1bda85f26c6be89656abe2efcacc9c.00003e4a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/2d1bda85f26c6be89656abe2efcacc9c.00003e4a.honggfuzz.cov new file mode 100644 index 000000000..478f8b1f6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/2d1bda85f26c6be89656abe2efcacc9c.00003e4a.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/81018c8ec16dd1760f9345f884bf7884.00002ddb.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/81018c8ec16dd1760f9345f884bf7884.00002ddb.honggfuzz.cov new file mode 100644 index 000000000..ecea28e77 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/81018c8ec16dd1760f9345f884bf7884.00002ddb.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/99d1820d217a526f53f014ac738f9f13.000001cc.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/99d1820d217a526f53f014ac738f9f13.000001cc.honggfuzz.cov new file mode 100644 index 000000000..7007d8a7a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/99d1820d217a526f53f014ac738f9f13.000001cc.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/9c997889bc333a763153889a6ef41f9d.00002000.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/9c997889bc333a763153889a6ef41f9d.00002000.honggfuzz.cov new file mode 100644 index 000000000..e8b2a7f7b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/9c997889bc333a763153889a6ef41f9d.00002000.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/ac9bb13a181a013e28827cca4ca6b58b.00001022.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/ac9bb13a181a013e28827cca4ca6b58b.00001022.honggfuzz.cov new file mode 100644 index 000000000..febebef24 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/ac9bb13a181a013e28827cca4ca6b58b.00001022.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000000_orig-002763ccd013ccf03c63d0bc63d7f000.00000007.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000000_orig-002763ccd013ccf03c63d0bc63d7f000.00000007.honggfuzz.cov new file mode 100644 index 000000000..810138fd0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000000_orig-002763ccd013ccf03c63d0bc63d7f000.00000007.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000002_orig-745aa2bf1eb4f96b10a6e86143c9a9b9.0000019e.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000002_orig-745aa2bf1eb4f96b10a6e86143c9a9b9.0000019e.honggfuzz.cov new file mode 100644 index 000000000..723f55bc4 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000002_orig-745aa2bf1eb4f96b10a6e86143c9a9b9.0000019e.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000003_orig-0ab99d259c9be939f6dc7076393bec9c.0000000b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000003_orig-0ab99d259c9be939f6dc7076393bec9c.0000000b.honggfuzz.cov new file mode 100644 index 000000000..8a1ee5f1e --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000003_orig-0ab99d259c9be939f6dc7076393bec9c.0000000b.honggfuzz.cov @@ -0,0 +1 @@ +-4277411353 \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000008_orig-cbae8f9530fd6ce23ddf96240f65e2d9.000007ac.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000008_orig-cbae8f9530fd6ce23ddf96240f65e2d9.000007ac.honggfuzz.cov new file mode 100644 index 000000000..f44e2d228 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000008_orig-cbae8f9530fd6ce23ddf96240f65e2d9.000007ac.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000011_orig-fd15b185d5abc685014501da4b98b0df.00001ecf.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000011_orig-fd15b185d5abc685014501da4b98b0df.00001ecf.honggfuzz.cov new file mode 100644 index 000000000..51f977add Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000011_orig-fd15b185d5abc685014501da4b98b0df.00001ecf.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000012_orig-2125d9ea2ab360351298a9bddfea3e5b.000000af.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000012_orig-2125d9ea2ab360351298a9bddfea3e5b.000000af.honggfuzz.cov new file mode 100644 index 000000000..bc5665733 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000012_orig-2125d9ea2ab360351298a9bddfea3e5b.000000af.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000012_orig-febd092ddff9c72cc7e25dab4d0cbd5a.00000323.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000012_orig-febd092ddff9c72cc7e25dab4d0cbd5a.00000323.honggfuzz.cov new file mode 100644 index 000000000..fa252572f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000012_orig-febd092ddff9c72cc7e25dab4d0cbd5a.00000323.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000015_orig-a7114a6c122f99cbbed5448562b7a513.000000aa.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000015_orig-a7114a6c122f99cbbed5448562b7a513.000000aa.honggfuzz.cov new file mode 100644 index 000000000..9711c9b77 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000015_orig-a7114a6c122f99cbbed5448562b7a513.000000aa.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000016_orig-0001b0900b48d74067d82b409001b000.00000007.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000016_orig-0001b0900b48d74067d82b409001b000.00000007.honggfuzz.cov new file mode 100644 index 000000000..98587d866 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000016_orig-0001b0900b48d74067d82b409001b000.00000007.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000017_orig-8530f6c85f51e01782b6e9d970a22f7f.000013b1.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000017_orig-8530f6c85f51e01782b6e9d970a22f7f.000013b1.honggfuzz.cov new file mode 100644 index 000000000..3faa97c5b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000017_orig-8530f6c85f51e01782b6e9d970a22f7f.000013b1.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000018_orig-7091449e57d7e974bbd12814f2dace4a.0000002b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000018_orig-7091449e57d7e974bbd12814f2dace4a.0000002b.honggfuzz.cov new file mode 100644 index 000000000..54d481022 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000018_orig-7091449e57d7e974bbd12814f2dace4a.0000002b.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000019_orig-900090847ae00000ba64c09000900000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000019_orig-900090847ae00000ba64c09000900000.00000005.honggfuzz.cov new file mode 100644 index 000000000..b5de797c5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000019_orig-900090847ae00000ba64c09000900000.00000005.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000020_orig-7469f7d107c7fd99f43029ee8c9787e0.00001590.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000020_orig-7469f7d107c7fd99f43029ee8c9787e0.00001590.honggfuzz.cov new file mode 100644 index 000000000..00a8dec45 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000020_orig-7469f7d107c7fd99f43029ee8c9787e0.00001590.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000023_orig-auto_000043 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000023_orig-auto_000043 new file mode 100644 index 000000000..4af8ee427 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000023_orig-auto_000043 @@ -0,0 +1 @@ +Gƒóý \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000023_orig-cb75435edf707028dd307804fc133fbb.00002000.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000023_orig-cb75435edf707028dd307804fc133fbb.00002000.honggfuzz.cov new file mode 100644 index 000000000..72c70a02a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000023_orig-cb75435edf707028dd307804fc133fbb.00002000.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000024_orig-bc4caef929c4fe562ce1da2737e3688c.0000002b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000024_orig-bc4caef929c4fe562ce1da2737e3688c.0000002b.honggfuzz.cov new file mode 100644 index 000000000..7d8df0234 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000024_orig-bc4caef929c4fe562ce1da2737e3688c.0000002b.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000028_orig-da420ddf8a5b5f69df89af72278b7eea.00000015.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000028_orig-da420ddf8a5b5f69df89af72278b7eea.00000015.honggfuzz.cov new file mode 100644 index 000000000..01f0e6b71 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000028_orig-da420ddf8a5b5f69df89af72278b7eea.00000015.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000029_orig-e4e83fa44f6fe9836f08b12e0d8e188a.000006f4.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000029_orig-e4e83fa44f6fe9836f08b12e0d8e188a.000006f4.honggfuzz.cov new file mode 100644 index 000000000..98da8414a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000029_orig-e4e83fa44f6fe9836f08b12e0d8e188a.000006f4.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000041_orig-fafb191376bf650083767ba57a6560f3.00000081.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000041_orig-fafb191376bf650083767ba57a6560f3.00000081.honggfuzz.cov new file mode 100644 index 000000000..33bcbdbd8 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000041_orig-fafb191376bf650083767ba57a6560f3.00000081.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000043_orig-53b59d89e4b4a8f9bfaf8e6585044b53.00000063.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000043_orig-53b59d89e4b4a8f9bfaf8e6585044b53.00000063.honggfuzz.cov new file mode 100644 index 000000000..d6a4c786a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000043_orig-53b59d89e4b4a8f9bfaf8e6585044b53.00000063.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000045_orig-4a108700000029838ddc73d910000000.0000000a.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000045_orig-4a108700000029838ddc73d910000000.0000000a.honggfuzz.cov new file mode 100644 index 000000000..d50016546 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000045_orig-4a108700000029838ddc73d910000000.0000000a.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000047_orig-f286eecdb14369a68b60c9dfa2bd7561.0000003b.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000047_orig-f286eecdb14369a68b60c9dfa2bd7561.0000003b.honggfuzz.cov new file mode 100644 index 000000000..094181eab Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000047_orig-f286eecdb14369a68b60c9dfa2bd7561.0000003b.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000050_orig-919cb2dd5670000046ed82fcb1200000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000050_orig-919cb2dd5670000046ed82fcb1200000.00000005.honggfuzz.cov new file mode 100644 index 000000000..b0a4d453c --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000050_orig-919cb2dd5670000046ed82fcb1200000.00000005.honggfuzz.cov @@ -0,0 +1 @@ +u÷üÎþ \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000051_orig-990000001456c00006d4500000990000.00000006.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000051_orig-990000001456c00006d4500000990000.00000006.honggfuzz.cov new file mode 100644 index 000000000..67f9a620c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000051_orig-990000001456c00006d4500000990000.00000006.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000052_orig-000000008ddd50008ddd500000000000.00000006.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000052_orig-000000008ddd50008ddd500000000000.00000006.honggfuzz.cov new file mode 100644 index 000000000..054ede9f8 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000052_orig-000000008ddd50008ddd500000000000.00000006.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000053_orig-00f9c95959300000f95959c930000000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000053_orig-00f9c95959300000f95959c930000000.00000005.honggfuzz.cov new file mode 100644 index 000000000..5d3fdf864 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000053_orig-00f9c95959300000f95959c930000000.00000005.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000054_orig-649e8b804eaa54943b1d7b1d50b246e6.00000010.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000054_orig-649e8b804eaa54943b1d7b1d50b246e6.00000010.honggfuzz.cov new file mode 100644 index 000000000..52fb5b608 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000054_orig-649e8b804eaa54943b1d7b1d50b246e6.00000010.honggfuzz.cov differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000057_orig-8ddec9bd500000008da9bebd50000000.00000004.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000057_orig-8ddec9bd500000008da9bebd50000000.00000004.honggfuzz.cov new file mode 100644 index 000000000..f18cbda6a --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000057_orig-8ddec9bd500000008da9bebd50000000.00000004.honggfuzz.cov @@ -0,0 +1 @@ +ë¹éë \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000057_orig-id-000095_src-000000+000044_op-splice_rep-64 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000057_orig-id-000095_src-000000+000044_op-splice_rep-64 new file mode 100644 index 000000000..ab06da2cd Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000057_orig-id-000095_src-000000+000044_op-splice_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000060_orig-c5d936add940000089cdb63915c00000.00000005.honggfuzz.cov b/fuzz/hfuzz_input/deserialize_transaction/input/id-000060_orig-c5d936add940000089cdb63915c00000.00000005.honggfuzz.cov new file mode 100644 index 000000000..da99751c8 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000060_orig-c5d936add940000089cdb63915c00000.00000005.honggfuzz.cov @@ -0,0 +1 @@ +ìë®” \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000060_orig-id-000101_src-000002_op-flip2_pos-6 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000060_orig-id-000101_src-000002_op-flip2_pos-6 new file mode 100644 index 000000000..58741b649 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000060_orig-id-000101_src-000002_op-flip2_pos-6 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000061_orig-id-000107_src-000002_op-int16_pos-4773_val-+1000 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000061_orig-id-000107_src-000002_op-int16_pos-4773_val-+1000 new file mode 100644 index 000000000..713e4e495 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000061_orig-id-000107_src-000002_op-int16_pos-4773_val-+1000 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000062_orig-id-000060_src-000000_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000062_orig-id-000060_src-000000_op-havoc_rep-64 new file mode 100644 index 000000000..bfdce2fb3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000062_orig-id-000060_src-000000_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000072_src-000000_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000072_src-000000_op-havoc_rep-16 new file mode 100644 index 000000000..ad4c09e54 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000072_src-000000_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000074_src-000000_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000074_src-000000_op-havoc_rep-8 new file mode 100644 index 000000000..ae6434dc7 --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000074_src-000000_op-havoc_rep-8 @@ -0,0 +1 @@ +ðððñ×ðó \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000076_src-000000_op-havoc_rep-128 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000076_src-000000_op-havoc_rep-128 new file mode 100644 index 000000000..e47447d7f --- /dev/null +++ b/fuzz/hfuzz_input/deserialize_transaction/input/id-000076_src-000000_op-havoc_rep-128 @@ -0,0 +1 @@ +CCCCCCCCCCC+CCCCCCCCCCCCCCCC+CCCCCCCCCaCCCC \ No newline at end of file diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000077_src-000000_op-havoc_rep-128 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000077_src-000000_op-havoc_rep-128 new file mode 100644 index 000000000..e84bbec96 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000077_src-000000_op-havoc_rep-128 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000080_src-000000_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000080_src-000000_op-havoc_rep-32 new file mode 100644 index 000000000..1070e0bda Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000080_src-000000_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000082_src-000000_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000082_src-000000_op-havoc_rep-4 new file mode 100644 index 000000000..1e44a4317 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000082_src-000000_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000084_src-000000+000044_op-splice_rep-8 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000084_src-000000+000044_op-splice_rep-8 new file mode 100644 index 000000000..4787adb69 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000084_src-000000+000044_op-splice_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000087_src-000000_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000087_src-000000_op-havoc_rep-64 new file mode 100644 index 000000000..c0e116019 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000087_src-000000_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000088_src-000000+000010_op-splice_rep-128 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000088_src-000000+000010_op-splice_rep-128 new file mode 100644 index 000000000..223d3db70 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000088_src-000000+000010_op-splice_rep-128 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000088_src-000000_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000088_src-000000_op-havoc_rep-2 new file mode 100644 index 000000000..a587bbcbb Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000088_src-000000_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000089_src-000003_op-flip1_pos-43 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000089_src-000003_op-flip1_pos-43 new file mode 100644 index 000000000..214bbdb0a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000089_src-000003_op-flip1_pos-43 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000090_src-000003_op-flip1_pos-3258 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000090_src-000003_op-flip1_pos-3258 new file mode 100644 index 000000000..dc3704e65 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000090_src-000003_op-flip1_pos-3258 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000091_src-000003_op-flip2_pos-1612 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000091_src-000003_op-flip2_pos-1612 new file mode 100644 index 000000000..da8dadac7 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000091_src-000003_op-flip2_pos-1612 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000092_src-000003_op-flip8_pos-84 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000092_src-000003_op-flip8_pos-84 new file mode 100644 index 000000000..b07e6feb3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000092_src-000003_op-flip8_pos-84 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000093_src-000002_op-flip1_pos-535 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000093_src-000002_op-flip1_pos-535 new file mode 100644 index 000000000..02c71fda5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000093_src-000002_op-flip1_pos-535 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000095_src-000003_op-arith16_pos-1118_val--5 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000095_src-000003_op-arith16_pos-1118_val--5 new file mode 100644 index 000000000..d12741271 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000095_src-000003_op-arith16_pos-1118_val--5 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000096_src-000007_op-int32_pos-2110_val-+1024 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000096_src-000007_op-int32_pos-2110_val-+1024 new file mode 100644 index 000000000..ca726819c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000096_src-000007_op-int32_pos-2110_val-+1024 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000097_src-000000+000010_op-splice_rep-64 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000097_src-000000+000010_op-splice_rep-64 new file mode 100644 index 000000000..7ccf96bae Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000097_src-000000+000010_op-splice_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000097_src-000007_op-havoc_rep-2 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000097_src-000007_op-havoc_rep-2 new file mode 100644 index 000000000..3e60b96e1 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000097_src-000007_op-havoc_rep-2 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000098_src-000025_op-arith8_pos-6_val--30 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000098_src-000025_op-arith8_pos-6_val--30 new file mode 100644 index 000000000..cae44215f Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000098_src-000025_op-arith8_pos-6_val--30 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000099_src-000051_op-flip1_pos-698 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000099_src-000051_op-flip1_pos-698 new file mode 100644 index 000000000..2596d285c Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000099_src-000051_op-flip1_pos-698 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000100_src-000053_op-int16_pos-370_val-+1024 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000100_src-000053_op-int16_pos-370_val-+1024 new file mode 100644 index 000000000..115bc2efe Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000100_src-000053_op-int16_pos-370_val-+1024 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000101_src-000053_op-int32_pos-111_val-+1024 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000101_src-000053_op-int32_pos-111_val-+1024 new file mode 100644 index 000000000..2535e71d6 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000101_src-000053_op-int32_pos-111_val-+1024 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000103_src-000073_op-flip1_pos-181 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000103_src-000073_op-flip1_pos-181 new file mode 100644 index 000000000..e31922516 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000103_src-000073_op-flip1_pos-181 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000106_src-000076_op-flip1_pos-57 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000106_src-000076_op-flip1_pos-57 new file mode 100644 index 000000000..755a7669b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000106_src-000076_op-flip1_pos-57 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000107_src-000076_op-int32_pos-58_val-+1000 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000107_src-000076_op-int32_pos-58_val-+1000 new file mode 100644 index 000000000..cf776fcfa Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000107_src-000076_op-int32_pos-58_val-+1000 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000108_src-000096_op-havoc_rep-8 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000108_src-000096_op-havoc_rep-8 new file mode 100644 index 000000000..d52234890 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000108_src-000096_op-havoc_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000114_src-000002_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000114_src-000002_op-havoc_rep-64 new file mode 100644 index 000000000..5d229c216 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000114_src-000002_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000114_src-000107_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000114_src-000107_op-havoc_rep-32 new file mode 100644 index 000000000..c5a9f63c5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000114_src-000107_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000115_src-000107_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000115_src-000107_op-havoc_rep-32 new file mode 100644 index 000000000..8eb758680 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000115_src-000107_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000116_src-000111_op-int16_pos-58_val-+512 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000116_src-000111_op-int16_pos-58_val-+512 new file mode 100644 index 000000000..a84cb7201 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000116_src-000111_op-int16_pos-58_val-+512 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000117_src-000052_op-int16_pos-1595_val-+512 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000117_src-000052_op-int16_pos-1595_val-+512 new file mode 100644 index 000000000..36ff52b7b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000117_src-000052_op-int16_pos-1595_val-+512 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000118_src-000002_op-havoc_rep-64 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000118_src-000002_op-havoc_rep-64 new file mode 100644 index 000000000..b3b727b83 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000118_src-000002_op-havoc_rep-64 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000118_src-000062_op-int16_pos-427_val-be-+100 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000118_src-000062_op-int16_pos-427_val-be-+100 new file mode 100644 index 000000000..0a0f26b9b Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000118_src-000062_op-int16_pos-427_val-be-+100 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000119_src-000085_op-arith8_pos-15196_val-+11 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000119_src-000085_op-arith8_pos-15196_val-+11 new file mode 100644 index 000000000..b5c479594 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000119_src-000085_op-arith8_pos-15196_val-+11 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000122_src-000016_op-int16_pos-6_val-be-+127 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000122_src-000016_op-int16_pos-6_val-be-+127 new file mode 100644 index 000000000..967f834d3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000122_src-000016_op-int16_pos-6_val-be-+127 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000124_src-000119_op-arith8_pos-584_val-+10 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000124_src-000119_op-arith8_pos-584_val-+10 new file mode 100644 index 000000000..f83b1d5ec Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000124_src-000119_op-arith8_pos-584_val-+10 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000125_src-000020_op-flip1_pos-1946 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000125_src-000020_op-flip1_pos-1946 new file mode 100644 index 000000000..3251da698 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000125_src-000020_op-flip1_pos-1946 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000127_src-000072_op-havoc_rep-4 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000127_src-000072_op-havoc_rep-4 new file mode 100644 index 000000000..31d94ab21 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000127_src-000072_op-havoc_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000129_src-000128_op-int32_pos-406_val-be-+512 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000129_src-000128_op-int32_pos-406_val-be-+512 new file mode 100644 index 000000000..e1ced3f8a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000129_src-000128_op-int32_pos-406_val-be-+512 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000130_src-000076_op-flip1_pos-6 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000130_src-000076_op-flip1_pos-6 new file mode 100644 index 000000000..5193295e5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000130_src-000076_op-flip1_pos-6 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000130_src-000129_op-havoc_rep-16 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000130_src-000129_op-havoc_rep-16 new file mode 100644 index 000000000..2f268baac Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000130_src-000129_op-havoc_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000131_src-000068_op-flip2_pos-43 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000131_src-000068_op-flip2_pos-43 new file mode 100644 index 000000000..6c11913d4 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000131_src-000068_op-flip2_pos-43 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000132_src-000097+000109_op-splice_rep-4 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000132_src-000097+000109_op-splice_rep-4 new file mode 100644 index 000000000..8d3ffafcf Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000132_src-000097+000109_op-splice_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000133_src-000027+000052_op-splice_rep-8 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000133_src-000027+000052_op-splice_rep-8 new file mode 100644 index 000000000..db6431fd0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000133_src-000027+000052_op-splice_rep-8 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000134_src-000060+000111_op-splice_rep-4 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000134_src-000060+000111_op-splice_rep-4 new file mode 100644 index 000000000..00b3ec480 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000134_src-000060+000111_op-splice_rep-4 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000137_src-000047+000127_op-splice_rep-16 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000137_src-000047+000127_op-splice_rep-16 new file mode 100644 index 000000000..cc573b256 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000137_src-000047+000127_op-splice_rep-16 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000140_src-000090_op-arith16_pos-114_val-be--6 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000140_src-000090_op-arith16_pos-114_val-be--6 new file mode 100644 index 000000000..dfdf5a6ef Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000140_src-000090_op-arith16_pos-114_val-be--6 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000142_src-000123_op-flip1_pos-92 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000142_src-000123_op-flip1_pos-92 new file mode 100644 index 000000000..9bf3875d0 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000142_src-000123_op-flip1_pos-92 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000144_src-000121_op-flip2_pos-743 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000144_src-000121_op-flip2_pos-743 new file mode 100644 index 000000000..917e6d863 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000144_src-000121_op-flip2_pos-743 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000166_sync-deserialize_transaction_master_src-000136 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000166_sync-deserialize_transaction_master_src-000136 new file mode 100644 index 000000000..3ccf790d3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000166_sync-deserialize_transaction_master_src-000136 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000176_sync-deserialize_transaction_2_src-000163 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000176_sync-deserialize_transaction_2_src-000163 new file mode 100644 index 000000000..9a448e435 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000176_sync-deserialize_transaction_2_src-000163 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000176_sync-deserialize_transaction_master_src-000128 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000176_sync-deserialize_transaction_master_src-000128 new file mode 100644 index 000000000..f226aa65d Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000176_sync-deserialize_transaction_master_src-000128 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000188_sync-deserialize_transaction_master_src-000172 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000188_sync-deserialize_transaction_master_src-000172 new file mode 100644 index 000000000..04be3a434 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000188_sync-deserialize_transaction_master_src-000172 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000190_sync-deserialize_transaction_master_src-000171 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000190_sync-deserialize_transaction_master_src-000171 new file mode 100644 index 000000000..66acf3be5 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000190_sync-deserialize_transaction_master_src-000171 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000194_src-000154_op-havoc_rep-32 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000194_src-000154_op-havoc_rep-32 new file mode 100644 index 000000000..6b5c5b165 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000194_src-000154_op-havoc_rep-32 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000196_sync-deserialize_transaction_2_src-000177 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000196_sync-deserialize_transaction_2_src-000177 new file mode 100644 index 000000000..d5fd922ed Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000196_sync-deserialize_transaction_2_src-000177 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000199_sync-deserialize_transaction_0_src-000190 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000199_sync-deserialize_transaction_0_src-000190 new file mode 100644 index 000000000..427fc0eb8 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000199_sync-deserialize_transaction_0_src-000190 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000202_src-000173_op-arith8_pos-178_val--2 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000202_src-000173_op-arith8_pos-178_val--2 new file mode 100644 index 000000000..973a27a80 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000202_src-000173_op-arith8_pos-178_val--2 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000202_sync-deserialize_transaction_master_src-000162 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000202_sync-deserialize_transaction_master_src-000162 new file mode 100644 index 000000000..305f1519a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000202_sync-deserialize_transaction_master_src-000162 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000209_sync-deserialize_transaction_3_src-000202 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000209_sync-deserialize_transaction_3_src-000202 new file mode 100644 index 000000000..b31ea914a Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000209_sync-deserialize_transaction_3_src-000202 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000213_sync-deserialize_transaction_3_src-000206 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000213_sync-deserialize_transaction_3_src-000206 new file mode 100644 index 000000000..8ce5981b3 Binary files /dev/null and b/fuzz/hfuzz_input/deserialize_transaction/input/id-000213_sync-deserialize_transaction_3_src-000206 differ diff --git a/fuzz/hfuzz_input/deserialize_transaction/input/id-000226_sync-deserialize_transaction_2_src-000216 b/fuzz/hfuzz_input/deserialize_transaction/input/id-000226_sync-deserialize_transaction_2_src-000216 new file mode 100644 index 000000000..e69de29bb diff --git a/fuzz/src/fuzz_utils.rs b/fuzz/src/fuzz_utils.rs new file mode 100644 index 000000000..883729c3c --- /dev/null +++ b/fuzz/src/fuzz_utils.rs @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Helper functions for fuzzing. + +pub fn consume_random_bytes<'a>(data: &mut &'a [u8]) -> &'a [u8] { + if data.is_empty() { + return &[]; + } + + let length = (data[0] as usize) % (data.len() + 1); + let (bytes, rest) = data.split_at(length); + *data = rest; + + bytes +} + +#[allow(dead_code)] +pub fn consume_u64(data: &mut &[u8]) -> u64 { + // We need at least 8 bytes to read a u64 + if data.len() < 8 { + return 0; + } + + let (u64_bytes, rest) = data.split_at(8); + *data = rest; + + u64::from_le_bytes([ + u64_bytes[0], + u64_bytes[1], + u64_bytes[2], + u64_bytes[3], + u64_bytes[4], + u64_bytes[5], + u64_bytes[6], + u64_bytes[7], + ]) +} + +#[allow(dead_code)] +pub fn consume_u32(data: &mut &[u8]) -> u32 { + // We need at least 4 bytes to read a u32 + if data.len() < 4 { + return 0; + } + + let (u32_bytes, rest) = data.split_at(4); + *data = rest; + + u32::from_le_bytes([u32_bytes[0], u32_bytes[1], u32_bytes[2], u32_bytes[3]]) +} diff --git a/fuzz/src/lib.rs b/fuzz/src/lib.rs new file mode 100644 index 000000000..3421bc224 --- /dev/null +++ b/fuzz/src/lib.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Fuzzing + +pub mod fuzz_utils; diff --git a/githooks/post-merge b/githooks/post-merge new file mode 100755 index 000000000..2d78934d1 --- /dev/null +++ b/githooks/post-merge @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# === RUST-BITCOIN GITHOOK === + +# Scan the githooks after merge. If the user is using any of the rust-bitcoin githooks and they have changed, let them know +# to rerun the githooks setup. + +# We only care about this on master +[[ "$(git branch --show-current)" = "master" ]] || exit + +# Get the local githooks directory, regardless of configuration. +GIT_DIR=$(git rev-parse --git-common-dir) +HOOKS_DIR=$(git config --get core.hooksPath || echo "$GIT_DIR/hooks") + +# Scan each of the hooks looking for the tag. If the tag is found, then the user is using a +# rust-bitcoin githook. We should compare them to the repo's hooks to see if they have +# changed in the latest git pull. +for hook in "$HOOKS_DIR"/* +do + if grep -q '=== RUST-BITCOIN GITHOOK ===' "$hook"; then + BN=$(basename "$hook") + if ! cmp --quiet "$hook" "githooks/$BN"; then + >&2 cat <<- EOF + ================================================== + Project githooks have changed. Please inspect the + changes and re-run \`just githooks-install\` if + they are legitimate. + + Remove $HOOKS_DIR/post-merge to skip this warning + in the future. + ================================================== + EOF + exit + fi + fi +done diff --git a/githooks/pre-commit b/githooks/pre-commit new file mode 100755 index 000000000..9d873fd3e --- /dev/null +++ b/githooks/pre-commit @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# === RUST-BITCOIN GITHOOK === +# +# Verify what is about to be committed. Called by "git commit" with no +# arguments. The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test "$(git diff --cached --name-only --diff-filter=A -z "$against" | + LC_ALL=C tr -d '[ -~]\0' | wc -c)" != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +git diff-index --check --cached "$against" -- || exit 1 + +# Check that code lints cleanly. +cargo +"$(cat ./nightly-version)" clippy --workspace --all-targets --all-features -- --deny warnings || exit 1 diff --git a/hashes/CHANGELOG.md b/hashes/CHANGELOG.md new file mode 100644 index 000000000..17e0d4eb6 --- /dev/null +++ b/hashes/CHANGELOG.md @@ -0,0 +1,284 @@ +# 0.18.0 - 2025-11-27 + +* Add a dependency on the new `consensus_encoding` crate [#5181](https://github.com/rust-bitcoin/rust-bitcoin/pull/5181) + +# 0.17.0 - 2025-10-17 + +* Bump MSRV from 1.63.0 to 1.74.0 for all crates in the repo [#4926](https://github.com/rust-bitcoin/rust-bitcoin/pull/4926) +* Add a `sha3_256` module with `SHA3-256` [#4919](https://github.com/rust-bitcoin/rust-bitcoin/pull/4919) +* Remove code deprecated in `v0.15.0` [#4840](https://github.com/rust-bitcoin/rust-bitcoin/pull/4840) +* Update `serde` dependency to match workspace [#4321](https://github.com/rust-bitcoin/rust-bitcoin/pull/4321) +* Remove `From` for not-general-hash types [#4128 ](https://github.com/rust-bitcoin/rust-bitcoin/pull/4128) +* Remove the `GeneralHash` trait [#4085](https://github.com/rust-bitcoin/rust-bitcoin/pull/4085) +* Only enable `hex`/`std`, and `hex`/`alloc` when `hex` is [#4055](https://github.com/rust-bitcoin/rust-bitcoin/pull/4055) +* Derive `Debug` for all hash engines [#4015](https://github.com/rust-bitcoin/rust-bitcoin/pull/4015) +* Add a tagged hash engine [#4010](https://github.com/rust-bitcoin/rust-bitcoin/pull/4010) +* Add engine function to `siphash24::Hash` [#4003](https://github.com/rust-bitcoin/rust-bitcoin/pull/4003) +* Do not implement `Default` for `HmacEngine` [#3981](https://github.com/rust-bitcoin/rust-bitcoin/pull/3981) +* Invert dependency between `io` and `hashes` [#3961](https://github.com/rust-bitcoin/rust-bitcoin/pull/3961) + +# 0.16.0 - 2024-12-12 + +* Make `hex-conservative` an optional dependency [#3611](https://github.com/rust-bitcoin/rust-bitcoin/pull/3611) +* Bump `hex-conservative` to `v0.3.0` [#3543](https://github.com/rust-bitcoin/rust-bitcoin/pull/3543) +* Hide error internals [#3579](https://github.com/rust-bitcoin/rust-bitcoin/pull/3579) + +# 0.15.0 - 2024-10-16 + +This release is massive. The biggest visible changes are to the `Hash` trait, which has mostly been replaced +by inherent functions. You should not need to import it at all anymore for normal usage. Check out how we are +using `hashes` in `rust-bitcoin` to see an example. Enjoy! + +* Remove the `util` and `serde_macros` modules and roll all code into new public `macros` module [#3299](https://github.com/rust-bitcoin/rust-bitcoin/pull/3299) +* Remove `SliceIndex` implementation from hash types [#3296](https://github.com/rust-bitcoin/rust-bitcoin/pull/3296) +* Rename `Midstate::into_parts` to `Midstate::to_parts` since it derives `Copy` [#3429](https://github.com/rust-bitcoin/rust-bitcoin/pull/3429) +* Remove `schemars` support [#3395](https://github.com/rust-bitcoin/rust-bitcoin/pull/3395) +* Deprecate `from_slice` methods in favor of arrays [#3301](https://github.com/rust-bitcoin/rust-bitcoin/pull/3301) +* Rename `length` field to `bytes_hashed` [#3298](https://github.com/rust-bitcoin/rust-bitcoin/pull/3298) +* Enforce that `Hash::Bytes` is an array [#3257](https://github.com/rust-bitcoin/rust-bitcoin/pull/3257) +* `Siphash24` cleanup [#3222](https://github.com/rust-bitcoin/rust-bitcoin/pull/3222) +* Reduce API surface of tagged wrapped hash types [#3184](https://github.com/rust-bitcoin/rust-bitcoin/pull/3184) +* Rename `const_hash` functions to `hash_unoptimized` [#3129](https://github.com/rust-bitcoin/rust-bitcoin/pull/3129) +* Remove `io` feature (use `bitcoin-io` dependency directly) [#3128](https://github.com/rust-bitcoin/rust-bitcoin/pull/3128) +* Rename `Siphash::as_u64` to `Siphash::to_u64` [#3119](https://github.com/rust-bitcoin/rust-bitcoin/pull/3119) +* Push up the `Default` bound on `HashEngine` in order to better support keyed hash functions [#3113](https://github.com/rust-bitcoin/rust-bitcoin/pull/3113) +* Add a new `hash_reader` function [#3077](https://github.com/rust-bitcoin/rust-bitcoin/pull/3077) +* Add `length` field to `sha256::Midstate` [#3010](https://github.com/rust-bitcoin/rust-bitcoin/pull/3010) +* Remove midstate from the `GeneralHash` and `HashEngine` traits [#3009](https://github.com/rust-bitcoin/rust-bitcoin/pull/3009) +* Add additional `HashEngine` types [#2988](https://github.com/rust-bitcoin/rust-bitcoin/pull/2988) +* Remove `to`/`from`/`as_raw_hash` functions [#2981](https://github.com/rust-bitcoin/rust-bitcoin/pull/2981) +* Split `Hash` trait into `GeneralHash` and `Hash` [#2910](https://github.com/rust-bitcoin/rust-bitcoin/pull/2910) +* Remove `all_zeros` and constify constructors [#2877](https://github.com/rust-bitcoin/rust-bitcoin/pull/2877) +* Add inherent functions to hashes (reduces need to import `Hash`) [#2852](https://github.com/rust-bitcoin/rust-bitcoin/pull/2852) +* Add HKDF support [#2644](https://github.com/rust-bitcoin/rust-bitcoin/pull/2644) +* Bump MSRV to Rust version 1.63.0 [#3100](https://github.com/rust-bitcoin/rust-bitcoin/pull/3100) +* Change the default display direction of for tagged hashes to forwards [#2707](https://github.com/rust-bitcoin/rust-bitcoin/pull/2707) + + Note please this usage if you need to display backward: + +```rust + sha256t_hash_newtype! { + /// Test detailed explanation. + struct NewTypeTag = hash_str("tag"); + + /// A test hash. + #[hash_newtype(backward)] + struct NewTypeHash(_); + } +``` + +# 0.14.0 - 2024-03-21 + +* Bump MSRV to Rust version 1.56.1 [#2188](https://github.com/rust-bitcoin/rust-bitcoin/pull/2188) + +## API improvements + +* Add support for SHA384 [#2538](https://github.com/rust-bitcoin/rust-bitcoin/pull/2538) +* Make from_hex inherent for byte-like types [#2491](https://github.com/rust-bitcoin/rust-bitcoin/pull/2491) +* Add `Hash::from_bytes_iter` to construct hashes from iterators [#2272](https://github.com/rust-bitcoin/rust-bitcoin/pull/2272) +* Make some constructors `const` [#2446](https://github.com/rust-bitcoin/rust-bitcoin/pull/2446) + +## Features/dependencies changes + +* Removed `core2` dependency in favour of the new `bitcoin-io` crate [#2066](https://github.com/rust-bitcoin/rust-bitcoin/pull/2066) +* Remove "serde-std" [#2384](https://github.com/rust-bitcoin/rust-bitcoin/pull/2384) + +## Error handling improvements + +* Improve leaf errors [#2530](https://github.com/rust-bitcoin/rust-bitcoin/pull/2530) +* Implement `From` for errors [#2516](https://github.com/rust-bitcoin/rust-bitcoin/pull/2516) + +# 0.13.0 - 2023-06-29 + +The main improvement in this version is removal of the `hex` module in favour of the new +[`hex-conservative`](https://crates.io/crates/hex-conservative) crate (which we wrote). We also +bumped the Minimum Supported Rust Version across the `rust-bitcoin` ecosystem to v1.48 + +* Bump MSRV to 1.48.0 [#1729](https://github.com/rust-bitcoin/rust-bitcoin/pull/1729). +* Depend on new `hex-conservative` crate and remove `hex` module [#1883](https://github.com/rust-bitcoin/rust-bitcoin/pull/1833). +* Make `sha256t_hash_newtype!` evocative of the output [#1773](https://github.com/rust-bitcoin/rust-bitcoin/pull/1773). +* Implement computing SHA256 in const context [#1769](https://github.com/rust-bitcoin/rust-bitcoin/pull/1769). +* Add `from_bytes_ref` and `from_bytes_mut` to all hash types [#1761](https://github.com/rust-bitcoin/rust-bitcoin/pull/1761). +* Rename `crate::Error` to `crate::FromSliceError` [#1873](https://github.com/rust-bitcoin/rust-bitcoin/pull/1873). +* Add simd sha256 intrinsics for x86 machines [#1962](https://github.com/rust-bitcoin/rust-bitcoin/pull/1962). +* Introduce the "small-hash" feature for `bitcoin_hashes` [#1990](https://github.com/rust-bitcoin/rust-bitcoin/pull/1990). + +# 0.12.0 - 2023-03-05 + +0.12 is a significant release. We pulled the repository into the rust-bitcoin +repo to improve our integration testing and to get more eyes on this crate. We +began the process of replacing the hex functionality in this crate with a more +performant, dedicated crate, and otherwise cleaning up the API as we look forward +to 1.0. + +* [Remove `FromHex` implementation](https://github.com/rust-bitcoin/rust-bitcoin/pull/1565/commits/a308e1e2ea5c6ae419d961b8da71cc8a35a92715) +from all hashes and implement `FromStr` instead. +* Move crate from [original repo](https://github.com/rust-bitcoin/bitcoin_hashes) to the +`rust-bitcoin` repository. Commit history was lost during move, for commit history see the original +repository. Tip of bitcoin_hashes:master at time of import: 54c16249e06cc6b7870c7fc07d90f489d82647c7 +* [Remove `Deref` impls for all hashes](https://github.com/rust-bitcoin/rust-bitcoin/pull/1450) +* [Add `AsRef` impls for all hashes from fixed-size arrays](https://github.com/rust-bitcoin/rust-bitcoin/pull/1593) +* [Add the `sha512_256` hash](https://github.com/rust-bitcoin/rust-bitcoin/pull/1413) +* [Remove the `ToHex` trait in favor of `DisplayHex` and `fmt::Display`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1531) +* [Remove the now-unused `HexWriter` object](https://github.com/rust-bitcoin/rust-bitcoin/pull/1572) +* [nostd: `alloc` feature no longer enables `core2`](https://github.com/rust-bitcoin/rust-bitcoin/pull/1612) +* [Rewrite `hash_newtype` macro with new syntax](https://github.com/rust-bitcoin/rust-bitcoin/pull/1659) +* [Rename `Hash::Inner` to `Hash::Bytes`, 'Hash::*_inner` and several related conversion methods](https://github.com/rust-bitcoin/rust-bitcoin/pull/1577) + + +# 0.11.0 - 2022-06-25 + +The major change in this version is the increase of the Minimum Supported Rust Version (MSRV) from +1.29 to 1.41.1. This is a big change because it introduces Rust Edition 2018 to the codebase along +with all the benefits that brings. We also did a bunch of optimisations to speed up encoding and +decoding hex strings. + +## Breaking changes + +* [Enable edition 2018 and bump MSRV to Rust 1.41.1](https://github.com/rust-bitcoin/bitcoin_hashes/pull/136) + +## New features/APIs + +* [Add `all_zeros` to `Hash` trait](https://github.com/rust-bitcoin/bitcoin_hashes/pull/148) +* [Implement `Write` on `HmacEngine`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/133) +* [Introduce `HexWriter`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/156), makes serialising hex faster +* [Implement `Read` on `HexIterator`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/135), makes deserialising hex faster + +## Other improvements + +* Use `rotate_left` [instead of custom macro](https://github.com/rust-bitcoin/bitcoin_hashes/pull/162) +* [Enable clippy on CI](https://github.com/rust-bitcoin/bitcoin_hashes/pull/152) +* Various docs fixes +* [Improve feature test coverage](https://github.com/rust-bitcoin/bitcoin_hashes/pull/147) +* [Add a disabled `rustfmt.toml`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/141) to improve interaction with auto-formatting in editors + + +# 0.10.0 - 2021-07-05 + +* Increase `core2` to released version of 0.3.0 + +# 0.9.7 - 2021-06-17 + +* Introduce `alloc` feature and `core2` dependency for nostd support (this feature has MSRV of 1.36 rather than 1.29) + +# 0.9.6 - 2021-05-03 + +* Re-export `core` as `_export::_core`. This resolves an issue when calling several exported macros with the `std` feature. + +# 0.9.5 - 2021-04-28 + +* Add [`#[repr(transparent)]` to all newtype wrappers](https://github.com/rust-bitcoin/bitcoin_hashes/pull/108/) +* Add [missing `#derive`s](https://github.com/rust-bitcoin/bitcoin_hashes/pull/110/) +* Replace `fuzztarget` feature with [use of `cfg(fuzzing)`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/111/) +* Use [`core` rather than `std`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/118/) and [fix `no_std` compilation](https://github.com/rust-bitcoin/bitcoin_hashes/pull/122/) + +Note that we have stopped re-exporting the `core` crate when compiling without `std`. This is technically a breaking change but it is hard to imagine what user might be affected. + +# 0.9.4 - 2020-10-23 + +* Add `Hmac::from_inner_engines` + +# 0.9.3 - 2020-10-19 + +* More serde macro fixes + +# 0.9.2 - 2020-10-18 + +* Fix rustc 1.29.0 downstream issues with serde macros + +# 0.9.2 - 2020-10-16 + +* Fix visibility issue with serde macros + +# 0.9.1 - 2020-10-07 + +* Add `FromStr` impl to `sha256t::Hash` +* Fix `Hash::engine()` implementation for hash newtypes +* Add `sha256t_hash_newtype!` macro for creating tagged hashes + +# 0.9.0 - 2020-08-27 + +* **Update MSRV to 1.29.0** + +# 0.8.0 - 2020-08-26 + +* Add `as_inner` method to `Hash` trait +* Add `n_bytes_hashed` to `HashEngine` trait + +# 0.7.6 - 2020-04-05 + +* Support hash newtypes with reversed hex serialization. + +# 0.7.5 - 2020-04-02 + +* Add `sha256t` module for SHA-256-based tagged hashes. +* Add `FromStr` for hash newtypes. +* Add `from_hash` for hash newtypes. + +# 0.7.3 - 2019-12-18 + +* Add `as_hash(&self) -> ` method to hash newtypes. + +# 0.7.2 - 2019-11-29 + +* Make the inner variable of `sha256::Midstat` public +* Drop the `byteorder` dependency in favor of manual endianness implementations +(later this will be in stdlib so we can drop even that) +* Fix the `hash_newtype` macro, which did not compile before + +# 0.7.1 - 2019-08-14 + +* Add hash_newtype macro that allows third parties to create newtype structs. + +# 0.7.0 - 2019-07-19 + +* Add `hex::Error` type for errors generated by the `hex` module. + +# 0.6.0 - 2019-07-10 + +* Add `no_std` support, rearrange traits to not depend on `io::Write` + +# 0.5.0 - 2019-06-28 + +* Fix panic when parsing hashes that contain multibyte characters +* Add `FromStr` to all hashes which hex-parses them + +# 0.4.0 - 2019-06-23 + +* [Add `from_inner` method](https://github.com/rust-bitcoin/bitcoin_hashes/pull/20) to all hashes +* [Update `FromHex` trait](https://github.com/rust-bitcoin/bitcoin_hashes/pull/40) to require `from_byte_iter` method rather than `from_hex` be implemented +* Make `Hmac` midstate [an actual HMAC midstate](https://github.com/rust-bitcoin/bitcoin_hashes/pull/43) +* Allow `Display` [of truncated hashes](https://github.com/rust-bitcoin/bitcoin_hashes/pull/9) +* Require [using a constructor for `HexIterator`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/44) and then [clean up the internals](https://github.com/rust-bitcoin/bitcoin_hashes/pull/47) +* [Strongly type `sha256::Midstate`](https://github.com/rust-bitcoin/bitcoin_hashes/pull/39) to allow independent serialization +* Add [siphash24 module](https://github.com/rust-bitcoin/bitcoin_hashes/pull/46) + +# 0.3.2 - 2019-03-20 + +* Implement the `FromHex` trait on [many more types](https://github.com/rust-bitcoin/bitcoin_hashes/pull/38) + +# 0.3.1 - 2019-03-04 + +* [Fix serde serialization](https://github.com/rust-bitcoin/bitcoin_hashes/pull/36) + +# 0.3.0 - 2019-01-23 + +* Bump minimum required rustc version to 1.22.0 +* Fixed serde deserialization into owned string that previously caused panics + when doing round-trip (de)serialization +* `HashEngine::block_size()` and `Hash::len()` are now associated constants + `HashEngine::BLOCK_SIZE` and `Hash::LEN` +* Removed `block_size()` method from `Hash` trait. It is still available as + `::Engine::BLOCK_SIZE` + +# 0.2.0 - 2019-01-15 + +* Add a constant-time comparison function +* Simplify `io::Write::write` implementations by having them do only partial writes +* Add fuzzing support +* Allow `Hash`es to be borrowed as `[u8]` +* Replace public `Hash` inners with `into_inner` method + +# 0.1.0 - 2018-12-08 + +* Initial release diff --git a/hashes/Cargo.toml b/hashes/Cargo.toml new file mode 100644 index 000000000..358a44d74 --- /dev/null +++ b/hashes/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "bitcoin_hashes" +version = "0.18.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +documentation = "https://docs.rs/bitcoin_hashes/" +description = "Hash functions used by the rust-bitcoin eccosystem" +categories = ["algorithms", "cryptography", "no-std"] +keywords = [ "crypto", "bitcoin", "hash", "digest" ] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc", "hex?/std"] +alloc = ["hex?/alloc"] +serde = ["dep:serde", "hex"] +# Smaller (but slower) implementation of sha256, sha512 and ripemd160 +small-hash = [] + +[dependencies] +internals = { package = "bitcoin-internals", path = "../internals", version = "0.4.1" } +encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "=1.0.0-rc.2", default-features = false } + +hex = { package = "hex-conservative", version = "0.3.0", default-features = false, optional = true } +serde = { version = "1.0.195", default-features = false, optional = true } + +[dev-dependencies] +serde_test = "1.0.19" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(hashes_fuzz)', 'cfg(rust_v_1_64)' ] } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/hashes/README.md b/hashes/README.md new file mode 100644 index 000000000..3f6dfd8dd --- /dev/null +++ b/hashes/README.md @@ -0,0 +1,29 @@ +# Bitcoin Hashes Library + +This is a simple, no-dependency library which implements the hash functions +needed by Bitcoin. These are SHA1, SHA256, SHA256d, SHA512, and RIPEMD160. As an +ancillary thing, it exposes hexadecimal serialization and deserialization, +since these are needed to display hashes anyway. + +[Documentation](https://docs.rs/bitcoin_hashes/) + +## Contributions + +Contributions are welcome, including additional hash function implementations. + +### Githooks + +To assist devs in catching errors _before_ running CI we provide some githooks. If you do not +already have locally configured githooks you can use the ones in this repository by running, in the +root directory of the repository: + +```bash +git config --local core.hooksPath githooks/ +``` + +Alternatively add symlinks in your `.git/hooks` directory to any of the githooks we provide. + +### Running Benchmarks + +We use a custom Rust compiler configuration conditional to guard the benchmark code. To run the +benchmarks use: `RUSTFLAGS='--cfg=bench' cargo +nightly bench`. diff --git a/hashes/contrib/extra_lints.sh b/hashes/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/hashes/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/hashes/contrib/sanitizer.sh b/hashes/contrib/sanitizer.sh new file mode 100755 index 000000000..495e404c1 --- /dev/null +++ b/hashes/contrib/sanitizer.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# +# Run the Address/Memory Sanitizer tests. + +set -euox pipefail + +# Run the sanitizer with these features. +FEATURES="std serde" + +cargo clean +CC='clang -fsanitize=address -fno-omit-frame-pointer' \ + RUSTFLAGS='-Zsanitizer=address -Clinker=clang -Cforce-frame-pointers=yes' \ + ASAN_OPTIONS='detect_leaks=1 detect_invalid_pointer_pairs=1 detect_stack_use_after_return=1' \ + cargo test --lib --no-default-features --features="$FEATURES" -Zbuild-std --target x86_64-unknown-linux-gnu + +# There is currently a bug in the MemorySanitizer (MSAN) - disable the job for now. +# +# cargo clean +# CC='clang -fsanitize=memory -fno-omit-frame-pointer' \ + # RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins -Cforce-frame-pointers=yes' \ + # cargo test --lib --no-default-features --features="$FEATURES" -Zbuild-std --target x86_64-unknown-linux-gnu diff --git a/hashes/contrib/test_vars.sh b/hashes/contrib/test_vars.sh new file mode 100644 index 000000000..efcd3dcfc --- /dev/null +++ b/hashes/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="serde small-hash" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc serde small-hash" + +# Run these examples. +EXAMPLES="" diff --git a/hashes/contrib/wasm.sh b/hashes/contrib/wasm.sh new file mode 100755 index 000000000..c7b5c8b7c --- /dev/null +++ b/hashes/contrib/wasm.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# +# Run the WASM tests. + +set -euox pipefail + +clang --version && + CARGO_TARGET_DIR=wasm cargo install --force wasm-pack && + printf '\n[target.wasm32-unknown-unknown.dev-dependencies]\nwasm-bindgen-test = "0.3"\n' >> Cargo.toml && + printf '\n[lib]\ncrate-type = ["cdylib", "rlib"]\n' >> Cargo.toml && + CC=clang-9 wasm-pack build; +# wasm-pack test isn't currently working. +# CC=clang-9 wasm-pack test --node; diff --git a/hashes/embedded/Cargo.toml b/hashes/embedded/Cargo.toml new file mode 100644 index 000000000..ef1466853 --- /dev/null +++ b/hashes/embedded/Cargo.toml @@ -0,0 +1,38 @@ +[package] +authors = ["Riccardo Casatta "] +edition = "2021" +readme = "README.md" +name = "embedded" +version = "0.1.0" + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[features] +alloc = ["alloc-cortex-m", "bitcoin_hashes/alloc"] +hex = ["bitcoin_hashes/hex"] + +[dependencies] +cortex-m-rt = "0.6.10" +cortex-m-semihosting = "0.3.3" +panic-halt = "0.2.0" +alloc-cortex-m = { version = "0.4.1", optional = true } +bitcoin_hashes = { path="../", default-features = false, features = [] } +bitcoin-io = { path = "../../io", default_features = false, features = ["hashes"] } + +[lints.clippy] +use_self = "warn" + +[[bin]] +name = "embedded" +test = false +bench = false + +[profile.release] +codegen-units = 1 # better optimizations +debug = true # symbols are nice and they don't increase the size on Flash +lto = true # better optimizations + +[patch.crates-io.bitcoin_hashes] +path = "../../hashes" diff --git a/hashes/embedded/README.md b/hashes/embedded/README.md new file mode 100644 index 000000000..60e4e1a11 --- /dev/null +++ b/hashes/embedded/README.md @@ -0,0 +1,30 @@ +# Running + +To run the embedded test, first prepare your environment: + +```shell +sudo ./scripts/install-deps +rustup +nightly target add thumbv7m-none-eabi +``` + +Then: + +```shell +source ./scripts/env.sh && cargo +nightly run --target thumbv7m-none-eabi +``` + +Output should be something like: + +```text +hash:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad hash_check:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad +hash:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad hash_check:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad +``` + +## Cleanup + +After sourcing `scripts/env.sh` and _before_ building again using another target +you'll want to unset `RUSTFLAGS` otherwise you'll get linker errors. + +```shell +unset RUSTFLAGS +``` diff --git a/hashes/embedded/memory.x b/hashes/embedded/memory.x new file mode 100644 index 000000000..95de161be --- /dev/null +++ b/hashes/embedded/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 64K +} diff --git a/hashes/embedded/scripts/env.sh b/hashes/embedded/scripts/env.sh new file mode 100644 index 000000000..798c4af83 --- /dev/null +++ b/hashes/embedded/scripts/env.sh @@ -0,0 +1,4 @@ +# we don't want shebangs in env.sh, disable shellcheck warning +# shellcheck disable=SC2148 +export RUSTFLAGS="-C link-arg=-Tlink.x" +export CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER="qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -nographic -semihosting-config enable=on,target=native -kernel" diff --git a/hashes/embedded/scripts/install-deps b/hashes/embedded/scripts/install-deps new file mode 100755 index 000000000..49cf20442 --- /dev/null +++ b/hashes/embedded/scripts/install-deps @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +apt install gcc-arm-none-eabi qemu-system-arm gdb-multiarch diff --git a/hashes/embedded/src/main.rs b/hashes/embedded/src/main.rs new file mode 100644 index 000000000..ca36383cc --- /dev/null +++ b/hashes/embedded/src/main.rs @@ -0,0 +1,77 @@ +#![cfg_attr(feature = "alloc", feature(alloc_error_handler))] +#![no_std] +#![no_main] + +#[macro_use] +extern crate bitcoin_hashes; + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "alloc")] +use alloc::string::ToString; + +#[cfg(feature = "alloc")] +use alloc_cortex_m::CortexMHeap; +use bitcoin_hashes::{sha256, HashEngine}; +use bitcoin_io::Write; +use cortex_m_rt::entry; +use cortex_m_semihosting::debug; +#[cfg(feature = "hex")] +use cortex_m_semihosting::hprintln; +use panic_halt as _; + +hash_newtype! { + struct TestType(sha256::Hash); +} + +#[cfg(feature = "hex")] +bitcoin_hashes::impl_hex_for_newtype!(TestType); +#[cfg(not(feature = "hex"))] +bitcoin_hashes::impl_debug_only_for_newtype!(TestType); + +// this is the allocator the application will use +#[cfg(feature = "alloc")] +#[global_allocator] +static ALLOCATOR: CortexMHeap = CortexMHeap::empty(); + +#[cfg(feature = "alloc")] +const HEAP_SIZE: usize = 1024; // in bytes + +#[entry] +fn main() -> ! { + #[cfg(feature = "alloc")] + unsafe { + ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) + } + + let mut engine = sha256::Hash::engine(); + engine.write_all(b"abc").unwrap(); + #[cfg(feature = "hex")] + check_result(engine); + + let mut engine = sha256::Hash::engine(); + engine.input(b"abc"); + #[cfg(feature = "hex")] + check_result(engine); + + debug::exit(debug::EXIT_SUCCESS); + loop {} +} + +#[cfg(feature = "hex")] +fn check_result(engine: sha256::HashEngine) { + let hash = TestType(sha256::Hash::from_engine(engine)); + + let hash_check = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" + .parse::() + .unwrap(); + hprintln!("hash:{} hash_check:{}", hash, hash_check).unwrap(); + if hash != hash_check { + debug::exit(debug::EXIT_FAILURE); + } + + #[cfg(feature = "alloc")] + if hash.to_string() != hash_check.to_string() { + debug::exit(debug::EXIT_FAILURE); + } +} diff --git a/hashes/src/cmp.rs b/hashes/src/cmp.rs new file mode 100644 index 000000000..3eeded7a8 --- /dev/null +++ b/hashes/src/cmp.rs @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Useful comparison functions. + +/// Compares two slices for equality in fixed time. Panics if the slices are of non-equal length. +/// +/// This works by XOR'ing each byte of the two inputs together and keeping an OR counter of the +/// results. +/// +/// Instead of doing fancy bit twiddling to try to outsmart the compiler and prevent early exits, +/// which is not guaranteed to remain stable as compilers get ever smarter, we take the hit of +/// writing each intermediate value to memory with a volatile write and then re-reading it with a +/// volatile read. This should remain stable across compiler upgrades, but is much slower. +/// +/// As of rust 1.31.0 disassembly looks completely within reason for this, see +/// . +pub fn fixed_time_eq(a: &[u8], b: &[u8]) -> bool { + #[cfg(hashes_fuzz)] + { + // Fuzzers want to break memcmp calls into separate comparisons for coverage monitoring, + // so we avoid our fancy fixed-time comparison below for fuzzers. + a == b + } + #[cfg(not(hashes_fuzz))] + { + assert!(a.len() == b.len()); + let count = a.len(); + let lhs = &a[..count]; + let rhs = &b[..count]; + + let mut r: u8 = 0; + for i in 0..count { + let mut rs = unsafe { core::ptr::read_volatile(&r) }; + rs |= lhs[i] ^ rhs[i]; + unsafe { + core::ptr::write_volatile(&mut r, rs); + } + } + { + let mut t = unsafe { core::ptr::read_volatile(&r) }; + t |= t >> 4; + unsafe { + core::ptr::write_volatile(&mut r, t); + } + } + { + let mut t = unsafe { core::ptr::read_volatile(&r) }; + t |= t >> 2; + unsafe { + core::ptr::write_volatile(&mut r, t); + } + } + { + let mut t = unsafe { core::ptr::read_volatile(&r) }; + t |= t >> 1; + unsafe { + core::ptr::write_volatile(&mut r, t); + } + } + unsafe { (::core::ptr::read_volatile(&r) & 1) == 0 } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn eq_test() { + assert!(fixed_time_eq(&[0b00000000], &[0b00000000])); + assert!(fixed_time_eq(&[0b00000001], &[0b00000001])); + assert!(fixed_time_eq(&[0b00000010], &[0b00000010])); + assert!(fixed_time_eq(&[0b00000100], &[0b00000100])); + assert!(fixed_time_eq(&[0b00001000], &[0b00001000])); + assert!(fixed_time_eq(&[0b00010000], &[0b00010000])); + assert!(fixed_time_eq(&[0b00100000], &[0b00100000])); + assert!(fixed_time_eq(&[0b01000000], &[0b01000000])); + assert!(fixed_time_eq(&[0b10000000], &[0b10000000])); + assert!(fixed_time_eq(&[0b11111111], &[0b11111111])); + + assert!(!fixed_time_eq(&[0b00000001], &[0b00000000])); + assert!(!fixed_time_eq(&[0b00000001], &[0b11111111])); + assert!(!fixed_time_eq(&[0b00000010], &[0b00000000])); + assert!(!fixed_time_eq(&[0b00000010], &[0b11111111])); + assert!(!fixed_time_eq(&[0b00000100], &[0b00000000])); + assert!(!fixed_time_eq(&[0b00000100], &[0b11111111])); + assert!(!fixed_time_eq(&[0b00001000], &[0b00000000])); + assert!(!fixed_time_eq(&[0b00001000], &[0b11111111])); + assert!(!fixed_time_eq(&[0b00010000], &[0b00000000])); + assert!(!fixed_time_eq(&[0b00010000], &[0b11111111])); + assert!(!fixed_time_eq(&[0b00100000], &[0b00000000])); + assert!(!fixed_time_eq(&[0b00100000], &[0b11111111])); + assert!(!fixed_time_eq(&[0b01000000], &[0b00000000])); + assert!(!fixed_time_eq(&[0b01000000], &[0b11111111])); + assert!(!fixed_time_eq(&[0b10000000], &[0b00000000])); + assert!(!fixed_time_eq(&[0b10000000], &[0b11111111])); + + assert!(fixed_time_eq(&[0b00000000, 0b00000000], &[0b00000000, 0b00000000])); + assert!(!fixed_time_eq(&[0b00000001, 0b00000000], &[0b00000000, 0b00000000])); + assert!(!fixed_time_eq(&[0b00000000, 0b00000001], &[0b00000000, 0b00000000])); + assert!(!fixed_time_eq(&[0b00000000, 0b00000000], &[0b00000001, 0b00000000])); + assert!(!fixed_time_eq(&[0b00000000, 0b00000000], &[0b00000001, 0b00000001])); + } +} diff --git a/hashes/src/hash160/mod.rs b/hashes/src/hash160/mod.rs new file mode 100644 index 000000000..499c66667 --- /dev/null +++ b/hashes/src/hash160/mod.rs @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: CC0-1.0 +// +// This module is largely copied from the rust-crypto ripemd.rs file; +// while rust-crypto is licensed under Apache, that file specifically +// was written entirely by Andrew Poelstra, who is re-licensing its +// contents here as CC0. + +//! HASH160 (SHA256 then RIPEMD160) implementation. + +use crate::{ripemd160, sha256}; + +crate::internal_macros::general_hash_type! { + 160, + false, + "Output of the Bitcoin HASH160 hash function. (RIPEMD160(SHA256))" +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + pub fn from_engine(e: HashEngine) -> Self { + let sha2 = sha256::Hash::from_engine(e.0); + let rmd = ripemd160::Hash::hash(sha2.as_byte_array()); + + let mut ret = [0; 20]; + ret.copy_from_slice(rmd.as_byte_array()); + Self(ret) + } +} + +/// Engine to compute HASH160 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine(sha256::HashEngine); + +impl HashEngine { + /// Constructs a new HASH160 hash engine. + pub const fn new() -> Self { Self(sha256::HashEngine::new()) } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 20]; + const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; + + fn input(&mut self, data: &[u8]) { self.0.input(data) } + fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn test() { + use alloc::string::ToString; + + use super::Hash; + use crate::{hash160, HashEngine}; + + #[derive(Clone)] + struct Test { + input: [u8; 65], + output: [u8; 20], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Uncompressed pubkey obtained from Bitcoin key; data from validateaddress + Test { + input: [ + 0x04, 0xa1, 0x49, 0xd7, 0x6c, 0x5d, 0xe2, 0x7a, 0x2d, + 0xdb, 0xfa, 0xa1, 0x24, 0x6c, 0x4a, 0xdc, 0xd2, 0xb6, + 0xf7, 0xaa, 0x29, 0x54, 0xc2, 0xe2, 0x53, 0x03, 0xf5, + 0x51, 0x54, 0xca, 0xad, 0x91, 0x52, 0xe4, 0xf7, 0xe4, + 0xb8, 0x5d, 0xf1, 0x69, 0xc1, 0x8a, 0x3c, 0x69, 0x7f, + 0xbb, 0x2d, 0xc4, 0xec, 0xef, 0x94, 0xac, 0x55, 0xfe, + 0x81, 0x64, 0xcc, 0xf9, 0x82, 0xa1, 0x38, 0x69, 0x1a, + 0x55, 0x19, + ], + output: [ + 0xda, 0x0b, 0x34, 0x52, 0xb0, 0x6f, 0xe3, 0x41, + 0x62, 0x6a, 0xd0, 0x94, 0x9c, 0x18, 0x3f, 0xbd, + 0xa5, 0x67, 0x68, 0x26, + ], + output_str: "da0b3452b06fe341626ad0949c183fbda5676826", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = hash160::Hash::hash(&test.input[..]); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = hash160::Hash::engine(); + for ch in test.input { + engine.input(&[ch]); + } + let manual_hash = Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } + } + + #[test] + #[cfg(feature = "serde")] + fn ripemd_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + use crate::hash160; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 20] = [ + 0x13, 0x20, 0x72, 0xdf, + 0x69, 0x09, 0x33, 0x83, + 0x5e, 0xb8, 0xb6, 0xad, + 0x0b, 0x77, 0xe7, 0xb6, + 0xf1, 0x4a, 0xca, 0xd7, + ]; + + let hash = hash160::Hash::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]); + } +} diff --git a/hashes/src/hkdf/mod.rs b/hashes/src/hkdf/mod.rs new file mode 100644 index 000000000..8d852d1a3 --- /dev/null +++ b/hashes/src/hkdf/mod.rs @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! HMAC-based Extract-and-Expand Key Derivation Function (HKDF). +//! +//! Implementation based on RFC5869, but the interface is scoped +//! to BIP-0324's requirements. + +#[cfg(feature = "alloc")] +use alloc::vec; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +use core::fmt; + +use crate::{HashEngine, Hmac, HmacEngine, IsByteArray}; + +/// Output keying material max length multiple. +const MAX_OUTPUT_BLOCKS: usize = 255; + +/// Size of output exceeds maximum length allowed. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct MaxLengthError { + max: usize, +} + +impl fmt::Display for MaxLengthError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "exceeds {} byte max output material limit", self.max) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for MaxLengthError {} + +/// HMAC-based Extract-and-Expand Key Derivation Function (HKDF). +#[derive(Copy, Clone)] +pub struct Hkdf { + /// Pseudorandom key based on the extract step. + prk: Hmac, +} + +impl Hkdf +where + T: Default, +{ + /// Initializes a HKDF by performing the extract step. + pub fn new(salt: &[u8], ikm: &[u8]) -> Self { + let mut engine: HmacEngine = HmacEngine::new(salt); + engine.input(ikm); + Self { prk: engine.finalize() } + } + + /// Expand the key to generate output key material in okm. + /// + /// Expand may be called multiple times to derive multiple keys, + /// but the info must be independent from the ikm for security. + pub fn expand(&self, info: &[u8], okm: &mut [u8]) -> Result<(), MaxLengthError> { + // Length of output keying material in bytes must be less than 255 * hash length. + if okm.len() > (MAX_OUTPUT_BLOCKS * T::Bytes::LEN) { + return Err(MaxLengthError { max: MAX_OUTPUT_BLOCKS * T::Bytes::LEN }); + } + + // Counter starts at "1" based on RFC5869 spec and is committed to in the hash. + let mut counter = 1u8; + // Ceiling calculation for the total number of blocks (iterations) required for the expand. + let total_blocks = okm.len().div_ceil(T::Bytes::LEN); + + while counter <= total_blocks as u8 { + let mut engine: HmacEngine = HmacEngine::new(self.prk.as_ref()); + + // First block does not have a previous block, + // all other blocks include last block in the HMAC input. + if counter != 1u8 { + let previous_start_index = (counter as usize - 2) * T::Bytes::LEN; + let previous_end_index = (counter as usize - 1) * T::Bytes::LEN; + engine.input(&okm[previous_start_index..previous_end_index]); + } + engine.input(info); + engine.input(&[counter]); + + let t = engine.finalize(); + let start_index = (counter as usize - 1) * T::Bytes::LEN; + // Last block might not take full hash length. + let end_index = if counter == (total_blocks as u8) { + okm.len() + } else { + counter as usize * T::Bytes::LEN + }; + + okm[start_index..end_index].copy_from_slice(&t.as_ref()[0..(end_index - start_index)]); + + counter += 1; + } + + Ok(()) + } + + /// Expand the key to specified length. + /// + /// Expand may be called multiple times to derive multiple keys, + /// but the info must be independent from the ikm for security. + #[cfg(feature = "alloc")] + pub fn expand_to_len(&self, info: &[u8], len: usize) -> Result, MaxLengthError> { + let mut okm = vec![0u8; len]; + self.expand(info, &mut okm)?; + Ok(okm) + } +} + +impl fmt::Debug for Hkdf { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use crate::{sha256t, sha256t_tag}; + + struct Fingerprint([u8; 8]); // Print 16 hex characters as a fingerprint. + + impl fmt::Debug for Fingerprint { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { crate::debug_hex(&self.0, f) } + } + + sha256t_tag! { + pub struct Tag = hash_str("bitcoin_hashes1DEBUG"); + } + + let hash = sha256t::Hash::::hash(self.prk.as_ref()); + let fingerprint = Fingerprint(core::array::from_fn(|i| hash.as_byte_array()[i])); + f.debug_tuple("Hkdf").field(&format_args!("#{:?}", fingerprint)).finish() + } +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +mod tests { + use hex::prelude::{DisplayHex, FromHex}; + + use super::*; + use crate::sha256; + + #[test] + fn rfc5869_basic() { + let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap(); + let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); + + let hkdf = Hkdf::::new(&salt, &ikm); + let mut okm = [0u8; 42]; + hkdf.expand(&info, &mut okm).unwrap(); + + assert_eq!( + okm.to_lower_hex_string(), + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" + ); + } + + #[test] + fn rfc5869_longer_inputs_outputs() { + let salt = Vec::from_hex( + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + ).unwrap(); + let ikm = Vec::from_hex( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" + ).unwrap(); + let info = Vec::from_hex( + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" + ).unwrap(); + + let hkdf = Hkdf::::new(&salt, &ikm); + let mut okm = [0u8; 82]; + hkdf.expand(&info, &mut okm).unwrap(); + + assert_eq!( + okm.to_lower_hex_string(), + "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87" + ); + } + + #[test] + fn too_long_okm() { + let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap(); + let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); + + let hkdf = Hkdf::::new(&salt, &ikm); + let mut okm = [0u8; 256 * 32]; + let e = hkdf.expand(&info, &mut okm); + + assert!(e.is_err()); + } + + #[test] + fn short_okm() { + let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap(); + let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); + + let hkdf = Hkdf::::new(&salt, &ikm); + let mut okm = [0u8; 1]; + hkdf.expand(&info, &mut okm).unwrap(); + + assert_eq!(okm.to_lower_hex_string(), "3c"); + } + + #[test] + fn alloc_wrapper() { + let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap(); + let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + let info = Vec::from_hex("f0f1f2f3f4f5f6f7f8f9").unwrap(); + + let hkdf = Hkdf::::new(&salt, &ikm); + let okm = hkdf.expand_to_len(&info, 42).unwrap(); + + assert_eq!( + okm.to_lower_hex_string(), + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" + ); + } + + #[test] + fn debug() { + let salt = Vec::from_hex("000102030405060708090a0b0c").unwrap(); + let ikm = Vec::from_hex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + + let hkdf = Hkdf::::new(&salt, &ikm); + let debug = alloc::format!("{:?}", hkdf); + + assert_eq!(debug, "Hkdf(#ec7bd36ab2ed4045)"); + } +} diff --git a/hashes/src/hmac/mod.rs b/hashes/src/hmac/mod.rs new file mode 100644 index 000000000..b1939fd6a --- /dev/null +++ b/hashes/src/hmac/mod.rs @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: CC0-1.0 + +// This module is largely copied from the rust-crypto ripemd.rs file; +// while rust-crypto is licensed under Apache, that file specifically +// was written entirely by Andrew Poelstra, who is re-licensing its +// contents here as CC0. + +//! Hash-based Message Authentication Code (HMAC). + +use core::{convert, fmt, str}; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use crate::{Hash, HashEngine}; + +/// A hash computed from a RFC 2104 HMAC. Parameterized by the underlying hash function. +#[derive(Copy, Clone, PartialOrd, Ord, Hash)] +#[repr(transparent)] +#[allow(clippy::derived_hash_with_manual_eq)] +pub struct Hmac(T); + +impl str::FromStr for Hmac { + type Err = ::Err; + fn from_str(s: &str) -> Result { Ok(Self(str::FromStr::from_str(s)?)) } +} + +impl PartialEq for Hmac { + fn eq(&self, other: &Self) -> bool { crate::cmp::fixed_time_eq(self.as_ref(), other.as_ref()) } +} + +impl Eq for Hmac {} + +/// Pair of underlying hash engines, used for the inner and outer hash of HMAC. +#[derive(Debug, Clone)] +pub struct HmacEngine { + iengine: T, + oengine: T, +} + +impl HmacEngine { + /// Constructs a new keyed HMAC engine from `key`. + /// + /// We only support underlying hashes whose block sizes are ≤ 128 bytes. + /// + /// # Panics + /// + /// Larger hashes will result in a panic. + pub fn new(key: &[u8]) -> Self + where + T: Default, + { + debug_assert!(T::BLOCK_SIZE <= 128); + + let mut ipad = [0x36u8; 128]; + let mut opad = [0x5cu8; 128]; + let mut ret = Self { iengine: T::default(), oengine: T::default() }; + + if key.len() > T::BLOCK_SIZE { + let mut engine = T::default(); + engine.input(key); + let hash = engine.finalize(); + + for (b_i, b_h) in ipad.iter_mut().zip(hash.as_ref()) { + *b_i ^= *b_h; + } + for (b_o, b_h) in opad.iter_mut().zip(hash.as_ref()) { + *b_o ^= *b_h; + } + } else { + for (b_i, b_h) in ipad.iter_mut().zip(key) { + *b_i ^= *b_h; + } + for (b_o, b_h) in opad.iter_mut().zip(key) { + *b_o ^= *b_h; + } + }; + + ret.iengine.input(&ipad[..T::BLOCK_SIZE]); + ret.oengine.input(&opad[..T::BLOCK_SIZE]); + ret + } + + /// A special constructor giving direct access to the underlying "inner" and "outer" engines. + pub fn from_inner_engines(iengine: T, oengine: T) -> Self { + Self { iengine, oengine } + } +} + +impl HashEngine for HmacEngine { + type Hash = Hmac; + type Bytes = T::Bytes; + const BLOCK_SIZE: usize = T::BLOCK_SIZE; + + fn n_bytes_hashed(&self) -> u64 { self.iengine.n_bytes_hashed() } + fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) } + fn finalize(mut self) -> Self::Hash { + let ihash = self.iengine.finalize(); + self.oengine.input(ihash.as_ref()); + Hmac(self.oengine.finalize()) + } +} + +impl fmt::Debug for Hmac { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } +} + +impl fmt::Display for Hmac { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } +} + +impl fmt::LowerHex for Hmac { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } +} + +impl convert::AsRef<[u8]> for Hmac { + // Calling as_byte_array is more reliable + fn as_ref(&self) -> &[u8] { self.0.as_byte_array().as_ref() } +} + +impl Hash for Hmac { + type Bytes = T::Bytes; + + fn from_byte_array(bytes: T::Bytes) -> Self { Self(T::from_byte_array(bytes)) } + + fn to_byte_array(self) -> Self::Bytes { self.0.to_byte_array() } + + fn as_byte_array(&self) -> &Self::Bytes { self.0.as_byte_array() } +} + +#[cfg(feature = "serde")] +impl Serialize for Hmac { + fn serialize(&self, s: S) -> Result { + Serialize::serialize(&self.0, s) + } +} + +#[cfg(feature = "serde")] +impl<'de, T: Hash + Deserialize<'de>> Deserialize<'de> for Hmac { + fn deserialize>(d: D) -> Result { + let bytes = Deserialize::deserialize(d)?; + Ok(Self(bytes)) + } +} + +#[cfg(feature = "std")] +crate::internal_macros::impl_write!( + HmacEngine, + |us: &mut HmacEngine, buf| { + us.input(buf); + Ok(buf.len()) + }, + |_us| { Ok(()) }, + T: crate::HashEngine +); + +#[cfg(test)] +mod tests { + #[test] + fn test() { + use crate::{sha256, Hash as _, HashEngine, HmacEngine}; + + #[derive(Clone)] + struct Test { + key: &'static [u8], + input: &'static [u8], + output: [u8; 32], + } + + #[rustfmt::skip] + let tests = [ + // Test vectors copied from libsecp256k1 + // Sadly the RFC2104 test vectors all use MD5 as their underlying hash function, + // which of course this library does not support. + Test { + key: &[ 0x0b; 20 ], + input: &[ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 ], + output: [ + 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7, + ], + }, + Test { + key: &[ 0x4a, 0x65, 0x66, 0x65 ], + input: &[ + 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, + 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, + 0x69, 0x6e, 0x67, 0x3f, + ], + output: [ + 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43, + ], + }, + Test { + key: &[ 0xaa; 20 ], + input: &[ 0xdd; 50 ], + output: [ + 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, + 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, + 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, + 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe, + ], + }, + Test { + key: &[ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19 + ], + input: &[ 0xcd; 50 ], + output: [ + 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, + 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, + 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, + 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b, + ], + }, + Test { + key: &[ 0xaa; 131 ], + input: &[ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, + 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, + 0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, + 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, + 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, + 0x20, 0x46, 0x69, 0x72, 0x73, 0x74, + ], + output: [ + 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, + 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, + 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, + 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54, + ], + }, + Test { + key: &[ 0xaa; 131 ], + input: &[ + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, + 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c, + 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, + 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, + 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, + 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, + 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, + 0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65, + 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, + 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, + 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, + 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62, + 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, + 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e, + ], + output: [ + 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, + 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, + 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, + 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2, + ], + }, + ]; + + for test in tests { + let mut engine = HmacEngine::::new(test.key); + engine.input(test.input); + let hash = engine.finalize(); + assert_eq!(hash.as_ref(), test.output); + assert_eq!(hash.to_byte_array(), test.output); + } + } + + #[test] + #[cfg(feature = "serde")] + fn hmac_sha512_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + use crate::{sha512, Hash as _, Hmac}; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 64] = [ + 0x8b, 0x41, 0xe1, 0xb7, 0x8a, 0xd1, 0x15, 0x21, + 0x11, 0x3c, 0x52, 0xff, 0x18, 0x2a, 0x1b, 0x8e, + 0x0a, 0x19, 0x57, 0x54, 0xaa, 0x52, 0x7f, 0xcd, + 0x00, 0xa4, 0x11, 0x62, 0x0b, 0x46, 0xf2, 0x0f, + 0xff, 0xfb, 0x80, 0x88, 0xcc, 0xf8, 0x54, 0x97, + 0x12, 0x1a, 0xd4, 0x49, 0x9e, 0x08, 0x45, 0xb8, + 0x76, 0xf6, 0xdd, 0x66, 0x40, 0x08, 0x8a, 0x2f, + 0x0b, 0x2d, 0x8a, 0x60, 0x0b, 0xdf, 0x4c, 0x0c, + ]; + + let hash = Hmac::::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens( + &hash.readable(), + &[Token::Str( + "8b41e1b78ad11521113c52ff182a1b8e0a195754aa527fcd00a411620b46f20f\ + fffb8088ccf85497121ad4499e0845b876f6dd6640088a2f0b2d8a600bdf4c0c", + )], + ); + } +} diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs new file mode 100644 index 000000000..1f6a8a0df --- /dev/null +++ b/hashes/src/internal_macros.rs @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Non-public macros + +/// Adds trait impls to the type called `Hash` in the current scope. +/// +/// Implements various conversion traits as well as the [`crate::Hash`] trait. +/// +/// # Parameters +/// +/// * `$bits` - the number of bits this hash type has +/// * `$reverse` - `bool` - `true` if the hash type should be displayed backwards, `false` +/// otherwise. +/// * `$gen: $gent` - the generic type(s) and trait bound(s) +/// +/// Restrictions on usage: +/// +/// * The `Hash` type in scope must provide `from_byte_array`, `to_byte_array`, and `as_byte_array` (e.g., via `hash_type_no_default!`). +macro_rules! hash_trait_impls { + ($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => { + $crate::impl_bytelike_traits!(Hash, { $bits / 8 } $(, $gen: $gent)*); + #[cfg(feature = "hex")] + $crate::impl_hex_string_traits!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*); + #[cfg(not(feature = "hex"))] + $crate::impl_debug_only!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*); + + #[cfg(feature = "serde")] + $crate::serde_impl!(Hash, { $bits / 8} $(, $gen: $gent)*); + + impl<$($gen: $gent),*> $crate::Hash for Hash<$($gen),*> { + type Bytes = [u8; $bits / 8]; + + const DISPLAY_BACKWARD: bool = $reverse; + + fn from_byte_array(bytes: Self::Bytes) -> Self { Self::from_byte_array(bytes) } + + fn to_byte_array(self) -> Self::Bytes { self.to_byte_array() } + + fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() } + } + } +} +pub(crate) use hash_trait_impls; + +/// Constructs a type called `Hash` and implements the standard general hashing interface for it. +/// +/// The created type has a single field and will have all standard derives as well as an +/// implementation of [`crate::Hash`]. +/// +/// # Parameters +/// +/// * `$bits` - the number of bits of the hash type +/// * `$reverse` - `true` if the hash should be displayed backwards, `false` otherwise +/// * `$doc` - the doc string to put on the type +/// +/// Restrictions on usage: +/// +/// * Requires a `HashEngine` type in this module implementing `Default` and `crate::HashEngine`. +macro_rules! general_hash_type { + ($bits:expr, $reverse:expr, $doc:literal) => { + /// Hashes some bytes. + pub fn hash(data: &[u8]) -> Hash { + use crate::HashEngine as _; + + let mut engine = Hash::engine(); + engine.input(data); + engine.finalize() + } + + /// Hashes all the byte slices retrieved from the iterator together. + pub fn hash_byte_chunks(byte_slices: I) -> Hash + where + B: AsRef<[u8]>, + I: IntoIterator, + { + use crate::HashEngine as _; + + let mut engine = Hash::engine(); + for slice in byte_slices { + engine.input(slice.as_ref()); + } + engine.finalize() + } + + $crate::internal_macros::hash_type_no_default!($bits, $reverse, $doc); + + impl Hash { + /// Constructs a new engine. + pub fn engine() -> HashEngine { Default::default() } + + /// Hashes some bytes. + #[allow(clippy::self_named_constructors)] // Hash is a noun and a verb. + pub fn hash(data: &[u8]) -> Self { hash(data) } + + /// Hashes all the byte slices retrieved from the iterator together. + pub fn hash_byte_chunks(byte_slices: I) -> Self + where + B: AsRef<[u8]>, + I: IntoIterator, + { + hash_byte_chunks(byte_slices) + } + } + }; +} +pub(crate) use general_hash_type; + +macro_rules! hash_type_no_default { + ($bits:expr, $reverse:expr, $doc:literal) => { + internals::transparent_newtype! { + #[doc = $doc] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Hash([u8; $bits / 8]); + + impl Hash { + /// Zero cost conversion between a fixed length byte array shared reference and + /// a shared reference to this Hash type. + pub fn from_bytes_ref(bytes: &_) -> &Self; + + /// Zero cost conversion between a fixed length byte array exclusive reference and + /// an exclusive reference to this Hash type. + pub fn from_bytes_mut(bytes: &mut _) -> &mut Self; + } + } + + impl Hash { + /// Constructs a new hash from the underlying byte array. + pub const fn from_byte_array(bytes: [u8; $bits / 8]) -> Self { Hash(bytes) } + + /// Returns the underlying byte array. + pub const fn to_byte_array(self) -> [u8; $bits / 8] { self.0 } + + /// Returns a reference to the underlying byte array. + pub const fn as_byte_array(&self) -> &[u8; $bits / 8] { &self.0 } + } + + $crate::internal_macros::hash_trait_impls!($bits, $reverse); + + $crate::internal_macros::impl_write!( + HashEngine, + |us: &mut HashEngine, buf| { + crate::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } + ); + }; +} +pub(crate) use hash_type_no_default; + +macro_rules! impl_write { + ($ty: ty, $write_fn: expr, $flush_fn: expr $(, $bounded_ty: ident : $bounds: path),*) => { + // `bitcoin_io::Write` is implemented in `bitcoin_io`. + #[cfg(feature = "std")] + impl<$($bounded_ty: $bounds),*> std::io::Write for $ty { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + $write_fn(self, buf) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + $flush_fn(self) + } + } + } +} +pub(crate) use impl_write; + +macro_rules! engine_input_impl( + () => ( + #[cfg(not(hashes_fuzz))] + fn input(&mut self, mut inp: &[u8]) { + + while !inp.is_empty() { + let buf_idx = $crate::incomplete_block_len(self); + let rem_len = ::BLOCK_SIZE - buf_idx; + let write_len = cmp::min(rem_len, inp.len()); + + self.buffer[buf_idx..buf_idx + write_len] + .copy_from_slice(&inp[..write_len]); + self.bytes_hashed += write_len as u64; + if $crate::incomplete_block_len(self) == 0 { + self.process_block(); + } + inp = &inp[write_len..]; + } + } + + #[cfg(hashes_fuzz)] + fn input(&mut self, inp: &[u8]) { + for c in inp { + self.buffer[0] ^= *c; + } + self.bytes_hashed += inp.len() as u64; + } + ) +); +pub(crate) use engine_input_impl; diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs new file mode 100644 index 000000000..4e519fee2 --- /dev/null +++ b/hashes/src/lib.rs @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Rust Bitcoin Hashes Library +//! +//! This library implements the hash functions needed by Bitcoin. As an ancillary thing, it exposes +//! hexadecimal serialization and deserialization, since these are needed to display hashes. +//! +//! # Examples +//! +//! Hashing a single byte slice or a string: +//! +//! ``` +//! use bitcoin_hashes::Sha256; +//! +//! let bytes = [0u8; 5]; +//! let _hash_of_bytes = Sha256::hash(&bytes); +//! let _hash_of_string = Sha256::hash("some string".as_bytes()); +//! ``` +//! +//! +//! Hashing content from a reader: +//! +//! ``` +//! # #[cfg(feature = "std")] { +//! use bitcoin_hashes::Sha256; +//! +//! let mut reader: &[u8] = b"hello"; // In real code, this could be a `File` or `TcpStream`. +//! let mut engine = Sha256::engine(); +//! std::io::copy(&mut reader, &mut engine).expect("engine writes don't error"); +//! let _hash = Sha256::from_engine(engine); +//! # } +//! ``` +//! +//! +//! Hashing content using [`std::io::Write`] on a `HashEngine`: +//! +//! ``` +//! # #[cfg(feature = "std")] { +//! use std::io::Write as _; +//! use bitcoin_hashes::Sha256; +//! +//! let part1: &[u8] = b"hello"; +//! let part2: &[u8] = b" "; +//! let part3: &[u8] = b"world"; +//! let mut engine = Sha256::engine(); +//! engine.write_all(part1).expect("engine writes don't error"); +//! engine.write_all(part2).unwrap(); +//! engine.write_all(part3).unwrap(); +//! let _hash = Sha256::from_engine(engine); +//! # } +//! ``` + +#![no_std] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Pedantic lints that we enforce. +#![warn(clippy::return_self_not_must_use)] +// Instead of littering the codebase for non-fuzzing and bench code just globally allow. +#![cfg_attr(hashes_fuzz, allow(dead_code, unused_imports))] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +#[cfg(feature = "alloc")] +extern crate alloc; + +extern crate core; + +#[cfg(feature = "std")] +extern crate std; + +/// A generic serialization/deserialization framework. +#[cfg(feature = "serde")] +pub extern crate serde; + +#[cfg(all(test, feature = "serde"))] +extern crate serde_test; + +/// Re-export the `hex-conservative` crate. +#[cfg(feature = "hex")] +pub extern crate hex; + +#[doc(hidden)] +pub mod _export { + /// A re-export of core::* + pub mod _core { + pub use core::*; + } +} + +mod internal_macros; + +pub mod cmp; +pub mod hash160; +pub mod hkdf; +pub mod hmac; +#[macro_use] +pub mod macros; +pub mod ripemd160; +pub mod sha1; +pub mod sha256; +pub mod sha256d; +pub mod sha256t; +pub mod sha384; +pub mod sha3_256; +pub mod sha512; +pub mod sha512_256; +pub mod siphash24; + +use core::fmt::{self, Write as _}; +use core::{convert, hash}; + +use encoding::Encoder; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + hkdf::Hkdf, + hmac::{Hmac, HmacEngine}, +}; +/// HASH-160: Alias for the [`hash160::Hash`] hash type. +#[doc(inline)] +pub use hash160::Hash as Hash160; +/// RIPEMD-160: Alias for the [`ripemd160::Hash`] hash type. +#[doc(inline)] +pub use ripemd160::Hash as Ripemd160; +/// SHA-1: Alias for the [`sha1::Hash`] hash type. +#[doc(inline)] +pub use sha1::Hash as Sha1; +/// SHA-256: Alias for the [`sha256::Hash`] hash type. +#[doc(inline)] +pub use sha256::Hash as Sha256; +/// Double SHA-256: Alias for the [`sha256d::Hash`] hash type. +#[doc(inline)] +pub use sha256d::Hash as Sha256d; +/// SHA-384: Alias for the [`sha384::Hash`] hash type. +#[doc(inline)] +pub use sha384::Hash as Sha384; +/// SHA3-256: Alias for the [`sha3_256::Hash`] hash type. +pub use sha3_256::Hash as Sha3_256; +/// SHA-512: Alias for the [`sha512::Hash`] hash type. +#[doc(inline)] +pub use sha512::Hash as Sha512; +/// SHA-512-256: Alias for the [`sha512_256::Hash`] hash type. +#[doc(inline)] +pub use sha512_256::Hash as Sha512_256; +/// SipHash-2-4: Alias for the [`siphash24::Hash`] hash type. +#[doc(inline)] +pub use siphash24::Hash as Siphash24; + +/// Tagged SHA-256: Type alias for the [`sha256t::Hash`] hash type. +pub type Sha256t = sha256t::Hash; + +/// HMAC-SHA-256: Type alias for the [`Hmac`] type. +pub type HmacSha256 = Hmac; + +/// HMAC-SHA-512: Type alias for the [`Hmac`] type. +pub type HmacSha512 = Hmac; + +/// HKDF-HMAC-SHA-256: Type alias for the [`Hkdf`] type. +pub type HkdfSha256 = Hkdf; + +/// HKDF-HMAC-SHA-512: Type alias for the [`Hkdf`] type. +pub type HkdfSha512 = Hkdf; + +/// A hashing engine which bytes can be serialized into. +pub trait HashEngine: Clone { + /// The `Hash` type returned when finalizing this engine. + type Hash: Hash; + + /// The byte array that is used internally in `finalize`. + type Bytes: Copy + IsByteArray; + + /// Length of the hash, in bytes. + const LEN: usize = Self::Bytes::LEN; + + /// Length of the hash's internal block size, in bytes. + const BLOCK_SIZE: usize; + + /// Adds data to the hash engine. + fn input(&mut self, data: &[u8]); + + /// Returns the number of bytes already input into the engine. + fn n_bytes_hashed(&self) -> u64; + + /// Finalizes this engine. + fn finalize(self) -> Self::Hash; +} + +/// Encodes an object into a hash engine. +/// +/// Consumes and returns the hash engine to make it easier to call +/// [`HashEngine::finalize`] directly on the result. +pub fn encode_to_engine(object: &T, mut engine: H) -> H +where + T: encoding::Encodable + ?Sized, + H: HashEngine, +{ + let mut encoder = object.encoder(); + loop { + engine.input(encoder.current_chunk()); + if !encoder.advance() { + break; + } + } + engine +} + +/// Trait which applies to hashes of all types. +pub trait Hash: + Copy + Clone + PartialEq + Eq + PartialOrd + Ord + hash::Hash + convert::AsRef<[u8]> +{ + /// The byte array that represents the hash internally. + type Bytes: Copy + IsByteArray; + + /// Length of the hash, in bytes. + const LEN: usize = Self::Bytes::LEN; + + /// Flag indicating whether user-visible serializations of this hash should be backward. + /// + /// For some reason Satoshi decided this should be true for `Sha256dHash`, so here we are. + const DISPLAY_BACKWARD: bool = false; + + /// Constructs a new hash from the underlying byte array. + fn from_byte_array(bytes: Self::Bytes) -> Self; + + /// Returns the underlying byte array. + fn to_byte_array(self) -> Self::Bytes; + + /// Returns a reference to the underlying byte array. + fn as_byte_array(&self) -> &Self::Bytes; +} + +/// Ensures that a type is an array. +pub trait IsByteArray: AsRef<[u8]> + sealed::IsByteArray { + /// The length of the array. + const LEN: usize; +} + +impl IsByteArray for [u8; N] { + const LEN: usize = N; +} + +mod sealed { + pub trait IsByteArray {} + + impl IsByteArray for [u8; N] {} +} + +fn incomplete_block_len(eng: &H) -> usize { + let block_size = ::BLOCK_SIZE as u64; // Cast usize to u64 is ok. + + // After modulo operation we know cast u64 to usize as ok. + (eng.n_bytes_hashed() % block_size) as usize +} + +/// Writes `bytes` as a `hex` string to the formatter. +/// +/// For when we cannot rely on having the `hex` feature enabled. Ignores formatter options and just +/// writes with plain old `f.write_char()`. +pub fn debug_hex(bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + const HEX_TABLE: [u8; 16] = *b"0123456789abcdef"; + + for &b in bytes { + let lower = HEX_TABLE[usize::from(b >> 4)]; + let upper = HEX_TABLE[usize::from(b & 0b00001111)]; + f.write_char(char::from(lower))?; + f.write_char(char::from(upper))?; + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sha256d; + + hash_newtype! { + /// A test newtype + struct TestNewtype(sha256d::Hash); + + /// A test newtype + struct TestNewtype2(sha256d::Hash); + } + + #[cfg(feature = "hex")] + crate::impl_hex_for_newtype!(TestNewtype, TestNewtype2); + #[cfg(not(feature = "hex"))] + crate::impl_debug_only_for_newtype!(TestNewtype, TestNewtype2); + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn newtype_fmt_roundtrip() { + use alloc::format; + + #[rustfmt::skip] + const DUMMY: TestNewtype = TestNewtype::from_byte_array([ + 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, + 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, + 0x14, 0x25, 0x36, 0x47, 0x58, 0x69, 0x7a, 0x8b, + 0x15, 0x26, 0x37, 0x48, 0x59, 0x6a, 0x7b, 0x8c, + ]); + + let orig = DUMMY; + let hex = format!("{}", orig); + let roundtrip = hex.parse::().expect("failed to parse hex"); + assert_eq!(roundtrip, orig) + } +} diff --git a/hashes/src/macros.rs b/hashes/src/macros.rs new file mode 100644 index 000000000..bb530b7f8 --- /dev/null +++ b/hashes/src/macros.rs @@ -0,0 +1,640 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Public macros. +//! +//! - [`sha256t_tag`](crate::sha256t_tag) +//! - [`hash_newtype`](crate::hash_newtype) +//! - [`impl_hex_for_newtype`](crate::impl_hex_for_newtype) +//! - [`impl_serde_for_newtype`](crate::impl_serde_for_newtype) + +/// Macro used to define a tag. +/// +/// Defines new struct and implements `Tag` for it. +/// +/// The syntax is: +/// +/// ``` +/// # use bitcoin_hashes::sha256t_tag; +/// sha256t_tag! { +/// /// Optional documentation details here. +/// /// Summary is always generated. +/// pub struct FooTag = hash_str("foo"); +/// } +/// ``` +/// +/// The `hash_str` marker says the midstate should be generated by hashing the supplied string in a +/// way described in BIP-0341. Alternatively, you can supply `hash_bytes` to hash raw bytes. If you +/// have the midstate already pre-computed and prefer **compiler** performance to readability you +/// may use `raw(MIDSTATE_BYTES, HASHED_BYTES_LENGTH)` instead, note that HASHED_BYTES_LENGTH must +/// be a multiple of 64. +#[macro_export] +macro_rules! sha256t_tag { + ($(#[$($tag_attr:tt)*])* $tag_vis:vis struct $tag:ident = $constructor:tt($($tag_value:tt)+);) => { + $crate::sha256t_tag_struct!($tag_vis, $tag, stringify!($hash_name), $(#[$($tag_attr)*])*); + + impl $crate::sha256t::Tag for $tag { + const MIDSTATE: $crate::sha256::Midstate = $crate::sha256t_tag_constructor!($constructor, $($tag_value)+); + } + } +} + +/// Constructs a new newtype around a [`Hash`] type. +/// +/// The syntax is similar to the usual tuple struct syntax: +/// +/// ``` +/// # use bitcoin_hashes::{hash_newtype, sha256}; +/// hash_newtype! { +/// /// Hash of `Foo`. +/// pub struct MyNewtype(pub sha256::Hash); +/// } +/// ``` +/// +/// You can use any valid visibility specifier in place of `pub` or you can omit either or both, if +/// you want the type or its field to be private. +/// +/// Whether the hash is reversed or not when displaying depends on the inner type. However you can +/// override it like this: +/// +/// ``` +/// # use bitcoin_hashes::{hash_newtype, sha256}; +/// hash_newtype! { +/// #[hash_newtype(backward)] +/// struct MyNewtype(sha256::Hash); +/// } +/// ``` +/// +/// This will display the hash backwards regardless of what the inner type does. Use `forward` +/// instead of `backward` to force displaying forward. +/// +/// You can add arbitrary doc comments or other attributes to the struct or its field. Note that +/// the macro already derives [`Copy`], [`Clone`], [`Eq`], [`PartialEq`], +/// [`Hash`](core::hash::Hash), [`Ord`], [`PartialOrd`]. +/// +/// You can also define multiple newtypes within one macro call: +/// +/// ``` +/// # use bitcoin_hashes::{hash_newtype, sha256, hash160}; +/// +/// hash_newtype! { +/// /// My custom type 1 +/// pub struct Newtype1(sha256::Hash); +/// +/// /// My custom type 2 +/// struct Newtype2(hash160::Hash); +/// } +/// ``` +/// +/// Note: the macro is internally recursive. If you use too many attributes (> 256 tokens) you may +/// hit recursion limit. If you have so many attributes for a good reason, just raising the limit +/// should be OK. Note however that attribute-processing part has to use [TT muncher] which has +/// quadratic complexity, so having many attributes may blow up compile time. This should be rare. +/// +/// [TT muncher]: https://danielkeep.github.io/tlborm/book/pat-incremental-tt-munchers.html +/// +// Ever heard of legendary comments warning developers to not touch the code? Yep, here's another +// one. The following code is written the way it is for some specific reasons. If you think you can +// simplify it, I suggest spending your time elsewhere. +// +// If you look at the code carefully you might ask these questions: +// +// * Why are attributes using `tt` and not `meta`?! +// * Why are the macros split like that?! +// * Why use recursion instead of `$()*`? +// +// None of these are here by accident. For some reason unknown to me, if you accept an argument to +// macro with any fragment specifier other than `tt` it will **not** match any of the rules +// requiring a specific token. Yep, I tried it, I literally got error that `hash_newtype` doesn't +// match `hash_newtype`. So all input attributes must be `tt`. +// +// Originally I wanted to define a bunch of macros that would filter-out hash_type attributes. Then +// I remembered (by seeing compiler error) that calling macros is not allowed inside attributes. +// And no, you can't bypass it by calling a helper macro and passing "output of another macro" into +// it. The whole macro gets passed, not the resulting value. So we have to generate the entire +// attributes. And you can't just place an attribute-producing macro above struct - they are +// considered separate items. This is not C. +// +// Thus struct is generated in a separate macro together with attributes. And since the macro needs +// attributes as the input and I didn't want to create confusion by using `#[]` syntax *after* +// struct, I opted to use `{}` as a separator. Yes, a separator is required because an attribute +// may be composed of multiple token trees - that's the point of "double repetition". +#[macro_export] +macro_rules! hash_newtype { + ($($(#[$($type_attrs:tt)*])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:tt])* $field_vis:vis $hash:path);)+) => { + $( + $($crate::hash_newtype_known_attrs!(#[ $($type_attrs)* ]);)* + + $crate::hash_newtype_struct! { + $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash); + + $({ $($type_attrs)* })* + } + + $crate::impl_bytelike_traits!($newtype, { <$newtype as $crate::Hash>::LEN }); + + #[allow(unused)] // Private wrapper types may not need all functions. + impl $newtype { + /// Constructs a new hash from the underlying byte array. + pub const fn from_byte_array(bytes: <$hash as $crate::Hash>::Bytes) -> Self { + $newtype(<$hash>::from_byte_array(bytes)) + } + + /// Returns the underlying byte array. + pub const fn to_byte_array(self) -> <$hash as $crate::Hash>::Bytes { + self.0.to_byte_array() + } + + /// Returns a reference to the underlying byte array. + pub const fn as_byte_array(&self) -> &<$hash as $crate::Hash>::Bytes { + self.0.as_byte_array() + } + } + + impl $crate::Hash for $newtype { + type Bytes = <$hash as $crate::Hash>::Bytes; + + const DISPLAY_BACKWARD: bool = $crate::hash_newtype_get_direction!($hash, $(#[$($type_attrs)*])*); + + fn from_byte_array(bytes: Self::Bytes) -> Self { Self::from_byte_array(bytes) } + + fn to_byte_array(self) -> Self::Bytes { self.to_byte_array() } + + fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() } + } + )+ + }; +} + +/// Implements string functions using hex for a new type created with [`crate::hash_newtype`] macro. +/// +/// Implements: +/// +/// * `str::FromStr` +/// * `fmt::{LowerHex, UpperHex}` using `hex-conservative` +/// * `fmt::{Display, Debug}` by calling `LowerHex` +#[macro_export] +#[cfg(feature = "hex")] +macro_rules! impl_hex_for_newtype { + ($($newtype:ident),*) => { + $( + $crate::impl_hex_string_traits!($newtype, { <$newtype as $crate::Hash>::LEN }, { <$newtype as $crate::Hash>::DISPLAY_BACKWARD }); + )* + } +} + +/// Implements `fmt::Debug` using hex for a new type created with [`crate::hash_newtype`] macro. +/// +/// This is provided in case you do not want to use the `hex` feature. +#[macro_export] +macro_rules! impl_debug_only_for_newtype { + ($($newtype:ident),*) => { + $( + $crate::impl_debug_only!($newtype, { <$newtype as $crate::Hash>::LEN }, { <$newtype as $crate::Hash>::DISPLAY_BACKWARD }); + )* + } +} + +/// Adds trait impls to a bytelike type. +/// +/// Implements: +/// +/// * `AsRef[u8; $len]` +/// * `AsRef[u8]` +/// * `Borrow<[u8; $len]>` +/// * `Borrow<[u8]>` +/// +/// # Parameters +/// +/// * `ty` - the bytelike type to implement the traits on. +/// * `$len` - the number of bytes this type has. +/// * `$gen: $gent` - the generic type(s) and trait bound(s). +#[doc(hidden)] +#[macro_export] +macro_rules! impl_bytelike_traits { + ($ty:ident, $len:expr $(, $gen:ident: $gent:ident)*) => { + impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8; { $len }]> for $ty<$($gen),*> { + #[inline] + fn as_ref(&self) -> &[u8; { $len }] { self.as_byte_array() } + } + + impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> { + #[inline] + fn as_ref(&self) -> &[u8] { self.as_byte_array() } + } + + impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8; { $len }]> for $ty<$($gen),*> { + fn borrow(&self) -> &[u8; { $len }] { self.as_byte_array() } + } + + impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> { + fn borrow(&self) -> &[u8] { self.as_byte_array() } + } + } +} + +/// Adds hex string trait impls to a bytelike type using hex. +/// +/// Implements: +/// +/// * `str::FromStr` +/// * `fmt::{LowerHex, UpperHex}` using `hex-conservative`. +/// * `fmt::{Display, Debug}` by calling `LowerHex` +/// +/// Requires: +/// +/// * [`hex-conservative`] to publicly available as `$crate::hex`. +/// * `$ty` must implement `IntoIterator>`. +/// +/// (See also [`hex-conservative::fmt_hex_exact`].) +/// +/// # Parameters +/// +/// * `ty` - The bytelike type to implement the traits on. +/// * `$len` - The number of bytes this type has. +/// * `$reverse` - `true` if the type should be displayed backwards, `false` otherwise. +/// * `$gen: $gent` - generic type(s) and trait bound(s). +/// +/// [`hex-conservative`]: +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "hex")] +macro_rules! impl_hex_string_traits { + ($ty:ident, $len:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => { + impl<$($gen: $gent),*> $crate::_export::_core::str::FromStr for $ty<$($gen),*> { + type Err = $crate::hex::HexToArrayError; + + fn from_str(s: &str) -> $crate::_export::_core::result::Result { + use $crate::hex::FromHex; + + let mut bytes = <[u8; { $len }]>::from_hex(s)?; + if $reverse { + bytes.reverse(); + } + Ok(Self::from_byte_array(bytes)) + } + } + + $crate::hex::impl_fmt_traits! { + #[display_backward($reverse)] + impl<$($gen: $gent),*> fmt_traits for $ty<$($gen),*> { + const LENGTH: usize = ($len); // parens required due to rustc parser weirdness + } + } + } +} + +/// Implements `fmt::Debug` using hex. +#[doc(hidden)] +#[macro_export] +macro_rules! impl_debug_only { + ($ty:ident, $len:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => { + impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> { + #[inline] + fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result { + $crate::debug_hex(self.as_byte_array(), f) + } + } + } +} + +// Generates the struct only (no impls) +// +// This is a separate macro to make it more readable and have a separate interface that allows for +// two groups of type attributes: processed and not-yet-processed ones (think about it like +// computation via recursion). The macro recursively matches unprocessed attributes, popping them +// one at a time and either ignoring them (`hash_newtype`) or appending them to the list of +// processed attributes to be added to the struct. +// +// Once the list of not-yet-processed attributes is empty the struct is generated with processed +// attributes added. +#[doc(hidden)] +#[macro_export] +macro_rules! hash_newtype_struct { + ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path);) => { + $(#[$other_attrs])* + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash); + }; + ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path); { hash_newtype($($ignore:tt)*) } $($type_attrs:tt)*) => { + $crate::hash_newtype_struct! { + $(#[$other_attrs])* + $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash); + + $($type_attrs)* + } + }; + ($(#[$other_attrs:meta])* $type_vis:vis struct $newtype:ident($(#[$field_attrs:meta])* $field_vis:vis $hash:path); { $other_attr:meta } $($type_attrs:tt)*) => { + $crate::hash_newtype_struct! { + $(#[$other_attrs])* + #[$other_attr] + $type_vis struct $newtype($(#[$field_attrs])* $field_vis $hash); + + $($type_attrs)* + } + }; +} + +// Extracts `hash_newtype(forward)` and `hash_newtype(backward)` attributes if any and turns them +// into bool, defaulting to `DISPLAY_BACKWARD` of the wrapped type if the attribute is omitted. +// +// Once an appropriate attribute is found we pass the remaining ones into another macro to detect +// duplicates/conflicts and report an error. +// +// FYI, no, we can't use a helper macro to first filter all `hash_newtype` attributes. We would be +// attempting to match on macros instead. So we must write `hash_newtype` in each branch. +#[doc(hidden)] +#[macro_export] +macro_rules! hash_newtype_get_direction { + ($hash:ty, ) => { <$hash as $crate::Hash>::DISPLAY_BACKWARD }; + ($hash:ty, #[hash_newtype(forward)] $($others:tt)*) => { { $crate::hash_newtype_forbid_direction!(forward, $($others)*); false } }; + ($hash:ty, #[hash_newtype(backward)] $($others:tt)*) => { { $crate::hash_newtype_forbid_direction!(backward, $($others)*); true } }; + ($hash:ty, #[$($ignore:tt)*] $($others:tt)*) => { $crate::hash_newtype_get_direction!($hash, $($others)*) }; +} + +// Reports an error if any of the attributes is `hash_newtype($direction)`. +// +// This is used for detection of duplicates/conflicts, see the macro above. +#[doc(hidden)] +#[macro_export] +macro_rules! hash_newtype_forbid_direction { + ($direction:ident, ) => {}; + ($direction:ident, #[hash_newtype(forward)] $(others:tt)*) => { + compile_error!(concat!("cannot set display direction to forward: ", stringify!($direction), " was already specified")); + }; + ($direction:ident, #[hash_newtype(backward)] $(others:tt)*) => { + compile_error!(concat!("cannot set display direction to backward: ", stringify!($direction), " was already specified")); + }; + ($direction:ident, #[$($ignore:tt)*] $(#[$others:tt])*) => { + $crate::hash_newtype_forbid_direction!($direction, $(#[$others])*) + }; +} + +// Checks (at compile time) that all `hash_newtype` attributes are known. +// +// An unknown attribute could be a typo that could cause problems - e.g. wrong display direction if +// it's missing. To prevent this, we call this macro above. The macro produces nothing unless an +// unknown attribute is found in which case it produces `compile_error!`. +#[doc(hidden)] +#[macro_export] +macro_rules! hash_newtype_known_attrs { + (#[hash_newtype(forward)]) => {}; + (#[hash_newtype(backward)]) => {}; + (#[hash_newtype($($unknown:tt)*)]) => { compile_error!(concat!("unrecognized attribute ", stringify!($($unknown)*))); }; + ($($ignore:tt)*) => {}; +} + +/// Functions used by serde impls of all hashes. +#[cfg(feature = "serde")] +pub mod serde_details { + use core::marker::PhantomData; + use core::str::FromStr; + use core::{fmt, str}; + + use serde::de; + + /// Type used to implement serde traits for hashes as hex strings. + pub struct HexVisitor(PhantomData); + + impl Default for HexVisitor { + fn default() -> Self { Self(PhantomData) } + } + + impl de::Visitor<'_> for HexVisitor + where + ValueT: FromStr, + ::Err: fmt::Display, + { + type Value = ValueT; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> core::result::Result + where + E: de::Error, + { + if let Ok(hex) = str::from_utf8(v) { + hex.parse::().map_err(E::custom) + } else { + Err(E::invalid_value(de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> core::result::Result + where + E: de::Error, + { + v.parse::().map_err(E::custom) + } + } + + /// Type used to implement serde traits for hashes as bytes. + pub struct BytesVisitor(PhantomData); + + impl Default for BytesVisitor { + fn default() -> Self { Self(PhantomData) } + } + + impl de::Visitor<'_> for BytesVisitor + where + ValueT: crate::Hash, + ValueT: crate::Hash, + { + type Value = ValueT; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> core::result::Result + where + E: de::Error, + { + let bytes = <[u8; N]>::try_from(v).map_err(|_| { + // from_slice only errors on incorrect length + E::invalid_length(v.len(), &stringify!(N)) + })?; + + Ok(::from_byte_array(bytes)) + } + } +} + +/// Implements `Serialize` and `Deserialize` for a new type created with [`crate::hash_newtype`] macro. +#[macro_export] +#[cfg(feature = "serde")] +macro_rules! impl_serde_for_newtype { + ($($newtype:ident),*) => { + $( + $crate::serde_impl!($newtype, { <$newtype as $crate::Hash>::LEN }); + )* + } +} + +/// Implements `Serialize` and `Deserialize` for a type `$t` which +/// represents a newtype over a byte-slice over length `$len`. +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "serde")] +macro_rules! serde_impl( + ($t:ident, $len:expr $(, $gen:ident: $gent:ident)*) => ( + impl<$($gen: $gent),*> $crate::serde::Serialize for $t<$($gen),*> { + fn serialize(&self, s: S) -> core::result::Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(::as_byte_array(self)) + } + } + } + + impl<'de $(, $gen: $gent)*> $crate::serde::Deserialize<'de> for $t<$($gen),*> { + fn deserialize>(d: D) -> core::result::Result<$t<$($gen),*>, D::Error> { + use $crate::macros::serde_details::{BytesVisitor, HexVisitor}; + + if d.is_human_readable() { + d.deserialize_str(HexVisitor::::default()) + } else { + d.deserialize_bytes(BytesVisitor::::default()) + } + } + } +)); + +/// Does an "empty" serde implementation for the configuration without serde feature. +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "serde"))] +macro_rules! serde_impl( + ($t:ident, $len:expr $(, $gen:ident: $gent:ident)*) => () +); + +#[cfg(test)] +mod test { + use crate::sha256; + + #[test] + fn hash_as_ref_array() { + let hash = sha256::Hash::hash(&[3, 50]); + let r = AsRef::<[u8; 32]>::as_ref(&hash); + assert_eq!(r, hash.as_byte_array()); + } + + #[test] + fn hash_as_ref_slice() { + let hash = sha256::Hash::hash(&[3, 50]); + let r = AsRef::<[u8]>::as_ref(&hash); + assert_eq!(r, hash.as_byte_array()); + } + + #[test] + fn hash_borrow() { + use core::borrow::Borrow; + + let hash = sha256::Hash::hash(&[3, 50]); + let borrowed: &[u8] = hash.borrow(); + assert_eq!(borrowed, hash.as_byte_array()); + } + + hash_newtype! { + /// Test hash. + struct TestHash(crate::sha256d::Hash); + } + #[cfg(feature = "hex")] + crate::impl_hex_for_newtype!(TestHash); + #[cfg(not(feature = "hex"))] + crate::impl_debug_only_for_newtype!(TestHash); + + impl TestHash { + fn all_zeros() -> Self { Self::from_byte_array([0; 32]) } + } + + #[test] + fn macros_work_in_function_scope() { + use crate::sha256t; + + sha256t_tag! { + #[repr(align(2))] // This tests that we can add additional attributes. + pub struct FunctionScopeTag = hash_str("It works"); + } + + hash_newtype! { + /// Some docs. + #[repr(align(4))] // This tests that we can add additional attributes. + pub struct FunctionScopeHash(pub(crate) sha256t::Hash); + } + + assert_eq!(2, core::mem::align_of::()); + assert_eq!(4, core::mem::align_of::()); + } + + // NB: This runs with and without `hex` feature enabled, testing different code paths for each. + #[test] + #[cfg(feature = "alloc")] + fn debug() { + use alloc::format; + + let want = "0000000000000000000000000000000000000000000000000000000000000000"; + let got = format!("{:?}", TestHash::all_zeros()); + assert_eq!(got, want) + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn display() { + use alloc::format; + + let want = "0000000000000000000000000000000000000000000000000000000000000000"; + let got = format!("{}", TestHash::all_zeros()); + assert_eq!(got, want) + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn display_alternate() { + use alloc::format; + + let want = "0x0000000000000000000000000000000000000000000000000000000000000000"; + let got = format!("{:#}", TestHash::all_zeros()); + assert_eq!(got, want) + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn lower_hex() { + use alloc::format; + + let want = "0000000000000000000000000000000000000000000000000000000000000000"; + let got = format!("{:x}", TestHash::all_zeros()); + assert_eq!(got, want) + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn lower_hex_alternate() { + use alloc::format; + + let want = "0x0000000000000000000000000000000000000000000000000000000000000000"; + let got = format!("{:#x}", TestHash::all_zeros()); + assert_eq!(got, want) + } + + #[test] + fn inner_hash_as_ref_array() { + let hash = TestHash::all_zeros(); + let r = AsRef::<[u8; 32]>::as_ref(&hash); + assert_eq!(r, hash.as_byte_array()); + } + + #[test] + fn inner_hash_as_ref_slice() { + let hash = TestHash::all_zeros(); + let r = AsRef::<[u8]>::as_ref(&hash); + assert_eq!(r, hash.as_byte_array()); + } +} diff --git a/hashes/src/ripemd160/benches.rs b/hashes/src/ripemd160/benches.rs new file mode 100644 index 000000000..cb023a933 --- /dev/null +++ b/hashes/src/ripemd160/benches.rs @@ -0,0 +1,33 @@ +use test::Bencher; + +use crate::{ripemd160, Hash, HashEngine}; + +#[bench] +pub fn ripemd160_10(bh: &mut Bencher) { + let mut engine = ripemd160::Hash::engine(); + let bytes = [1u8; 10]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn ripemd160_1k(bh: &mut Bencher) { + let mut engine = ripemd160::Hash::engine(); + let bytes = [1u8; 1024]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn ripemd160_64k(bh: &mut Bencher) { + let mut engine = ripemd160::Hash::engine(); + let bytes = [1u8; 65536]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} diff --git a/hashes/src/ripemd160/crypto.rs b/hashes/src/ripemd160/crypto.rs new file mode 100644 index 000000000..115974f20 --- /dev/null +++ b/hashes/src/ripemd160/crypto.rs @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: CC0-1.0 + +use internals::slice::SliceExt; + +use super::{HashEngine, BLOCK_SIZE}; + +#[cfg(feature = "small-hash")] +#[macro_use] +mod small_hash { + #[rustfmt::skip] + pub(super) fn round(a: u32, _b: u32, c: u32, _d: u32, e: u32, + x: u32, bits: u32, add: u32, round: u32, + ) -> (u32, u32) { + let a = a.wrapping_add(round).wrapping_add(x).wrapping_add(add); + let a = a.rotate_left(bits).wrapping_add(e); + let c = c.rotate_left(10); + + (a, c) + } + + macro_rules! round( + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, + $x:expr, $bits:expr, $add:expr, $round:expr) => ({ + let updates = small_hash::round($a, $b, $c, $d, $e, $x, $bits, $add, $round); + $a = updates.0; + $c = updates.1; + }); + ); +} + +#[cfg(not(feature = "small-hash"))] +macro_rules! round( + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, + $x:expr, $bits:expr, $add:expr, $round:expr) => ({ + $a = $a.wrapping_add($round).wrapping_add($x).wrapping_add($add); + $a = $a.rotate_left($bits).wrapping_add($e); + $c = $c.rotate_left(10); + }); +); + +macro_rules! process_block( + ($h:expr, $data:expr, + $( round1: h_ordering $f0:expr, $f1:expr, $f2:expr, $f3:expr, $f4:expr; + data_index $data_index1:expr; roll_shift $bits1:expr; )* + $( round2: h_ordering $g0:expr, $g1:expr, $g2:expr, $g3:expr, $g4:expr; + data_index $data_index2:expr; roll_shift $bits2:expr; )* + $( round3: h_ordering $h0:expr, $h1:expr, $h2:expr, $h3:expr, $h4:expr; + data_index $data_index3:expr; roll_shift $bits3:expr; )* + $( round4: h_ordering $i0:expr, $i1:expr, $i2:expr, $i3:expr, $i4:expr; + data_index $data_index4:expr; roll_shift $bits4:expr; )* + $( round5: h_ordering $j0:expr, $j1:expr, $j2:expr, $j3:expr, $j4:expr; + data_index $data_index5:expr; roll_shift $bits5:expr; )* + $( par_round1: h_ordering $pj0:expr, $pj1:expr, $pj2:expr, $pj3:expr, $pj4:expr; + data_index $pdata_index1:expr; roll_shift $pbits1:expr; )* + $( par_round2: h_ordering $pi0:expr, $pi1:expr, $pi2:expr, $pi3:expr, $pi4:expr; + data_index $pdata_index2:expr; roll_shift $pbits2:expr; )* + $( par_round3: h_ordering $ph0:expr, $ph1:expr, $ph2:expr, $ph3:expr, $ph4:expr; + data_index $pdata_index3:expr; roll_shift $pbits3:expr; )* + $( par_round4: h_ordering $pg0:expr, $pg1:expr, $pg2:expr, $pg3:expr, $pg4:expr; + data_index $pdata_index4:expr; roll_shift $pbits4:expr; )* + $( par_round5: h_ordering $pf0:expr, $pf1:expr, $pf2:expr, $pf3:expr, $pf4:expr; + data_index $pdata_index5:expr; roll_shift $pbits5:expr; )* + ) => ({ + let mut bb = $h; + let mut bbb = $h; + + // Round 1 + $( round!(bb[$f0], bb[$f1], bb[$f2], bb[$f3], bb[$f4], + $data[$data_index1], $bits1, 0x00000000, + bb[$f1] ^ bb[$f2] ^ bb[$f3]); )* + + // Round 2 + $( round!(bb[$g0], bb[$g1], bb[$g2], bb[$g3], bb[$g4], + $data[$data_index2], $bits2, 0x5a827999, + (bb[$g1] & bb[$g2]) | (!bb[$g1] & bb[$g3])); )* + + // Round 3 + $( round!(bb[$h0], bb[$h1], bb[$h2], bb[$h3], bb[$h4], + $data[$data_index3], $bits3, 0x6ed9eba1, + (bb[$h1] | !bb[$h2]) ^ bb[$h3]); )* + + // Round 4 + $( round!(bb[$i0], bb[$i1], bb[$i2], bb[$i3], bb[$i4], + $data[$data_index4], $bits4, 0x8f1bbcdc, + (bb[$i1] & bb[$i3]) | (bb[$i2] & !bb[$i3])); )* + + // Round 5 + $( round!(bb[$j0], bb[$j1], bb[$j2], bb[$j3], bb[$j4], + $data[$data_index5], $bits5, 0xa953fd4e, + bb[$j1] ^ (bb[$j2] | !bb[$j3])); )* + + // Parallel rounds: these are the same as the previous five + // rounds except that the constants have changed, we work + // with the other buffer, and they are applied in reverse + // order. + + // Parallel Round 1 + $( round!(bbb[$pj0], bbb[$pj1], bbb[$pj2], bbb[$pj3], bbb[$pj4], + $data[$pdata_index1], $pbits1, 0x50a28be6, + bbb[$pj1] ^ (bbb[$pj2] | !bbb[$pj3])); )* + + // Parallel Round 2 + $( round!(bbb[$pi0], bbb[$pi1], bbb[$pi2], bbb[$pi3], bbb[$pi4], + $data[$pdata_index2], $pbits2, 0x5c4dd124, + (bbb[$pi1] & bbb[$pi3]) | (bbb[$pi2] & !bbb[$pi3])); )* + + // Parallel Round 3 + $( round!(bbb[$ph0], bbb[$ph1], bbb[$ph2], bbb[$ph3], bbb[$ph4], + $data[$pdata_index3], $pbits3, 0x6d703ef3, + (bbb[$ph1] | !bbb[$ph2]) ^ bbb[$ph3]); )* + + // Parallel Round 4 + $( round!(bbb[$pg0], bbb[$pg1], bbb[$pg2], bbb[$pg3], bbb[$pg4], + $data[$pdata_index4], $pbits4, 0x7a6d76e9, + (bbb[$pg1] & bbb[$pg2]) | (!bbb[$pg1] & bbb[$pg3])); )* + + // Parallel Round 5 + $( round!(bbb[$pf0], bbb[$pf1], bbb[$pf2], bbb[$pf3], bbb[$pf4], + $data[$pdata_index5], $pbits5, 0x00000000, + bbb[$pf1] ^ bbb[$pf2] ^ bbb[$pf3]); )* + + // Combine results + bbb[3] = bbb[3].wrapping_add($h[1]).wrapping_add(bb[2]); + $h[1] = $h[2].wrapping_add(bb[3]).wrapping_add(bbb[4]); + $h[2] = $h[3].wrapping_add(bb[4]).wrapping_add(bbb[0]); + $h[3] = $h[4].wrapping_add(bb[0]).wrapping_add(bbb[1]); + $h[4] = $h[0].wrapping_add(bb[1]).wrapping_add(bbb[2]); + $h[0] = bbb[3]; + }); +); + +impl HashEngine { + pub(super) fn process_block(&mut self) { + debug_assert_eq!(self.buffer.len(), BLOCK_SIZE); + + let mut w = [0u32; 16]; + for (w_val, buff_bytes) in w.iter_mut().zip(self.buffer.bitcoin_as_chunks().0) { + *w_val = u32::from_le_bytes(*buff_bytes) + } + + process_block!(self.h, w, + // Round 1 + round1: h_ordering 0, 1, 2, 3, 4; data_index 0; roll_shift 11; + round1: h_ordering 4, 0, 1, 2, 3; data_index 1; roll_shift 14; + round1: h_ordering 3, 4, 0, 1, 2; data_index 2; roll_shift 15; + round1: h_ordering 2, 3, 4, 0, 1; data_index 3; roll_shift 12; + round1: h_ordering 1, 2, 3, 4, 0; data_index 4; roll_shift 5; + round1: h_ordering 0, 1, 2, 3, 4; data_index 5; roll_shift 8; + round1: h_ordering 4, 0, 1, 2, 3; data_index 6; roll_shift 7; + round1: h_ordering 3, 4, 0, 1, 2; data_index 7; roll_shift 9; + round1: h_ordering 2, 3, 4, 0, 1; data_index 8; roll_shift 11; + round1: h_ordering 1, 2, 3, 4, 0; data_index 9; roll_shift 13; + round1: h_ordering 0, 1, 2, 3, 4; data_index 10; roll_shift 14; + round1: h_ordering 4, 0, 1, 2, 3; data_index 11; roll_shift 15; + round1: h_ordering 3, 4, 0, 1, 2; data_index 12; roll_shift 6; + round1: h_ordering 2, 3, 4, 0, 1; data_index 13; roll_shift 7; + round1: h_ordering 1, 2, 3, 4, 0; data_index 14; roll_shift 9; + round1: h_ordering 0, 1, 2, 3, 4; data_index 15; roll_shift 8; + + // Round 2 + round2: h_ordering 4, 0, 1, 2, 3; data_index 7; roll_shift 7; + round2: h_ordering 3, 4, 0, 1, 2; data_index 4; roll_shift 6; + round2: h_ordering 2, 3, 4, 0, 1; data_index 13; roll_shift 8; + round2: h_ordering 1, 2, 3, 4, 0; data_index 1; roll_shift 13; + round2: h_ordering 0, 1, 2, 3, 4; data_index 10; roll_shift 11; + round2: h_ordering 4, 0, 1, 2, 3; data_index 6; roll_shift 9; + round2: h_ordering 3, 4, 0, 1, 2; data_index 15; roll_shift 7; + round2: h_ordering 2, 3, 4, 0, 1; data_index 3; roll_shift 15; + round2: h_ordering 1, 2, 3, 4, 0; data_index 12; roll_shift 7; + round2: h_ordering 0, 1, 2, 3, 4; data_index 0; roll_shift 12; + round2: h_ordering 4, 0, 1, 2, 3; data_index 9; roll_shift 15; + round2: h_ordering 3, 4, 0, 1, 2; data_index 5; roll_shift 9; + round2: h_ordering 2, 3, 4, 0, 1; data_index 2; roll_shift 11; + round2: h_ordering 1, 2, 3, 4, 0; data_index 14; roll_shift 7; + round2: h_ordering 0, 1, 2, 3, 4; data_index 11; roll_shift 13; + round2: h_ordering 4, 0, 1, 2, 3; data_index 8; roll_shift 12; + + // Round 3 + round3: h_ordering 3, 4, 0, 1, 2; data_index 3; roll_shift 11; + round3: h_ordering 2, 3, 4, 0, 1; data_index 10; roll_shift 13; + round3: h_ordering 1, 2, 3, 4, 0; data_index 14; roll_shift 6; + round3: h_ordering 0, 1, 2, 3, 4; data_index 4; roll_shift 7; + round3: h_ordering 4, 0, 1, 2, 3; data_index 9; roll_shift 14; + round3: h_ordering 3, 4, 0, 1, 2; data_index 15; roll_shift 9; + round3: h_ordering 2, 3, 4, 0, 1; data_index 8; roll_shift 13; + round3: h_ordering 1, 2, 3, 4, 0; data_index 1; roll_shift 15; + round3: h_ordering 0, 1, 2, 3, 4; data_index 2; roll_shift 14; + round3: h_ordering 4, 0, 1, 2, 3; data_index 7; roll_shift 8; + round3: h_ordering 3, 4, 0, 1, 2; data_index 0; roll_shift 13; + round3: h_ordering 2, 3, 4, 0, 1; data_index 6; roll_shift 6; + round3: h_ordering 1, 2, 3, 4, 0; data_index 13; roll_shift 5; + round3: h_ordering 0, 1, 2, 3, 4; data_index 11; roll_shift 12; + round3: h_ordering 4, 0, 1, 2, 3; data_index 5; roll_shift 7; + round3: h_ordering 3, 4, 0, 1, 2; data_index 12; roll_shift 5; + + // Round 4 + round4: h_ordering 2, 3, 4, 0, 1; data_index 1; roll_shift 11; + round4: h_ordering 1, 2, 3, 4, 0; data_index 9; roll_shift 12; + round4: h_ordering 0, 1, 2, 3, 4; data_index 11; roll_shift 14; + round4: h_ordering 4, 0, 1, 2, 3; data_index 10; roll_shift 15; + round4: h_ordering 3, 4, 0, 1, 2; data_index 0; roll_shift 14; + round4: h_ordering 2, 3, 4, 0, 1; data_index 8; roll_shift 15; + round4: h_ordering 1, 2, 3, 4, 0; data_index 12; roll_shift 9; + round4: h_ordering 0, 1, 2, 3, 4; data_index 4; roll_shift 8; + round4: h_ordering 4, 0, 1, 2, 3; data_index 13; roll_shift 9; + round4: h_ordering 3, 4, 0, 1, 2; data_index 3; roll_shift 14; + round4: h_ordering 2, 3, 4, 0, 1; data_index 7; roll_shift 5; + round4: h_ordering 1, 2, 3, 4, 0; data_index 15; roll_shift 6; + round4: h_ordering 0, 1, 2, 3, 4; data_index 14; roll_shift 8; + round4: h_ordering 4, 0, 1, 2, 3; data_index 5; roll_shift 6; + round4: h_ordering 3, 4, 0, 1, 2; data_index 6; roll_shift 5; + round4: h_ordering 2, 3, 4, 0, 1; data_index 2; roll_shift 12; + + // Round 5 + round5: h_ordering 1, 2, 3, 4, 0; data_index 4; roll_shift 9; + round5: h_ordering 0, 1, 2, 3, 4; data_index 0; roll_shift 15; + round5: h_ordering 4, 0, 1, 2, 3; data_index 5; roll_shift 5; + round5: h_ordering 3, 4, 0, 1, 2; data_index 9; roll_shift 11; + round5: h_ordering 2, 3, 4, 0, 1; data_index 7; roll_shift 6; + round5: h_ordering 1, 2, 3, 4, 0; data_index 12; roll_shift 8; + round5: h_ordering 0, 1, 2, 3, 4; data_index 2; roll_shift 13; + round5: h_ordering 4, 0, 1, 2, 3; data_index 10; roll_shift 12; + round5: h_ordering 3, 4, 0, 1, 2; data_index 14; roll_shift 5; + round5: h_ordering 2, 3, 4, 0, 1; data_index 1; roll_shift 12; + round5: h_ordering 1, 2, 3, 4, 0; data_index 3; roll_shift 13; + round5: h_ordering 0, 1, 2, 3, 4; data_index 8; roll_shift 14; + round5: h_ordering 4, 0, 1, 2, 3; data_index 11; roll_shift 11; + round5: h_ordering 3, 4, 0, 1, 2; data_index 6; roll_shift 8; + round5: h_ordering 2, 3, 4, 0, 1; data_index 15; roll_shift 5; + round5: h_ordering 1, 2, 3, 4, 0; data_index 13; roll_shift 6; + + // Parallel Round 1; + par_round1: h_ordering 0, 1, 2, 3, 4; data_index 5; roll_shift 8; + par_round1: h_ordering 4, 0, 1, 2, 3; data_index 14; roll_shift 9; + par_round1: h_ordering 3, 4, 0, 1, 2; data_index 7; roll_shift 9; + par_round1: h_ordering 2, 3, 4, 0, 1; data_index 0; roll_shift 11; + par_round1: h_ordering 1, 2, 3, 4, 0; data_index 9; roll_shift 13; + par_round1: h_ordering 0, 1, 2, 3, 4; data_index 2; roll_shift 15; + par_round1: h_ordering 4, 0, 1, 2, 3; data_index 11; roll_shift 15; + par_round1: h_ordering 3, 4, 0, 1, 2; data_index 4; roll_shift 5; + par_round1: h_ordering 2, 3, 4, 0, 1; data_index 13; roll_shift 7; + par_round1: h_ordering 1, 2, 3, 4, 0; data_index 6; roll_shift 7; + par_round1: h_ordering 0, 1, 2, 3, 4; data_index 15; roll_shift 8; + par_round1: h_ordering 4, 0, 1, 2, 3; data_index 8; roll_shift 11; + par_round1: h_ordering 3, 4, 0, 1, 2; data_index 1; roll_shift 14; + par_round1: h_ordering 2, 3, 4, 0, 1; data_index 10; roll_shift 14; + par_round1: h_ordering 1, 2, 3, 4, 0; data_index 3; roll_shift 12; + par_round1: h_ordering 0, 1, 2, 3, 4; data_index 12; roll_shift 6; + + // Parallel Round 2 + par_round2: h_ordering 4, 0, 1, 2, 3; data_index 6; roll_shift 9; + par_round2: h_ordering 3, 4, 0, 1, 2; data_index 11; roll_shift 13; + par_round2: h_ordering 2, 3, 4, 0, 1; data_index 3; roll_shift 15; + par_round2: h_ordering 1, 2, 3, 4, 0; data_index 7; roll_shift 7; + par_round2: h_ordering 0, 1, 2, 3, 4; data_index 0; roll_shift 12; + par_round2: h_ordering 4, 0, 1, 2, 3; data_index 13; roll_shift 8; + par_round2: h_ordering 3, 4, 0, 1, 2; data_index 5; roll_shift 9; + par_round2: h_ordering 2, 3, 4, 0, 1; data_index 10; roll_shift 11; + par_round2: h_ordering 1, 2, 3, 4, 0; data_index 14; roll_shift 7; + par_round2: h_ordering 0, 1, 2, 3, 4; data_index 15; roll_shift 7; + par_round2: h_ordering 4, 0, 1, 2, 3; data_index 8; roll_shift 12; + par_round2: h_ordering 3, 4, 0, 1, 2; data_index 12; roll_shift 7; + par_round2: h_ordering 2, 3, 4, 0, 1; data_index 4; roll_shift 6; + par_round2: h_ordering 1, 2, 3, 4, 0; data_index 9; roll_shift 15; + par_round2: h_ordering 0, 1, 2, 3, 4; data_index 1; roll_shift 13; + par_round2: h_ordering 4, 0, 1, 2, 3; data_index 2; roll_shift 11; + + // Parallel Round 3 + par_round3: h_ordering 3, 4, 0, 1, 2; data_index 15; roll_shift 9; + par_round3: h_ordering 2, 3, 4, 0, 1; data_index 5; roll_shift 7; + par_round3: h_ordering 1, 2, 3, 4, 0; data_index 1; roll_shift 15; + par_round3: h_ordering 0, 1, 2, 3, 4; data_index 3; roll_shift 11; + par_round3: h_ordering 4, 0, 1, 2, 3; data_index 7; roll_shift 8; + par_round3: h_ordering 3, 4, 0, 1, 2; data_index 14; roll_shift 6; + par_round3: h_ordering 2, 3, 4, 0, 1; data_index 6; roll_shift 6; + par_round3: h_ordering 1, 2, 3, 4, 0; data_index 9; roll_shift 14; + par_round3: h_ordering 0, 1, 2, 3, 4; data_index 11; roll_shift 12; + par_round3: h_ordering 4, 0, 1, 2, 3; data_index 8; roll_shift 13; + par_round3: h_ordering 3, 4, 0, 1, 2; data_index 12; roll_shift 5; + par_round3: h_ordering 2, 3, 4, 0, 1; data_index 2; roll_shift 14; + par_round3: h_ordering 1, 2, 3, 4, 0; data_index 10; roll_shift 13; + par_round3: h_ordering 0, 1, 2, 3, 4; data_index 0; roll_shift 13; + par_round3: h_ordering 4, 0, 1, 2, 3; data_index 4; roll_shift 7; + par_round3: h_ordering 3, 4, 0, 1, 2; data_index 13; roll_shift 5; + + // Parallel Round 4 + par_round4: h_ordering 2, 3, 4, 0, 1; data_index 8; roll_shift 15; + par_round4: h_ordering 1, 2, 3, 4, 0; data_index 6; roll_shift 5; + par_round4: h_ordering 0, 1, 2, 3, 4; data_index 4; roll_shift 8; + par_round4: h_ordering 4, 0, 1, 2, 3; data_index 1; roll_shift 11; + par_round4: h_ordering 3, 4, 0, 1, 2; data_index 3; roll_shift 14; + par_round4: h_ordering 2, 3, 4, 0, 1; data_index 11; roll_shift 14; + par_round4: h_ordering 1, 2, 3, 4, 0; data_index 15; roll_shift 6; + par_round4: h_ordering 0, 1, 2, 3, 4; data_index 0; roll_shift 14; + par_round4: h_ordering 4, 0, 1, 2, 3; data_index 5; roll_shift 6; + par_round4: h_ordering 3, 4, 0, 1, 2; data_index 12; roll_shift 9; + par_round4: h_ordering 2, 3, 4, 0, 1; data_index 2; roll_shift 12; + par_round4: h_ordering 1, 2, 3, 4, 0; data_index 13; roll_shift 9; + par_round4: h_ordering 0, 1, 2, 3, 4; data_index 9; roll_shift 12; + par_round4: h_ordering 4, 0, 1, 2, 3; data_index 7; roll_shift 5; + par_round4: h_ordering 3, 4, 0, 1, 2; data_index 10; roll_shift 15; + par_round4: h_ordering 2, 3, 4, 0, 1; data_index 14; roll_shift 8; + + // Parallel Round 5 + par_round5: h_ordering 1, 2, 3, 4, 0; data_index 12; roll_shift 8; + par_round5: h_ordering 0, 1, 2, 3, 4; data_index 15; roll_shift 5; + par_round5: h_ordering 4, 0, 1, 2, 3; data_index 10; roll_shift 12; + par_round5: h_ordering 3, 4, 0, 1, 2; data_index 4; roll_shift 9; + par_round5: h_ordering 2, 3, 4, 0, 1; data_index 1; roll_shift 12; + par_round5: h_ordering 1, 2, 3, 4, 0; data_index 5; roll_shift 5; + par_round5: h_ordering 0, 1, 2, 3, 4; data_index 8; roll_shift 14; + par_round5: h_ordering 4, 0, 1, 2, 3; data_index 7; roll_shift 6; + par_round5: h_ordering 3, 4, 0, 1, 2; data_index 6; roll_shift 8; + par_round5: h_ordering 2, 3, 4, 0, 1; data_index 2; roll_shift 13; + par_round5: h_ordering 1, 2, 3, 4, 0; data_index 13; roll_shift 6; + par_round5: h_ordering 0, 1, 2, 3, 4; data_index 14; roll_shift 5; + par_round5: h_ordering 4, 0, 1, 2, 3; data_index 0; roll_shift 15; + par_round5: h_ordering 3, 4, 0, 1, 2; data_index 3; roll_shift 13; + par_round5: h_ordering 2, 3, 4, 0, 1; data_index 9; roll_shift 11; + par_round5: h_ordering 1, 2, 3, 4, 0; data_index 11; roll_shift 11; + ); + } +} diff --git a/hashes/src/ripemd160/mod.rs b/hashes/src/ripemd160/mod.rs new file mode 100644 index 000000000..e130eedb8 --- /dev/null +++ b/hashes/src/ripemd160/mod.rs @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! RIPEMD160 implementation. + +use internals::slice::SliceExt; +mod crypto; +#[cfg(test)] +mod tests; + +use core::cmp; + +use crate::{incomplete_block_len, HashEngine as _}; + +crate::internal_macros::general_hash_type! { + 160, + false, + "Output of the RIPEMD160 hash function." +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + #[cfg(not(hashes_fuzz))] + pub fn from_engine(mut e: HashEngine) -> Self { + // pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining + let n_bytes_hashed = e.bytes_hashed; + + let zeroes = [0; BLOCK_SIZE - 8]; + e.input(&[0x80]); + if crate::incomplete_block_len(&e) > zeroes.len() { + e.input(&zeroes); + } + let pad_length = zeroes.len() - incomplete_block_len(&e); + e.input(&zeroes[..pad_length]); + debug_assert_eq!(incomplete_block_len(&e), zeroes.len()); + + e.input(&(8 * n_bytes_hashed).to_le_bytes()); + debug_assert_eq!(incomplete_block_len(&e), 0); + + Self(e.midstate()) + } + + /// Finalize a hash engine to produce a hash. + #[cfg(hashes_fuzz)] + pub fn from_engine(e: HashEngine) -> Self { + let mut res = e.midstate(); + res[0] ^= (e.bytes_hashed & 0xff) as u8; + Hash(res) + } +} + +const BLOCK_SIZE: usize = 64; + +/// Engine to compute RIPEMD160 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine { + buffer: [u8; BLOCK_SIZE], + h: [u32; 5], + bytes_hashed: u64, +} + +impl HashEngine { + /// Constructs a new RIPEMD160 hash engine. + pub const fn new() -> Self { + Self { + h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0], + bytes_hashed: 0, + buffer: [0; BLOCK_SIZE], + } + } + + #[cfg(not(hashes_fuzz))] + fn midstate(&self) -> [u8; 20] { + let mut ret = [0; 20]; + for (val, ret_bytes) in self.h.iter().zip(ret.bitcoin_as_chunks_mut().0) { + *ret_bytes = val.to_le_bytes(); + } + ret + } + + #[cfg(hashes_fuzz)] + fn midstate(&self) -> [u8; 20] { + let mut ret = [0; 20]; + ret.copy_from_slice(&self.buffer[..20]); + ret + } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 20]; + const BLOCK_SIZE: usize = 64; + + fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } + crate::internal_macros::engine_input_impl!(); + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} diff --git a/hashes/src/ripemd160/tests.rs b/hashes/src/ripemd160/tests.rs new file mode 100644 index 000000000..8eb9061af --- /dev/null +++ b/hashes/src/ripemd160/tests.rs @@ -0,0 +1,106 @@ +#[test] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +fn test() { + use alloc::string::ToString; + + use crate::{ripemd160, HashEngine}; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 20], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Test messages from FIPS 180-1 + Test { + input: "abc", + output: [ + 0x8e, 0xb2, 0x08, 0xf7, + 0xe0, 0x5d, 0x98, 0x7a, + 0x9b, 0x04, 0x4a, 0x8e, + 0x98, 0xc6, 0xb0, 0x87, + 0xf1, 0x5a, 0x0b, 0xfc, + ], + output_str: "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" + }, + Test { + input: + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + output: [ + 0x12, 0xa0, 0x53, 0x38, + 0x4a, 0x9c, 0x0c, 0x88, + 0xe4, 0x05, 0xa0, 0x6c, + 0x27, 0xdc, 0xf4, 0x9a, + 0xda, 0x62, 0xeb, 0x2b, + ], + output_str: "12a053384a9c0c88e405a06c27dcf49ada62eb2b" + }, + // Examples from wikipedia + Test { + input: "The quick brown fox jumps over the lazy dog", + output: [ + 0x37, 0xf3, 0x32, 0xf6, + 0x8d, 0xb7, 0x7b, 0xd9, + 0xd7, 0xed, 0xd4, 0x96, + 0x95, 0x71, 0xad, 0x67, + 0x1c, 0xf9, 0xdd, 0x3b, + ], + output_str: "37f332f68db77bd9d7edd4969571ad671cf9dd3b", + }, + Test { + input: "The quick brown fox jumps over the lazy cog", + output: [ + 0x13, 0x20, 0x72, 0xdf, + 0x69, 0x09, 0x33, 0x83, + 0x5e, 0xb8, 0xb6, 0xad, + 0x0b, 0x77, 0xe7, 0xb6, + 0xf1, 0x4a, 0xca, 0xd7, + ], + output_str: "132072df690933835eb8b6ad0b77e7b6f14acad7", + }, + ]; + + for mut test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = ripemd160::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + assert_eq!(ripemd160::Hash::from_bytes_ref(&test.output), &hash); + assert_eq!(ripemd160::Hash::from_bytes_mut(&mut test.output), &hash); + + // Hash through engine, checking that we can input byte by byte + let mut engine = ripemd160::Hash::engine(); + for ch in test.input.as_bytes() { + engine.input(&[*ch]); + } + let manual_hash = ripemd160::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } +} + +#[test] +#[cfg(feature = "serde")] +fn ripemd_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + use crate::ripemd160; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 20] = [ + 0x13, 0x20, 0x72, 0xdf, + 0x69, 0x09, 0x33, 0x83, + 0x5e, 0xb8, 0xb6, 0xad, + 0x0b, 0x77, 0xe7, 0xb6, + 0xf1, 0x4a, 0xca, 0xd7, + ]; + + let hash = ripemd160::Hash::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]); +} diff --git a/hashes/src/sha1/benches.rs b/hashes/src/sha1/benches.rs new file mode 100644 index 000000000..fcf2518df --- /dev/null +++ b/hashes/src/sha1/benches.rs @@ -0,0 +1,33 @@ +use test::Bencher; + +use crate::{sha1, Hash, HashEngine}; + +#[bench] +pub fn sha1_10(bh: &mut Bencher) { + let mut engine = sha1::Hash::engine(); + let bytes = [1u8; 10]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha1_1k(bh: &mut Bencher) { + let mut engine = sha1::Hash::engine(); + let bytes = [1u8; 1024]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha1_64k(bh: &mut Bencher) { + let mut engine = sha1::Hash::engine(); + let bytes = [1u8; 65536]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} diff --git a/hashes/src/sha1/crypto.rs b/hashes/src/sha1/crypto.rs new file mode 100644 index 000000000..70d04f506 --- /dev/null +++ b/hashes/src/sha1/crypto.rs @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: CC0-1.0 + +use internals::slice::SliceExt; + +use super::{HashEngine, BLOCK_SIZE}; + +impl HashEngine { + // Basic unoptimized algorithm from Wikipedia + pub(super) fn process_block(&mut self) { + debug_assert_eq!(self.buffer.len(), BLOCK_SIZE); + + let mut w = [0u32; 80]; + for (w_val, buff_bytes) in w.iter_mut().zip(self.buffer.bitcoin_as_chunks().0) { + *w_val = u32::from_be_bytes(*buff_bytes) + } + for i in 16..80 { + w[i] = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]).rotate_left(1); + } + + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + + for (i, &wi) in w.iter().enumerate() { + let (f, k) = match i { + 0..=19 => ((b & c) | (!b & d), 0x5a827999), + 20..=39 => (b ^ c ^ d, 0x6ed9eba1), + 40..=59 => ((b & c) | (b & d) | (c & d), 0x8f1bbcdc), + 60..=79 => (b ^ c ^ d, 0xca62c1d6), + _ => unreachable!(), + }; + + let new_a = + a.rotate_left(5).wrapping_add(f).wrapping_add(e).wrapping_add(k).wrapping_add(wi); + e = d; + d = c; + c = b.rotate_left(30); + b = a; + a = new_a; + } + + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + } +} diff --git a/hashes/src/sha1/mod.rs b/hashes/src/sha1/mod.rs new file mode 100644 index 000000000..c2a8aecc1 --- /dev/null +++ b/hashes/src/sha1/mod.rs @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA1 implementation. + +use internals::slice::SliceExt; +mod crypto; +#[cfg(test)] +mod tests; + +use core::cmp; + +use crate::{incomplete_block_len, HashEngine as _}; + +crate::internal_macros::general_hash_type! { + 160, + false, + "Output of the SHA1 hash function." +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + pub fn from_engine(mut e: HashEngine) -> Self { + // pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining + let n_bytes_hashed = e.bytes_hashed; + + let zeroes = [0; BLOCK_SIZE - 8]; + e.input(&[0x80]); + if incomplete_block_len(&e) > zeroes.len() { + e.input(&zeroes); + } + let pad_length = zeroes.len() - incomplete_block_len(&e); + e.input(&zeroes[..pad_length]); + debug_assert_eq!(incomplete_block_len(&e), zeroes.len()); + + e.input(&(8 * n_bytes_hashed).to_be_bytes()); + debug_assert_eq!(incomplete_block_len(&e), 0); + + Self(e.midstate()) + } +} + +const BLOCK_SIZE: usize = 64; + +/// Engine to compute SHA1 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine { + buffer: [u8; BLOCK_SIZE], + h: [u32; 5], + bytes_hashed: u64, +} + +impl HashEngine { + /// Constructs a new SHA1 hash engine. + pub const fn new() -> Self { + Self { + h: [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0], + bytes_hashed: 0, + buffer: [0; BLOCK_SIZE], + } + } + + #[cfg(not(hashes_fuzz))] + pub(crate) fn midstate(&self) -> [u8; 20] { + let mut ret = [0; 20]; + for (val, ret_bytes) in self.h.iter().zip(ret.bitcoin_as_chunks_mut().0) { + *ret_bytes = val.to_be_bytes(); + } + ret + } + + #[cfg(hashes_fuzz)] + pub(crate) fn midstate(&self) -> [u8; 20] { + let mut ret = [0; 20]; + ret.copy_from_slice(&self.buffer[..20]); + ret + } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 20]; + const BLOCK_SIZE: usize = 64; + + fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } + + crate::internal_macros::engine_input_impl!(); + + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} diff --git a/hashes/src/sha1/tests.rs b/hashes/src/sha1/tests.rs new file mode 100644 index 000000000..831457ac2 --- /dev/null +++ b/hashes/src/sha1/tests.rs @@ -0,0 +1,91 @@ +#[test] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +fn test() { + use alloc::string::ToString; + + use crate::{sha1, HashEngine}; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 20], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Examples from wikipedia + Test { + input: "", + output: [ + 0xda, 0x39, 0xa3, 0xee, + 0x5e, 0x6b, 0x4b, 0x0d, + 0x32, 0x55, 0xbf, 0xef, + 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09, + ], + output_str: "da39a3ee5e6b4b0d3255bfef95601890afd80709" + }, + Test { + input: "The quick brown fox jumps over the lazy dog", + output: [ + 0x2f, 0xd4, 0xe1, 0xc6, + 0x7a, 0x2d, 0x28, 0xfc, + 0xed, 0x84, 0x9e, 0xe1, + 0xbb, 0x76, 0xe7, 0x39, + 0x1b, 0x93, 0xeb, 0x12, + ], + output_str: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + }, + Test { + input: "The quick brown fox jumps over the lazy cog", + output: [ + 0xde, 0x9f, 0x2c, 0x7f, + 0xd2, 0x5e, 0x1b, 0x3a, + 0xfa, 0xd3, 0xe8, 0x5a, + 0x0b, 0xd1, 0x7d, 0x9b, + 0x10, 0x0d, 0xb4, 0xb3, + ], + output_str: "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = sha1::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = sha1::Hash::engine(); + for ch in test.input.as_bytes() { + engine.input(&[*ch]); + } + let manual_hash = sha1::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } +} + +#[test] +#[cfg(feature = "serde")] +fn sha1_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + use crate::sha1; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 20] = [ + 0x13, 0x20, 0x72, 0xdf, + 0x69, 0x09, 0x33, 0x83, + 0x5e, 0xb8, 0xb6, 0xad, + 0x0b, 0x77, 0xe7, 0xb6, + 0xf1, 0x4a, 0xca, 0xd7, + ]; + + let hash = sha1::Hash::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens(&hash.readable(), &[Token::Str("132072df690933835eb8b6ad0b77e7b6f14acad7")]); +} diff --git a/hashes/src/sha256/benches.rs b/hashes/src/sha256/benches.rs new file mode 100644 index 000000000..f6e270d90 --- /dev/null +++ b/hashes/src/sha256/benches.rs @@ -0,0 +1,33 @@ +use test::Bencher; + +use crate::{sha256, Hash, HashEngine}; + +#[bench] +pub fn sha256_10(bh: &mut Bencher) { + let mut engine = sha256::Hash::engine(); + let bytes = [1u8; 10]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha256_1k(bh: &mut Bencher) { + let mut engine = sha256::Hash::engine(); + let bytes = [1u8; 1024]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha256_64k(bh: &mut Bencher) { + let mut engine = sha256::Hash::engine(); + let bytes = [1u8; 65536]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} diff --git a/hashes/src/sha256/crypto.rs b/hashes/src/sha256/crypto.rs new file mode 100644 index 000000000..905a58488 --- /dev/null +++ b/hashes/src/sha256/crypto.rs @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: CC0-1.0 + +#[cfg(all(feature = "std", target_arch = "x86"))] +use core::arch::x86::*; +#[cfg(all(feature = "std", target_arch = "x86_64"))] +use core::arch::x86_64::*; + +use internals::slice::SliceExt; + +use super::{HashEngine, Midstate, BLOCK_SIZE}; + +#[allow(non_snake_case)] +const fn Ch(x: u32, y: u32, z: u32) -> u32 { z ^ (x & (y ^ z)) } +#[allow(non_snake_case)] +const fn Maj(x: u32, y: u32, z: u32) -> u32 { (x & y) | (z & (x | y)) } +#[allow(non_snake_case)] +const fn Sigma0(x: u32) -> u32 { x.rotate_left(30) ^ x.rotate_left(19) ^ x.rotate_left(10) } +#[allow(non_snake_case)] +const fn Sigma1(x: u32) -> u32 { x.rotate_left(26) ^ x.rotate_left(21) ^ x.rotate_left(7) } +const fn sigma0(x: u32) -> u32 { x.rotate_left(25) ^ x.rotate_left(14) ^ (x >> 3) } +const fn sigma1(x: u32) -> u32 { x.rotate_left(15) ^ x.rotate_left(13) ^ (x >> 10) } + +#[cfg(feature = "small-hash")] +#[macro_use] +mod small_hash { + use super::*; + + #[rustfmt::skip] + pub(super) const fn round(a: u32, b: u32, c: u32, d: u32, e: u32, + f: u32, g: u32, h: u32, k: u32, w: u32) -> (u32, u32) { + let t1 = + h.wrapping_add(Sigma1(e)).wrapping_add(Ch(e, f, g)).wrapping_add(k).wrapping_add(w); + let t2 = Sigma0(a).wrapping_add(Maj(a, b, c)); + (d.wrapping_add(t1), t1.wrapping_add(t2)) + } + #[rustfmt::skip] + pub(super) const fn later_round(a: u32, b: u32, c: u32, d: u32, e: u32, + f: u32, g: u32, h: u32, k: u32, w: u32, + w1: u32, w2: u32, w3: u32, + ) -> (u32, u32, u32) { + let w = w.wrapping_add(sigma1(w1)).wrapping_add(w2).wrapping_add(sigma0(w3)); + let (d, h) = round(a, b, c, d, e, f, g, h, k, w); + (d, h, w) + } + + macro_rules! round( + // first round + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => ( + let updates = small_hash::round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w); + $d = updates.0; + $h = updates.1; + ); + // later rounds we reassign $w before doing the first-round computation + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => ( + let updates = small_hash::later_round($a, $b, $c, $d, $e, $f, $g, $h, $k, $w, $w1, $w2, $w3); + $d = updates.0; + $h = updates.1; + $w = updates.2; + ) + ); +} + +#[cfg(not(feature = "small-hash"))] +#[macro_use] +mod fast_hash { + macro_rules! round( + // first round + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => ( + let t1 = $h.wrapping_add(Sigma1($e)).wrapping_add(Ch($e, $f, $g)).wrapping_add($k).wrapping_add($w); + let t2 = Sigma0($a).wrapping_add(Maj($a, $b, $c)); + $d = $d.wrapping_add(t1); + $h = t1.wrapping_add(t2); + ); + // later rounds we reassign $w before doing the first-round computation + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => ( + $w = $w.wrapping_add(sigma1($w1)).wrapping_add($w2).wrapping_add(sigma0($w3)); + round!($a, $b, $c, $d, $e, $f, $g, $h, $k, $w); + ) + ); +} + +impl Midstate { + #[allow(clippy::identity_op)] // more readable + const fn read_u32(bytes: &[u8], index: usize) -> u32 { + ((bytes[index + 0] as u32) << 24) + | ((bytes[index + 1] as u32) << 16) + | ((bytes[index + 2] as u32) << 8) + | ((bytes[index + 3] as u32) << 0) + } + + const fn copy_w(bytes: &[u8], index: usize) -> [u32; 16] { + let mut w = [0u32; 16]; + let mut i = 0; + while i < 16 { + w[i] = Self::read_u32(bytes, index + i * 4); + i += 1; + } + w + } + + pub(super) const fn compute_midstate_unoptimized(bytes: &[u8], finalize: bool) -> Self { + let mut state = [ + 0x6a09e667u32, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19, + ]; + + let num_chunks = (bytes.len() + 9).div_ceil(64); + let mut chunk = 0; + #[allow(clippy::precedence)] + while chunk < num_chunks { + if !finalize && chunk + 1 == num_chunks { + break; + } + let mut w = if chunk * 64 + 64 <= bytes.len() { + Self::copy_w(bytes, chunk * 64) + } else { + let mut buf = [0; 64]; + let mut i = 0; + let offset = chunk * 64; + while offset + i < bytes.len() { + buf[i] = bytes[offset + i]; + i += 1; + } + if (bytes.len() % 64 <= 64 - 9) || (chunk + 2 == num_chunks) { + buf[i] = 0x80; + } + #[allow(clippy::identity_op)] // more readable + #[allow(clippy::erasing_op)] + if chunk + 1 == num_chunks { + let bit_len = bytes.len() as u64 * 8; + buf[64 - 8] = ((bit_len >> 8 * 7) & 0xFF) as u8; + buf[64 - 7] = ((bit_len >> 8 * 6) & 0xFF) as u8; + buf[64 - 6] = ((bit_len >> 8 * 5) & 0xFF) as u8; + buf[64 - 5] = ((bit_len >> 8 * 4) & 0xFF) as u8; + buf[64 - 4] = ((bit_len >> 8 * 3) & 0xFF) as u8; + buf[64 - 3] = ((bit_len >> 8 * 2) & 0xFF) as u8; + buf[64 - 2] = ((bit_len >> 8 * 1) & 0xFF) as u8; + buf[64 - 1] = ((bit_len >> 8 * 0) & 0xFF) as u8; + } + Self::copy_w(&buf, 0) + }; + chunk += 1; + + let mut a = state[0]; + let mut b = state[1]; + let mut c = state[2]; + let mut d = state[3]; + let mut e = state[4]; + let mut f = state[5]; + let mut g = state[6]; + let mut h = state[7]; + + round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]); + round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]); + round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]); + round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]); + round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]); + round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]); + round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]); + round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]); + round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]); + round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]); + round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]); + round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]); + round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]); + round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]); + round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]); + round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]); + + round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]); + + state[0] = state[0].wrapping_add(a); + state[1] = state[1].wrapping_add(b); + state[2] = state[2].wrapping_add(c); + state[3] = state[3].wrapping_add(d); + state[4] = state[4].wrapping_add(e); + state[5] = state[5].wrapping_add(f); + state[6] = state[6].wrapping_add(g); + state[7] = state[7].wrapping_add(h); + } + let mut output = [0u8; 32]; + let mut i = 0; + #[allow(clippy::identity_op)] // more readable + while i < 8 { + output[i * 4 + 0] = (state[i + 0] >> 24) as u8; + output[i * 4 + 1] = (state[i + 0] >> 16) as u8; + output[i * 4 + 2] = (state[i + 0] >> 8) as u8; + output[i * 4 + 3] = (state[i + 0] >> 0) as u8; + i += 1; + } + Self { bytes: output, bytes_hashed: bytes.len() as u64 } + } +} + +impl HashEngine { + pub(super) fn process_block(&mut self) { + #[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))] + { + if std::is_x86_feature_detected!("sse4.1") + && std::is_x86_feature_detected!("sha") + && std::is_x86_feature_detected!("sse2") + && std::is_x86_feature_detected!("ssse3") + { + return unsafe { self.process_block_simd_x86_intrinsics() }; + } + } + + // fallback implementation without using any intrinsics + self.software_process_block() + } + + #[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))] + #[target_feature(enable = "sha,sse2,ssse3,sse4.1")] + unsafe fn process_block_simd_x86_intrinsics(&mut self) { + // Code translated and based on from + // https://github.com/noloader/SHA-Intrinsics/blob/4899efc81d1af159c1fd955936c673139f35aea9/sha256-x86.c + + /* sha256-x86.c - Intel SHA extensions using C intrinsics */ + /* Written and place in public domain by Jeffrey Walton */ + /* Based on code from Intel, and by Sean Gulley for */ + /* the miTLS project. */ + + // Variable names are also kept the same as in the original C code for easier comparison. + let (mut state0, mut state1); + let (mut msg, mut tmp); + + let (mut msg0, mut msg1, mut msg2, mut msg3); + + let (abef_save, cdgh_save); + + #[allow(non_snake_case)] + let MASK: __m128i = + _mm_set_epi64x(0x0c0d_0e0f_0809_0a0bu64 as i64, 0x0405_0607_0001_0203u64 as i64); + + let block_offset = 0; + + // Load initial values + // CAST SAFETY: loadu_si128 documentation states that mem_addr does not + // need to be aligned on any particular boundary. + tmp = _mm_loadu_si128(self.h.as_ptr().add(0).cast::<__m128i>()); + state1 = _mm_loadu_si128(self.h.as_ptr().add(4).cast::<__m128i>()); + + tmp = _mm_shuffle_epi32(tmp, 0xB1); // CDAB + state1 = _mm_shuffle_epi32(state1, 0x1B); // EFGH + state0 = _mm_alignr_epi8(tmp, state1, 8); // ABEF + state1 = _mm_blend_epi16(state1, tmp, 0xF0); // CDGH + + // Process a single block + { + // Save current state + abef_save = state0; + cdgh_save = state1; + + // Rounds 0-3 + msg = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset).cast::<__m128i>()); + msg0 = _mm_shuffle_epi8(msg, MASK); + msg = _mm_add_epi32( + msg0, + _mm_set_epi64x(0xE9B5DBA5B5C0FBCFu64 as i64, 0x71374491428A2F98u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + + // Rounds 4-7 + msg1 = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset + 16).cast::<__m128i>()); + msg1 = _mm_shuffle_epi8(msg1, MASK); + msg = _mm_add_epi32( + msg1, + _mm_set_epi64x(0xAB1C5ED5923F82A4u64 as i64, 0x59F111F13956C25Bu64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg0 = _mm_sha256msg1_epu32(msg0, msg1); + + // Rounds 8-11 + msg2 = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset + 32).cast::<__m128i>()); + msg2 = _mm_shuffle_epi8(msg2, MASK); + msg = _mm_add_epi32( + msg2, + _mm_set_epi64x(0x550C7DC3243185BEu64 as i64, 0x12835B01D807AA98u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg1 = _mm_sha256msg1_epu32(msg1, msg2); + + // Rounds 12-15 + msg3 = _mm_loadu_si128(self.buffer.as_ptr().add(block_offset + 48).cast::<__m128i>()); + msg3 = _mm_shuffle_epi8(msg3, MASK); + msg = _mm_add_epi32( + msg3, + _mm_set_epi64x(0xC19BF1749BDC06A7u64 as i64, 0x80DEB1FE72BE5D74u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg3, msg2, 4); + msg0 = _mm_add_epi32(msg0, tmp); + msg0 = _mm_sha256msg2_epu32(msg0, msg3); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg2 = _mm_sha256msg1_epu32(msg2, msg3); + + // Rounds 16-19 + msg = _mm_add_epi32( + msg0, + _mm_set_epi64x(0x240CA1CC0FC19DC6u64 as i64, 0xEFBE4786E49B69C1u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg0, msg3, 4); + msg1 = _mm_add_epi32(msg1, tmp); + msg1 = _mm_sha256msg2_epu32(msg1, msg0); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg3 = _mm_sha256msg1_epu32(msg3, msg0); + + // Rounds 20-23 + msg = _mm_add_epi32( + msg1, + _mm_set_epi64x(0x76F988DA5CB0A9DCu64 as i64, 0x4A7484AA2DE92C6Fu64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg1, msg0, 4); + msg2 = _mm_add_epi32(msg2, tmp); + msg2 = _mm_sha256msg2_epu32(msg2, msg1); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg0 = _mm_sha256msg1_epu32(msg0, msg1); + + // Rounds 24-27 + msg = _mm_add_epi32( + msg2, + _mm_set_epi64x(0xBF597FC7B00327C8u64 as i64, 0xA831C66D983E5152u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg2, msg1, 4); + msg3 = _mm_add_epi32(msg3, tmp); + msg3 = _mm_sha256msg2_epu32(msg3, msg2); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg1 = _mm_sha256msg1_epu32(msg1, msg2); + + // Rounds 28-31 + msg = _mm_add_epi32( + msg3, + _mm_set_epi64x(0x1429296706CA6351u64 as i64, 0xD5A79147C6E00BF3u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg3, msg2, 4); + msg0 = _mm_add_epi32(msg0, tmp); + msg0 = _mm_sha256msg2_epu32(msg0, msg3); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg2 = _mm_sha256msg1_epu32(msg2, msg3); + + // Rounds 32-35 + msg = _mm_add_epi32( + msg0, + _mm_set_epi64x(0x53380D134D2C6DFCu64 as i64, 0x2E1B213827B70A85u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg0, msg3, 4); + msg1 = _mm_add_epi32(msg1, tmp); + msg1 = _mm_sha256msg2_epu32(msg1, msg0); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg3 = _mm_sha256msg1_epu32(msg3, msg0); + + // Rounds 36-39 + msg = _mm_add_epi32( + msg1, + _mm_set_epi64x(0x92722C8581C2C92Eu64 as i64, 0x766A0ABB650A7354u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg1, msg0, 4); + msg2 = _mm_add_epi32(msg2, tmp); + msg2 = _mm_sha256msg2_epu32(msg2, msg1); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg0 = _mm_sha256msg1_epu32(msg0, msg1); + + // Rounds 40-43 + msg = _mm_add_epi32( + msg2, + _mm_set_epi64x(0xC76C51A3C24B8B70u64 as i64, 0xA81A664BA2BFE8A1u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg2, msg1, 4); + msg3 = _mm_add_epi32(msg3, tmp); + msg3 = _mm_sha256msg2_epu32(msg3, msg2); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg1 = _mm_sha256msg1_epu32(msg1, msg2); + + // Rounds 44-47 + msg = _mm_add_epi32( + msg3, + _mm_set_epi64x(0x106AA070F40E3585u64 as i64, 0xD6990624D192E819u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg3, msg2, 4); + msg0 = _mm_add_epi32(msg0, tmp); + msg0 = _mm_sha256msg2_epu32(msg0, msg3); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg2 = _mm_sha256msg1_epu32(msg2, msg3); + + // Rounds 48-51 + msg = _mm_add_epi32( + msg0, + _mm_set_epi64x(0x34B0BCB52748774Cu64 as i64, 0x1E376C0819A4C116u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg0, msg3, 4); + msg1 = _mm_add_epi32(msg1, tmp); + msg1 = _mm_sha256msg2_epu32(msg1, msg0); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + msg3 = _mm_sha256msg1_epu32(msg3, msg0); + + // Rounds 52-55 + msg = _mm_add_epi32( + msg1, + _mm_set_epi64x(0x682E6FF35B9CCA4Fu64 as i64, 0x4ED8AA4A391C0CB3u64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg1, msg0, 4); + msg2 = _mm_add_epi32(msg2, tmp); + msg2 = _mm_sha256msg2_epu32(msg2, msg1); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + + // Rounds 56-59 + msg = _mm_add_epi32( + msg2, + _mm_set_epi64x(0x8CC7020884C87814u64 as i64, 0x78A5636F748F82EEu64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + tmp = _mm_alignr_epi8(msg2, msg1, 4); + msg3 = _mm_add_epi32(msg3, tmp); + msg3 = _mm_sha256msg2_epu32(msg3, msg2); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + + // Rounds 60-63 + msg = _mm_add_epi32( + msg3, + _mm_set_epi64x(0xC67178F2BEF9A3F7u64 as i64, 0xA4506CEB90BEFFFAu64 as i64), + ); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + msg = _mm_shuffle_epi32(msg, 0x0E); + state0 = _mm_sha256rnds2_epu32(state0, state1, msg); + + // Combine state + state0 = _mm_add_epi32(state0, abef_save); + state1 = _mm_add_epi32(state1, cdgh_save); + } + + tmp = _mm_shuffle_epi32(state0, 0x1B); // FEBA + state1 = _mm_shuffle_epi32(state1, 0xB1); // DCHG + state0 = _mm_blend_epi16(tmp, state1, 0xF0); // DCBA + state1 = _mm_alignr_epi8(state1, tmp, 8); // ABEF + + // Save state + // CAST SAFETY: storeu_si128 documentation states that mem_addr does not + // need to be aligned on any particular boundary. + _mm_storeu_si128(self.h.as_mut_ptr().add(0).cast::<__m128i>(), state0); + _mm_storeu_si128(self.h.as_mut_ptr().add(4).cast::<__m128i>(), state1); + } + + // Algorithm copied from libsecp256k1 + fn software_process_block(&mut self) { + debug_assert_eq!(self.buffer.len(), BLOCK_SIZE); + + let mut w = [0u32; 16]; + for (w_val, buff_bytes) in w.iter_mut().zip(self.buffer.bitcoin_as_chunks().0) { + *w_val = u32::from_be_bytes(*buff_bytes); + } + + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut h = self.h[7]; + + round!(a, b, c, d, e, f, g, h, 0x428a2f98, w[0]); + round!(h, a, b, c, d, e, f, g, 0x71374491, w[1]); + round!(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w[2]); + round!(f, g, h, a, b, c, d, e, 0xe9b5dba5, w[3]); + round!(e, f, g, h, a, b, c, d, 0x3956c25b, w[4]); + round!(d, e, f, g, h, a, b, c, 0x59f111f1, w[5]); + round!(c, d, e, f, g, h, a, b, 0x923f82a4, w[6]); + round!(b, c, d, e, f, g, h, a, 0xab1c5ed5, w[7]); + round!(a, b, c, d, e, f, g, h, 0xd807aa98, w[8]); + round!(h, a, b, c, d, e, f, g, 0x12835b01, w[9]); + round!(g, h, a, b, c, d, e, f, 0x243185be, w[10]); + round!(f, g, h, a, b, c, d, e, 0x550c7dc3, w[11]); + round!(e, f, g, h, a, b, c, d, 0x72be5d74, w[12]); + round!(d, e, f, g, h, a, b, c, 0x80deb1fe, w[13]); + round!(c, d, e, f, g, h, a, b, 0x9bdc06a7, w[14]); + round!(b, c, d, e, f, g, h, a, 0xc19bf174, w[15]); + + round!(a, b, c, d, e, f, g, h, 0xe49b69c1, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0xefbe4786, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x0fc19dc6, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x240ca1cc, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x2de92c6f, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x4a7484aa, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x76f988da, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x983e5152, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0xa831c66d, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0xb00327c8, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0xbf597fc7, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0xc6e00bf3, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xd5a79147, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0x06ca6351, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x14292967, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0x27b70a85, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0x2e1b2138, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x53380d13, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x650a7354, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x766a0abb, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x81c2c92e, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x92722c85, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0xa81a664b, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0xc24b8b70, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0xc76c51a3, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0xd192e819, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xd6990624, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0xf40e3585, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x106aa070, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0x19a4c116, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0x1e376c08, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x2748774c, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x34b0bcb5, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x391c0cb3, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x5b9cca4f, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x682e6ff3, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x748f82ee, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0x78a5636f, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0x84c87814, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0x8cc70208, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0x90befffa, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xa4506ceb, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0xbef9a3f7, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0xc67178f2, w[15], w[13], w[8], w[0]); + let _ = w[15]; // silence "unnecessary assignment" lint in macro + + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(h); + } +} diff --git a/hashes/src/sha256/mod.rs b/hashes/src/sha256/mod.rs new file mode 100644 index 000000000..6633c6737 --- /dev/null +++ b/hashes/src/sha256/mod.rs @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA256 implementation. + +mod crypto; +#[cfg(test)] +mod tests; + +use core::{cmp, convert, fmt}; + +use internals::slice::SliceExt; + +use crate::{incomplete_block_len, sha256d, HashEngine as _}; +#[cfg(doc)] +use crate::{sha256t, sha256t_tag}; + +crate::internal_macros::general_hash_type! { + 256, + false, + "Output of the SHA256 hash function." +} + +const BLOCK_SIZE: usize = 64; + +/// Engine to compute SHA256 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine { + buffer: [u8; BLOCK_SIZE], + h: [u32; 8], + bytes_hashed: u64, +} + +impl HashEngine { + /// Constructs a new SHA256 hash engine. + pub const fn new() -> Self { + Self { + h: [ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, + 0x5be0cd19, + ], + bytes_hashed: 0, + buffer: [0; BLOCK_SIZE], + } + } + + /// Constructs a new [`HashEngine`] from a [`Midstate`]. + /// + /// Please see docs on [`Midstate`] before using this function. + pub fn from_midstate(midstate: Midstate) -> Self { + let mut ret = [0; 8]; + for (ret_val, midstate_bytes) in ret.iter_mut().zip(midstate.as_ref().bitcoin_as_chunks().0) + { + *ret_val = u32::from_be_bytes(*midstate_bytes); + } + + Self { buffer: [0; BLOCK_SIZE], h: ret, bytes_hashed: midstate.bytes_hashed } + } + + /// Returns `true` if the midstate can be extracted from this engine. + /// + /// The midstate can only be extracted if the number of bytes input into + /// the hash engine is a multiple of 64. See caveat on [`Self::midstate`]. + /// + /// Please see docs on [`Midstate`] before using this function. + pub const fn can_extract_midstate(&self) -> bool { self.bytes_hashed % 64 == 0 } + + /// Outputs the midstate of the hash engine. + /// + /// Please see docs on [`Midstate`] before using this function. + pub fn midstate(&self) -> Result { + if !self.can_extract_midstate() { + return Err(MidstateError { invalid_n_bytes_hashed: self.bytes_hashed }); + } + Ok(self.midstate_unchecked()) + } + + // Does not check that `HashEngine::can_extract_midstate`. + #[cfg(not(hashes_fuzz))] + fn midstate_unchecked(&self) -> Midstate { + let mut ret = [0; 32]; + for (val, ret_bytes) in self.h.iter().zip(ret.bitcoin_as_chunks_mut::<4>().0) { + *ret_bytes = val.to_be_bytes(); + } + Midstate { bytes: ret, bytes_hashed: self.bytes_hashed } + } + + // Does not check that `HashEngine::can_extract_midstate`. + #[cfg(hashes_fuzz)] + fn midstate_unchecked(&self) -> Midstate { + let mut ret = [0; 32]; + ret.copy_from_slice(&self.buffer[..32]); + Midstate { bytes: ret, bytes_hashed: self.bytes_hashed } + } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 32]; + const BLOCK_SIZE: usize = 64; + + fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } + crate::internal_macros::engine_input_impl!(); + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +impl Hash { + /// Finalize a hash engine to obtain a hash. + #[cfg(not(hashes_fuzz))] + pub fn from_engine(mut e: HashEngine) -> Self { + // pad buffer with a single 1-bit then all 0s, until there are exactly 8 bytes remaining + let n_bytes_hashed = e.bytes_hashed; + + let zeroes = [0; BLOCK_SIZE - 8]; + e.input(&[0x80]); + if incomplete_block_len(&e) > zeroes.len() { + e.input(&zeroes); + } + let pad_length = zeroes.len() - incomplete_block_len(&e); + e.input(&zeroes[..pad_length]); + debug_assert_eq!(incomplete_block_len(&e), zeroes.len()); + + e.input(&(8 * n_bytes_hashed).to_be_bytes()); + debug_assert_eq!(incomplete_block_len(&e), 0); + + Self(e.midstate_unchecked().bytes) + } + + /// Finalize a hash engine to obtain a hash. + #[cfg(hashes_fuzz)] + pub fn from_engine(e: HashEngine) -> Self { + let mut hash = e.midstate_unchecked().bytes; + if hash == [0; 32] { + // Assume sha256 is secure and never generate 0-hashes (which represent invalid + // secp256k1 secret keys, causing downstream application breakage). + hash[0] = 1; + } + Hash(hash) + } + + /// Iterate the sha256 algorithm to turn a sha256 hash into a sha256d hash + #[must_use] + pub fn hash_again(&self) -> sha256d::Hash { sha256d::Hash::from_byte_array(hash(&self.0).0) } + + /// Computes hash from `bytes` in `const` context. + /// + /// Warning: this function is inefficient. It should be only used in `const` context. + pub const fn hash_unoptimized(bytes: &[u8]) -> Self { + Self(Midstate::compute_midstate_unoptimized(bytes, true).bytes) + } +} + +/// Unfinalized output of the SHA256 hash function. +/// +/// The `Midstate` type is obscure and specialized and should not be used unless you are sure of +/// what you are doing. +/// +/// It represents "partially hashed data" but does not itself have properties of cryptographic +/// hashes. For example, when (ab)used as hashes, midstates are vulnerable to trivial +/// length-extension attacks. They are typically used to optimize the computation of full hashes. +/// For example, when implementing BIP-0340 tagged hashes, which always begin by hashing the same +/// fixed 64-byte prefix, it makes sense to hash the prefix once, store the midstate as a constant, +/// and hash any future data starting from the constant rather than from a fresh hash engine. +/// +/// For BIP-0340 support we provide the [`sha256t`] module, and the [`sha256t_tag`] macro which will +/// create the midstate for you in const context. +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Midstate { + /// Raw bytes of the midstate i.e., the already-hashed contents of the hash engine. + bytes: [u8; 32], + /// Number of bytes hashed to achieve this midstate. + // INVARIANT must always be a multiple of 64. + bytes_hashed: u64, +} + +impl Midstate { + /// Constructs a new [`Midstate`] from the `state` and the `bytes_hashed` to get to that state. + /// + /// # Panics + /// + /// Panics if `bytes_hashed` is not a multiple of 64. + pub const fn new(state: [u8; 32], bytes_hashed: u64) -> Self { + if bytes_hashed % 64 != 0 { + panic!("bytes hashed is not a multiple of 64"); + } + + Self { bytes: state, bytes_hashed } + } + + /// Deconstructs the [`Midstate`], returning the underlying byte array and number of bytes hashed. + pub const fn as_parts(&self) -> (&[u8; 32], u64) { (&self.bytes, self.bytes_hashed) } + + /// Deconstructs the [`Midstate`], returning the underlying byte array and number of bytes hashed. + pub const fn to_parts(self) -> ([u8; 32], u64) { (self.bytes, self.bytes_hashed) } + + /// Constructs a new midstate for tagged hashes. + /// + /// Warning: this function is inefficient. It should be only used in `const` context. + /// + /// Computes non-finalized hash of `sha256(tag) || sha256(tag)` for use in [`sha256t`]. It's + /// provided for use with [`sha256t`]. + #[must_use] + pub const fn hash_tag(tag: &[u8]) -> Self { + let hash = Hash::hash_unoptimized(tag); + let mut buf = [0u8; 64]; + let mut i = 0usize; + while i < buf.len() { + buf[i] = hash.0[i % hash.0.len()]; + i += 1; + } + Self::compute_midstate_unoptimized(&buf, false) + } +} + +impl fmt::Debug for Midstate { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + struct Encoder<'a> { + bytes: &'a [u8; 32], + } + impl fmt::Debug for Encoder<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { crate::debug_hex(self.bytes, f) } + } + + f.debug_struct("Midstate") + .field("bytes", &Encoder { bytes: &self.bytes }) + .field("length", &self.bytes_hashed) + .finish() + } +} + +impl convert::AsRef<[u8]> for Midstate { + fn as_ref(&self) -> &[u8] { &self.bytes } +} + +/// `Midstate` invariant violated (not a multiple of 64). +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct MidstateError { + /// The invalid number of bytes hashed. + invalid_n_bytes_hashed: u64, +} + +impl fmt::Display for MidstateError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "invalid number of bytes hashed {} (should have been a multiple of 64)", + self.invalid_n_bytes_hashed + ) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for MidstateError {} diff --git a/hashes/src/sha256/tests.rs b/hashes/src/sha256/tests.rs new file mode 100644 index 000000000..b320969eb --- /dev/null +++ b/hashes/src/sha256/tests.rs @@ -0,0 +1,231 @@ +use core::array; + +use super::*; +use crate::{sha256, HashEngine}; + +#[test] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +fn test() { + use alloc::string::ToString; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 32], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Examples from wikipedia + Test { + input: "", + output: [ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, + ], + output_str: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + Test { + input: "The quick brown fox jumps over the lazy dog", + output: [ + 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, + 0x69, 0xca, 0x9a, 0xbc, 0xb0, 0x08, 0x2e, 0x4f, + 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, + 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92, + ], + output_str: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", + }, + Test { + input: "The quick brown fox jumps over the lazy dog.", + output: [ + 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7, + 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97, + 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2, + 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c, + ], + output_str: "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = sha256::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = sha256::Hash::engine(); + for ch in test.input.as_bytes() { + engine.input(&[*ch]); + } + let manual_hash = sha256::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } +} + +#[test] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +fn fmt_roundtrips() { + use alloc::format; + + let hash = sha256::Hash::hash(b"some arbitrary bytes"); + let hex = format!("{}", hash); + let roundtrip = hex.parse::().expect("failed to parse hex"); + assert_eq!(roundtrip, hash) +} + +#[test] +#[rustfmt::skip] +fn midstate() { + // Test vector obtained by doing an asset issuance on Elements + let mut engine = sha256::Hash::engine(); + // sha256dhash of outpoint + // 73828cbc65fd68ab78dc86992b76ae50ae2bf8ceedbe8de0483172f0886219f7:0 + engine.input(&[ + 0x9d, 0xd0, 0x1b, 0x56, 0xb1, 0x56, 0x45, 0x14, + 0x3e, 0xad, 0x15, 0x8d, 0xec, 0x19, 0xf8, 0xce, + 0xa9, 0x0b, 0xd0, 0xa9, 0xb2, 0xf8, 0x1d, 0x21, + 0xff, 0xa3, 0xa4, 0xc6, 0x44, 0x81, 0xd4, 0x1c, + ]); + // 32 bytes of zeroes representing "new asset" + engine.input(&[0; 32]); + + // RPC output + static WANT: Midstate = sha256::Midstate::new([ + 0x0b, 0xcf, 0xe0, 0xe5, 0x4e, 0x6c, 0xc7, 0xd3, + 0x4f, 0x4f, 0x7c, 0x1d, 0xf0, 0xb0, 0xf5, 0x03, + 0xf2, 0xf7, 0x12, 0x91, 0x2a, 0x06, 0x05, 0xb4, + 0x14, 0xed, 0x33, 0x7f, 0x7f, 0x03, 0x2e, 0x03, + ], 64); + + assert_eq!( + engine.midstate().expect("total_bytes_hashed is valid"), + WANT, + ); +} + +#[test] +fn engine_with_state() { + let mut engine = sha256::Hash::engine(); + let midstate_engine = sha256::HashEngine::from_midstate(engine.midstate_unchecked()); + // Fresh engine and engine initialized with fresh state should have same state + assert_eq!(engine.h, midstate_engine.h); + + // Midstate changes after writing 64 bytes + engine.input(&[1; 63]); + assert_eq!(engine.h, midstate_engine.h); + engine.input(&[2; 1]); + assert_ne!(engine.h, midstate_engine.h); + + // Initializing an engine with midstate from another engine should result in + // both engines producing the same hashes + let data_vec: &[&[u8]] = &[&[3u8; 1], &[4u8; 63], &[5u8; 65], &[6u8; 66]]; + for data in data_vec { + let mut engine = engine.clone(); + let mut midstate_engine = sha256::HashEngine::from_midstate(engine.midstate_unchecked()); + assert_eq!(engine.h, midstate_engine.h); + assert_eq!(engine.bytes_hashed, midstate_engine.bytes_hashed); + engine.input(data); + midstate_engine.input(data); + assert_eq!(engine.h, midstate_engine.h); + let hash1 = sha256::Hash::from_engine(engine); + let hash2 = sha256::Hash::from_engine(midstate_engine); + assert_eq!(hash1, hash2); + } + + // Test that a specific midstate results in a specific hash. Midstate was + // obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig + // coefficient"). + #[rustfmt::skip] + static MIDSTATE: [u8; 32] = [ + 0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97, + 0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30, 0xd8, 0x64, + 0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f, + 0x6f, 0x43, 0xb8, 0x01, 0x85, 0xce, 0x27, 0xcd, + ]; + #[rustfmt::skip] + static HASH_EXPECTED: [u8; 32] = [ + 0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a, + 0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6, 0x23, 0xa8, + 0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20, + 0x8f, 0xf1, 0xf7, 0xa9, 0xd5, 0x69, 0x09, 0x59, + ]; + let midstate_engine = sha256::HashEngine::from_midstate(sha256::Midstate::new(MIDSTATE, 64)); + let hash = sha256::Hash::from_engine(midstate_engine); + assert_eq!(hash, sha256::Hash(HASH_EXPECTED)); +} + +#[test] +fn hash_unoptimized() { + let bytes: [u8; 256] = array::from_fn(|i| i as u8); + + for i in 0..=256 { + let bytes = &bytes[0..i]; + assert_eq!( + Hash::hash(bytes), + Hash::hash_unoptimized(bytes), + "hashes don't match for n_bytes_hashed {}", + i + 1 + ); + } +} + +// The midstate of an empty hash engine tagged with "TapLeaf". +#[cfg(feature = "alloc")] +const TAP_LEAF_MIDSTATE: Midstate = Midstate::new( + [ + 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, + 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, + ], + 64, +); + +#[test] +#[cfg(feature = "alloc")] +fn regression_midstate_debug_format() { + use alloc::format; + + let want = "Midstate { bytes: 9ce0e4e67c116c3938b3caf2c30f5089d3f3936c47636e607db33eeaddc6f0c9, length: 64 }"; + let got = format!("{:?}", TAP_LEAF_MIDSTATE); + assert_eq!(got, want); +} + +#[test] +#[cfg(feature = "serde")] +fn sha256_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 32] = [ + 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7, + 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97, + 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2, + 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c, + ]; + + let hash = sha256::Hash::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens( + &hash.readable(), + &[Token::Str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")], + ); +} + +#[cfg(target_arch = "wasm32")] +mod wasm_tests { + use super::*; + #[test] + #[wasm_bindgen_test::wasm_bindgen_test] + fn sha256_tests() { + test(); + midstate(); + engine_with_state(); + } +} diff --git a/hashes/src/sha256d/mod.rs b/hashes/src/sha256d/mod.rs new file mode 100644 index 000000000..f96497710 --- /dev/null +++ b/hashes/src/sha256d/mod.rs @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA256d implementation (double SHA256). + +use crate::sha256; + +crate::internal_macros::general_hash_type! { + 256, + true, + "Output of the SHA256d hash function." +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + pub fn from_engine(e: HashEngine) -> Self { + let sha2 = sha256::Hash::from_engine(e.0); + let sha2d = sha256::Hash::hash(sha2.as_byte_array()); + + let mut ret = [0; 32]; + ret.copy_from_slice(sha2d.as_byte_array()); + Self(ret) + } +} + +/// Engine to compute SHA256d hash function. +#[derive(Debug, Clone)] +pub struct HashEngine(sha256::HashEngine); + +impl HashEngine { + /// Constructs a new SHA256d hash engine. + pub const fn new() -> Self { Self(sha256::HashEngine::new()) } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 32]; + const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; + + fn input(&mut self, data: &[u8]) { self.0.input(data) } + fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +#[cfg(test)] +mod tests { + #[allow(unused_imports)] // whether this is used depends on features + use crate::sha256d; + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn test() { + use alloc::string::ToString; + + use crate::{sha256, HashEngine}; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 32], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Test vector copied out of rust-bitcoin + Test { + input: "", + output: [ + 0x5d, 0xf6, 0xe0, 0xe2, 0x76, 0x13, 0x59, 0xd3, + 0x0a, 0x82, 0x75, 0x05, 0x8e, 0x29, 0x9f, 0xcc, + 0x03, 0x81, 0x53, 0x45, 0x45, 0xf5, 0x5c, 0xf4, + 0x3e, 0x41, 0x98, 0x3f, 0x5d, 0x4c, 0x94, 0x56, + ], + output_str: "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = sha256d::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = sha256d::Hash::engine(); + for ch in test.input.as_bytes() { + engine.input(&[*ch]); + } + let manual_hash = sha256d::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + + // Hash by computing a sha256 then `hash_again`ing it + let sha2_hash = sha256::Hash::hash(test.input.as_bytes()); + let sha2d_hash = sha2_hash.hash_again(); + assert_eq!(hash, sha2d_hash); + + assert_eq!(hash.to_byte_array(), test.output); + } + } + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn fmt_roundtrips() { + use alloc::format; + + let hash = sha256d::Hash::hash(b"some arbitrary bytes"); + let hex = format!("{}", hash); + let roundtrip = hex.parse::().expect("failed to parse hex"); + assert_eq!(roundtrip, hash) + } + + #[test] + #[cfg(feature = "serde")] + fn sha256_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 32] = [ + 0xef, 0x53, 0x7f, 0x25, 0xc8, 0x95, 0xbf, 0xa7, + 0x82, 0x52, 0x65, 0x29, 0xa9, 0xb6, 0x3d, 0x97, + 0xaa, 0x63, 0x15, 0x64, 0xd5, 0xd7, 0x89, 0xc2, + 0xb7, 0x65, 0x44, 0x8c, 0x86, 0x35, 0xfb, 0x6c, + ]; + + let hash = sha256d::Hash::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens( + &hash.readable(), + &[Token::Str("6cfb35868c4465b7c289d7d5641563aa973db6a929655282a7bf95c8257f53ef")], + ); + } +} diff --git a/hashes/src/sha256t/mod.rs b/hashes/src/sha256t/mod.rs new file mode 100644 index 000000000..b7c73aa94 --- /dev/null +++ b/hashes/src/sha256t/mod.rs @@ -0,0 +1,293 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA256t implementation (tagged SHA256). + +use core::cmp; +use core::marker::PhantomData; + +#[cfg(doc)] +use crate::sha256::Midstate; +use crate::{sha256, HashEngine as _}; + +/// Hashes some bytes. +pub fn hash(data: &[u8]) -> Hash +where + T: Tag, +{ + use crate::HashEngine as _; + + let mut engine = HashEngine::default(); + engine.input(data); + engine.finalize() +} + +/// Hashes all the byte slices retrieved from the iterator together. +pub fn hash_byte_chunks(byte_slices: I) -> Hash +where + B: AsRef<[u8]>, + I: IntoIterator, + T: Tag, +{ + use crate::HashEngine as _; + + let mut engine = HashEngine::default(); + for slice in byte_slices { + engine.input(slice.as_ref()); + } + engine.finalize() +} + +/// Trait representing a tag that can be used as a context for SHA256t hashes. +pub trait Tag { + /// The [`Midstate`] after pre-tagging the hash engine. + const MIDSTATE: sha256::Midstate; +} + +internals::transparent_newtype! { + /// Output of the SHA256t hash function. + pub struct Hash(PhantomData, [u8; 32]); + + impl Hash { + /// Zero cost conversion between a fixed length byte array shared reference and + /// a shared reference to this Hash type. + pub fn from_bytes_ref(bytes: &_) -> &Self; + + /// Zero cost conversion between a fixed length byte array exclusive reference and + /// an exclusive reference to this Hash type. + pub fn from_bytes_mut(bytes: &mut _) -> &mut Self; + } +} + +impl Hash +where + T: Tag, +{ + /// Constructs a new hash from the underlying byte array. + pub const fn from_byte_array(bytes: [u8; 32]) -> Self { Self(PhantomData, bytes) } + + /// Produces a hash from the current state of a given engine. + pub fn from_engine(e: HashEngine) -> Self { + Self::from_byte_array(sha256::Hash::from_engine(e.0).to_byte_array()) + } + + /// Constructs a new engine. + pub fn engine() -> HashEngine { HashEngine::default() } + + /// Hashes some bytes. + #[allow(clippy::self_named_constructors)] // Hash is a noun and a verb. + pub fn hash(data: &[u8]) -> Self { + use crate::HashEngine; + + let mut engine = Self::engine(); + engine.input(data); + Self::from_engine(engine) + } + + /// Hashes all the byte slices retrieved from the iterator together. + pub fn hash_byte_chunks(byte_slices: I) -> Self + where + B: AsRef<[u8]>, + I: IntoIterator, + { + let mut engine = Self::engine(); + for slice in byte_slices { + engine.input(slice.as_ref()); + } + Self::from_engine(engine) + } + + /// Returns the underlying byte array. + pub const fn to_byte_array(self) -> [u8; 32] { self.1 } + + /// Returns a reference to the underlying byte array. + pub const fn as_byte_array(&self) -> &[u8; 32] { &self.1 } +} + +impl Copy for Hash {} +impl Clone for Hash { + fn clone(&self) -> Self { *self } +} +impl PartialEq for Hash { + fn eq(&self, other: &Self) -> bool { self.as_byte_array() == other.as_byte_array() } +} +impl Eq for Hash {} +impl PartialOrd for Hash { + fn partial_cmp(&self, other: &Self) -> Option { + Some(cmp::Ord::cmp(self, other)) + } +} +impl Ord for Hash { + fn cmp(&self, other: &Self) -> cmp::Ordering { + cmp::Ord::cmp(&self.as_byte_array(), &other.as_byte_array()) + } +} +impl core::hash::Hash for Hash { + fn hash(&self, h: &mut H) { self.as_byte_array().hash(h) } +} + +crate::internal_macros::hash_trait_impls!(256, false, T: Tag); + +/// Engine to compute SHA256t hash function. +#[derive(Debug)] +pub struct HashEngine(sha256::HashEngine, PhantomData); + +impl Default for HashEngine { + fn default() -> Self { + let tagged = sha256::HashEngine::from_midstate(T::MIDSTATE); + Self(tagged, PhantomData) + } +} + +impl Clone for HashEngine { + fn clone(&self) -> Self { Self(self.0.clone(), PhantomData) } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 32]; + const BLOCK_SIZE: usize = 64; // Same as sha256::HashEngine::BLOCK_SIZE; + + fn input(&mut self, data: &[u8]) { self.0.input(data) } + fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +crate::internal_macros::impl_write!( + HashEngine, + |us: &mut HashEngine, buf| { + us.input(buf); + Ok(buf.len()) + }, + |_us| { Ok(()) }, + T: crate::sha256t::Tag +); + +// Workaround macros being unavailable in attributes. +#[doc(hidden)] +#[macro_export] +macro_rules! sha256t_tag_struct { + ($vis:vis, $tag:ident, $name:expr, $(#[$($attr:meta)*])*) => { + #[doc = "The tag used for [`"] + #[doc = $name] + #[doc = "`].\n\n"] + $(#[$($attr)*])* + #[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] + $vis struct $tag; + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! sha256t_tag_constructor { + (hash_str, $value:expr) => { + $crate::sha256::Midstate::hash_tag($value.as_bytes()) + }; + (hash_bytes, $value:expr) => { + $crate::sha256::Midstate::hash_tag($value) + }; + (raw, $bytes:expr, $len:expr) => { + $crate::sha256::Midstate::new($bytes, $len) + }; +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "alloc")] + use crate::sha256; + use crate::sha256t; + + const TEST_MIDSTATE: [u8; 32] = [ + 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, + 108, 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, + ]; + + // The digest created by sha256 hashing `&[0]` starting with `TEST_MIDSTATE`. + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + const HASH_ZERO_BACKWARD: &str = + "29589d5122ec666ab5b4695070b6debc63881a4f85d88d93ddc90078038213ed"; + // And the same thing, forward. + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + const HASH_ZERO_FORWARD: &str = + "ed1382037800c9dd938dd8854f1a8863bcdeb6705069b4b56a66ec22519d5829"; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] + #[cfg(feature = "alloc")] + pub struct TestHashTag; + + #[cfg(feature = "alloc")] + impl sha256t::Tag for TestHashTag { + const MIDSTATE: sha256::Midstate = sha256::Midstate::new(TEST_MIDSTATE, 64); + } + + // We support manually implementing `Tag` and creating a tagged hash from it. + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + pub type TestHash = sha256t::Hash; + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn manually_created_sha256t_hash_type() { + use alloc::string::ToString; + + assert_eq!(TestHash::hash(&[0]).to_string(), HASH_ZERO_FORWARD); + } + + // We also provide macros to create the tag and the hash type. + sha256t_tag! { + /// Test detailed explanation. + struct NewTypeTagBackward = raw(TEST_MIDSTATE, 64); + } + hash_newtype! { + /// A test hash. + #[hash_newtype(backward)] + struct NewTypeHashBackward(sha256t::Hash); + } + #[cfg(feature = "hex")] + crate::impl_hex_for_newtype!(NewTypeHashBackward); + #[cfg(not(feature = "hex"))] + crate::impl_debug_only_for_newtype!(NewTypeHashBackward); + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn macro_created_sha256t_hash_type_backward() { + use alloc::string::ToString; + + let inner = sha256t::Hash::::hash(&[0]); + let hash = NewTypeHashBackward::from_byte_array(inner.to_byte_array()); + assert_eq!(hash.to_string(), HASH_ZERO_BACKWARD); + // Note one has to use the new wrapper type to get backwards formatting. + assert_eq!(sha256t::Hash::::hash(&[0]).to_string(), HASH_ZERO_FORWARD); + } + + // We also provide a macro to create the tag and the hash type. + sha256t_tag! { + /// Test detailed explanation. + struct NewTypeTagForward = raw(TEST_MIDSTATE, 64); + } + hash_newtype! { + /// A test hash. + #[hash_newtype(forward)] + struct NewTypeHashForward(sha256t::Hash); + } + #[cfg(feature = "hex")] + crate::impl_hex_for_newtype!(NewTypeHashForward); + #[cfg(not(feature = "hex"))] + crate::impl_debug_only_for_newtype!(NewTypeHashForward); + + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn macro_created_sha256t_hash_type_prints_forward() { + use alloc::string::ToString; + + let inner = sha256t::Hash::::hash(&[0]); + let hash = NewTypeHashForward::from_byte_array(inner.to_byte_array()); + assert_eq!(hash.to_string(), HASH_ZERO_FORWARD); + // We can also just use the `sha256t::Hash` type directly. + assert_eq!(sha256t::Hash::::hash(&[0]).to_string(), HASH_ZERO_FORWARD); + } +} diff --git a/hashes/src/sha384/mod.rs b/hashes/src/sha384/mod.rs new file mode 100644 index 000000000..baa5651c7 --- /dev/null +++ b/hashes/src/sha384/mod.rs @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA384 implementation. + +use crate::sha512; + +crate::internal_macros::general_hash_type! { + 384, + false, + "Output of the SHA384 hash function." +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + pub fn from_engine(e: HashEngine) -> Self { + let mut ret = [0; 48]; + ret.copy_from_slice(&sha512::Hash::from_engine(e.0).as_byte_array()[..48]); + Self(ret) + } +} + +/// Engine to compute SHA384 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine(sha512::HashEngine); + +impl HashEngine { + /// Constructs a new SHA384 hash engine. + pub const fn new() -> Self { Self(sha512::HashEngine::sha384()) } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 48]; + const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; + + fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } + fn input(&mut self, inp: &[u8]) { self.0.input(inp); } + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn test() { + use alloc::string::ToString; + + use crate::{sha384, HashEngine}; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 48], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Examples from go sha384 tests. + Test { + input: "", + output: [ + 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, + 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, + 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, + 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, + 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, + 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b, + ], + output_str: "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" + }, + Test { + input: "abcdef", + output: [ + 0xc6, 0xa4, 0xc6, 0x5b, 0x22, 0x7e, 0x73, 0x87, + 0xb9, 0xc3, 0xe8, 0x39, 0xd4, 0x48, 0x69, 0xc4, + 0xcf, 0xca, 0x3e, 0xf5, 0x83, 0xde, 0xa6, 0x41, + 0x17, 0x85, 0x9b, 0x80, 0x8c, 0x1e, 0x3d, 0x8a, + 0xe6, 0x89, 0xe1, 0xe3, 0x14, 0xee, 0xef, 0x52, + 0xa6, 0xff, 0xe2, 0x26, 0x81, 0xaa, 0x11, 0xf5, + ], + output_str: "c6a4c65b227e7387b9c3e839d44869c4cfca3ef583dea64117859b808c1e3d8ae689e1e314eeef52a6ffe22681aa11f5", + }, + Test { + input: "Discard medicine more than two years old.", + output: [ + 0x86, 0xf5, 0x8e, 0xc2, 0xd7, 0x4d, 0x1b, 0x7f, + 0x8e, 0xb0, 0xc2, 0xff, 0x09, 0x67, 0x31, 0x66, + 0x99, 0x63, 0x9e, 0x8d, 0x4e, 0xb1, 0x29, 0xde, + 0x54, 0xbd, 0xf3, 0x4c, 0x96, 0xcd, 0xba, 0xbe, + 0x20, 0x0d, 0x05, 0x21, 0x49, 0xf2, 0xdd, 0x78, + 0x7f, 0x43, 0x57, 0x1b, 0xa7, 0x46, 0x70, 0xd4, + ], + output_str: "86f58ec2d74d1b7f8eb0c2ff0967316699639e8d4eb129de54bdf34c96cdbabe200d052149f2dd787f43571ba74670d4", + }, + Test { + input: "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", + output: [ + 0x72, 0x2d, 0x10, 0xc5, 0xde, 0x37, 0x1e, 0xc0, + 0xc8, 0xc4, 0xb5, 0x24, 0x7a, 0xc8, 0xa5, 0xf1, + 0xd2, 0x40, 0xd6, 0x8c, 0x73, 0xf8, 0xda, 0x13, + 0xd8, 0xb2, 0x5f, 0x01, 0x66, 0xd6, 0xf3, 0x09, + 0xbf, 0x95, 0x61, 0x97, 0x9a, 0x11, 0x1a, 0x00, + 0x49, 0x40, 0x57, 0x71, 0xd2, 0x01, 0x94, 0x1a, + ], + output_str: "722d10c5de371ec0c8c4b5247ac8a5f1d240d68c73f8da13d8b25f0166d6f309bf9561979a111a0049405771d201941a", + }, + Test { + input: "The major problem is with sendmail. -Mark Horton", + output: [ + 0x5f, 0xf8, 0xe0, 0x75, 0xe4, 0x65, 0x64, 0x6e, + 0x7b, 0x73, 0xef, 0x36, 0xd8, 0x12, 0xc6, 0xe9, + 0xf7, 0xd6, 0x0f, 0xa6, 0xea, 0x0e, 0x53, 0x3e, + 0x55, 0x69, 0xb4, 0xf7, 0x3c, 0xde, 0x53, 0xcd, + 0xd2, 0xcc, 0x78, 0x7f, 0x33, 0x54, 0x0a, 0xf5, + 0x7c, 0xca, 0x3f, 0xe4, 0x67, 0xd3, 0x2f, 0xe0, + ], + output_str: "5ff8e075e465646e7b73ef36d812c6e9f7d60fa6ea0e533e5569b4f73cde53cdd2cc787f33540af57cca3fe467d32fe0", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = sha384::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = sha384::Hash::engine(); + for ch in test.input.as_bytes() { + engine.0.input(&[*ch]); + } + let manual_hash = sha384::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } + } +} diff --git a/hashes/src/sha3_256/benches.rs b/hashes/src/sha3_256/benches.rs new file mode 100644 index 000000000..afefdcb72 --- /dev/null +++ b/hashes/src/sha3_256/benches.rs @@ -0,0 +1,33 @@ +use test::Bencher; + +use crate::{Hash, HashEngine}; + +#[bench] +pub fn sha3_256_10(bh: &mut Bencher) { + let mut engine = crate::sha3_256::Hash::engine(); + let bytes = [1u8; 10]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha3_256_1k(bh: &mut Bencher) { + let mut engine = crate::sha3_256::Hash::engine(); + let bytes = [1u8; 1024]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha3_256_64k(bh: &mut Bencher) { + let mut engine = crate::sha3_256::Hash::engine(); + let bytes = [1u8; 65536]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} diff --git a/hashes/src/sha3_256/mod.rs b/hashes/src/sha3_256/mod.rs new file mode 100644 index 000000000..9838da1ff --- /dev/null +++ b/hashes/src/sha3_256/mod.rs @@ -0,0 +1,829 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA3-256 from the family of hashes based on the Keccak permutation function. + +// The Keccak permutation function is defined by five functions and a state array of N-bits, +// commonly 1600 bits. These 1600 bits are often divided into a 5x5 matrix of `u64` little endian +// numbers, commonly called a "lane." A single Keccak round comprises of a theta, rho, pi, chi, and iota step. Each of these +// steps are easily performed on a lane. Keccakf1600 is a function that performs a number of Keccak rounds, each defined with +// a different round-constant. +// +// SHA3-256 is a hash function that accepts arbitrary data and alters a Keccak state via the +// Keccakf1600 function. Data is chunked into fixed-sizes slices, called padded messages, each with +// a size of "bitrate" or "rate" for short. Each padded message block is XOR'd into parts of the +// state array, followed by a call of Keccakf1600. To pad the final message block, a +// domain-specific identifier is appended to the message (`0x06`), followed by an XOR of the last +// byte with `0x80`. +// +// To read this file, follow the example code: https://keccak.team/keccak_specs_summary.html +// For a detailed specification: https://keccak.team/files/Keccak-reference-3.0.pdf + +use core::fmt; + +crate::internal_macros::general_hash_type! { + 256, + false, + "Output of the SHA3-256 hash function." +} +// The number of rows or columns. +const B: usize = 5; +// 1600 bits are divided into 25, 64-bit "lanes." +const NUM_LANES: usize = B * B; +// Let the word size be 64. Let 2^l = 64, then l is 6. In Keccak, the number of rounds is 12 + 2l. +const NUM_ROUNDS: usize = 24; +// The number of bytes "absorbed" into the state-array per message block. +const RATE: usize = 136; +// The number of lanes a message block may be divided into. +const RATE_LANES: usize = RATE / 8; + +// These create non-linear relations between rounds to avoid timing analysis. +const ROUND_CONSTANTS: [u64; NUM_ROUNDS] = [ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +]; + +const ROTATION_OFFSETS: [[u32; 5]; 5] = [ + [0, 36, 3, 41, 18], + [1, 44, 10, 45, 2], + [62, 6, 43, 15, 61], + [28, 55, 25, 21, 56], + [27, 20, 39, 8, 14], +]; + +// A `x` and `y` index into a flattened matrix. +#[inline(always)] +const fn ind(x: usize, y: usize) -> usize { x + B * y } + +// A flattened 5x5 matrix of little-endian `u64`. +#[derive(Clone, Default)] +struct KeccakState([u64; NUM_LANES]); + +// A row-column labeled output of the current state. +impl fmt::Debug for KeccakState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for y in 0..B { + for x in 0..B { + writeln!(f, "[{},{}]: {:016x}", x, y, self.lane(x, y).to_le())?; + } + } + Ok(()) + } +} + +impl KeccakState { + const fn new() -> Self { Self([0u64; NUM_LANES]) } + + #[inline(always)] + fn assign(&mut self, x: usize, y: usize, val: u64) { self.0[ind(x, y)] = val; } + + #[inline(always)] + const fn lane(&self, x: usize, y: usize) -> u64 { self.0[ind(x, y)] } + + #[inline(always)] + const fn column_xor(&self, x: usize) -> u64 { + self.0[ind(x, 0)] + ^ self.0[ind(x, 1)] + ^ self.0[ind(x, 2)] + ^ self.0[ind(x, 3)] + ^ self.0[ind(x, 4)] + } + + #[inline(always)] + fn xor_assign(&mut self, x: usize, y: usize, val: u64) { self.0[ind(x, y)] ^= val } + + #[inline(always)] + const fn chi(&self, x: usize, y: usize) -> u64 { + self.lane(x, y) ^ (!self.lane((x + 1) % B, y) & self.lane((x + 2) % B, y)) + } +} + +fn keccak_round(state: &mut KeccakState, round_constant: u64) { + // Theta + let mut c: [u64; B] = [0; B]; + (0..B).for_each(|x| { + c[x] = state.column_xor(x); + }); + let mut d: [u64; B] = [0; B]; + (0..B).for_each(|x| { + // Avoid an underflow here with a mod trick + d[x] = c[(x + B - 1) % B] ^ (c[(x + 1) % B].rotate_left(1)); + }); + (0..B).for_each(|x| { + (0..B).for_each(|y| { + state.xor_assign(x, y, d[x]); + }); + }); + + // Rho and Pi combined + let mut b = KeccakState::default(); + (0..B).for_each(|x| { + (0..B).for_each(|y| { + let offset = ROTATION_OFFSETS[x][y]; + let val = state.lane(x, y).rotate_left(offset); + let b_y = ((2 * x) + (3 * y)) % B; + b.assign(y, b_y, val); + }); + }); + + // Chi + (0..B).for_each(|x| { + (0..B).for_each(|y| { + state.assign(x, y, b.chi(x, y)); + }); + }); + + // Iota + state.xor_assign(0, 0, round_constant); +} + +fn keccakf1600(state: &mut KeccakState) { + for c in ROUND_CONSTANTS { + keccak_round(state, c); + } +} + +/// Engine to compute the Sha3-256 hash function. +#[derive(Debug, Clone, Default)] +pub struct HashEngine { + state: KeccakState, + bytes_hashed: u64, +} + +impl HashEngine { + /// Construct a new Sha3-256 hash engine. + pub const fn new() -> Self { Self { state: KeccakState::new(), bytes_hashed: 0 } } + + fn absorb(&mut self, block: [u8; RATE]) { + for lane in 0..RATE_LANES { + let x = lane % 5; + let y = lane / 5; + let mut pad_block = [0u8; 8]; + pad_block.copy_from_slice(&block[8 * lane..8 * lane + 8]); + let shuffle = u64::from_le_bytes(pad_block); + self.state.xor_assign(x, y, shuffle); + } + } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 32]; + const BLOCK_SIZE: usize = RATE; + + fn input(&mut self, mut data: &[u8]) { + while data.len().ge(&RATE) { + let mut block = [0u8; RATE]; + block.copy_from_slice(&data[..RATE]); + self.bytes_hashed += RATE as u64; + self.absorb(block); + keccakf1600(&mut self.state); + data = &data[RATE..]; + } + let mut final_block = [0u8; RATE]; + final_block[..data.len()].copy_from_slice(data); + self.bytes_hashed += data.len() as u64; + final_block[data.len()] = 0x06; + final_block[RATE - 1] ^= 0x80; + self.absorb(final_block); + keccakf1600(&mut self.state); + } + + fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } + + fn finalize(self) -> Self::Hash { + let mut out = [0u8; 32]; + out[..8].copy_from_slice(&self.state.lane(0, 0).to_le_bytes()); + out[8..16].copy_from_slice(&self.state.lane(1, 0).to_le_bytes()); + out[16..24].copy_from_slice(&self.state.lane(2, 0).to_le_bytes()); + out[24..].copy_from_slice(&self.state.lane(3, 0).to_le_bytes()); + Hash(out) + } +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +mod tests { + use alloc::string::ToString; + use alloc::vec::Vec; + + use hex::prelude::*; + + use crate::HashEngine; + + struct TestCase { + input: &'static str, + output: &'static str, + } + + #[test] + fn test() { + // LONG and SHORT are separate to match the NIST test vectors. + let tcs = [SHORT.as_ref(), LONG.as_ref()]; + for tc in tcs { + for test in tc { + let mut sha3 = super::HashEngine::new(); + let input_bytes = Vec::from_hex(test.input).unwrap(); + sha3.input(&input_bytes); + let hash = sha3.finalize(); + assert_eq!(hash.to_string(), test.output); + } + } + } + + const SHORT: [TestCase; 137] = [ + TestCase { + input: "", + output: "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" + }, + TestCase { + input: "e9", + output: "f0d04dd1e6cfc29a4460d521796852f25d9ef8d28b44ee91ff5b759d72c1e6d6" + }, + TestCase { + input: "d477", + output: "94279e8f5ccdf6e17f292b59698ab4e614dfe696a46c46da78305fc6a3146ab7" + }, + TestCase { + input: "b053fa", + output: "9d0ff086cd0ec06a682c51c094dc73abdc492004292344bd41b82a60498ccfdb" + }, + TestCase { + input: "e7372105", + output: "3a42b68ab079f28c4ca3c752296f279006c4fe78b1eb79d989777f051e4046ae" + }, + TestCase { + input: "0296f2c40a", + output: "53a018937221081d09ed0497377e32a1fa724025dfdc1871fa503d545df4b40d" + }, + TestCase { + input: "e6fd42037f80", + output: "2294f8d3834f24aa9037c431f8c233a66a57b23fa3de10530bbb6911f6e1850f" + }, + TestCase { + input: "37b442385e0538", + output: "cfa55031e716bbd7a83f2157513099e229a88891bb899d9ccd317191819998f8" + }, + TestCase { + input: "8bca931c8a132d2f", + output: "dbb8be5dec1d715bd117b24566dc3f24f2cc0c799795d0638d9537481ef1e03e" + }, + TestCase { + input: "fb8dfa3a132f9813ac", + output: "fd09b3501888445ffc8c3bb95d106440ceee469415fce1474743273094306e2e" + }, + TestCase { + input: "71fbacdbf8541779c24a", + output: "cc4e5a216b01f987f24ab9cad5eb196e89d32ed4aac85acb727e18e40ceef00e" + }, + TestCase { + input: "7e8f1fd1882e4a7c49e674", + output: "79bef78c78aa71e11a3375394c2562037cd0f82a033b48a6cc932cc43358fd9e" + }, + TestCase { + input: "5c56a6b18c39e66e1b7a993a", + output: "b697556cb30d6df448ee38b973cb6942559de4c2567b1556240188c55ec0841c" + }, + TestCase { + input: "9c76ca5b6f8d1212d8e6896ad8", + output: "69dfc3a25865f3535f18b4a7bd9c0c69d78455f1fc1f4bf4e29fc82bf32818ec" + }, + TestCase { + input: "687ff7485b7eb51fe208f6ff9a1b", + output: "fe7e68ae3e1a91944e4d1d2146d9360e5333c099a256f3711edc372bc6eeb226" + }, + TestCase { + input: "4149f41be1d265e668c536b85dde41", + output: "229a7702448c640f55dafed08a52aa0b1139657ba9fc4c5eb8587e174ecd9b92" + }, + TestCase { + input: "d83c721ee51b060c5a41438a8221e040", + output: "b87d9e4722edd3918729ded9a6d03af8256998ee088a1ae662ef4bcaff142a96" + }, + TestCase { + input: "266e8cbd3e73d80df2a49cfdaf0dc39cd1", + output: "6c2de3c95900a1bcec6bd4ca780056af4acf3aa36ee640474b6e870187f59361" + }, + TestCase { + input: "a1d7ce5104eb25d6131bb8f66e1fb13f3523", + output: "ee9062f39720b821b88be5e64621d7e0ca026a9fe7248d78150b14bdbaa40bed" + }, + TestCase { + input: "d751ccd2cd65f27db539176920a70057a08a6b", + output: "7aaca80dbeb8dc3677d18b84795985463650d72f2543e0ec709c9e70b8cd7b79" + }, + TestCase { + input: "b32dec58865ab74614ea982efb93c08d9acb1bb0", + output: "6a12e535dbfddab6d374058d92338e760b1a211451a6c09be9b61ee22f3bb467" + }, + TestCase { + input: "4e0cc4f5c6dcf0e2efca1f9f129372e2dcbca57ea6", + output: "d2b7717864e9438dd02a4f8bb0203b77e2d3cd8f8ffcf9dc684e63de5ef39f0d" + }, + TestCase { + input: "d16d978dfbaecf2c8a04090f6eebdb421a5a711137a6", + output: "7f497913318defdc60c924b3704b65ada7ca3ba203f23fb918c6fb03d4b0c0da" + }, + TestCase { + input: "47249c7cb85d8f0242ab240efd164b9c8b0bd3104bba3b", + output: "435e276f06ae73aa5d5d6018f58e0f009be351eada47b677c2f7c06455f384e7" + }, + TestCase { + input: "cf549a383c0ac31eae870c40867eeb94fa1b6f3cac4473f2", + output: "cdfd1afa793e48fd0ee5b34dfc53fbcee43e9d2ac21515e4746475453ab3831f" + }, + TestCase { + input: "9b3fdf8d448680840d6284f2997d3af55ffd85f6f4b33d7f8d", + output: "25005d10e84ff97c74a589013be42fb37f68db64bdfc7626efc0dd628077493a" + }, + TestCase { + input: "6b22fe94be2d0b2528d9847e127eb6c7d6967e7ec8b9660e77cc", + output: "157a52b0477639b3bc179667b35c1cdfbb3eef845e4486f0f84a526e940b518c" + }, + TestCase { + input: "d8decafdad377904a2789551135e782e302aed8450a42cfb89600c", + output: "3ddecf5bba51643cd77ebde2141c8545f862067b209990d4cb65bfa65f4fa0c0" + }, + TestCase { + input: "938fe6afdbf14d1229e03576e532f078898769e20620ae2164f5abfa", + output: "9511abd13c756772b852114578ef9b96f9dc7d0f2b8dcde6ea7d1bd14c518890" + }, + TestCase { + input: "66eb5e7396f5b451a02f39699da4dbc50538fb10678ec39a5e28baa3c0", + output: "540acf81810a199996a612e885781308802fe460e9c638cc022e17076be8597a" + }, + TestCase { + input: "de98968c8bd9408bd562ac6efbca2b10f5769aacaa01365763e1b2ce8048", + output: "6b2f2547781449d4fa158180a178ef68d7056121bf8a2f2f49891afc24978521" + }, + TestCase { + input: "94464e8fafd82f630e6aab9aa339d981db0a372dc5c1efb177305995ae2dc0", + output: "ea7952ad759653cd47a18004ac2dbb9cf4a1e7bba8a530cf070570c711a634ea" + }, + TestCase { + input: "c178ce0f720a6d73c6cf1caa905ee724d5ba941c2e2628136e3aad7d853733ba", + output: "64537b87892835ff0963ef9ad5145ab4cfce5d303a0cb0415b3b03f9d16e7d6b" + }, + TestCase { + input: "6ef70a3a21f9f7dc41c553c9b7ef70db82ca6994ac89b3627da4f521f07e1ae263", + output: "0afe03b175a1c9489663d8a6f66d1b24aba5139b996400b8bd3d0e1a79580e4d" + }, + TestCase { + input: "0c4a931ff7eace5ea7cd8d2a6761940838f30e43c5d1253299abd1bd903fed1e8b36", + output: "dc5bebe05c499496a7ebfe04309cae515e3ea57c5d2a5fe2e6801243dd52c93b" + }, + TestCase { + input: "210f7b00bf8b4337b42450c721c3f781256359d208733846b97c0a4b7b044c38dbb219", + output: "3305c9d28e05288a2d13994d64c88d3506399cd62b2b544213cf3539a8e92e2e" + }, + TestCase { + input: "3cb8992759e2dc60ebb022bd8ee27f0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5", + output: "3c00bf3e12ade9d2de2756506f809f147c8d6adc22e7bb666e0b1d26469e65a5" + }, + TestCase { + input: "22634f6ba7b4fccaa3ba4040b664dbe5a72bf394fb534e49c76ec4cdc223f4969e2d37e899", + output: "a87e5c78837d7be0060d8f5eda975489ec961b28d7088f42a70f92414ae17793" + }, + TestCase { + input: "6e1dcd796b2015ee6760f98fdb40e668b2cf38b05c91f6a91e83bcc8ac59f816f90a59d64e8e", + output: "746bf845c08aa186b5fe1ca35528232c4a491a3a2a32cd23e990bc603f3268ae" + }, + TestCase { + input: "ee0be20320f9d44073281265a6e9fa6b9d252495624b8d016b8ef57e1b4e859d8ad3b50b89416d", + output: "a3257baf14ca16e1137dc5158703f3b02ebc74fc7677165fe86d4be1f38e2f7c" + }, + TestCase { + input: "8ae2da242635b6568289bf6bec8a438dbac1f5b4d50a90bb7449bdb92a59378e23452dbcabbbe879", + output: "e25c44802c5cf2e9f633e683d37aa8c8db8a0e21c367808121d14d96c8a400b5" + }, + TestCase { + input: "bdd0252dec5b798ef20e51791a18e8ca234d9bfde632a9e5395337a112dd97cdf068c9f57615424f59", + output: "e02c1b197979c44a5a50d05ea4882c16d8205c2e3344265f8fe0e80aed06c065" + }, + TestCase { + input: "c4c7b6315cb60b0e6cd01ef0b65f6486fdae4b94c6be21465c3a31c416ad2f06dcf3d6eae8eecf84ca7a", + output: "2da21867cd6b5402d3caff92a05fddfca90199fd51a94a066af164ce3d36c949" + }, + TestCase { + input: "b17977aced3a1184b14b0e41a04dd8b513c925ca19211e1abdc6c1b987ac845545fb3b820a083b4f7883c0", + output: "f91b016d013ede8d6a2e1efd4c0dd99417da8b0222d787867ca02b0ea2e80e45" + }, + TestCase { + input: "f65c3aa1d9981a84e49fc86d938f3f756f60e3858d5e1f6957dd4d268e28d68e90ba9a11d7b192d6c37fb30b", + output: "3acbebf8eda9d3c99a6b6b666366c391e8200d55fd33ad8680734def1dc7ae85" + }, + TestCase { + input: "49abba1fa98f3c4470d5dd4ed36924af4a7ad62f4c2dd13e599238883ed7d0cb95bbaae58b460332e6b7681446", + output: "02bcd9ea4f1aa5276f38e30351a14a072bc5d53a52d04d559a65ca46f1bcb56e" + }, + TestCase { + input: "275645b5a2514fe65a82efac57e406f224e0259677674f1d133f00a5ee9a6d1a8fed0eadbbff5a825041d2a9715d", + output: "c70a874d786cd0f3f09fa4dc1bb8f551d45f26d77ad63de1a9fdfb3b7c09c041" + }, + TestCase { + input: "cd02b32107b9a640fc1bf439ac81a5c27d037c6076e1cfe6ad229638037ac1550e71cf9557c29c2fc6017afd5a8184", + output: "36c73d11d450784eb99af068cd4e1cbc5768c8a2118010aceec6d852dda80d95" + }, + TestCase { + input: "5a72e0e1aec82a6541f04883bb463b0c39c22b59431cfb8bfd332117a1afb5832ce5c76a58fcf6c6cb4e3e6f8e1112de", + output: "90fc3193552ec71d3315ebbb807913afd4cd2f0833a65e40d011d64de5e66513" + }, + TestCase { + input: "43402165911890719f9179f883bbbc2a3be77682e60dd24b356a22621c6d2e3dcdd4cb2ce613b0dfe9f58629ee853e0394", + output: "5c4b6ceac9441defa99b10b805a725d4018b74b3e1f24ad8934fc89b41b8fd9e" + }, + TestCase { + input: "fc56ca9a93982a4669ccaba6e3d184a19de4ce800bb643a360c14572aedb22974f0c966b859d91ad5d713b7ad99935794d22", + output: "e21806ce766bbce8b8d1b99bcf162fd154f54692351aec8e6914e1a694bda9ee" + }, + TestCase { + input: "ace6297e50d50a11388118efc88ef97209b11e9dfcb7ad482fc9bf7d8deecc237ad163d920c51f250306d6cedc411386a457c7", + output: "f5581403a082bbf5ad7e09bdfccc43bf9683ebc88291d71d9ce885a37e952bd6" + }, + TestCase { + input: "3bad18046e9424de24e12944cd992cfba4556f0b2ae88b7bd342be5cff9586092bb66fac69c529040d10dd66aa35c1023d87eb68", + output: "faed76ff5a1cd99183b311e502c54e516d70a87050cf8961c8cd46f65c1358cd" + }, + TestCase { + input: "e564c9a1f1aaf8545a259f52c3fd1821ed03c22fd7424a0b2ad629d5d3026ef4f27cbe06f30b991dfa54de2885f192af4dc4ddc46d", + output: "811529c600c9d780f796a29a6b3e89f8a12b3f29c36f72b06cca7edc36f48dc0" + }, + TestCase { + input: "6043fa6465d69cab45520af5f0fd46c81dbf677531799802629863681cea30ffa3b00836fbf49f87051d92aaeac0ed09bcb9f0755b7b", + output: "b0fceecdaef6c76d5fc3835b523ce2416f4a9b9bd1f90234445df0f2b689f2f5" + }, + TestCase { + input: "2040c538c79237e6f2b8188c6375ec2f610ac2301607b9c23660c3a1e1c3a902cb2950c59aac3af28f984f6369c4debe8623dfa74c967b", + output: "e33dbdc0acc23fcfad3c759c4333410bd3a40efb1366ade157d2c81d65a0a6c7" + }, + TestCase { + input: "00ff6c96b7aa3cf27d036cf20af7031434113252574bda9cf9244d85aef2593d3a7a83bff6be904b75164a1766828042bc3f4f090d98a03d", + output: "d000eafca34815783bed9b050c6901c97f2e77d4771a0ed724dd8f6ff1448791" + }, + TestCase { + input: "e8df14936cce118139e690f1662f88cfbc9c333b6dea658c02cb1d959644592842542fd9d8d61a04d4a892128f0ddff7b6502efffbabe5cb0a", + output: "3479a9617a3adca35854c08fe987c2fe7ff2b01b04f2d952c107b3f066420551" + }, + TestCase { + input: "4ed981a31f70dd6b70c161be1f01fc1bba54d06d9494e7eb194e213d5e0e71e0fddd49cb1f075353da22624cbe4ba871aab32906e45b6fbb691b", + output: "9c824a00e068d2fda73f9c2e7798e8d9394f57f94df0edeb132e78e8a379a0cf" + }, + TestCase { + input: "7802b70c6158bc26d5f157671c3f3d81ab399db552b9f851b72333770348eb1fdb8a085f924095eb9d5ccfd8474b7ba5a61c7d7bcde5a7b44362cf", + output: "fa9726ccb068c0adb5d20079c35a318b3d951eb43b196c509ab790b7e9202207" + }, + TestCase { + input: "ff83dcd7c1a488e5a128d5b746284552f1f2c091615d9519f459bc9010ca5e0ac19796c4a3fd7a15032a55a1410737d07855b07f61fbd8f5759e9218", + output: "8bd8d494a41acda4b7cd2994badaecff0f46ba2743458f6c3fdc0226f9492ede" + }, + TestCase { + input: "afd4764cc7d5de16a3cf80c51d0c0d919f18700c7dc9bc4e887d634fe0a3aa94097d590e4123b73f11ccb59e23496a3d53d2bfa908056c11c52c23abfb", + output: "e9e3b3da648cf230f1973f3814eb81316d2a496826ea39adf4674576f97e1167" + }, + TestCase { + input: "6fa6de509719ffbf17759f051453c0ac3cbe13346546bbc17050541074b034af197af06e41142211ee906a476039b3e07d6cb83a76aac6fca8eac307c034", + output: "766630993fbb651fd8d3603e3eebc81931fb1302a46791df259a6e13ca2cba9f" + }, + TestCase { + input: "93cbb7e47c8859bef939155bea488090283ecf5023d99767c960d86baa333af05aa696fc170fb8bbac1e6473956d96b964580ee6640f0cc57be9598e55fc86", + output: "d3212abca1100eb7658c0f916daf2692c57a47b772ee031c4ec6ad28a4a46de9" + }, + TestCase { + input: "67e384d209f1bc449fa67da6ce5fbbe84f4610129f2f0b40f7c0caea7ed5cb69be22ffb7541b2077ec1045356d9db4ee7141f7d3f84d324a5d00b33689f0cb78", + output: "9c9160268608ef09fe0bd3927d3dffa0c73499c528943e837be467b50e5c1f1e" + }, + TestCase { + input: "4bef1a43faacc3e38412c875360606a8115d9197d59f61a85e0b48b433db27695dc962ed75d191c4013979f401cf3a67c472c99000d3a152227db61de313ab5a1c", + output: "8703a1f7424c3535f1d4f88c9b03d194893499478969fbb0a5dc2808a069ab8f" + }, + TestCase { + input: "f0be5e961bb55b3a9452a536504f612a3e66aec8160a882e5156eb7278433b7ea21de31e39383d57fcdfb2fb4a8d227a9d6085fb55cad3abb78a225535da0e34efea", + output: "2fa180209bf6b4ad13c357d917fabb3e52c101a0cdb3f2299fa0f7f81dfb848e" + }, + TestCase { + input: "206f1c36ba25aea73398fffc9b65c4637cc1f05a6bbee014dccbd61e3b7aa9423887bbac62152a4bf73a4b7afabe54e08720589464da7985d8e6591ac081d115df2fe6", + output: "558ea7c800b687380cce7e06006e1ebe0b89973f788c4caac5780f22dbf382e8" + }, + TestCase { + input: "8cd71434c00663f3bda0205508a4a266548dc69e00ca91fde06d165b40279af92674f75bd8133e5a9eb9a075c9068f68f4b820008a1fb42d89d1d759859e68f8efc6fb60", + output: "085b343b08516f320a9b90fe50440a8bc51ae0850fa38d88724a4d6bd3df1ad4" + }, + TestCase { + input: "4cf5bbd91cac61c21102052634e99faedd6cdddcd4426b42b6a372f29a5a5f35f51ce580bb1845a3c7cfcd447d269e8caeb9b320bb731f53fe5c969a65b12f40603a685afe", + output: "f9dbb88c5bb4415e17dee9222174538eeab371b12d8d572cfdf55b806e3158e4" + }, + TestCase { + input: "e00e46c96dec5cb36cf4732048376657bcd1eff08ccc05df734168ae5cc07a0ad5f25081c07d098a4b285ec623407b85e53a0d8cd6999d16d3131c188befbfc9ebb10d62daf9", + output: "3571326a1577c400b967ac1c26df2a0dcf5db7070eac262a8071da16afa7c419" + }, + TestCase { + input: "981f41a83d8f17f71fc03f915a30cd8ac91d99aa1b49ef5c29fb88c68646b93a588debcd67474b457400c339cca028731df0b599875ab80df6f18b11b0b1c62f2a07b3d8209402", + output: "62aea8760759a996f4d855e99bcd79e9a57ea362522d9b42fd82c12c9294a217" + }, + TestCase { + input: "5c589fc54fefc4d6e2249a36583e1992fc6b8a9c070e8e00c45a639af22063e66ae5cdb80238c82db043a5e1f39f65626e6d7be5d6a2d3380fa212f89211200412e5e4315fc04e40", + output: "18deba74e9d93ae7df93c6c316ef201bf5e3a661e68868e14d4f56264f5d858c" + }, + TestCase { + input: "7c8691e7b2560fe87fcc5e2877f7e3c84d9101eca4818f6322a58986c6cf05627c0d6919ef2edc859f81fa1f33e0cc1f10edf7e52a9c33981af2ff0d720c94ea4d62170b2a4d1224fa", + output: "5a5a438b57c1b3ce8756094252362afeaa9fc91cd45b385d16994ec8af49aa6b" + }, + TestCase { + input: "97359b564b2bc20800ed1e5151b4d2581a0427ce9539d324c3637cfb0e5378dc2cf6d72946e2a3535a2f664ede88ed42a6814c84072b22c43de71e880a77c2d9a05b673bc15a82e3255f", + output: "be54f2e435f760d5b77c0ae61ef0aa7f5f3366f47819f350dc8a39aff8c73a8f" + }, + TestCase { + input: "a0dfaecd3e307c5ddf9a93603f7e19725a779218734904525b14586ff0ce0425e4efe7e1c06e745c28ed136f6031c4280fd4061d433ef700b6d1bc745064231fecf387015f94f504b6ad8c", + output: "60d80f1c703dad5da93db222fb45fb7fa768c8aa2787f4b81f1e00365b8f49e2" + }, + TestCase { + input: "568d66d061306c3419a1928ce7edc8e3400c30998f09bdac6f63ff351eb23d362e8dc5927eac805d694ac9563dcd7fb2efa9591c0d827af9f39146f0424873aa8e3963d65734b1713baf0a44", + output: "7a4fe37f296991121792dd7c2c30390725a1eebbf20b766a5a1c3c6c3646d996" + }, + TestCase { + input: "d65b9f881d1fc7f17d6dd429faca8404e6ce60fba7d89b7fba003c8ef84d8083182979327611fc341291ba80dc70ad3b2f28b6d29b988445e7fdb7c6561f45822ac81dbf677a0b27d961dc6358", + output: "51cc71b6934afcf28fa49942b76323f36cd6a0aecc5a0e49c10994ddcabdbb80" + }, + TestCase { + input: "711c88adf13e7a0e694652f2b9a397543f4937fafb4ccca7f1ad1d93cf74e818d0fedfaee099f019014ec9e1edfe9c03fdb11fe6492ad89011bf971a5c674461de15daff1f44b47adad308baa314", + output: "1780e52e306858478290c46b04d8068f078a7f6ad8e3790a68fc40dccfbdadc9" + }, + TestCase { + input: "f714a27cd2d1bc754f5e4972ab940d366a754e029b6536655d977956a2c53880332424ddf597e6866a22bfca7aa26b7d74bc4c925014c4ed37bfe37245fa42628d1c2ee75dc909edc469ee3452d894", + output: "f4afa72f3e489ad473dc247aae353da99fb005b490e2c4e1f5bd16a99732b100" + }, + TestCase { + input: "fe0c3280422c4ef6c82116e947da89f344d6ff997bf1aec6807e7379a695d0ba20ae31d2666f73bbdbc3a6d6ac2c12dcfb5a79173dfc9cd2e0d6000e3114f2767edec995772c6b47dadc136d500251e5", + output: "89198e2363efd4e0ba7a8a45f690f02712e6f856668517bae118d11e9a9dc7cc" + }, + TestCase { + input: "02e238461d0a99d49c4cd16f442edf682c39b93114fc3d79f8546a99e5ead02f0cfc45081561da44b5c70eb48340418707fd6b2614580d5c581868ba32f1ee3ac34bf6224845b32ba7f867e34700d45025", + output: "abef81b33591eedcac0cf32fb5a91c931f2d719c37801409133552170ce50dbf" + }, + TestCase { + input: "fb7c8cd4031007f8159d5c4c6120dee6777a3ace0a245b56f31e8aae7828dab3cf35c308de1d0d684592ef3a9e55796603a92f68d109f7a3ac1635f7c4d334955614c812753431bb0a0743291a0fc41547f3", + output: "5a67284d39e4f37caa64ca1a54593c35f6d8f3a3ec20d460393a39f6f57c4486" + }, + TestCase { + input: "6b2e868c7d0ee1c240d3a67e2fdf36e8e23817c02644a54453d10454da5859d41e833a5285ec63e8ce28aa64a50435a7740eea4b7d5827892678b35993d3f5da7a1c64f533173f3d0fa37e1aebf70827052c26", + output: "aecf5dab6fea9ffd1bce2cdfeec0bee9d214a669e8306d5b6688afa8957fc91f" + }, + TestCase { + input: "e5f3ba000c43bb6aca4e0a711a75912a48241cffa5b4b0b17f901f9e5097d94036c205f7a307d008567d05e58ac0dfaf6d971bf9d3d450cf2c7c83f6b328f676e9ab425642f5a5a71e389dc4fa49b6d7e848a09f", + output: "182d6e4316f4bc18d7163b1b21462d99f99c6f34d2c00ee771ce54fd6c5018b9" + }, + TestCase { + input: "939c61e68af5e2fdb75a2eebb159a85b0c87a126ce22701622f5c5ef517c3ab0ed492b1650a6c862457c685c04732198645b95f84ccb0e726a07ce132827a044dc76b34d3f19a81721f1ea365bc23e2604949bd5e8", + output: "121057b0b9a627be07dc54e7d1b719f0a3df9d20d29a03a38b5df0a51503df93" + }, + TestCase { + input: "9eadaf4811a604c65eaa7b1c6e89f2c0ab96bebec25a950ba78aac16d9371ca1e7458acf331e077ef6a735d68474ab22d2389bdf357fb2136c9f40e1e1eb99592c2bbb95d94931016b4d37faa08b1e9bf71bf2d3708a", + output: "c237194b902e48dca5bd096cb51562079d0cdccb2af8088197676c17b0896be2" + }, + TestCase { + input: "71dcca239dced2ac5cc49a9bf9ea69a99be22ba62216716b524db80f337dee5eb7e032869e4adc1497babd1fa82fa8c3cfbd30d2eadfb4c5d40f99f9d194d7182c9cb7d41e8adbdcf2917e086782fdd756e2961c944070", + output: "377d1cffb626735810b613fd31ef9bbb4577cd752521abe3a41afa921e623da0" + }, + TestCase { + input: "ea130d3236bca7dffb4b9e50e805309a503e7347227aeb9f1bd15c263a98dd65753d2eedaa734b9ad88f41158f32419ca529f3062b910c019f3f239f635fc1116e5ab7b242feb4471ed9168474e501d39d6bae52cc21061a", + output: "85c7a52d53f7b41162ea9f1ef0d07c3fb8f0ec621617f88cb3828ebe5388ab3d" + }, + TestCase { + input: "28f1be1156792af95c6f72e971bf1b64e0127b7653ff1e8c527f698907a27d1544815e38c7745529bc859260832416f2b41cd01e60c506239a7bf7553650bf70d1fe7a2c1220ac122ea1e18db27490447d8545a70bf0ffc8fa", + output: "b2eb3762a743d252567796692863b55636cb088e75527efd7306a2f6e3a48a85" + }, + TestCase { + input: "c8400ef09c13e8acc8a72258f5d1d20302c6e43b53250c2f6c38ff15be77e3cac04d04b8421fc8fdff8be5ca71edd108e9287b42dea338bf859100eea376da08a0e695f0dc90b95e467cbd3c2a917a504a5ae01c310ae802c4bd", + output: "69966e89b7bc7f39cd85791b92180ff3fed658d8240e393e1e6d7c24b8d0ac95" + }, + TestCase { + input: "a48950c961438e09f4d054ac66a498e5f1a4f6eabfde9b4bf5776182f0e43bcbce5dd436318f73fa3f92220cee1a0ff07ef132d047a530cbb47e808f90b2cc2a80dc9a1dd1ab2bb274d7a390475a6b8d97dcd4c3e26ffde6e17cf6", + output: "44c00cf622beca0fad08539ea466dcbe4476aef6b277c450ce8282fbc9a49111" + }, + TestCase { + input: "e543edcff8c094c0b329c8190b31c03fa86f06ace957918728692d783fa824ba4a4e1772afbe2d3f5cba701250d673405d2c38d52c52522c818947bcc0373835b198c4cc80b029d20884ac8c50893c3f565d528a0cb51bf8a197d9d6", + output: "6d5260384f3cefd3758fb900dcba3730d2b23cee03d197abeff01369dc73c180" + }, + TestCase { + input: "4e10ab631718aa5f6e69ee2c7e17908ec82cb81667e508f6981f3814790cfd5d112a305c91762c0bd9dd78e93ef3a64c8be77af945b74ff234a0b78f1ed962d0d68041f276d5ea40e8a63f2cab0a4a9ed3526c8c523db7cb776b9825b4", + output: "d88e5f3b2d0a698fd943233760a3000a3360d9040e7374b22e39ea58d868102d" + }, + TestCase { + input: "604d8842855354811cd736d95c7f46d043a194048b64bf6cda22c3e0391113dcc723e881ae2ad8dc5740aa6bda6669ddb96bb71acd10648380693f7b3d862c262553777004bd6852831618519fbb824759f4dd65af1b2a79cc01096d7c8d", + output: "8a8ab6cf5c02b9ae8f4c170740eff1592f3eda11d3420ac8b421d93cfbb35db8" + }, + TestCase { + input: "628180e14f41ebdfde3b4439de55ee9cd743d41040f3457ef2280370dd659619fa0ce69580c709725b275a6eda8bcb82a8447c20fdf68cba15412f83e2a10079fe9399a3e3fa61975ec0a64041c0ecde59e4844e9f8a608cb22d2576854182", + output: "8d154bf6f9cb72efc0d8b3927a8f690060d1d48bbe5cc72094d2c8b149a75132" + }, + TestCase { + input: "fc150b1619d5c344d615e86fca1a723f4eeb24fbe21b12facde3615a04744ef54d8a7191a4454357de35df878cb305692278648759681919d1af73c1fb0ff9783678aec838da933db0376e1629fcca3f32913f84bc2ff3ffc3f261d2312f591c", + output: "3f626c8bb20a132495bd3022b3fcd0ce0604b91a9d70132dab4099f73dde23d5" + }, + TestCase { + input: "6dadbecdd15e5646e3f37a6fe5b328e06113cce3c8cf07285939afba44d117321017902b3a9d2ff51f60d18e1b585dcdf34e49e170ee60fa4d1dc246548d2c1fc38e7983f42769c43d65a28016f3f4d479ebe1cd8fec5d1f886dd21aca5067d94f", + output: "9098ea34c40b541b153e80a8bd92da19432b18b7d329760b302f8a54c395dd06" + }, + TestCase { + input: "9cc5fd3035b72dc63b8c3c326fd013081e6b8716f526d3fe176b45256d4c37cc3dc8417dff49ada96c702b8fd715c65fc08a17a0a720b9cf1eedfd4922ccde6baba437f782ee33b95371056b0350dad743470c3b663299f16fcfd34f6fc459cd0ee4", + output: "b0c04f24bb6d3d4fcbfdf9222d0e886f1eb60a0566a478085f7623a025a5b981" + }, + TestCase { + input: "f3f063fbcf2d74aa5a02d240c962ed7bb119b3a212bdb41594e28428108e613152ed16e01e451fcf702b0e5a08f82eb12677652b93e05fdee00ae86cf2dc9a1fbf05b93952ec5b8515eacc324fb830e1ec236afd7d073d4b7f7ab1c2e048b99cbfa012", + output: "f930d79360b581b1bbfdeac57133a339444f5c44538c921631eabaf058277d32" + }, + TestCase { + input: "840739a3d6992c13ec63e6dbf46f9d6875b2bd87d8878a7b265c074e13ab17643c2de356ad4a7bfda6d3c0cc9ff381638963e46257de087bbdd5e8cc3763836b4e833a421781791dfcae9901be5805c0bbf99cca6daf574634ec2c61556f32e642730510", + output: "19795657e08cfbb247a17cf209a4905f46e4ddf58eea47feee0be9bb9f5c460f" + }, + TestCase { + input: "4a51b49393ab4d1b44fb6dc6628855a34e7c94d13b8b2142e5d5a7bf810e202cefdca50e3780844a33b9942f89e5c5b7dd6afb0a44541d44fb40687859780af5025fecc85e10cf8249429a3b0c6ff2d68c350c87c2fcbf936bd9de5701b2c48ce9a330c9ee", + output: "128fb4114e43eefd19277c708be9e6873e66d7fd59c58a1485b7b015facfa795" + }, + TestCase { + input: "afc309e6b7b74dfb0d368e3894266fc4a706c3325e21f5550d07a6560e3d9703c134ca6ad078e4a7b82ad6fa85b0bc1ddcab05d43f29d5c58d1da78ac80c37051b089ff31ce2c0c44e9ce3abea1da0f1df28008e178fdefafca493413bf1d256c729d0a9225e", + output: "03e782b01a4ba10f640470bb3cae487eb9cbbaab8c9941978b194f6a312cf79e" + }, + TestCase { + input: "c5ae750f2230642092397b84ad5526c46ae9480ada16892816e0f2db7690b751035653ea2f33da3cc4168b591b46a5548eff7d012f60ccfdbb854deec9f0880c472de8e127b5144c56147cccee4732fbac68fc59a48da74b33ed9e643644bbe279795c7c737eba", + output: "f64b7ab243ce6e6c04b483888ba8a655465c21d95eb60c7b8d6e566a3811bae2" + }, + TestCase { + input: "603e13f61499e12ec6b33b68847a281d314f54dc705c0f3fc428981ff5689c04b519fadf83cbc9fcd0409c326035045df480570e265bb080940037ce4076a36437aafdb371c1a62af9ad9b614dfef89708fbbb5ebef2cb9528cc399781e4c5b22f1aa4dba623809f", + output: "5f76962fd3d373e5db2953c0823a51fe81f874450bedf7e46876394b04d3ef66" + }, + TestCase { + input: "e03115cfa19efcd796da389063c4be6acce684d983f8edfb3da6887b0b94fbb5e89e3a1a8e64fdd68f0670b1a02c2c33384a660c5a2266b3ae8a3b4cd76faecf011a7467b9b2a818020278a5a57d1eb1c87f1224c2d67dd02e81f1553eb75841532c2b7cca8fe5e418", + output: "d107ee6ee4a58871a33c49657faa2573e475f11918c4a4e3801d0e17fb93c6e3" + }, + TestCase { + input: "0e6c1d58b1b9d3a2d399aafd60529e07d483a2755bb7e44c373b5355632d5fca76d6ff56c93af93ddcec5ed6f62753420c1b1758e48542df7b824b00a3a54dfaf0470b18d51e31e10b12dd8e324b5dc1bb8f3b7305cb762ec6ef137dadffd4a2466748861d9004f626b0", + output: "02ab2dbb02944354799051247b1a25c19f3696e1afcb502b859e83798b33fd77" + }, + TestCase { + input: "6db2a43a229b10c3629249fc5136468b4d84df7b89ec90ebf7aa7a036c53aa2dffae9e81b2c60580543dc706a5e3457abc87e248a60ec29150c2d221a6ec08a1fda4ec0daee8576904ec7ab059b1230e7bd93c4e55ba9496cbb1e352e5b8086e303b94c861288ce53c466b", + output: "8cc4d39b2f5ba0bc9d2ee2a8777cf08533e60cc69b65a7b31c5c2121193aa31e" + }, + TestCase { + input: "31d995f7ff8b6de70829a8336c610f10df2c866107a4922b25151849f8566861df5a79163d02767f21357ad82733997899261f03dafb1ce1056f20efd16d4374b89768565823c38e19e899d910b847b023f1867b6e4fed02e604b8243c0bc7cb05b9ea1f17955bfa36698c9c", + output: "c99c7191b34c9ad3f941d4ad442cc865205cbb4c2a6927c592e831cbc4d36fcf" + }, + TestCase { + input: "cb0b8cb7de621c8e0a0fc6be2fc18d0e8818a2c2dd0b3219fa87831a61583f903c4d105495976ccac973b3ae3a09771145931a9e74c19f22f45cba4c492b29b1401347122581dfe2370d3e0359578cd10a355c619711810a8f8c232578671312c0a45c7cf7e81bdd3b249044f3", + output: "6d2f57a7e42b35369cf2cd60caf9e65aca7d9aa019e6824bb806348f1acf3c7c" + }, + TestCase { + input: "48dff78aed5f6e823054924a78dc1b8e51a117f1610181529f6d164ebf0f6406f0b02422cad8c916823759a361437ca17423d3fd84cc8afe486a31ccda01c732685418a32c064a7b9effb288e811ecc99adb2a759feecc3f702f31d9877dcdb717937c15fa2f163bea744400f58c", + output: "14b631f0f00a3024ad1810dabf02711e28449668abe27f69380942268968d4f6" + }, + TestCase { + input: "06cc9fa542ceb35c88fb6ab82c29d5dcd530f807d3f1c3bcb3974421101d1aa6ac112de6bf979cd28eb0f70c40bcaf91ed3eca9bf9e0dbc6a0b73271d1c7506740ca9ebfb72d5e00ac5ce189193ffa308804b42a6d20402bb99031cdac65ec36eb7f59f5d299df2e0b8690f760b9a0", + output: "574fd82a9fceb8f7bbbf244d16e0412cbda8153b720846c32b8f10fe5779a881" + }, + TestCase { + input: "8d93627c0b7cbf61a7fe70e78c2c8ed23b1344b4cfed31bd85980dd37b4690e5b8758f7d6d2269957a39a1ac3451cc196696ae9e9606a04089e13456095a1ce1e593481b3ac84f53f1cb10f789b099f316c948398ad52fa13474bdf486de9b431bd5d57ef9d83a42139a05f112b2bd08", + output: "344ec86642eabb206b2fd930e4c5dde78aa878577d6c271cb0069d4999495652" + }, + TestCase { + input: "d0af484b8be6b41c1971ae9d90650a1e894356c9191d6be303fa424f2b7c09544ec076a0f1865c8c97927ca137529d5bedc0df2ef08a4cc7c470b094b1eeaa86731c041633d24086b60f7369d59c57652dec9b3817477df9db289ba020e306c9a78a99b539128992deb23cfc508c5fc3af", + output: "b7ba998726477c32792e9c3eddc1cb6feb7c3933e49f2e7590d8ce7a2113e6f8" + }, + TestCase { + input: "b212f7ef04ffcdcf72c39a6309486c0eeb390ff8f218d6bd978b976612f7f898c350e90bd130723e1126af69295019b4f52c06a629ab74e03887020b75d73f0f78e12785c42feb70a7e5f12761511c9688c44da6aaa02afa35b31edc94c3a0779b6ab9462525c0ccfba76986f873fe1e6ba9", + output: "2f26b96c1fa3f3dee728f17584e733b4189821c659b8885a5fb1d12d60d2aaa9" + }, + TestCase { + input: "86591ada83fba8175a0fe91d264e7f9b2df97ee4c32570e76b579d6140508951932abdadd6a4ca53b8bb8c42927aac0a02126881d52d97b82b80e72dd59f6a42021651ee1bb5f7b3eb2b21d003d784b75dda87c13f714b216282e8175474fa661b445d071bd5341f3a88302f410d0f8a857962", + output: "e3edbc8c42ce5d2384dfb24fb1de5d4798b1bc3cc78c97033894040dfa6feb6c" + }, + TestCase { + input: "92b5a8e84b6a2ac4d5b1e61d63804abd641dd630058ec6d5f752f135724ef1947a0a84c6611d32448de6307f7b7d857404e96b81df94f87768fcfdf09faa2fe37468847542afe012995ff1bd40b257a47a7309f8896bf4fb711de55bfeb3a8be0837729ef6067c578182f17ebb080a754f22773c", + output: "80ed0a702812297c2aa1b6b4b530c2b5ed17ecfba6d51791cf152d4303ced2e6" + }, + TestCase { + input: "d284a0a9a4de5d4c68cc23884c95ad7619aa39b20a2cf401deaeb3362c3ce356f79cc3fa82d3d1f565ec8137e1f435f171496afaa1152f722315dca5209f0031cce39b6c3d718e007dfb4fd8de5ce1408dda04476aa8a96817afa86a4f8fb5857ae091c67ebd7db5d783f434ead699aa96e56f610d", + output: "654eccefd0a4fdb2ac0ab56288c64399b37bc4d57ff4a9f1cce94362fc491bda" + }, + TestCase { + input: "f57f0f8795385b805246a0a2573afc274346a9eccf50c626b0455a50bfb09668578b5a5afe54fbbd486444bdf97dba586aa224ce2e2b4b52f418ff06afa65a26f5204983a5f84734cd166c88cb70a73fb2db48f9ef20c1ee2c53ade07460114e98e7e2ebd24ac84ea90422eb143c4a42e2991a565959", + output: "135ec8b144a667dceae8fadd287df81c10ef3ebef87ff2fb56e60ae708a88f3b" + }, + TestCase { + input: "2a41a52e6578873588a57f11f1be7c7eb398d01f3bfdec2c33fe6b65a68a534a6540978daa82e0c8fccb8c6c5242f7f97b8ffa75bdedb217bd8083439eea5cbb6d193c13bd62f5658ed4304774c6b1faf5b3dce432487840cabab415fb5d67640a739ca6e5414e760869708a9d7331e7e7ad7d55e035c7", + output: "a6a1b8a26f6f440f19f16dce1d3001477d73ee7f6c374bce2922167b81970d6a" + }, + TestCase { + input: "4d11aa5d3c6b6900f49ff90dd815744572be5648b64bde638b9db7a9877dd745fa8ea80e2f7f655cee85c71a4509e21d899e49b4973579815f947587a404ad83fd4a248020d9d2a65f46485373fc926d793161f63a196ae0af590923c5be2a0e5d2f69da97e0788550c9c1dee9574ddc4a61e533275d7729", + output: "fc5159f0ddd6d765c85fcc3fc3ac1dc0d317d8ea0b110e96ac9f7a398dc386c5" + }, + TestCase { + input: "05cd99bfe031d123ca7061d3de0956f4bbf164bad792db881713d6599ddab55ee24fcee804e360896152c8766424f8309f7a24641a07be0feb5da5e5076a9af45842f385101f93433ca5199f9c6b5872b2b808e4198aba8e18dd12db772930b4912d6f5cabeb529884f4bb142de55e021b3276047b22b64cc5", + output: "8aa07742e6f1f47ad020ed6684edc8dba4af36b782955f0f972be3ae980aea0e" + }, + TestCase { + input: "529684398d68bdc19e7a00ce32cc1a8c1315b97f07137474f61f0cb84a04f2879b1109c78c6dacf7f0abf362329e3298f36fc31ef4ec06653723a5f961301dfb63537ad15946611cb2cd54ea928e322e7423fd6d146ee0b98c2c71e3bdcd33edf0845fbebd9ae4192d07acd01b432135e05af0d22f3f0c5a3d62", + output: "a07049b6ebd7b355479a3d802fda436b83ae6747d741cf9626f7c62f47cbd563" + }, + TestCase { + input: "982fb5f4af498a4a75e33a033235ea3ddb70d9d236519f883ff5b388cbef30126b98d96e93a65a26fb00d17246d18cf4e2db14a52f0f6b10e35a93beadc14ff118b02e95b38fc4736f973ba848e40b5527cb0599076d96bc578c4aada09e8faf6820bc4f562d5199974f808b7f95edca74e6b3940894a7f66534e0", + output: "09c60fec5a089a23f5da3ed2492aa21fcf7aa36183850fafc15ae8c63f596db0" + }, + TestCase { + input: "ca88614828f8acdb5fcffab6bb2fb62d932b7808e4d9cc3139a835b0cef471d9f4d8ffc4b744dffebf4f997e74ce80db662538bceb5d768f0a77077e9700149ea0e6a46a088a62717216a14b60119dd19c31038ed870b4709161c6c339c5cc60945a582263f3be9a40cd1a04c921947900f6e266f2390f3c970f7b69", + output: "fe2d4183ccdaa816b4446a9b6c07d0ba4b42ac743599db5dc482b1941f443c71" + }, + TestCase { + input: "ab6b92daf83275cb9c1b76cfb59fbcc8ac53188e0b6980918e7ac0c07c836ca9372d19e11251cca664bbb3c3db2e13b412a9820b65e95612042f5db24643cf9340b9808597735a1f92670ba573a2fb2f088d81087d70565574344af7576d35b2ed98318e2ca0067d4fa8e63f28045b83b6887d4ffa0668a10712ed5759", + output: "744538e1ae1cd7357710b56c3bc6f1bd7a8564118a1e0f9acc30fcf0b5396eef" + }, + TestCase { + input: "bfd4c7c8e90858ccf9c8834abefd9c1846ca4a11966fdd139d6de24a6bebf4b19f58d5d51e52bddd0bc6f1c7f35998f44707cae7100aeb4adefe373101429da3fca1d15737329dbbf47c783a84de59bfbb2fcd75a1a148d26aebb8d3a9a76089c0f8e4d49b71a06f9e323e2cdb54888189887a44b1fa9cb32b7c8fb7c9e0", + output: "58b17843bc851a721c5a258eef57b3854d02190e732d9b8e7a9f926ac409c173" + }, + TestCase { + input: "c5019433c285da2bb93f119e58b4f36cd1e4d99dda35dbf4f8ae39c7fe65fa0ed03bd2b96dc649472d8f1a94477ed9f29592d97c9cd54da7c790ad1af3bb5cc030b7871bc64050db779d2caf0419895bf3b7b50b8e22fbe62fe30fe7bbd6ace86ddf7b00d5d9370f20cf0f97996f4bce70bb33f1ba022cdaba0f25d55fa031", + output: "f7c92a3fb7f180370d628be78de874d693f74ccc7a54c741634258d8c512fd7f" + }, + TestCase { + input: "84b60cb3720bf29748483cf7abd0d1f1d9380459dfa968460c86e5d1a54f0b19dac6a78bf9509460e29dd466bb8bdf04e5483b782eb74d6448166f897add43d295e946942ad9a814fab95b4aaede6ae4c8108c8edaeff971f58f7cf96566c9dc9b6812586b70d5bc78e2f829ec8e179a6cd81d224b161175fd3a33aacfb1483f", + output: "8814630a39dcb99792cc4e08cae5dd078973d15cd19f17bacf04deda9e62c45f" + }, + TestCase { + input: "14365d3301150d7c5ba6bb8c1fc26e9dab218fc5d01c9ed528b72482aadee9c27bef667907797d55514468f68791f053daa2df598d7db7d54beea493bdcbb0c75c7b36ad84b9996dca96354190bd96d9d7fbe8ff54ffaf77c55eb92985da50825ee3b4179f5ec88b6fa60bb361d0caf9493494fe4d28ef843f0f498a2a9331b82a", + output: "9b690531dee948a9c559a2e0efab2ec824151a9175f2730a030b748d07cbaa7f" + }, + TestCase { + input: "4a757db93f6d4c6529211d70d5f8491799c0f73ae7f24bbd2138db2eaf2c63a85063b9f7adaa03fc348f275323248334e3ffdf9798859f9cf6693d29566ff7d50976c505ecb58e543c459b39acdf4ce4b5e80a682eaa7c1f1ce5fe4acb864ff91eb6892b23165735ea49626898b40ceeb78161f5d0ea4a103cb404d937f9d1dc362b", + output: "1ac7cc7e2e8ea14fb1b90096f41265100712c5dd41519d78b2786cfb6355af72" + }, + TestCase { + input: "da11c39c77250f6264dda4b096341ff9c4cc2c900633b20ea1664bf32193f790a923112488f882450cf334819bbaca46ffb88eff0265aa803bc79ca42739e4347c6bff0bb9aa99780261ffe42be0d3b5135d03723338fb2776841a0b4bc26360f9ef769b34c2bec5ed2feb216e2fa30fa5c37430c0360ecbfba3af6fb6b8dedacbb95c", + output: "c163cd43de224ac5c262ae39db746cfcad66074ebaec4a6da23d86b310520f21" + }, + TestCase { + input: "3341ca020d4835838b0d6c8f93aaaebb7af60730d208c85283f6369f1ee27fd96d38f2674f316ef9c29c1b6b42dd59ec5236f65f5845a401adceaa4cf5bbd91cac61c21102052634e99faedd6cdddcd4426b42b6a372f29a5a5f35f51ce580bb1845a3c7cfcd447d269e8caeb9b320bb731f53fe5c969a65b12f40603a685afed86bfe53", + output: "6c3e93f2b49f493344cc3eb1e9454f79363032beee2f7ea65b3d994b5cae438f" + }, + TestCase { + input: "989fc49594afc73405bacee4dbbe7135804f800368de39e2ea3bbec04e59c6c52752927ee3aa233ba0d8aab5410240f4c109d770c8c570777c928fce9a0bec9bc5156c821e204f0f14a9ab547e0319d3e758ae9e28eb2dbc3d9f7acf51bd52f41bf23aeb6d97b5780a35ba08b94965989744edd3b1d6d67ad26c68099af85f98d0f0e4fff9", + output: "b10adeb6a9395a48788931d45a7b4e4f69300a76d8b716c40c614c3113a0f051" + }, + TestCase { + input: "e5022f4c7dfe2dbd207105e2f27aaedd5a765c27c0bc60de958b49609440501848ccf398cf66dfe8dd7d131e04f1432f32827a057b8904d218e68ba3b0398038d755bd13d5f168cfa8a11ab34c0540873940c2a62eace3552dcd6953c683fdb29983d4e417078f1988c560c9521e6f8c78997c32618fc510db282a985f868f2d973f82351d11", + output: "3293a4b9aeb8a65e1014d3847500ffc8241594e9c4564cbd7ce978bfa50767fe" + }, + TestCase { + input: "b1f6076509938432145bb15dbe1a7b2e007934be5f753908b50fd24333455970a7429f2ffbd28bd6fe1804c4688311f318fe3fcd9f6744410243e115bcb00d7e039a4fee4c326c2d119c42abd2e8f4155a44472643704cc0bc72403b8a8ab0fd4d68e04a059d6e5ed45033b906326abb4eb4147052779bad6a03b55ca5bd8b140e131bed2dfada", + output: "f82d9602b231d332d902cb6436b15aef89acc591cb8626233ced20c0a6e80d7a" + }, + TestCase { + input: "56ea14d7fcb0db748ff649aaa5d0afdc2357528a9aad6076d73b2805b53d89e73681abfad26bee6c0f3d20215295f354f538ae80990d2281be6de0f6919aa9eb048c26b524f4d91ca87b54c0c54aa9b54ad02171e8bf31e8d158a9f586e92ffce994ecce9a5185cc80364d50a6f7b94849a914242fcb73f33a86ecc83c3403630d20650ddb8cd9c4", + output: "4beae3515ba35ec8cbd1d94567e22b0d7809c466abfbafe9610349597ba15b45" + }, + ]; + + const LONG: [TestCase; 5] = [ + TestCase { + input: "b1caa396771a09a1db9bc20543e988e359d47c2a616417bbca1b62cb02796a888fc6eeff5c0b5c3d5062fcb4256f6ae1782f492c1cf03610b4a1fb7b814c057878e1190b9835425c7a4a0e182ad1f91535ed2a35033a5d8c670e21c575ff43c194a58a82d4a1a44881dd61f9f8161fc6b998860cbe4975780be93b6f87980bad0a99aa2cb7556b478ca35d1f3746c33e2bb7c47af426641cc7bbb3425e2144820345e1d0ea5b7da2c3236a52906acdc3b4d34e474dd714c0c40bf006a3a1d889a632983814bbc4a14fe5f159aa89249e7c738b3b73666bac2a615a83fd21ae0a1ce7352ade7b278b587158fd2fabb217aa1fe31d0bda53272045598015a8ae4d8cec226fefa58daa05500906c4d85e7567", + output: "cb5648a1d61c6c5bdacd96f81c9591debc3950dcf658145b8d996570ba881a05" + }, + TestCase { + input: "712b03d9ebe78d3a032a612939c518a6166ca9a161183a7596aa35b294d19d1f962da3ff64b57494cb5656e24adcf3b50e16f4e52135d2d9de76e94aa801cf49db10e384035329c54c9455bb3a9725fd9a44f44cb9078d18d3783d46ce372c31281aecef2f8b53d5702b863d71bc5786a33dd15d9256103b5ff7572f703d5cde6695e6c84f239acd1d6512ef581330590f4ab2a114ea064a693d5f8df5d908587bc7f998cde4a8b43d8821595566597dc8b3bf9ea78b154bd8907ee6c5d4d8a851f94be510962292b7ddda04d17b79fab4c022deb400e5489639dbc448f573d5cf72073a8001b36f73ac6677351b39d9bdb900e9a1121f488a7fa0aee60682e7dc7c531c85ec0154593ded3ae70e4121cae58445d8896b549cacf22d07cdace7625d57158721b44851d796d6511c38dac28dd37cbf2d7073b407fbc813149adc485e3dacee66755443c389d2d90dc70d8ff91816c0c5d7adbad7e30772a1f3ce76c72a6a2284ec7f174aefb6e9a895c118717999421b470a9665d2728c3c60c6d3e048d58b43c0d1b5b2f00be8b64bfe453d1e8fadf5699331f9", + output: "095dcd0bc55206d2e1e715fb7173fc16a81979f278495dfc69a6d8f3174eba5a" + }, + TestCase { + input: "2a459282195123ebc6cf5782ab611a11b9487706f7795e236df3a476404f4b8c1e9904e2dc5ef29c5e06b179b8649707928c3913d1e53164747f1fa9bba6eeaf8fb759d71e32adc8c611d061345882f1cdeee3ab4cab3554adb2e43f4b01c37b4546994b25f4dcd6c497bc206865643930157cb5b2f4f25be235fa223688535907efcc253bcd083021407ea09cb1c34684aa0c1849e7efe2d9af6938c46525af9e5afb4da6e5b83da4b61dc718672a8090549cbe5aadb44f5bc93a6b3fbdc2e6d32e2eaaae637465179ea17f23ad1e4f1ebc328e2c6dc90c302b74a1edbbb0676c136b269d70c41040a313af06ab291bf489d9700950b77f207c1fc41884799931b3bca8b93331a6e96b7a3f0a8bd24cdb64964c377e0512f36444bb0643a4e3ecb328194cd5428fd89ede167472a14a9bf5730aff1e3b2c708de96eff1ebaaf63beb75f9c7d8034d6e5471e8f8a1f7efce37793a958e134619c19c54d3d42645f7a7263f25471fbaae8be3ea2fbd34ec6d7aacd7d5680948c3cd9a837c9c469a88f600d95829f4d1e4e4a5ef4ed4623c07815a1c33d9fb3b91333ff04eac92806a68a46cf2e9293f8bff466ce87fe66b46fbff7c238c7f9b2c92eb2fdc7d8084167f6f4e680d03301e5c33f78f1857d6863b1b8c36c7fce3e07d2a96a8979712079ae0023a1e3970165bfcf3a5463d2a4fdf1ca0e044f9a247528cd935734cb6d85ba53ceb95325c0eaf0ff5cd81ecb32e58917eb26bfc52dba3704bf5a927fee3220", + output: "cb1c691c87244c0caf733aacd427f83412cd48820b358c1b15dd9fadee54e5af" + }, + TestCase { + input: "32659902674c94473a283be00835eb86339d394a189a87da41dad500db27da6b6a4753b2bb219c961a227d88c6df466ba2fc1e9a2d4c982db4398778c76714d5e9940da48bc3808f3c9989131a07683b8c29d6af336e9aee1dfa57d83c48a86f17146edec07869bb06550689ebf4788159ed0a921048b4a6e3e3ec272413bec15d8e1f6a40897fa0e11d9df223ef9fc270106249ae220fdc6ebdef6d6611805421ccc850f53ee9c836baf657a94005883b5a85def344d218264f07b2ea8714afcc941096c6ded0bb6bf5b8bf652fd15a21931c58c9f526e27363ddff98c0a25bc7af9f469ab35bffea948b333f042cc18a82cec0177f33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc52820426c2c61cf12974ec249fd3502f017ffa06220075ced7e2d6b86a52677ba3916e8e8726062aec5bc8ea1c18b1e4137680b2c9d002191b423bee8691bd7e0f93c3b9959bc1c14d5c5cbe8f7c9c336aa16e9de9faa12f3f048c66d04cb441eb2bbc5e8a91e052c0f9000856896f9b7ba30c1e2eead36fc7ac30a7d3ddfc65caaba0e3b292d26dfba46b5e2dc9bc9acadde1c9f52b2969299bd1281ddff65822b629cfba2928613200e73661b803afdcc4a817d9361389e975e67dfadd22a797bdaf991ddf42db18711c079ecec55925f9978e478612609bacd900172011c27e24bad639ffc24a23877278318872153aef6893ccb5b68b94b33154df7334375aadd3edbb35272cc7b672dec68faa62900873ded52f6049891b77f2d0311a84b19b73660e09d1f1998095c1da1edecfa9f741b5fd6db048dd68255085d43529279021d59ed853470d6863b7c8e07fcb0d1e6acfb1eb16f7f60bb1f46ce70493010e57930a3b4b8b87e065272f6f1dd31df057627f4214e58798b664e1e40960f2789d44ccacfb3dbd8b02a68a053976711f8034c1ed3a8", + output: "5ac9275e02543410359a3f364b2ae3b85763321fd6d374d13fe54314e5561b01" + }, + TestCase { + input: "a65da8277a3b3738432bca9822d43b3d810cdad3b0ed2468d02bd269f1a416cd77392190c2dde8630eeb28a297bda786017abe9cf82f14751422ac9fff6322d5d9a33173db49792d3bc37fff501af667f7ca3dd335d028551e04039ef5a9d42a9443e1b80ea872fd945ad8999514ae4a29a35f60b0f7e971b67ae04d1ba1b53470c03847a3225c3ddf593a57aed3599661ae2d2bb1cddd2fa62c4a94b8704c5c35c33e08e2debe54e567ae21e27e7eb36593ae1c807a8ef8b5c1495b15412108aaf3fce4130520aa6e2d3bdf7b3ea609fdf9ea1c64258435aae2e58a7b3abda198f979c17dbe0aa74253e979bf3a5800f388ea11a7f7454c4e36270a3083a790c77cbe89693205b32880c0d8f79b1c000ee9b5e58f175ba7696616c17c45673cff25d1221f899836e95cc9e26a887a7115c4537e65ad4eacc319ba98a9a8860c089cbc76e7ea4c984d900b80622afbbbd1c0cdc670e3a4c523f81c77fed38b6aa988876b097da8411cc48e9b25a826460a862aa3fadfe75952aa4347c2effebdac9138ebcc6c34991e9f5b19fc2b847a87be72ff49c99ecf19d837ee3e23686cd760d9dd7adc78091bca79e42fdb9bc0120faec1a6ca52913e2a0156ba9850e1f39d712859f7fdf7daedf0e206dff67e7121e5d1590a8a068947a8657d753e83c7f009b6b2e54acc24afc9fdc9601a1d6d9d1f17aab0ce96c4d83405d1e3baba1dffa86ecccee7f1c1b80b1bbf859106ce2b647ae1e4a6a9b584ae1dfc0a4deebb755638f1d95dcc79b1be263177e2a05c72bde545d09ba726f41d9547117e876af81bfc672e33c71442eb05675d9552df1b313d1f9934f9ddd08955fa21d6edf23000a277f6f149591299a0a96032861ecdc96bb76afa05a2bffb445d61dc891bc70c13695920b911cad0df3fa842a3e2318c57556974343f69794cb8fa18c1ad624835857e4781041198aa705c4d11f3ef82e941be2aee7a770e54521312fe6facbaf1138eee08fa90fae986a5d93719aeb30ac292a49c1d91bf4574d553a92a4a6c305ab09db6bbeffd84c7aa707f1c1628a0220d6ba4ee5e960566686228a6e766d8a30dddf30ed5aa637c949950c3d0e894a7560670b6879a7d70f3c7e5ab29aed236cc3527bdea076fec8add12d784fbcf9a", + output: "68f62c418a6b97026cc70f6abf8419b671ee373709fa13074e37bd39f0a50fcb" + }, + ]; +} diff --git a/hashes/src/sha512/benches.rs b/hashes/src/sha512/benches.rs new file mode 100644 index 000000000..56b71800b --- /dev/null +++ b/hashes/src/sha512/benches.rs @@ -0,0 +1,33 @@ +use test::Bencher; + +use crate::{sha512, Hash, HashEngine}; + +#[bench] +pub fn sha512_10(bh: &mut Bencher) { + let mut engine = sha512::Hash::engine(); + let bytes = [1u8; 10]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha512_1k(bh: &mut Bencher) { + let mut engine = sha512::Hash::engine(); + let bytes = [1u8; 1024]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} + +#[bench] +pub fn sha512_64k(bh: &mut Bencher) { + let mut engine = sha512::Hash::engine(); + let bytes = [1u8; 65536]; + bh.iter(|| { + engine.input(&bytes); + }); + bh.bytes = bytes.len() as u64; +} diff --git a/hashes/src/sha512/crypto.rs b/hashes/src/sha512/crypto.rs new file mode 100644 index 000000000..a86d962ed --- /dev/null +++ b/hashes/src/sha512/crypto.rs @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: CC0-1.0 + +use internals::slice::SliceExt; + +use super::{HashEngine, BLOCK_SIZE}; + +#[allow(non_snake_case)] +fn Ch(x: u64, y: u64, z: u64) -> u64 { z ^ (x & (y ^ z)) } +#[allow(non_snake_case)] +fn Maj(x: u64, y: u64, z: u64) -> u64 { (x & y) | (z & (x | y)) } +#[allow(non_snake_case)] +fn Sigma0(x: u64) -> u64 { x.rotate_left(36) ^ x.rotate_left(30) ^ x.rotate_left(25) } +#[allow(non_snake_case)] +fn Sigma1(x: u64) -> u64 { x.rotate_left(50) ^ x.rotate_left(46) ^ x.rotate_left(23) } +fn sigma0(x: u64) -> u64 { x.rotate_left(63) ^ x.rotate_left(56) ^ (x >> 7) } +fn sigma1(x: u64) -> u64 { x.rotate_left(45) ^ x.rotate_left(3) ^ (x >> 6) } + +#[cfg(feature = "small-hash")] +#[macro_use] +mod small_hash { + use super::*; + + #[rustfmt::skip] + pub(super) fn round(a: u64, b: u64, c: u64, d: &mut u64, e: u64, + f: u64, g: u64, h: &mut u64, k: u64, w: u64, + ) { + let t1 = + h.wrapping_add(Sigma1(e)).wrapping_add(Ch(e, f, g)).wrapping_add(k).wrapping_add(w); + let t2 = Sigma0(a).wrapping_add(Maj(a, b, c)); + *d = d.wrapping_add(t1); + *h = t1.wrapping_add(t2); + } + #[rustfmt::skip] + pub(super) fn later_round(a: u64, b: u64, c: u64, d: &mut u64, e: u64, + f: u64, g: u64, h: &mut u64, k: u64, w: u64, + w1: u64, w2: u64, w3: u64, + ) -> u64 { + let w = w.wrapping_add(sigma1(w1)).wrapping_add(w2).wrapping_add(sigma0(w3)); + round(a, b, c, d, e, f, g, h, k, w); + w + } + + macro_rules! round( + // first round + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => ( + small_hash::round($a, $b, $c, &mut $d, $e, $f, $g, &mut $h, $k, $w) + ); + // later rounds we reassign $w before doing the first-round computation + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => ( + $w = small_hash::later_round($a, $b, $c, &mut $d, $e, $f, $g, &mut $h, $k, $w, $w1, $w2, $w3) + ) + ); +} + +#[cfg(not(feature = "small-hash"))] +#[macro_use] +mod fast_hash { + macro_rules! round( + // first round + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr) => ( + let t1 = $h.wrapping_add(Sigma1($e)).wrapping_add(Ch($e, $f, $g)).wrapping_add($k).wrapping_add($w); + let t2 = Sigma0($a).wrapping_add(Maj($a, $b, $c)); + $d = $d.wrapping_add(t1); + $h = t1.wrapping_add(t2); + ); + // later rounds we reassign $w before doing the first-round computation + ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr, $g:expr, $h:expr, $k:expr, $w:expr, $w1:expr, $w2:expr, $w3:expr) => ( + $w = $w.wrapping_add(sigma1($w1)).wrapping_add($w2).wrapping_add(sigma0($w3)); + round!($a, $b, $c, $d, $e, $f, $g, $h, $k, $w); + ) + ); +} + +impl HashEngine { + // Algorithm copied from libsecp256k1 + pub(crate) fn process_block(&mut self) { + debug_assert_eq!(self.buffer.len(), BLOCK_SIZE); + + let mut w = [0u64; 16]; + for (w_val, buff_bytes) in w.iter_mut().zip(self.buffer.bitcoin_as_chunks().0) { + *w_val = u64::from_be_bytes(*buff_bytes); + } + + let mut a = self.h[0]; + let mut b = self.h[1]; + let mut c = self.h[2]; + let mut d = self.h[3]; + let mut e = self.h[4]; + let mut f = self.h[5]; + let mut g = self.h[6]; + let mut h = self.h[7]; + + round!(a, b, c, d, e, f, g, h, 0x428a2f98d728ae22, w[0]); + round!(h, a, b, c, d, e, f, g, 0x7137449123ef65cd, w[1]); + round!(g, h, a, b, c, d, e, f, 0xb5c0fbcfec4d3b2f, w[2]); + round!(f, g, h, a, b, c, d, e, 0xe9b5dba58189dbbc, w[3]); + round!(e, f, g, h, a, b, c, d, 0x3956c25bf348b538, w[4]); + round!(d, e, f, g, h, a, b, c, 0x59f111f1b605d019, w[5]); + round!(c, d, e, f, g, h, a, b, 0x923f82a4af194f9b, w[6]); + round!(b, c, d, e, f, g, h, a, 0xab1c5ed5da6d8118, w[7]); + round!(a, b, c, d, e, f, g, h, 0xd807aa98a3030242, w[8]); + round!(h, a, b, c, d, e, f, g, 0x12835b0145706fbe, w[9]); + round!(g, h, a, b, c, d, e, f, 0x243185be4ee4b28c, w[10]); + round!(f, g, h, a, b, c, d, e, 0x550c7dc3d5ffb4e2, w[11]); + round!(e, f, g, h, a, b, c, d, 0x72be5d74f27b896f, w[12]); + round!(d, e, f, g, h, a, b, c, 0x80deb1fe3b1696b1, w[13]); + round!(c, d, e, f, g, h, a, b, 0x9bdc06a725c71235, w[14]); + round!(b, c, d, e, f, g, h, a, 0xc19bf174cf692694, w[15]); + + round!(a, b, c, d, e, f, g, h, 0xe49b69c19ef14ad2, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0xefbe4786384f25e3, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x0fc19dc68b8cd5b5, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x240ca1cc77ac9c65, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x2de92c6f592b0275, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x4a7484aa6ea6e483, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x5cb0a9dcbd41fbd4, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x76f988da831153b5, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x983e5152ee66dfab, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0xa831c66d2db43210, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0xb00327c898fb213f, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0xbf597fc7beef0ee4, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0xc6e00bf33da88fc2, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xd5a79147930aa725, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0x06ca6351e003826f, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x142929670a0e6e70, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0x27b70a8546d22ffc, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0x2e1b21385c26c926, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x4d2c6dfc5ac42aed, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x53380d139d95b3df, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x650a73548baf63de, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x766a0abb3c77b2a8, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x81c2c92e47edaee6, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x92722c851482353b, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0xa2bfe8a14cf10364, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0xa81a664bbc423001, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0xc24b8b70d0f89791, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0xc76c51a30654be30, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0xd192e819d6ef5218, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xd69906245565a910, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0xf40e35855771202a, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x106aa07032bbd1b8, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0x19a4c116b8d2d0c8, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0x1e376c085141ab53, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0x2748774cdf8eeb99, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0x34b0bcb5e19b48a8, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x391c0cb3c5c95a63, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x4ed8aa4ae3418acb, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x5b9cca4f7763e373, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x682e6ff3d6b2b8a3, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x748f82ee5defb2fc, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0x78a5636f43172f60, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0x84c87814a1f0ab72, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0x8cc702081a6439ec, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0x90befffa23631e28, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0xa4506cebde82bde9, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0xbef9a3f7b2c67915, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0xc67178f2e372532b, w[15], w[13], w[8], w[0]); + + round!(a, b, c, d, e, f, g, h, 0xca273eceea26619c, w[0], w[14], w[9], w[1]); + round!(h, a, b, c, d, e, f, g, 0xd186b8c721c0c207, w[1], w[15], w[10], w[2]); + round!(g, h, a, b, c, d, e, f, 0xeada7dd6cde0eb1e, w[2], w[0], w[11], w[3]); + round!(f, g, h, a, b, c, d, e, 0xf57d4f7fee6ed178, w[3], w[1], w[12], w[4]); + round!(e, f, g, h, a, b, c, d, 0x06f067aa72176fba, w[4], w[2], w[13], w[5]); + round!(d, e, f, g, h, a, b, c, 0x0a637dc5a2c898a6, w[5], w[3], w[14], w[6]); + round!(c, d, e, f, g, h, a, b, 0x113f9804bef90dae, w[6], w[4], w[15], w[7]); + round!(b, c, d, e, f, g, h, a, 0x1b710b35131c471b, w[7], w[5], w[0], w[8]); + round!(a, b, c, d, e, f, g, h, 0x28db77f523047d84, w[8], w[6], w[1], w[9]); + round!(h, a, b, c, d, e, f, g, 0x32caab7b40c72493, w[9], w[7], w[2], w[10]); + round!(g, h, a, b, c, d, e, f, 0x3c9ebe0a15c9bebc, w[10], w[8], w[3], w[11]); + round!(f, g, h, a, b, c, d, e, 0x431d67c49c100d4c, w[11], w[9], w[4], w[12]); + round!(e, f, g, h, a, b, c, d, 0x4cc5d4becb3e42b6, w[12], w[10], w[5], w[13]); + round!(d, e, f, g, h, a, b, c, 0x597f299cfc657e2a, w[13], w[11], w[6], w[14]); + round!(c, d, e, f, g, h, a, b, 0x5fcb6fab3ad6faec, w[14], w[12], w[7], w[15]); + round!(b, c, d, e, f, g, h, a, 0x6c44198c4a475817, w[15], w[13], w[8], w[0]); + let _ = w[15]; // silence "unnecessary assignment" lint in macro + + self.h[0] = self.h[0].wrapping_add(a); + self.h[1] = self.h[1].wrapping_add(b); + self.h[2] = self.h[2].wrapping_add(c); + self.h[3] = self.h[3].wrapping_add(d); + self.h[4] = self.h[4].wrapping_add(e); + self.h[5] = self.h[5].wrapping_add(f); + self.h[6] = self.h[6].wrapping_add(g); + self.h[7] = self.h[7].wrapping_add(h); + } +} diff --git a/hashes/src/sha512/mod.rs b/hashes/src/sha512/mod.rs new file mode 100644 index 000000000..b5fbc610a --- /dev/null +++ b/hashes/src/sha512/mod.rs @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA512 implementation. + +use internals::slice::SliceExt; + +mod crypto; +#[cfg(test)] +mod tests; + +use core::cmp; + +use crate::{incomplete_block_len, HashEngine as _}; + +crate::internal_macros::general_hash_type! { + 512, + false, + "Output of the SHA512 hash function." +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + #[cfg(not(hashes_fuzz))] + pub fn from_engine(mut e: HashEngine) -> Self { + // pad buffer with a single 1-bit then all 0s, until there are exactly 16 bytes remaining + let n_bytes_hashed = e.bytes_hashed; + + let zeroes = [0; BLOCK_SIZE - 16]; + e.input(&[0x80]); + if incomplete_block_len(&e) > zeroes.len() { + e.input(&zeroes); + } + let pad_length = zeroes.len() - incomplete_block_len(&e); + e.input(&zeroes[..pad_length]); + debug_assert_eq!(incomplete_block_len(&e), zeroes.len()); + + e.input(&[0; 8]); + e.input(&(8 * n_bytes_hashed).to_be_bytes()); + debug_assert_eq!(incomplete_block_len(&e), 0); + + Self(e.midstate()) + } + + /// Finalize a hash engine to produce a hash. + #[cfg(hashes_fuzz)] + pub fn from_engine(e: HashEngine) -> Self { + let mut hash = e.midstate(); + hash[0] ^= 0xff; // Make this distinct from SHA-256 + Hash(hash) + } +} + +pub(crate) const BLOCK_SIZE: usize = 128; + +/// Engine to compute SHA512 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine { + h: [u64; 8], + bytes_hashed: u64, + buffer: [u8; BLOCK_SIZE], +} + +impl HashEngine { + /// Constructs a new SHA512 hash engine. + #[rustfmt::skip] + pub const fn new() -> Self { + Self { + h: [ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, + ], + bytes_hashed: 0, + buffer: [0; BLOCK_SIZE], + } + } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl HashEngine { + #[cfg(not(hashes_fuzz))] + pub(crate) fn midstate(&self) -> [u8; 64] { + let mut ret = [0; 64]; + for (val, ret_bytes) in self.h.iter().zip(ret.bitcoin_as_chunks_mut().0) { + *ret_bytes = val.to_be_bytes(); + } + ret + } + + #[cfg(hashes_fuzz)] + pub(crate) fn midstate(&self) -> [u8; 64] { + let mut ret = [0; 64]; + ret.copy_from_slice(&self.buffer[..64]); + ret + } + + /// Constructs a new hash engine suitable for use constructing a `sha512_256::HashEngine`. + #[rustfmt::skip] + pub(crate) const fn sha512_256() -> Self { + Self { + h: [ + 0x22312194fc2bf72c, 0x9f555fa3c84c64c2, 0x2393b86b6f53b151, 0x963877195940eabd, + 0x96283ee2a88effe3, 0xbe5e1e2553863992, 0x2b0199fc2c85b8aa, 0x0eb72ddc81c52ca2, + ], + bytes_hashed: 0, + buffer: [0; BLOCK_SIZE], + } + } + + /// Constructs a new hash engine suitable for constructing a `sha384::HashEngine`. + #[rustfmt::skip] + pub(crate) const fn sha384() -> Self { + Self { + h: [ + 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, + 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4, + ], + bytes_hashed: 0, + buffer: [0; BLOCK_SIZE], + } + } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 64]; + const BLOCK_SIZE: usize = 128; + + fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } + crate::internal_macros::engine_input_impl!(); + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} diff --git a/hashes/src/sha512/tests.rs b/hashes/src/sha512/tests.rs new file mode 100644 index 000000000..4d982fd9e --- /dev/null +++ b/hashes/src/sha512/tests.rs @@ -0,0 +1,109 @@ +#[test] +#[cfg(feature = "alloc")] +#[cfg(feature = "hex")] +fn test() { + use alloc::string::ToString; + + use crate::{sha512, HashEngine}; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 64], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Test vectors computed with `sha512sum` + Test { + input: "", + output: [ + 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, + 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, + 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, + 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, + 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, + 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, + 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, + 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e, + ], + output_str: "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" + }, + Test { + input: "The quick brown fox jumps over the lazy dog", + output: [ + 0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73, + 0xf7, 0x3f, 0xba, 0xc0, 0x43, 0x5e, 0xd7, 0x69, + 0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88, + 0xa3, 0x09, 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64, + 0x2e, 0x93, 0xa2, 0x52, 0xa9, 0x54, 0xf2, 0x39, + 0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6, + 0xe1, 0xbf, 0xd7, 0x09, 0x78, 0x21, 0x23, 0x3f, + 0xa0, 0x53, 0x8f, 0x3d, 0xb8, 0x54, 0xfe, 0xe6, + ], + output_str: "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", + }, + Test { + input: "The quick brown fox jumps over the lazy dog.", + output: [ + 0x91, 0xea, 0x12, 0x45, 0xf2, 0x0d, 0x46, 0xae, + 0x9a, 0x03, 0x7a, 0x98, 0x9f, 0x54, 0xf1, 0xf7, + 0x90, 0xf0, 0xa4, 0x76, 0x07, 0xee, 0xb8, 0xa1, + 0x4d, 0x12, 0x89, 0x0c, 0xea, 0x77, 0xa1, 0xbb, + 0xc6, 0xc7, 0xed, 0x9c, 0xf2, 0x05, 0xe6, 0x7b, + 0x7f, 0x2b, 0x8f, 0xd4, 0xc7, 0xdf, 0xd3, 0xa7, + 0xa8, 0x61, 0x7e, 0x45, 0xf3, 0xc4, 0x63, 0xd4, + 0x81, 0xc7, 0xe5, 0x86, 0xc3, 0x9a, 0xc1, 0xed, + ], + output_str: "91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = sha512::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = sha512::Hash::engine(); + for ch in test.input.as_bytes() { + engine.input(&[*ch]); + } + let manual_hash = sha512::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } +} + +#[test] +#[cfg(feature = "serde")] +fn sha512_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + use crate::sha512; + + #[rustfmt::skip] + static HASH_BYTES: [u8; 64] = [ + 0x8b, 0x41, 0xe1, 0xb7, 0x8a, 0xd1, 0x15, 0x21, + 0x11, 0x3c, 0x52, 0xff, 0x18, 0x2a, 0x1b, 0x8e, + 0x0a, 0x19, 0x57, 0x54, 0xaa, 0x52, 0x7f, 0xcd, + 0x00, 0xa4, 0x11, 0x62, 0x0b, 0x46, 0xf2, 0x0f, + 0xff, 0xfb, 0x80, 0x88, 0xcc, 0xf8, 0x54, 0x97, + 0x12, 0x1a, 0xd4, 0x49, 0x9e, 0x08, 0x45, 0xb8, + 0x76, 0xf6, 0xdd, 0x66, 0x40, 0x08, 0x8a, 0x2f, + 0x0b, 0x2d, 0x8a, 0x60, 0x0b, 0xdf, 0x4c, 0x0c, + ]; + + let hash = sha512::Hash::from_byte_array(HASH_BYTES); + assert_tokens(&hash.compact(), &[Token::BorrowedBytes(&HASH_BYTES[..])]); + assert_tokens( + &hash.readable(), + &[Token::Str( + "8b41e1b78ad11521113c52ff182a1b8e0a195754aa527fcd00a411620b46f20f\ + fffb8088ccf85497121ad4499e0845b876f6dd6640088a2f0b2d8a600bdf4c0c", + )], + ); +} diff --git a/hashes/src/sha512_256/mod.rs b/hashes/src/sha512_256/mod.rs new file mode 100644 index 000000000..1ce6f6579 --- /dev/null +++ b/hashes/src/sha512_256/mod.rs @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SHA512_256 implementation. +//! +//! SHA512/256 is a hash function that uses the sha512 algorithm but it truncates +//! the output to 256 bits. It has different initial constants than sha512 so it +//! produces an entirely different hash compared to sha512. More information at +//! . + +use crate::sha512; + +crate::internal_macros::general_hash_type! { + 256, + false, + "Output of the SHA512/256 hash function.\n\nSHA512/256 is a hash function that uses the sha512 algorithm but it truncates the output to 256 bits. It has different initial constants than sha512 so it produces an entirely different hash compared to sha512. More information at ." +} + +impl Hash { + /// Finalize a hash engine to produce a hash. + pub fn from_engine(e: HashEngine) -> Self { + let mut ret = [0; 32]; + ret.copy_from_slice(&sha512::Hash::from_engine(e.0).as_byte_array()[..32]); + Self(ret) + } +} + +/// Engine to compute SHA512/256 hash function. +/// +/// SHA512/256 is a hash function that uses the sha512 algorithm but it truncates +/// the output to 256 bits. It has different initial constants than sha512 so it +/// produces an entirely different hash compared to sha512. More information at +/// . +#[derive(Debug, Clone)] +pub struct HashEngine(sha512::HashEngine); + +impl HashEngine { + /// Constructs a new SHA512/256 hash engine. + pub const fn new() -> Self { Self(sha512::HashEngine::sha512_256()) } +} + +impl Default for HashEngine { + fn default() -> Self { Self::new() } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 64]; + const BLOCK_SIZE: usize = sha512::BLOCK_SIZE; + + fn n_bytes_hashed(&self) -> u64 { self.0.n_bytes_hashed() } + fn input(&mut self, inp: &[u8]) { self.0.input(inp); } + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +#[cfg(test)] +mod tests { + #[test] + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn test() { + use alloc::string::ToString; + + use crate::{sha512_256, HashEngine}; + + #[derive(Clone)] + struct Test { + input: &'static str, + output: [u8; 32], + output_str: &'static str, + } + + #[rustfmt::skip] + let tests = [ + // Examples from go sha512/256 tests. + Test { + input: "", + output: [ + 0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28, + 0xab, 0x87, 0xc3, 0x62, 0x2c, 0x51, 0x14, 0x06, + 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74, + 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a, + ], + output_str: "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a" + }, + Test { + input: "abcdef", + output: [ + 0xe4, 0xfd, 0xcb, 0x11, 0xd1, 0xac, 0x14, 0xe6, + 0x98, 0x74, 0x3a, 0xcd, 0x88, 0x05, 0x17, 0x4c, + 0xea, 0x5d, 0xdc, 0x0d, 0x31, 0x2e, 0x3e, 0x47, + 0xf6, 0x37, 0x20, 0x32, 0x57, 0x1b, 0xad, 0x84, + ], + output_str: "e4fdcb11d1ac14e698743acd8805174cea5ddc0d312e3e47f6372032571bad84", + }, + Test { + input: "Discard medicine more than two years old.", + output: [ + 0x69, 0x0c, 0x8a, 0xd3, 0x91, 0x6c, 0xef, 0xd3, + 0xad, 0x29, 0x22, 0x6d, 0x98, 0x75, 0x96, 0x5e, + 0x3e, 0xe9, 0xec, 0x0d, 0x44, 0x82, 0xea, 0xcc, + 0x24, 0x8f, 0x2f, 0xf4, 0xaa, 0x0d, 0x8e, 0x5b, + ], + output_str: "690c8ad3916cefd3ad29226d9875965e3ee9ec0d4482eacc248f2ff4aa0d8e5b", + }, + Test { + input: "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", + output: [ + 0xb5, 0xba, 0xf7, 0x47, 0xc3, 0x07, 0xf9, 0x88, + 0x49, 0xec, 0x88, 0x1c, 0xf0, 0xd4, 0x86, 0x05, + 0xae, 0x4e, 0xdd, 0x38, 0x63, 0x72, 0xae, 0xa9, + 0xb2, 0x6e, 0x71, 0xdb, 0x51, 0x7e, 0x65, 0x0b, + ], + output_str: "b5baf747c307f98849ec881cf0d48605ae4edd386372aea9b26e71db517e650b", + }, + Test { + input: "The major problem is with sendmail. -Mark Horton", + output: [ + 0x53, 0xed, 0x5f, 0x9b, 0x5c, 0x0b, 0x67, 0x4a, + 0xc0, 0xf3, 0x42, 0x5d, 0x9f, 0x9a, 0x5d, 0x46, + 0x26, 0x55, 0xb0, 0x7c, 0xc9, 0x0f, 0x5d, 0x0f, + 0x69, 0x2e, 0xec, 0x09, 0x38, 0x84, 0xa6, 0x07, + ], + output_str: "53ed5f9b5c0b674ac0f3425d9f9a5d462655b07cc90f5d0f692eec093884a607", + }, + ]; + + for test in tests { + // Hash through high-level API, check hex encoding/decoding + let hash = sha512_256::Hash::hash(test.input.as_bytes()); + assert_eq!(hash, test.output_str.parse::().expect("parse hex")); + assert_eq!(hash.as_byte_array(), &test.output); + assert_eq!(hash.to_string(), test.output_str); + + // Hash through engine, checking that we can input byte by byte + let mut engine = sha512_256::Hash::engine(); + for ch in test.input.as_bytes() { + engine.0.input(&[*ch]); + } + let manual_hash = sha512_256::Hash::from_engine(engine); + assert_eq!(hash, manual_hash); + assert_eq!(hash.to_byte_array(), test.output); + } + } +} diff --git a/hashes/src/siphash24/mod.rs b/hashes/src/siphash24/mod.rs new file mode 100644 index 000000000..d65585dd5 --- /dev/null +++ b/hashes/src/siphash24/mod.rs @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! SipHash 2-4 implementation. + +use core::{cmp, mem}; + +use crate::HashEngine as _; + +crate::internal_macros::hash_type_no_default! { + 64, + false, + "Output of the SipHash24 hash function." +} + +macro_rules! compress { + ($state:expr) => {{ + compress!($state.v0, $state.v1, $state.v2, $state.v3) + }}; + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{ + $v0 = $v0.wrapping_add($v1); + $v1 = $v1.rotate_left(13); + $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); + $v3 = $v3.rotate_left(16); + $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); + $v3 = $v3.rotate_left(21); + $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); + $v1 = $v1.rotate_left(17); + $v1 ^= $v2; + $v2 = $v2.rotate_left(32); + }}; +} + +/// Loads an integer of the desired type from a byte stream, in LE order. Uses +/// `copy_nonoverlapping` to let the compiler generate the most efficient way +/// to load it from a possibly unaligned address. +/// +/// Unsafe because: unchecked indexing at `i..i+size_of(int_ty)`. +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => {{ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + $int_ty::from_le_bytes( + $buf.get_unchecked($i..($i + mem::size_of::<$int_ty>())) + .try_into() + .expect("len is correctly computed using size_of"), + ) + }}; +} + +/// Internal state of the [`HashEngine`]. +#[derive(Debug, Clone)] +pub struct State { + // v0, v2 and v1, v3 show up in pairs in the algorithm, + // and simd implementations of SipHash will use vectors + // of v02 and v13. By placing them in this order in the struct, + // the compiler can pick up on just a few simd optimizations by itself. + v0: u64, + v2: u64, + v1: u64, + v3: u64, +} + +/// Engine to compute the SipHash24 hash function. +#[derive(Debug, Clone)] +pub struct HashEngine { + k0: u64, + k1: u64, + bytes_hashed: u64, // how many bytes we've processed + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid +} + +impl HashEngine { + /// Constructs a new SipHash24 engine with keys. + #[inline] + pub const fn with_keys(k0: u64, k1: u64) -> Self { + Self { + k0, + k1, + bytes_hashed: 0, + state: State { + v0: k0 ^ 0x736f6d6570736575, + v1: k1 ^ 0x646f72616e646f6d, + v2: k0 ^ 0x6c7967656e657261, + v3: k1 ^ 0x7465646279746573, + }, + tail: 0, + ntail: 0, + } + } + + /// Retrieves the keys of this engine. + pub fn keys(&self) -> (u64, u64) { (self.k0, self.k1) } + + #[inline] + fn c_rounds(state: &mut State) { + compress!(state); + compress!(state); + } + + #[inline] + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + compress!(state); + } +} + +impl crate::HashEngine for HashEngine { + type Hash = Hash; + type Bytes = [u8; 8]; + const BLOCK_SIZE: usize = 8; + + #[inline] + fn input(&mut self, msg: &[u8]) { + let bytes_hashed = msg.len(); + self.bytes_hashed += bytes_hashed as u64; // Cast usize to u64 is ok. + + let mut needed = 0; + + if self.ntail != 0 { + needed = 8 - self.ntail; + self.tail |= + unsafe { u8to64_le(msg, 0, cmp::min(bytes_hashed, needed)) } << (8 * self.ntail); + if bytes_hashed < needed { + self.ntail += bytes_hashed; + return; + } else { + self.state.v3 ^= self.tail; + Self::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; + } + } + + // Buffered tail is now flushed, process new input. + let len = bytes_hashed - needed; + let left = len & 0x7; + + let mut i = needed; + while i < len - left { + let mi = unsafe { load_int_le!(msg, i, u64) }; + + self.state.v3 ^= mi; + Self::c_rounds(&mut self.state); + self.state.v0 ^= mi; + + i += 8; + } + + self.tail = unsafe { u8to64_le(msg, i, left) }; + self.ntail = left; + } + + fn n_bytes_hashed(&self) -> u64 { self.bytes_hashed } + + fn finalize(self) -> Self::Hash { Hash::from_engine(self) } +} + +impl Hash { + /// Constructs a new SipHash24 engine with keys. + pub fn engine(k0: u64, k1: u64) -> HashEngine { HashEngine::with_keys(k0, k1) } + + /// Produces a hash from the current state of a given engine. + #[cfg(not(hashes_fuzz))] + pub fn from_engine(e: HashEngine) -> Self { Self::from_u64(Self::from_engine_to_u64(e)) } + + #[cfg(hashes_fuzz)] + pub fn from_engine(e: HashEngine) -> Self { + let state = e.state.clone(); + Hash::from_u64(state.v0 ^ state.v1 ^ state.v2 ^ state.v3) + } + + /// Hashes the given data with an engine with the provided keys. + pub fn hash_with_keys(k0: u64, k1: u64, data: &[u8]) -> Self { + let mut engine = HashEngine::with_keys(k0, k1); + engine.input(data); + Self::from_engine(engine) + } + + /// Hashes the given data directly to u64 with an engine with the provided keys. + pub fn hash_to_u64_with_keys(k0: u64, k1: u64, data: &[u8]) -> u64 { + let mut engine = HashEngine::with_keys(k0, k1); + engine.input(data); + Self::from_engine_to_u64(engine) + } + + /// Produces a hash as `u64` from the current state of a given engine. + #[inline] + pub fn from_engine_to_u64(e: HashEngine) -> u64 { + let mut state = e.state; + + let b: u64 = ((e.bytes_hashed & 0xff) << 56) | e.tail; + + state.v3 ^= b; + HashEngine::c_rounds(&mut state); + state.v0 ^= b; + + state.v2 ^= 0xff; + HashEngine::d_rounds(&mut state); + + state.v0 ^ state.v1 ^ state.v2 ^ state.v3 + } + + /// Returns the (little endian) 64-bit integer representation of the hash value. + pub fn to_u64(self) -> u64 { u64::from_le_bytes(self.0) } + + /// Constructs a new hash from its (little endian) 64-bit integer representation. + pub fn from_u64(hash: u64) -> Self { Self(hash.to_le_bytes()) } +} + +/// Loads a u64 using up to 7 bytes of a byte slice. +/// +/// Unsafe because: unchecked indexing at `start..start+len`. +#[inline] +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + out = u64::from(load_int_le!(buf, start + i, u32)); + i += 4; + } + if i + 1 < len { + out |= u64::from(load_int_le!(buf, start + i, u16)) << (i * 8); + i += 2 + } + if i < len { + out |= u64::from(*buf.get_unchecked(start + i)) << (i * 8); + i += 1; + } + debug_assert_eq!(i, len); + out +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn siphash_2_4() { + #[rustfmt::skip] + let vecs: [[u8; 8]; 64] = [ + [0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72], + [0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74], + [0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d], + [0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85], + [0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf], + [0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18], + [0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb], + [0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab], + [0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93], + [0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e], + [0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a], + [0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4], + [0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75], + [0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14], + [0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7], + [0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1], + [0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f], + [0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69], + [0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b], + [0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb], + [0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe], + [0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0], + [0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93], + [0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8], + [0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8], + [0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc], + [0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17], + [0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f], + [0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde], + [0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6], + [0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad], + [0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32], + [0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71], + [0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7], + [0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12], + [0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15], + [0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31], + [0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02], + [0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca], + [0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a], + [0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e], + [0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad], + [0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18], + [0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4], + [0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9], + [0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9], + [0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb], + [0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0], + [0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6], + [0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7], + [0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee], + [0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1], + [0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a], + [0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81], + [0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f], + [0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24], + [0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7], + [0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea], + [0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60], + [0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66], + [0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c], + [0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f], + [0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5], + [0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95], + ]; + + let k0 = 0x_07_06_05_04_03_02_01_00; + let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; + let mut vin = [0u8; 64]; + let mut state_inc = HashEngine::with_keys(k0, k1); + + for i in 0..64 { + vin[i] = i as u8; + let vec = Hash::from_byte_array(vecs[i]); + let out = Hash::hash_with_keys(k0, k1, &vin[0..i]); + assert_eq!(vec, out, "vec #{}", i); + + let inc = Hash::from_engine(state_inc.clone()); + assert_eq!(vec, inc, "vec #{}", i); + state_inc.input(&[i as u8]); + } + } +} diff --git a/hashes/tests/api.rs b/hashes/tests/api.rs new file mode 100644 index 000000000..387b316d0 --- /dev/null +++ b/hashes/tests/api.rs @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Test the API surface of `units`. +//! +//! The point of these tests is to check the API surface as opposed to test the API functionality. +//! +//! ref: + +#![allow(dead_code)] +#![allow(unused_imports)] +// Exclude lints we don't think are valuable. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +// Import using module style e.g., `sha256::Hash`. +use bitcoin_hashes::{ + hash160, hash_newtype, hkdf, hmac, ripemd160, sha1, sha256, sha256d, sha256t, sha256t_tag, + sha384, sha3_256, sha512, sha512_256, siphash24, Hash, HashEngine, +}; +// Import using type alias style e.g., `Sha256`. +use bitcoin_hashes::{ + Hash160, Hkdf, Hmac, HmacEngine, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha3_256, + Sha512, Sha512_256, Siphash24, +}; + +// Arbitrary midstate value; taken from as sha256t unit tests. +const TEST_MIDSTATE: [u8; 32] = [ + 156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, 108, + 71, 99, 110, 96, 125, 179, 62, 234, 221, 198, 240, 201, +]; + +sha256t_tag! { + /// Test tag so we don't have to use generics. + #[derive(Debug)] + struct Tag = raw(TEST_MIDSTATE, 64); +} +hash_newtype! { + /// A concrete sha256t hash type so we don't have to use generics. + #[derive(Debug)] + struct TaggedHash(sha256t::Hash); +} + +/// All the hash types excluding `Hkdf`. +// `Hkdf` only implements `Copy` and `Clone` ATM - by design. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] // C-COMMON-TRAITS +// We check `Hkdf` implements `Debug` in the non-empty debug test below. +#[derive(Debug)] // All public types implement Debug (C-DEBUG). +struct Hashes { + a: hash160::Hash, + c: Hmac, + d: ripemd160::Hash, + e: sha1::Hash, + f: sha256::Hash, + g: sha256d::Hash, + h: TaggedHash, + i: sha384::Hash, + j: sha512::Hash, + k: sha512_256::Hash, + l: siphash24::Hash, + m: sha3_256::Hash, +} + +impl Hashes { + fn new_sha256() -> Self { + let hmac = HmacEngine::::new(&[]).finalize(); + // `TaggedHash` is not a general hash but `Sha256` is. + let tagged = TaggedHash::from_byte_array(Sha256t::::hash(&[]).to_byte_array()); + let siphash = Siphash24::from_engine(siphash24::HashEngine::with_keys(0, 0)); + + Self { + a: Hash160::hash(&[]), + // b: hkdf, + c: hmac, + d: Ripemd160::hash(&[]), + e: Sha1::hash(&[]), + f: Sha256::hash(&[]), + g: Sha256d::hash(&[]), + h: tagged, + i: Sha384::hash(&[]), + j: Sha512::hash(&[]), + k: Sha512_256::hash(&[]), + l: siphash, + m: Sha3_256::hash(&[]), + } + } +} + +/// All the hash engines. +#[derive(Clone)] // C-COMMON-TRAITS +#[derive(Debug)] // All public types implement Debug (C-DEBUG). +struct Engines { + a: hash160::HashEngine, + // We cannot derive `Debug` on a generic `HmacEngine` engine. + b: hmac::HmacEngine, + c: ripemd160::HashEngine, + d: sha1::HashEngine, + e: sha256::HashEngine, + f: sha256d::HashEngine, + g: sha256t::HashEngine, + h: sha384::HashEngine, + i: sha512::HashEngine, + j: sha512_256::HashEngine, + k: siphash24::HashEngine, + l: sha3_256::HashEngine, +} + +impl Engines { + fn new_sha256() -> Self { + Self { + a: hash160::HashEngine::new(), + b: hmac::HmacEngine::::new(&[]), + c: ripemd160::HashEngine::new(), + d: sha1::HashEngine::new(), + e: sha256::HashEngine::new(), + f: sha256d::HashEngine::new(), + g: sha256t::Hash::::engine(), + h: sha384::HashEngine::new(), + i: sha512::HashEngine::new(), + j: sha512_256::HashEngine::new(), + k: siphash24::HashEngine::with_keys(0, 0), + l: sha3_256::HashEngine::new(), + } + } +} + +/// Public structs that are not hashes, engines, or errors. +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] // C-COMMON-TRAITS +#[derive(Debug)] // All public types implement Debug (C-DEBUG). +struct OtherStructs { + a: sha256::Midstate, + // There is no way to construct a `siphash24::State` so we cannot directly + // test it but `siphash24::HashEngine` includes one so `Engines` implicitly + // tests it (e.g. `Debug` and `Clone`). + // + // b: siphash24::State, + + // Don't worry about including a tag because its tested in `primitives`. +} + +impl OtherStructs { + fn new() -> Self { Self { a: sha256::Midstate::new(TEST_MIDSTATE, 0) } } +} + +/// All hash engine types that implement `Default`. +#[derive(Default)] +struct Default { + a: hash160::HashEngine, + b: ripemd160::HashEngine, + c: sha1::HashEngine, + d: sha256::HashEngine, + e: sha256d::HashEngine, + f: sha256t::HashEngine, + g: sha384::HashEngine, + h: sha512::HashEngine, + i: sha512_256::HashEngine, + j: sha3_256::HashEngine, +} + +/// Hash types that require a key. +struct Keyed { + a: Hmac, + l: siphash24::Hash, +} + +/// A struct that includes all public error types. +// These derives are the policy of `rust-bitcoin` not Rust API guidelines. +#[derive(Debug, Clone, PartialEq, Eq)] // All public types implement Debug (C-DEBUG). +struct Errors { + b: hkdf::MaxLengthError, + c: sha256::MidstateError, +} + +#[test] +fn api_can_use_modules_from_crate_root() { + use bitcoin_hashes::{ + hash160, hkdf, hmac, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256, + siphash24, + }; +} + +#[test] +fn api_can_use_alias_from_crate_root() { + use bitcoin_hashes::{ + Hash160, Hkdf, Hmac, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha512, Sha512_256, + Siphash24, + }; +} + +// `Debug` representation is never empty (C-DEBUG-NONEMPTY). +#[test] +fn api_all_non_error_types_have_non_empty_debug() { + macro_rules! check_debug { + ($t:tt; $($field:tt),* $(,)?) => { + $( + let debug = format!("{:?}", $t.$field); + assert!(!debug.is_empty()); + )* + } + } + + let t = Hashes::::new_sha256(); + check_debug!(t; a, c, d, e, f, g, h, i, j, k, l); + + // This tests `Debug` on `Hkdf` but not for all `HashEngine` types. + let t = Hkdf::::new(&[], &[]); + let debug = format!("{:?}", t); + assert!(!debug.is_empty()); + + let t = Engines::new_sha256(); + check_debug!(t; a, c, d, e, f, g, h, i, j, k); + + let t = OtherStructs::new(); + check_debug!(t; a); +} + +#[test] +fn all_types_implement_send_sync() { + fn assert_send() {} + fn assert_sync() {} + + // Types are `Send` and `Sync` where possible (C-SEND-SYNC). + assert_send::>(); + assert_sync::>(); + assert_send::(); + assert_sync::(); + assert_send::(); + assert_sync::(); + + // Error types should implement the Send and Sync traits (C-GOOD-ERR). + assert_send::(); + assert_sync::(); +} diff --git a/hashes/tests/regression.rs b/hashes/tests/regression.rs new file mode 100644 index 000000000..716bf3d31 --- /dev/null +++ b/hashes/tests/regression.rs @@ -0,0 +1,102 @@ +//! Regression tests for each hash type. +//! +//! Note that if `bitcoin-io` is enabled then we get more regression-like testing from `./io.rs`. +//! +//! Test input data and expected hashes is the same as in `io/src/hash.rs`. + +#![cfg(feature = "hex")] +// Exclude lints we don't think are valuable. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +use bitcoin_hashes::{ + hash160, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha3_256, sha512, sha512_256, + siphash24, HashEngine as _, HmacEngine, +}; + +const DATA: &str = "arbitrary data to hash as a regression test"; +const HMAC_KEY: &[u8] = b"some key"; + +macro_rules! impl_regression_test { + ($($test_name:ident, $module:ident, $want:literal);* $(;)?) => { + $( + #[test] + fn $test_name() { + let hash = $module::Hash::hash(DATA.as_bytes()); + let got = format!("{}", hash); + assert_eq!(got, $want); + } + )* + } +} + +impl_regression_test! { + regression_hash160, hash160, "a17909f6d5373b0085c4180ba207126e5040f74d"; + regression_ripemd160, ripemd160, "e6801701c77a1cd85662335258c7869631b4a9a8"; + regression_sha1, sha1, "e1e81eeabadafa3d5d41cc3f405385426b0f47fd"; + regression_sha256, sha256, "d291c6c5a07fa1d9315cdae090ebe14169fbe0a219cd55a48d0d2104eab6ec51"; + regression_sha256d, sha256d, "93a743b022290bde3233a619b21aaebe06c5cf5cc959464c41be35711e37731b"; + regression_sha384, sha384, "f545bd83d297978d47a7f26b858a54188499dfb4d7d570a6a2362c765031d57a29d7e002df5e34d184e70b65a4f47153"; + regression_sha3_256, sha3_256, "9479c957c295f4e42a31dbd571062610c2c3435310b27a9548b83c0b45f4c9b3"; + regression_sha512, sha512, "057d0a37e9e0ac9a93acde0752748da059a27bcf946c7af00692ac1a95db8d21f965f40af22efc4710f100f8d3e43f79f77b1f48e1e400a95b7344b7bc0dfd10"; + regression_sha512_256, sha512_256, "e204244c429b5bca037a2a8a6e7ed8a42b808ceaff182560840bb8c5c8e9a2ec"; +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +pub struct RegHashTag; + +impl sha256t::Tag for RegHashTag { + const MIDSTATE: sha256::Midstate = sha256::Midstate::new([0xab; 32], 64); +} + +type RegHash = sha256t::Hash; + +#[test] +fn regression_sha256t() { + let hash = RegHash::hash(DATA.as_bytes()); + let got = format!("{}", hash); + let want = "17db326d7c13867376ccca1f8a211377be3cbeaeb372f167822284866ddf14ca"; + assert_eq!(got, want); +} + +#[test] +fn regression_hmac_sha256_with_key() { + let mut engine = HmacEngine::::new(HMAC_KEY); + engine.input(DATA.as_bytes()); + let hash = engine.finalize(); + + let got = format!("{}", hash); + let want = "d159cecaf4adf90b6a641bab767e4817d3a51c414acea3682686c35ec0b37b52"; + assert_eq!(got, want); +} + +#[test] +fn regression_hmac_sha512_with_key() { + let mut engine = HmacEngine::::new(HMAC_KEY); + engine.input(DATA.as_bytes()); + let hash = engine.finalize(); + + let got = format!("{}", hash); + let want = "8511773748f89ba22c07fb3a2981a12c1823695119de41f4a62aead6b848bd34939acf16475c35ed7956114fead3e794cc162ecd35e447a4dabc3227d55f757b"; + assert_eq!(got, want); +} + +#[test] +fn regression_siphash24_with_key() { + let mut engine = siphash24::HashEngine::with_keys(0, 0); + engine.input(DATA.as_bytes()); + let hash = siphash24::Hash::from_engine(engine); + + let got = format!("{}", hash); + let want = "e823ed82311d601a"; + assert_eq!(got, want); +} + +#[test] +fn regression_sha256_hash_again() { + let hash = sha256::Hash::hash(b"Don't explain your philosophy. Embody it."); + let again = hash.hash_again(); + + let got = format!("{}", again); + let want = "28273103bcd88ab99e2b1007174770ff3f0ea91ee4b3ac942879ed1a2d264b4c"; + assert_eq!(got, want); +} diff --git a/internals/CHANGELOG.md b/internals/CHANGELOG.md new file mode 100644 index 000000000..249b7dfe2 --- /dev/null +++ b/internals/CHANGELOG.md @@ -0,0 +1,33 @@ +# 0.4.2 - 2025-12-08 + +- Move `impl_array_newtype` to internals [#5334](https://github.com/rust-bitcoin/rust-bitcoin/pull/5334) + +# 0.4.1 - 2024-10-18 + +- Bump MSRV to Rust 1.74.0 [#4926](https://github.com/rust-bitcoin/rust-bitcoin/pull/4926) +- Add `hex-conservative` dependency + +# 0.4.0 - 2024-09-18 + +- Introduce `ToU64` trait [#2929](https://github.com/rust-bitcoin/rust-bitcoin/pull/2929) +- Add macro `impl_to_hex_from_lower_hex ` [#3150](https://github.com/rust-bitcoin/rust-bitcoin/pull/3150) +- Fix bug in `ArrayVec::extend_from_slice` [#3272](https://github.com/rust-bitcoin/rust-bitcoin/pull/3272) +- Introduce `read_push_data_len()` and [#3293](https://github.com/rust-bitcoin/rust-bitcoin/pull/3293/) +- Introduce new `compact_size` module [#3259](https://github.com/rust-bitcoin/rust-bitcoin/pull/3259) + +# 0.3.0 - 2024-03-24 + +- Bump MSRV to Rust version 1.56.1 [#2188](https://github.com/rust-bitcoin/rust-bitcoin/pull/2188) +- Implement custom `ArrayVec` that is `Copy` [#2287](https://github.com/rust-bitcoin/rust-bitcoin/pull/2287) + +# 0.2.0 - 2023-06-20 + +- [Rename crate](https://github.com/rust-bitcoin/rust-bitcoin/pull/1885) to `bitcoin-internals` +- Add module to assist [alloc-free parse error handling](https://github.com/rust-bitcoin/rust-bitcoin/pull/1297) +- Move various macros here. + +# 0.1.0 - 2023-03-08 + +Split this crate out from the [rust-bitcoin](https://github.com/rust-bitcoin/rust-bitcoin) crate. +For previous development history see the original +[CHANGELOG](https://github.com/rust-bitcoin/rust-bitcoin/blob/master/bitcoin/CHANGELOG.md) file. diff --git a/internals/Cargo.toml b/internals/Cargo.toml new file mode 100644 index 000000000..72da6efbe --- /dev/null +++ b/internals/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = "bitcoin-internals" +version = "0.4.2" +authors = ["Andrew Poelstra ", "The Rust Bitcoin developers"] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin/" +documentation = "https://docs.rs/bitcoin-internals" +description = "Internal types and macros used by rust-bitcoin ecosystem" +categories = ["cryptography::cryptocurrencies", "no-std"] +keywords = ["internal"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = [] +std = ["alloc", "hex?/std"] +alloc = ["hex?/alloc"] + +test-serde = ["serde", "serde_json", "bincode"] + +[dependencies] +hex = { package = "hex-conservative", version = "0.3.0", default-features = false, optional = true } +serde = { version = "1.0.195", default-features = false, optional = true } + +# Don't enable these directly, use `test-serde` feature instead. +serde_json = { version = "1.0.68", optional = true } +bincode = { version = "1.3.1", optional = true } + +[dev-dependencies] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unexpected_cfgs = { level = "deny", check-cfg = ['cfg(kani)'] } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/internals/README.md b/internals/README.md new file mode 100644 index 000000000..66aae69cd --- /dev/null +++ b/internals/README.md @@ -0,0 +1,6 @@ +# Rust Bitcoin Internals + +This crate is only meant to be used internally by crates in the +[rust-bitcoin](https://github.com/rust-bitcoin) ecosystem. + +This crate will never be stabilized, depend on it at your own risk. diff --git a/internals/build.rs b/internals/build.rs new file mode 100644 index 000000000..635e60009 --- /dev/null +++ b/internals/build.rs @@ -0,0 +1,96 @@ +// Exclude lints we don't think are valuable. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +const MAX_USED_VERSION: u64 = 80; + +use std::io; + +fn main() { + let rustc = std::env::var_os("RUSTC"); + let rustc = rustc.as_ref().map(std::path::Path::new).unwrap_or_else(|| "rustc".as_ref()); + let output = std::process::Command::new(rustc) + .arg("--version") + .output() + .unwrap_or_else(|error| panic!("failed to run `{:?} --version`: {:?}", rustc, error)); + assert!(output.status.success(), "{:?} -- version returned non-zero exit code", rustc); + let stdout = String::from_utf8(output.stdout).expect("rustc produced non-UTF-8 output"); + let version_prefix = "rustc "; + if !stdout.starts_with(version_prefix) { + panic!("unexpected rustc output: {}", stdout); + } + + let version = &stdout[version_prefix.len()..]; + let end = version.find(&[' ', '-'] as &[_]).unwrap_or(version.len()); + let version = &version[..end]; + let mut version_components = version.split('.'); + let major = version_components.next().unwrap(); + assert_eq!(major, "1", "unexpected Rust major version"); + let minor = version_components + .next() + .unwrap_or("0") + .parse::() + .expect("invalid Rust minor version"); + + let msrv = std::env::var("CARGO_PKG_RUST_VERSION").unwrap(); + let mut msrv = msrv.split("."); + let msrv_major = msrv.next().unwrap(); + assert_eq!(msrv_major, "1", "unexpected Rust major version"); + let msrv_minor = msrv.next().unwrap().parse::().unwrap(); + + let out_dir = std::env::var_os("OUT_DIR").expect("missing OUT_DIR env var"); + let out_dir = std::path::PathBuf::from(out_dir); + let macro_file = std::fs::File::create(out_dir.join("rust_version.rs")) + .expect("failed to create rust_version.rs"); + let macro_file = io::BufWriter::new(macro_file); + write_macro(macro_file, msrv_minor, minor).expect("failed to write to rust_version.rs"); +} + +fn write_macro(mut macro_file: impl io::Write, msrv_minor: u64, minor: u64) -> io::Result<()> { + writeln!(macro_file, "/// Expands code based on Rust version this is compiled under.")?; + writeln!(macro_file, "///")?; + writeln!(macro_file, "/// Example:")?; + writeln!(macro_file, "/// ```")?; + writeln!(macro_file, "/// bitcoin_internals::rust_version! {{")?; + writeln!(macro_file, "/// if >= 1.78 {{")?; + writeln!(macro_file, "/// println!(\"This is Rust 1.78+\");")?; + writeln!(macro_file, "/// }} else {{")?; + writeln!(macro_file, "/// println!(\"This is Rust < 1.78\");")?; + writeln!(macro_file, "/// }}")?; + writeln!(macro_file, "/// }}")?; + writeln!(macro_file, "/// ```")?; + writeln!(macro_file, "///")?; + writeln!(macro_file, "/// The `else` branch is optional.")?; + writeln!(macro_file, "/// Currently only the `>=` operator is supported.")?; + writeln!(macro_file, "#[macro_export]")?; + writeln!(macro_file, "macro_rules! rust_version {{")?; + + // These two loops are the magic; we output the clause if_yes/if_no + // dependent on the current compiler version (`minor`). + for version in msrv_minor..=minor { + writeln!( + macro_file, + " (if >= 1.{} {{ $($if_yes:tt)* }} $(else {{ $($if_no:tt)* }})?) => {{", + version + )?; + writeln!(macro_file, " $($if_yes)*")?; + writeln!(macro_file, " }};")?; + } + for version in (minor + 1)..(MAX_USED_VERSION + 1) { + writeln!( + macro_file, + " (if >= 1.{} {{ $($if_yes:tt)* }} $(else {{ $($if_no:tt)* }})?) => {{", + version + )?; + writeln!(macro_file, " $($($if_no)*)?")?; + writeln!(macro_file, " }};")?; + } + writeln!(macro_file, " (if >= $unknown:tt $($rest:tt)*) => {{")?; + writeln!( + macro_file, + " compile_error!(concat!(\"unknown Rust version \", stringify!($unknown)));" + )?; + writeln!(macro_file, " }};")?; + writeln!(macro_file, "}}")?; + writeln!(macro_file, "pub use rust_version;")?; + macro_file.flush() +} diff --git a/internals/contrib/extra_lints.sh b/internals/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/internals/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/internals/contrib/test_vars.sh b/internals/contrib/test_vars.sh new file mode 100644 index 000000000..ad0a3f27e --- /dev/null +++ b/internals/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="serde" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc serde" + +# Run these examples. +EXAMPLES="" diff --git a/internals/src/array.rs b/internals/src/array.rs new file mode 100644 index 000000000..c56401c92 --- /dev/null +++ b/internals/src/array.rs @@ -0,0 +1,105 @@ +//! Contains extensions related to arrays. + +/// Extension trait for arrays. +pub trait ArrayExt { + /// The item type the array is storing. + type Item; + + /// Just like the slicing operation, this returns an array `LEN` items long at position + /// `OFFSET`. + /// + /// The correctness of this operation is compile-time checked. + /// + /// Note that unlike slicing where the second number is the end index, here the second number + /// is array length! + fn sub_array(&self) -> &[Self::Item; LEN]; + + /// Returns an item at given statically-known index. + /// + /// This is just like normal indexing except the check happens at compile time. + fn get_static(&self) -> &Self::Item { &self.sub_array::()[0] } + + /// Returns the first item in an array. + /// + /// Fails to compile if the array is empty. + /// + /// Note that this method's name intentionally shadows the `std`'s `first` method which + /// returns `Option`. The rationale is that given the known length of the array, we always know + /// that this will not return `None` so trying to keep the `std` method around is pointless. + /// Importing the trait will also cause compile failures - that's also intentional to expose + /// the places where useless checks are made. + fn first(&self) -> &Self::Item { self.get_static::<0>() } + + /// Splits the array into two, non-overlapping smaller arrays covering the entire range. + /// + /// This is almost equivalent to just calling [`sub_array`](Self::sub_array) twice, except it also + /// checks that the arrays don't overlap and that they cover the full range. This is very useful + /// for demonstrating correctness, especially when chained. Using this technique even revealed + /// a bug in the past. ([#4195](https://github.com/rust-bitcoin/rust-bitcoin/issues/4195)) + fn split_array( + &self, + ) -> (&[Self::Item; LEFT], &[Self::Item; RIGHT]); + + /// Splits the array into the first element and the remaining, one element shorter, array. + /// + /// Fails to compile if the array is empty. + /// + /// Note that this method's name intentionally shadows the `std`'s `split_first` method which + /// returns `Option`. The rationale is that given the known length of the array, we always know + /// that this will not return `None` so trying to keep the `std` method around is pointless. + /// Importing the trait will also cause compile failures - that's also intentional to expose + /// the places where useless checks are made. + fn split_first(&self) -> (&Self::Item, &[Self::Item; RIGHT]) { + let (first, remaining) = self.split_array::<1, RIGHT>(); + (&first[0], remaining) + } + + /// Splits the array into the last element and the remaining, one element shorter, array. + /// + /// Fails to compile if the array is empty. + /// + /// Note that this method's name intentionally shadows the `std`'s `split_last` method which + /// returns `Option`. The rationale is that given the known length of the array, we always know + /// that this will not return `None` so trying to keep the `std` method around is pointless. + /// Importing the trait will also cause compile failures - that's also intentional to expose + /// the places where useless checks are made. + /// + /// The returned tuple is also reversed just as `std` for consistency and simpler diffs when + /// migrating. + fn split_last(&self) -> (&Self::Item, &[Self::Item; LEFT]) { + let (remaining, last) = self.split_array::(); + (&last[0], remaining) + } +} + +impl ArrayExt for [T; N] { + type Item = T; + + fn sub_array(&self) -> &[Self::Item; LEN] { + #[allow(clippy::let_unit_value)] + let _ = Hack::::IS_VALID_RANGE; + + self[OFFSET..(OFFSET + LEN)].try_into().expect("this is also compiler-checked above") + } + + fn split_array( + &self, + ) -> (&[Self::Item; LEFT], &[Self::Item; RIGHT]) { + #[allow(clippy::let_unit_value)] + let _ = Hack2::::IS_FULL_RANGE; + + (self.sub_array::<0, LEFT>(), self.sub_array::()) + } +} + +struct Hack; + +impl Hack { + const IS_VALID_RANGE: () = assert!(OFFSET + LEN <= N); +} + +struct Hack2; + +impl Hack2 { + const IS_FULL_RANGE: () = assert!(LEFT + RIGHT == N); +} diff --git a/internals/src/array_vec.rs b/internals/src/array_vec.rs new file mode 100644 index 000000000..13c0f569c --- /dev/null +++ b/internals/src/array_vec.rs @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! A simplified `Copy` version of `arrayvec::ArrayVec`. + +use core::fmt; + +pub use safety_boundary::ArrayVec; + +/// Limits the scope of `unsafe` auditing. +// New trait impls and fns that don't need to access internals should go below the module, not +// inside it! +mod safety_boundary { + use core::mem::MaybeUninit; + + /// A growable contiguous collection backed by array. + #[derive(Copy)] + pub struct ArrayVec { + len: usize, + data: [MaybeUninit; CAP], + } + + impl ArrayVec { + /// Constructs an empty `ArrayVec`. + pub const fn new() -> Self { Self { len: 0, data: [MaybeUninit::uninit(); CAP] } } + + /// Constructs a new `ArrayVec` initialized with the contents of `slice`. + /// + /// # Panics + /// + /// If the slice is longer than `CAP`. + pub const fn from_slice(slice: &[T]) -> Self { + assert!(slice.len() <= CAP); + let mut data = [MaybeUninit::uninit(); CAP]; + let mut i = 0; + // can't use mutable references and operators in const + while i < slice.len() { + data[i] = MaybeUninit::new(slice[i]); + i += 1; + } + + Self { len: slice.len(), data } + } + + /// Returns a reference to the underlying data. + pub const fn as_slice(&self) -> &[T] { + // transmute needed; see https://github.com/rust-lang/rust/issues/63569 + // SAFETY: self.len is chosen such that everything is initialized up to len, + // and MaybeUninit has the same representation as T. + let ptr = self.data.as_ptr().cast::(); + unsafe { core::slice::from_raw_parts(ptr, self.len) } + } + + /// Returns a mutable reference to the underlying data. + pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: self.len is chosen such that everything is initialized up to len, + // and MaybeUninit has the same representation as T. + let ptr = self.data.as_mut_ptr().cast::(); + unsafe { core::slice::from_raw_parts_mut(ptr, self.len) } + } + + /// Adds an element into `self`. + /// + /// # Panics + /// + /// If the length would increase past CAP. + pub fn push(&mut self, element: T) { + assert!(self.len < CAP); + self.data[self.len] = MaybeUninit::new(element); + self.len += 1; + } + + /// Removes the last element, returning it. + /// + /// # Returns + /// + /// None if the ArrayVec is empty. + pub fn pop(&mut self) -> Option { + if self.len > 0 { + self.len -= 1; + // SAFETY: All elements in 0..len are initialized + let res = self.data[self.len]; + self.data[self.len] = MaybeUninit::uninit(); + Some(unsafe { res.assume_init() }) + } else { + None + } + } + + /// Copies and appends all elements from `slice` into `self`. + /// + /// # Panics + /// + /// If the length would increase past CAP. + pub fn extend_from_slice(&mut self, slice: &[T]) { + let new_len = self.len.checked_add(slice.len()).expect("integer/buffer overflow"); + assert!(new_len <= CAP, "buffer overflow"); + // SAFETY: MaybeUninit has the same layout as T + let slice = unsafe { + let ptr = slice.as_ptr(); + core::slice::from_raw_parts(ptr.cast::>(), slice.len()) + }; + self.data[self.len..new_len].copy_from_slice(slice); + self.len = new_len; + } + } +} + +impl Default for ArrayVec { + fn default() -> Self { Self::new() } +} + +/// Clones the value *faster* than using `Copy`. +/// +/// Because we avoid copying the uninitialized part of the array this copies the value faster than +/// memcpy. +#[allow(clippy::non_canonical_clone_impl)] +impl Clone for ArrayVec { + fn clone(&self) -> Self { Self::from_slice(self) } +} + +impl core::ops::Deref for ArrayVec { + type Target = [T]; + + fn deref(&self) -> &Self::Target { self.as_slice() } +} + +impl core::ops::DerefMut for ArrayVec { + fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() } +} + +impl Eq for ArrayVec {} + +impl PartialEq> + for ArrayVec +{ + fn eq(&self, other: &ArrayVec) -> bool { **self == **other } +} + +impl PartialEq<[T]> for ArrayVec { + fn eq(&self, other: &[T]) -> bool { **self == *other } +} + +impl PartialEq> for [T] { + fn eq(&self, other: &ArrayVec) -> bool { *self == **other } +} + +impl PartialEq<[T; LEN]> + for ArrayVec +{ + fn eq(&self, other: &[T; LEN]) -> bool { **self == *other } +} + +impl PartialEq> + for [T; LEN] +{ + fn eq(&self, other: &ArrayVec) -> bool { *self == **other } +} + +impl Ord for ArrayVec { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { (**self).cmp(&**other) } +} + +impl PartialOrd> + for ArrayVec +{ + fn partial_cmp(&self, other: &ArrayVec) -> Option { + (**self).partial_cmp(&**other) + } +} + +impl fmt::Debug for ArrayVec { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } +} + +impl core::hash::Hash for ArrayVec { + fn hash(&self, state: &mut H) { core::hash::Hash::hash(&**self, state) } +} + +#[cfg(test)] +mod tests { + use super::ArrayVec; + + #[test] + fn arrayvec_ops() { + let mut av = ArrayVec::<_, 1>::new(); + assert!(av.is_empty()); + av.push(42); + assert_eq!(av.len(), 1); + assert_eq!(av, [42]); + } + + #[test] + #[should_panic] + fn overflow_push() { + let mut av = ArrayVec::<_, 0>::new(); + av.push(42); + } + + #[test] + #[should_panic] + fn overflow_extend() { + let mut av = ArrayVec::<_, 0>::new(); + av.extend_from_slice(&[42]); + } + + #[test] + fn extend_from_slice() { + let mut av = ArrayVec::::new(); + av.extend_from_slice(b"abc"); + } +} + +#[cfg(kani)] +mod verification { + use super::*; + + #[kani::unwind(16)] // One greater than 15 (max number of elements). + #[kani::proof] + fn no_out_of_bounds_less_than_cap() { + const CAP: usize = 32; + let n = kani::any::(); + let elements = (n & 0x0F) as usize; // Just use 4 bits. + + let val = kani::any::(); + + let mut v = ArrayVec::::new(); + for _ in 0..elements { + v.push(val); + } + + for i in 0..elements { + assert_eq!(v[i], val); + } + } + + #[kani::unwind(16)] // One greater than 15. + #[kani::proof] + fn no_out_of_bounds_upto_cap() { + const CAP: usize = 15; + let elements = CAP; + + let val = kani::any::(); + + let mut v = ArrayVec::::new(); + for _ in 0..elements { + v.push(val); + } + + for i in 0..elements { + assert_eq!(v[i], val); + } + } +} diff --git a/internals/src/compact_size.rs b/internals/src/compact_size.rs new file mode 100644 index 000000000..5b5c26dfe --- /dev/null +++ b/internals/src/compact_size.rs @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Variable length integer encoding A.K.A [`CompactSize`]. +//! +//! An integer can be encoded depending on the represented value to save space. Variable length +//! integers always precede an array/vector of a type of data that may vary in length. +//! +//! [`CompactSize`]: + +use crate::array_vec::ArrayVec; +use crate::ToU64; + +/// The maximum size of a serialized object in bytes or number of elements +/// (for eg vectors) when the size is encoded as `CompactSize`. +/// +/// This is `MAX_SIZE` in Bitcoin Core. +// Issue: https://github.com/rust-bitcoin/rust-bitcoin/issues/3264 +pub const MAX_ENCODABLE_VALUE: u64 = 0x0200_0000; + +/// The maximum length of an encoding. +pub const MAX_ENCODING_SIZE: usize = 9; + +/// Returns the number of bytes used to encode this `CompactSize` value. +/// +/// # Returns +/// +/// - 1 for 0..=0xFC +/// - 3 for 0xFD..=(2^16-1) +/// - 5 for 0x10000..=(2^32-1) +/// - 9 otherwise. +#[inline] +pub fn encoded_size(value: impl ToU64) -> usize { encoded_size_const(value.to_u64()) } + +/// Returns the number of bytes used to encode this `CompactSize` value (in const context). +/// +/// # Returns +/// +/// - 1 for 0..=0xFC +/// - 3 for 0xFD..=(2^16-1) +/// - 5 for 0x10000..=(2^32-1) +/// - 9 otherwise. +#[inline] +pub const fn encoded_size_const(value: u64) -> usize { + match value { + 0..=0xFC => 1, + 0xFD..=0xFFFF => 3, + 0x10000..=0xFFFFFFFF => 5, + _ => 9, + } +} + +/// Encodes `CompactSize` without allocating. +#[inline] +pub fn encode(value: impl ToU64) -> ArrayVec { + let value = value.to_u64(); + let mut res = ArrayVec::::new(); + match value { + 0..=0xFC => { + res.push(value as u8); // Cast ok because of match. + } + 0xFD..=0xFFFF => { + let v = value as u16; // Cast ok because of match. + res.push(0xFD); + res.extend_from_slice(&v.to_le_bytes()); + } + 0x10000..=0xFFFFFFFF => { + let v = value as u32; // Cast ok because of match. + res.push(0xFE); + res.extend_from_slice(&v.to_le_bytes()); + } + _ => { + res.push(0xFF); + res.extend_from_slice(&value.to_le_bytes()); + } + } + res +} + +/// Gets the compact size encoded value from `slice` and moves slice past the encoding. +/// +/// Caller to guarantee that the encoding is well formed. Well formed is defined as: +/// +/// * Being at least long enough. +/// * Containing a minimal encoding. +/// +/// # Panics +/// +/// * Panics in release mode if the `slice` does not contain a valid minimal compact size encoding. +/// * Panics in debug mode if the encoding is not minimal (referred to as "non-canonical" in Core). +pub fn decode_unchecked(slice: &mut &[u8]) -> u64 { + if slice.is_empty() { + panic!("tried to decode an empty slice"); + } + + match slice[0] { + 0xFF => { + const SIZE: usize = 9; + if slice.len() < SIZE { + panic!("slice too short, expected at least 9 bytes"); + }; + + let mut bytes = [0_u8; SIZE - 1]; + bytes.copy_from_slice(&slice[1..SIZE]); + + let v = u64::from_le_bytes(bytes); + debug_assert!(v > u32::MAX.into(), "non-minimal encoding of a u64"); + *slice = &slice[SIZE..]; + v + } + 0xFE => { + const SIZE: usize = 5; + if slice.len() < SIZE { + panic!("slice too short, expected at least 5 bytes"); + }; + + let mut bytes = [0_u8; SIZE - 1]; + bytes.copy_from_slice(&slice[1..SIZE]); + + let v = u32::from_le_bytes(bytes); + debug_assert!(v > u16::MAX.into(), "non-minimal encoding of a u32"); + *slice = &slice[SIZE..]; + u64::from(v) + } + 0xFD => { + const SIZE: usize = 3; + if slice.len() < SIZE { + panic!("slice too short, expected at least 3 bytes"); + }; + + let mut bytes = [0_u8; SIZE - 1]; + bytes.copy_from_slice(&slice[1..SIZE]); + + let v = u16::from_le_bytes(bytes); + debug_assert!(v >= 0xFD, "non-minimal encoding of a u16"); + *slice = &slice[SIZE..]; + u64::from(v) + } + n => { + *slice = &slice[1..]; + u64::from(n) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn encoded_value_1_byte() { + // Check lower bound, upper bound (and implicitly endian-ness). + for v in [0x00, 0x01, 0x02, 0xFA, 0xFB, 0xFC] { + let v = v as u32; + assert_eq!(encoded_size(v), 1); + // Should be encoded as the value as a u8. + let want = [v as u8]; + let got = encode(v); + assert_eq!(got.as_slice().len(), 1); // sanity check + assert_eq!(got.as_slice(), want); + } + } + + #[test] + fn decode_value_1_byte() { + // Check lower bound, upper bound. + for v in [0x00, 0x01, 0x02, 0xFA, 0xFB, 0xFC] { + let raw = [v]; + let mut slice = raw.as_slice(); + let got = decode_unchecked(&mut slice); + assert_eq!(got, u64::from(v)); + assert!(slice.is_empty()); + } + } + + macro_rules! check_encode { + ($($test_name:ident, $size:expr, $value:expr, $want:expr);* $(;)?) => { + $( + #[test] + fn $test_name() { + let value = $value as u64; // Because default integer type is i32. + let got = encode(value); + assert_eq!(got.as_slice().len(), $size); // sanity check + assert_eq!(got.as_slice(), &$want); + } + )* + } + } + + check_encode! { + // 3 byte encoding. + encoded_value_3_byte_lower_bound, 3, 0xFD, [0xFD, 0xFD, 0x00]; // 0x00FD + encoded_value_3_byte_endianness, 3, 0xABCD, [0xFD, 0xCD, 0xAB]; + encoded_value_3_byte_upper_bound, 3, 0xFFFF, [0xFD, 0xFF, 0xFF]; + // 5 byte encoding. + encoded_value_5_byte_lower_bound, 5, 0x0001_0000, [0xFE, 0x00, 0x00, 0x01, 0x00]; + encoded_value_5_byte_endianness, 5, 0x0123_4567, [0xFE, 0x67, 0x45, 0x23, 0x01]; + encoded_value_5_byte_upper_bound, 5, 0xFFFF_FFFF, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF]; + // 9 byte encoding. + encoded_value_9_byte_lower_bound, 9, 0x0000_0001_0000_0000, [0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]; + encoded_value_9_byte_endianness, 9, 0x0123_4567_89AB_CDEF, [0xFF, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]; + encoded_value_9_byte_upper_bound, 9, u64::MAX, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; + } + + macro_rules! check_decode { + ($($test_name:ident, $size:expr, $want:expr, $encoded:expr);* $(;)?) => { + $( + #[test] + fn $test_name() { + let mut slice = $encoded.as_slice(); + let got = decode_unchecked(&mut slice); + assert_eq!(got, $want); + assert_eq!(slice.len(), $encoded.len() - $size); + } + )* + } + } + + check_decode! { + // 3 byte encoding. + decode_from_3_byte_slice_lower_bound, 3, 0xFD, [0xFD, 0xFD, 0x00]; + decode_from_3_byte_slice_three_over_lower_bound, 3, 0x0100, [0xFD, 0x00, 0x01]; + decode_from_3_byte_slice_endianness, 3, 0xABCD, [0xFD, 0xCD, 0xAB]; + decode_from_3_byte_slice_upper_bound, 3, 0xFFFF, [0xFD, 0xFF, 0xFF]; + + // 5 byte encoding. + decode_from_5_byte_slice_lower_bound, 5, 0x0001_0000, [0xFE, 0x00, 0x00, 0x01, 0x00]; + decode_from_5_byte_slice_endianness, 5, 0x0123_4567, [0xFE, 0x67, 0x45, 0x23, 0x01]; + decode_from_5_byte_slice_upper_bound, 5, 0xFFFF_FFFF, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF]; + // 9 byte encoding. + decode_from_9_byte_slice_lower_bound, 9, 0x0000_0001_0000_0000, [0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00]; + decode_from_9_byte_slice_endianness, 9, 0x0123_4567_89AB_CDEF, [0xFF, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]; + decode_from_9_byte_slice_upper_bound, 9, u64::MAX, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]; + + // Check slices that are bigger than the actual encoding. + decode_1_byte_from_bigger_slice, 1, 32, [0x20, 0xAB, 0xBC]; + decode_3_byte_from_bigger_slice, 3, 0xFFFF, [0xFD, 0xFF, 0xFF, 0xAB, 0xBC]; + decode_5_byte_from_bigger_slice, 5, 0xFFFF_FFFF, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0xBC]; + decode_9_byte_from_bigger_slice, 9, u64::MAX, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0xBC]; + } + + #[test] + #[should_panic] + fn decode_from_empty_slice_panics() { + let mut slice = [].as_slice(); + let _ = decode_unchecked(&mut slice); + } + + #[test] + #[should_panic] + // Non-minimal is referred to as non-canonical in Core (`bitcoin/src/serialize.h`). + fn decode_non_minimal_panics() { + let mut slice = [0xFE, 0xCD, 0xAB].as_slice(); + let _ = decode_unchecked(&mut slice); + } +} diff --git a/internals/src/const_casts.rs b/internals/src/const_casts.rs new file mode 100644 index 000000000..03ca18da7 --- /dev/null +++ b/internals/src/const_casts.rs @@ -0,0 +1,18 @@ +//! Const-compatible integer casting functions. +//! +//! This module provides explicit, const-compatible functions for integer type conversions +//! that would normally be done using the [`Into`] trait. Since trait methods cannot be used +//! in `const` contexts, these functions serve as alternatives that make conversion intent +//! clear while maintaining compile-time evaluation capabilities. + +/// Converts `u16` to `u64` +pub const fn u16_to_u64(value: u16) -> u64 { value as u64 } + +/// Converts `u32` to `u64` +pub const fn u32_to_u64(value: u32) -> u64 { value as u64 } + +/// Converts `i16` to `i64` +pub const fn i16_to_i64(value: i16) -> i64 { value as i64 } + +/// Converts `u16` to `u32` +pub const fn u16_to_u32(value: u16) -> u32 { value as u32 } diff --git a/internals/src/const_tools.rs b/internals/src/const_tools.rs new file mode 100644 index 000000000..70e2b8852 --- /dev/null +++ b/internals/src/const_tools.rs @@ -0,0 +1,90 @@ +//! Contains tools (workarounds) to make implementing `const fn`s easier. + +/// Copies first `$len` bytes from `$slice` and returns them as an array. +/// +/// Returns `None` if `$len > $slice.len()`. `$len` must be (obviously) statically known. +/// Calling from non-const context doesn't affect performance. +#[macro_export] +macro_rules! copy_byte_array_from_slice { + ($slice:expr, $len:expr) => { + if $len > $slice.len() { + None + } else { + let mut array = [0u8; $len]; + // Note: produces same assemble as copy_from_slice + let mut i = 0; + while i < $len { + array[i] = $slice[i]; + i += 1; + } + Some(array) + } + }; +} +pub use copy_byte_array_from_slice; + +/// Concatenates two byte slices or byte arrays (or combination) to a single array. +/// +/// # Panics +/// +/// This macro panics if `$len` is not equal to the sum of `$a.len()` and `$b.len()`. +#[macro_export] +macro_rules! concat_bytes_to_arr { + ($a:expr, $b:expr, $len:expr) => {{ + // avoid repeated eval + let a = $a; + let b = $b; + + #[allow(unconditional_panic)] + let _ = [(); 1][($len != a.len() + b.len()) as usize]; + + let mut output = [0u8; $len]; + let mut i = 0; + while i < a.len() { + output[i] = a[i]; + i += 1; + } + while i < a.len() + b.len() { + output[i] = b[i - a.len()]; + i += 1; + } + output + }}; +} +pub use concat_bytes_to_arr; + +#[macro_export] +/// Enables const fn in specified Rust version +macro_rules! cond_const { + ($($(#[$attr:meta])* $vis:vis const(in $version:tt) fn $name:ident$(<$($gen:tt)*>)?($($args:tt)*) $(-> $ret:ty)? $body:block)+ ) => { + $( + $crate::rust_version::rust_version! { + if >= $version { + $(#[$attr])* + #[doc = concat!("\nNote: the function is only `const` in Rust ", stringify!($version), ".")] + $vis const fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body + } else { + $(#[$attr])* + #[doc = concat!("\nNote: the function is `const` in Rust ", stringify!($version), ".")] + $vis fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body + } + } + )+ + }; + ($($(#[$attr:meta])* $vis:vis const(in $version:tt) unsafe fn $name:ident$(<$($gen:tt)*>)?($($args:tt)*) $(-> $ret:ty)? $body:block)+ ) => { + $( + $crate::rust_version::rust_version! { + if >= $version { + $(#[$attr])* + #[doc = concat!("\nNote: the function is only `const` in Rust ", stringify!($version), ".")] + $vis const unsafe fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body + } else { + $(#[$attr])* + #[doc = concat!("\nNote: the function is `const` in Rust ", stringify!($version), ".")] + $vis unsafe fn $name$(<$($gen)*>)?($($args)*) $(-> $ret)? $body + } + } + )+ + }; +} +pub use cond_const; diff --git a/internals/src/error/input_string.rs b/internals/src/error/input_string.rs new file mode 100644 index 000000000..d5e71aa39 --- /dev/null +++ b/internals/src/error/input_string.rs @@ -0,0 +1,166 @@ +//! Implements the [`InputString`] type storing the parsed input. + +use core::fmt; + +use storage::Storage; + +/// Conditionally stores the input string in parse errors. +/// +/// This type stores the input string of a parse function depending on whether `alloc` feature is +/// enabled. When it is enabled, the string is stored inside as `String`. When disabled this is a +/// zero-sized type and attempt to store a string does nothing. +/// +/// This provides two methods to format the error strings depending on the context. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct InputString(Storage); + +impl InputString { + /// Displays a message saying `failed to parse as `. + /// + /// This is normally used with the `write_err!` macro. + /// + /// # Examples + /// + /// ``` + /// use core::fmt; + /// use bitcoin_internals::error::InputString; + /// use bitcoin_internals::write_err; + /// + /// /// An example parsing error including the parse error from core. + /// #[derive(Debug, Clone, PartialEq, Eq)] + /// pub struct ParseError { + /// input: InputString, + /// error: core::num::ParseIntError, + /// } + /// + /// impl fmt::Display for ParseError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// // Outputs "failed to parse '' as foo" + /// write_err!(f, "{}", self.input.display_cannot_parse("foo"); self.error) + /// } + /// } + /// ``` + pub fn display_cannot_parse<'a, T>(&'a self, what: &'a T) -> CannotParse<'a, T> + where + T: fmt::Display + ?Sized, + { + CannotParse { input: self, what } + } + + /// Formats a message saying ` is not a known `. + /// + /// This is normally used in leaf parse errors (with no source) when parsing an enum. + /// + /// # Examples + /// + /// ``` + /// use core::fmt; + /// use bitcoin_internals::error::InputString; + /// + /// /// An example parsing error. + /// #[derive(Debug, Clone, PartialEq, Eq)] + /// pub struct ParseError(InputString); + /// + /// impl fmt::Display for ParseError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// // Outputs "'' is not a known foo" + /// self.0.unknown_variant("foo", f) + /// } + /// } + /// ``` + pub fn unknown_variant(&self, what: &T, f: &mut fmt::Formatter) -> fmt::Result + where + T: fmt::Display + ?Sized, + { + storage::unknown_variant(&self.0, what, f) + } +} + +macro_rules! impl_from { + ($($type:ty),+ $(,)?) => { + $( + impl From<$type> for InputString { + fn from(input: $type) -> Self { + #[allow(clippy::useless_conversion)] + InputString(input.into()) + } + } + )+ + } +} + +impl_from!(&str); + +/// Displays message saying `failed to parse as `. +/// +/// This is created by `display_cannot_parse` method and should be used as +/// `write_err!("{}", self.input.display_cannot_parse("what is parsed"); self.source)` in parse +/// error [`Display`](fmt::Display) implementation if the error has source. If the error doesn't +/// have a source just use regular `write!` with same formatting arguments. +pub struct CannotParse<'a, T: fmt::Display + ?Sized> { + input: &'a InputString, + what: &'a T, +} + +impl fmt::Display for CannotParse<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + storage::cannot_parse(&self.input.0, &self.what, f) + } +} + +#[cfg(not(feature = "alloc"))] +mod storage { + use core::fmt; + + #[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] + pub(super) struct Storage; + + impl fmt::Debug for Storage { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("") + } + } + + impl From<&str> for Storage { + fn from(_value: &str) -> Self { Self } + } + + pub(super) fn cannot_parse(_: &Storage, what: &W, f: &mut fmt::Formatter) -> fmt::Result + where + W: fmt::Display + ?Sized, + { + write!(f, "failed to parse {}", what) + } + + pub(super) fn unknown_variant(_: &Storage, what: &W, f: &mut fmt::Formatter) -> fmt::Result + where + W: fmt::Display + ?Sized, + { + write!(f, "unknown {}", what) + } +} + +#[cfg(feature = "alloc")] +mod storage { + use core::fmt; + + use super::InputString; + + pub(super) type Storage = alloc::string::String; + + pub(super) fn cannot_parse(input: &Storage, what: &W, f: &mut fmt::Formatter) -> fmt::Result + where + W: fmt::Display + ?Sized, + { + write!(f, "failed to parse '{}' as {}", input, what) + } + + pub(super) fn unknown_variant(inp: &Storage, what: &W, f: &mut fmt::Formatter) -> fmt::Result + where + W: fmt::Display + ?Sized, + { + write!(f, "'{}' is not a known {}", inp, what) + } + + impl_from!(alloc::string::String, alloc::boxed::Box, alloc::borrow::Cow<'_, str>); +} diff --git a/internals/src/error/mod.rs b/internals/src/error/mod.rs new file mode 100644 index 000000000..9d52822de --- /dev/null +++ b/internals/src/error/mod.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! # Error +//! +//! Error handling macros and helpers. + +pub mod input_string; +mod parse_error; + +pub use input_string::InputString; + +/// Formats error. +/// +/// If `std` feature is OFF appends error source (delimited by `: `). We do this because +/// `e.source()` is only available in std builds, without this macro the error source is lost for +/// no-std builds. +#[macro_export] +macro_rules! write_err { + ($writer:expr, $string:literal $(, $args:expr)*; $source:expr) => { + { + #[cfg(feature = "std")] + { + let _ = &$source; // Prevents clippy warnings. + write!($writer, $string $(, $args)*) + } + #[cfg(not(feature = "std"))] + { + write!($writer, concat!($string, ": {}") $(, $args)*, $source) + } + } + } +} diff --git a/internals/src/error/parse_error.rs b/internals/src/error/parse_error.rs new file mode 100644 index 000000000..b81954a4e --- /dev/null +++ b/internals/src/error/parse_error.rs @@ -0,0 +1,48 @@ +//! Contains helpers for parsing-related errors. + +/// Constructs an error type intended for string parsing errors. +/// +/// The resulting error type has two fields: `input` and `source`. The type of `input` is +/// [`InputString`](super::InputString), the type of `source` is specified as the second argument +/// to the macro. +/// +/// The resulting type is public, conditionally implements [`std::error::Error`] and has a private +/// `new()` method for convenience. +/// +/// # Parameters +/// +/// * `name` - the name of the error type +/// * `source` - the type of the source type +/// * `subject` - the english description of the type being parsed (e.g. "a bitcoin amount") +/// * `derive` - the list of derives to add +#[macro_export] +macro_rules! parse_error_type { + ($vis:vis $name:ident, $source:ty, $subject:expr $(, $derive:path)* $(,)?) => { + #[derive(Debug $(, $derive)*)] + $vis struct $name { + input: $crate::error::InputString, + source: $source, + } + + impl $name { + /// Constructs a new `Self`. + fn new>(input: T, source: $source) -> Self { + $name { + input: input.into(), + source, + } + } + } + + impl core::fmt::Display for $name { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + $crate::error::write_err!(f, "{}", self.input.display_cannot_parse($subject); self.source) + } + } + + #[cfg(feature = "std")] + impl std::error::Error for $name { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.source) } + } + } +} diff --git a/internals/src/lib.rs b/internals/src/lib.rs new file mode 100644 index 000000000..b7cc74fb4 --- /dev/null +++ b/internals/src/lib.rs @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Rust Bitcoin Internal +//! +//! This crate is only meant to be used internally by crates in the +//! [rust-bitcoin](https://github.com/rust-bitcoin) ecosystem. + +#![no_std] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "test-serde")] +pub extern crate serde_json; + +#[cfg(feature = "test-serde")] +pub extern crate bincode; + +// The pub module is a workaround for strange error: +// "macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths" +#[doc(hidden)] +pub mod rust_version { + include!(concat!(env!("OUT_DIR"), "/rust_version.rs")); +} + +#[doc(hidden)] +pub mod _export { + #[cfg(feature = "alloc")] + pub extern crate alloc; +} + +pub mod array; +pub mod array_vec; +pub mod compact_size; +pub mod const_tools; +pub mod error; +pub mod macros; +mod parse; +pub mod script; +pub mod slice; +pub mod wrap_debug; +#[cfg(feature = "serde")] +#[macro_use] +pub mod serde; +pub mod const_casts; + +/// A conversion trait for unsigned integer types smaller than or equal to 64-bits. +/// +/// This trait exists because [`usize`] doesn't implement `Into`. We only support 32 and 64 bit +/// architectures because of consensus code so we can infallibly do the conversion. +pub trait ToU64 { + /// Converts unsigned integer type to a [`u64`]. + fn to_u64(self) -> u64; +} + +macro_rules! impl_to_u64 { + ($($ty:ident),*) => { + $( + impl ToU64 for $ty { fn to_u64(self) -> u64 { self.into() } } + )* + } +} +impl_to_u64!(u8, u16, u32, u64); + +impl ToU64 for usize { + fn to_u64(self) -> u64 { + crate::const_assert!( + core::mem::size_of::() <= 8; + "platforms that have usize larger than 64 bits are not supported" + ); + self as u64 + } +} diff --git a/internals/src/macros.rs b/internals/src/macros.rs new file mode 100644 index 000000000..1119fcde1 --- /dev/null +++ b/internals/src/macros.rs @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Various macros used by the Rust Bitcoin ecosystem. + +/// Asserts a boolean expression at compile time. +#[macro_export] +macro_rules! const_assert { + ($x:expr $(; $message:expr)?) => { + const _: () = { + if !$x { + // We can't use formatting in const, only concatenating literals. + panic!(concat!("assertion ", stringify!($x), " failed" $(, ": ", $message)?)) + } + }; + } +} + +/// Adds an implementation of `pub fn to_hex(&self) -> String`. +/// +/// The added function allocates a `String` then calls through to [`core::fmt::LowerHex`]. +#[macro_export] +macro_rules! impl_to_hex_from_lower_hex { + ($t:ident, $hex_len_fn:expr) => { + impl $t { + /// Gets the hex representation of this type + pub fn to_hex(&self) -> alloc::string::String { + use core::fmt::Write; + + let mut hex_string = alloc::string::String::with_capacity($hex_len_fn(self)); + write!(&mut hex_string, "{:x}", self).expect("writing to string shouldn't fail"); + + hex_string + } + } + }; +} + +/// Constructs a transparent wrapper around an inner type and soundly implements reference casts. +/// +/// This macro takes care of several issues related to newtypes that need to allow casting their +/// inner types to themselves: +/// +/// * It makes sure to put repr(transparent) on the type +/// * It optionally implements conversions from `&`, `&mut`, `Box`, `Rc`, `Arc` +/// * It makes sure to put `#[inline]` on all of these conversions since they are trivial +/// * It makes sure the reference cast is const +/// * It makes sure the `Arc` conversion is conditioned on `target_has_atomic = "ptr"` +/// +/// Usage: just type the struct inside the macro as you would implementing it manually except leave +/// `#[repr(transparent)]` out. Then add an impl block for the just-defined type containing function +/// declarations that take a reference/smart pointer to `_` (use literal underscore; e.g. `&_` for +/// shared references) and return `Self` behind the appropriate "pointer" type. Do not write the +/// body, just semicolon. +/// +/// The `alloc` types MUST NOT have import paths and don't need imports. +#[macro_export] +macro_rules! transparent_newtype { + ( + $(#[$($struct_attr:tt)*])* + $vis:vis struct $newtype:tt$(<$gen:ident $(= $default:ty)?>)?($($fields:tt)+) $(where $($where_ty:ty: $bound:path),* $(,)?)?; + + impl$(<$gen2:tt>)? $newtype2:ident$(<$gen3:tt>)? { + $( + $(#[$($fn_attr:tt)*])* + $fn_vis:vis $(const)? fn $fn:ident($fn_arg_name:ident: $($fn_arg_ty:tt)+) -> $fn_ret_ty:ty; + )* + } + ) => { + $crate::_check_tts_eq!($newtype2, $newtype, "the type name in the impl block doesn't match the struct name"); + $( + // WARNING: renaming has to be disabled for soundness! + // If it weren't it'd be possible to make the type inside struct not match the one passed + // to functions. In principle we could also omit the generics but that'd be confusing for + // readers. + $crate::_check_tts_eq!($gen2, $gen, "the name of the left generic parameter in impl block doesn't match the one on struct"); + $crate::_check_tts_eq!($gen3, $gen, "the name of the right generic parameter in impl block doesn't match the one on struct"); + )? + $(#[$($struct_attr)*])* + #[repr(transparent)] + $vis struct $newtype$(<$gen $(= $default)?>)?($($fields)+) $(where $($where_ty: $bound),*)?; + + impl$(<$gen2>)? $newtype$(<$gen3>)? $(where $($where_ty: $bound),*)? { + $crate::_transparent_ref_conversions! { + $crate::_transparent_newtype_inner_type!($($fields)+); + $( + $(#[$($fn_attr)*])* + $fn_vis fn $fn($fn_arg_name: $($fn_arg_ty)+) -> $fn_ret_ty; + )+ + } + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! _transparent_ref_conversions { + ( + $inner:ty; + $( + $(#[$($fn_attr:tt)*])* + $fn_vis:vis $(const)? fn $fn:ident($fn_arg_name:ident: $($fn_arg_ty:tt)+) -> $fn_ret_ty:ty; + )+ + ) => { + $( + $crate::_transparent_ref_conversion! { + $inner; + $(#[$($fn_attr)*])* + $fn_vis fn $fn($fn_arg_name: $($fn_arg_ty)+) -> $fn_ret_ty; + } + )+ + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! _transparent_ref_conversion { + ( + $inner:ty; + $(#[$($from_ref_attr:tt)*])* + $from_ref_vis:vis fn $from_ref:ident($from_ref_arg_name:ident: &_) -> $fn_ret_ty:ty; + ) => { + #[inline] + $(#[$($from_ref_attr)*])* + $from_ref_vis const fn $from_ref($from_ref_arg_name: &$inner) -> &Self { + // SAFETY: the pointer is created by casting a pointer that is pointing to an object + // with the same layout and validity invariants and the previous pointer was created + // directly from a reference. (Notice repr(transparent).) + // The lifetime of the input reference matches the lifetime of the returned reference. + unsafe { &*($from_ref_arg_name as *const $inner as *const Self) } + } + }; + ( + $inner:ty; + $(#[$($from_mut_attr:tt)*])* + $from_mut_vis:vis fn $from_mut:ident($from_mut_arg_name:ident: &mut _) -> $fn_ret_ty:ty; + ) => { + #[inline] + $(#[$($from_mut_attr)*])* + $from_mut_vis fn $from_mut($from_mut_arg_name: &mut $inner) -> &mut Self { + // SAFETY: the pointer is created by casting a pointer that is pointing to an object + // with the same layout and validity invariants and the previous pointer was created + // directly from a reference. (Notice repr(transparent).) + // The lifetime of the input reference matches the lifetime of the returned reference. + unsafe { &mut *($from_mut_arg_name as *mut $inner as *mut Self) } + } + }; + ( + $inner:ty; + $(#[$($from_box_attr:tt)*])* + $from_box_vis:vis fn $from_box:ident($from_box_arg_name:ident: Box<_>) -> $fn_ret_ty:ty; + ) => { + $crate::_emit_alloc! { + $(#[$($from_box_attr)*])* + #[inline] + $from_box_vis fn $from_box($from_box_arg_name: $crate::_export::alloc::boxed::Box<$inner>) -> $crate::_export::alloc::boxed::Box { + let ptr = $crate::_export::alloc::boxed::Box::into_raw($from_box_arg_name); + // SAFETY: the pointer is created by casting a pointer that is pointing to an object + // with the same layout and validity invariants and the previous pointer was created + // directly from box. (Notice repr(transparent).) + unsafe { $crate::_export::alloc::boxed::Box::from_raw(ptr as *mut Self) } + } + } + }; + + ( + $inner:ty; + $(#[$($from_rc_attr:tt)*])* + $from_rc_vis:vis fn $from_rc:ident($from_rc_arg_name:ident: Rc<_>) -> $fn_ret_ty:ty; + ) => { + $crate::_emit_alloc! { + $(#[$($from_rc_attr)*])* + #[inline] + $from_rc_vis fn $from_rc($from_rc_arg_name: $crate::_export::alloc::rc::Rc<$inner>) -> $crate::_export::alloc::rc::Rc { + let ptr = $crate::_export::alloc::rc::Rc::into_raw($from_rc_arg_name); + // SAFETY: the pointer is created by casting a pointer that is pointing to an object + // with the same layout and validity invariants and the previous pointer was created + // directly from box. (Notice repr(transparent).) + unsafe { $crate::_export::alloc::rc::Rc::from_raw(ptr as *mut Self) } + } + } + }; + + ( + $inner:ty; + $(#[$($from_arc_attr:tt)*])* + $from_arc_vis:vis fn $from_arc:ident($from_arc_arg_name:ident: Arc<_>) -> $fn_ret_ty:ty; + ) => { + $crate::_emit_alloc! { + $(#[$($from_arc_attr)*])* + #[cfg(target_has_atomic = "ptr")] + #[inline] + $from_arc_vis fn $from_arc($from_arc_arg_name: $crate::_export::alloc::sync::Arc<$inner>) -> $crate::_export::alloc::sync::Arc { + let ptr = $crate::_export::alloc::sync::Arc::into_raw($from_arc_arg_name); + // SAFETY: the pointer is created by casting a pointer that is pointing to an object + // with the same layout and validity invariants and the previous pointer was created + // directly from box. (Notice repr(transparent).) + unsafe { $crate::_export::alloc::sync::Arc::from_raw(ptr as *mut Self) } + } + } + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! _check_tts_eq { + ($left:tt, $right:tt, $message:literal) => { + macro_rules! token_eq { + ($right) => {}; + ($any:tt) => { + compile_error!($message) + }; + } + token_eq!($left); + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! _transparent_newtype_inner_type { + ($(#[$($field_attr:tt)*])* $inner:ty) => { + $inner + }; + ($(#[$($phantom_attr:tt)*])* PhantomData<$phantom:ty>, $(#[$($field_attr:tt)*])* $inner:ty) => { + $inner + }; +} + +/// Emits given tokens only if the `alloc` feature **in this crate** is enabled. +/// +/// (The feature is currently enabled.) +#[cfg(feature = "alloc")] +#[doc(hidden)] +#[macro_export] +macro_rules! _emit_alloc { + ($($tokens:tt)*) => { $($tokens)* }; +} + +/// Emits given tokens only if the `alloc` feature **in this crate** is enabled. +/// +/// (The feature is currently disabled.) +#[cfg(not(feature = "alloc"))] +#[doc(hidden)] +#[macro_export] +macro_rules! _emit_alloc { + ($($tokens:tt)*) => {}; +} + +/// Implements standard array methods for a given wrapper type. +#[macro_export] +macro_rules! impl_array_newtype { + ($thing:ident, $ty:ty, $len:literal) => { + impl $thing { + /// Constructs a new `Self` by wrapping `bytes`. + #[inline] + pub fn from_byte_array(bytes: [u8; $len]) -> Self { Self(bytes) } + + /// Returns a reference the underlying byte array. + #[inline] + pub fn as_byte_array(&self) -> &[u8; $len] { &self.0 } + + /// Returns the underlying byte array. + #[inline] + pub fn to_byte_array(self) -> [u8; $len] { + // We rely on `Copy` being implemented for $thing so conversion + // methods use the correct Rust naming conventions. + fn check_copy() {} + check_copy::<$thing>(); + + self.0 + } + + /// Copies the underlying bytes into a new `Vec`. + #[inline] + pub fn to_vec(self) -> alloc::vec::Vec { self.0.to_vec() } + + /// Returns a slice of the underlying bytes. + #[inline] + pub fn as_bytes(&self) -> &[u8] { &self.0 } + + /// Converts the object to a raw pointer. + #[inline] + pub fn as_ptr(&self) -> *const $ty { + let &$thing(ref dat) = self; + dat.as_ptr() + } + + /// Converts the object to a mutable raw pointer. + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut $ty { + let &mut $thing(ref mut dat) = self; + dat.as_mut_ptr() + } + + /// Returns the length of the object as an array. + #[inline] + pub fn len(&self) -> usize { $len } + + /// Returns whether the object, as an array, is empty. Always false. + #[inline] + pub fn is_empty(&self) -> bool { false } + } + + impl<'a> core::convert::From<[$ty; $len]> for $thing { + fn from(data: [$ty; $len]) -> Self { $thing(data) } + } + + impl<'a> core::convert::From<&'a [$ty; $len]> for $thing { + fn from(data: &'a [$ty; $len]) -> Self { $thing(*data) } + } + + impl<'a> core::convert::TryFrom<&'a [$ty]> for $thing { + type Error = core::array::TryFromSliceError; + + fn try_from(data: &'a [$ty]) -> core::result::Result { + use core::convert::TryInto; + + Ok($thing(data.try_into()?)) + } + } + + impl AsRef<[$ty; $len]> for $thing { + fn as_ref(&self) -> &[$ty; $len] { &self.0 } + } + + impl AsMut<[$ty; $len]> for $thing { + fn as_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 } + } + + impl AsRef<[$ty]> for $thing { + fn as_ref(&self) -> &[$ty] { &self.0 } + } + + impl AsMut<[$ty]> for $thing { + fn as_mut(&mut self) -> &mut [$ty] { &mut self.0 } + } + + impl core::borrow::Borrow<[$ty; $len]> for $thing { + fn borrow(&self) -> &[$ty; $len] { &self.0 } + } + + impl core::borrow::BorrowMut<[$ty; $len]> for $thing { + fn borrow_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 } + } + + // The following two are valid because `[T; N]: Borrow<[T]>` + impl core::borrow::Borrow<[$ty]> for $thing { + fn borrow(&self) -> &[$ty] { &self.0 } + } + + impl core::borrow::BorrowMut<[$ty]> for $thing { + fn borrow_mut(&mut self) -> &mut [$ty] { &mut self.0 } + } + + impl core::ops::Index for $thing + where + [$ty]: core::ops::Index, + { + type Output = <[$ty] as core::ops::Index>::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { &self.0[index] } + } + }; +} diff --git a/internals/src/parse.rs b/internals/src/parse.rs new file mode 100644 index 000000000..363006e9f --- /dev/null +++ b/internals/src/parse.rs @@ -0,0 +1,107 @@ +//! Support for parsing strings. + +// Impls a single TryFrom conversion +#[doc(hidden)] +#[macro_export] +macro_rules! impl_try_from_stringly { + ($from:ty, $to:ty, $error:ty, $func:expr) => { + $(#[$attr])? + impl core::convert::TryFrom<$from> for $to { + type Error = $error; + + fn try_from(s: $from) -> core::result::Result { + $func(AsRef::::as_ref(s)).map_err(|source| <$error>::new(s, source)) + } + } + + } +} + +/// Implements conversions from various string types. +/// +/// This macro implements `FromStr` as well as `TryFrom<{stringly}` where `{stringly}` is one of +/// these types: +/// +/// * `&str` +/// * `String` +/// * `Box` +/// * `Cow<'_, str>` +/// +/// The last three are only available with `alloc` feature turned on. +#[macro_export] +macro_rules! impl_parse { + ($type:ty, $descr:expr, $func:expr, $vis:vis $error:ident, $error_source:ty $(, $error_derive:path)*) => { + $crate::parse_error_type!($vis $error, $error_source, $descr $(, $error_derive)*); + + impl core::str::FromStr for $type { + type Err = $error; + + fn from_str(s: &str) -> core::result::Result { + $func(s).map_err(|source| <$error>::new(s, source)) + } + } + + impl_try_from_stringly!(&str); + + #[cfg(feature = "alloc")] + impl_try_from_stringly!(alloc::string::String, $type, $error, $func); + #[cfg(feature = "alloc")] + impl_try_from_stringly!(alloc::borrow::Cow<'_, str>, $type, $error, $func); + #[cfg(feature = "alloc")] + impl_try_from_stringly!(alloc::boxed::Box, $type, $error, $func); + } +} + +/// Implements conversions from various string types as well as `serde` (de)serialization. +/// +/// This calls `impl_parse` macro and implements serde deserialization by expecting and parsing a +/// string and serialization by outputting a string. +#[macro_export] +macro_rules! impl_parse_and_serde { + ($type:ty, $descr:expr, $func:expr, $error:ident, $error_source:ty $(, $error_derive:path)*) => { + impl_parse!($type, $descr, $func, $error, $error_source $(, $error_derive)*); + + // We don't use `serde_string_impl` because we want to avoid allocating input. + #[cfg(feature = "serde")] + impl<'de> $crate::serde::Deserialize<'de> for $type { + fn deserialize(deserializer: D) -> core::result::Result<$name, D::Error> + where + D: $crate::serde::de::Deserializer<'de>, + { + use core::fmt::{self, Formatter}; + use core::str::FromStr; + + struct Visitor; + impl<'de> $crate::serde::de::Visitor<'de> for Visitor { + type Value = $name; + + fn expecting(&self, f: &mut Formatter) -> core::fmt::Result { + f.write_str($descr) + } + + fn visit_str(self, s: &str) -> core::result::Result + where + E: $crate::serde::de::Error, + { + s.parse().map_err(|error| { + $crate::serde::IntoDeError::try_into_de_error(error) + .unwrap_or_else(|_| E::invalid_value(Unexpected::Str(s), &self)) + }) + } + } + + deserializer.deserialize_str(Visitor) + } + } + + #[cfg(feature = "serde")] + impl $crate::serde::Serialize for $name { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: $crate::serde::Serializer, + { + serializer.collect_str(&self) + } + } + } +} diff --git a/internals/src/script.rs b/internals/src/script.rs new file mode 100644 index 000000000..89e2a326e --- /dev/null +++ b/internals/src/script.rs @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Internal script related helper functions and types. + +/// Reads a `usize` from an iterator. +/// +/// A script push data instruction includes the length of the data being pushed, this function reads +/// that length from an iterator (encoded in either 1, 2, or 4 bytes). +// We internally use implementation based on iterator so that it automatically advances as needed. +pub fn read_push_data_len( + data: &mut core::slice::Iter<'_, u8>, + size: PushDataLenLen, +) -> Result { + // The `size` enum enforces that the maximum shift will be 32 and + // that we can only ever read up to 4 bytes. + let size = size as usize; + + if data.len() < size { + return Err(EarlyEndOfScriptError); + }; + + let mut ret = 0; + for (i, item) in data.take(size).enumerate() { + ret |= usize::from(*item) << (i * 8); + } + Ok(ret) +} + +/// The number of bytes used to encode an unsigned integer as the length of a push data instruction. +/// +/// This makes it easier to prove correctness of `next_push_data_len` and `read_push_data_len`. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub enum PushDataLenLen { + /// Unsigned integer comprising of a single byte. + One = 1, + /// Unsigned integer comprising of two bytes. + Two = 2, + /// Unsigned integer comprising of four bytes. + Four = 4, +} + +/// Indicates that we tried to read more bytes from the script than available. +#[derive(Debug)] +pub struct EarlyEndOfScriptError; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn reads_4_bytes() { + let bytes = [0x01, 0x23, 0x45, 0x67]; + let want = u32::from_le_bytes([0x01, 0x23, 0x45, 0x67]); + let got = read_push_data_len(&mut bytes.iter(), PushDataLenLen::Four).unwrap(); + assert_eq!(got, want as usize) + } + + #[test] + fn reads_2_bytes() { + let bytes = [0x01, 0x23]; + let want = u16::from_le_bytes([0x01, 0x23]); + let got = read_push_data_len(&mut bytes.iter(), PushDataLenLen::Two).unwrap(); + assert_eq!(got, want as usize) + } + + #[test] + fn reads_1_byte() { + let bytes = [0x01]; + let want = 0x01; + let got = read_push_data_len(&mut bytes.iter(), PushDataLenLen::One).unwrap(); + assert_eq!(got, want as usize) + } +} diff --git a/internals/src/serde.rs b/internals/src/serde.rs new file mode 100644 index 000000000..7c25cfae4 --- /dev/null +++ b/internals/src/serde.rs @@ -0,0 +1,327 @@ +//! Contains extensions of `serde` and internal reexports. + +#[doc(hidden)] +pub use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer}; + +/// Converts given error type to a type implementing [`de::Error`]. +/// +/// This is used in [`Deserialize`] implementations to convert specialized errors into serde +/// errors. +pub trait IntoDeError: Sized { + /// Converts to deserializer error possibly outputting vague message. + /// + /// This method is allowed to return a vague error message if the error type doesn't contain + /// enough information to explain the error precisely. + fn into_de_error(self, expected: Option<&dyn de::Expected>) -> E; + + /// Converts to deserializer error without outputting vague message. + /// + /// If the error type doesn't contain enough information to explain the error precisely this + /// should return `Err(self)` allowing the caller to use its information instead. + fn try_into_de_error(self, expected: Option<&dyn de::Expected>) -> Result + where + E: de::Error, + { + Ok(self.into_de_error(expected)) + } +} + +mod impls { + use super::*; + + impl IntoDeError for core::convert::Infallible { + fn into_de_error(self, _expected: Option<&dyn de::Expected>) -> E { + match self {} + } + } + + impl IntoDeError for core::num::ParseIntError { + fn into_de_error(self, expected: Option<&dyn de::Expected>) -> E { + self.try_into_de_error(expected).unwrap_or_else(|_| { + let expected = expected.unwrap_or(&"an integer"); + + E::custom(format_args!("invalid string, expected {}", expected)) + }) + } + + fn try_into_de_error(self, expected: Option<&dyn de::Expected>) -> Result + where + E: de::Error, + { + use core::num::IntErrorKind::Empty; + + let expected = expected.unwrap_or(&"an integer"); + + match self.kind() { + Empty => Ok(E::invalid_value(de::Unexpected::Str(""), expected)), + _ => Err(self), + } + } + } +} + +/// Implements `serde::Serialize` by way of `Display`. +/// +/// `$name` is required to implement `core::fmt::Display`. +#[macro_export] +macro_rules! serde_string_serialize_impl { + ($name:ty, $expecting:literal) => { + impl $crate::serde::Serialize for $name { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: $crate::serde::Serializer, + { + serializer.collect_str(&self) + } + } + }; +} + +/// Implements `serde::Deserialize` by way of `FromStr`. +/// +/// `$name` is required to implement `core::str::FromStr`. +#[macro_export] +macro_rules! serde_string_deserialize_impl { + ($name:ty, $expecting:literal) => { + impl<'de> $crate::serde::Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> core::result::Result<$name, D::Error> + where + D: $crate::serde::de::Deserializer<'de>, + { + use core::fmt::Formatter; + + struct Visitor; + impl<'de> $crate::serde::de::Visitor<'de> for Visitor { + type Value = $name; + + fn expecting(&self, f: &mut Formatter) -> core::fmt::Result { + f.write_str($expecting) + } + + fn visit_str(self, v: &str) -> core::result::Result + where + E: $crate::serde::de::Error, + { + v.parse::<$name>().map_err(E::custom) + } + } + + deserializer.deserialize_str(Visitor) + } + } + }; +} + +/// Implements `serde::Serialize` and `Deserialize` by way of `Display` and `FromStr` respectively. +/// +/// `$name` is required to implement `core::fmt::Display` and `core::str::FromStr`. +#[macro_export] +macro_rules! serde_string_impl { + ($name:ty, $expecting:literal) => { + $crate::serde_string_deserialize_impl!($name, $expecting); + $crate::serde_string_serialize_impl!($name, $expecting); + }; +} + +/// A combination macro where the human-readable serialization is done like +/// serde_string_impl and the non-human-readable impl is done as a struct. +#[macro_export] +macro_rules! serde_struct_human_string_impl { + ($name:ident, $expecting:literal, $($fe:ident),*) => ( + impl<'de> $crate::serde::Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> core::result::Result<$name, D::Error> + where + D: $crate::serde::de::Deserializer<'de>, + { + if deserializer.is_human_readable() { + use core::fmt::Formatter; + + struct Visitor; + impl<'de> $crate::serde::de::Visitor<'de> for Visitor { + type Value = $name; + + fn expecting(&self, f: &mut Formatter) -> core::fmt::Result { + f.write_str($expecting) + } + + fn visit_str(self, v: &str) -> core::result::Result + where + E: $crate::serde::de::Error, + { + v.parse::<$name>().map_err(E::custom) + } + + } + + deserializer.deserialize_str(Visitor) + } else { + use core::fmt::Formatter; + use $crate::serde::de::IgnoredAny; + + #[allow(non_camel_case_types)] + enum Enum { Unknown__Field, $($fe),* } + + struct EnumVisitor; + impl<'de> $crate::serde::de::Visitor<'de> for EnumVisitor { + type Value = Enum; + + fn expecting(&self, f: &mut Formatter) -> core::fmt::Result { + f.write_str("a field name") + } + + fn visit_str(self, v: &str) -> core::result::Result + where + E: $crate::serde::de::Error, + { + match v { + $( + stringify!($fe) => Ok(Enum::$fe) + ),*, + _ => Ok(Enum::Unknown__Field) + } + } + } + + impl<'de> $crate::serde::Deserialize<'de> for Enum { + fn deserialize(deserializer: D) -> core::result::Result + where + D: $crate::serde::de::Deserializer<'de>, + { + deserializer.deserialize_str(EnumVisitor) + } + } + + struct Visitor; + + impl<'de> $crate::serde::de::Visitor<'de> for Visitor { + type Value = $name; + + fn expecting(&self, f: &mut Formatter) -> core::fmt::Result { + f.write_str("a struct") + } + + fn visit_seq(self, mut seq: V) -> core::result::Result + where + V: $crate::serde::de::SeqAccess<'de>, + { + use $crate::serde::de::Error; + + let length = 0; + $( + let $fe = seq.next_element()?.ok_or_else(|| { + Error::invalid_length(length, &self) + })?; + #[allow(unused_variables)] + let length = length + 1; + )* + + let ret = $name { + $($fe),* + }; + + Ok(ret) + } + + fn visit_map(self, mut map: A) -> core::result::Result + where + A: $crate::serde::de::MapAccess<'de>, + { + use $crate::serde::de::Error; + + $(let mut $fe = None;)* + + loop { + match map.next_key::()? { + Some(Enum::Unknown__Field) => { + map.next_value::()?; + } + $( + Some(Enum::$fe) => { + $fe = Some(map.next_value()?); + } + )* + None => { break; } + } + } + + $( + let $fe = match $fe { + Some(x) => x, + None => return Err(A::Error::missing_field(stringify!($fe))), + }; + )* + + let ret = $name { + $($fe),* + }; + + Ok(ret) + } + } + // end type defs + + static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*]; + + deserializer.deserialize_struct(stringify!($name), FIELDS, Visitor) + } + } + } + + impl $crate::serde::Serialize for $name { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: $crate::serde::Serializer, + { + if serializer.is_human_readable() { + serializer.collect_str(&self) + } else { + use $crate::serde::ser::SerializeStruct; + + // Only used to get the struct length. + static FIELDS: &'static [&'static str] = &[$(stringify!($fe)),*]; + + let mut st = serializer.serialize_struct(stringify!($name), FIELDS.len())?; + + $( + st.serialize_field(stringify!($fe), &self.$fe)?; + )* + + st.end() + } + } + } + ) +} + +/// Does round trip test to/from serde value. +#[cfg(feature = "test-serde")] +#[macro_export] +macro_rules! serde_round_trip ( + ($var:expr) => ({ + use serde_json; + + let encoded = $crate::serde_json::to_value(&$var).expect("serde_json failed to encode"); + let decoded = $crate::serde_json::from_value(encoded).expect("serde_json failed to decode"); + assert_eq!($var, decoded); + + let encoded = $crate::bincode::serialize(&$var).expect("bincode failed to encode"); + let decoded = $crate::bincode::deserialize(&encoded).expect("bincode failed to decode"); + assert_eq!($var, decoded); + }) +); + +#[cfg(feature = "hex")] +/// Serializes a byte slice using the `hex` crate. +pub struct SerializeBytesAsHex<'a>(pub &'a [u8]); + +#[cfg(feature = "hex")] +impl serde::Serialize for SerializeBytesAsHex<'_> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use hex::DisplayHex; + + serializer.collect_str(&format_args!("{:x}", self.0.as_hex())) + } +} diff --git a/internals/src/slice.rs b/internals/src/slice.rs new file mode 100644 index 000000000..6c91a4d2b --- /dev/null +++ b/internals/src/slice.rs @@ -0,0 +1,186 @@ +//! Contains extensions related to slices. + +/// Extension trait for slice. +pub trait SliceExt { + /// The item type the slice is storing. + type Item; + + /// Splits up the slice into a slice of arrays and a remainder. + /// + /// Note that `N` must not be zero: + /// + /// ```ignore + /// # use bitcoin_internals::slice::SliceExt; + /// let slice = [1, 2, 3]; + /// let _fail = slice.bitcoin_as_chunks::<0>(); // Fails to compile + /// ``` + fn bitcoin_as_chunks(&self) -> (&[[Self::Item; N]], &[Self::Item]); + + /// Splits up the slice into a slice of arrays and a remainder. + /// + /// Note that `N` must not be zero: + /// + /// ```ignore + /// # use bitcoin_internals::slice::SliceExt; + /// let mut slice = [1, 2, 3]; + /// let _fail = slice.bitcoin_as_chunks_mut::<0>(); // Fails to compile + /// ``` + fn bitcoin_as_chunks_mut( + &mut self, + ) -> (&mut [[Self::Item; N]], &mut [Self::Item]); + + /// Tries to access a sub-array of length `ARRAY_LEN` at the specified `offset`. + /// + /// Returns `None` in case of out-of-bounds access. + fn get_array(&self, offset: usize) -> Option<&[Self::Item; ARRAY_LEN]>; + + /// Splits the slice into an array and remainder if it's long enough. + /// + /// Returns `None` if the slice is shorter than `ARRAY_LEN` + #[allow(clippy::type_complexity)] // it's not really complex and redefining would make it + // harder to understand + fn split_first_chunk( + &self, + ) -> Option<(&[Self::Item; ARRAY_LEN], &[Self::Item])>; + + /// Splits the slice into a remainder and an array if it's long enough. + /// + /// Returns `None` if the slice is shorter than `ARRAY_LEN` + #[allow(clippy::type_complexity)] // it's not really complex and redefining would make it + // harder to understand + fn split_last_chunk( + &self, + ) -> Option<(&[Self::Item], &[Self::Item; ARRAY_LEN])>; +} + +impl SliceExt for [T] { + type Item = T; + + fn bitcoin_as_chunks(&self) -> (&[[Self::Item; N]], &[Self::Item]) { + #[allow(clippy::let_unit_value)] + let _ = Hack::::IS_NONZERO; + + let chunks_count = self.len() / N; + let total_left_len = chunks_count * N; + let (left, right) = self.split_at(total_left_len); + // SAFETY: we've obtained the pointer from a slice that's still live + // we're merely casting, so no aliasing issues here + // arrays of T have same alignment as T + // the resulting slice points within the obtained slice as was computed above + let left = unsafe { + core::slice::from_raw_parts(left.as_ptr().cast::<[Self::Item; N]>(), chunks_count) + }; + (left, right) + } + + fn bitcoin_as_chunks_mut( + &mut self, + ) -> (&mut [[Self::Item; N]], &mut [Self::Item]) { + #[allow(clippy::let_unit_value)] + let _ = Hack::::IS_NONZERO; + + let chunks_count = self.len() / N; + let total_left_len = chunks_count * N; + let (left, right) = self.split_at_mut(total_left_len); + // SAFETY: we've obtained the pointer from a slice that's still live + // we're merely casting, so no aliasing issues here + // arrays of T have same alignment as T + // the resulting slice points within the obtained slice as was computed above + let left = unsafe { + core::slice::from_raw_parts_mut( + left.as_mut_ptr().cast::<[Self::Item; N]>(), + chunks_count, + ) + }; + (left, right) + } + + fn get_array(&self, offset: usize) -> Option<&[Self::Item; ARRAY_LEN]> { + self.get(offset..(offset + ARRAY_LEN)).map(|slice| { + slice + .try_into() + .expect("the arguments to `get` evaluate to the same length the return type uses") + }) + } + + fn split_first_chunk( + &self, + ) -> Option<(&[Self::Item; ARRAY_LEN], &[Self::Item])> { + if self.len() < ARRAY_LEN { + return None; + } + let (first, remainder) = self.split_at(ARRAY_LEN); + Some((first.try_into().expect("we're passing `ARRAY_LEN` to `split_at` above"), remainder)) + } + + fn split_last_chunk( + &self, + ) -> Option<(&[Self::Item], &[Self::Item; ARRAY_LEN])> { + if self.len() < ARRAY_LEN { + return None; + } + let (remainder, last) = self.split_at(self.len() - ARRAY_LEN); + Some(( + remainder, + last.try_into().expect("we're passing `self.len() - ARRAY_LEN` to `split_at` above"), + )) + } +} + +struct Hack; + +impl Hack { + const IS_NONZERO: () = { + assert!(N != 0); + }; +} + +#[cfg(test)] +mod tests { + use super::SliceExt; + + // some comparisons require type annotations + const EMPTY: &[i32] = &[]; + + #[test] + fn one_to_one() { + let slice = [1]; + let (left, right) = slice.bitcoin_as_chunks::<1>(); + assert_eq!(left, &[[1]]); + assert_eq!(right, EMPTY); + } + + #[test] + fn one_to_two() { + const EMPTY_LEFT: &[[i32; 2]] = &[]; + + let slice = [1i32]; + let (left, right) = slice.bitcoin_as_chunks::<2>(); + assert_eq!(left, EMPTY_LEFT); + assert_eq!(right, &[1]); + } + + #[test] + fn two_to_one() { + let slice = [1, 2]; + let (left, right) = slice.bitcoin_as_chunks::<1>(); + assert_eq!(left, &[[1], [2]]); + assert_eq!(right, EMPTY); + } + + #[test] + fn two_to_two() { + let slice = [1, 2]; + let (left, right) = slice.bitcoin_as_chunks::<2>(); + assert_eq!(left, &[[1, 2]]); + assert_eq!(right, EMPTY); + } + + #[test] + fn three_to_two() { + let slice = [1, 2, 3]; + let (left, right) = slice.bitcoin_as_chunks::<2>(); + assert_eq!(left, &[[1, 2]]); + assert_eq!(right, &[3]); + } +} diff --git a/internals/src/wrap_debug.rs b/internals/src/wrap_debug.rs new file mode 100644 index 000000000..9a3f63d9b --- /dev/null +++ b/internals/src/wrap_debug.rs @@ -0,0 +1,9 @@ +//! Contains a wrapper for a function that implements `Debug`. +use core::fmt; + +/// A wrapper for a function that implements `Debug`. +pub struct WrapDebug fmt::Result>(pub F); + +impl fmt::Result> fmt::Debug for WrapDebug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (self.0)(f) } +} diff --git a/io/CHANGELOG.md b/io/CHANGELOG.md new file mode 100644 index 000000000..1cb9e4b40 --- /dev/null +++ b/io/CHANGELOG.md @@ -0,0 +1,48 @@ +# 0.3.0 - 2025-12-01 + +* Bump MSRV to Rust `1.74` [#4926](https://github.com/rust-bitcoin/rust-bitcoin/pull/) +* Make traits dyn compatible [#5249](https://github.com/rust-bitcoin/rust-bitcoin/pull/5249) +* Invert dependency between `io` and `hashes` [#3961](https://github.com/rust-bitcoin/rust-bitcoin/pull/3961) +* Introduce `encode_to_writer` for `Write` trait [#5214](https://github.com/rust-bitcoin/rust-bitcoin/pull/5214) +* Add consensus decoding functions [#5212](https://github.com/rust-bitcoin/rust-bitcoin/pull/5212) +* Remove assertion in `Cursor` when reading past end [#5062](https://github.com/rust-bitcoin/rust-bitcoin/pull/5062) +* Enable features in internals crate [#4890](https://github.com/rust-bitcoin/rust-bitcoin/pull/4890) +* Make `io::Error` `Sync` [#3920](https://github.com/rust-bitcoin/rust-bitcoin/pull/3920) +* Use `get_ref` / `get_mut` API [#3855](https://github.com/rust-bitcoin/rust-bitcoin/pull/3855) + +# 0.2.0 - 2024-09-18 + +* Add blanket impl of io traits for `&mut T` [#3188](https://github.com/rust-bitcoin/rust-bitcoin/pull/3188) +* Add `std` bridge [#3176](https://github.com/rust-bitcoin/rust-bitcoin/pull/3176) +* Bump MSRV to Rust `v1.63.0` [#3100](https://github.com/rust-bitcoin/rust-bitcoin/pull/3100) +* Remove blanket trait impls [#2453](https://github.com/rust-bitcoin/rust-bitcoin/pull/2453) + +# 0.1.3 - 2024-11-02 + +* Backport IO improvements [#3181](https://github.com/rust-bitcoin/rust-bitcoin/pull/3181) + (Original PR: [#3176](https://github.com/rust-bitcoin/rust-bitcoin/pull/3176)) + +# 0.1.2 - 2024-03-14 + +* Implement `From` for Errors [#2516](https://github.com/rust-bitcoin/rust-bitcoin/pull/2516) +* Fix new CI build warnings [#2488](https://github.com/rust-bitcoin/rust-bitcoin/pull/2488) + +# 0.1.1 - Initial Release - 2024-02-18 + +Create the `io` crate, add basic I/O traits, types, and implementations. + +Traits: + +- `Read` +- `BufRead` +- `Write` + +Types: + +- `Take` +- `Cursor` +- `Sink` + +# 0.1.0 - Placeholder release + +Empty crate to reserve the name on crates.io \ No newline at end of file diff --git a/io/Cargo.toml b/io/Cargo.toml new file mode 100644 index 000000000..2649a69d4 --- /dev/null +++ b/io/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "bitcoin-io" +version = "0.3.0" +authors = ["Matt Corallo "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +documentation = "https://docs.rs/bitcoin-io/" +description = "Simple I/O traits for no-std (and std) environments" +categories = ["no-std"] +keywords = [ "io", "no-std" ] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["alloc", "encoding/std", "hashes?/std", "internals/std"] +alloc = ["encoding/alloc", "hashes?/alloc", "internals/alloc"] + +[dependencies] +internals = { package = "bitcoin-internals", path = "../internals", version = "0.4.1" } +encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "=1.0.0-rc.2", default-features = false } + +hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.18.0", default-features = false, optional = true } + +[dev-dependencies] +hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.18.0", default-features = false, features = ["hex"] } + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.rust] +unexpected_cfgs = { level = "deny" } + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/io/README.md b/io/README.md new file mode 100644 index 000000000..3d5508de3 --- /dev/null +++ b/io/README.md @@ -0,0 +1,9 @@ +# Rust-Bitcoin I/O Library + +The `std::io` module is not exposed in `no-std` Rust so building `no-std` applications which require +reading and writing objects via standard traits is not generally possible. Thus, this library exists +to export a minimal version of `std::io`'s traits which we use in `rust-bitcoin` so that we can +support `no-std` applications. + +These traits are not one-for-one drop-ins, but are as close as possible while still implementing +`std::io`'s traits without unnecessary complexity. diff --git a/io/contrib/extra_lints.sh b/io/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/io/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/io/contrib/test_vars.sh b/io/contrib/test_vars.sh new file mode 100644 index 000000000..279c2507c --- /dev/null +++ b/io/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="hashes" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc hashes" + +# Run these examples. +EXAMPLES="" diff --git a/io/src/bridge.rs b/io/src/bridge.rs new file mode 100644 index 000000000..371dde8b1 --- /dev/null +++ b/io/src/bridge.rs @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: CC0-1.0 + +use internals::rust_version; + +internals::transparent_newtype! { + /// A bridging wrapper providing the I/O traits for types that already implement `std` I/O traits. + #[derive(Debug)] + pub struct FromStd(T); + + impl FromStd { + /// Wraps a mutable reference to I/O type. + pub fn new_mut(inner: &mut _) -> &mut Self; + + /// Wraps a boxed I/O type. + pub fn new_boxed(inner: Box<_>) -> Box; + } +} + +impl FromStd { + /// Wraps an I/O type. + #[inline] + pub const fn new(inner: T) -> Self { Self(inner) } + + /// Returns the wrapped value. + #[inline] + pub fn into_inner(self) -> T { self.0 } + + /// Returns a reference to the wrapped value. + #[inline] + pub fn get_ref(&self) -> &T { &self.0 } + + /// Returns a mutable reference to the wrapped value. + #[inline] + pub fn get_mut(&mut self) -> &mut T { &mut self.0 } + + /// Returns a reference to the wrapped value. + #[inline] + #[deprecated(since = "0.3.0", note = "use `get_ref()` instead")] + pub fn inner(&self) -> &T { &self.0 } + + /// Returns a mutable reference to the wrapped value. + #[inline] + #[deprecated(since = "0.3.0", note = "use `get_mut()` instead")] + pub fn inner_mut(&mut self) -> &mut T { &mut self.0 } +} + +impl super::Read for FromStd { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> super::Result { + self.0.read(buf).map_err(Into::into) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> { + self.0.read_exact(buf).map_err(Into::into) + } +} + +impl super::BufRead for FromStd { + #[inline] + fn fill_buf(&mut self) -> super::Result<&[u8]> { self.0.fill_buf().map_err(Into::into) } + + #[inline] + fn consume(&mut self, amount: usize) { self.0.consume(amount) } +} + +impl super::Write for FromStd { + #[inline] + fn write(&mut self, buf: &[u8]) -> super::Result { + self.0.write(buf).map_err(Into::into) + } + + #[inline] + fn flush(&mut self) -> super::Result<()> { self.0.flush().map_err(Into::into) } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> super::Result<()> { + self.0.write_all(buf).map_err(Into::into) + } +} + +// We also impl std traits so that mixing the calls is not annoying. + +impl std::io::Read for FromStd { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.0.read(buf) } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { self.0.read_exact(buf) } +} + +impl std::io::BufRead for FromStd { + #[inline] + fn fill_buf(&mut self) -> std::io::Result<&[u8]> { self.0.fill_buf() } + + #[inline] + fn consume(&mut self, amount: usize) { self.0.consume(amount) } +} + +impl std::io::Write for FromStd { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { self.0.write(buf) } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { self.0.flush() } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { self.0.write_all(buf) } +} + +internals::transparent_newtype! { + /// A bridging wrapper providing the std traits for types that already implement our traits. + #[derive(Debug)] + pub struct ToStd(T); + + impl ToStd { + /// Wraps a mutable reference to I/O type. + pub fn new_mut(inner: &mut _) -> &mut Self; + + /// Wraps a boxed I/O type. + pub fn new_boxed(inner: Box<_>) -> Box; + } +} + +impl ToStd { + /// Wraps an I/O type. + #[inline] + pub const fn new(inner: T) -> Self { Self(inner) } + + /// Returns the wrapped value. + #[inline] + pub fn into_inner(self) -> T { self.0 } + + /// Returns a reference to the wrapped value. + #[inline] + pub fn inner(&self) -> &T { &self.0 } + + /// Returns a mutable reference to the wrapped value. + #[inline] + pub fn inner_mut(&mut self) -> &mut T { &mut self.0 } +} + +impl std::io::Read for ToStd { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.0.read(buf).map_err(Into::into) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { + self.0.read_exact(buf).map_err(Into::into) + } +} + +impl std::io::BufRead for ToStd { + #[inline] + fn fill_buf(&mut self) -> std::io::Result<&[u8]> { self.0.fill_buf().map_err(Into::into) } + + #[inline] + fn consume(&mut self, amount: usize) { self.0.consume(amount) } +} + +impl std::io::Write for ToStd { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.0.write(buf).map_err(Into::into) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { self.0.flush().map_err(Into::into) } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { + self.0.write_all(buf).map_err(Into::into) + } +} + +// We also impl our traits so that mixing the calls is not annoying. + +impl super::Read for ToStd { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> super::Result { self.0.read(buf) } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> { self.0.read_exact(buf) } +} + +impl super::BufRead for ToStd { + #[inline] + fn fill_buf(&mut self) -> super::Result<&[u8]> { self.0.fill_buf() } + + #[inline] + fn consume(&mut self, amount: usize) { self.0.consume(amount) } +} + +impl super::Write for ToStd { + #[inline] + fn write(&mut self, buf: &[u8]) -> super::Result { self.0.write(buf) } + + #[inline] + fn flush(&mut self) -> super::Result<()> { self.0.flush() } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> super::Result<()> { self.0.write_all(buf) } +} + +macro_rules! impl_our { + (impl$(<$($gen:ident $(: $gent:path)?),*>)? Read for $std_type:ty $(where $($where:tt)*)?) => { + impl$(<$($gen$(: $gent)?),*>)? super::Read for $std_type $(where $($where)*)? { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> super::Result { + std::io::Read::read(self, buf).map_err(Into::into) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> super::Result<()> { + std::io::Read::read_exact(self, buf).map_err(Into::into) + } + } + }; + + (impl$(<$($gen:ident $(: $gent:path)?),*>)? BufRead for $std_type:ty $(where $($where:tt)*)?) => { + impl$(<$($gen$(: $gent)?),*>)? super::BufRead for $std_type $(where $($where)*)? { + #[inline] + fn fill_buf(&mut self) -> super::Result<&[u8]> { + std::io::BufRead::fill_buf(self).map_err(Into::into) + } + + #[inline] + fn consume(&mut self, amount: usize) { + std::io::BufRead::consume(self, amount) + } + } + }; + + (impl$(<$($gen:ident $(: $gent:path)?),*>)? Write for $std_type:ty $(where $($where:tt)*)?) => { + impl$(<$($gen$(: $gent)?),*>)? super::Write for $std_type $(where $($where)*)? { + #[inline] + fn write(&mut self, buf: &[u8]) -> super::Result { + std::io::Write::write(self, buf).map_err(Into::into) + } + + #[inline] + fn flush(&mut self) -> super::Result<()> { + std::io::Write::flush(self).map_err(Into::into) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> super::Result<()> { + std::io::Write::write_all(self, buf).map_err(Into::into) + } + } + }; +} + +impl_our! { + impl Read for std::io::BufReader where R: ?Sized +} + +impl_our! { + impl BufRead for std::io::BufReader where R: ?Sized +} + +impl_our! { + impl Write for std::io::BufWriter where W: ?Sized +} + +impl_our! { + impl Write for std::io::LineWriter where W: ?Sized +} + +impl std::io::Write for super::Sink { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { Ok(buf.len()) } + + #[inline] + fn write_all(&mut self, _: &[u8]) -> std::io::Result<()> { Ok(()) } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { Ok(()) } +} + +impl_our! { + impl Read for std::io::Take +} + +impl_our! { + impl BufRead for std::io::Take +} + +impl_our! { + impl Read for std::io::Chain +} + +impl_our! { + impl BufRead for std::io::Chain +} + +impl_our! { + impl> Read for std::io::Cursor +} + +impl_our! { + impl> BufRead for std::io::Cursor +} + +impl_our! { + impl Write for std::io::Cursor> +} + +impl_our! { + impl Write for std::io::Cursor<&'_ mut std::vec::Vec> +} + +impl_our! { + impl Write for std::io::Cursor> +} + +impl_our! { + impl Read for std::io::Empty +} + +impl_our! { + impl BufRead for std::io::Empty +} + +impl_our! { + impl Write for std::io::Empty +} + +// No idea why &Empty impls Write but not Read + BufRead +impl_our! { + impl Write for &'_ std::io::Empty +} + +impl_our! { + impl Read for std::sync::Arc +} + +impl_our! { + impl Write for std::sync::Arc +} + +impl_our! { + impl Read for std::io::Repeat +} + +impl_our! { + impl Read for std::io::Stdin +} + +rust_version! { + if >= 1.78 { + impl_our! { + impl Read for &'_ std::io::Stdin + } + } +} + +impl_our! { + impl Write for std::io::Stdout +} + +impl_our! { + impl Write for &'_ std::io::Stdout +} + +impl_our! { + impl Write for std::io::Stderr +} + +impl_our! { + impl Write for &'_ std::io::Stderr +} + +impl_our! { + impl Read for std::io::StdinLock<'_> +} + +impl_our! { + impl BufRead for std::io::StdinLock<'_> +} + +impl_our! { + impl Read for std::fs::File +} + +impl_our! { + impl Write for std::fs::File +} + +impl_our! { + impl Read for &'_ std::fs::File +} + +impl_our! { + impl Write for &'_ std::fs::File +} + +impl_our! { + impl Read for std::net::TcpStream +} + +impl_our! { + impl Write for std::net::TcpStream +} + +impl_our! { + impl Read for &'_ std::net::TcpStream +} + +impl_our! { + impl Write for &'_ std::net::TcpStream +} + +#[cfg(target_family = "unix")] +impl_our! { + impl Read for std::os::unix::net::UnixStream +} + +#[cfg(target_family = "unix")] +impl_our! { + impl Write for std::os::unix::net::UnixStream +} + +#[cfg(target_family = "unix")] +impl_our! { + impl Read for &'_ std::os::unix::net::UnixStream +} + +#[cfg(target_family = "unix")] +impl_our! { + impl Write for &'_ std::os::unix::net::UnixStream +} + +impl_our! { + impl Read for std::process::ChildStderr +} + +impl_our! { + impl Read for std::process::ChildStdout +} + +impl_our! { + impl Write for std::process::ChildStdin +} + +// No idea why other &ChildStd* are not implemented +impl_our! { + impl Write for &'_ std::process::ChildStdin +} + +rust_version! { + if >= 1.75 { + impl_our! { + impl Read for std::collections::VecDeque + } + + impl_our! { + impl BufRead for std::collections::VecDeque + } + } +} + +impl_our! { + impl Write for std::collections::VecDeque +} diff --git a/io/src/error.rs b/io/src/error.rs new file mode 100644 index 000000000..61a574d54 --- /dev/null +++ b/io/src/error.rs @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: CC0-1.0 + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use alloc::boxed::Box; +use core::fmt; + +/// The `io` crate error type. +#[derive(Debug)] +pub struct Error { + kind: ErrorKind, + /// We want this type to be `?UnwindSafe` and `?RefUnwindSafe` - the same as `std::io::Error`. + /// + /// In `std` builds the existence of `dyn std::error:Error` prevents `UnwindSafe` and + /// `RefUnwindSafe` from being automatically implemented. But in `no-std` builds without the + /// marker nothing prevents it. + _not_unwind_safe: core::marker::PhantomData, + + #[cfg(feature = "std")] + error: Option>, + #[cfg(all(feature = "alloc", not(feature = "std")))] + error: Option>, +} + +impl Error { + /// Constructs a new I/O error. + #[cfg(feature = "std")] + pub fn new(kind: ErrorKind, error: E) -> Self + where + E: Into>, + { + Self { kind, _not_unwind_safe: core::marker::PhantomData, error: Some(error.into()) } + } + + /// Constructs a new I/O error. + #[cfg(all(feature = "alloc", not(feature = "std")))] + pub fn new(kind: ErrorKind, error: E) -> Self { + Self { kind, _not_unwind_safe: core::marker::PhantomData, error: Some(error.into()) } + } + + /// Returns the error kind for this error. + pub fn kind(&self) -> ErrorKind { self.kind } + + /// Returns a reference to this error. + #[cfg(feature = "std")] + pub fn get_ref(&self) -> Option<&(dyn std::error::Error + Send + Sync + 'static)> { + self.error.as_deref() + } + + /// Returns a reference to this error. + #[cfg(all(feature = "alloc", not(feature = "std")))] + pub fn get_ref(&self) -> Option<&(dyn fmt::Debug + Send + Sync + 'static)> { + self.error.as_deref() + } +} + +impl From for Error { + fn from(kind: ErrorKind) -> Self { + Self { + kind, + _not_unwind_safe: core::marker::PhantomData, + #[cfg(any(feature = "std", feature = "alloc"))] + error: None, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> core::result::Result<(), core::fmt::Error> { + fmt.write_fmt(format_args!("I/O Error: {}", self.kind.description()))?; + #[cfg(any(feature = "alloc", feature = "std"))] + if let Some(e) = &self.error { + fmt.write_fmt(format_args!(". {:?}", e))?; + } + Ok(()) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.error.as_ref().and_then(|e| e.as_ref().source()) + } +} + +#[cfg(feature = "std")] +impl From for Error { + fn from(o: std::io::Error) -> Self { + Self { + kind: ErrorKind::from_std(o.kind()), + _not_unwind_safe: core::marker::PhantomData, + error: o.into_inner(), + } + } +} + +#[cfg(feature = "std")] +impl From for std::io::Error { + fn from(o: Error) -> Self { + if let Some(err) = o.error { + Self::new(o.kind.to_std(), err) + } else { + o.kind.to_std().into() + } + } +} + +/// Useful for preventing `UnwindSafe` and `RefUnwindSafe` from being automatically implemented. +struct NotUnwindSafe { + _not_unwind_safe: core::marker::PhantomData<(&'static mut (), core::cell::UnsafeCell<()>)>, +} + +unsafe impl Sync for NotUnwindSafe {} + +macro_rules! define_errorkind { + ($($(#[$($attr:tt)*])* $kind:ident),*) => { + #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] + /// A minimal subset of [`std::io::ErrorKind`] which is used for [`Error`]. + /// + /// Note that, as with [`std::io`], only [`Self::Interrupted`] has defined semantics in this + /// crate, all other variants are provided here only to provide higher-fidelity conversions + /// to and from [`std::io::Error`]. + pub enum ErrorKind { + $( + $(#[$($attr)*])* + $kind + ),* + } + + impl From for ErrorKind { + fn from(never: core::convert::Infallible) -> Self { match never {} } + } + + impl ErrorKind { + fn description(&self) -> &'static str { + match self { + $(Self::$kind => stringify!($kind)),* + } + } + + #[cfg(feature = "std")] + fn to_std(self) -> std::io::ErrorKind { + match self { + $(Self::$kind => std::io::ErrorKind::$kind),* + } + } + + #[cfg(feature = "std")] + fn from_std(o: std::io::ErrorKind) -> ErrorKind { + match o { + $(std::io::ErrorKind::$kind => ErrorKind::$kind),*, + _ => ErrorKind::Other + } + } + } + } +} + +define_errorkind!( + /// An entity was not found, often a file. + NotFound, + /// The operation lacked the necessary privileges to complete. + PermissionDenied, + /// The connection was refused by the remote server. + ConnectionRefused, + /// The connection was reset by the remote server. + ConnectionReset, + /// The connection was aborted (terminated) by the remote server. + ConnectionAborted, + /// The network operation failed because it was not connected yet. + NotConnected, + /// A socket address could not be bound because the address is already in use elsewhere. + AddrInUse, + /// A nonexistent interface was requested or the requested address was not local. + AddrNotAvailable, + /// The operation failed because a pipe was closed. + BrokenPipe, + /// An entity already exists, often a file. + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was requested to not occur. + WouldBlock, + /// A parameter was incorrect. + InvalidInput, + /// Data not valid for the operation were encountered. + InvalidData, + /// The I/O operation’s timeout expired, causing it to be canceled. + TimedOut, + /// An error returned when an operation could not be completed because a call to `write` returned `Ok(0)`. + WriteZero, + /// This operation was interrupted. + Interrupted, + /// An error returned when an operation could not be completed because an "end of file" was reached prematurely. + UnexpectedEof, + // Note: Any time we bump the MSRV any new error kinds should be added here! + /// A custom error that does not fall under any other I/O error kind + Other +); + +#[cfg(all(feature = "alloc", not(feature = "std")))] +mod sealed { + use alloc::boxed::Box; + use alloc::string::String; + use core::fmt; + + pub trait IntoBoxDynDebug { + fn into(self) -> Box; + } + + impl IntoBoxDynDebug for &str { + fn into(self) -> Box { + Box::new(String::from(self)) + } + } + + impl IntoBoxDynDebug for String { + fn into(self) -> Box { Box::new(self) } + } +} diff --git a/io/src/hash.rs b/io/src/hash.rs new file mode 100644 index 000000000..8fa4ce12b --- /dev/null +++ b/io/src/hash.rs @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! I/O hashing support. +//! +//! Support for various hashing related things e.g. +//! +//! - Hashing to a writer. +//! - Implement I/O traits for hash engines. + +use hashes::hmac::HmacEngine; +use hashes::{ + hash160, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256, siphash24, + HashEngine as _, +}; + +use crate::BufRead; + +macro_rules! impl_write { + ($ty: ty, $write_fn: expr, $flush_fn: expr $(, $bounded_ty: ident : $bounds: path),*) => { + // `std::io::Write` is implemented in `bitcoin_hashes` because of the orphan rule. + impl<$($bounded_ty: $bounds),*> crate::Write for $ty { + #[inline] + fn write(&mut self, buf: &[u8]) -> crate::Result { + $write_fn(self, buf)} + + #[inline] + fn flush(&mut self) -> crate::Result<()> { + $flush_fn(self) + } + } + } +} + +impl_write!( + hash160::HashEngine, + |us: &mut hash160::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + ripemd160::HashEngine, + |us: &mut ripemd160::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + sha1::HashEngine, + |us: &mut sha1::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + sha256::HashEngine, + |us: &mut sha256::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + sha256d::HashEngine, + |us: &mut sha256d::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + sha256t::HashEngine, + |us: &mut sha256t::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) }, + T: sha256t::Tag +); + +impl_write!( + sha384::HashEngine, + |us: &mut sha384::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + sha512::HashEngine, + |us: &mut sha512::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + sha512_256::HashEngine, + |us: &mut sha512_256::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + siphash24::HashEngine, + |us: &mut siphash24::HashEngine, buf| { + hashes::HashEngine::input(us, buf); + Ok(buf.len()) + }, + |_us| { Ok(()) } +); + +impl_write!( + HmacEngine, + |us: &mut HmacEngine, buf| { + us.input(buf); + Ok(buf.len()) + }, + |_us| { Ok(()) }, + T: hashes::HashEngine +); + +/// Hashes data from a reader. +pub fn hash_reader(reader: &mut impl BufRead) -> Result +where + T: hashes::HashEngine + Default, +{ + let mut engine = T::default(); + loop { + let bytes = reader.fill_buf()?; + + let read = bytes.len(); + // Empty slice means EOF. + if read == 0 { + break; + } + + engine.input(bytes); + reader.consume(read); + } + Ok(engine.finalize()) +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +mod tests { + use alloc::format; + + use hashes::hmac; + + use super::*; + use crate::{Cursor, Write as _}; + + macro_rules! write_test { + ($mod:ident, $exp_empty:expr, $exp_256:expr, $exp_64k:expr,) => { + #[test] + fn $mod() { + let mut engine = $mod::Hash::engine(); + engine.write_all(&[]).unwrap(); + assert_eq!(format!("{}", $mod::Hash::from_engine(engine)), $exp_empty); + + let mut engine = $mod::Hash::engine(); + engine.write_all(&[1; 256]).unwrap(); + assert_eq!(format!("{}", $mod::Hash::from_engine(engine)), $exp_256); + + let mut engine = $mod::Hash::engine(); + engine.write_all(&[99; 64000]).unwrap(); + assert_eq!(format!("{}", $mod::Hash::from_engine(engine)), $exp_64k); + } + }; + } + + write_test!( + sha1, + "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "ac458b067c6b021c7e9358229b636e9d1e4cb154", + "e4b66838f9f7b6f91e5be32a02ae78094df402e7", + ); + + write_test!( + sha256, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "2661920f2409dd6c8adeb0c44972959f232b6429afa913845d0fd95e7e768234", + "5c5e904f5d4fd587c7a906bf846e08a927286f388c54c39213a4884695271bbc", + ); + + write_test!( + sha256d, + "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d", + "374000d830c75d10d9417e493a7652920f30efbd300e3fb092f24c28c20baf64", + "0050d4148ad7a0437ca0643fad5bf4614cd95d9ba21fde52370b37dcc3f03307", + ); + + write_test!( + sha384, + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", + "82135637ef6d6dd31a20e2bc9998681a3eecaf8f8c76d45e545214de38439d9a533848ec75f53e4b1a8805709c5124d0", + "fb7511d9a98c5686f9c2f55e242397815c9229d8759451e1710b8da6861e08d52f0357176f4b74f8cad9e23ab65411c7", + ); + + write_test!( + sha512, + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce\ + 47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "57ecf739d3a7ca647639adae80a05f4f361304bfcbfa1ceba93296b096e74287\ + 45fc10c142cecdd3bb587a3dba598c072f6f78b31cc0a06a3da0105ee51f75d6", + "dd28f78c53f3bc9bd0c2dca9642a1ad402a70412f985c1f6e54fadb98ce9c458\ + 4761df8d04ed04bb734ba48dd2106bb9ea54524f1394cdd18e6da3166e71c3ee", + ); + + write_test!( + sha512_256, + "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a", + "8d4bb96e7956cf5f08bf5c45f7982630c46b0b022f25cbaf722ae97c06a6e7a2", + "3367646f3e264653f7dd664ac2cb6d3b96329e86ffb7a29a1082e2a4ddc9ee7a", + ); + + write_test!( + ripemd160, + "9c1185a5c5e9fc54612808977ee8f548b2258d31", + "e571a1ca5b780aa52bafdb9ec852544ffca418ba", + "ddd2ecce739e823629c7d46ab18918e9c4a51c75", + ); + + write_test!( + hash160, + "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb", + "671356a1a874695ad3bc20cae440f4360835bd5a", + "a9608c952c8dbcc20c53803d2ca5ad31d64d9313", + ); + + #[test] + fn hmac() { + let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); + engine.write_all(&[]).unwrap(); + assert_eq!( + format!("{}", engine.finalize()), + "bf5515149cf797955c4d3194cca42472883281951697c8375d9d9b107f384225" + ); + + let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); + engine.write_all(&[1; 256]).unwrap(); + assert_eq!( + format!("{}", engine.finalize()), + "59c9aca10c81c73cb4c196d94db741b6bf2050e0153d5a45f2526bff34675ac5" + ); + + let mut engine = hmac::HmacEngine::::new(&[0xde, 0xad, 0xbe, 0xef]); + engine.write_all(&[99; 64000]).unwrap(); + assert_eq!( + format!("{}", engine.finalize()), + "30df499717415a395379a1eaabe50038036e4abb5afc94aa55c952f4aa57be08" + ); + } + + #[test] + fn siphash24() { + let mut engine = siphash24::HashEngine::with_keys(0, 0); + engine.write_all(&[]).unwrap(); + assert_eq!(format!("{}", siphash24::Hash::from_engine(engine)), "d70077739d4b921e"); + + let mut engine = siphash24::HashEngine::with_keys(0, 0); + engine.write_all(&[1; 256]).unwrap(); + assert_eq!(format!("{}", siphash24::Hash::from_engine(engine)), "3a3ccefde9b5b1e3"); + + let mut engine = siphash24::HashEngine::with_keys(0, 0); + engine.write_all(&[99; 64000]).unwrap(); + assert_eq!(format!("{}", siphash24::Hash::from_engine(engine)), "ce456e4e4ecbc5bf"); + } + + // Data and expected hashes taken from `bitcoin_hashes/tests/regression.rs`. + const DATA: &str = "arbitrary data to hash as a regression test"; + const HMAC_KEY: &[u8] = b"some key"; + + macro_rules! impl_hash_reader_test { + ($($test_name:ident, $module:ident, $want:literal);* $(;)?) => { + $( + #[test] + fn $test_name() { + let hash = $module::Hash::hash(DATA.as_bytes()); + let got = format!("{}", hash); + assert_eq!(got, $want); + + let mut reader = Cursor::new(DATA); + let hash_from_reader = $crate::hash_reader::<$module::HashEngine>(&mut reader).unwrap(); + assert_eq!(hash_from_reader, hash) + } + )* + } + } + + impl_hash_reader_test! { + hash_from_reader_hash160, hash160, "a17909f6d5373b0085c4180ba207126e5040f74d"; + hash_from_reader_ripemd160, ripemd160, "e6801701c77a1cd85662335258c7869631b4a9a8"; + hash_from_reader_sha1, sha1, "e1e81eeabadafa3d5d41cc3f405385426b0f47fd"; + hash_from_reader_sha256, sha256, "d291c6c5a07fa1d9315cdae090ebe14169fbe0a219cd55a48d0d2104eab6ec51"; + hash_from_reader_sha256d, sha256d, "93a743b022290bde3233a619b21aaebe06c5cf5cc959464c41be35711e37731b"; + hash_from_reader_sha384, sha384, "f545bd83d297978d47a7f26b858a54188499dfb4d7d570a6a2362c765031d57a29d7e002df5e34d184e70b65a4f47153"; + hash_from_reader_sha512, sha512, "057d0a37e9e0ac9a93acde0752748da059a27bcf946c7af00692ac1a95db8d21f965f40af22efc4710f100f8d3e43f79f77b1f48e1e400a95b7344b7bc0dfd10"; + hash_from_reader_sha512_256, sha512_256, "e204244c429b5bca037a2a8a6e7ed8a42b808ceaff182560840bb8c5c8e9a2ec"; + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] + pub struct RegHashTag; // Name comes from regression tests in `bitcoin_hashes`. + + impl sha256t::Tag for RegHashTag { + const MIDSTATE: sha256::Midstate = sha256::Midstate::new([0xab; 32], 64); + } + + type RegHash = sha256t::Hash; + + #[test] + fn regression_sha256t() { + let hash = RegHash::hash(DATA.as_bytes()); + let got = format!("{}", hash); + let want = "17db326d7c13867376ccca1f8a211377be3cbeaeb372f167822284866ddf14ca"; + assert_eq!(got, want); + } + + #[test] + fn regression_hmac_sha256_with_key() { + let mut engine = HmacEngine::::new(HMAC_KEY); + engine.input(DATA.as_bytes()); + let hash = engine.finalize(); + + let got = format!("{}", hash); + let want = "d159cecaf4adf90b6a641bab767e4817d3a51c414acea3682686c35ec0b37b52"; + assert_eq!(got, want); + } + + #[test] + fn regression_hmac_sha512_with_key() { + let mut engine = HmacEngine::::new(HMAC_KEY); + engine.input(DATA.as_bytes()); + let hash = engine.finalize(); + + let got = format!("{}", hash); + let want = "8511773748f89ba22c07fb3a2981a12c1823695119de41f4a62aead6b848bd34939acf16475c35ed7956114fead3e794cc162ecd35e447a4dabc3227d55f757b"; + assert_eq!(got, want); + } + + #[test] + fn regression_siphash24_with_key() { + let mut engine = siphash24::HashEngine::with_keys(0, 0); + engine.input(DATA.as_bytes()); + let hash = siphash24::Hash::from_engine(engine); + + let got = format!("{}", hash); + let want = "e823ed82311d601a"; + assert_eq!(got, want); + } +} diff --git a/io/src/lib.rs b/io/src/lib.rs new file mode 100644 index 000000000..1fca04d32 --- /dev/null +++ b/io/src/lib.rs @@ -0,0 +1,888 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Rust Bitcoin I/O Library +//! +//! The [`std::io`] module is not exposed in `no-std` Rust so building `no-std` applications which +//! require reading and writing objects via standard traits is not generally possible. Thus, this +//! library exists to export a minimal version of `std::io`'s traits which we use in `rust-bitcoin` +//! so that we can support `no-std` applications. +//! +//! These traits are not one-for-one drop-ins, but are as close as possible while still implementing +//! `std::io`'s traits without unnecessary complexity. +//! +//! For examples of how to use and implement the types and traits in this crate see `io.rs` in the +//! `github.com/rust-bitcoin/rust-bitcoin/bitcoin/examples/` directory. + +#![cfg_attr(not(feature = "std"), no_std)] +// Coding conventions. +#![warn(missing_docs)] +#![doc(test(attr(warn(unused))))] +// Pedantic lints that we enforce. +#![warn(clippy::return_self_not_must_use)] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "hashes")] +pub extern crate hashes; + +#[cfg(feature = "std")] +mod bridge; +mod error; + +#[cfg(feature = "hashes")] +mod hash; + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use alloc::vec::Vec; +use core::cmp; + +use encoding::{Decodable, Decoder, Encoder}; + +#[rustfmt::skip] // Keep public re-exports separate. +pub use self::error::{Error, ErrorKind}; +#[cfg(feature = "hashes")] +pub use self::hash::hash_reader; +#[cfg(feature = "std")] +pub use self::bridge::{FromStd, ToStd}; + +/// Result type returned by functions in this crate. +pub type Result = core::result::Result; + +/// A generic trait describing an input stream. +/// +/// See [`std::io::Read`] for more information. +pub trait Read { + /// Reads bytes from source into `buf`. + /// + /// # Returns + /// + /// The number of bytes read if successful or an [`Error`] if reading fails. + fn read(&mut self, buf: &mut [u8]) -> Result; + + /// Reads bytes from source until `buf` is full. + /// + /// # Errors + /// + /// If the exact number of bytes required to fill `buf` cannot be read. + #[inline] + fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { + while !buf.is_empty() { + match self.read(buf) { + Ok(0) => return Err(ErrorKind::UnexpectedEof.into()), + Ok(len) => buf = &mut buf[len..], + Err(e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } + + /// Constructs a new adapter which will read at most `limit` bytes. + #[inline] + fn take(self, limit: u64) -> Take + where Self: Sized, + { Take { reader: self, remaining: limit } } + + /// Attempts to read up to limit bytes from the reader, allocating space in `buf` as needed. + /// + /// `limit` is used to prevent a denial of service attack vector since an unbounded reader will + /// exhaust all memory. + /// + /// Similar to [`std::io::Read::read_to_end`] but with the DOS protection. + /// + /// # Returns + /// + /// The number of bytes read if successful or an [`Error`] if reading fails. + #[doc(alias = "read_to_end")] + #[cfg(feature = "alloc")] + #[inline] + fn read_to_limit(&mut self, buf: &mut Vec, limit: u64) -> Result { + self.take(limit).read_to_end(buf) + } +} + +/// A trait describing an input stream that uses an internal buffer when reading. +pub trait BufRead: Read { + /// Returns data read from this reader, filling the internal buffer if needed. + /// + /// # Errors + /// + /// May error if reading fails. + fn fill_buf(&mut self) -> Result<&[u8]>; + + /// Marks the buffered data up to amount as consumed. + /// + /// # Panics + /// + /// May panic if `amount` is greater than amount of data read by `fill_buf`. + fn consume(&mut self, amount: usize); +} + +/// Reader adapter which limits the bytes read from an underlying reader. +/// +/// Created by calling `[Read::take]`. +#[derive(Debug)] +pub struct Take { + reader: R, + remaining: u64, +} + +impl Take { + /// Reads all bytes until EOF from the underlying reader into `buf`. + /// + /// Allocates space in `buf` as needed. + /// + /// # Returns + /// + /// The number of bytes read if successful or an [`Error`] if reading fails. + #[cfg(feature = "alloc")] + #[inline] + pub fn read_to_end(&mut self, buf: &mut Vec) -> Result { + let mut read: usize = 0; + let mut chunk = [0u8; 64]; + loop { + match self.read(&mut chunk) { + Ok(0) => break, + Ok(n) => { + buf.extend_from_slice(&chunk[0..n]); + read += n; + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + }; + } + Ok(read) + } +} + +impl Read for Take { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + let len = cmp::min(buf.len(), self.remaining.try_into().unwrap_or(buf.len())); + let read = self.reader.read(&mut buf[..len])?; + self.remaining -= read.try_into().unwrap_or(self.remaining); + Ok(read) + } +} + +// Impl copied from Rust stdlib. +impl BufRead for Take { + #[inline] + fn fill_buf(&mut self) -> Result<&[u8]> { + // Don't call into inner reader at all at EOF because it may still block + if self.remaining == 0 { + return Ok(&[]); + } + + let buf = self.reader.fill_buf()?; + // Cast length to a u64 instead of casting `remaining` to a `usize` + // (in case `remaining > u32::MAX` and we are on a 32 bit machine). + let cap = cmp::min(buf.len() as u64, self.remaining) as usize; + Ok(&buf[..cap]) + } + + #[inline] + fn consume(&mut self, amount: usize) { + assert!(amount as u64 <= self.remaining); + self.remaining -= amount as u64; + self.reader.consume(amount); + } +} + +impl Read for &'_ mut T { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { (**self).read(buf) } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { (**self).read_exact(buf) } +} + +impl BufRead for &'_ mut T { + #[inline] + fn fill_buf(&mut self) -> Result<&[u8]> { (**self).fill_buf() } + + #[inline] + fn consume(&mut self, amount: usize) { (**self).consume(amount) } +} + +impl Read for &[u8] { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + let cnt = cmp::min(self.len(), buf.len()); + buf[..cnt].copy_from_slice(&self[..cnt]); + *self = &self[cnt..]; + Ok(cnt) + } +} + +impl BufRead for &[u8] { + #[inline] + fn fill_buf(&mut self) -> Result<&[u8]> { Ok(self) } + + // This panics if amount is out of bounds, same as the std version. + #[inline] + fn consume(&mut self, amount: usize) { *self = &self[amount..] } +} + +/// Wraps an in memory buffer providing `position` functionality for read and write. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct Cursor { + inner: T, + pos: u64, +} + +impl> Cursor { + /// Constructs a new `Cursor` by wrapping `inner`. + #[inline] + pub const fn new(inner: T) -> Self { Self { inner, pos: 0 } } + + /// Returns the position read or written up to thus far. + #[inline] + pub const fn position(&self) -> u64 { self.pos } + + /// Sets the internal position. + /// + /// This method allows seeking within the wrapped memory by setting the position. + /// + /// Note that setting a position that is larger than the buffer length will cause reads to + /// succeed by reading zero bytes. Further, writes will be no-op zero length writes. + #[inline] + pub fn set_position(&mut self, position: u64) { self.pos = position; } + + /// Returns the inner buffer. + /// + /// This is the whole wrapped buffer, including the bytes already read. + #[inline] + pub fn into_inner(self) -> T { self.inner } + + /// Returns a reference to the inner buffer. + /// + /// This is the whole wrapped buffer, including the bytes already read. + #[inline] + pub const fn get_ref(&self) -> &T { &self.inner } + + /// Returns a mutable reference to the inner buffer. + /// + /// This is the whole wrapped buffer, including the bytes already read. + #[inline] + pub fn get_mut(&mut self) -> &mut T { &mut self.inner } + + /// Returns a reference to the inner buffer. + /// + /// This is the whole wrapped buffer, including the bytes already read. + #[inline] + #[deprecated(since = "0.3.0", note = "use `get_ref()` instead")] + pub fn inner(&self) -> &T { &self.inner } +} + +impl> Read for Cursor { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + let inner: &[u8] = self.inner.as_ref(); + let start_pos = self.pos.try_into().unwrap_or(inner.len()); + if start_pos >= self.inner.as_ref().len() { + return Ok(0); + } + + let read = core::cmp::min(inner.len().saturating_sub(start_pos), buf.len()); + buf[..read].copy_from_slice(&inner[start_pos..start_pos + read]); + self.pos = self.pos.saturating_add(read.try_into().unwrap_or(u64::MAX /* unreachable */)); + Ok(read) + } +} + +impl> BufRead for Cursor { + #[inline] + fn fill_buf(&mut self) -> Result<&[u8]> { + let inner: &[u8] = self.inner.as_ref(); + let pos = self.pos.min(inner.len() as u64) as usize; + Ok(&inner[pos..]) + } + + #[inline] + fn consume(&mut self, amount: usize) { self.pos = self.pos.saturating_add(amount as u64); } +} + +impl> Write for Cursor { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + let write_slice = self.inner.as_mut(); + let pos = cmp::min(self.pos, write_slice.len() as u64); + let amt = (&mut write_slice[(pos as usize)..]).write(buf)?; + self.pos += amt as u64; + Ok(amt) + } + + #[inline] + fn flush(&mut self) -> Result<()> { Ok(()) } +} + +/// A generic trait describing an output stream. +/// +/// See [`std::io::Write`] for more information. +pub trait Write { + /// Writes `buf` into this writer, returning how many bytes were written. + fn write(&mut self, buf: &[u8]) -> Result; + + /// Flushes this output stream, ensuring that all intermediately buffered contents + /// reach their destination. + fn flush(&mut self) -> Result<()>; + + /// Attempts to write an entire buffer into this writer. + #[inline] + fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { + while !buf.is_empty() { + match self.write(buf) { + Ok(0) => return Err(ErrorKind::UnexpectedEof.into()), + Ok(len) => buf = &buf[len..], + Err(e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } +} + +impl Write for &'_ mut T { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { (**self).write(buf) } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> Result<()> { (**self).write_all(buf) } + + #[inline] + fn flush(&mut self) -> Result<()> { (**self).flush() } +} + +#[cfg(feature = "alloc")] +impl Write for alloc::vec::Vec { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> Result<()> { Ok(()) } +} + +impl Write for &mut [u8] { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + let cnt = core::cmp::min(self.len(), buf.len()); + self[..cnt].copy_from_slice(&buf[..cnt]); + *self = &mut core::mem::take(self)[cnt..]; + Ok(cnt) + } + + #[inline] + fn flush(&mut self) -> Result<()> { Ok(()) } +} + +/// A sink to which all writes succeed. +/// +/// Created using [`sink()`]. See [`std::io::Sink`] for more information. +#[derive(Clone, Copy, Debug, Default)] +pub struct Sink; + +impl Write for Sink { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { Ok(buf.len()) } + + #[inline] + fn write_all(&mut self, _: &[u8]) -> Result<()> { Ok(()) } + + #[inline] + fn flush(&mut self) -> Result<()> { Ok(()) } +} + +/// Returns a sink to which all writes succeed. +/// +/// See [`std::io::sink`] for more information. +#[inline] +pub fn sink() -> Sink { Sink } + +/// Wraps a `std` I/O type to implement the traits from this crate. +/// +/// All methods are passed through converting the errors. +#[cfg(feature = "std")] +#[inline] +pub const fn from_std(std_io: T) -> FromStd { FromStd::new(std_io) } + +/// Wraps a mutable reference to `std` I/O type to implement the traits from this crate. +/// +/// All methods are passed through converting the errors. +#[cfg(feature = "std")] +#[inline] +pub fn from_std_mut(std_io: &mut T) -> &mut FromStd { FromStd::new_mut(std_io) } + +/// Encodes a consensus_encoding object to an I/O writer. +pub fn encode_to_writer(object: &T, mut writer: W) -> Result<()> +where + T: encoding::Encodable + ?Sized, + W: Write, +{ + let mut encoder = object.encoder(); + loop { + writer.write_all(encoder.current_chunk())?; + if !encoder.advance() { + break; + } + } + Ok(()) +} + +/// Decodes an object from a buffered reader. +/// +/// # Performance +/// +/// For unbuffered readers (like [`std::fs::File`] or [`std::net::TcpStream`]), consider wrapping +/// your reader with [`std::io::BufReader`] in order to use this function. This avoids frequent +/// small reads, which can significantly impact performance. +/// +/// # Errors +/// +/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing +/// the data, or [`ReadError::Io`] if an I/O error occurs while reading. +pub fn decode_from_read(mut reader: R) -> core::result::Result::Error>> +where + T: Decodable, + R: BufRead, +{ + let mut decoder = T::decoder(); + + loop { + let mut buffer = match reader.fill_buf() { + Ok(buffer) => buffer, + // Auto retry read for non-fatal error. + Err(error) if error.kind() == ErrorKind::Interrupted => continue, + Err(error) => return Err(ReadError::Io(error)), + }; + + if buffer.is_empty() { + // EOF, but still try to finalize the decoder. + return decoder.end().map_err(ReadError::Decode); + } + + let original_len = buffer.len(); + let need_more = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?; + let consumed = original_len - buffer.len(); + reader.consume(consumed); + + if !need_more { + return decoder.end().map_err(ReadError::Decode); + } + } +} + +/// Decodes an object from an unbuffered reader using a fixed-size buffer. +/// +/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. +/// This function is only needed when you have an unbuffered reader which you +/// cannot wrap. It will probably have worse performance. +/// +/// # Buffer +/// +/// Uses a fixed 4KB (4096 bytes) stack-allocated buffer that is reused across +/// read operations. This size is a good balance between memory usage and +/// system call efficiency for most use cases. +/// +/// For different buffer sizes, use [`decode_from_read_unbuffered_with`]. +/// +/// # Errors +/// +/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing +/// the data, or [`ReadError::Io`] if an I/O error occurs while reading. +pub fn decode_from_read_unbuffered( + reader: R, +) -> core::result::Result::Error>> +where + T: Decodable, + R: Read, +{ + decode_from_read_unbuffered_with::(reader) +} + +/// Decodes an object from an unbuffered reader using a custom-sized buffer. +/// +/// For most use cases, prefer [`decode_from_read`] with a [`std::io::BufReader`]. +/// This function is only needed when you have an unbuffered reader which you +/// cannot wrap. It will probably have worse performance. +/// +/// # Buffer +/// +/// The `BUFFER_SIZE` parameter controls the intermediate buffer size used for +/// reading. The buffer is allocated on the stack (not heap) and reused across +/// read operations. Larger buffers reduce the number of system calls, but use +/// more memory. +/// +/// # Errors +/// +/// Returns [`ReadError::Decode`] if the decoder encounters an error while parsing +/// the data, or [`ReadError::Io`] if an I/O error occurs while reading. +pub fn decode_from_read_unbuffered_with( + mut reader: R, +) -> core::result::Result::Error>> +where + T: Decodable, + R: Read, +{ + let mut decoder = T::decoder(); + let mut buffer = [0u8; BUFFER_SIZE]; + + while decoder.read_limit() > 0 { + // Only read what we need, up to buffer size. + let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)]; + match reader.read(clamped_buffer) { + Ok(0) => { + // EOF, but still try to finalize the decoder. + return decoder.end().map_err(ReadError::Decode); + } + Ok(bytes_read) => { + if !decoder + .push_bytes(&mut &clamped_buffer[..bytes_read]) + .map_err(ReadError::Decode)? + { + return decoder.end().map_err(ReadError::Decode); + } + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => { + // Auto retry read for non-fatal error. + } + Err(e) => return Err(ReadError::Io(e)), + } + } + + decoder.end().map_err(ReadError::Decode) +} + +/// An error that can occur when reading and decoding from a buffered reader. +#[derive(Debug)] +pub enum ReadError { + /// An I/O error occurred while reading from the reader. + Io(Error), + /// The decoder encountered an error while parsing the data. + Decode(D), +} + +impl core::fmt::Display for ReadError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Io(e) => write!(f, "I/O error: {}", e), + Self::Decode(e) => write!(f, "decode error: {}", e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ReadError +where + D: core::fmt::Debug + core::fmt::Display + std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::Io(e) => Some(e), + Self::Decode(e) => Some(e), + } + } +} + +#[cfg(feature = "std")] +impl From for ReadError { + fn from(e: Error) -> Self { Self::Io(e) } +} + +#[cfg(test)] +mod tests { + #[cfg(all(not(feature = "std"), feature = "alloc"))] + use alloc::{string::ToString, vec}; + + use encoding::{ArrayDecoder, ArrayEncoder, UnexpectedEofError}; + + use super::*; + + #[test] + fn buf_read_fill_and_consume_slice() { + let data = [0_u8, 1, 2]; + + let mut slice = &data[..]; + + let fill = BufRead::fill_buf(&mut slice).unwrap(); + assert_eq!(fill.len(), 3); + assert_eq!(fill, &[0_u8, 1, 2]); + slice.consume(2); + + let fill = BufRead::fill_buf(&mut slice).unwrap(); + assert_eq!(fill.len(), 1); + assert_eq!(fill, &[2_u8]); + slice.consume(1); + + // checks we can attempt to read from a now-empty reader. + let fill = BufRead::fill_buf(&mut slice).unwrap(); + assert!(fill.is_empty()); + } + + #[test] + #[cfg(feature = "alloc")] + fn read_to_limit_greater_than_total_length() { + let s = "16-byte-string!!".to_string(); + let mut reader = Cursor::new(&s); + let mut buf = vec![]; + + // 32 is greater than the reader length. + let read = reader.read_to_limit(&mut buf, 32).expect("failed to read to limit"); + assert_eq!(read, s.len()); + assert_eq!(&buf, s.as_bytes()) + } + + #[test] + #[cfg(feature = "alloc")] + fn read_to_limit_less_than_total_length() { + let s = "16-byte-string!!".to_string(); + let mut reader = Cursor::new(&s); + let mut buf = vec![]; + + let read = reader.read_to_limit(&mut buf, 2).expect("failed to read to limit"); + assert_eq!(read, 2); + assert_eq!(&buf, "16".as_bytes()) + } + + #[test] + #[cfg(feature = "std")] + fn set_position_past_end_read_returns_eof() { + const BUF_LEN: usize = 64; // Just a small buffer. + let mut buf = [0_u8; BUF_LEN]; // We never actually write to this buffer. + + let v = [1_u8; BUF_LEN]; + + // Sanity check the stdlib Cursor's behaviour. + let mut c = std::io::Cursor::new(v); + for pos in [BUF_LEN, BUF_LEN + 1, BUF_LEN * 2] { + c.set_position(pos as u64); + let read = c.read(&mut buf).unwrap(); + assert_eq!(read, 0); + assert_eq!(buf[0], 0x00); // Double check that buffer state is sane. + } + + let mut c = Cursor::new(v); + for pos in [BUF_LEN, BUF_LEN + 1, BUF_LEN * 2] { + c.set_position(pos as u64); + let read = c.read(&mut buf).unwrap(); + assert_eq!(read, 0); + assert_eq!(buf[0], 0x00); // Double check that buffer state is sane. + } + } + + #[test] + fn read_into_zero_length_buffer() { + use crate::Read as _; + + const BUF_LEN: usize = 64; + let data = [1_u8; BUF_LEN]; + let mut buf = [0_u8; BUF_LEN]; + + let mut slice = data.as_ref(); + let mut take = Read::take(&mut slice, 32); + + let read = take.read(&mut buf[0..0]).unwrap(); + assert_eq!(read, 0); + assert_eq!(buf[0], 0x00); // Check the buffer didn't get touched. + } + + #[test] + #[cfg(feature = "alloc")] + fn take_and_read_to_end() { + const BUF_LEN: usize = 64; + let data = [1_u8; BUF_LEN]; + + let mut slice = data.as_ref(); + let mut take = Read::take(&mut slice, 32); + + let mut v = Vec::new(); + let read = take.read_to_end(&mut v).unwrap(); + assert_eq!(read, 32); + assert_eq!(data[0..32], v[0..32]); + } + + #[test] + fn cursor_fill_buf_past_end() { + let data = [1, 2, 3]; + let mut cursor = Cursor::new(&data); + cursor.set_position(10); + + let buf = cursor.fill_buf().unwrap(); + assert!(buf.is_empty()); + } + + #[test] + fn cursor_write() { + let data = [0x78, 0x56, 0x34, 0x12]; + + let mut buf = [0_u8; 4]; + let mut cursor = Cursor::new(&mut buf); + let amt = cursor.write(&data).unwrap(); + + assert_eq!(buf, data); + assert_eq!(amt, 4); + } + + #[test] + fn cursor_offset_write() { + let data = [0x78, 0x56, 0x34, 0x12]; + + let mut buf = [0_u8; 4]; + let mut cursor = Cursor::new(&mut buf); + cursor.set_position(2); + let amt = cursor.write(&data).unwrap(); + + assert_eq!(buf, [0, 0, 0x78, 0x56]); + assert_eq!(amt, 2); + } + + #[test] + fn cursor_consume_past_end() { + let data = [1, 2, 3]; + let mut cursor = Cursor::new(&data); + cursor.set_position(10); + + cursor.consume(5); + assert_eq!(cursor.position(), 15); + } + + // Simple test type that implements Encodable. + struct TestData(u32); + + impl encoding::Encodable for TestData { + type Encoder<'s> + = ArrayEncoder<4> + where + Self: 's; + + fn encoder(&self) -> Self::Encoder<'_> { + ArrayEncoder::without_length_prefix(self.0.to_le_bytes()) + } + } + + #[test] + fn encode_io_writer() { + let data = TestData(0x1234_5678); + + let mut buf = [0_u8; 4]; + encode_to_writer(&data, buf.as_mut_slice()).unwrap(); + + assert_eq!(buf, [0x78, 0x56, 0x34, 0x12]); + } + + #[derive(Debug, PartialEq)] + struct TestArray([u8; 4]); + + impl Decodable for TestArray { + type Decoder = TestArrayDecoder; + fn decoder() -> Self::Decoder { TestArrayDecoder { inner: ArrayDecoder::new() } } + } + + struct TestArrayDecoder { + inner: ArrayDecoder<4>, + } + + impl Decoder for TestArrayDecoder { + type Output = TestArray; + type Error = UnexpectedEofError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result { + self.inner.push_bytes(bytes) + } + + fn end(self) -> core::result::Result { self.inner.end().map(TestArray) } + + fn read_limit(&self) -> usize { self.inner.read_limit() } + } + + #[test] + fn decode_from_read_success() { + let data = [1, 2, 3, 4]; + let cursor = Cursor::new(&data); + let result: core::result::Result = decode_from_read(cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + fn decode_from_read_unexpected_eof() { + let data = [1, 2, 3]; + let cursor = Cursor::new(&data); + let result: core::result::Result = decode_from_read(cursor); + assert!(matches!(result, Err(ReadError::Decode(_)))); + } + + #[test] + fn decode_from_read_trait_object() { + let data = [1, 2, 3, 4]; + let mut cursor = Cursor::new(&data); + // Test that we can pass a trait object (&mut dyn BufRead implements BufRead). + let reader: &mut dyn BufRead = &mut cursor; + let result: core::result::Result = decode_from_read(reader); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + #[cfg(feature = "alloc")] + fn decode_from_read_by_reference() { + use crate::alloc::vec::Vec; + + let data = [1, 2, 3, 4]; + let mut cursor = Cursor::new(&data); + // Test that we can pass by reference (&mut T implements BufRead when T: BufRead). + let result: core::result::Result = decode_from_read(&mut cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + + let mut buf = Vec::new(); + let _ = cursor.read_to_limit(&mut buf, 100); + } + + #[test] + fn decode_from_read_unbuffered_success() { + let data = [1, 2, 3, 4]; + let cursor = Cursor::new(&data); + let result: core::result::Result = decode_from_read_unbuffered(cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } + + #[test] + fn decode_from_read_unbuffered_unexpected_eof() { + let data = [1, 2, 3]; + let cursor = Cursor::new(&data); + let result: core::result::Result = decode_from_read_unbuffered(cursor); + assert!(matches!(result, Err(ReadError::Decode(_)))); + } + + #[test] + fn decode_from_read_unbuffered_empty() { + let data = []; + let cursor = Cursor::new(&data); + let result: core::result::Result = decode_from_read_unbuffered(cursor); + assert!(matches!(result, Err(ReadError::Decode(_)))); + } + + #[test] + fn decode_from_read_unbuffered_extra_data() { + let data = [1, 2, 3, 4, 5, 6]; + let cursor = Cursor::new(&data); + let result: core::result::Result = decode_from_read_unbuffered(cursor); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.0, [1, 2, 3, 4]); + } +} diff --git a/io/tests/api.rs b/io/tests/api.rs new file mode 100644 index 000000000..28be86a19 --- /dev/null +++ b/io/tests/api.rs @@ -0,0 +1,160 @@ +//! Test the API surface of `io`. +//! +//! The point of these tests is to check the API surface as opposed to test the API functionality. +//! +//! ref: + +#![allow(dead_code)] +#![allow(unused_imports)] + +use core::cell::Cell; +use core::convert::Infallible; + +// These imports test "typical" usage by user code. +use bitcoin_io::{self as io, BufRead, Cursor, ErrorKind, Read, Sink, Take, Write}; +#[cfg(feature = "std")] +use bitcoin_io::{FromStd, ToStd}; + +/// An arbitrary error kind. +const ERROR_KIND: ErrorKind = ErrorKind::TimedOut; + +/// A struct that includes all public non-error enums. +#[derive(Debug)] // All public types implement Debug (C-DEBUG). +struct Enums { + a: ErrorKind, +} + +impl Enums { + /// Constructs an arbitrary `Enums` instance. + fn new() -> Self { Self { a: ERROR_KIND } } +} + +/// A struct that includes all public non-error structs except `Take`. +#[derive(Debug)] // All public types implement Debug (C-DEBUG). +struct Structs { + #[cfg(feature = "std")] + a: FromStd, + #[cfg(feature = "std")] + b: ToStd, + c: Cursor, + d: Sink, +} + +impl Structs { + fn new() -> Self { + Self { + #[cfg(feature = "std")] + a: FromStd::new(0), + #[cfg(feature = "std")] + b: ToStd::new(DUMMY), + c: Cursor::new(DUMMY), + d: Sink, + } + } +} + +#[derive(Debug)] // `Take` implements Debug (C-DEBUG). +struct Taker { + a: Take, +} + +/// An arbitrary `Dummy` instance. +static DUMMY: Dummy = Dummy(0); + +/// Dummy struct to implement all the traits we provide. +#[derive(Debug, Copy, Clone)] +struct Dummy(u64); + +impl Read for Dummy { + fn read(&mut self, buf: &mut [u8]) -> Result { + if buf.is_empty() { + Ok(0) + } else { + buf[0] = (self.0 & 0xFF) as u8; + Ok(1) + } + } +} + +impl BufRead for Dummy { + fn fill_buf(&mut self) -> Result<&[u8], io::Error> { Ok(&[]) } + fn consume(&mut self, _: usize) {} +} + +impl Write for Dummy { + fn write(&mut self, buf: &[u8]) -> Result { Ok(buf.len()) } + fn write_all(&mut self, _: &[u8]) -> Result<(), io::Error> { Ok(()) } + fn flush(&mut self) -> Result<(), io::Error> { Ok(()) } +} + +impl AsRef<[u8]> for Dummy { + fn as_ref(&self) -> &[u8] { &[] } +} + +/// A struct that includes all public non-error types. +#[derive(Debug)] // All public types implement Debug (C-DEBUG). +struct Types { + a: Enums, + b: Structs, +} + +impl Types { + fn new() -> Self { Self { a: Enums::new(), b: Structs::new() } } +} + +/// A struct that includes all public error types. +#[derive(Debug)] // `io::Error` only implements `Debug`. +struct Errors { + a: io::Error, +} + +// `Debug` representation is never empty (C-DEBUG-NONEMPTY). +#[test] +fn api_all_non_error_types_have_non_empty_debug() { + let t = Types::new(); + + let debug = format!("{:?}", t.a.a); + assert!(!debug.is_empty()); + + #[cfg(feature = "std")] + { + let debug = format!("{:?}", t.b.a); + assert!(!debug.is_empty()); + let debug = format!("{:?}", t.b.b); + assert!(!debug.is_empty()); + } + let debug = format!("{:?}", t.b.c); + assert!(!debug.is_empty()); + let debug = format!("{:?}", t.b.d); + assert!(!debug.is_empty()); +} + +#[test] +fn all_non_error_types_implement_send_sync() { + fn assert_send() {} + fn assert_sync() {} + + // Types are `Send` and `Sync` where possible (C-SEND-SYNC). + assert_send::(); + assert_sync::(); + + // Error types are meaningful and well-behaved (C-GOOD-ERR) + assert_send::(); + assert_sync::(); +} + +#[test] +fn dyn_compatible() { + // Sanity check, these are all dyn compatible. + struct StdlibTraits { + p: Box, + q: Box, + r: Box, + } + // If this builds then our three traits are dyn compatible also. + struct OurTraits { + p: Box, + q: Box, + r: Box, + } +} diff --git a/justfile b/justfile new file mode 100644 index 000000000..299ff3a26 --- /dev/null +++ b/justfile @@ -0,0 +1,83 @@ +set positional-arguments + +# Once just v1.39.0 is widely deployed, simplify with the `read` function. +NIGHTLY_VERSION := trim(shell('cat "$1"', justfile_directory() / "nightly-version")) + +alias ulf := update-lock-files + +_default: + @just --list + +# Run the given CI task using maintainer tools. +[group('ci')] +@ci task toolchain="stable" lock="recent": + {{justfile_directory()}}/contrib/ensure-maintainer-tools.sh + cp -f {{justfile_directory()}}/Cargo-{{lock}}.lock {{justfile_directory()}}/Cargo.lock + MAINTAINER_TOOLS_LOG_LEVEL=quiet rustup run {{toolchain}} {{justfile_directory()}}/.maintainer-tools/ci/run_task.sh {{task}} + +# Test workspace with stable toolchain. +[group('ci')] +ci-stable: (ci "stable") + +# Lint workspace. +[group('ci')] +ci-lint: (ci "lint" NIGHTLY_VERSION) + +# Generate documentation. +[group('ci')] +ci-docs: (ci "docs") + +# Generate documentation with nightly. +[group('ci')] +ci-docsrs: (ci "docsrs" NIGHTLY_VERSION) + +# Run benchmarks. +[group('ci')] +ci-bench: (ci "bench") + +# Quick workspace lint. +@lint: + cargo +{{NIGHTLY_VERSION}} clippy --quiet --workspace --all-targets --all-features -- --deny warnings + +# Quick workspace sanity check. +@sane: lint + cargo test --quiet --workspace --all-targets --no-default-features + cargo test --quiet --workspace --all-targets --all-features + +# Format workspace. +@fmt: + cargo +{{NIGHTLY_VERSION}} fmt --all + +# Generate documentation (accepts cargo doc args, e.g. --open). +@docsrs *flags: + RUSTDOCFLAGS="--cfg docsrs -D warnings -D rustdoc::broken-intra-doc-links" cargo +{{NIGHTLY_VERSION}} doc --all-features {{flags}} + +# Check for API changes. +[group('scripts')] +check-api: + {{justfile_directory()}}/contrib/check-for-api-changes.sh + +# Query the current API. +[group('scripts')] +@query-api crate command: + {{justfile_directory()}}/contrib/api.sh $1 $2 + +# Update the recent and minimal lock files. +[group('scripts')] +update-lock-files: + {{justfile_directory()}}/contrib/update-lock-files.sh + +# Install githooks. +[group('scripts')] +githooks-install: + {{justfile_directory()}}/contrib/copy-githooks.sh + +# Remove githooks. +[group('scripts')] +githooks-remove: + {{justfile_directory()}}/contrib/copy-githooks.sh -r + +# Generate a dependency tree for workspace crates. +[group('scripts')] +gen-dep-tree: + {{justfile_directory()}}/contrib/gen-dep-tree.sh diff --git a/logo/README.md b/logo/README.md new file mode 100644 index 000000000..e68633c7d --- /dev/null +++ b/logo/README.md @@ -0,0 +1,32 @@ +# Rust Bitcoin Logo + +## Files + +Included are: + +- [rust-bitcoin-inkscape.svg](./rust-bitcoin-inkscape.svg) - The Inkscape source file with the things used to make the logo in case adjustments are desired +- [rust-bitcoin-optimized.svg](./rust-bitcoin-optimized.svg) - An optimized SVG for embedding or rendering at any size desired +- [rust-bitcoin.png](./rust-bitcoin.png) - The PNG logo rendered at 300px used by this project +- [rust-bitcoin-large.png](./rust-bitcoin-large.png) - A larger size 1024px x 1024px for convenience for embedding in presentations + +## Author + +Hunter Trujillo, @cryptoquick on [Twitter](https://twitter.com/cryptoquick), [GitHub](https://github.com/cryptoquick), and Telegram. + +## License + +Licensed in the public domain under [CC0 1.0 Universal Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/), and the author of this work rescinds all claims to copyright or coercion or acts of force from any nation state over this work for any purpose + +Bitcoin Logo is licensed under the CC Public Domain Dedication: and + +Rust Logo is licensed under CC-BY, which allows reuse and modifications for any purpose, as long as distributors give appropriate credit and indicate changes have been made. See here: + +## Acknowledgements + +Acknowledgement for the runners up in this PR: + +In particular, the Rust Bitcoin Wizard gear was an incredibly inspired piece of art. Also, the meshed gears design was beloved by some but not all. + +Thank you to the Rust Bitcoin maintainers and community, your timely responses and guidance was appreciated. + +Also, thank you to the voters on the Rust in Bitcoin Telegram group: . diff --git a/logo/rust-bitcoin-inkscape.svg b/logo/rust-bitcoin-inkscape.svg new file mode 100644 index 000000000..9b504a344 --- /dev/null +++ b/logo/rust-bitcoin-inkscape.svg @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logo/rust-bitcoin-large.png b/logo/rust-bitcoin-large.png new file mode 100644 index 000000000..f0cce3403 Binary files /dev/null and b/logo/rust-bitcoin-large.png differ diff --git a/logo/rust-bitcoin-optimized.svg b/logo/rust-bitcoin-optimized.svg new file mode 100644 index 000000000..31cf374ba --- /dev/null +++ b/logo/rust-bitcoin-optimized.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/logo/rust-bitcoin.png b/logo/rust-bitcoin.png new file mode 100644 index 000000000..0f59dd168 Binary files /dev/null and b/logo/rust-bitcoin.png differ diff --git a/maintainer-tools-version b/maintainer-tools-version new file mode 100644 index 000000000..f9a7d00fd --- /dev/null +++ b/maintainer-tools-version @@ -0,0 +1 @@ +e7ad5b2aa5f742093d8e07d4a2a7d415254cf6f4 diff --git a/nightly-version b/nightly-version new file mode 100644 index 000000000..fa9b5fe68 --- /dev/null +++ b/nightly-version @@ -0,0 +1 @@ +nightly-2025-09-26 diff --git a/p2p/CHANGELOG.md b/p2p/CHANGELOG.md new file mode 100644 index 000000000..4c310ad4b --- /dev/null +++ b/p2p/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.1.0 - 2025-05-27 + +* Initial release of the `github.com/rust-bitcoin/rust-bitcoin/p2p` crate as `bitcoin-p2p-messages`. diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml new file mode 100644 index 000000000..ee93bc226 --- /dev/null +++ b/p2p/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "bitcoin-p2p-messages" +version = "0.1.0" +authors = ["Andrew Poelstra "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +description = "Peer-to-peer messages defined by the Bitcoin protocol" +categories = ["cryptography::cryptocurrencies"] +keywords = ["bitcoin", "peer-to-peer"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std"] +std = ["encoding/std", "hashes/std", "hex/std", "internals/std", "io/std", "units/std", "bitcoin/std"] +arbitrary = ["dep:arbitrary", "bitcoin/arbitrary"] + +[dependencies] +bitcoin = { path = "../bitcoin/", default-features = false } +encoding = { package = "bitcoin-consensus-encoding", version = "=1.0.0-rc.2", path = "../consensus_encoding", default-features = false } +hashes = { package = "bitcoin_hashes", version = "0.18.0", path = "../hashes", default-features = false } +hex = { package = "hex-conservative", version = "0.3.0", default-features = false } +internals = { package = "bitcoin-internals", path = "../internals", default-features = false } +io = { package = "bitcoin-io", path = "../io", default-features = false } +units = { package = "bitcoin-units", path = "../units", version = "=1.0.0-rc.3", default-features = false } + +arbitrary = { version = "1.4.1", optional = true } + +[dev-dependencies] +hex_lit = "0.1.1" + +[[example]] +name = "handshake" +required-features = ["std"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints.clippy] +redundant_clone = "warn" +use_self = "warn" diff --git a/p2p/README.md b/p2p/README.md new file mode 100644 index 000000000..23d3f939f --- /dev/null +++ b/p2p/README.md @@ -0,0 +1,3 @@ +# Rust Bitcoin Peer to Peer Message Types + +This crate provides data types used in the Bitcoin peer-to-peer protocol. diff --git a/p2p/contrib/extra_lints.sh b/p2p/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/p2p/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/p2p/contrib/test_vars.sh b/p2p/contrib/test_vars.sh new file mode 100644 index 000000000..701c4c89b --- /dev/null +++ b/p2p/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" enabled. +FEATURES_WITHOUT_STD="arbitrary" + +# Run these examples. +EXAMPLES="" diff --git a/p2p/examples/handshake.rs b/p2p/examples/handshake.rs new file mode 100644 index 000000000..690ffc062 --- /dev/null +++ b/p2p/examples/handshake.rs @@ -0,0 +1,117 @@ +use std::io::BufReader; +use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream}; +use std::time::{SystemTime, UNIX_EPOCH}; +use std::{env, process}; + +use bitcoin_p2p_messages::message_network::{ClientSoftwareVersion, UserAgent, UserAgentVersion}; +use bitcoin_p2p_messages::{ + self, address, message, message_network, Magic, ProtocolVersion, ServiceFlags, +}; + +const SOFTWARE_VERSION: ClientSoftwareVersion = + ClientSoftwareVersion::SemVer { major: 0, minor: 1, revision: 0 }; +const USER_AGENT_VERSION: UserAgentVersion = UserAgentVersion::new(SOFTWARE_VERSION); +const SOFTWARE_NAME: &str = "rust-client"; + +fn main() { + // This example establishes a connection to a Bitcoin node, sends the initial + // "version" message, waits for the reply, and finally closes the connection. + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("not enough arguments"); + process::exit(1); + } + + let str_address = &args[1]; + + let address: SocketAddr = str_address.parse().unwrap_or_else(|error| { + eprintln!("error parsing address: {error:?}"); + process::exit(1); + }); + + let version_message = build_version_message(address); + + let first_message = message::RawNetworkMessage::new(Magic::BITCOIN, version_message); + + if let Ok(mut stream) = TcpStream::connect(address) { + // Send the message + encoding::encode_to_writer(&first_message, &mut stream).unwrap(); + println!("Sent version message"); + + // Setup StreamReader + let read_stream = stream.try_clone().unwrap(); + let mut stream_reader = BufReader::new(read_stream); + loop { + // Loop and retrieve new messages + let reply = + encoding::decode_from_read::(&mut stream_reader) + .unwrap(); + match reply.payload() { + message::NetworkMessage::Version(_) => { + println!("Received version message: {:?}", reply.payload()); + + let second_message = message::RawNetworkMessage::new( + Magic::BITCOIN, + message::NetworkMessage::Verack, + ); + + encoding::encode_to_writer(&second_message, &mut stream).unwrap(); + println!("Sent verack message"); + } + message::NetworkMessage::Verack => { + println!("Received verack message: {:?}", reply.payload()); + break; + } + _ => { + println!("Received unknown message: {:?}", reply.payload()); + break; + } + } + } + let _ = stream.shutdown(Shutdown::Both); + } else { + eprintln!("failed to open connection"); + } +} + +fn build_version_message(address: SocketAddr) -> message::NetworkMessage { + // Building version message, see https://en.bitcoin.it/wiki/Protocol_documentation#version + let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); + + // The version of the p2p protocol this client will use + let protocol_version = ProtocolVersion::BIP0031_VERSION; + + // "bitfield of features to be enabled for this connection" + let services = ServiceFlags::NONE; + + // "standard UNIX timestamp in seconds" + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs(); + + // "The network address of the node receiving this message" + let addr_recv = address::Address::new(&address, ServiceFlags::NONE); + + // "The network address of the node emitting this message" + let addr_from = address::Address::new(&my_address, ServiceFlags::NONE); + + // "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self." + // Because this crate does not include the `rand` dependency, this is a fixed value. + let nonce: u64 = 42; + + // "The last block received by the emitting node" + let start_height: i32 = 0; + + // A formatted string describing the software in use. + let user_agent = UserAgent::new(SOFTWARE_NAME, USER_AGENT_VERSION); + + // Construct the message + message::NetworkMessage::Version(message_network::VersionMessage::new( + protocol_version, + services, + timestamp as i64, + addr_recv, + addr_from, + nonce, + user_agent, + start_height, + )) +} diff --git a/p2p/src/address.rs b/p2p/src/address.rs new file mode 100644 index 000000000..945e02d49 --- /dev/null +++ b/p2p/src/address.rs @@ -0,0 +1,982 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin network addresses. +//! +//! This module defines the structures and functions needed to encode +//! network addresses in Bitcoin messages. + +use alloc::vec; +use alloc::vec::Vec; +use core::{fmt, iter}; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::consensus::encode::{self, Decodable, Encodable, ReadExt, WriteExt}; +use io::{BufRead, Read, Write}; + +use crate::ServiceFlags; + +/// A message which can be sent on the Bitcoin network +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct Address { + /// Services provided by the peer whose address this is + pub services: ServiceFlags, + /// Network byte-order ipv6 address, or ipv4-mapped ipv6 address + pub address: [u16; 8], + /// Network port + pub port: u16, +} + +const ONION: [u16; 3] = [0xFD87, 0xD87E, 0xEB43]; + +impl Address { + /// Constructs a new address message for a socket + pub fn new(socket: &SocketAddr, services: ServiceFlags) -> Self { + let (address, port) = match *socket { + SocketAddr::V4(addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()), + SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()), + }; + Self { address, port, services } + } + + /// Builds a useless address that cannot be connected to. One may find this desirable if it is + /// known the data will be ignored by the recipient. + pub const fn useless() -> Self { + Self { services: ServiceFlags::NONE, address: [0; 8], port: 0 } + } + + /// Extracts socket address from an [Address] message. + /// + /// # Errors + /// + /// Returns an error if the message contains a Tor V2 onion address. + pub fn socket_addr(&self) -> Result { + let addr = &self.address; + if addr[0..3] == ONION { + return Err(UnroutableAddressError::TorV2); + } + let ipv6 = + Ipv6Addr::new(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); + if let Some(ipv4) = ipv6.to_ipv4() { + Ok(SocketAddr::V4(SocketAddrV4::new(ipv4, self.port))) + } else { + Ok(SocketAddr::V6(SocketAddrV6::new(ipv6, self.port, 0, 0))) + } + } +} + +impl Encodable for Address { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = self.services.consensus_encode(w)?; + + for word in &self.address { + w.write_all(&word.to_be_bytes())?; + len += 2; + } + + w.write_all(&self.port.to_be_bytes())?; + len += 2; + + Ok(len) + } +} + +impl Decodable for Address { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Ok(Self { + services: Decodable::consensus_decode(r)?, + address: read_be_address(r)?, + port: u16::swap_bytes(Decodable::consensus_decode(r)?), + }) + } +} + +/// Reads a big-endian address from reader. +fn read_be_address(r: &mut R) -> Result<[u16; 8], encode::Error> { + let mut address = [0u16; 8]; + let mut buf = [0u8; 2]; + + for word in &mut address { + Read::read_exact(r, &mut buf)?; + *word = u16::from_be_bytes(buf) + } + Ok(address) +} + +impl fmt::Debug for Address { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ipv6 = Ipv6Addr::from(self.address); + + match ipv6.to_ipv4() { + Some(addr) => write!( + f, + "Address {{services: {}, address: {}, port: {}}}", + self.services, addr, self.port + ), + None => write!( + f, + "Address {{services: {}, address: {}, port: {}}}", + self.services, ipv6, self.port + ), + } + } +} + +impl ToSocketAddrs for Address { + type Iter = iter::Once; + fn to_socket_addrs(&self) -> Result { + self.socket_addr() + .map(iter::once) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e)) + } +} + +/// Supported networks for use in BIP-0155 addrv2 message +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum AddrV2 { + /// IPV4 + Ipv4(Ipv4Addr), + /// IPV6 + Ipv6(Ipv6Addr), + /// TORV3 + TorV3([u8; 32]), + /// I2P + I2p([u8; 32]), + /// CJDNS + Cjdns(Ipv6Addr), + /// Unknown + Unknown(u8, Vec), +} + +impl TryFrom for IpAddr { + type Error = UnroutableAddressError; + + fn try_from(addr: AddrV2) -> Result { + match addr { + AddrV2::Ipv4(ip) => Ok(Self::V4(ip)), + AddrV2::Ipv6(ip) => Ok(Self::V6(ip)), + AddrV2::Cjdns(_) => Err(UnroutableAddressError::Cjdns), + AddrV2::TorV3(_) => Err(UnroutableAddressError::TorV3), + AddrV2::I2p(_) => Err(UnroutableAddressError::I2p), + AddrV2::Unknown(_, _) => Err(UnroutableAddressError::Unknown), + } + } +} + +impl TryFrom for Ipv4Addr { + type Error = AddrV2ToIpv4AddrError; + + fn try_from(addr: AddrV2) -> Result { + match addr { + AddrV2::Ipv4(ip) => Ok(ip), + AddrV2::Ipv6(_) => Err(AddrV2ToIpv4AddrError::Ipv6), + AddrV2::Cjdns(_) => Err(AddrV2ToIpv4AddrError::Cjdns), + AddrV2::TorV3(_) => Err(AddrV2ToIpv4AddrError::TorV3), + AddrV2::I2p(_) => Err(AddrV2ToIpv4AddrError::I2p), + AddrV2::Unknown(_, _) => Err(AddrV2ToIpv4AddrError::Unknown), + } + } +} + +impl TryFrom for Ipv6Addr { + type Error = AddrV2ToIpv6AddrError; + + fn try_from(addr: AddrV2) -> Result { + match addr { + AddrV2::Ipv6(ip) => Ok(ip), + AddrV2::Cjdns(_) => Err(AddrV2ToIpv6AddrError::Cjdns), + AddrV2::Ipv4(_) => Err(AddrV2ToIpv6AddrError::Ipv4), + AddrV2::TorV3(_) => Err(AddrV2ToIpv6AddrError::TorV3), + AddrV2::I2p(_) => Err(AddrV2ToIpv6AddrError::I2p), + AddrV2::Unknown(_, _) => Err(AddrV2ToIpv6AddrError::Unknown), + } + } +} + +impl From for AddrV2 { + fn from(addr: IpAddr) -> Self { + match addr { + IpAddr::V4(ip) => Self::Ipv4(ip), + IpAddr::V6(ip) => Self::Ipv6(ip), + } + } +} + +impl From for AddrV2 { + fn from(addr: Ipv4Addr) -> Self { + Self::Ipv4(addr) + } +} + +impl From for AddrV2 { + fn from(addr: Ipv6Addr) -> Self { + Self::Ipv6(addr) + } +} + +impl Encodable for AddrV2 { + fn consensus_encode(&self, w: &mut W) -> Result { + fn encode_addr( + w: &mut W, + network: u8, + bytes: &[u8], + ) -> Result { + Ok(network.consensus_encode(w)? + + crate::consensus::consensus_encode_with_size(bytes, w)?) + } + Ok(match *self { + Self::Ipv4(ref addr) => encode_addr(w, 1, &addr.octets())?, + Self::Ipv6(ref addr) => encode_addr(w, 2, &addr.octets())?, + Self::TorV3(ref bytes) => encode_addr(w, 4, bytes)?, + Self::I2p(ref bytes) => encode_addr(w, 5, bytes)?, + Self::Cjdns(ref addr) => encode_addr(w, 6, &addr.octets())?, + Self::Unknown(network, ref bytes) => encode_addr(w, network, bytes)?, + }) + } +} + +impl Decodable for AddrV2 { + fn consensus_decode(r: &mut R) -> Result { + let network_id = u8::consensus_decode(r)?; + let len = r.read_compact_size()?; + if len > 512 { + return Err(crate::consensus::parse_failed_error("IP must be <= 512 bytes")); + } + Ok(match network_id { + 1 => { + if len != 4 { + return Err(crate::consensus::parse_failed_error("invalid IPv4 address")); + } + let addr: [u8; 4] = Decodable::consensus_decode(r)?; + Self::Ipv4(Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3])) + } + 2 => { + if len != 16 { + return Err(crate::consensus::parse_failed_error("invalid IPv6 address")); + } + let addr: [u16; 8] = read_be_address(r)?; + if addr[0..3] == ONION { + return Err(crate::consensus::parse_failed_error( + "OnionCat address sent with IPv6 network id", + )); + } + if addr[0..6] == [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF] { + return Err(crate::consensus::parse_failed_error( + "IPV4 wrapped address sent with IPv6 network id", + )); + } + Self::Ipv6(Ipv6Addr::new( + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + )) + } + + 4 => { + if len != 32 { + return Err(crate::consensus::parse_failed_error("invalid TorV3 address")); + } + let pubkey = Decodable::consensus_decode(r)?; + Self::TorV3(pubkey) + } + 5 => { + if len != 32 { + return Err(crate::consensus::parse_failed_error("invalid I2P address")); + } + let hash = Decodable::consensus_decode(r)?; + Self::I2p(hash) + } + 6 => { + if len != 16 { + return Err(crate::consensus::parse_failed_error("invalid CJDNS address")); + } + let addr: [u16; 8] = read_be_address(r)?; + // check the first byte for the CJDNS marker + if addr[0] >> 8 != 0xFC { + return Err(crate::consensus::parse_failed_error("invalid CJDNS address")); + } + Self::Cjdns(Ipv6Addr::new( + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], + )) + } + _ => { + // len already checked above to be <= 512 + let mut addr = vec![0u8; len as usize]; + r.read_slice(&mut addr)?; + Self::Unknown(network_id, addr) + } + }) + } +} + +/// Address received from BIP-0155 addrv2 message +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct AddrV2Message { + /// Time that this node was last seen as connected to the network + pub time: u32, + /// Service bits + pub services: ServiceFlags, + /// Network ID + Network Address + pub addr: AddrV2, + /// Network port, 0 if not applicable + pub port: u16, +} + +impl AddrV2Message { + /// Extracts socket address from an [AddrV2Message] message. + /// + /// # Errors + /// + /// Returns an error if the address type cannot be converted to a socket address + /// (e.g. Tor, I2P, CJDNS addresses). + pub fn socket_addr(&self) -> Result { + match self.addr { + AddrV2::Ipv4(addr) => Ok(SocketAddr::V4(SocketAddrV4::new(addr, self.port))), + AddrV2::Ipv6(addr) => Ok(SocketAddr::V6(SocketAddrV6::new(addr, self.port, 0, 0))), + AddrV2::TorV3(_) => Err(UnroutableAddressError::TorV3), + AddrV2::I2p(_) => Err(UnroutableAddressError::I2p), + AddrV2::Cjdns(_) => Err(UnroutableAddressError::Cjdns), + AddrV2::Unknown(_, _) => Err(UnroutableAddressError::Unknown), + } + } +} + +impl Encodable for AddrV2Message { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += self.time.consensus_encode(w)?; + len += w.emit_compact_size(self.services.to_u64())?; + len += self.addr.consensus_encode(w)?; + + w.write_all(&self.port.to_be_bytes())?; + len += 2; // port u16 is two bytes. + + Ok(len) + } +} + +impl Decodable for AddrV2Message { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self { + time: Decodable::consensus_decode(r)?, + services: ServiceFlags::from(r.read_compact_size()?), + addr: Decodable::consensus_decode(r)?, + port: u16::swap_bytes(Decodable::consensus_decode(r)?), + }) + } +} + +impl ToSocketAddrs for AddrV2Message { + type Iter = iter::Once; + fn to_socket_addrs(&self) -> Result { + self.socket_addr() + .map(iter::once) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e)) + } +} + +/// Error returned when an address cannot be converted to an IP-based address. +/// +/// Addresses like Tor, I2P, and CJDNS use different routing mechanisms +/// and cannot be represented as standard IP addresses or socket addresses. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum UnroutableAddressError { + /// Tor V2 onion address. + TorV2, + /// Tor V3 onion address. + TorV3, + /// I2P address. + I2p, + /// CJDNS address. + Cjdns, + /// Unknown address type. + Unknown, +} + +impl fmt::Display for UnroutableAddressError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::TorV2 => write!(f, "Tor v2 addresses cannot be converted to IP addresses"), + Self::TorV3 => write!(f, "Tor v3 addresses cannot be converted to IP addresses"), + Self::I2p => write!(f, "I2P addresses cannot be converted to IP addresses"), + Self::Cjdns => write!(f, "CJDNS addresses cannot be converted to IP addresses"), + Self::Unknown => write!(f, "unknown address type cannot be converted to IP addresses"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnroutableAddressError {} + +/// Error types for [`AddrV2`] to [`IpAddr`] conversion. +#[derive(Debug, PartialEq, Eq)] +pub enum AddrV2ToIpAddrError { + /// A [`AddrV2::TorV3`] address cannot be converted to a [`IpAddr`]. + TorV3, + /// A [`AddrV2::I2p`] address cannot be converted to a [`IpAddr`]. + I2p, + /// A [`AddrV2::Cjdns`] address cannot be converted to a [`IpAddr`], + Cjdns, + /// A [`AddrV2::Unknown`] address cannot be converted to a [`IpAddr`]. + Unknown, +} + +impl fmt::Display for AddrV2ToIpAddrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::TorV3 => write!(f, "TorV3 addresses cannot be converted to IpAddr"), + Self::I2p => write!(f, "I2P addresses cannot be converted to IpAddr"), + Self::Cjdns => write!(f, "Cjdns addresses cannot be converted to IpAddr"), + Self::Unknown => write!(f, "Unknown address type cannot be converted to IpAddr"), + } + } +} + +impl std::error::Error for AddrV2ToIpAddrError {} + +/// Error types for [`AddrV2`] to [`Ipv4Addr`] conversion. +#[derive(Debug, PartialEq, Eq)] +pub enum AddrV2ToIpv4AddrError { + /// A [`AddrV2::Ipv6`] address cannot be converted to a [`Ipv4Addr`]. + Ipv6, + /// A [`AddrV2::TorV3`] address cannot be converted to a [`Ipv4Addr`]. + TorV3, + /// A [`AddrV2::I2p`] address cannot be converted to a [`Ipv4Addr`]. + I2p, + /// A [`AddrV2::Cjdns`] address cannot be converted to a [`Ipv4Addr`], + Cjdns, + /// A [`AddrV2::Unknown`] address cannot be converted to a [`Ipv4Addr`]. + Unknown, +} + +impl fmt::Display for AddrV2ToIpv4AddrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Ipv6 => write!(f, "Ipv6 addresses cannot be converted to Ipv4Addr"), + Self::TorV3 => write!(f, "TorV3 addresses cannot be converted to Ipv4Addr"), + Self::I2p => write!(f, "I2P addresses cannot be converted to Ipv4Addr"), + Self::Cjdns => write!(f, "Cjdns addresses cannot be converted to Ipv4Addr"), + Self::Unknown => write!(f, "Unknown address type cannot be converted to Ipv4Addr"), + } + } +} + +impl std::error::Error for AddrV2ToIpv4AddrError {} + +/// Error types for [`AddrV2`] to [`Ipv6Addr`] conversion. +#[derive(Debug, PartialEq, Eq)] +pub enum AddrV2ToIpv6AddrError { + /// A [`AddrV2::Ipv4`] address cannot be converted to a [`Ipv6Addr`]. + Ipv4, + /// A [`AddrV2::TorV3`] address cannot be converted to a [`Ipv6Addr`]. + TorV3, + /// A [`AddrV2::I2p`] address cannot be converted to a [`Ipv6Addr`]. + I2p, + /// A [`AddrV2::Cjdns`] address cannot be converted to a [`Ipv6Addr`], + Cjdns, + /// A [`AddrV2::Unknown`] address cannot be converted to a [`Ipv6Addr`]. + Unknown, +} + +impl fmt::Display for AddrV2ToIpv6AddrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Ipv4 => write!(f, "Ipv4 addresses cannot be converted to Ipv6Addr"), + Self::TorV3 => write!(f, "TorV3 addresses cannot be converted to Ipv6Addr"), + Self::I2p => write!(f, "I2P addresses cannot be converted to Ipv6Addr"), + Self::Cjdns => write!(f, "Cjdns addresses cannot be converted to Ipv6Addr"), + Self::Unknown => write!(f, "Unknown address type cannot be converted to Ipv6Addr"), + } + } +} + +impl std::error::Error for AddrV2ToIpv6AddrError {} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Address { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let socket_addr = match bool::arbitrary(u)? { + true => SocketAddr::new( + IpAddr::V4(Ipv4Addr::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + )), + u.arbitrary()?, + ), + false => SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + )), + u.arbitrary()?, + ), + }; + + Ok(Self::new(&socket_addr, u.arbitrary()?)) + } +} +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for AddrV2 { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match u.int_in_range(0..=5)? { + 0 => Ok(Self::Ipv4(Ipv4Addr::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + ))), + 1 => Ok(Self::Ipv6(Ipv6Addr::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + ))), + 2 => Ok(Self::TorV3(u.arbitrary()?)), + 3 => Ok(Self::I2p(u.arbitrary()?)), + 4 => Ok(Self::Cjdns(Ipv6Addr::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + ))), + _ => Ok(Self::Unknown(u.arbitrary()?, Vec::::arbitrary(u)?)), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for AddrV2Message { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + time: u.arbitrary()?, + services: u.arbitrary()?, + addr: u.arbitrary()?, + port: u.arbitrary()?, + }) + } +} + +#[cfg(test)] +mod test { + use alloc::{format, vec}; + use std::net::IpAddr; + + use bitcoin::consensus::encode::{deserialize, serialize}; + use hex::FromHex; + use hex_lit::hex; + + use super::*; + use crate::message::AddrV2Payload; + + #[test] + fn serialize_address() { + assert_eq!( + serialize(&Address { + services: ServiceFlags::NETWORK, + address: [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001], + port: 8333 + }), + [ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + 0x20, 0x8d + ] + ); + } + + #[test] + fn debug_format() { + let mut flags = ServiceFlags::NETWORK; + assert_eq!( + format!("The address is: {:?}", Address { + services: flags.add(ServiceFlags::WITNESS), + address: [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001], + port: 8333 + }), + "The address is: Address {services: ServiceFlags(NETWORK|WITNESS), address: 10.0.0.1, port: 8333}" + ); + + assert_eq!( + format!("The address is: {:?}", Address { + services: ServiceFlags::NETWORK_LIMITED, + address: [0xFD87, 0xD87E, 0xEB43, 0, 0, 0xffff, 0x0a00, 0x0001], + port: 8333 + }), + "The address is: Address {services: ServiceFlags(NETWORK_LIMITED), address: fd87:d87e:eb43::ffff:a00:1, port: 8333}" + ); + } + + #[test] + fn deserialize_address() { + let mut addr: Result = deserialize(&[ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + 0x20, 0x8d, + ]); + assert!(addr.is_ok()); + let full = addr.unwrap(); + assert!(matches!(full.socket_addr().unwrap(), SocketAddr::V4(_))); + assert_eq!(full.services, ServiceFlags::NETWORK); + assert_eq!(full.address, [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]); + assert_eq!(full.port, 8333); + + addr = deserialize(&[ + 1u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1, + ]); + assert!(addr.is_err()); + } + + #[test] + fn socket_addr() { + let s4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(111, 222, 123, 4)), 5555); + let a4 = Address::new(&s4, ServiceFlags::NETWORK | ServiceFlags::WITNESS); + assert_eq!(a4.socket_addr().unwrap(), s4); + let s6 = SocketAddr::new( + IpAddr::V6(Ipv6Addr::new( + 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, + )), + 9999, + ); + let a6 = Address::new(&s6, ServiceFlags::NETWORK | ServiceFlags::WITNESS); + assert_eq!(a6.socket_addr().unwrap(), s6); + } + + #[test] + fn onion() { + let onionaddr = SocketAddr::new( + IpAddr::V6("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca".parse::().unwrap()), + 1111, + ); + let addr = Address::new(&onionaddr, ServiceFlags::NONE); + assert!(addr.socket_addr().is_err()); + } + + #[test] + fn serialize_addrv2() { + // Taken from https://github.com/bitcoin/bitcoin/blob/12a1c3ad1a43634d2a98717e49e3f02c4acea2fe/src/test/net_tests.cpp#L348 + + let ip = AddrV2::Ipv4(Ipv4Addr::new(1, 2, 3, 4)); + assert_eq!(serialize(&ip), hex!("010401020304")); + + let ip = + AddrV2::Ipv6("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b".parse::().unwrap()); + assert_eq!(serialize(&ip), hex!("02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b")); + + let ip = AddrV2::TorV3( + FromHex::from_hex("53cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88") + .unwrap(), + ); + assert_eq!( + serialize(&ip), + hex!("042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88") + ); + + let ip = AddrV2::I2p( + FromHex::from_hex("a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + .unwrap(), + ); + assert_eq!( + serialize(&ip), + hex!("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87") + ); + + let ip = AddrV2::Cjdns("fc01:1:2:3:4:5:6:7".parse::().unwrap()); + assert_eq!(serialize(&ip), hex!("0610fc010001000200030004000500060007")); + + let ip = AddrV2::Unknown(170, hex!("01020304").to_vec()); + assert_eq!(serialize(&ip), hex!("aa0401020304")); + } + + #[test] + fn deserialize_addrv2() { + // Taken from https://github.com/bitcoin/bitcoin/blob/12a1c3ad1a43634d2a98717e49e3f02c4acea2fe/src/test/net_tests.cpp#L386 + + // Valid IPv4. + let ip: AddrV2 = deserialize(&hex!("010401020304")).unwrap(); + assert_eq!(ip, AddrV2::Ipv4(Ipv4Addr::new(1, 2, 3, 4))); + + // Invalid IPv4, valid length but address itself is shorter. + deserialize::(&hex!("01040102")).unwrap_err(); + + // Invalid IPv4, with bogus length. + assert!(deserialize::(&hex!("010501020304")).is_err()); + + // Invalid IPv4, with extreme length. + assert!(deserialize::(&hex!("01fd010201020304")).is_err()); + + // Valid IPv6. + let ip: AddrV2 = deserialize(&hex!("02100102030405060708090a0b0c0d0e0f10")).unwrap(); + assert_eq!( + ip, + AddrV2::Ipv6("102:304:506:708:90a:b0c:d0e:f10".parse::().unwrap()) + ); + + // Invalid IPv6, with bogus length. + assert!(deserialize::(&hex!("020400")).is_err()); + + // Invalid IPv6, contains embedded IPv4. + assert!(deserialize::(&hex!("021000000000000000000000ffff01020304")).is_err()); + + // Invalid IPv6, contains embedded TORv2. + assert!(deserialize::(&hex!("0210fd87d87eeb430102030405060708090a")).is_err()); + + // Valid TORv3. + let ip: AddrV2 = deserialize(&hex!( + "042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f" + )) + .unwrap(); + assert_eq!( + ip, + AddrV2::TorV3( + FromHex::from_hex( + "79bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f" + ) + .unwrap() + ) + ); + + // Invalid TORv3, with bogus length. + assert!(deserialize::(&hex!("040000")).is_err()); + + // Valid I2P. + let ip: AddrV2 = deserialize(&hex!( + "0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87" + )) + .unwrap(); + assert_eq!( + ip, + AddrV2::I2p( + FromHex::from_hex( + "a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87" + ) + .unwrap() + ) + ); + + // Invalid I2P, with bogus length. + assert!(deserialize::(&hex!("050300")).is_err()); + + // Valid CJDNS. + let ip: AddrV2 = deserialize(&hex!("0610fc000001000200030004000500060007")).unwrap(); + assert_eq!(ip, AddrV2::Cjdns("fc00:1:2:3:4:5:6:7".parse::().unwrap())); + + // Invalid CJDNS, incorrect marker + assert!(deserialize::(&hex!("0610fd000001000200030004000500060007")).is_err()); + + // Invalid CJDNS, with bogus length. + assert!(deserialize::(&hex!("060100")).is_err()); + + // Unknown, with extreme length. + assert!(deserialize::(&hex!("aafe0000000201020304050607")).is_err()); + + // Unknown, with reasonable length. + let ip: AddrV2 = deserialize(&hex!("aa0401020304")).unwrap(); + assert_eq!(ip, AddrV2::Unknown(170, hex!("01020304").to_vec())); + + // Unknown, with zero length. + let ip: AddrV2 = deserialize(&hex!("aa00")).unwrap(); + assert_eq!(ip, AddrV2::Unknown(170, vec![])); + } + + #[test] + fn addrv2message() { + let raw = hex!("0261bc6649019902abab208d79627683fd4804010409090909208d"); + let addresses: AddrV2Payload = deserialize(&raw).unwrap(); + + assert_eq!( + addresses.0, + vec![ + AddrV2Message { + services: ServiceFlags::NETWORK, + time: 0x4966bc61, + port: 8333, + addr: AddrV2::Unknown(153, hex!("abab").to_vec()) + }, + AddrV2Message { + services: ServiceFlags::NETWORK_LIMITED + | ServiceFlags::WITNESS + | ServiceFlags::COMPACT_FILTERS, + time: 0x83766279, + port: 8333, + addr: AddrV2::Ipv4(Ipv4Addr::new(9, 9, 9, 9)) + }, + ] + ); + + assert_eq!(serialize(&addresses), raw); + } + + #[test] + fn addrv2_to_ipaddr_ipv4() { + let addr = AddrV2::Ipv4(Ipv4Addr::new(192, 168, 1, 1)); + let ip_addr = IpAddr::try_from(addr).unwrap(); + + assert_eq!(ip_addr, IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))); + } + + #[test] + fn addrv2_to_ipaddr_ipv6() { + let addr = AddrV2::Ipv6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); + let ip_addr = IpAddr::try_from(addr).unwrap(); + + assert_eq!(ip_addr, IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1))); + } + + #[test] + fn addrv2_to_ipaddr_cjdns() { + let addr = AddrV2::Cjdns(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 1)); + let result = IpAddr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), UnroutableAddressError::Cjdns); + } + + #[test] + fn addrv2_to_ipaddr_torv3() { + let addr = AddrV2::TorV3([0; 32]); + let result = IpAddr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), UnroutableAddressError::TorV3); + } + + #[test] + fn addrv2_to_ipaddr_i2p() { + let addr = AddrV2::I2p([0; 32]); + let result = IpAddr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), UnroutableAddressError::I2p); + } + + #[test] + fn addrv2_to_ipaddr_unknown() { + let addr = AddrV2::Unknown(42, vec![1, 2, 3, 4]); + let result = IpAddr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), UnroutableAddressError::Unknown); + } + + #[test] + fn addrv2_to_ipv4addr_ipv4() { + let addr = AddrV2::Ipv4(Ipv4Addr::new(192, 168, 1, 1)); + let ip_addr = Ipv4Addr::try_from(addr).unwrap(); + + assert_eq!(ip_addr, Ipv4Addr::new(192, 168, 1, 1)); + } + + #[test] + fn addrv2_to_ipv4addr_ipv6() { + let addr = AddrV2::Ipv6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); + let result = Ipv4Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv4AddrError::Ipv6); + } + + #[test] + fn addrv2_to_ipv4addr_cjdns() { + let addr = AddrV2::Cjdns(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 1)); + let result = Ipv4Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv4AddrError::Cjdns); + } + + #[test] + fn addrv2_to_ipv4addr_torv3() { + let addr = AddrV2::TorV3([0; 32]); + let result = Ipv4Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv4AddrError::TorV3); + } + + #[test] + fn addrv2_to_ipv4addr_i2p() { + let addr = AddrV2::I2p([0; 32]); + let result = Ipv4Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv4AddrError::I2p); + } + + #[test] + fn addrv2_to_ipv4addr_unknown() { + let addr = AddrV2::Unknown(42, vec![1, 2, 3, 4]); + let result = Ipv4Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv4AddrError::Unknown); + } + + #[test] + fn addrv2_to_ipv6addr_ipv4() { + let addr = AddrV2::Ipv4(Ipv4Addr::new(192, 168, 1, 1)); + let result = Ipv6Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv6AddrError::Ipv4); + } + + #[test] + fn addrv2_to_ipv6addr_ipv6() { + let addr = AddrV2::Ipv6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); + let ip_addr = Ipv6Addr::try_from(addr).unwrap(); + + assert_eq!(ip_addr, Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); + } + + #[test] + fn addrv2_to_ipv6addr_cjdns() { + let addr = AddrV2::Cjdns(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 1)); + let result = Ipv6Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv6AddrError::Cjdns); + } + + #[test] + fn addrv2_to_ipv6addr_torv3() { + let addr = AddrV2::TorV3([0; 32]); + let result = Ipv6Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv6AddrError::TorV3); + } + + #[test] + fn addrv2_to_ipv6addr_i2p() { + let addr = AddrV2::I2p([0; 32]); + let result = Ipv6Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv6AddrError::I2p); + } + + #[test] + fn addrv2_to_ipv6addr_unknown() { + let addr = AddrV2::Unknown(42, vec![1, 2, 3, 4]); + let result = Ipv6Addr::try_from(addr); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), AddrV2ToIpv6AddrError::Unknown); + } +} diff --git a/p2p/src/bip152.rs b/p2p/src/bip152.rs new file mode 100644 index 000000000..171ce0479 --- /dev/null +++ b/p2p/src/bip152.rs @@ -0,0 +1,599 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! BIP-0152 Compact Blocks. +//! +//! Implementation of compact blocks data structure and algorithms. + +use alloc::vec::Vec; +use core::convert::Infallible; +use core::{convert, fmt, mem}; +#[cfg(feature = "std")] +use std::error; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::{sha256, siphash24}; +use internals::array::ArrayExt as _; +use internals::ToU64 as _; +use io::{BufRead, Write}; + +use bitcoin::consensus::encode::{self, Decodable, Encodable, ReadExt, WriteExt}; +use bitcoin::transaction::TxIdentifier; +use bitcoin::{block, Block, BlockChecked, BlockHash, Transaction}; + +/// A BIP-0152 error +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// An unknown version number was used. + UnknownVersion, + /// The prefill slice provided was invalid. + InvalidPrefill, +} + +impl From for Error { + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::UnknownVersion => write!(f, "an unknown version number was used"), + Self::InvalidPrefill => write!(f, "the prefill slice provided was invalid"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::UnknownVersion | Self::InvalidPrefill => None, + } + } +} + +/// A [`PrefilledTransaction`] structure is used in [`HeaderAndShortIds`] to +/// provide a list of a few transactions explicitly. +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct PrefilledTransaction { + /// The index of the transaction in the block. + /// + /// This field is differentially encoded relative to the previous + /// prefilled transaction as described as follows: + /// + /// > Several uses of CompactSize below are "differentially encoded". For + /// > these, instead of using raw indexes, the number encoded is the + /// > difference between the current index and the previous index, minus one. + /// > For example, a first index of 0 implies a real index of 0, a second + /// > index of 0 thereafter refers to a real index of 1, etc. + pub idx: u16, + /// The actual transaction. + pub tx: Transaction, +} + +impl convert::AsRef for PrefilledTransaction { + fn as_ref(&self) -> &Transaction { &self.tx } +} + +impl Encodable for PrefilledTransaction { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + Ok(w.emit_compact_size(self.idx)? + self.tx.consensus_encode(w)?) + } +} + +impl Decodable for PrefilledTransaction { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + let idx = r.read_compact_size()?; + let idx = u16::try_from(idx).map_err(|_| { + crate::consensus::parse_failed_error("BIP-0152 prefilled tx index out of bounds") + })?; + let tx = Transaction::consensus_decode(r)?; + Ok(Self { idx, tx }) + } +} + +/// Short transaction IDs are used to represent a transaction without sending a full 256-bit hash. +#[derive(PartialEq, Eq, Clone, Copy, Hash, Default, PartialOrd, Ord)] +pub struct ShortId([u8; 6]); +internals::impl_array_newtype!(ShortId, u8, 6); + +impl ShortId { + /// Calculates the SipHash24 keys used to calculate short IDs. + pub fn calculate_siphash_keys(header: &block::Header, nonce: u64) -> (u64, u64) { + // 1. single-SHA256 hashing the block header with the nonce appended (in little-endian) + let h = { + let mut engine = sha256::Hash::engine(); + header.consensus_encode(&mut engine).expect("engines don't error"); + nonce.consensus_encode(&mut engine).expect("engines don't error"); + sha256::Hash::from_engine(engine) + }; + + // 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) + // set to the first two little-endian 64-bit integers from the above hash, respectively. + ( + u64::from_le_bytes(*h.as_byte_array().sub_array::<0, 8>()), + u64::from_le_bytes(*h.as_byte_array().sub_array::<8, 8>()), + ) + } + + /// Calculates the short ID with the given (w)txid and using the provided SipHash keys. + pub fn with_siphash_keys(txid: &T, siphash_keys: (u64, u64)) -> Self { + // 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) + // set to the first two little-endian 64-bit integers from the above hash, respectively. + let hash = siphash24::Hash::hash_with_keys(siphash_keys.0, siphash_keys.1, txid.as_ref()); + + // 3. Dropping the 2 most significant bytes from the SipHash output to make it 6 bytes. + let mut id = Self([0; 6]); + id.0.copy_from_slice(&hash.as_byte_array()[0..6]); + id + } +} + +impl core::fmt::LowerHex for ShortId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + hex::display::fmt_hex_exact!(f, 6, &self.0, hex::Case::Lower) + } +} + +impl core::fmt::UpperHex for ShortId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + hex::display::fmt_hex_exact!(f, 6, &self.0, hex::Case::Upper) + } +} + +impl core::fmt::Display for ShortId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::LowerHex::fmt(self, f) + } +} + +impl core::fmt::Debug for ShortId { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::LowerHex::fmt(self, f) + } +} + +impl Encodable for ShortId { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) + } +} + +impl Decodable for ShortId { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Ok(Self(Decodable::consensus_decode(r)?)) + } +} + +/// A structure to relay a block header, short IDs, and a select few transactions. +/// +/// A [`HeaderAndShortIds`] structure is used to relay a block header, the short +/// transactions IDs used for matching already-available transactions, and a +/// select few transactions which we expect a peer may be missing. +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct HeaderAndShortIds { + /// The header of the block being provided. + pub header: block::Header, + /// A nonce for use in short transaction ID calculations. + pub nonce: u64, + /// The short transaction IDs calculated from the transactions + /// which were not provided explicitly in prefilled_txs. + pub short_ids: Vec, + /// Used to provide the coinbase transaction and a select few + /// which we expect a peer may be missing. + pub prefilled_txs: Vec, +} + +impl Decodable for HeaderAndShortIds { + fn consensus_decode(r: &mut R) -> Result { + let header_short_ids = Self { + header: Decodable::consensus_decode(r)?, + nonce: Decodable::consensus_decode(r)?, + short_ids: Decodable::consensus_decode(r)?, + prefilled_txs: Decodable::consensus_decode(r)?, + }; + match header_short_ids.short_ids.len().checked_add(header_short_ids.prefilled_txs.len()) { + Some(x) if x <= u16::MAX.into() => Ok(header_short_ids), + _ => Err(crate::consensus::parse_failed_error("indexes overflowed 16 bits")), + } + } +} + +impl Encodable for HeaderAndShortIds { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += self.header.consensus_encode(w)?; + len += self.nonce.consensus_encode(w)?; + len += self.short_ids.consensus_encode(w)?; + len += self.prefilled_txs.consensus_encode(w)?; + Ok(len) + } +} + +impl HeaderAndShortIds { + /// Constructs a new [`HeaderAndShortIds`] from a full block. + /// + /// The version number must be either 1 or 2. + /// + /// The `prefill` slice indicates which transactions should be prefilled in + /// the block. It should contain the indexes in the block of the txs to + /// prefill. It must be ordered. 0 should not be included as the + /// coinbase tx is always prefilled. + /// + /// > Nodes SHOULD NOT use the same nonce across multiple different blocks. + pub fn from_block( + block: &Block, + nonce: u64, + version: u32, + mut prefill: &[usize], + ) -> Result { + if version != 1 && version != 2 { + return Err(Error::UnknownVersion); + } + + let siphash_keys = ShortId::calculate_siphash_keys(block.header(), nonce); + + let mut prefilled = Vec::with_capacity(prefill.len() + 1); // +1 for coinbase tx + let mut short_ids = Vec::with_capacity(block.transactions().len() - prefill.len()); + let mut last_prefill = 0; + for (idx, tx) in block.transactions().iter().enumerate() { + // Check if we should prefill this tx. + let prefill_tx = if prefill.first() == Some(&idx) { + prefill = &prefill[1..]; + true + } else { + idx == 0 // Always prefill coinbase. + }; + + if prefill_tx { + let diff_idx = idx - last_prefill; + last_prefill = idx + 1; + prefilled.push(PrefilledTransaction { + idx: diff_idx as u16, + tx: match version { + // > As encoded in "tx" messages sent in response to getdata MSG_TX + 1 => { + // strip witness for version 1 + let mut no_witness = tx.clone(); + no_witness.inputs.iter_mut().for_each(|i| i.witness.clear()); + no_witness + } + // > Transactions inside cmpctblock messages (both those used as direct + // > announcement and those in response to getdata) and in blocktxn should + // > include witness data, using the same format as responses to getdata + // > MSG_WITNESS_TX, specified in BIP-0144. + 2 => tx.clone(), + _ => unreachable!(), + }, + }); + } else { + match version { + 1 => + short_ids.push(ShortId::with_siphash_keys(&tx.compute_txid(), siphash_keys)), + 2 => short_ids + .push(ShortId::with_siphash_keys(&tx.compute_wtxid(), siphash_keys)), + _ => unreachable!(), + } + } + } + + if !prefill.is_empty() { + return Err(Error::InvalidPrefill); + } + + Ok(Self { + header: *block.header(), + nonce, + // Provide coinbase prefilled. + prefilled_txs: prefilled, + short_ids, + }) + } +} + +/// A [`BlockTransactionsRequest`] structure is used to list transaction indexes +/// in a block being requested. +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct BlockTransactionsRequest { + /// The blockhash of the block which the transactions being requested are in. + pub block_hash: BlockHash, + /// The indexes of the transactions being requested in the block. + /// + /// Warning: Encoding panics with [`u64::MAX`] values. See [`BlockTransactionsRequest::consensus_encode()`] + pub indexes: Vec, +} + +impl Encodable for BlockTransactionsRequest { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = self.block_hash.consensus_encode(w)?; + // Manually encode indexes because they are differentially encoded as CompactSize. + len += w.emit_compact_size(self.indexes.len())?; + let mut last_idx = 0; + for idx in &self.indexes { + len += w.emit_compact_size(*idx - last_idx)?; + last_idx = *idx + 1; // can panic here + } + Ok(len) + } +} + +impl Decodable for BlockTransactionsRequest { + fn consensus_decode(r: &mut R) -> Result { + Ok(Self { + block_hash: BlockHash::consensus_decode(r)?, + indexes: { + // Manually decode indexes because they are differentially encoded as CompactSize. + let nb_indexes = r.read_compact_size()? as usize; + + // Since the number of indices ultimately represent transactions, + // we can limit the number of indices to the maximum number of + // transactions that would be allowed in a vector. + let byte_size = nb_indexes + .checked_mul(mem::size_of::()) + .ok_or(crate::consensus::parse_failed_error("invalid length"))?; + if byte_size > encode::MAX_VEC_SIZE { + return Err(encode::ParseError::OversizedVectorAllocation { + requested: byte_size, + max: encode::MAX_VEC_SIZE, + } + .into()); + } + + let mut indexes = Vec::with_capacity(nb_indexes); + let mut last_index: u64 = 0; + for _ in 0..nb_indexes { + let differential = r.read_compact_size()?; + last_index = match last_index.checked_add(differential) { + Some(i) => i, + None => return Err(crate::consensus::parse_failed_error("block index overflow")), + }; + indexes.push(last_index); + last_index = match last_index.checked_add(1) { + Some(i) => i, + None => return Err(crate::consensus::parse_failed_error("block index overflow")), + }; + } + indexes + }, + }) + } +} + +/// A transaction index is requested that is out of range from the +/// corresponding block. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct TxIndexOutOfRangeError(u64); + +impl fmt::Display for TxIndexOutOfRangeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "a transaction index is requested that is \ + out of range from the corresponding block: {}", + self.0, + ) + } +} + +#[cfg(feature = "std")] +impl error::Error for TxIndexOutOfRangeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// A [`BlockTransactions`] structure is used to provide some of the transactions +/// in a block, as requested. +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct BlockTransactions { + /// The blockhash of the block which the transactions being provided are in. + pub block_hash: BlockHash, + /// The transactions provided. + pub transactions: Vec, +} +crate::consensus::impl_consensus_encoding!(BlockTransactions, block_hash, transactions); + +impl BlockTransactions { + /// Constructs a new [`BlockTransactions`] from a [`BlockTransactionsRequest`] and + /// the corresponding full [`Block`] by providing all requested transactions. + pub fn from_request( + request: &BlockTransactionsRequest, + block: &Block, + ) -> Result { + Ok(Self { + block_hash: request.block_hash, + transactions: { + let mut txs = Vec::with_capacity(request.indexes.len()); + for idx in &request.indexes { + if *idx >= block.transactions().len().to_u64() { + return Err(TxIndexOutOfRangeError(*idx)); + } + txs.push(block.transactions()[*idx as usize].clone()); + } + txs + }, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for ShortId { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for PrefilledTransaction { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { idx: u.arbitrary()?, tx: u.arbitrary()? }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for HeaderAndShortIds { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + header: u.arbitrary()?, + nonce: u.arbitrary()?, + short_ids: Vec::::arbitrary(u)?, + prefilled_txs: Vec::::arbitrary(u)?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for BlockTransactions { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + block_hash: u.arbitrary()?, + transactions: Vec::::arbitrary(u)?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for BlockTransactionsRequest { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + block_hash: u.arbitrary()?, + indexes: Vec::::arbitrary(u)?, + }) + } +} + +#[cfg(test)] +mod test { + use alloc::vec; + use hex::FromHex; + + use super::*; + use bitcoin::consensus::encode::{deserialize, serialize}; + use bitcoin::locktime::absolute; + use bitcoin::merkle_tree::TxMerkleNode; + use bitcoin::transaction::OutPointExt; + use bitcoin::{ + transaction, Amount, BlockChecked, BlockTime, CompactTarget, OutPoint, ScriptPubKeyBuf, + ScriptSigBuf, Sequence, TxIn, TxOut, Txid, Witness, + }; + + fn dummy_tx(nonce: &[u8]) -> Transaction { + let dummy_txid = Txid::from_byte_array(hashes::sha256::Hash::hash(nonce).to_byte_array()); + Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::from_consensus(2), + inputs: vec![TxIn { + previous_output: OutPoint::new(dummy_txid, 0), + script_sig: ScriptSigBuf::new(), + sequence: Sequence(1), + witness: Witness::new(), + }], + outputs: vec![TxOut { amount: Amount::ONE_SAT, script_pubkey: ScriptPubKeyBuf::new() }], + } + } + + fn dummy_block() -> Block { + let header = block::Header { + version: block::Version::ONE, + prev_blockhash: BlockHash::from_byte_array([0x99; 32]), + merkle_root: TxMerkleNode::from_byte_array([0x77; 32]), + time: BlockTime::from_u32(2), + bits: CompactTarget::from_consensus(3), + nonce: 4, + }; + let transactions = vec![dummy_tx(&[2]), dummy_tx(&[3]), dummy_tx(&[4])]; + Block::new_unchecked(header, transactions).assume_checked(None) + } + + #[test] + fn header_and_short_ids_from_block() { + let block = dummy_block(); + + let compact = HeaderAndShortIds::from_block(&block, 42, 2, &[]).unwrap(); + assert_eq!(compact.nonce, 42); + assert_eq!(compact.short_ids.len(), 2); + assert_eq!(compact.prefilled_txs.len(), 1); + assert_eq!(compact.prefilled_txs[0].idx, 0); + assert_eq!(&compact.prefilled_txs[0].tx, &block.transactions()[0]); + + let compact = HeaderAndShortIds::from_block(&block, 42, 2, &[0, 1, 2]).unwrap(); + let idxs = compact.prefilled_txs.iter().map(|t| t.idx).collect::>(); + assert_eq!(idxs, [0, 0, 0]); + + let compact = HeaderAndShortIds::from_block(&block, 42, 2, &[2]).unwrap(); + let idxs = compact.prefilled_txs.iter().map(|t| t.idx).collect::>(); + assert_eq!(idxs, [0, 1]); + } + + #[test] + fn compact_block_vector() { + // Tested with Elements implementation of compact blocks. + let raw_block = Vec::::from_hex("000000206c750a364035aefd5f81508a08769975116d9195312ee4520dceac39e1fdc62c4dc67473b8e354358c1e610afeaff7410858bd45df43e2940f8a62bd3d5e3ac943c2975cffff7f200000000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04016b0101ffffffff020006062a0100000001510000000000000000266a24aa21a9ed4a3d9f3343dafcc0d6f6d4310f2ee5ce273ed34edca6c75db3a73e7f368734200120000000000000000000000000000000000000000000000000000000000000000000000000020000000001021fc20ba2bd745507b8e00679e3b362558f9457db374ca28ffa5243f4c23a4d5f00000000171600147c9dea14ffbcaec4b575e03f05ceb7a81cd3fcbffdffffff915d689be87b43337f42e26033df59807b768223368f189a023d0242d837768900000000171600147c9dea14ffbcaec4b575e03f05ceb7a81cd3fcbffdffffff0200cdf5050000000017a9146803c72d9154a6a20f404bed6d3dcee07986235a8700e1f5050000000017a9144e6a4c7cb5b5562904843bdf816342f4db9f5797870247304402205e9bf6e70eb0e4b495bf483fd8e6e02da64900f290ef8aaa64bb32600d973c450220670896f5d0e5f33473e5f399ab680cc1d25c2d2afd15abd722f04978f28be887012103e4e4d9312b2261af508b367d8ba9be4f01b61d6d6e78bec499845b4f410bcf2702473044022045ac80596a6ac9c8c572f94708709adaf106677221122e08daf8b9741a04f66a022003ccd52a3b78f8fd08058fc04fc0cffa5f4c196c84eae9e37e2a85babe731b57012103e4e4d9312b2261af508b367d8ba9be4f01b61d6d6e78bec499845b4f410bcf276a000000").unwrap(); + let raw_compact = Vec::::from_hex("000000206c750a364035aefd5f81508a08769975116d9195312ee4520dceac39e1fdc62c4dc67473b8e354358c1e610afeaff7410858bd45df43e2940f8a62bd3d5e3ac943c2975cffff7f2000000000a4df3c3744da89fa010a6979e971450100020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04016b0101ffffffff020006062a0100000001510000000000000000266a24aa21a9ed4a3d9f3343dafcc0d6f6d4310f2ee5ce273ed34edca6c75db3a73e7f368734200120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + + let block: Block = deserialize(&raw_block).unwrap(); + let block = block.assume_checked(None); + let nonce = 18053200567810711460; + let compact = HeaderAndShortIds::from_block(&block, nonce, 2, &[]).unwrap(); + let compact_expected = deserialize(&raw_compact).unwrap(); + + assert_eq!(compact, compact_expected); + } + + #[test] + fn getblocktx_differential_encoding_de_and_serialization() { + let testcases = vec![ + // differentially encoded CompactSizes, indices + (vec![4, 0, 5, 1, 10], vec![0, 6, 8, 19]), + (vec![1, 0], vec![0]), + (vec![5, 0, 0, 0, 0, 0], vec![0, 1, 2, 3, 4]), + (vec![3, 1, 1, 1], vec![1, 3, 5]), + (vec![3, 0, 0, 253, 0, 1], vec![0, 1, 258]), // .., 253, 0, 1] == CompactSize(256) + ]; + let deser_errorcases = vec![ + vec![2, 255, 254, 255, 255, 255, 255, 255, 255, 255, 0], // .., 255, 254, .., 255] == CompactSize(u64::MAX-1) + vec![1, 255, 255, 255, 255, 255, 255, 255, 255, 255], // .., 255, 255, .., 255] == CompactSize(u64::MAX) + ]; + for testcase in testcases { + { + // test deserialization + let mut raw: Vec = vec![0u8; 32]; + raw.extend(testcase.0.clone()); + let btr: BlockTransactionsRequest = deserialize(&raw.to_vec()).unwrap(); + assert_eq!(testcase.1, btr.indexes); + } + { + // test serialization + let raw: Vec = serialize(&BlockTransactionsRequest { + block_hash: BlockHash::from_byte_array([0; 32]), + indexes: testcase.1, + }); + let mut expected_raw: Vec = [0u8; 32].to_vec(); + expected_raw.extend(testcase.0); + assert_eq!(expected_raw, raw); + } + } + for errorcase in deser_errorcases { + { + // test that we return Err() if deserialization fails (and don't panic) + let mut raw: Vec = [0u8; 32].to_vec(); + raw.extend(errorcase); + assert!(deserialize::(&raw.to_vec()).is_err()); + } + } + } + + #[test] + #[cfg(debug_assertions)] + #[should_panic] // 'attempt to add with overflow' in consensus_encode() + fn getblocktx_panic_when_encoding_u64_max() { + serialize(&BlockTransactionsRequest { + block_hash: BlockHash::from_byte_array([0; 32]), + indexes: vec![u64::MAX], + }); + } +} diff --git a/p2p/src/consensus.rs b/p2p/src/consensus.rs new file mode 100644 index 000000000..5bc377d72 --- /dev/null +++ b/p2p/src/consensus.rs @@ -0,0 +1,101 @@ +#[cfg(feature = "std")] +use bitcoin::consensus::encode::WriteExt; +#[cfg(feature = "std")] +use io::Write; + +#[cfg(feature = "std")] +pub(crate) fn consensus_encode_with_size( + data: &[u8], + w: &mut W, +) -> Result { + Ok(w.emit_compact_size(data.len())? + w.emit_slice(data)?) +} + +pub(crate) fn parse_failed_error(msg: &'static str) -> bitcoin::consensus::encode::Error { + bitcoin::consensus::encode::Error::Parse(bitcoin::consensus::encode::ParseError::ParseFailed( + msg, + )) +} + +macro_rules! impl_consensus_encoding { + ($thing:ident, $($field:ident),+) => ( + impl bitcoin::consensus::Encodable for $thing { + #[inline] + fn consensus_encode( + &self, + w: &mut W, + ) -> core::result::Result { + let mut len = 0; + $(len += self.$field.consensus_encode(w)?;)+ + Ok(len) + } + } + + impl bitcoin::consensus::Decodable for $thing { + + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> core::result::Result<$thing, bitcoin::consensus::encode::Error> { + Ok($thing { + $($field: bitcoin::consensus::Decodable::consensus_decode_from_finite_reader(r)?),+ + }) + } + + #[inline] + fn consensus_decode( + r: &mut R, + ) -> core::result::Result<$thing, bitcoin::consensus::encode::Error> { + let mut r = io::Read::take(r, internals::ToU64::to_u64(bitcoin::consensus::encode::MAX_VEC_SIZE)); + Ok($thing { + $($field: bitcoin::consensus::Decodable::consensus_decode(&mut r)?),+ + }) + } + } + ); +} +pub(crate) use impl_consensus_encoding; + +#[cfg(feature = "std")] +macro_rules! impl_vec_wrapper { + ($wrapper: ident, $type: ty) => { + impl bitcoin::consensus::encode::Encodable for $wrapper { + #[inline] + fn consensus_encode( + &self, + w: &mut W, + ) -> core::result::Result { + let mut len = 0; + len += w.emit_compact_size(self.0.len())?; + for c in self.0.iter() { + len += c.consensus_encode(w)?; + } + Ok(len) + } + } + + impl bitcoin::consensus::encode::Decodable for $wrapper { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> core::result::Result<$wrapper, bitcoin::consensus::encode::Error> { + let len = r.read_compact_size()?; + // Limit the initial vec allocation to at most 8,000 bytes, which is + // sufficient for most use cases. We don't allocate more space upfront + // than this, since `len` is an untrusted allocation capacity. If the + // vector does overflow the initial capacity `push` will just reallocate. + // Note: OOM protection relies on reader eventually running out of + // data to feed us. + let max_init_capacity = 8000 / core::mem::size_of::<$type>(); + let mut ret = Vec::with_capacity(core::cmp::min(len as usize, max_init_capacity)); + for _ in 0..len { + ret.push(Decodable::consensus_decode_from_finite_reader(r)?); + } + Ok($wrapper(ret)) + } + } + }; +} + +#[cfg(feature = "std")] +pub(crate) use impl_vec_wrapper; diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs new file mode 100644 index 000000000..3a2918aa9 --- /dev/null +++ b/p2p/src/lib.rs @@ -0,0 +1,595 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Rust Bitcoin Peer to Peer Message Types + +#![no_std] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Pedantic lints that we enforce. +#![warn(clippy::return_self_not_must_use)] +// Exclude lints we don't think are valuable. +#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +#![allow(clippy::manual_range_contains)] // More readable than clippy's format. +#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")` + +mod consensus; +mod network_ext; + +#[cfg(feature = "std")] +pub mod address; +pub mod bip152; +#[cfg(feature = "std")] +pub mod message; +pub mod message_blockdata; +pub mod message_bloom; +pub mod message_compact_blocks; +pub mod message_filter; +#[cfg(feature = "std")] +pub mod message_network; + +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +use alloc::borrow::ToOwned; +use alloc::string::String; +use core::borrow::{Borrow, BorrowMut}; +use core::str::FromStr; +use core::{fmt, ops}; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::consensus::encode::{self, Decodable, Encodable}; +use bitcoin::network::{Network, Params, TestnetVersion}; +use hex::FromHex; +use internals::impl_to_hex_from_lower_hex; +use io::{BufRead, Write}; + +#[rustfmt::skip] +#[doc(inline)] +pub use self::network_ext::NetworkExt; + +#[cfg(feature = "std")] +#[rustfmt::skip] +#[doc(inline)] +pub use self::{address::Address, message::CheckedData}; + +/// Version of the protocol as appearing in network version handshakes and some message headers. +/// +/// This constant is used to signal to other peers which features you support. Increasing it implies +/// that your software also supports every feature prior to this version. Doing so without support +/// may lead to you incorrectly banning other peers or other peers banning you. +/// +/// These are the features required for each version: +/// 70016 - Support receiving `wtxidrelay` message between `version` and `verack` message +/// 70015 - Support receiving invalid compact blocks from a peer without banning them +/// 70014 - Support compact block messages `sendcmpct`, `cmpctblock`, `getblocktxn` and `blocktxn` +/// 70013 - Support `feefilter` message +/// 70012 - Support `sendheaders` message and announce new blocks via headers rather than inv +/// 70011 - Support NODE_BLOOM service flag and don't support bloom filter messages if it is not set +/// 70002 - Support `reject` message +/// 70001 - Support bloom filter messages `filterload`, `filterclear` `filteradd`, `merkleblock` and FILTERED_BLOCK inventory type +/// 60002 - Support `mempool` message +/// 60001 - Support `pong` message and nonce in `ping` message +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ProtocolVersion(u32); + +impl ProtocolVersion { + /// Support receiving `wtxidrelay` message between `version` and `verack` message + pub const WTXID_RELAY_VERSION: Self = Self(70016); + /// Support receiving invalid compact blocks from a peer without banning them + pub const INVALID_CB_NO_BAN_VERSION: Self = Self(70015); + /// Support compact block messages `sendcmpct`, `cmpctblock`, `getblocktxn` and `blocktxn` + pub const SHORT_IDS_BLOCKS_VERSION: Self = Self(70014); + /// Support `feefilter` message + pub const FEEFILTER_VERSION: Self = Self(70013); + /// Support `sendheaders` message and announce new blocks via headers rather than inv + pub const SENDHEADERS_VERSION: Self = Self(70012); + /// Support `pong` message and nonce in `ping` message + pub const BIP0031_VERSION: Self = Self(60001); + /// All connections will be terminated below this version. + pub const MIN_PEER_PROTO_VERSION: Self = Self(31800); +} + +impl ProtocolVersion { + /// Constructs a protocol version that is not well-known. + pub fn from_nonstandard(version: u32) -> Self { Self(version) } +} + +impl From for u32 { + fn from(version: ProtocolVersion) -> Self { version.0 } +} + +impl Encodable for ProtocolVersion { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) + } +} + +impl Decodable for ProtocolVersion { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Ok(Self(Decodable::consensus_decode(r)?)) + } +} + +/// Flags to indicate which network services a node supports. +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ServiceFlags(u64); + +impl ServiceFlags { + /// NONE means no services supported. + pub const NONE: Self = Self(0); + + /// NETWORK means that the node is capable of serving the complete block chain. It is currently + /// set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light + /// clients. + pub const NETWORK: Self = Self(1 << 0); + + /// GETUTXO means the node is capable of responding to the getutxo protocol request. Bitcoin + /// Core does not support this but a patch set called Bitcoin XT does. + /// See BIP-0064 for details on how this is implemented. + pub const GETUTXO: Self = Self(1 << 1); + + /// BLOOM means the node is capable and willing to handle bloom-filtered connections. Bitcoin + /// Core nodes used to support this by default, without advertising this bit, but no longer do + /// as of protocol version 70011 (= NO_BLOOM_VERSION) + pub const BLOOM: Self = Self(1 << 2); + + /// WITNESS indicates that a node can be asked for blocks and transactions including witness + /// data. + pub const WITNESS: Self = Self(1 << 3); + + /// COMPACT_FILTERS means the node will service basic block filter requests. + /// See BIP-0157 and BIP-0158 for details on how this is implemented. + pub const COMPACT_FILTERS: Self = Self(1 << 6); + + /// NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only serving the last + /// 288 (2 day) blocks. + /// See BIP-0159 for details on how this is implemented. + pub const NETWORK_LIMITED: Self = Self(1 << 10); + + /// P2P_V2 indicates that the node supports the P2P v2 encrypted transport protocol. + /// See BIP-0324 for details on how this is implemented. + pub const P2P_V2: Self = Self(1 << 11); + + // NOTE: When adding new flags, remember to update the Display impl accordingly. + + /// Add [ServiceFlags] together. + /// + /// Returns itself. + #[must_use] + pub fn add(&mut self, other: Self) -> Self { + self.0 |= other.0; + *self + } + + /// Removes [ServiceFlags] from this. + /// + /// Returns itself. + #[must_use] + pub fn remove(&mut self, other: Self) -> Self { + self.0 &= !other.0; + *self + } + + /// Checks whether [ServiceFlags] are included in this one. + pub fn has(self, flags: Self) -> bool { (self.0 | flags.0) == self.0 } + + /// Gets the integer representation of this [`ServiceFlags`]. + pub fn to_u64(self) -> u64 { self.0 } +} + +impl fmt::LowerHex for ServiceFlags { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } +} +impl_to_hex_from_lower_hex!(ServiceFlags, |service_flags: &ServiceFlags| 16 + - service_flags.0.leading_zeros() as usize / 4); + +impl fmt::UpperHex for ServiceFlags { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } +} + +impl fmt::Display for ServiceFlags { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut flags = *self; + if flags == Self::NONE { + return write!(f, "ServiceFlags(NONE)"); + } + let mut first = true; + macro_rules! write_flag { + ($f:ident) => { + if flags.has(ServiceFlags::$f) { + if !first { + write!(f, "|")?; + } + first = false; + write!(f, stringify!($f))?; + let _ = flags.remove(ServiceFlags::$f); + } + }; + } + write!(f, "ServiceFlags(")?; + write_flag!(NETWORK); + write_flag!(GETUTXO); + write_flag!(BLOOM); + write_flag!(WITNESS); + write_flag!(COMPACT_FILTERS); + write_flag!(NETWORK_LIMITED); + write_flag!(P2P_V2); + // If there are unknown flags left, we append them in hex. + if flags != Self::NONE { + if !first { + write!(f, "|")?; + } + write!(f, "0x{:x}", flags)?; + } + write!(f, ")") + } +} + +impl From for ServiceFlags { + fn from(f: u64) -> Self { Self(f) } +} + +impl From for u64 { + fn from(flags: ServiceFlags) -> Self { flags.0 } +} + +impl ops::BitOr for ServiceFlags { + type Output = Self; + + fn bitor(mut self, rhs: Self) -> Self { self.add(rhs) } +} + +impl ops::BitOrAssign for ServiceFlags { + fn bitor_assign(&mut self, rhs: Self) { let _ = self.add(rhs); } +} + +impl ops::BitXor for ServiceFlags { + type Output = Self; + + fn bitxor(mut self, rhs: Self) -> Self { self.remove(rhs) } +} + +impl ops::BitXorAssign for ServiceFlags { + fn bitxor_assign(&mut self, rhs: Self) { let _ = self.remove(rhs); } +} + +impl Encodable for ServiceFlags { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) + } +} + +impl Decodable for ServiceFlags { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Ok(Self(Decodable::consensus_decode(r)?)) + } +} +/// Network magic bytes to identify the cryptocurrency network the message was intended for. +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] +pub struct Magic([u8; 4]); + +impl Magic { + /// Bitcoin mainnet network magic bytes. + pub const BITCOIN: Self = Self([0xF9, 0xBE, 0xB4, 0xD9]); + /// Bitcoin testnet3 network magic bytes. + pub const TESTNET3: Self = Self([0x0B, 0x11, 0x09, 0x07]); + /// Bitcoin testnet4 network magic bytes. + pub const TESTNET4: Self = Self([0x1c, 0x16, 0x3f, 0x28]); + /// Bitcoin signet network magic bytes. + pub const SIGNET: Self = Self([0x0A, 0x03, 0xCF, 0x40]); + /// Bitcoin regtest network magic bytes. + pub const REGTEST: Self = Self([0xFA, 0xBF, 0xB5, 0xDA]); + + /// Constructs a new network magic from bytes. + pub const fn from_bytes(bytes: [u8; 4]) -> Self { Self(bytes) } + + /// Gets network magic bytes. + pub fn to_bytes(self) -> [u8; 4] { self.0 } + + /// Returns the magic bytes for the network defined by `params`. + pub fn from_params(params: impl AsRef) -> Option { + params.as_ref().network.try_into().ok() + } +} + +impl FromStr for Magic { + type Err = ParseMagicError; + + fn from_str(s: &str) -> Result { + match <[u8; 4]>::from_hex(s) { + Ok(magic) => Ok(Self::from_bytes(magic)), + Err(e) => Err(ParseMagicError { error: e, magic: s.to_owned() }), + } + } +} + +impl TryFrom for Magic { + type Error = UnknownNetworkError; + + fn try_from(network: Network) -> Result { + match network { + Network::Bitcoin => Ok(Self::BITCOIN), + Network::Testnet(TestnetVersion::V3) => Ok(Self::TESTNET3), + Network::Testnet(TestnetVersion::V4) => Ok(Self::TESTNET4), + Network::Signet => Ok(Self::SIGNET), + Network::Regtest => Ok(Self::REGTEST), + _ => Err(UnknownNetworkError(network)), + } + } +} + +impl TryFrom for Network { + type Error = UnknownMagicError; + + fn try_from(magic: Magic) -> Result { + match magic { + Magic::BITCOIN => Ok(Self::Bitcoin), + Magic::TESTNET3 => Ok(Self::Testnet(TestnetVersion::V3)), + Magic::TESTNET4 => Ok(Self::Testnet(TestnetVersion::V4)), + Magic::SIGNET => Ok(Self::Signet), + Magic::REGTEST => Ok(Self::Regtest), + _ => Err(UnknownMagicError(magic)), + } + } +} + +impl fmt::Display for Magic { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?; + Ok(()) + } +} + +impl fmt::Debug for Magic { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Display::fmt(self, f) } +} + +impl fmt::LowerHex for Magic { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?; + Ok(()) + } +} +impl_to_hex_from_lower_hex!(Magic, |_| 8); + +impl fmt::UpperHex for Magic { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Upper)?; + Ok(()) + } +} + +impl Encodable for Magic { + fn consensus_encode(&self, writer: &mut W) -> Result { + self.0.consensus_encode(writer) + } +} + +impl Decodable for Magic { + fn consensus_decode(reader: &mut R) -> Result { + Ok(Self(Decodable::consensus_decode(reader)?)) + } +} + +impl AsRef<[u8]> for Magic { + fn as_ref(&self) -> &[u8] { &self.0 } +} + +impl AsRef<[u8; 4]> for Magic { + fn as_ref(&self) -> &[u8; 4] { &self.0 } +} + +impl AsMut<[u8]> for Magic { + fn as_mut(&mut self) -> &mut [u8] { &mut self.0 } +} + +impl AsMut<[u8; 4]> for Magic { + fn as_mut(&mut self) -> &mut [u8; 4] { &mut self.0 } +} + +impl Borrow<[u8]> for Magic { + fn borrow(&self) -> &[u8] { &self.0 } +} + +impl Borrow<[u8; 4]> for Magic { + fn borrow(&self) -> &[u8; 4] { &self.0 } +} + +impl BorrowMut<[u8]> for Magic { + fn borrow_mut(&mut self) -> &mut [u8] { &mut self.0 } +} + +impl BorrowMut<[u8; 4]> for Magic { + fn borrow_mut(&mut self) -> &mut [u8; 4] { &mut self.0 } +} + +/// An error in parsing magic bytes. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct ParseMagicError { + /// The error that occurred when parsing the string. + error: hex::HexToArrayError, + /// The byte string that failed to parse. + magic: String, +} + +impl fmt::Display for ParseMagicError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "failed to parse {} as network magic", self.magic) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ParseMagicError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.error) } +} + +/// Error in creating a Network from Magic bytes. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UnknownMagicError(Magic); + +impl fmt::Display for UnknownMagicError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "unknown network magic {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnknownMagicError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// Error in creating a Magic from a Network. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct UnknownNetworkError(Network); + +impl fmt::Display for UnknownNetworkError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "unknown network {}", self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for UnknownNetworkError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for ProtocolVersion { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for ServiceFlags { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Magic { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { Ok(Self(u.arbitrary()?)) } +} + +#[cfg(test)] +mod tests { + use alloc::string::ToString; + + use bitcoin::consensus::encode::{deserialize, serialize}; + + use super::*; + + #[test] + fn serialize_deserialize() { + assert_eq!(serialize(&Magic::BITCOIN), &[0xf9, 0xbe, 0xb4, 0xd9]); + let magic: Magic = Network::Bitcoin.try_into().unwrap(); + assert_eq!(serialize(&magic), &[0xf9, 0xbe, 0xb4, 0xd9]); + assert_eq!(serialize(&Magic::TESTNET3), &[0x0b, 0x11, 0x09, 0x07]); + let magic: Magic = Network::Testnet(TestnetVersion::V3).try_into().unwrap(); + assert_eq!(serialize(&magic), &[0x0b, 0x11, 0x09, 0x07]); + assert_eq!(serialize(&Magic::TESTNET4), &[0x1c, 0x16, 0x3f, 0x28]); + let magic: Magic = Network::Testnet(TestnetVersion::V4).try_into().unwrap(); + assert_eq!(serialize(&magic), &[0x1c, 0x16, 0x3f, 0x28]); + assert_eq!(serialize(&Magic::SIGNET), &[0x0a, 0x03, 0xcf, 0x40]); + let magic: Magic = Network::Signet.try_into().unwrap(); + assert_eq!(serialize(&magic), &[0x0a, 0x03, 0xcf, 0x40]); + assert_eq!(serialize(&Magic::REGTEST), &[0xfa, 0xbf, 0xb5, 0xda]); + let magic: Magic = Network::Regtest.try_into().unwrap(); + assert_eq!(serialize(&magic), &[0xfa, 0xbf, 0xb5, 0xda]); + + assert_eq!( + deserialize::(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), + Network::Bitcoin.try_into().ok() + ); + assert_eq!( + deserialize::(&[0x0b, 0x11, 0x09, 0x07]).ok(), + Network::Testnet(TestnetVersion::V3).try_into().ok() + ); + assert_eq!( + deserialize::(&[0x1c, 0x16, 0x3f, 0x28]).ok(), + Network::Testnet(TestnetVersion::V4).try_into().ok() + ); + assert_eq!( + deserialize::(&[0x0a, 0x03, 0xcf, 0x40]).ok(), + Network::Signet.try_into().ok() + ); + assert_eq!( + deserialize::(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), + Network::Regtest.try_into().ok() + ); + } + + #[test] + fn service_flags_test() { + let all = [ + ServiceFlags::NETWORK, + ServiceFlags::GETUTXO, + ServiceFlags::BLOOM, + ServiceFlags::WITNESS, + ServiceFlags::COMPACT_FILTERS, + ServiceFlags::NETWORK_LIMITED, + ServiceFlags::P2P_V2, + ]; + + let mut flags = ServiceFlags::NONE; + for f in all.iter() { + assert!(!flags.has(*f)); + } + + flags |= ServiceFlags::WITNESS; + assert_eq!(flags, ServiceFlags::WITNESS); + + let mut flags2 = flags | ServiceFlags::GETUTXO; + for f in all.iter() { + assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO); + } + + flags2 ^= ServiceFlags::WITNESS; + assert_eq!(flags2, ServiceFlags::GETUTXO); + + flags2 |= ServiceFlags::COMPACT_FILTERS; + flags2 ^= ServiceFlags::GETUTXO; + assert_eq!(flags2, ServiceFlags::COMPACT_FILTERS); + + // Test formatting. + assert_eq!("ServiceFlags(NONE)", ServiceFlags::NONE.to_string()); + assert_eq!("ServiceFlags(WITNESS)", ServiceFlags::WITNESS.to_string()); + assert_eq!("ServiceFlags(P2P_V2)", ServiceFlags::P2P_V2.to_string()); + let flag = ServiceFlags::WITNESS + | ServiceFlags::BLOOM + | ServiceFlags::NETWORK + | ServiceFlags::P2P_V2; + assert_eq!("ServiceFlags(NETWORK|BLOOM|WITNESS|P2P_V2)", flag.to_string()); + let flag = ServiceFlags::WITNESS | 0xf0.into(); + assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string()); + } + + #[test] + fn magic_from_str() { + let known_network_magic_strs = [ + ("f9beb4d9", Network::Bitcoin), + ("0b110907", Network::Testnet(TestnetVersion::V3)), + ("1c163f28", Network::Testnet(TestnetVersion::V4)), + ("fabfb5da", Network::Regtest), + ("0a03cf40", Network::Signet), + ]; + + for (magic_str, network) in &known_network_magic_strs { + let magic: Magic = magic_str.parse::().unwrap(); + assert_eq!(Network::try_from(magic).unwrap(), *network); + assert_eq!(&magic.to_string(), magic_str); + } + } +} diff --git a/p2p/src/message.rs b/p2p/src/message.rs new file mode 100644 index 000000000..84be65162 --- /dev/null +++ b/p2p/src/message.rs @@ -0,0 +1,2120 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin network messages. +//! +//! This module defines the `NetworkMessage` and `RawNetworkMessage` types that +//! are used for (de)serializing Bitcoin objects for transmission on the network. + +use alloc::borrow::{Cow, ToOwned}; +use alloc::boxed::Box; +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; +use core::{cmp, fmt}; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::consensus::encode::{self, Decodable, Encodable, ReadExt, WriteExt}; +use bitcoin::merkle_tree::MerkleBlock; +use bitcoin::{block, transaction}; +use encoding; +use hashes::sha256d; +use internals::ToU64 as _; +use io::{self, BufRead, Read, Write}; +use units::FeeRate; + +use crate::address::{AddrV2Message, Address}; +use crate::consensus::{impl_consensus_encoding, impl_vec_wrapper}; +use crate::{ + message_blockdata, message_bloom, message_compact_blocks, message_filter, message_network, + Magic, +}; + +/// The maximum number of [super::message_blockdata::Inventory] items in an `inv` message. +/// +/// This limit is not currently enforced by this implementation. +pub const MAX_INV_SIZE: usize = 50_000; + +/// Maximum size, in bytes, of an encoded message +/// This by necessity should be larger than `MAX_VEC_SIZE` +pub const MAX_MSG_SIZE: usize = 5_000_000; + +/// Serializer for command string +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct CommandString(Cow<'static, str>); + +impl CommandString { + /// Converts `&'static str` to `CommandString` + /// + /// This is more efficient for string literals than non-static conversions because it avoids + /// allocation. + /// + /// # Errors + /// + /// Returns an error if, and only if, the string is + /// larger than 12 characters in length. + pub fn try_from_static(s: &'static str) -> Result { + Self::try_from_static_cow(s.into()) + } + + fn try_from_static_cow(cow: Cow<'static, str>) -> Result { + if cow.len() > 12 { + Err(CommandStringError { cow }) + } else { + Ok(Self(cow)) + } + } +} + +impl TryFrom for CommandString { + type Error = CommandStringError; + + fn try_from(value: String) -> Result { + Self::try_from_static_cow(value.into()) + } +} + +impl TryFrom> for CommandString { + type Error = CommandStringError; + + fn try_from(value: Box) -> Result { + Self::try_from_static_cow(String::from(value).into()) + } +} + +impl<'a> TryFrom<&'a str> for CommandString { + type Error = CommandStringError; + + fn try_from(value: &'a str) -> Result { + Self::try_from_static_cow(value.to_owned().into()) + } +} + +impl core::str::FromStr for CommandString { + type Err = CommandStringError; + + fn from_str(s: &str) -> Result { + Self::try_from_static_cow(s.to_owned().into()) + } +} + +impl fmt::Display for CommandString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.0.as_ref()) } +} + +impl AsRef for CommandString { + fn as_ref(&self) -> &str { self.0.as_ref() } +} + +impl Encodable for CommandString { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + let mut rawbytes = [0u8; 12]; + let strbytes = self.0.as_bytes(); + debug_assert!(strbytes.len() <= 12); + rawbytes[..strbytes.len()].copy_from_slice(strbytes); + rawbytes.consensus_encode(w) + } +} + +impl Decodable for CommandString { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + let rawbytes: [u8; 12] = Decodable::consensus_decode(r)?; + + // Find the last non-null byte and trim null padding from the end + let trimmed = &rawbytes[..rawbytes.iter().rposition(|&b| b != 0).map_or(0, |i| i + 1)]; + + if !trimmed.is_ascii() { + return Err(crate::consensus::parse_failed_error("Command string must be ASCII")); + } + + Ok(Self(Cow::Owned(unsafe { String::from_utf8_unchecked(trimmed.to_vec()) }))) + } +} + +impl encoding::Encodable for CommandString { + type Encoder<'e> = encoding::ArrayEncoder<12>; + + fn encoder(&self) -> Self::Encoder<'_> { + let mut rawbytes = [0u8; 12]; + let strbytes = self.0.as_bytes(); + debug_assert!(strbytes.len() <= 12); + rawbytes[..strbytes.len()].copy_from_slice(strbytes); + encoding::ArrayEncoder::without_length_prefix(rawbytes) + } +} + +impl encoding::Decodable for CommandString { + type Decoder = CommandStringDecoder; + + fn decoder() -> Self::Decoder { CommandStringDecoder { inner: encoding::ArrayDecoder::new() } } +} + +/// Decoder for [`CommandString`]. +pub struct CommandStringDecoder { + inner: encoding::ArrayDecoder<12>, +} + +impl encoding::Decoder for CommandStringDecoder { + type Output = CommandString; + type Error = CommandStringDecodeError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.inner.push_bytes(bytes).map_err(CommandStringDecodeError::UnexpectedEof) + } + + fn end(self) -> Result { + let rawbytes = self.inner.end().map_err(CommandStringDecodeError::UnexpectedEof)?; + // Trim null padding from the end. + let trimmed = + rawbytes.iter().rposition(|&b| b != 0).map_or(&rawbytes[..0], |i| &rawbytes[..=i]); + + if !trimmed.is_ascii() { + return Err(CommandStringDecodeError::NotAscii); + } + + Ok(CommandString(Cow::Owned(unsafe { String::from_utf8_unchecked(trimmed.to_vec()) }))) + } + + fn read_limit(&self) -> usize { self.inner.read_limit() } +} + +/// Error decoding a [`CommandString`]. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum CommandStringDecodeError { + /// Unexpected end of data. + UnexpectedEof(encoding::UnexpectedEofError), + /// Command string contains non-ASCII characters. + NotAscii, +} + +impl fmt::Display for CommandStringDecodeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::UnexpectedEof(e) => write!(f, "unexpected end of data: {}", e), + Self::NotAscii => write!(f, "command string must be ASCII"), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for CommandStringDecodeError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::UnexpectedEof(e) => Some(e), + Self::NotAscii => None, + } + } +} + +/// Error returned when a command string is invalid. +/// +/// This is currently returned for command strings longer than 12. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct CommandStringError { + cow: Cow<'static, str>, +} + +impl fmt::Display for CommandStringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "the command string '{}' has length {} which is larger than 12", + self.cow, + self.cow.len() + ) + } +} + +impl std::error::Error for CommandStringError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } +} + +/// A Network message using the v1 p2p protocol. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct RawNetworkMessage { + magic: Magic, + payload: NetworkMessage, + payload_len: u32, + checksum: [u8; 4], +} + +/// A v1 message header used to describe the incoming payload. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct V1MessageHeader { + /// The network magic, a unique 4 byte sequence. + pub magic: Magic, + /// The "command" used to describe the payload. + pub command: CommandString, + /// The length of the payload. + pub length: u32, + /// A checksum to the aforementioned data. + pub checksum: [u8; 4], +} + +impl_consensus_encoding!(V1MessageHeader, magic, command, length, checksum); + +/// A Network message using the v2 p2p protocol defined in BIP-0324. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct V2NetworkMessage { + payload: NetworkMessage, +} + +/// A list of inventory items. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct InventoryPayload(pub Vec); + +/// A list of legacy p2p address messages. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AddrPayload(pub Vec<(u32, Address)>); + +/// A list of v2 address messages. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct AddrV2Payload(pub Vec); + +impl_vec_wrapper!(InventoryPayload, message_blockdata::Inventory); +impl_vec_wrapper!(AddrPayload, (u32, Address)); +impl_vec_wrapper!(AddrV2Payload, AddrV2Message); + +/// The `feefilter` message, wrapper around [`FeeRate`] for P2P wire format encoding. +/// +/// This message is used to inform peers about the minimum fee rate for transactions +/// that should be relayed which is defined in [BIP-0133]. +/// +/// [BIP-0133]: +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FeeFilter(FeeRate); + +impl FeeFilter { + /// Constructs a new `FeeFilter` from a [`FeeRate`]. + pub const fn new(fee_rate: FeeRate) -> Self { Self(fee_rate) } + + /// Returns the inner [`FeeRate`]. + pub const fn fee_rate(self) -> FeeRate { self.0 } +} + +impl From for FeeFilter { + fn from(fee_rate: FeeRate) -> Self { Self(fee_rate) } +} + +impl From for FeeRate { + fn from(filter: FeeFilter) -> Self { filter.0 } +} + +impl bitcoin::consensus::encode::Encodable for FeeFilter { + fn consensus_encode(&self, w: &mut W) -> Result { + use encoding::Encoder; + let mut encoder = encoding::Encodable::encoder(self); + loop { + w.write_all(encoder.current_chunk())?; + if !encoder.advance() { + break; + } + } + Ok(8) + } +} + +impl bitcoin::consensus::encode::Decodable for FeeFilter { + fn consensus_decode( + r: &mut R, + ) -> Result { + use encoding::Decoder; + + let mut decoder = ::decoder(); + let mut buffer = [0u8; 8]; + + r.read_exact(&mut buffer)?; + + let mut slice = &buffer[..]; + decoder.push_bytes(&mut slice).map_err(|_| { + bitcoin::consensus::encode::Error::Io(io::Error::new( + io::ErrorKind::UnexpectedEof, + "insufficient data for FeeFilter", + )) + })?; + + decoder.end().map_err(|_| { + bitcoin::consensus::encode::Error::Io(io::Error::new( + io::ErrorKind::UnexpectedEof, + "insufficient data for FeeFilter", + )) + }) + } +} + +encoding::encoder_newtype! { + /// Encoder for [`FeeFilter`] type. + pub struct FeeFilterEncoder(encoding::ArrayEncoder<8>); +} + +impl encoding::Encodable for FeeFilter { + type Encoder<'e> = FeeFilterEncoder; + + fn encoder(&self) -> Self::Encoder<'_> { + // Encode as sat/kvB in little-endian (BIP 133 wire format). + let kvb = self.0.to_sat_per_kvb_ceil(); + FeeFilterEncoder(encoding::ArrayEncoder::without_length_prefix(kvb.to_le_bytes())) + } +} + +/// Decoder for [`FeeFilter`] type. +pub struct FeeFilterDecoder(encoding::ArrayDecoder<8>); + +impl FeeFilterDecoder { + /// Constructs a new [`FeeFilter`] decoder. + pub fn new() -> Self { Self(encoding::ArrayDecoder::new()) } +} + +impl Default for FeeFilterDecoder { + fn default() -> Self { Self::new() } +} + +impl encoding::Decoder for FeeFilterDecoder { + type Output = FeeFilter; + type Error = encoding::UnexpectedEofError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.0.push_bytes(bytes) + } + + fn end(self) -> Result { + let array = self.0.end()?; + let kvb = u64::from_le_bytes(array); + + // BIP-0133 specifies feefilter as int64_t (signed), but negative values and values + // exceeding u32::MAX are invalid for fee rates. We saturate both cases to FeeRate::MAX. + let fee_rate = kvb.try_into().ok().map_or(FeeRate::MAX, FeeRate::from_sat_per_kvb); + + Ok(FeeFilter(fee_rate)) + } + + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +impl encoding::Decodable for FeeFilter { + type Decoder = FeeFilterDecoder; + + fn decoder() -> Self::Decoder { FeeFilterDecoder::new() } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for FeeFilter { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let choice = u.int_in_range(0..=3)?; + match choice { + 0 => Ok(Self(FeeRate::MIN)), + 1 => Ok(Self(FeeRate::BROADCAST_MIN)), + 2 => Ok(Self(FeeRate::DUST)), + _ => Ok(Self(FeeRate::from_sat_per_kvb(u.int_in_range(0..=u32::MAX)?))), + } + } +} + +/// A Network message payload. Proper documentation is available at +/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification) +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum NetworkMessage { + /// `version` + Version(message_network::VersionMessage), + /// `verack` + Verack, + /// `addr` + Addr(AddrPayload), + /// `inv` + Inv(InventoryPayload), + /// `getdata` + GetData(InventoryPayload), + /// `notfound` + NotFound(InventoryPayload), + /// `getblocks` + GetBlocks(message_blockdata::GetBlocksMessage), + /// `getheaders` + GetHeaders(message_blockdata::GetHeadersMessage), + /// `mempool` + MemPool, + /// tx + Tx(transaction::Transaction), + /// `block` + Block(block::Block), + /// `headers` + Headers(HeadersMessage), + /// `sendheaders` + SendHeaders, + /// `getaddr` + GetAddr, + /// `ping` + Ping(u64), + /// `pong` + Pong(u64), + /// `merkleblock` + MerkleBlock(MerkleBlock), + /// BIP-0037 `filterload` + FilterLoad(message_bloom::FilterLoad), + /// BIP-0037 `filteradd` + FilterAdd(message_bloom::FilterAdd), + /// BIP-0037 `filterclear` + FilterClear, + /// BIP-0157 getcfilters + GetCFilters(message_filter::GetCFilters), + /// BIP-0157 cfilter + CFilter(message_filter::CFilter), + /// BIP-0157 getcfheaders + GetCFHeaders(message_filter::GetCFHeaders), + /// BIP-0157 cfheaders + CFHeaders(message_filter::CFHeaders), + /// BIP-0157 getcfcheckpt + GetCFCheckpt(message_filter::GetCFCheckpt), + /// BIP-0157 cfcheckpt + CFCheckpt(message_filter::CFCheckpt), + /// BIP-0152 sendcmpct + SendCmpct(message_compact_blocks::SendCmpct), + /// BIP-0152 cmpctblock + CmpctBlock(message_compact_blocks::CmpctBlock), + /// BIP-0152 getblocktxn + GetBlockTxn(message_compact_blocks::GetBlockTxn), + /// BIP-0152 blocktxn + BlockTxn(message_compact_blocks::BlockTxn), + /// `alert` + Alert(message_network::Alert), + /// `reject` + Reject(message_network::Reject), + /// `feefilter` + FeeFilter(FeeFilter), + /// `wtxidrelay` + WtxidRelay, + /// `addrv2` + AddrV2(AddrV2Payload), + /// `sendaddrv2` + SendAddrV2, + + /// Any other message. + Unknown { + /// The command of this message. + command: CommandString, + /// The payload of this message. + payload: Vec, + }, +} + +impl NetworkMessage { + /// Returns the message command as a static string reference. + /// + /// This returns `"unknown"` for [NetworkMessage::Unknown], + /// regardless of the actual command in the unknown message. + /// Use the [Self::command] method to get the command for unknown messages. + pub fn cmd(&self) -> &'static str { + match *self { + Self::Version(_) => "version", + Self::Verack => "verack", + Self::Addr(_) => "addr", + Self::Inv(_) => "inv", + Self::GetData(_) => "getdata", + Self::NotFound(_) => "notfound", + Self::GetBlocks(_) => "getblocks", + Self::GetHeaders(_) => "getheaders", + Self::MemPool => "mempool", + Self::Tx(_) => "tx", + Self::Block(_) => "block", + Self::Headers(_) => "headers", + Self::SendHeaders => "sendheaders", + Self::GetAddr => "getaddr", + Self::Ping(_) => "ping", + Self::Pong(_) => "pong", + Self::MerkleBlock(_) => "merkleblock", + Self::FilterLoad(_) => "filterload", + Self::FilterAdd(_) => "filteradd", + Self::FilterClear => "filterclear", + Self::GetCFilters(_) => "getcfilters", + Self::CFilter(_) => "cfilter", + Self::GetCFHeaders(_) => "getcfheaders", + Self::CFHeaders(_) => "cfheaders", + Self::GetCFCheckpt(_) => "getcfcheckpt", + Self::CFCheckpt(_) => "cfcheckpt", + Self::SendCmpct(_) => "sendcmpct", + Self::CmpctBlock(_) => "cmpctblock", + Self::GetBlockTxn(_) => "getblocktxn", + Self::BlockTxn(_) => "blocktxn", + Self::Alert(_) => "alert", + Self::Reject(_) => "reject", + Self::FeeFilter(_) => "feefilter", + Self::WtxidRelay => "wtxidrelay", + Self::AddrV2(_) => "addrv2", + Self::SendAddrV2 => "sendaddrv2", + Self::Unknown { .. } => "unknown", + } + } + + /// Returns the CommandString for the message command. + pub fn command(&self) -> CommandString { + match *self { + Self::Unknown { command: ref c, .. } => c.clone(), + _ => CommandString::try_from_static(self.cmd()).expect("cmd returns valid commands"), + } + } +} + +impl RawNetworkMessage { + /// Constructs a new [RawNetworkMessage] + pub fn new(magic: Magic, payload: NetworkMessage) -> Self { + let mut engine = sha256d::Hash::engine(); + let payload_len = payload.consensus_encode(&mut engine).expect("engine doesn't error"); + let payload_len = u32::try_from(payload_len).expect("network message use u32 as length"); + let checksum = sha256d::Hash::from_engine(engine); + let checksum = checksum.to_byte_array(); + let checksum = [checksum[0], checksum[1], checksum[2], checksum[3]]; + Self { magic, payload, payload_len, checksum } + } + + /// Consumes the [RawNetworkMessage] instance and returns the inner payload. + pub fn into_payload(self) -> NetworkMessage { self.payload } + + /// The actual message data + pub fn payload(&self) -> &NetworkMessage { &self.payload } + + /// Magic bytes to identify the network these messages are meant for + pub fn magic(&self) -> &Magic { &self.magic } + + /// Returns the message command as a static string reference. + /// + /// This returns `"unknown"` for [NetworkMessage::Unknown], + /// regardless of the actual command in the unknown message. + /// Use the [Self::command] method to get the command for unknown messages. + pub fn cmd(&self) -> &'static str { self.payload.cmd() } + + /// Returns the CommandString for the message command. + pub fn command(&self) -> CommandString { self.payload.command() } +} + +impl V2NetworkMessage { + /// Constructs a new [V2NetworkMessage]. + pub fn new(payload: NetworkMessage) -> Self { Self { payload } } + + /// Consumes the [V2NetworkMessage] instance and returns the inner payload. + pub fn into_payload(self) -> NetworkMessage { self.payload } + + /// The actual message data + pub fn payload(&self) -> &NetworkMessage { &self.payload } + + /// Returns the message command as a static string reference. + /// + /// This returns `"unknown"` for [NetworkMessage::Unknown], + /// regardless of the actual command in the unknown message. + /// Use the [Self::command] method to get the command for unknown messages. + pub fn cmd(&self) -> &'static str { self.payload.cmd() } + + /// Returns the CommandString for the message command. + pub fn command(&self) -> CommandString { self.payload.command() } +} + +impl Encodable for HeadersMessage { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += w.emit_compact_size(self.0.len())?; + for header in self.0.iter() { + len += header.consensus_encode(w)?; + len += 0u8.consensus_encode(w)?; + } + Ok(len) + } +} + +impl Encodable for NetworkMessage { + fn consensus_encode(&self, writer: &mut W) -> Result { + match self { + Self::Version(ref dat) => dat.consensus_encode(writer), + Self::Addr(ref dat) => dat.consensus_encode(writer), + Self::Inv(ref dat) => dat.consensus_encode(writer), + Self::GetData(ref dat) => dat.consensus_encode(writer), + Self::NotFound(ref dat) => dat.consensus_encode(writer), + Self::GetBlocks(ref dat) => dat.consensus_encode(writer), + Self::GetHeaders(ref dat) => dat.consensus_encode(writer), + Self::Tx(ref dat) => dat.consensus_encode(writer), + Self::Block(ref dat) => dat.consensus_encode(writer), + Self::Headers(ref dat) => dat.consensus_encode(writer), + Self::Ping(ref dat) => dat.consensus_encode(writer), + Self::Pong(ref dat) => dat.consensus_encode(writer), + Self::MerkleBlock(ref dat) => dat.consensus_encode(writer), + Self::FilterLoad(ref dat) => dat.consensus_encode(writer), + Self::FilterAdd(ref dat) => dat.consensus_encode(writer), + Self::GetCFilters(ref dat) => dat.consensus_encode(writer), + Self::CFilter(ref dat) => dat.consensus_encode(writer), + Self::GetCFHeaders(ref dat) => dat.consensus_encode(writer), + Self::CFHeaders(ref dat) => dat.consensus_encode(writer), + Self::GetCFCheckpt(ref dat) => dat.consensus_encode(writer), + Self::CFCheckpt(ref dat) => dat.consensus_encode(writer), + Self::SendCmpct(ref dat) => dat.consensus_encode(writer), + Self::CmpctBlock(ref dat) => dat.consensus_encode(writer), + Self::GetBlockTxn(ref dat) => dat.consensus_encode(writer), + Self::BlockTxn(ref dat) => dat.consensus_encode(writer), + Self::Alert(ref dat) => dat.consensus_encode(writer), + Self::Reject(ref dat) => dat.consensus_encode(writer), + Self::FeeFilter(ref dat) => dat.consensus_encode(writer), + Self::AddrV2(ref dat) => dat.consensus_encode(writer), + Self::Verack + | Self::SendHeaders + | Self::MemPool + | Self::GetAddr + | Self::WtxidRelay + | Self::FilterClear + | Self::SendAddrV2 => Ok(0), + Self::Unknown { payload: ref data, .. } => data.consensus_encode(writer), + } + } +} + +impl Encodable for RawNetworkMessage { + fn consensus_encode(&self, w: &mut W) -> Result { + let mut len = 0; + len += self.magic.consensus_encode(w)?; + len += self.command().consensus_encode(w)?; + len += self.payload_len.consensus_encode(w)?; + len += self.checksum.consensus_encode(w)?; + len += self.payload().consensus_encode(w)?; + Ok(len) + } +} + +struct NetworkMessageEncoder { + buffer: Vec, + exhausted: bool, +} + +impl NetworkMessageEncoder { + fn new(msg: &NetworkMessage) -> Self { + let mut buffer = Vec::new(); + // TODO: delegate to internal encoders once migrated to consensus_encoding. + bitcoin::consensus::encode::Encodable::consensus_encode(msg, &mut buffer) + .expect("encoding to vec cannot fail"); + Self { buffer, exhausted: false } + } +} + +impl encoding::Encoder for NetworkMessageEncoder { + fn current_chunk(&self) -> &[u8] { + if self.exhausted { + &[] + } else { + &self.buffer + } + } + + fn advance(&mut self) -> bool { + self.exhausted = true; + false + } +} + +encoding::encoder_newtype! { + /// Encoder for [`RawNetworkMessage`]. + pub struct RawNetworkMessageEncoder( + encoding::Encoder2< + encoding::Encoder4< + encoding::ArrayEncoder<4>, + encoding::ArrayEncoder<12>, + encoding::ArrayEncoder<4>, + encoding::ArrayEncoder<4>, + >, + NetworkMessageEncoder, + > + ); +} + +impl encoding::Encodable for RawNetworkMessage { + type Encoder<'e> = RawNetworkMessageEncoder; + + fn encoder(&self) -> Self::Encoder<'_> { + RawNetworkMessageEncoder(encoding::Encoder2::new( + encoding::Encoder4::new( + encoding::ArrayEncoder::without_length_prefix(self.magic.to_bytes()), + self.command().encoder(), + encoding::ArrayEncoder::without_length_prefix(self.payload_len.to_le_bytes()), + encoding::ArrayEncoder::without_length_prefix(self.checksum), + ), + NetworkMessageEncoder::new(&self.payload), + )) + } +} + +struct NetworkMessageDecoder { + command: CommandString, + payload_len: usize, + buffer: Vec, +} + +impl NetworkMessageDecoder { + fn new(command: CommandString, payload_len: usize) -> Self { + Self { command, payload_len, buffer: Vec::new() } + } +} + +impl encoding::Decoder for NetworkMessageDecoder { + type Output = NetworkMessage; + type Error = RawNetworkMessageDecodeError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + let remaining = self.payload_len - self.buffer.len(); + let copy_len = bytes.len().min(remaining); + + self.buffer.extend_from_slice(&bytes[..copy_len]); + *bytes = &bytes[copy_len..]; + + Ok(self.buffer.len() < self.payload_len) + } + + fn end(self) -> Result { + let payload_bytes = self.buffer; + + // Validate payload length matches actual data. + if payload_bytes.len() != self.payload_len { + return Err(RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload)); + } + + // TODO: delegate to internal decoders once migrated to consensus_encoding. + let mut mem_d = payload_bytes.as_slice(); + let payload = match self.command.as_ref() { + "version" => NetworkMessage::Version( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "verack" => NetworkMessage::Verack, + "addr" => NetworkMessage::Addr( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "inv" => NetworkMessage::Inv( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "getdata" => NetworkMessage::GetData( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "notfound" => NetworkMessage::NotFound( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "getblocks" => NetworkMessage::GetBlocks( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "getheaders" => NetworkMessage::GetHeaders( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "mempool" => NetworkMessage::MemPool, + "block" => NetworkMessage::Block( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "headers" => NetworkMessage::Headers( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "sendheaders" => NetworkMessage::SendHeaders, + "getaddr" => NetworkMessage::GetAddr, + "ping" => NetworkMessage::Ping( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "pong" => NetworkMessage::Pong( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "merkleblock" => NetworkMessage::MerkleBlock( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "filterload" => NetworkMessage::FilterLoad( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "filteradd" => NetworkMessage::FilterAdd( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "filterclear" => NetworkMessage::FilterClear, + "getcfilters" => NetworkMessage::GetCFilters( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "cfilter" => NetworkMessage::CFilter( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "getcfheaders" => NetworkMessage::GetCFHeaders( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "cfheaders" => NetworkMessage::CFHeaders( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "getcfcheckpt" => NetworkMessage::GetCFCheckpt( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "cfcheckpt" => NetworkMessage::CFCheckpt( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "sendcmpct" => NetworkMessage::SendCmpct( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "cmpctblock" => NetworkMessage::CmpctBlock( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "getblocktxn" => NetworkMessage::GetBlockTxn( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "blocktxn" => NetworkMessage::BlockTxn( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "tx" => NetworkMessage::Tx( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "alert" => NetworkMessage::Alert( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "reject" => NetworkMessage::Reject( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "feefilter" => NetworkMessage::FeeFilter( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "wtxidrelay" => NetworkMessage::WtxidRelay, + "addrv2" => NetworkMessage::AddrV2( + bitcoin::consensus::encode::Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + ) + .map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Payload) + })?, + ), + "sendaddrv2" => NetworkMessage::SendAddrV2, + _ => NetworkMessage::Unknown { command: self.command, payload: payload_bytes }, + }; + + Ok(payload) + } + + fn read_limit(&self) -> usize { self.payload_len - self.buffer.len() } +} + +enum DecoderState { + ReadingHeader { + header_decoder: encoding::Decoder4< + encoding::ArrayDecoder<4>, + CommandStringDecoder, + encoding::ArrayDecoder<4>, + encoding::ArrayDecoder<4>, + >, + }, + ReadingPayload { + magic_bytes: [u8; 4], + payload_len_bytes: [u8; 4], + checksum: [u8; 4], + payload_decoder: NetworkMessageDecoder, + }, +} + +/// Decoder for [`RawNetworkMessage`]. +/// +/// This decoder implements a two-phase decoding process for Bitcoin V1 P2P messages. +/// It first decodes the fixed-sized header. It then uses the payload length information +/// to decode the dynamically sized network message. +pub struct RawNetworkMessageDecoder { + state: DecoderState, +} + +impl encoding::Decoder for RawNetworkMessageDecoder { + type Output = RawNetworkMessage; + type Error = RawNetworkMessageDecodeError; + + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + match &mut self.state { + DecoderState::ReadingHeader { header_decoder } => { + let need_more = header_decoder.push_bytes(bytes).map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Header) + })?; + + if !need_more { + // Header complete, extract values and transition to payload state. + let old_state = core::mem::replace( + &mut self.state, + DecoderState::ReadingHeader { + header_decoder: encoding::Decoder4::new( + encoding::ArrayDecoder::new(), + CommandStringDecoder { inner: encoding::ArrayDecoder::new() }, + encoding::ArrayDecoder::new(), + encoding::ArrayDecoder::new(), + ), + }, + ); + + let header_decoder = match old_state { + DecoderState::ReadingHeader { header_decoder } => header_decoder, + _ => unreachable!("we are in ReadingHeader state"), + }; + + let (magic_bytes, command, payload_len_bytes, checksum) = + header_decoder.end().map_err(|_| { + RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Header) + })?; + + let payload_len = u32::from_le_bytes(payload_len_bytes) as usize; + if payload_len > MAX_MSG_SIZE { + return Err(RawNetworkMessageDecodeError( + RawNetworkMessageDecodeErrorInner::PayloadTooLarge, + )); + } + + let payload_decoder = NetworkMessageDecoder::new(command, payload_len); + self.state = DecoderState::ReadingPayload { + magic_bytes, + payload_len_bytes, + checksum, + payload_decoder, + }; + + // Continue with any remaining bytes. + return self.push_bytes(bytes); + } + + Ok(need_more) + } + DecoderState::ReadingPayload { payload_decoder, .. } => + payload_decoder.push_bytes(bytes), + } + } + + fn end(self) -> Result { + match self.state { + DecoderState::ReadingHeader { .. } => + Err(RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner::Header)), + DecoderState::ReadingPayload { + magic_bytes, + payload_len_bytes, + checksum, + payload_decoder, + .. + } => { + let payload = payload_decoder.end()?; + + Ok(RawNetworkMessage { + magic: Magic::from_bytes(magic_bytes), + payload, + payload_len: u32::from_le_bytes(payload_len_bytes), + checksum, + }) + } + } + } + + fn read_limit(&self) -> usize { + match &self.state { + DecoderState::ReadingHeader { header_decoder } => header_decoder.read_limit(), + DecoderState::ReadingPayload { payload_decoder, .. } => payload_decoder.read_limit(), + } + } +} + +impl encoding::Decodable for RawNetworkMessage { + type Decoder = RawNetworkMessageDecoder; + + fn decoder() -> Self::Decoder { + RawNetworkMessageDecoder { + state: DecoderState::ReadingHeader { + header_decoder: encoding::Decoder4::new( + encoding::ArrayDecoder::new(), + CommandStringDecoder { inner: encoding::ArrayDecoder::new() }, + encoding::ArrayDecoder::new(), + encoding::ArrayDecoder::new(), + ), + }, + } + } +} + +/// Error decoding a raw network message. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RawNetworkMessageDecodeError(RawNetworkMessageDecodeErrorInner); + +#[derive(Debug, Clone, PartialEq, Eq)] +enum RawNetworkMessageDecodeErrorInner { + /// Error decoding the message header. + Header, + /// Payload length exceeds maximum allowed message size. + PayloadTooLarge, + /// Error decoding the message payload. + Payload, +} + +impl fmt::Display for RawNetworkMessageDecodeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + RawNetworkMessageDecodeErrorInner::Header => { + write!(f, "error decoding message header") + } + RawNetworkMessageDecodeErrorInner::PayloadTooLarge => { + write!(f, "payload length exceeds maximum allowed message size") + } + RawNetworkMessageDecodeErrorInner::Payload => { + write!(f, "error decoding message payload") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for RawNetworkMessageDecodeError {} + +impl Encodable for V2NetworkMessage { + fn consensus_encode(&self, writer: &mut W) -> Result { + // A subset of message types are optimized to only use one byte to encode the command. + // Non-optimized message types use the zero-byte flag and the following twelve bytes to encode the command. + let (command_byte, full_command) = match self.payload { + NetworkMessage::Addr(_) => (1u8, None), + NetworkMessage::Inv(_) => (14u8, None), + NetworkMessage::GetData(_) => (11u8, None), + NetworkMessage::NotFound(_) => (17u8, None), + NetworkMessage::GetBlocks(_) => (9u8, None), + NetworkMessage::GetHeaders(_) => (12u8, None), + NetworkMessage::MemPool => (15u8, None), + NetworkMessage::Tx(_) => (21u8, None), + NetworkMessage::Block(_) => (2u8, None), + NetworkMessage::Headers(_) => (13u8, None), + NetworkMessage::Ping(_) => (18u8, None), + NetworkMessage::Pong(_) => (19u8, None), + NetworkMessage::MerkleBlock(_) => (16u8, None), + NetworkMessage::FilterLoad(_) => (8u8, None), + NetworkMessage::FilterAdd(_) => (6u8, None), + NetworkMessage::FilterClear => (7u8, None), + NetworkMessage::GetCFilters(_) => (22u8, None), + NetworkMessage::CFilter(_) => (23u8, None), + NetworkMessage::GetCFHeaders(_) => (24u8, None), + NetworkMessage::CFHeaders(_) => (25u8, None), + NetworkMessage::GetCFCheckpt(_) => (26u8, None), + NetworkMessage::CFCheckpt(_) => (27u8, None), + NetworkMessage::SendCmpct(_) => (20u8, None), + NetworkMessage::CmpctBlock(_) => (4u8, None), + NetworkMessage::GetBlockTxn(_) => (10u8, None), + NetworkMessage::BlockTxn(_) => (3u8, None), + NetworkMessage::FeeFilter(_) => (5u8, None), + NetworkMessage::AddrV2(_) => (28u8, None), + NetworkMessage::Version(_) + | NetworkMessage::Verack + | NetworkMessage::SendHeaders + | NetworkMessage::GetAddr + | NetworkMessage::WtxidRelay + | NetworkMessage::SendAddrV2 + | NetworkMessage::Alert(_) + | NetworkMessage::Reject(_) + | NetworkMessage::Unknown { .. } => (0u8, Some(self.payload.command())), + }; + + let mut len = command_byte.consensus_encode(writer)?; + if let Some(cmd) = full_command { + len += cmd.consensus_encode(writer)?; + } + + // Encode the payload. + len += self.payload.consensus_encode(writer)?; + + Ok(len) + } +} + +/// A list of bitcoin block headers. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct HeadersMessage(pub Vec); + +impl HeadersMessage { + /// Does each header point to the previous block hash in the list. + pub fn is_connected(&self) -> bool { + self.0 + .iter() + .zip(self.0.iter().skip(1)) + .all(|(first, second)| first.block_hash().eq(&second.prev_blockhash)) + } +} + +impl Decodable for HeadersMessage { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let len = r.read_compact_size()?; + // should be above usual number of items to avoid + // allocation + let mut ret = Vec::with_capacity(core::cmp::min(1024 * 16, len as usize)); + for _ in 0..len { + ret.push(Decodable::consensus_decode(r)?); + if u8::consensus_decode(r)? != 0u8 { + return Err(crate::consensus::parse_failed_error( + "Headers message should not contain transactions", + )); + } + } + Ok(Self(ret)) + } + + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE.to_u64())) + } +} + +impl Decodable for RawNetworkMessage { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let magic = Decodable::consensus_decode_from_finite_reader(r)?; + let cmd = CommandString::consensus_decode_from_finite_reader(r)?; + let checked_data = CheckedData::consensus_decode_from_finite_reader(r)?; + let checksum = checked_data.checksum(); + let raw_payload = checked_data.into_data(); + let payload_len = raw_payload.len() as u32; + + let mut mem_d = raw_payload.as_slice(); + let payload = match &cmd.0[..] { + "version" => + NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "verack" => NetworkMessage::Verack, + "addr" => + NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "inv" => + NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "getdata" => + NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "notfound" => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + )?), + "getblocks" => NetworkMessage::GetBlocks( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "getheaders" => NetworkMessage::GetHeaders( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "mempool" => NetworkMessage::MemPool, + "block" => + NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "headers" => NetworkMessage::Headers( + HeadersMessage::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "sendheaders" => NetworkMessage::SendHeaders, + "getaddr" => NetworkMessage::GetAddr, + "ping" => + NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "pong" => + NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "merkleblock" => NetworkMessage::MerkleBlock( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "filterload" => NetworkMessage::FilterLoad( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "filteradd" => NetworkMessage::FilterAdd( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "filterclear" => NetworkMessage::FilterClear, + "tx" => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "getcfilters" => NetworkMessage::GetCFilters( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cfilter" => + NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "getcfheaders" => NetworkMessage::GetCFHeaders( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cfheaders" => NetworkMessage::CFHeaders( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "getcfcheckpt" => NetworkMessage::GetCFCheckpt( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cfcheckpt" => NetworkMessage::CFCheckpt( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "reject" => + NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "alert" => + NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "feefilter" => NetworkMessage::FeeFilter( + FeeFilter::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "sendcmpct" => NetworkMessage::SendCmpct( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "cmpctblock" => NetworkMessage::CmpctBlock( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "getblocktxn" => NetworkMessage::GetBlockTxn( + Decodable::consensus_decode_from_finite_reader(&mut mem_d)?, + ), + "blocktxn" => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader( + &mut mem_d, + )?), + "wtxidrelay" => NetworkMessage::WtxidRelay, + "addrv2" => + NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(&mut mem_d)?), + "sendaddrv2" => NetworkMessage::SendAddrV2, + _ => NetworkMessage::Unknown { command: cmd, payload: raw_payload }, + }; + Ok(Self { magic, payload, payload_len, checksum }) + } + + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE.to_u64())) + } +} + +impl Decodable for V2NetworkMessage { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let short_id: u8 = Decodable::consensus_decode_from_finite_reader(r)?; + let payload = match short_id { + 0u8 => { + // Full command encoding. + let cmd = CommandString::consensus_decode_from_finite_reader(r)?; + match &cmd.0[..] { + "version" => + NetworkMessage::Version(Decodable::consensus_decode_from_finite_reader(r)?), + "verack" => NetworkMessage::Verack, + "sendheaders" => NetworkMessage::SendHeaders, + "getaddr" => NetworkMessage::GetAddr, + "wtxidrelay" => NetworkMessage::WtxidRelay, + "sendaddrv2" => NetworkMessage::SendAddrV2, + "alert" => + NetworkMessage::Alert(Decodable::consensus_decode_from_finite_reader(r)?), + "reject" => + NetworkMessage::Reject(Decodable::consensus_decode_from_finite_reader(r)?), + _ => NetworkMessage::Unknown { + command: cmd, + payload: Vec::consensus_decode_from_finite_reader(r)?, + }, + } + } + 1u8 => NetworkMessage::Addr(Decodable::consensus_decode_from_finite_reader(r)?), + 2u8 => NetworkMessage::Block(Decodable::consensus_decode_from_finite_reader(r)?), + 3u8 => NetworkMessage::BlockTxn(Decodable::consensus_decode_from_finite_reader(r)?), + 4u8 => NetworkMessage::CmpctBlock(Decodable::consensus_decode_from_finite_reader(r)?), + 5u8 => NetworkMessage::FeeFilter(FeeFilter::consensus_decode_from_finite_reader(r)?), + 6u8 => NetworkMessage::FilterAdd(Decodable::consensus_decode_from_finite_reader(r)?), + 7u8 => NetworkMessage::FilterClear, + 8u8 => NetworkMessage::FilterLoad(Decodable::consensus_decode_from_finite_reader(r)?), + 9u8 => NetworkMessage::GetBlocks(Decodable::consensus_decode_from_finite_reader(r)?), + 10u8 => NetworkMessage::GetBlockTxn(Decodable::consensus_decode_from_finite_reader(r)?), + 11u8 => NetworkMessage::GetData(Decodable::consensus_decode_from_finite_reader(r)?), + 12u8 => NetworkMessage::GetHeaders(Decodable::consensus_decode_from_finite_reader(r)?), + 13u8 => + NetworkMessage::Headers(HeadersMessage::consensus_decode_from_finite_reader(r)?), + 14u8 => NetworkMessage::Inv(Decodable::consensus_decode_from_finite_reader(r)?), + 15u8 => NetworkMessage::MemPool, + 16u8 => NetworkMessage::MerkleBlock(Decodable::consensus_decode_from_finite_reader(r)?), + 17u8 => NetworkMessage::NotFound(Decodable::consensus_decode_from_finite_reader(r)?), + 18u8 => NetworkMessage::Ping(Decodable::consensus_decode_from_finite_reader(r)?), + 19u8 => NetworkMessage::Pong(Decodable::consensus_decode_from_finite_reader(r)?), + 20u8 => NetworkMessage::SendCmpct(Decodable::consensus_decode_from_finite_reader(r)?), + 21u8 => NetworkMessage::Tx(Decodable::consensus_decode_from_finite_reader(r)?), + 22u8 => NetworkMessage::GetCFilters(Decodable::consensus_decode_from_finite_reader(r)?), + 23u8 => NetworkMessage::CFilter(Decodable::consensus_decode_from_finite_reader(r)?), + 24u8 => + NetworkMessage::GetCFHeaders(Decodable::consensus_decode_from_finite_reader(r)?), + 25u8 => NetworkMessage::CFHeaders(Decodable::consensus_decode_from_finite_reader(r)?), + 26u8 => + NetworkMessage::GetCFCheckpt(Decodable::consensus_decode_from_finite_reader(r)?), + 27u8 => NetworkMessage::CFCheckpt(Decodable::consensus_decode_from_finite_reader(r)?), + 28u8 => NetworkMessage::AddrV2(Decodable::consensus_decode_from_finite_reader(r)?), + _ => + return Err(encode::Error::Parse(encode::ParseError::ParseFailed( + "Unknown short ID", + ))), + }; + Ok(Self { payload }) + } + + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Self::consensus_decode_from_finite_reader(&mut r.take(MAX_MSG_SIZE.to_u64())) + } +} + +/// Data and a 4-byte checksum. +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct CheckedData { + data: Vec, + checksum: [u8; 4], +} + +impl CheckedData { + /// Constructs a new `CheckedData` computing the checksum of given data. + pub fn new(data: Vec) -> Self { + let checksum = sha2_checksum(&data); + Self { data, checksum } + } + + /// Returns a reference to the raw data without the checksum. + pub fn data(&self) -> &[u8] { &self.data } + + /// Returns the raw data without the checksum. + pub fn into_data(self) -> Vec { self.data } + + /// Returns the checksum of the data. + pub fn checksum(&self) -> [u8; 4] { self.checksum } +} + +impl Encodable for CheckedData { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + u32::try_from(self.data.len()) + .expect("network message use u32 as length") + .consensus_encode(w)?; + self.checksum().consensus_encode(w)?; + Ok(8 + w.emit_slice(&self.data)?) + } +} + +impl Decodable for CheckedData { + #[inline] + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { + let len = u32::consensus_decode_from_finite_reader(r)? as usize; + + let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(r)?; + let opts = ReadBytesFromFiniteReaderOpts { len, chunk_size: encode::MAX_VEC_SIZE }; + let data = read_bytes_from_finite_reader(r, opts)?; + let expected_checksum = sha2_checksum(&data); + if expected_checksum != checksum { + Err(encode::ParseError::InvalidChecksum { + expected: expected_checksum, + actual: checksum, + } + .into()) + } else { + Ok(Self { data, checksum }) + } + } +} + +struct ReadBytesFromFiniteReaderOpts { + len: usize, + chunk_size: usize, +} + +/// Read `opts.len` bytes from reader, where `opts.len` could potentially be malicious. +/// +/// This function relies on reader being bound in amount of data +/// it returns for OOM protection. See [`Decodable::consensus_decode_from_finite_reader`]. +#[inline] +fn read_bytes_from_finite_reader( + d: &mut D, + mut opts: ReadBytesFromFiniteReaderOpts, +) -> Result, encode::Error> { + let mut ret = vec![]; + + assert_ne!(opts.chunk_size, 0); + + while opts.len > 0 { + let chunk_start = ret.len(); + let chunk_size = cmp::min(opts.len, opts.chunk_size); + let chunk_end = chunk_start + chunk_size; + ret.resize(chunk_end, 0u8); + d.read_slice(&mut ret[chunk_start..chunk_end])?; + opts.len -= chunk_size; + } + + Ok(ret) +} + +/// Does a double-SHA256 on `data` and returns the first 4 bytes. +fn sha2_checksum(data: &[u8]) -> [u8; 4] { + let checksum = sha256d::hash(data); + let checksum = checksum.to_byte_array(); + [checksum[0], checksum[1], checksum[2], checksum[3]] +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for AddrPayload { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(Vec::<(u32, Address)>::arbitrary(u)?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for AddrV2Payload { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(Vec::::arbitrary(u)?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for InventoryPayload { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(Vec::::arbitrary(u)?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for CommandString { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(u.arbitrary::()?.into())) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for HeadersMessage { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for NetworkMessage { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match u.int_in_range(0..=36)? { + 0 => Ok(Self::Version(u.arbitrary()?)), + 1 => Ok(Self::Verack), + 2 => Ok(Self::Addr(u.arbitrary()?)), + 3 => Ok(Self::Inv(u.arbitrary()?)), + 4 => Ok(Self::GetData(u.arbitrary()?)), + 5 => Ok(Self::NotFound(u.arbitrary()?)), + 6 => Ok(Self::GetBlocks(u.arbitrary()?)), + 7 => Ok(Self::GetHeaders(u.arbitrary()?)), + 8 => Ok(Self::MemPool), + 9 => Ok(Self::Tx(u.arbitrary()?)), + 10 => Ok(Self::Block(u.arbitrary()?)), + 11 => Ok(Self::Headers(u.arbitrary()?)), + 12 => Ok(Self::SendHeaders), + 13 => Ok(Self::GetAddr), + 14 => Ok(Self::Ping(u.arbitrary()?)), + 15 => Ok(Self::Pong(u.arbitrary()?)), + 16 => Ok(Self::MerkleBlock(u.arbitrary()?)), + 17 => Ok(Self::FilterLoad(u.arbitrary()?)), + 18 => Ok(Self::FilterAdd(u.arbitrary()?)), + 19 => Ok(Self::FilterClear), + 20 => Ok(Self::GetCFilters(u.arbitrary()?)), + 21 => Ok(Self::CFilter(u.arbitrary()?)), + 22 => Ok(Self::GetCFHeaders(u.arbitrary()?)), + 23 => Ok(Self::CFHeaders(u.arbitrary()?)), + 24 => Ok(Self::GetCFCheckpt(u.arbitrary()?)), + 25 => Ok(Self::CFCheckpt(u.arbitrary()?)), + 26 => Ok(Self::SendCmpct(u.arbitrary()?)), + 27 => Ok(Self::CmpctBlock(u.arbitrary()?)), + 28 => Ok(Self::GetBlockTxn(u.arbitrary()?)), + 29 => Ok(Self::BlockTxn(u.arbitrary()?)), + 30 => Ok(Self::Alert(u.arbitrary()?)), + 31 => Ok(Self::Reject(u.arbitrary()?)), + 32 => Ok(Self::FeeFilter(u.arbitrary()?)), + 33 => Ok(Self::WtxidRelay), + 34 => Ok(Self::AddrV2(u.arbitrary()?)), + 35 => Ok(Self::SendAddrV2), + _ => Ok(Self::Unknown { + command: u.arbitrary()?, + payload: Vec::::arbitrary(u)?, + }), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for RawNetworkMessage { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::new(u.arbitrary()?, u.arbitrary()?)) + } +} + +#[cfg(test)] +mod test { + use alloc::string::ToString; + use alloc::vec; + use std::net::Ipv4Addr; + + use bitcoin::block::{Block, BlockHash}; + use bitcoin::consensus::encode::{deserialize, deserialize_partial, serialize}; + use bitcoin::transaction::{Transaction, Txid}; + use hex_lit::hex; + use units::BlockHeight; + + use super::*; + use crate::address::AddrV2; + use crate::bip152::BlockTransactionsRequest; + use crate::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory}; + use crate::message_bloom::{BloomFlags, FilterAdd, FilterLoad}; + use crate::message_compact_blocks::{GetBlockTxn, SendCmpct}; + use crate::message_filter::{ + CFCheckpt, CFHeaders, CFilter, FilterHash, FilterHeader, GetCFCheckpt, GetCFHeaders, GetCFilters, + }; + use crate::message_network::{Alert, Reject, RejectReason, VersionMessage}; + use crate::{ProtocolVersion, ServiceFlags}; + + fn hash(array: [u8; 32]) -> sha256d::Hash { sha256d::Hash::from_byte_array(array) } + + #[test] + fn full_round_ser_der_raw_network_message() { + let version_msg: VersionMessage = deserialize(&hex!("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001")).unwrap(); + let tx: Transaction = deserialize(&hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000")).unwrap(); + let block: Block = deserialize(&hex!("00608e2e094d41aecfbcbf8fe70cb60be57516b07db1bafee4c4de5dad760000000000004aec16eab3be95abe9c54e01cf850c14b8c5cad1bc6b2e73e811db5d5998ada404503e66fcff031b4ebd99d701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3402983a000404503e6604f1f617271083bc3d6600000000000000000007bb1b0a636b706f6f6c0d506f72746c616e642e484f444cffffffff0200f2052a010000001976a9142ce72b25fe97b52638c199acfaa5e3891ddfed5b88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000")).unwrap(); + let header: block::Header = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b")).unwrap(); + let script = &hex!("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac"); + let merkle_block: MerkleBlock = deserialize(&hex!("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101")).unwrap(); + let cmptblock = deserialize(&hex!("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000")).unwrap(); + let blocktxn = deserialize(&hex!("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000")).unwrap(); + + let msgs = [ + NetworkMessage::Version(version_msg), + NetworkMessage::Verack, + NetworkMessage::Addr(AddrPayload(vec![( + 45, + Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK), + )])), + NetworkMessage::Inv(InventoryPayload(vec![Inventory::Block( + BlockHash::from_byte_array(hash([8u8; 32]).to_byte_array()), + )])), + NetworkMessage::GetData(InventoryPayload(vec![Inventory::Transaction( + Txid::from_byte_array(hash([45u8; 32]).to_byte_array()), + )])), + NetworkMessage::NotFound(InventoryPayload(vec![Inventory::Error([0u8; 32])])), + NetworkMessage::GetBlocks(GetBlocksMessage { + version: ProtocolVersion::from_nonstandard(70001), + locator_hashes: vec![ + BlockHash::from_byte_array(hash([1u8; 32]).to_byte_array()), + BlockHash::from_byte_array(hash([4u8; 32]).to_byte_array()), + ], + stop_hash: BlockHash::from_byte_array(hash([5u8; 32]).to_byte_array()), + }), + NetworkMessage::GetHeaders(GetHeadersMessage { + version: ProtocolVersion::from_nonstandard(70001), + locator_hashes: vec![ + BlockHash::from_byte_array(hash([10u8; 32]).to_byte_array()), + BlockHash::from_byte_array(hash([40u8; 32]).to_byte_array()), + ], + stop_hash: BlockHash::from_byte_array(hash([50u8; 32]).to_byte_array()), + }), + NetworkMessage::MemPool, + NetworkMessage::Tx(tx), + NetworkMessage::Block(block), + NetworkMessage::Headers(HeadersMessage(vec![header])), + NetworkMessage::SendHeaders, + NetworkMessage::GetAddr, + NetworkMessage::Ping(15), + NetworkMessage::Pong(23), + NetworkMessage::MerkleBlock(merkle_block), + NetworkMessage::FilterLoad(FilterLoad { + filter: hex!("03614e9b050000000000000001").to_vec(), + hash_funcs: 1, + tweak: 2, + flags: BloomFlags::All, + }), + NetworkMessage::FilterAdd(FilterAdd { data: script.to_vec() }), + NetworkMessage::FilterAdd(FilterAdd { + data: hash([29u8; 32]).as_byte_array().to_vec(), + }), + NetworkMessage::FilterClear, + NetworkMessage::GetCFilters(GetCFilters { + filter_type: 2, + start_height: BlockHeight::from(52), + stop_hash: BlockHash::from_byte_array(hash([42u8; 32]).to_byte_array()), + }), + NetworkMessage::CFilter(CFilter { + filter_type: 7, + block_hash: BlockHash::from_byte_array(hash([25u8; 32]).to_byte_array()), + filter: vec![1, 2, 3], + }), + NetworkMessage::GetCFHeaders(GetCFHeaders { + filter_type: 4, + start_height: BlockHeight::from(102), + stop_hash: BlockHash::from_byte_array(hash([47u8; 32]).to_byte_array()), + }), + NetworkMessage::CFHeaders(CFHeaders { + filter_type: 13, + stop_hash: BlockHash::from_byte_array(hash([53u8; 32]).to_byte_array()), + previous_filter_header: FilterHeader::from_byte_array( + hash([12u8; 32]).to_byte_array(), + ), + filter_hashes: vec![ + FilterHash::from_byte_array(hash([4u8; 32]).to_byte_array()), + FilterHash::from_byte_array(hash([12u8; 32]).to_byte_array()), + ], + }), + NetworkMessage::GetCFCheckpt(GetCFCheckpt { + filter_type: 17, + stop_hash: BlockHash::from_byte_array(hash([25u8; 32]).to_byte_array()), + }), + NetworkMessage::CFCheckpt(CFCheckpt { + filter_type: 27, + stop_hash: BlockHash::from_byte_array(hash([77u8; 32]).to_byte_array()), + filter_headers: vec![ + FilterHeader::from_byte_array(hash([3u8; 32]).to_byte_array()), + FilterHeader::from_byte_array(hash([99u8; 32]).to_byte_array()), + ], + }), + NetworkMessage::Alert(Alert::final_alert()), + NetworkMessage::Reject(Reject { + message: "Test reject".into(), + ccode: RejectReason::Duplicate, + reason: "Cause".into(), + hash: hash([255u8; 32]), + }), + NetworkMessage::FeeFilter(FeeFilter::from(FeeRate::BROADCAST_MIN)), + NetworkMessage::WtxidRelay, + NetworkMessage::AddrV2(AddrV2Payload(vec![AddrV2Message { + addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)), + port: 0, + services: ServiceFlags::NONE, + time: 0, + }])), + NetworkMessage::SendAddrV2, + NetworkMessage::CmpctBlock(cmptblock), + NetworkMessage::GetBlockTxn(GetBlockTxn { + txs_request: BlockTransactionsRequest { + block_hash: BlockHash::from_byte_array(hash([11u8; 32]).to_byte_array()), + indexes: vec![0, 1, 2, 3, 10, 3002], + }, + }), + NetworkMessage::BlockTxn(blocktxn), + NetworkMessage::SendCmpct(SendCmpct { send_compact: true, version: 8333 }), + ]; + + for msg in &msgs { + // V1 messages. + let raw_msg = RawNetworkMessage::new(Magic::from_bytes([57, 0, 0, 0]), msg.clone()); + assert_eq!(deserialize::(&serialize(&raw_msg)).unwrap(), raw_msg); + + // V2 messages. + let v2_msg = V2NetworkMessage::new(msg.clone()); + assert_eq!(deserialize::(&serialize(&v2_msg)).unwrap(), v2_msg); + } + } + + #[test] + fn commandstring() { + // Test converting. + assert_eq!( + CommandString::try_from_static("AndrewAndrew").unwrap().as_ref(), + "AndrewAndrew" + ); + assert!(CommandString::try_from_static("AndrewAndrewA").is_err()); + + // Test serializing. + let cs = CommandString("Andrew".into()); + assert_eq!(serialize(&cs), [0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); + + // Test deserializing + let cs: Result = + deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]); + assert!(cs.is_ok()); + assert_eq!(cs.as_ref().unwrap().to_string(), "Andrew".to_owned()); + assert_eq!(cs.unwrap(), CommandString::try_from_static("Andrew").unwrap()); + + // Test that embedded null bytes are preserved while trailing nulls are trimmed + let cs: Result = + deserialize(&[0, 0x41u8, 0x6e, 0x64, 0, 0x72, 0x65, 0x77, 0, 0, 0, 0]); + assert!(cs.is_ok()); + assert_eq!(cs.as_ref().unwrap().to_string(), "\0And\0rew".to_owned()); + assert_eq!(cs.unwrap(), CommandString::try_from_static("\0And\0rew").unwrap()); + + // Invalid CommandString, must be ASCII + assert!(deserialize::(&[ + 0, 0x41u8, 0x6e, 0xa4, 0, 0x72, 0x65, 0x77, 0, 0, 0, 0 + ]) + .is_err()); + + // Invalid CommandString, must be 12 bytes + assert!(deserialize::(&[ + 0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0 + ]) + .is_err()); + } + + #[test] + #[rustfmt::skip] + fn serialize_verack() { + assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::Verack)), + [0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61, + 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + } + + #[test] + fn serialize_v2_verack() { + assert_eq!( + serialize(&V2NetworkMessage::new(NetworkMessage::Verack)), + [ + 0x00, // Full command encoding flag. + 0x76, 0x65, 0x72, 0x61, 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + ); + } + + #[test] + #[rustfmt::skip] + fn serialize_ping() { + assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::Ping(100))), + [0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + } + + #[test] + fn serialize_v2_ping() { + assert_eq!( + serialize(&V2NetworkMessage::new(NetworkMessage::Ping(100))), + [ + 0x12, // Ping command short ID + 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + ); + } + + #[test] + #[rustfmt::skip] + fn serialize_mempool() { + assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::MemPool)), + [0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70, + 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + } + + #[test] + fn serialize_v2_mempool() { + assert_eq!( + serialize(&V2NetworkMessage::new(NetworkMessage::MemPool)), + [ + 0x0F, // MemPool command short ID + ] + ); + } + + #[test] + #[rustfmt::skip] + fn serialize_getaddr() { + assert_eq!(serialize(&RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr)), + [0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61, + 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); + } + + #[test] + fn serialize_v2_getaddr() { + assert_eq!( + serialize(&V2NetworkMessage::new(NetworkMessage::GetAddr)), + [ + 0x00, // Full command encoding flag. + 0x67, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + ] + ); + } + + #[test] + fn deserialize_getaddr() { + #[rustfmt::skip] + let msg = deserialize(&[ + 0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61, + 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2 + ]); + let preimage = RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr); + assert!(msg.is_ok()); + let msg: RawNetworkMessage = msg.unwrap(); + assert_eq!(preimage.magic, msg.magic); + assert_eq!(preimage.payload, msg.payload); + } + + #[test] + fn deserialize_v2_getaddr() { + let msg = deserialize(&[ + 0x00, // Full command encoding flag + 0x67, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, + ]); + + let preimage = V2NetworkMessage::new(NetworkMessage::GetAddr); + assert!(msg.is_ok()); + let msg: V2NetworkMessage = msg.unwrap(); + assert_eq!(preimage, msg); + } + + #[test] + fn deserialize_version() { + #[rustfmt::skip] + let msg = deserialize::(&[ + 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, + 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, + 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, + 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, + 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01 + ]); + + assert!(msg.is_ok()); + let msg = msg.unwrap(); + assert_eq!(msg.magic, Magic::BITCOIN); + if let NetworkMessage::Version(version_msg) = msg.payload { + assert_eq!(version_msg.version, ProtocolVersion::INVALID_CB_NO_BAN_VERSION); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); + assert_eq!(version_msg.timestamp, 1548554224); + assert_eq!(version_msg.nonce, 13952548347456104954); + assert_eq!(version_msg.user_agent.to_string(), "/Satoshi:0.17.1/"); + assert_eq!(version_msg.start_height, 560275); + assert!(version_msg.relay); + } else { + panic!("wrong message type"); + } + } + + #[test] + fn deserialize_v2_version() { + #[rustfmt::skip] + let msg = deserialize::(&[ + 0x00, // Full command encoding flag + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, // "version" command + 0x7f, 0x11, 0x01, 0x00, // version: 70015 + 0x0d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // services + 0xf0, 0x0f, 0x4d, 0x5c, 0x00, 0x00, 0x00, 0x00, // timestamp: 1548554224 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // receiver services: NONE + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, // addr_recv + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sender services: NONE + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // addr_from + 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, // nonce + 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, 0x2f, // user_agent: "/Satoshi:0.17.1/" + 0x93, 0x8c, 0x08, 0x00, // start_height: 560275 + 0x01 // relay: true + ]).unwrap(); + + if let NetworkMessage::Version(version_msg) = msg.payload { + assert_eq!(version_msg.version, ProtocolVersion::INVALID_CB_NO_BAN_VERSION); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); + assert_eq!(version_msg.timestamp, 1548554224); + assert_eq!(version_msg.nonce, 13952548347456104954); + assert_eq!(version_msg.user_agent.to_string(), "/Satoshi:0.17.1/"); + assert_eq!(version_msg.start_height, 560275); + assert!(version_msg.relay); + } else { + panic!("wrong message type"); + } + } + + #[test] + fn deserialize_partial_message() { + #[rustfmt::skip] + let data = [ + 0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, + 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x4d, 0x5c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, 0x0d, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, + 0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, + 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, + 0x2f, 0x93, 0x8c, 0x08, 0x00, 0x01, 0x00, 0x00 + ]; + let msg = deserialize_partial::(&data); + assert!(msg.is_ok()); + + let (msg, consumed) = msg.unwrap(); + assert_eq!(consumed, data.to_vec().len() - 2); + assert_eq!(msg.magic, Magic::BITCOIN); + if let NetworkMessage::Version(version_msg) = msg.payload { + assert_eq!(version_msg.version, ProtocolVersion::INVALID_CB_NO_BAN_VERSION); + assert_eq!( + version_msg.services, + ServiceFlags::NETWORK + | ServiceFlags::BLOOM + | ServiceFlags::WITNESS + | ServiceFlags::NETWORK_LIMITED + ); + assert_eq!(version_msg.timestamp, 1548554224); + assert_eq!(version_msg.nonce, 13952548347456104954); + assert_eq!(version_msg.user_agent.to_string(), "/Satoshi:0.17.1/"); + assert_eq!(version_msg.start_height, 560275); + assert!(version_msg.relay); + } else { + panic!("wrong message type"); + } + } + + #[test] + fn serialize_checkeddata() { + let cd = CheckedData::new(vec![1u8, 2, 3, 4, 5]); + assert_eq!(serialize(&cd), [5, 0, 0, 0, 162, 107, 175, 90, 1, 2, 3, 4, 5]); + } + + #[test] + fn deserialize_checkeddata() { + let cd: Result = + deserialize(&[5u8, 0, 0, 0, 162, 107, 175, 90, 1, 2, 3, 4, 5]); + assert_eq!(cd.ok(), Some(CheckedData::new(vec![1u8, 2, 3, 4, 5]))); + } + + #[test] + fn headers_message() { + let block_900_000 = deserialize::( + &hex!("00a0ab20247d4d9f582f9750344cdf62c46d81d046be960340960100000000000000000070f96945530651135839d8adc3f40e595118ec74c7ad81a3d17bb022e554fb0c937f4268743702177ad05f92") + ).unwrap(); + let block_900_001 = deserialize::( + &hex!("00e000208a96960d6d1ca4ee4a283fd83da309b8d5d2bfed380501000000000000000000371c9ffd63d75fb36c57d58eb842d23c0e7ec049daf16d94cc38805c346e9d52e880426874370217973dc83b") + ).unwrap(); + let block_900_002 = deserialize::( + &hex!("0400ff3ffc834fac4e1eb2ae41f1f9776e0f8e24a6090603ffa8010000000000000000002efba7e7280aa60f0a650f29e30332d52e11af57bc58cc6e71f343851f016c676182426874370217e3615653") + ).unwrap(); + let headers_message = HeadersMessage(vec![block_900_000, block_900_001, block_900_002]); + assert!(headers_message.is_connected()); + } +} diff --git a/p2p/src/message_blockdata.rs b/p2p/src/message_blockdata.rs new file mode 100644 index 000000000..788e4c00d --- /dev/null +++ b/p2p/src/message_blockdata.rs @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin blockdata network messages. +//! +//! This module describes network messages which are used for passing +//! Bitcoin data (blocks and transactions) around. + +use alloc::vec::Vec; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::block::BlockHash; +use bitcoin::consensus::encode::{self, Decodable, Encodable}; +use bitcoin::transaction::{Txid, Wtxid}; +use io::{BufRead, Write}; + +use crate::consensus::impl_consensus_encoding; +use crate::ProtocolVersion; + +/// An inventory item. +#[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)] +pub enum Inventory { + /// Error --- these inventories can be ignored. + /// While a 32 byte hash is expected over the wire, the value is meaningless. + Error([u8; 32]), + /// Transaction + Transaction(Txid), + /// Block + Block(BlockHash), + /// Compact Block + CompactBlock(BlockHash), + /// Witness Transaction by Wtxid + WTx(Wtxid), + /// Witness Transaction + WitnessTransaction(Txid), + /// Witness Block + WitnessBlock(BlockHash), + /// Unknown inventory type + Unknown { + /// The inventory item type. + inv_type: u32, + /// The hash of the inventory item + hash: [u8; 32], + }, +} + +impl Inventory { + /// Returns the item value represented as a SHA256-d hash. + /// + /// Returns [None] only for [Inventory::Error] who's hash value is meaningless. + pub fn network_hash(&self) -> Option<[u8; 32]> { + match self { + Self::Error(_) => None, + Self::Transaction(t) => Some(t.to_byte_array()), + Self::Block(b) => Some(b.to_byte_array()), + Self::CompactBlock(b) => Some(b.to_byte_array()), + Self::WTx(t) => Some(t.to_byte_array()), + Self::WitnessTransaction(t) => Some(t.to_byte_array()), + Self::WitnessBlock(b) => Some(b.to_byte_array()), + Self::Unknown { hash, .. } => Some(*hash), + } + } +} + +impl Encodable for Inventory { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + macro_rules! encode_inv { + ($code:expr, $item:expr) => { + u32::consensus_encode(&$code, w)? + $item.consensus_encode(w)? + }; + } + Ok(match *self { + Self::Error(ref e) => encode_inv!(0, e), + Self::Transaction(ref t) => encode_inv!(1, t), + Self::Block(ref b) => encode_inv!(2, b), + Self::CompactBlock(ref b) => encode_inv!(4, b), + Self::WTx(ref w) => encode_inv!(5, w), + Self::WitnessTransaction(ref t) => encode_inv!(0x40000001, t), + Self::WitnessBlock(ref b) => encode_inv!(0x40000002, b), + Self::Unknown { inv_type: t, hash: ref d } => encode_inv!(t, d), + }) + } +} + +impl Decodable for Inventory { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + let inv_type: u32 = Decodable::consensus_decode(r)?; + Ok(match inv_type { + 0 => Self::Error(Decodable::consensus_decode(r)?), + 1 => Self::Transaction(Decodable::consensus_decode(r)?), + 2 => Self::Block(Decodable::consensus_decode(r)?), + 4 => Self::CompactBlock(Decodable::consensus_decode(r)?), + 5 => Self::WTx(Decodable::consensus_decode(r)?), + 0x40000001 => Self::WitnessTransaction(Decodable::consensus_decode(r)?), + 0x40000002 => Self::WitnessBlock(Decodable::consensus_decode(r)?), + tp => Self::Unknown { inv_type: tp, hash: Decodable::consensus_decode(r)? }, + }) + } +} + +// Some simple messages + +/// The `getblocks` message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct GetBlocksMessage { + /// The protocol version + pub version: ProtocolVersion, + /// Locator hashes --- ordered newest to oldest. The remote peer will + /// reply with its longest known chain, starting from a locator hash + /// if possible and block 1 otherwise. + pub locator_hashes: Vec, + /// References the block to stop at, or zero to just fetch the maximum 500 blocks + pub stop_hash: BlockHash, +} + +/// The `getheaders` message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct GetHeadersMessage { + /// The protocol version + pub version: ProtocolVersion, + /// Locator hashes --- ordered newest to oldest. The remote peer will + /// reply with its longest known chain, starting from a locator hash + /// if possible and block 1 otherwise. + pub locator_hashes: Vec, + /// References the header to stop at, or zero to just fetch the maximum 2000 headers + pub stop_hash: BlockHash, +} + +impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash); + +impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash); + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for GetHeadersMessage { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + version: u.arbitrary()?, + locator_hashes: Vec::::arbitrary(u)?, + stop_hash: u.arbitrary()?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for GetBlocksMessage { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + version: u.arbitrary()?, + locator_hashes: Vec::::arbitrary(u)?, + stop_hash: u.arbitrary()?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Inventory { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match u.int_in_range(0..=7)? { + 0 => Ok(Self::Error(u.arbitrary()?)), + 1 => Ok(Self::Transaction(u.arbitrary()?)), + 2 => Ok(Self::Block(u.arbitrary()?)), + 3 => Ok(Self::CompactBlock(u.arbitrary()?)), + 4 => Ok(Self::WTx(u.arbitrary()?)), + 5 => Ok(Self::WitnessTransaction(u.arbitrary()?)), + 6 => Ok(Self::WitnessBlock(u.arbitrary()?)), + _ => Ok(Self::Unknown { inv_type: u.arbitrary()?, hash: u.arbitrary()? }), + } + } +} + +#[cfg(test)] +mod tests { + use bitcoin::consensus::encode::{deserialize, serialize}; + use hex_lit::hex; + + use super::*; + + #[test] + fn getblocks_message() { + let from_sat = hex!("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000"); + let genhash = hex!("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + let decode: Result = deserialize(&from_sat); + assert!(decode.is_ok()); + let real_decode = decode.unwrap(); + assert_eq!(real_decode.version.0, 70002); + assert_eq!(real_decode.locator_hashes.len(), 1); + assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash); + assert_eq!(real_decode.stop_hash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); + + assert_eq!(serialize(&real_decode), from_sat); + } + + #[test] + fn getheaders_message() { + let from_sat = hex!("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000"); + let genhash = hex!("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + let decode: Result = deserialize(&from_sat); + assert!(decode.is_ok()); + let real_decode = decode.unwrap(); + assert_eq!(real_decode.version.0, 70002); + assert_eq!(real_decode.locator_hashes.len(), 1); + assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash); + assert_eq!(real_decode.stop_hash, BlockHash::GENESIS_PREVIOUS_BLOCK_HASH); + + assert_eq!(serialize(&real_decode), from_sat); + } +} diff --git a/p2p/src/message_bloom.rs b/p2p/src/message_bloom.rs new file mode 100644 index 000000000..c09ddce10 --- /dev/null +++ b/p2p/src/message_bloom.rs @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Connection Bloom filtering network messages. +//! +//! This module describes BIP-0037 Connection Bloom filtering network messages. + +use alloc::vec::Vec; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::consensus::{encode, Decodable, Encodable, ReadExt}; +use io::{BufRead, Write}; + +use crate::consensus::impl_consensus_encoding; + +/// `filterload` message sets the current bloom filter +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FilterLoad { + /// The filter itself + pub filter: Vec, + /// The number of hash functions to use + pub hash_funcs: u32, + /// A random value + pub tweak: u32, + /// Controls how matched items are added to the filter + pub flags: BloomFlags, +} + +impl_consensus_encoding!(FilterLoad, filter, hash_funcs, tweak, flags); + +/// Bloom filter update flags +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum BloomFlags { + /// Never update the filter with outpoints. + None, + /// Always update the filter with outpoints. + All, + /// Only update the filter with outpoints if it is P2PK or P2MS + PubkeyOnly, +} + +impl Encodable for BloomFlags { + fn consensus_encode(&self, w: &mut W) -> Result { + w.write_all(&[match self { + Self::None => 0, + Self::All => 1, + Self::PubkeyOnly => 2, + }])?; + Ok(1) + } +} + +impl Decodable for BloomFlags { + fn consensus_decode(r: &mut R) -> Result { + Ok(match r.read_u8()? { + 0 => Self::None, + 1 => Self::All, + 2 => Self::PubkeyOnly, + _ => return Err(crate::consensus::parse_failed_error("unknown bloom flag")), + }) + } +} + +/// `filteradd` message updates the current filter with new data +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FilterAdd { + /// The data element to add to the current filter. + pub data: Vec, +} + +impl_consensus_encoding!(FilterAdd, data); + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for BloomFlags { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match u.int_in_range(0..=2)? { + 0 => Ok(Self::None), + 1 => Ok(Self::All), + _ => Ok(Self::PubkeyOnly), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for FilterAdd { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { data: Vec::::arbitrary(u)? }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for FilterLoad { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + filter: Vec::::arbitrary(u)?, + hash_funcs: u.arbitrary()?, + tweak: u.arbitrary()?, + flags: u.arbitrary()?, + }) + } +} diff --git a/p2p/src/message_compact_blocks.rs b/p2p/src/message_compact_blocks.rs new file mode 100644 index 000000000..685696ff3 --- /dev/null +++ b/p2p/src/message_compact_blocks.rs @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! +//! BIP-0152 Compact Blocks network messages + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; + +use crate::bip152; +use crate::consensus::impl_consensus_encoding; + +/// sendcmpct message +#[derive(PartialEq, Eq, Clone, Debug, Copy, PartialOrd, Ord, Hash)] +pub struct SendCmpct { + /// Request to be sent compact blocks. + pub send_compact: bool, + /// Compact Blocks protocol version number. + pub version: u64, +} +impl_consensus_encoding!(SendCmpct, send_compact, version); + +/// cmpctblock message +/// +/// Note that the rules for validation before relaying compact blocks is +/// different from headers and regular block messages. Thus, you shouldn't use +/// compact blocks when relying on an upstream full node to have validated data +/// being forwarded to you. +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct CmpctBlock { + /// The Compact Block. + pub compact_block: bip152::HeaderAndShortIds, +} +impl_consensus_encoding!(CmpctBlock, compact_block); + +/// getblocktxn message +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct GetBlockTxn { + /// The block transactions request. + pub txs_request: bip152::BlockTransactionsRequest, +} +impl_consensus_encoding!(GetBlockTxn, txs_request); + +/// blocktxn message +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +pub struct BlockTxn { + /// The requested block transactions. + pub transactions: bip152::BlockTransactions, +} +impl_consensus_encoding!(BlockTxn, transactions); + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for SendCmpct { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { send_compact: u.arbitrary()?, version: u.arbitrary()? }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for CmpctBlock { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { compact_block: u.arbitrary()? }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for GetBlockTxn { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { txs_request: u.arbitrary()? }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for BlockTxn { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { transactions: u.arbitrary()? }) + } +} diff --git a/p2p/src/message_filter.rs b/p2p/src/message_filter.rs new file mode 100644 index 000000000..01ca9221a --- /dev/null +++ b/p2p/src/message_filter.rs @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Client Side Block Filtering network messages. +//! +//! This module describes BIP-0157 Client Side Block Filtering network messages. + +use alloc::vec::Vec; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::block::BlockHash; +use hashes::{sha256d, HashEngine}; +use units::BlockHeight; + +use crate::consensus::impl_consensus_encoding; + +hashes::hash_newtype! { + /// Filter hash, as defined in BIP-0157. + pub struct FilterHash(pub sha256d::Hash); + /// Filter header, as defined in BIP-0157. + pub struct FilterHeader(pub sha256d::Hash); +} + +hashes::impl_hex_for_newtype!(FilterHash, FilterHeader); + +impl FilterHash { + /// Computes the filter header from a filter hash and previous filter header. + pub fn filter_header(&self, previous_filter_header: FilterHeader) -> FilterHeader { + let mut engine = sha256d::Hash::engine(); + engine.input(self.as_ref()); + engine.input(previous_filter_header.as_ref()); + FilterHeader(sha256d::Hash::from_engine(engine)) + } +} + +#[rustfmt::skip] +macro_rules! impl_hashencode { + ($hashtype:ident) => { + impl bitcoin::consensus::Encodable for $hashtype { + fn consensus_encode(&self, w: &mut W) -> core::result::Result { + self.as_byte_array().consensus_encode(w) + } + } + + impl bitcoin::consensus::Decodable for $hashtype { + fn consensus_decode(r: &mut R) -> core::result::Result { + Ok(Self::from_byte_array(<<$hashtype as hashes::Hash>::Bytes>::consensus_decode(r)?)) + } + } + }; +} + +impl_hashencode!(FilterHash); +impl_hashencode!(FilterHeader); + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for FilterHash { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::from_byte_array(u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for FilterHeader { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::from_byte_array(u.arbitrary()?)) + } +} + +/// getcfilters message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct GetCFilters { + /// Filter type for which headers are requested + pub filter_type: u8, + /// The height of the first block in the requested range + pub start_height: BlockHeight, + /// The hash of the last block in the requested range + pub stop_hash: BlockHash, +} +impl_consensus_encoding!(GetCFilters, filter_type, start_height, stop_hash); + +/// cfilter message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct CFilter { + /// Byte identifying the type of filter being returned + pub filter_type: u8, + /// Block hash of the Bitcoin block for which the filter is being returned + pub block_hash: BlockHash, + /// The serialized compact filter for this block + pub filter: Vec, +} +impl_consensus_encoding!(CFilter, filter_type, block_hash, filter); + +/// getcfheaders message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct GetCFHeaders { + /// Byte identifying the type of filter being returned + pub filter_type: u8, + /// The height of the first block in the requested range + pub start_height: BlockHeight, + /// The hash of the last block in the requested range + pub stop_hash: BlockHash, +} +impl_consensus_encoding!(GetCFHeaders, filter_type, start_height, stop_hash); + +/// cfheaders message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct CFHeaders { + /// Filter type for which headers are requested + pub filter_type: u8, + /// The hash of the last block in the requested range + pub stop_hash: BlockHash, + /// The filter header preceding the first block in the requested range + pub previous_filter_header: FilterHeader, + /// The filter hashes for each block in the requested range + pub filter_hashes: Vec, +} +impl_consensus_encoding!(CFHeaders, filter_type, stop_hash, previous_filter_header, filter_hashes); + +/// getcfcheckpt message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct GetCFCheckpt { + /// Filter type for which headers are requested + pub filter_type: u8, + /// The hash of the last block in the requested range + pub stop_hash: BlockHash, +} +impl_consensus_encoding!(GetCFCheckpt, filter_type, stop_hash); + +/// cfcheckpt message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct CFCheckpt { + /// Filter type for which headers are requested + pub filter_type: u8, + /// The hash of the last block in the requested range + pub stop_hash: BlockHash, + /// The filter headers at intervals of 1,000 + pub filter_headers: Vec, +} +impl_consensus_encoding!(CFCheckpt, filter_type, stop_hash, filter_headers); + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for GetCFilters { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + filter_type: u.arbitrary()?, + start_height: u.arbitrary()?, + stop_hash: u.arbitrary()?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for CFilter { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + filter_type: u.arbitrary()?, + block_hash: u.arbitrary()?, + filter: Vec::::arbitrary(u)?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for GetCFHeaders { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + filter_type: u.arbitrary()?, + start_height: u.arbitrary()?, + stop_hash: u.arbitrary()?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for CFHeaders { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + filter_type: u.arbitrary()?, + stop_hash: u.arbitrary()?, + previous_filter_header: u.arbitrary()?, + filter_hashes: u.arbitrary()?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for GetCFCheckpt { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { filter_type: u.arbitrary()?, stop_hash: u.arbitrary()? }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for CFCheckpt { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + filter_type: u.arbitrary()?, + stop_hash: u.arbitrary()?, + filter_headers: Vec::::arbitrary(u)?, + }) + } +} diff --git a/p2p/src/message_network.rs b/p2p/src/message_network.rs new file mode 100644 index 000000000..b5fa11540 --- /dev/null +++ b/p2p/src/message_network.rs @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin network-related network messages. +//! +//! This module defines network messages which describe peers and their +//! capabilities. + +use alloc::borrow::Cow; +use alloc::format; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use bitcoin::consensus::{encode, Decodable, Encodable, ReadExt, WriteExt}; +use hashes::sha256d; +use io::{BufRead, Write}; + +use crate::address::Address; +use crate::consensus::{impl_consensus_encoding, impl_vec_wrapper}; +use crate::{ProtocolVersion, ServiceFlags}; + +// Some simple messages + +/// The `version` message +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct VersionMessage { + /// The P2P network protocol version + pub version: ProtocolVersion, + /// A bitmask describing the services supported by this node + pub services: ServiceFlags, + /// The time at which the `version` message was sent + pub timestamp: i64, + /// The network address of the peer receiving the message + pub receiver: Address, + /// The network address of the peer sending the message + pub sender: Address, + /// A random nonce used to detect loops in the network + /// + /// The nonce can be used to detect situations when a node accidentally + /// connects to itself. Set it to a random value and, in case of incoming + /// connections, compare the value - same values mean self-connection. + /// + /// If your application uses P2P to only fetch the data and doesn't listen + /// you may just set it to 0. + pub nonce: u64, + /// A string describing the peer's software + pub user_agent: UserAgent, + /// The height of the maximum-work blockchain that the peer is aware of + pub start_height: i32, + /// Whether the receiving peer should relay messages to the sender; used + /// if the sender is bandwidth-limited and would like to support bloom + /// filtering. Defaults to false. + pub relay: bool, +} + +impl VersionMessage { + /// Constructs a new `version` message with `relay` set to false + pub fn new( + version: ProtocolVersion, + services: ServiceFlags, + timestamp: i64, + receiver: Address, + sender: Address, + nonce: u64, + user_agent: UserAgent, + start_height: i32, + ) -> Self { + Self { + version, + services, + timestamp, + receiver, + sender, + nonce, + user_agent, + start_height, + relay: false, + } + } +} + +impl_consensus_encoding!( + VersionMessage, + version, + services, + timestamp, + receiver, + sender, + nonce, + user_agent, + start_height, + relay +); + +/// A bitcoin user agent defined by BIP-0014. The user agent is sent in the version message when a +/// connection between two peers is established. It is intended to advertise client software in a +/// well-defined format. +/// +/// ref: +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UserAgent { + user_agent: String, +} + +impl_consensus_encoding!(UserAgent, user_agent); + +impl UserAgent { + const MAX_USER_AGENT_LEN: usize = 256; + + fn panic_invalid_chars(agent_str: &str) { + if agent_str.chars().any(|c| matches!(c, '/' | '(' | ')' | ':')) { + panic!("user agent configuration cannot contain: / ( ) :"); + } + } + + fn panic_max_len(agent_str: &str) { + if agent_str.chars().count() > Self::MAX_USER_AGENT_LEN { + panic!("user agent cannot exceed 256 characters."); + } + } + /// Builds a new user agent from the lowest level client software. For example: `Satoshi` is + /// used by Bitcoin Core. + /// + /// # Panics + /// + /// If the client name contains one of: `/ ( ) :` or the user agent exceeds 256 characters. + pub fn new>(client_name: S, client_version: UserAgentVersion) -> Self { + let parsed_name = client_name.as_ref(); + Self::panic_invalid_chars(parsed_name); + let agent = format!("/{parsed_name}:{client_version}/"); + Self::panic_max_len(&agent); + Self { user_agent: agent } + } + + /// Builds a user agent, ignoring BIP-0014 recommendations. + pub fn from_nonstandard(agent: S) -> Self { + Self { user_agent: agent.to_string() } + } + + /// Adds a client to the user agent string. Examples may include the name of a wallet software. + /// + /// # Panics + /// + /// If the client name contains one of: `/ ( ) :` or the user agent exceeds 256 characters. + #[must_use] + pub fn add_client>( + mut self, + client_name: S, + client_version: UserAgentVersion, + ) -> Self { + let parsed_name = client_name.as_ref(); + Self::panic_invalid_chars(parsed_name); + let agent = format!("{parsed_name}:{client_version}/"); + self.user_agent.push_str(&agent); + Self::panic_max_len(&self.user_agent); + self + } +} + +impl std::fmt::Display for UserAgent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.user_agent.fmt(f) } +} + +impl From for String { + fn from(agent: UserAgent) -> Self { agent.user_agent } +} + +/// A software version field for inclusion in a user agent specified by BIP-0014. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UserAgentVersion { + version: ClientSoftwareVersion, + comments: Option, +} + +impl UserAgentVersion { + /// Creates a user agent client version associated with a name. + pub const fn new(software_version: ClientSoftwareVersion) -> Self { + Self { version: software_version, comments: None } + } + + /// Adds a comment to the version. Typical comments describe the operating system or platform + /// that is executing the program, however these may be any comment. + /// + /// An example may include `Android`. + /// + /// # Panics + /// + /// If the client name contains one of: `/ ( ) :` + #[must_use] + pub fn push_comment>(mut self, comment: S) -> Self { + let parsed_comment = comment.as_ref(); + UserAgent::panic_invalid_chars(parsed_comment); + match self.comments { + Some(mut comment) => { + let semi_colon_delimiter = format!("; {parsed_comment}"); + comment.push_str(&semi_colon_delimiter); + self.comments = Some(comment); + } + None => self.comments = Some(parsed_comment.to_string()), + } + self + } +} + +impl std::fmt::Display for UserAgentVersion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut software_version = self.version.to_string(); + if let Some(comments) = &self.comments { + let comments = format!("({comments})"); + software_version.push_str(&comments); + } + software_version.fmt(f) + } +} + +/// Software tagged by version number or date for inclusion in a user agent field. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum ClientSoftwareVersion { + /// Semantic versioning release. + SemVer { + /// X.0.0 + major: u16, + /// 0.X.0 + minor: u16, + /// 0.0.X + revision: u16, + }, + /// The release date of a software. + Date { + /// Year, represented as 4 digits + yyyy: u16, + /// The month + mm: u8, + /// The day + dd: u8, + }, +} + +impl std::fmt::Display for ClientSoftwareVersion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Date { yyyy, mm, dd } => format!("{yyyy}{mm:02}{dd:02}").fmt(f), + Self::SemVer { major, minor, revision } => format!("{major}.{minor}.{revision}").fmt(f), + } + } +} + +/// message rejection reason as a code +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum RejectReason { + /// malformed message + Malformed = 0x01, + /// invalid message + Invalid = 0x10, + /// obsolete message + Obsolete = 0x11, + /// duplicate message + Duplicate = 0x12, + /// nonstandard transaction + NonStandard = 0x40, + /// an output is below dust limit + Dust = 0x41, + /// insufficient fee + Fee = 0x42, + /// checkpoint + Checkpoint = 0x43, +} + +impl Encodable for RejectReason { + fn consensus_encode(&self, w: &mut W) -> Result { + w.write_all(&[*self as u8])?; + Ok(1) + } +} + +impl Decodable for RejectReason { + fn consensus_decode(r: &mut R) -> Result { + Ok(match r.read_u8()? { + 0x01 => Self::Malformed, + 0x10 => Self::Invalid, + 0x11 => Self::Obsolete, + 0x12 => Self::Duplicate, + 0x40 => Self::NonStandard, + 0x41 => Self::Dust, + 0x42 => Self::Fee, + 0x43 => Self::Checkpoint, + _ => return Err(crate::consensus::parse_failed_error("unknown reject code")), + }) + } +} + +/// Reject message might be sent by peers rejecting one of our messages +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct Reject { + /// message type rejected + pub message: Cow<'static, str>, + /// reason of rejection as code + pub ccode: RejectReason, + /// reason of rejection + pub reason: Cow<'static, str>, + /// reference to rejected item + pub hash: sha256d::Hash, +} + +impl_consensus_encoding!(Reject, message, ccode, reason, hash); + +/// A deprecated message type that was used to notify users of system changes. Due to a number of +/// vulnerabilities, alerts are no longer used. A final alert was sent as of Bitcoin Core 0.14.0, +/// and is sent to any node that is advertising a potentially vulnerable protocol version. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Alert(Vec); + +impl Alert { + const FINAL_ALERT: [u8; 96] = [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 127, 0, 0, 0, 0, 255, 255, 255, 127, + 254, 255, 255, 127, 1, 255, 255, 255, 127, 0, 0, 0, 0, 255, 255, 255, 127, 0, 255, 255, + 255, 127, 0, 47, 85, 82, 71, 69, 78, 84, 58, 32, 65, 108, 101, 114, 116, 32, 107, 101, 121, + 32, 99, 111, 109, 112, 114, 111, 109, 105, 115, 101, 100, 44, 32, 117, 112, 103, 114, 97, + 100, 101, 32, 114, 101, 113, 117, 105, 114, 101, 100, 0, + ]; + + /// Builds the final alert to send to a potentially vulnerable peer. + pub fn final_alert() -> Self { Self(Self::FINAL_ALERT.into()) } + + /// The final alert advertised by Bitcoin Core. This alert is sent if the advertised protocol + /// version is vulnerable to the alert-system vulnerabilities. + pub fn is_final_alert(&self) -> bool { self.0.eq(&Self::FINAL_ALERT) } +} + +impl_vec_wrapper!(Alert, Vec); + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for ClientSoftwareVersion { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match bool::arbitrary(u)? { + true => Ok(Self::Date { + yyyy: u.arbitrary()?, + mm: u.arbitrary()?, + dd: u.arbitrary()?, + }), + false => Ok(Self::SemVer { + major: u.arbitrary()?, + minor: u.arbitrary()?, + revision: u.arbitrary()?, + }), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for UserAgentVersion { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::new(u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for UserAgent { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::new(u.arbitrary::()?, u.arbitrary()?)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for VersionMessage { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self::new( + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + u.arbitrary()?, + )) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for RejectReason { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + match u.int_in_range(0..=7)? { + 0 => Ok(Self::Malformed), + 1 => Ok(Self::Invalid), + 2 => Ok(Self::Obsolete), + 3 => Ok(Self::Duplicate), + 4 => Ok(Self::NonStandard), + 5 => Ok(Self::Dust), + 6 => Ok(Self::Fee), + _ => Ok(Self::Checkpoint), + } + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Reject { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + message: u.arbitrary::()?.into(), + ccode: u.arbitrary()?, + reason: u.arbitrary::()?.into(), + hash: sha256d::Hash::from_byte_array(u.arbitrary()?), + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Alert { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self(Vec::::arbitrary(u)?)) + } +} + +#[cfg(test)] +mod tests { + use alloc::string::ToString; + + use bitcoin::consensus::encode::{deserialize, serialize}; + use hex_lit::hex; + + use super::*; + + #[test] + fn version_message_test() { + // This message is from my satoshi node, morning of May 27 2014 + let from_sat = hex!("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001"); + + let decode: Result = deserialize(&from_sat); + assert!(decode.is_ok()); + let real_decode = decode.unwrap(); + assert_eq!(real_decode.version.0, 70002); + assert_eq!(real_decode.services, ServiceFlags::NETWORK); + assert_eq!(real_decode.timestamp, 1401217254); + // address decodes should be covered by Address tests + assert_eq!(real_decode.nonce, 16735069437859780935); + assert_eq!( + real_decode.user_agent, + UserAgent::new( + "Satoshi", + UserAgentVersion::new(ClientSoftwareVersion::SemVer { + major: 0, + minor: 9, + revision: 99 + }) + ) + ); + assert_eq!(real_decode.start_height, 302892); + assert!(real_decode.relay); + + assert_eq!(serialize(&real_decode), from_sat); + } + + #[test] + fn reject_message_test() { + let reject_tx_conflict = hex!("027478121474786e2d6d656d706f6f6c2d636f6e666c69637405df54d3860b3c41806a3546ab48279300affacf4b88591b229141dcf2f47004"); + let reject_tx_nonfinal = hex!("02747840096e6f6e2d66696e616c259bbe6c83db8bbdfca7ca303b19413dc245d9f2371b344ede5f8b1339a5460b"); + + let decode_result_conflict: Result = deserialize(&reject_tx_conflict); + let decode_result_nonfinal: Result = deserialize(&reject_tx_nonfinal); + + assert!(decode_result_conflict.is_ok()); + assert!(decode_result_nonfinal.is_ok()); + + let conflict = decode_result_conflict.unwrap(); + assert_eq!("tx", conflict.message); + assert_eq!(RejectReason::Duplicate, conflict.ccode); + assert_eq!("txn-mempool-conflict", conflict.reason); + assert_eq!( + "0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05" + .parse::() + .unwrap(), + conflict.hash + ); + + let nonfinal = decode_result_nonfinal.unwrap(); + assert_eq!("tx", nonfinal.message); + assert_eq!(RejectReason::NonStandard, nonfinal.ccode); + assert_eq!("non-final", nonfinal.reason); + assert_eq!( + "0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25" + .parse::() + .unwrap(), + nonfinal.hash + ); + + assert_eq!(serialize(&conflict), reject_tx_conflict); + assert_eq!(serialize(&nonfinal), reject_tx_nonfinal); + } + + #[test] + fn alert_message_test() { + let alert_hex = hex!("60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c207570677261646520726571756972656400"); + let alert: Alert = deserialize(&alert_hex).unwrap(); + assert!(alert.is_final_alert()); + } + + #[test] + fn test_user_agent() { + let client_name = "Satoshi"; + let client_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer { + major: 5, + minor: 12, + revision: 0, + }); + let user_agent = UserAgent::new(client_name, client_version); + assert_eq!("/Satoshi:5.12.0/", user_agent.to_string()); + let wallet_name = "bitcoin-qt"; + let wallet_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer { + major: 0, + minor: 8, + revision: 0, + }); + let user_agent = user_agent.add_client(wallet_name, wallet_version); + assert_eq!("/Satoshi:5.12.0/bitcoin-qt:0.8.0/", user_agent.to_string()); + let client_name = "BitcoinJ"; + let client_version = + UserAgentVersion::new(ClientSoftwareVersion::Date { yyyy: 2011, mm: 1, dd: 28 }); + let user_agent = UserAgent::new(client_name, client_version); + assert_eq!("/BitcoinJ:20110128/", user_agent.to_string()); + let wallet_name = "Electrum"; + let wallet_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer { + major: 0, + minor: 9, + revision: 0, + }); + let wallet_version = wallet_version.push_comment("Ubuntu"); + let wallet_version = wallet_version.push_comment("24"); + let user_agent = user_agent.add_client(wallet_name, wallet_version); + assert_eq!("/BitcoinJ:20110128/Electrum:0.9.0(Ubuntu; 24)/", user_agent.to_string()); + } + + #[test] + #[should_panic] + fn test_incorrect_user_agent() { + let client_name = "Satoshi/"; + let client_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer { + major: 5, + minor: 12, + revision: 0, + }); + UserAgent::new(client_name, client_version); + } +} diff --git a/p2p/src/network_ext.rs b/p2p/src/network_ext.rs new file mode 100644 index 000000000..b30e90bbd --- /dev/null +++ b/p2p/src/network_ext.rs @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! This module implements an extension trait for [`Network`] +//! with getter methods for the default P2P port and default +//! network [`Magic`] bytes. + +use bitcoin::{Network, TestnetVersion}; + +use crate::Magic; + +/// Trait that extends [`Network`] by adding getter methods for the default P2P ports and [`Magic`] bytes. +pub trait NetworkExt { + /// The default P2P port for a given [`Network`]. + fn default_p2p_port(self) -> u16; + + /// The default network [`Magic`] for a given [`Network`]. + fn default_network_magic(self) -> Magic; +} + +impl NetworkExt for Network { + /// The default P2P port for a given [`Network`]. + /// + /// Note: All [`TestnetVersion`] variants >4 are treated as [`TestnetVersion::V4`]. + /// This function will be updated as new test networks are defined. + fn default_p2p_port(self) -> u16 { + match &self { + Self::Bitcoin => 8333, + Self::Signet => 38333, + Self::Testnet(TestnetVersion::V3) => 18333, + Self::Testnet(TestnetVersion::V4) => 48333, + Self::Testnet(_) => 48333, + Self::Regtest => 18444, + } + } + + /// The default network [`Magic`] for a given [`Network`]. + /// + /// Note: All [`TestnetVersion`] variants >4 are treated as [`TestnetVersion::V4`]. + /// This function will be updated as new test networks are defined. + fn default_network_magic(self) -> Magic { + match &self { + Self::Bitcoin => Magic::BITCOIN, + Self::Signet => Magic::SIGNET, + Self::Testnet(TestnetVersion::V3) => Magic::TESTNET3, + Self::Testnet(TestnetVersion::V4) => Magic::TESTNET4, + Self::Testnet(_) => Magic::TESTNET4, + Self::Regtest => Magic::REGTEST, + } + } +} + +#[cfg(test)] +mod tests { + use alloc::vec; + + use super::*; + + #[test] + fn default_p2p_port() { + let networks = [ + Network::Bitcoin, + Network::Signet, + Network::Testnet(TestnetVersion::V3), + Network::Testnet(TestnetVersion::V4), + Network::Regtest, + ]; + + let p2p_ports = vec![8333, 38333, 18333, 48333, 18444]; + + for (network, p2p_port) in networks.iter().zip(p2p_ports) { + assert_eq!(network.default_p2p_port(), p2p_port); + } + } + + #[test] + fn default_network_magic() { + let networks = [ + Network::Bitcoin, + Network::Signet, + Network::Testnet(TestnetVersion::V3), + Network::Testnet(TestnetVersion::V4), + Network::Regtest, + ]; + + let network_magics = + vec![Magic::BITCOIN, Magic::SIGNET, Magic::TESTNET3, Magic::TESTNET4, Magic::REGTEST]; + + for (network, network_magic) in networks.iter().zip(network_magics) { + assert_eq!(network.default_network_magic(), network_magic); + } + } +} diff --git a/primitives/CHANGELOG.md b/primitives/CHANGELOG.md new file mode 100644 index 000000000..5184c49e1 --- /dev/null +++ b/primitives/CHANGELOG.md @@ -0,0 +1,97 @@ +# 1.0.0 - 2025-10-18 + +This changelog is a rolling description of everything that will eventually end up in `v1.0`. + +There are a bunch of changes in this stable release, of note script +tagging and the consensus encoding re-write. + +- Introduce script tagging [#4907](https://github.com/rust-bitcoin/rust-bitcoin/pull/4907) +- Introduce pull encoding and use it for blockhash computation [#4912](https://github.com/rust-bitcoin/rust-bitcoin/pull/4912) +- Implement `Encodable` for `&Script` [#4978](https://github.com/rust-bitcoin/rust-bitcoin/pull/4978) + +And also we did: + +- Remove `hashes` from the public API [#4935](https://github.com/rust-bitcoin/rust-bitcoin/pull/4935) +- Bump MSRV from 1.63.0 to 1.74.0 for all crates in the repo [#4926](https://github.com/rust-bitcoin/rust-bitcoin/pull/4926) +- Rename `units::parse` to `parse_int` [#4886](https://github.com/rust-bitcoin/rust-bitcoin/pull/4886) +- Introduce `Ntxid` [#4839](https://github.com/rust-bitcoin/rust-bitcoin/pull/4839) +- Remove `serde` impls from some primitive types [#4806](https://github.com/rust-bitcoin/rust-bitcoin/pull/48064806) +- Pluralize transaction fields [#4788](https://github.com/rust-bitcoin/rust-bitcoin/pull/4788) +- Use `CompactSize` instead of `VarInt` [#4790](https://github.com/rust-bitcoin/rust-bitcoin/pull/4790) +- Do not derive `Default` on `CompactTarget` [#4561](https://github.com/rust-bitcoin/rust-bitcoin/pull/4561) +- Deserialize witness from a list of hex strings [#4366](https://github.com/rust-bitcoin/rust-bitcoin/pull/4366) +- Implement `FromIterator` for `Witness` [#4365](https://github.com/rust-bitcoin/rust-bitcoin/pull/4365) +- Return `ControlBlock` from `Witness::taproot_control_block` [#4281](https://github.com/rust-bitcoin/rust-bitcoin/pull/4281) +- Witness api improvements and test cleanups [#4279](https://github.com/rust-bitcoin/rust-bitcoin/pull/4279) +- Implement `Display` for `Header` [#4269](https://github.com/rust-bitcoin/rust-bitcoin/pull/4269) +- Make `hex` optional [#4262](https://github.com/rust-bitcoin/rust-bitcoin/pull/4262) +- Clean up Witness API [#4186](https://github.com/rust-bitcoin/rust-bitcoin/pull/4186) +- Move `taproot` back to `bitcoin` crate [#4129](https://github.com/rust-bitcoin/rust-bitcoin/pull/4129) +- Make `transaction::Version` field private [#4099](https://github.com/rust-bitcoin/rust-bitcoin/pull/4099) +- Hide error internals [#4091](https://github.com/rust-bitcoin/rust-bitcoin/pull/4091) +- locktimes: Remove `PartialOrd` and `ArbitraryOrd` [#4065](https://github.com/rust-bitcoin/rust-bitcoin/pull/4065) +- Make `Debug` representation of `Witness` to be slice of hex-encoded + bytes strings to improve readability [#4061](https://github.com/rust-bitcoin/rust-bitcoin/pull/4061) +- Implement `Default` for `Script` [#4043](https://github.com/rust-bitcoin/rust-bitcoin/pull/4043) +- Store `transaction::Version` as `u32` instead of `i32` [#4040](https://github.com/rust-bitcoin/rust-bitcoin/pull/4040) +- Delete `TxOut::NULL` [#3978](https://github.com/rust-bitcoin/rust-bitcoin/pull/3978) +- Reduce alloc requirements [#3711](https://github.com/rust-bitcoin/rust-bitcoin/pull/3711) +- Remove `serde` from amounts [#3672](https://github.com/rust-bitcoin/rust-bitcoin/pull/3672) +- Fix bug in witness stack getters [#3601](https://github.com/rust-bitcoin/rust-bitcoin/pull/3601) +- Re-design and move `Block` to `primitives` [#3582](https://github.com/rust-bitcoin/rust-bitcoin/pull/3582) +- Re-export `block::Header` as `BlockHeader` [#3562](https://github.com/rust-bitcoin/rust-bitcoin/pull/3562) +- Favour `to_vec` over `to_bytes` [#3544](https://github.com/rust-bitcoin/rust-bitcoin/pull/3544) + +## Locktimes + +Lock times got a bit of work. A big win was: + +- Improve lock times - fix off-by-one bug #4468 + +There was a bit of churn so we are not listing all the PRs. Better +just to take a look at the new and improved API. + +If you persist locktimes using `serde` you may want to look at because +we changed the format: + +- Modify locktime serde implementations #4511 + +## Arbitrary + +- Add Arbitrary impl for BlockHash, TxMerkleNode, and Wtxid #4720 +- Add Arbitrary impl for relative::LockTime #4689 + +## Mutation testing + +The whole crate is mutation tested using `cargo-mutants` - BOOM! + +# 0.101.0 - 2024-11-15 + +This is the first "real" release of the `primitives` crate, as such it +includes a lot of work. Search GitHub with the following filter to see +all related PRs: `is:pr label:C-primitives merged:<=2024-11-15` + +Move the following modules and types from `rust-bitcoin` to `bitcoin-primitives`: + +- `block`: `Block`, `Header`, `Version`, `BlockHash`, `WitnessCommitment`, `Validation`, `Checked`, `Unchecked` +- `locktime`: `absolute::LockTime`, `relative::LockTime` +- `merkle_tree`: `TxMerkleNode`, `WitnessMerkleNode` +- `opcodes`: `Opcode` +- `pow`: `CompactTarget` +- `sequence`: `Sequence` +- `taproot`: `TapBranchTag`, `TapLeafHash`, `TapLeafTag`, `TapNodeHash`, `TapTweakHash`, `TapTweakTag` +- `transaction`: `Transaction`, `TxIn`, `TxOut`, `OutPoint`, `Txid`, `Wtxid`, `Version` +- `witness`: `Witness`, `Iter` + +And various error types. See re-exports at the crate root and also in `rust-bitcoin` at the crate +root and from the respective module. + +We hope to very soon release `primitives 1.0` - please raise any and all issues you come across no +matter how small so we can fix them for the stable release. + +Enjoy! + +# 0.100.0 - 2024-07-01 + +* Initial release of the `github.com/rust-bitcoin/rust-bitcoin/primitives` crate as + `bitcoin-primitives`. The name on crates.io was generously transferred to us. diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml new file mode 100644 index 000000000..0cd7da938 --- /dev/null +++ b/primitives/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "bitcoin-primitives" +version = "1.0.0-rc.1" +authors = ["Andrew Poelstra ", "Tobin C. Harding "] +license = "CC0-1.0" +repository = "https://github.com/rust-bitcoin/rust-bitcoin" +description = "Primitive types used by the rust-bitcoin ecosystem" +categories = ["cryptography::cryptocurrencies", "no-std"] +keywords = ["bitcoin", "types"] +readme = "README.md" +edition = "2021" +rust-version = "1.74.0" +exclude = ["tests", "contrib"] + +[features] +default = ["std", "hex"] +std = ["alloc", "hashes/std", "hex-stable?/std", "hex-unstable?/std", "internals/std", "units/std", "arrayvec/std"] +alloc = ["hashes/alloc", "hex-stable?/alloc", "hex-unstable?/alloc", "internals/alloc", "units/alloc"] +serde = ["dep:serde", "hashes/serde", "internals/serde", "units/serde", "alloc", "hex"] +arbitrary = ["dep:arbitrary", "units/arbitrary"] +hex = ["dep:hex-stable", "dep:hex-unstable", "hashes/hex", "internals/hex"] + +[dependencies] +encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "=1.0.0-rc.2", default-features = false } +hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.18.0", default-features = false } +internals = { package = "bitcoin-internals", path = "../internals", version = "0.4.1" } +units = { package = "bitcoin-units", path = "../units", version = "=1.0.0-rc.3", default-features = false, features = [ "encoding" ] } +arrayvec = { version = "0.7.2", default-features = false } + +arbitrary = { version = "1.4.1", optional = true } +hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false, optional = true } +hex-unstable = { package = "hex-conservative", version = "0.3.0", default-features = false, optional = true } +serde = { version = "1.0.195", default-features = false, features = ["derive", "alloc"], optional = true } + +[dev-dependencies] +serde_json = "1.0.68" +bincode = "1.3.1" +hex_lit = "0.1.1" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true diff --git a/primitives/README.md b/primitives/README.md new file mode 100644 index 000000000..979cc40df --- /dev/null +++ b/primitives/README.md @@ -0,0 +1,9 @@ +# Rust Bitcoin - primitive types. + +This crate provides primitive data types that are used throughout the +[`rust-bitcoin`](https://github.com/rust-bitcoin) ecosystem. + +## Semver compliance + +Functions marked as unstable (e.g. `foo__unstable`) are not guaranteed to uphold semver compliance. +They are primarily provided to support `rust-bitcoin`. diff --git a/primitives/contrib/extra_lints.sh b/primitives/contrib/extra_lints.sh new file mode 100755 index 000000000..5e7f0c948 --- /dev/null +++ b/primitives/contrib/extra_lints.sh @@ -0,0 +1,4 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 + +cargo clippy --all-targets --no-default-features --keep-going -- -D warnings diff --git a/primitives/contrib/test_vars.sh b/primitives/contrib/test_vars.sh new file mode 100644 index 000000000..159713bb9 --- /dev/null +++ b/primitives/contrib/test_vars.sh @@ -0,0 +1,14 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test these features with "std" enabled. +FEATURES_WITH_STD="serde arbitrary" + +# Test these features without "std" enabled. +FEATURES_WITHOUT_STD="alloc serde arbitrary" + +# Run these examples. +EXAMPLES="" diff --git a/primitives/src/block.rs b/primitives/src/block.rs new file mode 100644 index 000000000..8bb15166e --- /dev/null +++ b/primitives/src/block.rs @@ -0,0 +1,1330 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin blocks. +//! +//! A block is a bundle of transactions with a proof-of-work attached, +//! which commits to an earlier block to form the blockchain. This +//! module describes structures and functions needed to describe +//! these blocks and the blockchain. + +use core::convert::Infallible; +use core::fmt; +#[cfg(feature = "alloc")] +use core::marker::PhantomData; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use encoding::Encodable; +#[cfg(feature = "alloc")] +use encoding::{CompactSizeEncoder, Decodable, Decoder, Decoder2, Decoder6, Encoder2, SliceEncoder, VecDecoder}; +use hashes::{sha256d, HashEngine as _}; +use internals::write_err; + +#[cfg(feature = "alloc")] +use crate::pow::{CompactTargetDecoder, CompactTargetDecoderError}; +#[cfg(feature = "alloc")] +use crate::prelude::Vec; +#[cfg(feature = "alloc")] +use crate::transaction::{TxMerkleNodeDecoder, TxMerkleNodeDecoderError}; +use crate::{BlockTime, CompactTarget, TxMerkleNode}; +#[cfg(feature = "alloc")] +use crate::{BlockTimeDecoder, BlockTimeDecoderError, Transaction, WitnessMerkleNode}; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use units::block::{BlockHeight, BlockHeightDecoder, BlockHeightEncoder, BlockHeightInterval, BlockMtp, BlockMtpInterval}; +// Re-export errors that appear directly in the API - but no doc inline. +#[doc(no_inline)] +pub use units::block::{BlockHeightDecoderError, TooBigForRelativeHeightError}; + +#[doc(inline)] +pub use crate::hash_types::{ + BlockHash, BlockHashDecoder, BlockHashDecoderError, BlockHashEncoder, WitnessCommitment, +}; + +/// Marker for whether or not a block has been validated. +/// +/// We define valid as: +/// +/// * The Merkle root of the header matches Merkle root of the transaction list. +/// * The witness commitment in coinbase matches the transaction list. +/// +/// See `bitcoin::block::BlockUncheckedExt::validate()`. +#[cfg(feature = "alloc")] +pub trait Validation: sealed::Validation + Sync + Send + Sized + Unpin { + /// Indicates whether this `Validation` is `Checked` or not. + const IS_CHECKED: bool; +} + +/// Bitcoin block. +/// +/// A collection of transactions with an attached proof of work. +/// +/// See [Bitcoin Wiki: Block][wiki-block] for more information. +/// +/// [wiki-block]: https://en.bitcoin.it/wiki/Block +/// +/// # Bitcoin Core References +/// +/// * [CBlock definition](https://github.com/bitcoin/bitcoin/blob/345457b542b6a980ccfbc868af0970a6f91d1b82/src/primitives/block.h#L62) +#[cfg(feature = "alloc")] +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct Block +where + V: Validation, +{ + /// The block header + header: Header, + /// List of transactions contained in the block + transactions: Vec, + /// Cached witness root if it's been computed. + witness_root: Option, + /// Validation marker. + _marker: PhantomData, +} + +#[cfg(feature = "alloc")] +impl Block { + /// Constructs a new `Block` without doing any validation. + #[inline] + pub fn new_unchecked(header: Header, transactions: Vec) -> Self { + Self { header, transactions, witness_root: None, _marker: PhantomData:: } + } + + /// Ignores block validation logic and just assumes you know what you are doing. + /// + /// You should only use this function if you trust the block i.e., it comes from a trusted node. + #[must_use] + #[inline] + pub fn assume_checked(self, witness_root: Option) -> Block { + Block { + header: self.header, + transactions: self.transactions, + witness_root, + _marker: PhantomData::, + } + } + + /// Decomposes block into its constituent parts. + #[inline] + pub fn into_parts(self) -> (Header, Vec) { (self.header, self.transactions) } + + /// Validates (or checks) a block. + /// + /// We define valid as: + /// + /// * The Merkle root of the header matches Merkle root of the transaction list. + /// * The witness commitment in coinbase matches the transaction list. + pub fn validate(self) -> Result, InvalidBlockError> { + if self.transactions.is_empty() { + return Err(InvalidBlockError::NoTransactions); + } + + if !self.transactions[0].is_coinbase() { + return Err(InvalidBlockError::InvalidCoinbase); + } + + if !self.check_merkle_root() { + return Err(InvalidBlockError::InvalidMerkleRoot); + } + + match self.check_witness_commitment() { + (false, _) => Err(InvalidBlockError::InvalidWitnessCommitment), + (true, witness_root) => { + let block = Self::new_unchecked(self.header, self.transactions); + Ok(block.assume_checked(witness_root)) + } + } + } + + /// Checks if Merkle root of header matches Merkle root of the transaction list. + pub fn check_merkle_root(&self) -> bool { + match compute_merkle_root(&self.transactions) { + Some(merkle_root) => self.header.merkle_root == merkle_root, + None => false, + } + } + + /// Computes the witness commitment for a list of transactions. + pub fn compute_witness_commitment(&self, witness_reserved_value: &[u8]) -> Option<(WitnessMerkleNode, WitnessCommitment)> { + compute_witness_root(&self.transactions).map(|witness_root| { + let mut encoder = sha256d::Hash::engine(); + encoder = hashes::encode_to_engine(&witness_root, encoder); + encoder.input(witness_reserved_value); + let witness_commitment = + WitnessCommitment::from_byte_array(sha256d::Hash::from_engine(encoder).to_byte_array()); + (witness_root, witness_commitment) + }) + } + + /// Checks if witness commitment in coinbase matches the transaction list. + // Returns the Merkle root if it was computed (so it can be cached in `assume_checked`). + pub fn check_witness_commitment(&self) -> (bool, Option) { + if self.transactions.is_empty() { + return (false, None); + } + + // Witness commitment is optional if there are no transactions using SegWit in the block. + if self.transactions.iter().all(|t| t.inputs.iter().all(|i| i.witness.is_empty())) { + return (true, None); + } + + if self.transactions[0].is_coinbase() { + let coinbase = self.transactions[0].clone(); + if let Some(commitment) = witness_commitment_from_coinbase(&coinbase) { + // Witness reserved value is in coinbase input witness. + let witness_vec: Vec<_> = coinbase.inputs[0].witness.iter().collect(); + if witness_vec.len() == 1 && witness_vec[0].len() == 32 { + if let Some((witness_root, witness_commitment)) = + self.compute_witness_commitment(witness_vec[0]) + { + if commitment == witness_commitment { + return (true, Some(witness_root)); + } + } + } + } + } + + (false, None) + } +} + +#[cfg(feature = "alloc")] +impl Block { + /// Gets a reference to the block header. + #[inline] + pub fn header(&self) -> &Header { &self.header } + + /// Gets a reference to the block's list of transactions. + #[inline] + pub fn transactions(&self) -> &[Transaction] { &self.transactions } + + /// Returns the cached witness root if one is present. + /// + /// It is assumed that a block will have the witness root calculated and cached as part of the + /// validation process. + #[inline] + pub fn cached_witness_root(&self) -> Option { self.witness_root } +} + +#[cfg(feature = "alloc")] +impl Block { + /// Returns the block hash. + #[inline] + pub fn block_hash(&self) -> BlockHash { self.header.block_hash() } +} + +#[cfg(feature = "alloc")] +impl From for BlockHash { + #[inline] + fn from(block: Block) -> Self { block.block_hash() } +} + +#[cfg(feature = "alloc")] +impl From<&Block> for BlockHash { + #[inline] + fn from(block: &Block) -> Self { block.block_hash() } +} + +/// Marker that the block's merkle root has been successfully validated. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg(feature = "alloc")] +pub enum Checked {} + +#[cfg(feature = "alloc")] +impl Validation for Checked { + const IS_CHECKED: bool = true; +} + +/// Marker that the block's merkle root has not been validated. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg(feature = "alloc")] +pub enum Unchecked {} + +#[cfg(feature = "alloc")] +impl Validation for Unchecked { + const IS_CHECKED: bool = false; +} + +#[cfg(feature = "alloc")] +mod sealed { + /// Seals the block validation marker traits. + pub trait Validation {} + impl Validation for super::Checked {} + impl Validation for super::Unchecked {} +} + +#[cfg(feature = "alloc")] +encoding::encoder_newtype! { + /// The encoder for the [`Block`] type. + pub struct BlockEncoder<'e>( + Encoder2>> + ); +} + +#[cfg(feature = "alloc")] +impl Encodable for Block { + type Encoder<'e> + = Encoder2>> + where + Self: 'e; + + fn encoder(&self) -> Self::Encoder<'_> { + Encoder2::new( + self.header.encoder(), + Encoder2::new( + CompactSizeEncoder::new(self.transactions.len()), + SliceEncoder::without_length_prefix(&self.transactions), + ), + ) + } +} + +#[cfg(feature = "alloc")] +type BlockInnerDecoder = Decoder2>; + +/// The decoder for the [`Block`] type. +/// +/// This decoder can only produce a `Block`. +#[cfg(feature = "alloc")] +pub struct BlockDecoder(BlockInnerDecoder); + +#[cfg(feature = "alloc")] +impl Decoder for BlockDecoder { + type Output = Block; + type Error = BlockDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.0.push_bytes(bytes).map_err(BlockDecoderError) + } + + #[inline] + fn end(self) -> Result { + let (header, transactions) = self.0.end().map_err(BlockDecoderError)?; + Ok(Self::Output::new_unchecked(header, transactions)) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +#[cfg(feature = "alloc")] +impl Decodable for Block { + type Decoder = BlockDecoder; + fn decoder() -> Self::Decoder { + BlockDecoder(Decoder2::new( + Header::decoder(), + VecDecoder::::new(), + )) + } +} + +/// An error consensus decoding a [`Block`]. +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BlockDecoderError(::Error); + +#[cfg(feature = "alloc")] +impl From for BlockDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +#[cfg(feature = "alloc")] +impl fmt::Display for BlockDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self.0 { + encoding::Decoder2Error::First(ref e) => write_err!(f, "block decoder error"; e), + encoding::Decoder2Error::Second(ref e) => write_err!(f, "block decoder error"; e), + } + } +} + +#[cfg(feature = "alloc")] +#[cfg(feature = "std")] +impl std::error::Error for BlockDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match &self.0 { + encoding::Decoder2Error::First(ref e) => Some(e), + encoding::Decoder2Error::Second(ref e) => Some(e), + } + } +} + +/// Invalid block error. +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum InvalidBlockError { + /// Header Merkle root does not match the calculated Merkle root. + InvalidMerkleRoot, + /// The witness commitment in coinbase transaction does not match the calculated `witness_root`. + InvalidWitnessCommitment, + /// Block has no transactions (missing coinbase). + NoTransactions, + /// The first transaction is not a valid coinbase transaction. + InvalidCoinbase, +} + +#[cfg(feature = "alloc")] +impl From for InvalidBlockError { + fn from(never: Infallible) -> Self { match never {} } +} + +#[cfg(feature = "alloc")] +impl fmt::Display for InvalidBlockError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::InvalidMerkleRoot => + write!(f, "header Merkle root does not match the calculated Merkle root"), + Self::InvalidWitnessCommitment => write!(f, "the witness commitment in coinbase transaction does not match the calculated witness_root"), + Self::NoTransactions => write!(f, "block has no transactions (missing coinbase)"), + Self::InvalidCoinbase => + write!(f, "the first transaction is not a valid coinbase transaction"), + } + } +} + +#[cfg(feature = "alloc")] +#[cfg(feature = "std")] +impl std::error::Error for InvalidBlockError {} + +/// Computes the Merkle root for a list of transactions. +/// +/// Returns `None` if the iterator was empty, or if the transaction list contains +/// consecutive duplicates which would trigger CVE 2012-2459. Blocks with duplicate +/// transactions will always be invalid, so there is no harm in us refusing to +/// compute their merkle roots. +/// +/// Unless you are certain your transaction list is nonempty and has no duplicates, +/// you should not unwrap the `Option` returned by this method! +#[cfg(feature = "alloc")] +pub fn compute_merkle_root(transactions: &[Transaction]) -> Option { + let hashes = transactions.iter().map(Transaction::compute_txid); + TxMerkleNode::calculate_root(hashes) +} + +/// Computes the Merkle root of transactions hashed for witness. +/// +/// Returns `None` if the iterator was empty, or if the transaction list contains +/// consecutive duplicates which would trigger CVE 2012-2459. Blocks with duplicate +/// transactions will always be invalid, so there is no harm in us refusing to +/// compute their merkle roots. +/// +/// Unless you are certain your transaction list is nonempty and has no duplicates, +/// you should not unwrap the `Option` returned by this method! +#[cfg(feature = "alloc")] +pub fn compute_witness_root(transactions: &[Transaction]) -> Option { + let hashes = transactions.iter().enumerate().map(|(i, t)| { + if i == 0 { + // Replace the first hash with zeroes. + crate::Wtxid::COINBASE + } else { + t.compute_wtxid() + } + }); + WitnessMerkleNode::calculate_root(hashes) +} + +#[cfg(feature = "alloc")] +fn witness_commitment_from_coinbase(coinbase: &Transaction) -> Option { + // Consists of OP_RETURN, OP_PUSHBYTES_36, and four "witness header" bytes. + const MAGIC: [u8; 6] = [0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed]; + + if !coinbase.is_coinbase() { + return None; + } + + // Commitment is in the last output that starts with magic bytes. + if let Some(pos) = coinbase + .outputs + .iter() + .rposition(|o| o.script_pubkey.len() >= 38 && o.script_pubkey.as_bytes()[0..6] == MAGIC) + { + let bytes = + <[u8; 32]>::try_from(&coinbase.outputs[pos].script_pubkey.as_bytes()[6..38]).unwrap(); + Some(WitnessCommitment::from_byte_array(bytes)) + } else { + None + } +} + +/// Bitcoin block header. +/// +/// Contains all the block's information except the actual transactions, but +/// including a root of a [Merkle tree] committing to all transactions in the block. +/// +/// [Merkle tree]: https://en.wikipedia.org/wiki/Merkle_tree +/// +/// # Bitcoin Core References +/// +/// * [CBlockHeader definition](https://github.com/bitcoin/bitcoin/blob/345457b542b6a980ccfbc868af0970a6f91d1b82/src/primitives/block.h#L20) +#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] +pub struct Header { + /// Block version, now repurposed for soft fork signalling. + pub version: Version, + /// Reference to the previous block in the chain. + pub prev_blockhash: BlockHash, + /// The root hash of the Merkle tree of transactions in the block. + pub merkle_root: TxMerkleNode, + /// The timestamp of the block, as claimed by the miner. + pub time: BlockTime, + /// The target value below which the blockhash must lie. + pub bits: CompactTarget, + /// The nonce, selected to obtain a low enough blockhash. + pub nonce: u32, +} + +impl Header { + /// The number of bytes that the block header contributes to the size of a block. + // Serialized length of fields (version, prev_blockhash, merkle_root, time, bits, nonce) + pub const SIZE: usize = 4 + 32 + 32 + 4 + 4 + 4; // 80 + + /// Returns the block hash. + // This is the same as `Encodable` but done manually because `Encodable` isn't in `primitives`. + pub fn block_hash(&self) -> BlockHash { + let bare_hash = hashes::encode_to_engine(self, sha256d::Hash::engine()).finalize(); + BlockHash::from_byte_array(bare_hash.to_byte_array()) + } +} + +#[cfg(feature = "hex")] +impl fmt::Display for Header { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use fmt::Write as _; + use hex_unstable::DisplayHex as _; + + let mut buf = arrayvec::ArrayString::<160>::new(); + write!( + &mut buf, + "{}{}{}{}{}{}", + self.version.to_consensus().to_le_bytes().as_hex(), + self.prev_blockhash.as_byte_array().as_hex(), + self.merkle_root.as_byte_array().as_hex(), + self.time.to_u32().to_le_bytes().as_hex(), + self.bits.to_consensus().to_le_bytes().as_hex(), + self.nonce.to_le_bytes().as_hex(), + ) + .expect("total length of written objects is 160 characters"); + fmt::Display::fmt(&buf, f) + } +} + +impl fmt::Debug for Header { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Header") + .field("block_hash", &self.block_hash()) + .field("version", &self.version) + .field("prev_blockhash", &self.prev_blockhash) + .field("merkle_root", &self.merkle_root) + .field("time", &self.time) + .field("bits", &self.bits) + .field("nonce", &self.nonce) + .finish() + } +} + +encoding::encoder_newtype! { + /// The encoder for the [`Header`] type. + pub struct HeaderEncoder( + encoding::Encoder6< + VersionEncoder, + BlockHashEncoder, + crate::merkle_tree::TxMerkleNodeEncoder, + crate::time::BlockTimeEncoder, + crate::pow::CompactTargetEncoder, + encoding::ArrayEncoder<4>, + > + ); +} + +impl Encodable for Header { + type Encoder<'e> = HeaderEncoder; + + fn encoder(&self) -> Self::Encoder<'_> { + HeaderEncoder(encoding::Encoder6::new( + self.version.encoder(), + self.prev_blockhash.encoder(), + self.merkle_root.encoder(), + self.time.encoder(), + self.bits.encoder(), + encoding::ArrayEncoder::without_length_prefix(self.nonce.to_le_bytes()), + )) + } +} + +#[cfg(feature = "alloc")] +type HeaderInnerDecoder = Decoder6< + VersionDecoder, + BlockHashDecoder, + TxMerkleNodeDecoder, + BlockTimeDecoder, + CompactTargetDecoder, + encoding::ArrayDecoder<4>, // Nonce +>; + +/// The decoder for the [`Header`] type. +#[cfg(feature = "alloc")] +pub struct HeaderDecoder(HeaderInnerDecoder); + +#[cfg(feature = "alloc")] +impl HeaderDecoder { + fn from_inner(e: ::Error) -> HeaderDecoderError { + match e { + encoding::Decoder6Error::First(e) => HeaderDecoderError::Version(e), + encoding::Decoder6Error::Second(e) => HeaderDecoderError::PrevBlockhash(e), + encoding::Decoder6Error::Third(e) => HeaderDecoderError::MerkleRoot(e), + encoding::Decoder6Error::Fourth(e) => HeaderDecoderError::Time(e), + encoding::Decoder6Error::Fifth(e) => HeaderDecoderError::Bits(e), + encoding::Decoder6Error::Sixth(e) => HeaderDecoderError::Nonce(e), + } + } +} + +#[cfg(feature = "alloc")] +impl Decoder for HeaderDecoder { + type Output = Header; + type Error = HeaderDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + self.0.push_bytes(bytes).map_err(Self::from_inner) + } + + #[inline] + fn end(self) -> Result { + let (version, prev_blockhash, merkle_root, time, bits, nonce) = + self.0.end().map_err(Self::from_inner)?; + let nonce = u32::from_le_bytes(nonce); + Ok(Header { version, prev_blockhash, merkle_root, time, bits, nonce }) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +#[cfg(feature = "alloc")] +impl Decodable for Header { + type Decoder = HeaderDecoder; + fn decoder() -> Self::Decoder { + HeaderDecoder(Decoder6::new( + VersionDecoder::new(), + BlockHashDecoder::new(), + TxMerkleNodeDecoder::new(), + BlockTimeDecoder::new(), + CompactTargetDecoder::new(), + encoding::ArrayDecoder::new(), + )) + } +} + +/// An error consensus decoding a `Header`. +#[cfg(feature = "alloc")] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum HeaderDecoderError { + /// Error while decoding the `version`. + Version(VersionDecoderError), + /// Error while decoding the `prev_blockhash`. + PrevBlockhash(BlockHashDecoderError), + /// Error while decoding the `merkle_root`. + MerkleRoot(TxMerkleNodeDecoderError), + /// Error while decoding the `time`. + Time(BlockTimeDecoderError), + /// Error while decoding the `bits`. + Bits(CompactTargetDecoderError), + /// Error while decoding the `nonce`. + Nonce(encoding::UnexpectedEofError), +} + +#[cfg(feature = "alloc")] +impl From for HeaderDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +#[cfg(feature = "alloc")] +impl fmt::Display for HeaderDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Version(ref e) => write_err!(f, "header decoder error"; e), + Self::PrevBlockhash(ref e) => write_err!(f, "header decoder error"; e), + Self::MerkleRoot(ref e) => write_err!(f, "header decoder error"; e), + Self::Time(ref e) => write_err!(f, "header decoder error"; e), + Self::Bits(ref e) => write_err!(f, "header decoder error"; e), + Self::Nonce(ref e) => write_err!(f, "header decoder error"; e), + } + } +} + +#[cfg(feature = "std")] +#[cfg(feature = "alloc")] +impl std::error::Error for HeaderDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + Self::Version(ref e) => Some(e), + Self::PrevBlockhash(ref e) => Some(e), + Self::MerkleRoot(ref e) => Some(e), + Self::Time(ref e) => Some(e), + Self::Bits(ref e) => Some(e), + Self::Nonce(ref e) => Some(e), + } + } +} + +impl From
for BlockHash { + #[inline] + fn from(header: Header) -> Self { header.block_hash() } +} + +impl From<&Header> for BlockHash { + #[inline] + fn from(header: &Header) -> Self { header.block_hash() } +} + +/// Bitcoin block version number. +/// +/// Originally used as a protocol version, but repurposed for soft-fork signaling. +/// +/// The inner value is a signed integer in Bitcoin Core for historical reasons, if the version bits are +/// being used the top three bits must be 001, this gives us a useful range of [0x20000000...0x3FFFFFFF]. +/// +/// > When a block nVersion does not have top bits 001, it is treated as if all bits are 0 for the purposes of deployments. +/// +/// # Relevant BIPs +/// +/// * [BIP-0009 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) +/// * [BIP-0034 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki) +#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct Version(i32); + +impl Version { + /// The original Bitcoin Block v1. + pub const ONE: Self = Self(1); + + /// BIP-0034 Block v2. + pub const TWO: Self = Self(2); + + /// BIP-0009 compatible version number that does not signal for any softforks. + pub const NO_SOFT_FORK_SIGNALLING: Self = Self(Self::USE_VERSION_BITS as i32); + + /// BIP-0009 soft fork signal bits mask. + const VERSION_BITS_MASK: u32 = 0x1FFF_FFFF; + + /// 32bit value starting with `001` to use version bits. + /// + /// The value has the top three bits `001` which enables the use of version bits to signal for soft forks. + const USE_VERSION_BITS: u32 = 0x2000_0000; + + /// Constructs a new [`Version`] from a signed 32 bit integer value. + /// + /// This is the data type used in consensus code in Bitcoin Core. + #[inline] + pub const fn from_consensus(v: i32) -> Self { Self(v) } + + /// Returns the inner `i32` value. + /// + /// This is the data type used in consensus code in Bitcoin Core. + #[inline] + pub const fn to_consensus(self) -> i32 { self.0 } + + /// Checks whether the version number is signalling a soft fork at the given bit. + /// + /// A block is signalling for a soft fork under BIP-0009 if the first 3 bits are `001` and + /// the version bit for the specific soft fork is toggled on. + pub fn is_signalling_soft_fork(self, bit: u8) -> bool { + // Only bits [0, 28] inclusive are used for signalling. + if bit > 28 { + return false; + } + + // To signal using version bits, the first three bits must be `001`. + if (self.0 as u32) & !Self::VERSION_BITS_MASK != Self::USE_VERSION_BITS { + return false; + } + + // The bit is set if signalling a soft fork. + (self.0 as u32 & Self::VERSION_BITS_MASK) & (1 << bit) > 0 + } +} + +impl Default for Version { + #[inline] + fn default() -> Self { Self::NO_SOFT_FORK_SIGNALLING } +} + +encoding::encoder_newtype! { + /// The encoder for the [`Version`] type. + pub struct VersionEncoder(encoding::ArrayEncoder<4>); +} + +impl Encodable for Version { + type Encoder<'e> = VersionEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + VersionEncoder(encoding::ArrayEncoder::without_length_prefix( + self.to_consensus().to_le_bytes(), + )) + } +} + +/// The decoder for the [`Version`] type. +pub struct VersionDecoder(encoding::ArrayDecoder<4>); + +impl VersionDecoder { + /// Constructs a new [`Version`] decoder. + pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) } +} + +impl Default for VersionDecoder { + fn default() -> Self { Self::new() } +} + +impl encoding::Decoder for VersionDecoder { + type Output = Version; + type Error = VersionDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + Ok(self.0.push_bytes(bytes)?) + } + + #[inline] + fn end(self) -> Result { + let n = i32::from_le_bytes(self.0.end()?); + Ok(Version::from_consensus(n)) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +impl encoding::Decodable for Version { + type Decoder = VersionDecoder; + fn decoder() -> Self::Decoder { VersionDecoder(encoding::ArrayDecoder::<4>::new()) } +} + +/// An error consensus decoding an `Version`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct VersionDecoderError(encoding::UnexpectedEofError); + +impl From for VersionDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for VersionDecoderError { + fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) } +} + +impl fmt::Display for VersionDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "version decoder error"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for VersionDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} + +#[cfg(feature = "arbitrary")] +#[cfg(feature = "alloc")] +impl<'a> Arbitrary<'a> for Block { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let header = Header::arbitrary(u)?; + let transactions = Vec::::arbitrary(u)?; + Ok(Self::new_unchecked(header, transactions)) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Header { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + Ok(Self { + version: Version::arbitrary(u)?, + prev_blockhash: BlockHash::from_byte_array(u.arbitrary()?), + merkle_root: TxMerkleNode::from_byte_array(u.arbitrary()?), + time: u.arbitrary()?, + bits: CompactTarget::from_consensus(u.arbitrary()?), + nonce: u.arbitrary()?, + }) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for Version { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + // Equally weight known versions and arbitrary versions + let choice = u.int_in_range(0..=3)?; + match choice { + 0 => Ok(Self::ONE), + 1 => Ok(Self::TWO), + 2 => Ok(Self::NO_SOFT_FORK_SIGNALLING), + _ => Ok(Self::from_consensus(u.arbitrary()?)), + } + } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "alloc")] + use alloc::{format, vec}; + + use super::*; + + fn dummy_header() -> Header { + Header { + version: Version::ONE, + prev_blockhash: BlockHash::from_byte_array([0x99; 32]), + merkle_root: TxMerkleNode::from_byte_array([0x77; 32]), + time: BlockTime::from(2), + bits: CompactTarget::from_consensus(3), + nonce: 4, + } + } + + #[test] + fn version_is_not_signalling_with_invalid_bit() { + let arbitrary_version = Version::from_consensus(1_234_567_890); + // The max bit number to signal is 28. + assert!(!Version::is_signalling_soft_fork(arbitrary_version, 29)); + } + + #[test] + fn version_is_not_signalling_when_use_version_bit_not_set() { + let version = Version::from_consensus(0b0100_0000_0000_0000_0000_0000_0000_0000); + // Top three bits must be 001 to signal. + assert!(!Version::is_signalling_soft_fork(version, 1)); + } + + #[test] + fn version_is_signalling() { + let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010); + assert!(Version::is_signalling_soft_fork(version, 1)); + let version = Version::from_consensus(0b0011_0000_0000_0000_0000_0000_0000_0000); + assert!(Version::is_signalling_soft_fork(version, 28)); + } + + #[test] + fn version_is_not_signalling() { + let version = Version::from_consensus(0b0010_0000_0000_0000_0000_0000_0000_0010); + assert!(!Version::is_signalling_soft_fork(version, 0)); + } + + #[test] + fn version_to_consensus() { + let version = Version::from_consensus(1_234_567_890); + assert_eq!(version.to_consensus(), 1_234_567_890); + } + + #[test] + fn version_default() { + let version = Version::default(); + assert_eq!(version.to_consensus(), Version::NO_SOFT_FORK_SIGNALLING.to_consensus()); + } + + // Check that the size of the header consensus serialization matches the const SIZE value + #[test] + fn header_size() { + let header = dummy_header(); + + // Calculate the size of the block header in bytes from the sum of the serialized lengths + // its fields: version, prev_blockhash, merkle_root, time, bits, nonce. + let header_size = header.version.to_consensus().to_le_bytes().len() + + header.prev_blockhash.as_byte_array().len() + + header.merkle_root.as_byte_array().len() + + header.time.to_u32().to_le_bytes().len() + + header.bits.to_consensus().to_le_bytes().len() + + header.nonce.to_le_bytes().len(); + + assert_eq!(header_size, Header::SIZE); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_new_unchecked() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions.clone()); + assert_eq!(block.header, header); + assert_eq!(block.transactions, transactions); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_assume_checked() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions.clone()); + let witness_root = Some(WitnessMerkleNode::from_byte_array([0x88; 32])); + let checked_block = block.assume_checked(witness_root); + assert_eq!(checked_block.header(), &header); + assert_eq!(checked_block.transactions(), &transactions); + assert_eq!(checked_block.cached_witness_root(), witness_root); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_into_parts() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions.clone()); + let (block_header, block_transactions) = block.into_parts(); + assert_eq!(block_header, header); + assert_eq!(block_transactions, transactions); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_cached_witness_root() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions); + let witness_root = Some(WitnessMerkleNode::from_byte_array([0x88; 32])); + let checked_block = block.assume_checked(witness_root); + assert_eq!(checked_block.cached_witness_root(), witness_root); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_validation_no_transactions() { + let header = dummy_header(); + let transactions = Vec::new(); // Empty transactions + + let block = Block::new_unchecked(header, transactions); + match block.validate() { + Err(InvalidBlockError::NoTransactions) => (), + other => panic!("Expected NoTransactions error, got: {:?}", other), + } + } + + #[test] + #[cfg(feature = "alloc")] + fn block_validation_invalid_coinbase() { + let header = dummy_header(); + + // Create a non-coinbase transaction (has a real previous output, not all zeros) + let non_coinbase_tx = Transaction { + version: crate::transaction::Version::TWO, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![crate::TxIn { + previous_output: crate::OutPoint { + txid: crate::Txid::from_byte_array([1; 32]), // Not all zeros + vout: 0, + }, + script_sig: crate::ScriptSigBuf::new(), + sequence: units::Sequence::ENABLE_LOCKTIME_AND_RBF, + witness: crate::Witness::new(), + }], + outputs: vec![crate::TxOut { amount: units::Amount::ONE_BTC, script_pubkey: crate::ScriptPubKeyBuf::new() }], + }; + + let transactions = vec![non_coinbase_tx]; + let block = Block::new_unchecked(header, transactions); + + match block.validate() { + Err(InvalidBlockError::InvalidCoinbase) => (), + other => panic!("Expected InvalidCoinbase error, got: {:?}", other), + } + } + + #[test] + #[cfg(feature = "alloc")] + fn block_check_witness_commitment_optional() { + // Valid block with optional witness commitment + let mut header = dummy_header(); + header.merkle_root = TxMerkleNode::from_byte_array([0u8; 32]); + let coinbase = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![crate::TxIn::EMPTY_COINBASE], + outputs: vec![], + }; + + let transactions = vec![coinbase]; + let block = Block::new_unchecked(header, transactions); + + let result = block.check_witness_commitment(); + assert_eq!(result, (true, None)); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_block_hash() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions); + assert_eq!(block.block_hash(), header.block_hash()); + } + + #[test] + fn block_hash_from_header() { + let header = dummy_header(); + let block_hash = header.block_hash(); + assert_eq!(block_hash, BlockHash::from(header)); + } + + #[test] + fn block_hash_from_header_ref() { + let header = dummy_header(); + let block_hash: BlockHash = BlockHash::from(&header); + assert_eq!(block_hash, header.block_hash()); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_hash_from_block() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions); + let block_hash: BlockHash = BlockHash::from(block); + assert_eq!(block_hash, header.block_hash()); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_hash_from_block_ref() { + let header = dummy_header(); + let transactions = vec![]; + let block = Block::new_unchecked(header, transactions); + let block_hash: BlockHash = BlockHash::from(&block); + assert_eq!(block_hash, header.block_hash()); + } + + #[test] + #[cfg(feature = "alloc")] + fn header_debug() { + let header = dummy_header(); + let expected = format!( + "Header {{ block_hash: {:?}, version: {:?}, prev_blockhash: {:?}, merkle_root: {:?}, time: {:?}, bits: {:?}, nonce: {:?} }}", + header.block_hash(), + header.version, + header.prev_blockhash, + header.merkle_root, + header.time, + header.bits, + header.nonce + ); + assert_eq!(format!("{:?}", header), expected); + } + + #[test] + #[cfg(feature = "hex")] + #[cfg(feature = "alloc")] + fn header_display() { + let seconds: u32 = 1_653_195_600; // Arbitrary timestamp: May 22nd, 5am UTC. + + let header = Header { + version: Version::TWO, + prev_blockhash: BlockHash::from_byte_array([0xab; 32]), + merkle_root: TxMerkleNode::from_byte_array([0xcd; 32]), + time: BlockTime::from(seconds), + bits: CompactTarget::from_consensus(0xbeef), + nonce: 0xcafe, + }; + + let want = concat!( + "02000000", // version + "abababababababababababababababababababababababababababababababab", // prev_blockhash + "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", // merkle_root + "50c38962", // time + "efbe0000", // bits + "feca0000", // nonce + ); + assert_eq!(want.len(), 160); + assert_eq!(format!("{}", header), want); + + // Check how formatting options are handled. + let want = format!("{:.20}", want); + let got = format!("{:.20}", header); + assert_eq!(got, want); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_decode() { + // Make a simple block, encode then decode. Verify equivalence. + let header = Header { + version: Version::ONE, + #[rustfmt::skip] + prev_blockhash: BlockHash::from_byte_array([ + 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, + 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, + 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, + 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, 0xDC, 0xBA, + ]), + #[rustfmt::skip] + merkle_root: TxMerkleNode::from_byte_array([ + 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, + 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, + 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, + 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, 0xAB, 0xCD, + ]), + time: BlockTime::from(1_742_979_600), // 26 Mar 2025 9:00 UTC + bits: CompactTarget::from_consensus(12_345_678), + nonce: 1024, + }; + + let block: u32 = 741_521; + let transactions = vec![ + Transaction { + version: crate::transaction::Version::ONE, + lock_time: units::absolute::LockTime::from_height(block).unwrap(), + inputs: vec![crate::transaction::TxIn::EMPTY_COINBASE], + outputs: Vec::new(), + }, + ]; + let original_block = Block::new_unchecked(header, transactions); + + // Encode + decode the block + let encoded = encoding::encode_to_vec(&original_block); + let decoded_block = encoding::decode_from_slice(encoded.as_slice()).unwrap(); + + assert_eq!(original_block, decoded_block); + } + + // Test vector provided by tm0 in issue #5023 + #[test] + #[cfg(all(feature = "alloc", feature = "hex"))] + fn merkle_tree_hash_collision() { + // https://learnmeabitcoin.com/explorer/block/00000000000008a662b4a95a46e4c54cb04852525ac0ef67d1bcac85238416d4 + // this block has 7 transactions + const BLOCK_128461_HEX: &str = "01000000166208c96de305f2a304130a1b53727abf8fb77e8a3cfe2a831e000000000000d4fd086755b4d46221362a09a4228bed60d729d22362b87803ff44b72c138ec04a8ce94d2194261af9551f720701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08042194261a026005ffffffff018076242a01000000434104390e51c3d66d5ee10327395872e33bc232e9e1660225c9f88fa594fdcdcd785d86b1152fb380a63cdf57d8cf2345a55878412a6864656b158704e0b734b3fd9dac000000000100000001f591edc180a889b21a45b6bd5b5e0017d4137dae9695703107ac1e6e878c9f02000000008b483045022100e066df28b29bf18bfcd8da11ea576a6f502f59e7b1d37e2e849ee4648008962b022023be840ec01ffa6860b5577bf0b8546541f40c287eb57b8b421a1396c7aea583014104add16286f51f68cee1b436d0c29a41a59fa8bd224eb6bec34b073512303c70fc3d630cb4952416ef02340c56bee2eef294659b4023ea8a3d90a297bdb54321f9ffffffff02508470b5000000001976a91472579bbeaeca0802fde07ce88f946b64da63989388ac40aeeb02000000001976a914d2a7410246b5ece345aa821af89bff0b6fa3bcaa88ac0000000001000000016197cb143d4cef51389076fdee3f62c294b65bc9aff217a6c71b9dd987e22754000000008c493046022100bf174e942e4619f4e470b5d8b1c0c8ded9e2f7a6616c073c5ab05cc9d699ede3022100a642fa9d0bcc89523635f9468e4813a120b233a249678de0ebf7ba398a4205f6014104122979c0ac1c3af2aa84b4c1d6a9b3b6fa491827f1a2ba37c4b58bdecd644438da715497a44b16aedbadbd18cf9765cdb36851284f643ed743c4365798dd314affffffff02c0404384000000001976a91443cd8fbad7421a53f9e899a2c9761259705d465b88acc0f4f50e000000001976a9142f6c963506b0a2c93a09a92171957e9e7e11a7a388ac00000000010000000228a11f953c26d558a8299ad9dc61279d7abc9a4059820b614bf403c05e471c481d0000008b48304502205baff189016e6fee8e0faa9eebdc8f150d2d3815007719ceccabd995607bb0b0022100f4cc49ef0b29561e976bf6f6f7ae135f665b8dd38a67634bb6bbe74c0da9c1f7014104dd5920aedc3f79ace9c8061f3724812f5b218ea81d175dd990071175874d6c79025f9db516ab23975e510645aabc4ee699cc5c24358a403d15a7736a504399f8ffffffff191b06773a7cec0bb30539f185edbf1d139f9756071c6ae395c1c29f3e2484f6010000008c493046022100c7123436476f923cd8dacbe132f5128b529baa194c9aedc570402d8d2d7902ac02210094e6974695265d96d5859ab493df00c90b62a84dcc33a05753aea23b38c249670141041d878bc5438ff439490e71d059e6b687e511336c0aa53e0d129663c91db71cfe20008891f1e4780bf1139ec9c9e81bfd2e3ea9009608a78d96a5a3a5bf7812baffffffff0200093d00000000001976a914fd0d4c3d0963db8358bd01ba6f386d4c5ef2e30288ac0084d717000000001976a914dcb1e8e699eb9f07a1ddfd5d764aa74359ddd93088ac00000000010000000118e2286c42643e6146669b0f5ee35454fe256aac2b1401dbeefd941f2e6d2074000000008b483045022100edec1c5078fed29d808282d62f167eb3f0ea6a6655f3869c12eca9c63d8463c2022031a3ae430be137932059b4a3e3fb7f1e1f2a05065dbc47c3142972de45c76daa01410423162e5ac10ec46c4a142fea3197cc66e614b9f28f014882ebc8271c4ab6022e474ccdc246445dd2479f9de217e8aaf4d770da15aff1078d329c02e0f4de8d77ffffffff02b00ac165000000001976a914f543a7f0dfcd621a05c646810ba94da791ed14c488ac80de8002000000001976a9144763f6309b3aca0bff49ed6365ffbd791b1afc5d88ac0000000001000000014e3632994e6cbcae4122bf9e8de242aa1d7c13bf6d045392fa69fa92353f13cf000000008c493046022100c6879938322e9945dae2404a2b104b534df7fdab5927a30a57a12418d619c3b8022100c53331f402010cbdc8297d7a827154e42263fc2f6cef6e56b85bbc061d5e30810141047e717e70b8c5e928bc2c482662dbe9007113f7a5fb0360da1d2f193add960fed97ab3163e85c02b127829d694ab4a796326918d4f639d0b19345f7558406667dffffffff0270c8b165000000001976a9146c908731300d5c0a4215ba3bb3041b4f313d14f688ac40420f00000000001976a91457b01e2a6bf178a10a0e36cd3e301a41ac58b68b88ac000000000100000001a2e94f26db15d7098104a3616b650cc7490eca961a23111c12c3d94f593ab3bc000000008c493046022100b355076f2c956d7565d44fdf589ebdbdff70abcd806c71845b47d31c3579cbc00221008352a03c5276ba481ae92a2327307ad1ce9b234be7386c105fb914ceb9c63341014104872ee8390f11c8ac309df772362614ff7c99f98e1fd68888c5e8765d630c93ae86fcd33922b17f5da490ea14a9f9002ef4e7fb11166ba399f9794296ca02e401ffffffff02f07d5460000000001976a914ff1da11fbd50b9906e78c694169c19902d2ee20388ac804a5d05000000001976a91444d5774b8277c59a07ed9dce1225e2d24a3faab188ac00000000"; + let bytes: [u8; 1948] = hex_unstable::FromHex::from_hex(BLOCK_128461_HEX).unwrap(); + let valid_block: Block = encoding::decode_from_slice(&bytes).unwrap(); + let (header, mut transactions) = valid_block.clone().into_parts(); + transactions.push(transactions[6].clone()); + let forged_block = Block::new_unchecked(header, transactions); + + assert!(valid_block.validate().is_ok()); + assert!(forged_block.validate().is_err()); + } + + #[test] + #[cfg(feature = "alloc")] + fn witness_commitment_from_coinbase_simple() { + // Add witness commitment to the coinbase + let magic = [0x6a, 0x24, 0xaa, 0x21, 0xa9, 0xed]; + let mut pubkey_bytes = [0; 38]; + pubkey_bytes[0..6].copy_from_slice(&magic); + let witness_commitment = WitnessCommitment::from_byte_array(pubkey_bytes[6..38].try_into().unwrap()); + let commitment_script = crate::script::ScriptBuf::from_bytes(pubkey_bytes.to_vec()); + + // Create a coinbase transaction with witness commitment + let tx = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![crate::TxIn::EMPTY_COINBASE], + outputs: vec![crate::TxOut { amount: units::Amount::MIN, script_pubkey: commitment_script }], + }; + + // Test if the witness commitment is extracted properly + let extracted = witness_commitment_from_coinbase(&tx); + assert_eq!(extracted, Some(witness_commitment)); + } + + #[test] + #[cfg(feature = "alloc")] + fn block_check_witness_commitment_empty_script_pubkey() { + let mut txin = crate::TxIn::EMPTY_COINBASE; + let push = [11_u8]; + txin.witness.push(push); + + let tx = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![txin], + outputs: vec![crate::TxOut { + amount: units::Amount::MIN, + // Empty scriptbuf means there is no witness commitment due to no magic bytes. + script_pubkey: crate::script::ScriptBuf::new(), + }], + }; + + let block = Block::new_unchecked(dummy_header(), vec![tx]); + let result = block.check_witness_commitment(); + assert_eq!(result, (false, None)); // (false, None) since there's no valid witness commitment + } + + #[test] + #[cfg(feature = "alloc")] + fn block_check_witness_commitment_no_transactions() { + // Test case of block with no transactions + let empty_block = Block::new_unchecked(dummy_header(), vec![]); + let result = empty_block.check_witness_commitment(); + assert_eq!(result, (false, None)); + } + + #[test] + #[cfg(all(feature = "alloc", feature = "hex"))] + fn block_check_witness_commitment_with_witness() { + let mut txin = crate::TxIn::EMPTY_COINBASE; + // Single witness item of 32 bytes. + let witness_bytes: [u8; 32] = [11u8; 32]; + txin.witness.push(witness_bytes); + + // pubkey bytes must match the magic bytes followed by the hash of the witness bytes. + let script_pubkey_bytes: [u8; 38] = hex_unstable::FromHex::from_hex("6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb").unwrap(); + let tx1 = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![txin], + outputs: vec![crate::TxOut { + amount: units::Amount::MIN, + script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()) + }], + }; + + let tx2 = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![crate::TxIn::EMPTY_COINBASE], + outputs: vec![crate::TxOut { + amount: units::Amount::MIN, + script_pubkey: crate::script::ScriptBuf::new() + }], + }; + + let block = Block::new_unchecked(dummy_header(), vec![tx1, tx2]); + let result = block.check_witness_commitment(); + + let exp_bytes: [u8; 32] = hex_unstable::FromHex::from_hex("fb848679079938b249a12f14b72d56aeb116df79254e17cdf72b46523bcb49db").unwrap(); + let expected = WitnessMerkleNode::from_byte_array(exp_bytes); + assert_eq!(result, (true, Some(expected))); + } + + #[test] + #[cfg(all(feature = "alloc", feature = "hex"))] + fn block_check_witness_commitment_invalid_witness() { + let mut txin = crate::TxIn::EMPTY_COINBASE; + let witness_bytes: [u8; 32] = [11u8; 32]; + // First witness item is 32 bytes, but there are two witness elements. + txin.witness.push(witness_bytes); + txin.witness.push([12u8]); + + let script_pubkey_bytes: [u8; 38] = hex_unstable::FromHex::from_hex("6a24aa21a9ed3cde9e0b9f4ad8f9d0fd66d6b9326cd68597c04fa22ab64b8e455f08d2e31ceb").unwrap(); + let tx1 = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![txin], + outputs: vec![crate::TxOut { + amount: units::Amount::MIN, + script_pubkey: crate::script::ScriptBuf::from_bytes(script_pubkey_bytes.to_vec()) + }], + }; + + let tx2 = Transaction { + version: crate::transaction::Version::ONE, + lock_time: crate::absolute::LockTime::ZERO, + inputs: vec![crate::TxIn::EMPTY_COINBASE], + outputs: vec![crate::TxOut { + amount: units::Amount::MIN, + script_pubkey: crate::script::ScriptBuf::new() + }], + }; + + let block = Block::new_unchecked(dummy_header(), vec![tx1, tx2]); + let result = block.check_witness_commitment(); + assert_eq!(result, (false, None)); + } +} diff --git a/primitives/src/hash_types/block_hash.rs b/primitives/src/hash_types/block_hash.rs new file mode 100644 index 000000000..ea0e35c0d --- /dev/null +++ b/primitives/src/hash_types/block_hash.rs @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `BlockHash` type. + +use core::convert::Infallible; +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use encoding::Encodable; +use hashes::sha256d; +use internals::write_err; + +/// A bitcoin block hash. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct BlockHash(sha256d::Hash); + +impl BlockHash { + /// Dummy hash used as the previous blockhash of the genesis block. + pub const GENESIS_PREVIOUS_BLOCK_HASH: Self = Self::from_byte_array([0; 32]); +} + +// The new hash wrapper type. +type HashType = BlockHash; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); + +encoding::encoder_newtype! { + /// The encoder for the [`BlockHash`] type. + pub struct BlockHashEncoder(encoding::ArrayEncoder<32>); +} + +impl Encodable for BlockHash { + type Encoder<'e> = BlockHashEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + BlockHashEncoder(encoding::ArrayEncoder::without_length_prefix(self.to_byte_array())) + } +} + +/// The decoder for the [`BlockHash`] type. +pub struct BlockHashDecoder(encoding::ArrayDecoder<32>); + +impl BlockHashDecoder { + /// Constructs a new [`BlockHash`] decoder. + pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) } +} + +impl Default for BlockHashDecoder { + fn default() -> Self { Self::new() } +} + +impl encoding::Decoder for BlockHashDecoder { + type Output = BlockHash; + type Error = BlockHashDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + Ok(self.0.push_bytes(bytes)?) + } + + #[inline] + fn end(self) -> Result { + let a = self.0.end()?; + Ok(BlockHash::from_byte_array(a)) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +impl encoding::Decodable for BlockHash { + type Decoder = BlockHashDecoder; + fn decoder() -> Self::Decoder { BlockHashDecoder(encoding::ArrayDecoder::<32>::new()) } +} + +/// An error consensus decoding an `BlockHash`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BlockHashDecoderError(encoding::UnexpectedEofError); + +impl From for BlockHashDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for BlockHashDecoderError { + fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) } +} + +impl fmt::Display for BlockHashDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "sequence decoder error"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for BlockHashDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} diff --git a/primitives/src/hash_types/generic.rs b/primitives/src/hash_types/generic.rs new file mode 100644 index 000000000..50ba31def --- /dev/null +++ b/primitives/src/hash_types/generic.rs @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: CC0-1.0 + +// NOTE: This is not a normal module. +// +// Generic implementation of hash wrapper types. +// +// File is included in other files using `include!` allowing us to +// follow the DRY principle without using macros. + +const LEN: usize = ::LEN; +#[cfg(feature = "hex")] +const REVERSE: bool = ::DISPLAY_BACKWARD; + +impl HashType { + /// Constructs a new type from the underlying byte array. + pub const fn from_byte_array(bytes: [u8; LEN]) -> Self { + Self(Inner::from_byte_array(bytes)) + } + + /// Returns the underlying byte array. + pub const fn to_byte_array(self) -> [u8; LEN] { self.0.to_byte_array() } + + /// Returns a reference to the underlying byte array. + pub const fn as_byte_array(&self) -> &[u8; LEN] { self.0.as_byte_array() } +} + +#[cfg(feature = "serde")] +super::impl_serde!(HashType, LEN); +super::impl_bytelike_traits!(HashType, LEN); + +#[cfg(feature = "hex")] +hex_unstable::impl_fmt_traits! { + #[display_backward(REVERSE)] + impl fmt_traits for HashType { + const LENGTH: usize = LEN; + } +} + +#[cfg(feature = "hex")] +impl str::FromStr for HashType { + type Err = hex::DecodeFixedLengthBytesError; + + fn from_str(s: &str) -> Result { + let mut bytes = crate::hex::decode_to_array(s)?; + + if REVERSE { + bytes.reverse(); + } + Ok(Self::from_byte_array(bytes)) + } +} + +#[cfg(not(feature = "hex"))] +impl fmt::Debug for HashType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for byte in self.as_byte_array() { + write!(f, "{:02x}", byte)?; + } + Ok(()) + } +} + +#[cfg(feature = "arbitrary")] +impl<'a> Arbitrary<'a> for HashType { + fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { + let arbitrary_bytes = u.arbitrary()?; + Ok(Self::from_byte_array(arbitrary_bytes)) + } +} diff --git a/primitives/src/hash_types/mod.rs b/primitives/src/hash_types/mod.rs new file mode 100644 index 000000000..5bb54e15e --- /dev/null +++ b/primitives/src/hash_types/mod.rs @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Primitive hash wrapper types. +//! +//! Note: To print and parse these hash types enable the "hex" feature. + +mod block_hash; +mod ntxid; +#[cfg(feature = "alloc")] +mod script_hash; +mod transaction_merkle_node; +mod txid; +mod witness_commitment; +mod witness_merkle_node; +#[cfg(feature = "alloc")] +mod witness_script_hash; +mod wtxid; + +#[rustfmt::skip] // Keep public re-exports separate. +#[doc(inline)] +pub use self::{ + block_hash::{BlockHash, BlockHashDecoder, BlockHashDecoderError, BlockHashEncoder}, + ntxid::Ntxid, + transaction_merkle_node::{TxMerkleNode, TxMerkleNodeEncoder, TxMerkleNodeDecoder, TxMerkleNodeDecoderError}, + txid::{Txid}, + wtxid::Wtxid, + witness_commitment::WitnessCommitment, + witness_merkle_node::WitnessMerkleNode, +}; +#[cfg(feature = "alloc")] +#[doc(inline)] +pub use self::{ + script_hash::{RedeemScriptSizeError, ScriptHash}, + witness_script_hash::{WScriptHash, WitnessScriptSizeError}, +}; + +/// Adds trait impls to a bytelike type. +/// +/// Implements: +/// +/// * `AsRef[u8; $len]` +/// * `AsRef[u8]` +/// * `Borrow<[u8; $len]>` +/// * `Borrow<[u8]>` +/// +/// # Parameters +/// +/// * `ty` - the bytelike type to implement the traits on. +/// * `$len` - the number of bytes this type has. +/// * `$gen: $gent` - the generic type(s) and trait bound(s). +macro_rules! impl_bytelike_traits { + ($ty:ident, $len:expr $(, $gen:ident: $gent:ident)*) => { + impl $crate::_export::_core::convert::AsRef<[u8; { $len }]> for $ty { + #[inline] + fn as_ref(&self) -> &[u8; { $len }] { self.as_byte_array() } + } + + impl $crate::_export::_core::convert::AsRef<[u8]> for $ty { + #[inline] + fn as_ref(&self) -> &[u8] { self.as_byte_array() } + } + + impl $crate::_export::_core::borrow::Borrow<[u8; { $len }]> for $ty { + fn borrow(&self) -> &[u8; { $len }] { self.as_byte_array() } + } + + impl $crate::_export::_core::borrow::Borrow<[u8]> for $ty { + fn borrow(&self) -> &[u8] { self.as_byte_array() } + } + }; +} +pub(in crate::hash_types) use impl_bytelike_traits; + +/// Implements `Serialize` and `Deserialize` for a hash wrapper type `$t`. +/// +/// This is equivalent to `hashes::impl_serde_for_newtype` but does not rely on the wrapper type +/// implementing the `Hash` trait. +/// +/// Requires `$t` to implement: +/// * `from_byte_array()` +/// * `as_byte_array()` +/// * `str::FromStr` +/// * `fmt::Display` +#[cfg(feature = "serde")] +macro_rules! impl_serde( + ($t:ident, $len:expr) => ( + impl $crate::serde::Serialize for $t { + fn serialize(&self, s: S) -> core::result::Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(self.as_byte_array()) + } + } + } + + impl<'de> $crate::serde::Deserialize<'de> for $t { + fn deserialize>(d: D) -> core::result::Result<$t, D::Error> { + use $crate::hash_types::serde_details::{BytesVisitor, HexVisitor}; + + if d.is_human_readable() { + d.deserialize_str(HexVisitor::::default()) + } else { + let bytes = d.deserialize_bytes(BytesVisitor::<$len>::default())?; + Ok(Self::from_byte_array(bytes)) + } + } + } +)); +#[cfg(feature = "serde")] +pub(in crate::hash_types) use impl_serde; + +/// Functions used by serde impls of all hashes. +#[cfg(feature = "serde")] +pub mod serde_details { + use core::marker::PhantomData; + use core::str::FromStr; + use core::{fmt, str}; + + use serde::de; + + /// Type used to implement serde traits for hashes as hex strings. + pub struct HexVisitor(PhantomData); + + impl Default for HexVisitor { + fn default() -> Self { Self(PhantomData) } + } + + impl de::Visitor<'_> for HexVisitor + where + ValueT: FromStr, + ::Err: fmt::Display, + { + type Value = ValueT; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> core::result::Result + where + E: de::Error, + { + if let Ok(hex) = str::from_utf8(v) { + hex.parse::().map_err(E::custom) + } else { + Err(E::invalid_value(de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> core::result::Result + where + E: de::Error, + { + v.parse::().map_err(E::custom) + } + } + + /// Type used to implement serde traits for hashes as bytes. + pub struct BytesVisitor(); + + impl Default for BytesVisitor { + fn default() -> Self { Self() } + } + + impl de::Visitor<'_> for BytesVisitor { + type Value = [u8; N]; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> core::result::Result + where + E: de::Error, + { + let bytes = <[u8; N]>::try_from(v).map_err(|_| { + // from_slice only errors on incorrect length + E::invalid_length(v.len(), &stringify!(N)) + })?; + + Ok(bytes) + } + } +} + +#[cfg(test)] +#[cfg(feature = "alloc")] +mod tests { + use super::*; + + // Creates an arbitrary dummy hash type object. + #[cfg(feature = "serde")] + fn dummy_test_case() -> Txid { + "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse::().unwrap() + } + + #[test] + #[cfg(feature = "serde")] // Implies alloc and hex + fn serde_human_readable_roundtrips() { + let tc = dummy_test_case(); + let ser = serde_json::to_string(&tc).unwrap(); + let got = serde_json::from_str::(&ser).unwrap(); + assert_eq!(got, tc); + } + + #[test] + #[cfg(feature = "serde")] // Implies alloc and hex + fn serde_non_human_readable_roundtrips() { + let tc = dummy_test_case(); + let ser = bincode::serialize(&tc).unwrap(); + let got = bincode::deserialize::(&ser).unwrap(); + assert_eq!(got, tc); + } + + #[test] + // This is solely to test that we can debug print WITH "hex" so its ok to require "alloc". + #[cfg(feature = "alloc")] + #[cfg(feature = "hex")] + fn debug() { + let tc = Txid::from_byte_array([0xab; 32]); + let got = alloc::format!("{:?}", tc); + let want = "abababababababababababababababababababababababababababababababab"; + assert_eq!(got, want); + } + + #[test] + // This is solely to test that we can debug print WITHOUT "hex" so its ok to require "alloc". + #[cfg(feature = "alloc")] + #[cfg(not(feature = "hex"))] + fn debug() { + let tc = Txid::from_byte_array([0xab; 32]); + let got = alloc::format!("{:?}", tc); + let want = "abababababababababababababababababababababababababababababababab"; + assert_eq!(got, want); + } +} diff --git a/primitives/src/hash_types/ntxid.rs b/primitives/src/hash_types/ntxid.rs new file mode 100644 index 000000000..df7a22bce --- /dev/null +++ b/primitives/src/hash_types/ntxid.rs @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `Txid` type. + +#[cfg(not(feature = "hex"))] +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256d; + +/// A "normalized TXID". +/// +/// Computed on a transaction that has had the signatures removed. +/// +/// This type is needed only for legacy (pre-Segwit or P2SH-wrapped segwit version 0) +/// applications. This method clears the `script_sig` field of each input, which in Segwit +/// transactions is already empty, so for Segwit transactions the ntxid will be equal to the +/// txid, and you should simply use the latter. +/// +/// This gives a way to identify a transaction that is "the same" as another in the sense of +/// having the same inputs and outputs. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Ntxid(sha256d::Hash); + +// The new hash wrapper type. +type HashType = Ntxid; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); diff --git a/primitives/src/hash_types/script_hash.rs b/primitives/src/hash_types/script_hash.rs new file mode 100644 index 000000000..444c849c8 --- /dev/null +++ b/primitives/src/hash_types/script_hash.rs @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `ScriptHash` type. + +use core::convert::Infallible; +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::hash160; + +use crate::script::{Script, ScriptHashableTag, MAX_REDEEM_SCRIPT_SIZE}; + +/// A 160-bit hash of Bitcoin Script bytecode. +/// +/// Note: there is another "script hash" object in bitcoin ecosystem (Electrum protocol) that +/// uses 256-bit hash and hashes a semantically different script. Thus, this type cannot +/// represent it. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ScriptHash(hash160::Hash); + +impl ScriptHash { + /// Constructs a new `ScriptHash` after first checking the script size. + /// + /// # 520-byte limitation on serialized script size + /// + /// > As a consequence of the requirement for backwards compatibility the serialized script is + /// > itself subject to the same rules as any other PUSHDATA operation, including the rule that + /// > no data greater than 520 bytes may be pushed to the stack. Thus it is not possible to + /// > spend a P2SH output if the redemption script it refers to is >520 bytes in length. + /// + /// ref: [BIP-0016](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size) + #[inline] + pub fn from_script(redeem_script: &Script) -> Result + where + T: ScriptHashableTag, + { + if redeem_script.len() > MAX_REDEEM_SCRIPT_SIZE { + return Err(RedeemScriptSizeError { size: redeem_script.len() }); + } + + // We've just checked the length + Ok(Self::from_script_unchecked(redeem_script)) + } + + /// Constructs a new `ScriptHash` from any script irrespective of script size. + /// + /// If you hash a script that exceeds 520 bytes in size and use it to create a P2SH output + /// then the output will be unspendable (see [BIP-0016]). + /// + /// [BIP-0016]: + #[inline] + pub fn from_script_unchecked(script: &Script) -> Self { + Self(hash160::Hash::hash(script.as_bytes())) + } +} + +/// Error while hashing a redeem script. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RedeemScriptSizeError { + /// Invalid redeem script size (cannot exceed 520 bytes). + size: usize, +} + +impl RedeemScriptSizeError { + /// Returns the invalid redeem script size. + pub fn invalid_size(&self) -> usize { self.size } +} + +impl From for RedeemScriptSizeError { + #[inline] + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for RedeemScriptSizeError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "redeem script size exceeds {} bytes: {}", MAX_REDEEM_SCRIPT_SIZE, self.size) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for RedeemScriptSizeError {} + +// The new hash wrapper type. +type HashType = ScriptHash; +// The inner hash type from `hashes`. +type Inner = hash160::Hash; + +include!("./generic.rs"); diff --git a/primitives/src/hash_types/transaction_merkle_node.rs b/primitives/src/hash_types/transaction_merkle_node.rs new file mode 100644 index 000000000..624b6922d --- /dev/null +++ b/primitives/src/hash_types/transaction_merkle_node.rs @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `TxMerkleNode` type. + +use core::convert::Infallible; +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256d; +use internals::write_err; + +use crate::merkle_tree::MerkleNode; +use crate::Txid; + +/// A hash of the Merkle tree branch or root for transactions. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TxMerkleNode(sha256d::Hash); + +// The new hash wrapper type. +type HashType = TxMerkleNode; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); + +impl TxMerkleNode { + /// Convert a [`Txid`] hash to a leaf node of the tree. + pub fn from_leaf(leaf: Txid) -> Self { MerkleNode::from_leaf(leaf) } + + /// Combine two nodes to get a single node. The final node of a tree is called the "root". + #[must_use] + pub fn combine(&self, other: &Self) -> Self { MerkleNode::combine(self, other) } + + /// Given an iterator of leaves, compute the Merkle root. + /// + /// Returns `None` if the iterator was empty, or if the transaction list contains + /// consecutive duplicates which would trigger CVE 2012-2459. Blocks with duplicate + /// transactions will always be invalid, so there is no harm in us refusing to + /// compute their merkle roots. + /// + /// Unless you are certain your transaction list is nonempty and has no duplicates, + /// you should not unwrap the `Option` returned by this method! + pub fn calculate_root>(iter: I) -> Option { MerkleNode::calculate_root(iter) } +} + +encoding::encoder_newtype! { + /// The encoder for the [`TxMerkleNode`] type. + pub struct TxMerkleNodeEncoder(encoding::ArrayEncoder<32>); +} + +impl encoding::Encodable for TxMerkleNode { + type Encoder<'e> = TxMerkleNodeEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + TxMerkleNodeEncoder(encoding::ArrayEncoder::without_length_prefix(self.to_byte_array())) + } +} + +/// The decoder for the [`TxMerkleNode`] type. +pub struct TxMerkleNodeDecoder(encoding::ArrayDecoder<32>); + +impl TxMerkleNodeDecoder { + /// Constructs a new [`TxMerkleNode`] decoder. + pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) } +} + +impl Default for TxMerkleNodeDecoder { + fn default() -> Self { Self::new() } +} + +impl encoding::Decoder for TxMerkleNodeDecoder { + type Output = TxMerkleNode; + type Error = TxMerkleNodeDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + Ok(self.0.push_bytes(bytes)?) + } + + #[inline] + fn end(self) -> Result { + let a = self.0.end()?; + Ok(TxMerkleNode::from_byte_array(a)) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +impl encoding::Decodable for TxMerkleNode { + type Decoder = TxMerkleNodeDecoder; + fn decoder() -> Self::Decoder { TxMerkleNodeDecoder(encoding::ArrayDecoder::<32>::new()) } +} + +/// An error consensus decoding an `TxMerkleNode`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TxMerkleNodeDecoderError(encoding::UnexpectedEofError); + +impl From for TxMerkleNodeDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for TxMerkleNodeDecoderError { + fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) } +} + +impl fmt::Display for TxMerkleNodeDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "sequence decoder error"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for TxMerkleNodeDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} diff --git a/primitives/src/hash_types/txid.rs b/primitives/src/hash_types/txid.rs new file mode 100644 index 000000000..b0d9fbf1f --- /dev/null +++ b/primitives/src/hash_types/txid.rs @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `Txid` type. +//! +//! In order to print and parse txids enable the "hex" feature. + +#[cfg(not(feature = "hex"))] +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256d; + +#[cfg(doc)] +use crate::OutPoint; + +/// A bitcoin transaction hash/transaction ID. +/// +/// For compatibility with the existing Bitcoin infrastructure and historical and current +/// versions of the Bitcoin Core software itself, this and other [`sha256d::Hash`] types, are +/// serialized in reverse byte order when converted to a hex string via [`std::fmt::Display`] +/// trait operations. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Txid(sha256d::Hash); + +impl Txid { + /// The `Txid` used in a coinbase prevout. + /// + /// This is used as the "txid" of the dummy input of a coinbase transaction. This is not a real + /// TXID and should not be used in any other contexts. See [`OutPoint::COINBASE_PREVOUT`]. + pub const COINBASE_PREVOUT: Self = Self::from_byte_array([0; 32]); +} + +// The new hash wrapper type. +type HashType = Txid; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); diff --git a/primitives/src/hash_types/witness_commitment.rs b/primitives/src/hash_types/witness_commitment.rs new file mode 100644 index 000000000..f4332e960 --- /dev/null +++ b/primitives/src/hash_types/witness_commitment.rs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `WitnessCommitment` type. + +#[cfg(not(feature = "hex"))] +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256d; + +/// A hash corresponding to the witness structure commitment in the coinbase transaction. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WitnessCommitment(sha256d::Hash); + +impl WitnessCommitment { + /// Dummy hash used as the previous blockhash of the genesis block. + pub const GENESIS_PREVIOUS_BLOCK_HASH: Self = Self::from_byte_array([0; 32]); +} + +// The new hash wrapper type. +type HashType = WitnessCommitment; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); diff --git a/primitives/src/hash_types/witness_merkle_node.rs b/primitives/src/hash_types/witness_merkle_node.rs new file mode 100644 index 000000000..b57af8272 --- /dev/null +++ b/primitives/src/hash_types/witness_merkle_node.rs @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `WitnessMerkleNode` type. + +use core::convert::Infallible; +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256d; +use internals::write_err; + +use crate::merkle_tree::MerkleNode; +use crate::Wtxid; + +/// A hash corresponding to the Merkle tree root for witness data. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WitnessMerkleNode(sha256d::Hash); + +// The new hash wrapper type. +type HashType = WitnessMerkleNode; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); + +impl WitnessMerkleNode { + /// Convert a [`Wtxid`] hash to a leaf node of the tree. + pub fn from_leaf(leaf: Wtxid) -> Self { MerkleNode::from_leaf(leaf) } + + /// Combine two nodes to get a single node. The final node of a tree is called the "root". + #[must_use] + pub fn combine(&self, other: &Self) -> Self { MerkleNode::combine(self, other) } + + /// Given an iterator of leaves, compute the Merkle root. + /// + /// Returns `None` if the iterator was empty, or if the transaction list contains + /// consecutive duplicates which would trigger CVE 2012-2459. Blocks with duplicate + /// transactions will always be invalid, so there is no harm in us refusing to + /// compute their merkle roots. + /// + /// Unless you are certain your transaction list is nonempty and has no duplicates, + /// you should not unwrap the `Option` returned by this method! + pub fn calculate_root>(iter: I) -> Option { MerkleNode::calculate_root(iter) } +} + +encoding::encoder_newtype! { + /// The encoder for the [`WitnessMerkleNode`] type. + pub struct WitnessMerkleNodeEncoder(encoding::ArrayEncoder<32>); +} + +impl encoding::Encodable for WitnessMerkleNode { + type Encoder<'e> = WitnessMerkleNodeEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + WitnessMerkleNodeEncoder(encoding::ArrayEncoder::without_length_prefix(self.to_byte_array())) + } +} + +/// The decoder for the [`WitnessMerkleNode`] type. +pub struct WitnessMerkleNodeDecoder(encoding::ArrayDecoder<32>); + +impl WitnessMerkleNodeDecoder { + /// Constructs a new [`WitnessMerkleNode`] decoder. + pub fn new() -> Self { Self(encoding::ArrayDecoder::new()) } +} + +impl Default for WitnessMerkleNodeDecoder { + fn default() -> Self { Self::new() } +} + +impl encoding::Decoder for WitnessMerkleNodeDecoder { + type Output = WitnessMerkleNode; + type Error = WitnessMerkleNodeDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + Ok(self.0.push_bytes(bytes)?) + } + + #[inline] + fn end(self) -> Result { + let a = self.0.end()?; + Ok(WitnessMerkleNode::from_byte_array(a)) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +impl encoding::Decodable for WitnessMerkleNode { + type Decoder = WitnessMerkleNodeDecoder; + fn decoder() -> Self::Decoder { WitnessMerkleNodeDecoder(encoding::ArrayDecoder::<32>::new()) } +} + +/// An error consensus decoding an `WitnessMerkleNode`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WitnessMerkleNodeDecoderError(encoding::UnexpectedEofError); + +impl From for WitnessMerkleNodeDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for WitnessMerkleNodeDecoderError { + fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) } +} + +impl fmt::Display for WitnessMerkleNodeDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "sequence decoder error"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for WitnessMerkleNodeDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} diff --git a/primitives/src/hash_types/witness_script_hash.rs b/primitives/src/hash_types/witness_script_hash.rs new file mode 100644 index 000000000..6dfb9d948 --- /dev/null +++ b/primitives/src/hash_types/witness_script_hash.rs @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `WScriptHash` type. + +use core::convert::Infallible; +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256; + +use crate::script::{WitnessScript, MAX_WITNESS_SCRIPT_SIZE}; + +/// SegWit (256-bit) version of a Bitcoin Script bytecode hash. +/// +/// Note: there is another "script hash" object in bitcoin ecosystem (Electrum protocol) that +/// looks similar to this one also being SHA256, however, they hash semantically different +/// scripts and have reversed representations, so this type cannot be used for both. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct WScriptHash(sha256::Hash); + +impl WScriptHash { + /// Constructs a new `WScriptHash` after first checking the script size. + /// + /// # 10,000-byte limit on the witness script + /// + /// > The witnessScript (≤ 10,000 bytes) is popped off the initial witness stack. SHA256 of the + /// > witnessScript must match the 32-byte witness program. + /// + /// ref: [BIP-0141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) + #[inline] + pub fn from_script(witness_script: &WitnessScript) -> Result { + if witness_script.len() > MAX_WITNESS_SCRIPT_SIZE { + return Err(WitnessScriptSizeError { size: witness_script.len() }); + } + + // We've just checked the length + Ok(Self::from_script_unchecked(witness_script)) + } + + /// Constructs a new `WScriptHash` from any script irrespective of script size. + /// + /// If you hash a script that exceeds 10,000 bytes in size and use it to create a Segwit + /// output then the output will be unspendable (see [BIP-0141]). + /// + /// ref: [BIP-0141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) + #[inline] + pub fn from_script_unchecked(script: &WitnessScript) -> Self { + Self(sha256::Hash::hash(script.as_bytes())) + } +} + +/// Error while hashing a witness script. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WitnessScriptSizeError { + /// Invalid witness script size (cannot exceed 10,000 bytes). + size: usize, +} + +impl WitnessScriptSizeError { + /// Returns the invalid witness script size. + pub fn invalid_size(&self) -> usize { self.size } +} + +impl From for WitnessScriptSizeError { + #[inline] + fn from(never: Infallible) -> Self { match never {} } +} + +impl fmt::Display for WitnessScriptSizeError { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "witness script size exceeds {} bytes: {}", MAX_WITNESS_SCRIPT_SIZE, self.size) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for WitnessScriptSizeError {} + +include!("./generic.rs"); + +// The new hash wrapper type. +type HashType = WScriptHash; +// The inner hash type from `hashes`. +type Inner = sha256::Hash; diff --git a/primitives/src/hash_types/wtxid.rs b/primitives/src/hash_types/wtxid.rs new file mode 100644 index 000000000..482623f50 --- /dev/null +++ b/primitives/src/hash_types/wtxid.rs @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The `Txid` type. +//! +//! In order to print and parse txids enable the "hex" feature. + +#[cfg(not(feature = "hex"))] +use core::fmt; +#[cfg(feature = "hex")] +use core::str; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use hashes::sha256d; + +/// A bitcoin witness transaction ID. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Wtxid(sha256d::Hash); + +impl Wtxid { + /// The `Wtxid` of a coinbase transaction. + /// + /// This is used as the wTXID for the coinbase transaction when constructing blocks (in the + /// witness commitment tree) since the coinbase transaction contains a commitment to all + /// transactions' wTXIDs but naturally cannot commit to its own. + pub const COINBASE: Self = Self::from_byte_array([0; 32]); +} + +// The new hash wrapper type. +type HashType = Wtxid; +// The inner hash type from `hashes`. +type Inner = sha256d::Hash; + +include!("./generic.rs"); diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs new file mode 100644 index 000000000..31011c06d --- /dev/null +++ b/primitives/src/lib.rs @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Rust Bitcoin - primitive types +//! +//! Primitive data types that are used throughout the [`rust-bitcoin`] ecosystem. +//! +//! If you are using `rust-bitcoin` then you do not need to access this crate directly. Everything +//! here is re-exported in `rust-bitcoin` at the same path. +//! +//! This crate can be used in a no-std environment but a lot of the functionality requires an +//! allocator i.e., requires the `alloc` feature to be enabled. +//! +//! [`rust-bitcoin`]: + +#![no_std] +// Coding conventions. +#![warn(missing_docs)] +#![warn(deprecated_in_future)] +#![doc(test(attr(warn(unused))))] +// Package-specific lint overrides. +#![allow(clippy::missing_errors_doc)] // TODO: Write errors section in docs. + +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "serde")] +#[macro_use] +extern crate serde; + +#[cfg(feature = "hex")] +pub extern crate hex_stable as hex; + +#[doc(hidden)] +pub mod _export { + /// A re-export of `core::*`. + pub mod _core { + pub use core::*; + } +} + +mod hash_types; +#[cfg(feature = "alloc")] +mod opcodes; + +pub mod block; +pub mod merkle_tree; +pub mod pow; +#[cfg(feature = "alloc")] +pub mod script; +pub mod transaction; +#[cfg(feature = "alloc")] +pub mod witness; + +#[doc(inline)] +pub use units::{ + amount::{self, Amount, SignedAmount}, + block::{BlockHeight, BlockHeightInterval, BlockMtp, BlockMtpInterval}, + fee_rate::{self, FeeRate}, + locktime::{self, absolute, relative}, + parse_int, + result::{self, NumOpResult}, + sequence::{self, Sequence}, + time::{self, BlockTime, BlockTimeDecoder, BlockTimeDecoderError}, + weight::{self, Weight}, +}; + +#[deprecated(since = "1.0.0-rc.0", note = "use `BlockHeightInterval` instead")] +#[doc(hidden)] +pub type BlockInterval = BlockHeightInterval; + +#[doc(inline)] +#[cfg(feature = "alloc")] +pub use self::{ + block::{ + Block, Checked as BlockChecked, Unchecked as BlockUnchecked, Validation as BlockValidation, + }, + script::{ + RedeemScript, RedeemScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf, + TapScript, TapScriptBuf, WitnessScript, WitnessScriptBuf, + }, + transaction::{Transaction, TxIn, TxOut}, + witness::Witness, +}; +#[doc(inline)] +pub use self::{ + block::{BlockHash, Header as BlockHeader, Version as BlockVersion, WitnessCommitment}, + merkle_tree::{TxMerkleNode, WitnessMerkleNode}, + pow::CompactTarget, + transaction::{Ntxid, OutPoint, Txid, Version as TransactionVersion, Wtxid}, +}; + +#[rustfmt::skip] +#[allow(unused_imports)] +mod prelude { + #[cfg(feature = "alloc")] + pub use alloc::collections::{BTreeMap, BTreeSet, btree_map, BinaryHeap}; + + #[cfg(feature = "alloc")] + pub use alloc::{string::{String, ToString}, vec::Vec, boxed::Box, borrow::{Borrow, BorrowMut, Cow, ToOwned}, slice, rc}; + + #[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] + pub use alloc::sync; +} diff --git a/primitives/src/merkle_tree.rs b/primitives/src/merkle_tree.rs new file mode 100644 index 000000000..468e7f264 --- /dev/null +++ b/primitives/src/merkle_tree.rs @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin Merkle tree functions. + +// This module is unusual in that it exists because of a bunch of (krufty) reasons: +// +// - We based the name off of the original `bitcoin` module. +// - We want the API to be the same here as in `bitcoin`. +// - We define all the other hash types in some module so the merkle tree hash types need a module. +// +// C'est la vie. +#[cfg(feature = "alloc")] +use alloc::vec::Vec; +#[cfg(not(feature = "alloc"))] +use internals::array_vec::ArrayVec; + +use hashes::{HashEngine, sha256d}; + +use crate::hash_types::{Txid, Wtxid}; +use crate::transaction::TxIdentifier; + +#[doc(inline)] +pub use crate::hash_types::{TxMerkleNode, TxMerkleNodeEncoder, WitnessMerkleNode}; + +/// A node in a Merkle tree of transactions or witness data within a block. +/// +/// This trait is used to compute the transaction Merkle root contained in +/// a block header. This is a particularly weird algorithm -- it interprets +/// the list of transactions as a balanced binary tree, duplicating branches +/// as needed to fill out the tree to a power of two size. +/// +/// Other Merkle trees in Bitcoin, such as those used in Taproot commitments, +/// do not use this algorithm and cannot use this trait. +pub(crate) trait MerkleNode: Copy + PartialEq { + /// The hash (TXID or WTXID) of a transaction in the tree. + type Leaf: TxIdentifier; + + /// Convert a hash to a leaf node of the tree. + fn from_leaf(leaf: Self::Leaf) -> Self; + /// Combine two nodes to get a single node. The final node of a tree is called the "root". + #[must_use] + fn combine(&self, other: &Self) -> Self; + + /// Given an iterator of leaves, compute the Merkle root. + /// + /// Returns `None` if the iterator was empty, or if the transaction list contains + /// consecutive duplicates which would trigger CVE 2012-2459. Blocks with duplicate + /// transactions will always be invalid, so there is no harm in us refusing to + /// compute their merkle roots. + /// + /// Also returns `None` if the `alloc` feature is disabled and `iter` has more than + /// 32,767 transactions. + /// + /// Unless you are certain your transaction list is nonempty and has no duplicates, + /// you should not unwrap the `Option` returned by this method! + fn calculate_root>(iter: I) -> Option { + { + #[cfg(feature = "alloc")] + let mut stack = Vec::<(usize, Self)>::with_capacity(32); + #[cfg(not(feature = "alloc"))] + let mut stack = ArrayVec::<(usize, Self), 15>::new(); + + // Start with a standard Merkle tree root computation... + for (mut n, leaf) in iter.enumerate() { + #[cfg(not(feature = "alloc"))] + // This is the only time that the stack actually grows, rather than being combined. + if stack.len() == 15 { return None; } + stack.push((0, Self::from_leaf(leaf))); + + while n & 1 == 1 { + let right = stack.pop().unwrap(); + let left = stack.pop().unwrap(); + if left.1 == right.1 { + // Reject duplicate trees since they are guaranteed-invalid (Bitcoin does + // not allow duplicate transactions in block) but can be used to confuse + // nodes about legitimate blocks. See CVE 2012-2459 and the block comment + // below. + return None; + } + debug_assert_eq!(left.0, right.0); + stack.push((left.0 + 1, left.1.combine(&right.1))); + n >>= 1; + } + } + // ...then, deal with incomplete trees. Bitcoin does a weird thing in + // which it doubles-up nodes of the tree to fill out the tree, rather + // than treating incomplete branches specially. This makes this tree + // construction vulnerable to collisions (see CVE 2012-2459). + // + // (It is also vulnerable to collisions because it does not distinguish + // between internal nodes and transactions, but this collisions of this + // form are probably impractical. It is likely that 64-byte transactions + // will be forbidden in the future which will close this for good.) + // + // This is consensus logic so we cannot fix the Merkle tree construction. + // Instead we just have to reject the clearly-invalid half of the collision + // (see previous comment). + while stack.len() > 1 { + let mut right = stack.pop().unwrap(); + let left = stack.pop().unwrap(); + while right.0 != left.0 { + assert!(right.0 < left.0); + right = (right.0 + 1, right.1.combine(&right.1)); // combine with self + } + stack.push((left.0 + 1, left.1.combine(&right.1))); + } + + stack.pop().map(|(_, h)| h) + } + } +} + +// These two impl blocks are identical. FIXME once we have nailed down +// our hash traits, it should be possible to put bounds on `MerkleNode` +// and `MerkleNode::Leaf` which are sufficient to turn both methods into +// provided methods in the trait definition. +impl MerkleNode for TxMerkleNode { + type Leaf = Txid; + fn from_leaf(leaf: Self::Leaf) -> Self { Self::from_byte_array(leaf.to_byte_array()) } + + fn combine(&self, other: &Self) -> Self { + let mut encoder = sha256d::Hash::engine(); + encoder.input(self.as_byte_array()); + encoder.input(other.as_byte_array()); + Self::from_byte_array(sha256d::Hash::from_engine(encoder).to_byte_array()) + } +} +impl MerkleNode for WitnessMerkleNode { + type Leaf = Wtxid; + fn from_leaf(leaf: Self::Leaf) -> Self { Self::from_byte_array(leaf.to_byte_array()) } + + fn combine(&self, other: &Self) -> Self { + let mut encoder = sha256d::Hash::engine(); + encoder.input(self.as_byte_array()); + encoder.input(other.as_byte_array()); + Self::from_byte_array(sha256d::Hash::from_engine(encoder).to_byte_array()) + } +} + +#[cfg(test)] +mod tests { + use crate::hash_types::*; + + // Helper to make a Txid, TxMerkleNode pair with a single number byte array + fn make_leaf_node(byte: u8) -> (Txid, TxMerkleNode) { + let leaf = Txid::from_byte_array([byte; 32]); + let node = TxMerkleNode::from_leaf(leaf); + (leaf, node) + } + + #[test] + fn tx_merkle_node_single_leaf() { + let (leaf, node) = make_leaf_node(1); + let root = TxMerkleNode::calculate_root([leaf].into_iter()); + assert!(root.is_some(), "Root should exist for a single leaf"); + assert_eq!(root.unwrap(), node, "Root should equal the leaf node"); + } + + #[test] + fn tx_merkle_node_two_leaves() { + let (leaf1, node1) = make_leaf_node(1); + let (leaf2, node2) = make_leaf_node(2); + let combined = node1.combine(&node2); + + let root = TxMerkleNode::calculate_root([leaf1, leaf2].into_iter()); + assert_eq!( + root.unwrap(), + combined, + "Root of two leaves should equal combine of the two leaf nodes" + ); + } + + #[test] + fn tx_merkle_node_duplicate_leaves() { + let leaf = Txid::from_byte_array([3; 32]); + // Duplicate transaction list should be rejected (CVE 2012‑2459). + let root = TxMerkleNode::calculate_root([leaf, leaf].into_iter()); + assert!(root.is_none(), "Duplicate leaves should return None"); + } + + #[test] + fn tx_merkle_node_empty() { + assert!(TxMerkleNode::calculate_root([].into_iter()).is_none(), "Empty iterator should return None"); + } + + #[test] + fn tx_merkle_node_2n_minus_1_unbalanced_tree() { + // Test a tree with 2^n - 1 unique nodes and at least 3 layers deep. + let (leaf1, node1) = make_leaf_node(1); + let (leaf2, node2) = make_leaf_node(2); + let (leaf3, node3) = make_leaf_node(3); + let (leaf4, node4) = make_leaf_node(4); + let (leaf5, node5) = make_leaf_node(5); + let (leaf6, node6) = make_leaf_node(6); + let (leaf7, node7) = make_leaf_node(7); + + // Combine leaf nodes + let subtree_a = node1.combine(&node2); + let subtree_b = node3.combine(&node4); + let subtree_c = node5.combine(&node6); + let subtree_d = node7.combine(&node7); // doubled + + // Combine the subtrees + let subtree_ab = subtree_a.combine(&subtree_b); + let subtree_cd = subtree_c.combine(&subtree_d); + let expected = subtree_ab.combine(&subtree_cd); + + let root = TxMerkleNode::calculate_root( + [leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7].into_iter() + ); + assert_eq!(root, Some(expected)); + } + + #[test] + #[cfg(feature = "alloc")] + fn tx_merkle_node_balanced_multi_level_tree() { + use alloc::vec::Vec; + + let leaves: Vec<_> = (0..16) + .map(|i| Txid::from_byte_array([i; 32])) + .collect(); + + // Create nodes for the txids. + let mut level = leaves + .iter() + .map(|l| TxMerkleNode::from_leaf(*l)) + .collect::>(); + + // Combine the leaves into a tree, ordered from left-to-right in the initial vector. + while level.len() > 1 { + level = level + .chunks(2) + .map(|chunk| chunk[0].combine(&chunk[1])) + .collect(); + } + + // Take the final node, which should be the root of the full tree. + let expected = level.pop().unwrap(); + + let root = TxMerkleNode::calculate_root(leaves.into_iter()); + assert_eq!( root, Some(expected) ); + } + + #[test] + fn tx_merkle_node_oversize_tree() { + // Confirm that with no-alloc, we return None for iter length >= 32768 + let root = TxMerkleNode::calculate_root((0..32768u32).map(|i| { + let mut buf = [0u8; 32]; + buf[..4].copy_from_slice(&i.to_le_bytes()); + Txid::from_byte_array(buf) + })); + + // We just want to confirm that we return None at the 32768 element boundary. + #[cfg(feature = "alloc")] + assert_ne!(root, None); + #[cfg(not(feature = "alloc"))] + assert_eq!(root, None); + + // Check just under the boundary + let root = TxMerkleNode::calculate_root((0..32767u32).map(|i| { + let mut buf = [0u8; 32]; + buf[..4].copy_from_slice(&i.to_le_bytes()); + Txid::from_byte_array(buf) + })); + assert_ne!(root, None); + } + + #[test] + fn witness_merkle_node_single_leaf() { + let leaf = Wtxid::from_byte_array([1; 32]); + let root = WitnessMerkleNode::calculate_root([leaf].into_iter()); + assert!(root.is_some(), "Root should exist for a single witness leaf"); + let node = WitnessMerkleNode::from_leaf(leaf); + assert_eq!(root.unwrap(), node, "Root should equal the leaf node"); + } + + #[test] + fn witness_merkle_node_duplicate_leaves() { + let leaf = Wtxid::from_byte_array([2; 32]); + let root = WitnessMerkleNode::calculate_root([leaf, leaf].into_iter()); + assert!(root.is_none(), "Duplicate witness leaves should return None"); + } +} diff --git a/primitives/src/opcodes.rs b/primitives/src/opcodes.rs new file mode 100644 index 000000000..4d39abf06 --- /dev/null +++ b/primitives/src/opcodes.rs @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Bitcoin script opcodes. +//! +//! Bitcoin's script uses a stack-based assembly language. This module defines +//! all of the opcodes for that language. + +#![allow(non_camel_case_types)] + +use core::fmt; + +/// Read the following byte as a length, and read the following +/// bytes as a push of that length. +pub const OP_PUSHDATA1: u8 = 0x4c; + +/// Read the following 2 bytes as a little-endian length, and read the following +/// bytes as a push of that length. +pub const OP_PUSHDATA2: u8 = 0x4d; + +/// Read the following 4 bytes as a little-endian length, and read the following +/// bytes as a push of that length. +pub const OP_PUSHDATA4: u8 = 0x4e; + +/// Format a byte as a script opcode. +pub fn fmt_opcode(op: u8, f: &mut fmt::Formatter) -> fmt::Result { + match op { + 0x00 => f.write_str("OP_0"), + 0x01..=0x4b => write!(f, "OP_PUSHBYTES_{}", op), + 0x4c => f.write_str("OP_PUSHDATA1"), + 0x4d => f.write_str("OP_PUSHDATA2"), + 0x4e => f.write_str("OP_PUSHDATA4"), + 0x4f => f.write_str("OP_1NEGATE"), + 0x50 => f.write_str("OP_RESERVED"), + 0x51..=0x60 => write!(f, "OP_{}", op - 0x50), + 0x61 => f.write_str("OP_NOP"), + 0x62 => f.write_str("OP_VER"), + 0x63 => f.write_str("OP_IF"), + 0x64 => f.write_str("OP_NOTIF"), + 0x65 => f.write_str("OP_VERIF"), + 0x66 => f.write_str("OP_VERNOTIF"), + 0x67 => f.write_str("OP_ELSE"), + 0x68 => f.write_str("OP_ENDIF"), + 0x69 => f.write_str("OP_VERIFY"), + 0x6a => f.write_str("OP_RETURN"), + 0x6b => f.write_str("OP_TOALTSTACK"), + 0x6c => f.write_str("OP_FROMALTSTACK"), + 0x6d => f.write_str("OP_2DROP"), + 0x6e => f.write_str("OP_2DUP"), + 0x6f => f.write_str("OP_3DUP"), + 0x70 => f.write_str("OP_2OVER"), + 0x71 => f.write_str("OP_2ROT"), + 0x72 => f.write_str("OP_2SWAP"), + 0x73 => f.write_str("OP_IFDUP"), + 0x74 => f.write_str("OP_DEPTH"), + 0x75 => f.write_str("OP_DROP"), + 0x76 => f.write_str("OP_DUP"), + 0x77 => f.write_str("OP_NIP"), + 0x78 => f.write_str("OP_OVER"), + 0x79 => f.write_str("OP_PICK"), + 0x7a => f.write_str("OP_ROLL"), + 0x7b => f.write_str("OP_ROT"), + 0x7c => f.write_str("OP_SWAP"), + 0x7d => f.write_str("OP_TUCK"), + 0x7e => f.write_str("OP_CAT"), + 0x7f => f.write_str("OP_SUBSTR"), + 0x80 => f.write_str("OP_LEFT"), + 0x81 => f.write_str("OP_RIGHT"), + 0x82 => f.write_str("OP_SIZE"), + 0x83 => f.write_str("OP_INVERT"), + 0x84 => f.write_str("OP_AND"), + 0x85 => f.write_str("OP_OR"), + 0x86 => f.write_str("OP_XOR"), + 0x87 => f.write_str("OP_EQUAL"), + 0x88 => f.write_str("OP_EQUALVERIFY"), + 0x89 => f.write_str("OP_RESERVED1"), + 0x8a => f.write_str("OP_RESERVED2"), + 0x8b => f.write_str("OP_1ADD"), + 0x8c => f.write_str("OP_1SUB"), + 0x8d => f.write_str("OP_2MUL"), + 0x8e => f.write_str("OP_2DIV"), + 0x8f => f.write_str("OP_NEGATE"), + 0x90 => f.write_str("OP_ABS"), + 0x91 => f.write_str("OP_NOT"), + 0x92 => f.write_str("OP_0NOTEQUAL"), + 0x93 => f.write_str("OP_ADD"), + 0x94 => f.write_str("OP_SUB"), + 0x95 => f.write_str("OP_MUL"), + 0x96 => f.write_str("OP_DIV"), + 0x97 => f.write_str("OP_MOD"), + 0x98 => f.write_str("OP_LSHIFT"), + 0x99 => f.write_str("OP_RSHIFT"), + 0x9a => f.write_str("OP_BOOLAND"), + 0x9b => f.write_str("OP_BOOLOR"), + 0x9c => f.write_str("OP_NUMEQUAL"), + 0x9d => f.write_str("OP_NUMEQUALVERIFY"), + 0x9e => f.write_str("OP_NUMNOTEQUAL"), + 0x9f => f.write_str("OP_LESSTHAN"), + 0xa0 => f.write_str("OP_GREATERTHAN"), + 0xa1 => f.write_str("OP_LESSTHANOREQUAL"), + 0xa2 => f.write_str("OP_GREATERTHANOREQUAL"), + 0xa3 => f.write_str("OP_MIN"), + 0xa4 => f.write_str("OP_MAX"), + 0xa5 => f.write_str("OP_WITHIN"), + 0xa6 => f.write_str("OP_RIPEMD160"), + 0xa7 => f.write_str("OP_SHA1"), + 0xa8 => f.write_str("OP_SHA256"), + 0xa9 => f.write_str("OP_HASH160"), + 0xaa => f.write_str("OP_HASH256"), + 0xab => f.write_str("OP_CODESEPARATOR"), + 0xac => f.write_str("OP_CHECKSIG"), + 0xad => f.write_str("OP_CHECKSIGVERIFY"), + 0xae => f.write_str("OP_CHECKMULTISIG"), + 0xaf => f.write_str("OP_CHECKMULTISIGVERIFY"), + 0xb1 => f.write_str("OP_CLTV"), + 0xb2 => f.write_str("OP_CSV"), + 0xb0..=0xb9 => write!(f, "OP_NOP{}", op - 0xb0 + 1), + 0xba => f.write_str("OP_CHECKSIGADD"), + 0xbb..=0xfe => write!(f, "OP_RETURN_{}", op), + 0xff => f.write_str("OP_INVALIDOPCODE"), + } +} diff --git a/primitives/src/pow.rs b/primitives/src/pow.rs new file mode 100644 index 000000000..75f4d1432 --- /dev/null +++ b/primitives/src/pow.rs @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Proof-of-work related integer types. + +use core::convert::Infallible; +use core::fmt; + +use internals::write_err; + +/// Encoding of 256-bit target as 32-bit float. +/// +/// This is used to encode a target into the block header. Satoshi made this part of consensus code +/// in the original version of Bitcoin, likely copying an idea from OpenSSL. +/// +/// OpenSSL's bignum (BN) type has an encoding, which is even called "compact" as in bitcoin, which +/// is exactly this format. +/// +/// # Note on order/equality +/// +/// Usage of the ordering and equality traits for this type may be surprising. Converting between +/// `CompactTarget` and `Target` is lossy *in both directions* (there are multiple `CompactTarget` +/// values that map to the same `Target` value). Ordering and equality for this type are defined in +/// terms of the underlying `u32`. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct CompactTarget(u32); + +impl CompactTarget { + /// Constructs a new [`CompactTarget`] from a consensus encoded `u32`. + #[inline] + pub fn from_consensus(bits: u32) -> Self { Self(bits) } + + /// Returns the consensus encoded `u32` representation of this [`CompactTarget`]. + #[inline] + pub const fn to_consensus(self) -> u32 { self.0 } + + /// Gets the hex representation of this [`CompactTarget`]. + #[cfg(feature = "alloc")] + #[inline] + #[deprecated(since = "1.0.0-rc.0", note = "use `format!(\"{var:x}\")` instead")] + pub fn to_hex(self) -> alloc::string::String { alloc::format!("{:x}", self) } +} + +impl fmt::LowerHex for CompactTarget { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } +} + +impl fmt::UpperHex for CompactTarget { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } +} + +encoding::encoder_newtype! { + /// The encoder for the [`CompactTarget`] type. + pub struct CompactTargetEncoder(encoding::ArrayEncoder<4>); +} + +impl encoding::Encodable for CompactTarget { + type Encoder<'e> = CompactTargetEncoder; + fn encoder(&self) -> Self::Encoder<'_> { + CompactTargetEncoder(encoding::ArrayEncoder::without_length_prefix( + self.to_consensus().to_le_bytes(), + )) + } +} + +/// The decoder for the [`CompactTarget`] type. +pub struct CompactTargetDecoder(encoding::ArrayDecoder<4>); + +impl CompactTargetDecoder { + /// Constructs a new [`CompactTarget`] decoder. + pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) } +} + +impl Default for CompactTargetDecoder { + fn default() -> Self { Self::new() } +} + +impl encoding::Decoder for CompactTargetDecoder { + type Output = CompactTarget; + type Error = CompactTargetDecoderError; + + #[inline] + fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result { + Ok(self.0.push_bytes(bytes)?) + } + + #[inline] + fn end(self) -> Result { + let n = u32::from_le_bytes(self.0.end()?); + Ok(CompactTarget::from_consensus(n)) + } + + #[inline] + fn read_limit(&self) -> usize { self.0.read_limit() } +} + +impl encoding::Decodable for CompactTarget { + type Decoder = CompactTargetDecoder; + fn decoder() -> Self::Decoder { CompactTargetDecoder(encoding::ArrayDecoder::<4>::new()) } +} + +/// An error consensus decoding an `CompactTarget`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CompactTargetDecoderError(encoding::UnexpectedEofError); + +impl From for CompactTargetDecoderError { + fn from(never: Infallible) -> Self { match never {} } +} + +impl From for CompactTargetDecoderError { + fn from(e: encoding::UnexpectedEofError) -> Self { Self(e) } +} + +impl fmt::Display for CompactTargetDecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_err!(f, "sequence decoder error"; self.0) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for CompactTargetDecoderError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) } +} + +#[cfg(test)] +mod tests { + #[cfg(feature = "alloc")] + use alloc::format; + + use super::*; + + #[test] + fn compact_target_ordering() { + let lower = CompactTarget::from_consensus(0x1d00_fffe); + let lower_copy = CompactTarget::from_consensus(0x1d00_fffe); + let higher = CompactTarget::from_consensus(0x1d00_ffff); + + assert!(lower < higher); + assert!(lower == lower_copy); + } + + #[test] + #[cfg(feature = "alloc")] + fn compact_target_formatting() { + let compact_target = CompactTarget::from_consensus(0x1d00_ffff); + assert_eq!(format!("{:x}", compact_target), "1d00ffff"); + assert_eq!(format!("{:X}", compact_target), "1D00FFFF"); + assert_eq!(compact_target.to_consensus(), 0x1d00_ffff); + } +} diff --git a/primitives/src/script/borrowed.rs b/primitives/src/script/borrowed.rs new file mode 100644 index 000000000..d75cc6a1c --- /dev/null +++ b/primitives/src/script/borrowed.rs @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: CC0-1.0 + +use core::marker::PhantomData; +use core::ops::{ + Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, +}; + +#[cfg(feature = "arbitrary")] +use arbitrary::{Arbitrary, Unstructured}; +use encoding::{BytesEncoder, CompactSizeEncoder, Encodable, Encoder2}; + +use super::ScriptBuf; +use crate::prelude::{Box, ToOwned, Vec}; + +internals::transparent_newtype! { + /// Bitcoin script slice. + /// + /// *[See also the `bitcoin::script` module](super).* + /// + /// `Script` is a script slice, the most primitive script type. It's usually seen in its borrowed + /// form `&Script`. It is always encoded as a series of bytes representing the opcodes and data + /// pushes. + /// + /// # Validity + /// + /// `Script` does not have any validity invariants - it's essentially just a marked slice of + /// bytes. This is similar to [`Path`](std::path::Path) vs [`OsStr`](std::ffi::OsStr) where they + /// are trivially cast-able to each-other and `Path` doesn't guarantee being a usable FS path but + /// having a newtype still has value because of added methods, readability and basic type checking. + /// + /// Although at least data pushes could be checked not to overflow the script, bad scripts are + /// allowed to be in a transaction (outputs just become unspendable) and there even are such + /// transactions in the chain. Thus we must allow such scripts to be placed in the transaction. + /// + /// # Slicing safety + /// + /// Slicing is similar to how `str` works: some ranges may be incorrect and indexing by + /// `usize` is not supported. However, as opposed to `std`, we have no way of checking + /// correctness without causing linear complexity so there are **no panics on invalid + /// ranges!** If you supply an invalid range, you'll get a garbled script. + /// + /// The range is considered valid if it's at a boundary of instruction. Care must be taken + /// especially with push operations because you could get a reference to arbitrary + /// attacker-supplied bytes that look like a valid script. + /// + /// It is recommended to use `.instructions()` method to get an iterator over script + /// instructions and work with that instead. + /// + /// # Memory safety + /// + /// The type is `#[repr(transparent)]` for internal purposes only! + /// No consumer crate may rely on the representation of the struct! + /// + /// # Hexadecimal strings + /// + /// Scripts are consensus encoded with a length prefix and as a result of this in some places in + /// the ecosystem one will encounter hex strings that include the prefix while in other places + /// the prefix is excluded. To support parsing and formatting scripts as hex we provide a bunch + /// of different APIs and trait implementations. Please see [`examples/script.rs`] for a + /// thorough example of all the APIs. + /// + /// # Bitcoin Core References + /// + /// * [CScript definition](https://github.com/bitcoin/bitcoin/blob/d492dc1cdaabdc52b0766bf4cba4bd73178325d0/src/script/script.h#L410) + /// + #[derive(PartialOrd, Ord, PartialEq, Eq, Hash)] + pub struct Script(PhantomData, [u8]); + + impl Script { + /// Treat byte slice as `Script` + pub const fn from_bytes(bytes: &_) -> &Self; + + /// Treat mutable byte slice as `Script` + pub fn from_bytes_mut(bytes: &mut _) -> &mut Self; + + pub(crate) fn from_boxed_bytes(bytes: Box<_>) -> Box; + pub(crate) fn from_rc_bytes(bytes: Rc<_>) -> Rc; + pub(crate) fn from_arc_bytes(bytes: Arc<_>) -> Arc; + } +} + +impl Default for &Script { + #[inline] + fn default() -> Self { Script::new() } +} + +impl ToOwned for Script { + type Owned = ScriptBuf; + + #[inline] + fn to_owned(&self) -> Self::Owned { ScriptBuf::from_bytes(self.to_vec()) } +} + +impl Script { + /// Constructs a new empty script. + #[inline] + pub const fn new() -> &'static Self { Self::from_bytes(&[]) } + + /// Returns the script data as a byte slice. + /// + /// This is just the script bytes **not** consensus encoding (which includes a length prefix). + #[inline] + pub const fn as_bytes(&self) -> &[u8] { &self.1 } + + /// Returns the script data as a mutable byte slice. + /// + /// This is just the script bytes **not** consensus encoding (which includes a length prefix). + #[inline] + pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.1 } + + /// Returns a copy of the script data. + /// + /// This is just the script bytes **not** consensus encoding (which includes a length prefix). + #[inline] + pub fn to_vec(&self) -> Vec { self.as_bytes().to_owned() } + + /// Returns a copy of the script data. + #[inline] + #[deprecated(since = "0.101.0", note = "use to_vec instead")] + pub fn to_bytes(&self) -> Vec { self.to_vec() } + + /// Returns the length in bytes of the script. + #[inline] + pub const fn len(&self) -> usize { self.as_bytes().len() } + + /// Returns whether the script is the empty script. + #[inline] + pub const fn is_empty(&self) -> bool { self.as_bytes().is_empty() } + + /// Converts a [`Box