diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 314a9ba78..9bfd48ab2 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -11,7 +11,7 @@ on: jobs: fuzz: if: ${{ !github.event.act }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -28,8 +28,8 @@ roundtrip_semantic, 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@v2 - - uses: actions/cache@v2 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 id: cache-fuzz with: path: | @@ -39,13 +39,13 @@ roundtrip_semantic, key: cache-${{ matrix.target }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} - uses: actions-rs/toolchain@v1 with: - toolchain: 1.58 + toolchain: 1.65 override: true profile: minimal - name: fuzz run: cd fuzz && ./fuzz.sh "${{ matrix.fuzz_target }}" - run: echo "${{ matrix.fuzz_target }}" >executed_${{ matrix.fuzz_target }} - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: name: executed_${{ matrix.fuzz_target }} path: executed_${{ matrix.fuzz_target }} @@ -55,8 +55,8 @@ roundtrip_semantic, needs: fuzz runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/download-artifact@v2 + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 - name: Display structure of downloaded files run: ls -R - run: find executed_* -type f -exec cat {} + | sort > executed diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d035a0d6d..76e79943b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -3,17 +3,29 @@ on: [push, pull_request] name: Continuous integration jobs: + Prepare: + runs-on: ubuntu-latest + outputs: + nightly_version: ${{ steps.read_toolchain.outputs.nightly_version }} + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + - name: "Read nightly version" + id: read_toolchain + run: echo "nightly_version=$(cat nightly-version)" >> $GITHUB_OUTPUT + Nightly: name: Nightly - Bench + Docs + Fmt + needs: Prepare runs-on: ubuntu-latest steps: - name: Checkout Crate - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Checkout Toolchain uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: ${{ needs.Prepare.outputs.nightly_version }} override: true - name: Running benchmarks env: @@ -33,7 +45,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Crate - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Checkout Toolchain uses: actions-rs/toolchain@v1 with: @@ -47,18 +59,18 @@ jobs: Tests: name: Tests + needs: Prepare runs-on: ubuntu-latest strategy: matrix: include: - rust: stable - rust: beta - - rust: nightly - rust: 1.41.1 - - rust: 1.47 + - rust: ${{ needs.Prepare.outputs.nightly_version }} steps: - name: Checkout Crate - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Checkout Toolchain uses: actions-rs/toolchain@v1 with: @@ -72,17 +84,18 @@ jobs: run: ./contrib/test.sh Embedded: + needs: Prepare runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up QEMU run: sudo apt update && sudo apt install -y qemu-system-arm gcc-arm-none-eabi - name: Checkout Toolchain uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly + toolchain: ${{ needs.Prepare.outputs.nightly_version }} override: true components: rust-src target: thumbv7m-none-eabi @@ -90,4 +103,4 @@ jobs: 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" - run: cd embedded && cargo run --target thumbv7m-none-eabi --release + run: cp Cargo-recent.lock Cargo.lock && cd embedded && cargo run --target thumbv7m-none-eabi --release diff --git a/Cargo-recent.lock b/Cargo-recent.lock new file mode 100644 index 000000000..c82cb8935 --- /dev/null +++ b/Cargo-recent.lock @@ -0,0 +1,559 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ahash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa60d2eadd8b12a996add391db32bd1153eac697ba4869660c0016353611426" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "bitcoin" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" +dependencies = [ + "base64", + "bech32", + "bitcoin-private", + "bitcoin_hashes", + "core2", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-private" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" + +[[package]] +name = "bitcoin_hashes" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +dependencies = [ + "bitcoin-private", + "core2", + "serde", +] + +[[package]] +name = "bitcoind" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4a98e66bb7c1f81abf4f8d992e1839fc0f9cbc627effbff122aae7d5e493a0" +dependencies = [ + "anyhow", + "core-rpc", + "log", + "tempfile", + "which", +] + +[[package]] +name = "bitcoind-tests" +version = "0.1.0" +dependencies = [ + "bitcoin-private", + "bitcoind", + "miniscript", + "rand 0.8.5", + "secp256k1", +] + +[[package]] +name = "cc" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-rpc" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d77079e1b71c2778d6e1daf191adadcd4ff5ec3ccad8298a79061d865b235b" +dependencies = [ + "bitcoin-private", + "core-rpc-json", + "jsonrpc", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "core-rpc-json" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581898ed9a83f31c64731b1d8ca2dfffcfec14edf1635afacd5234cddbde3a41" +dependencies = [ + "bitcoin", + "bitcoin-private", + "serde", + "serde_json", +] + +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr", +] + +[[package]] +name = "descriptor-fuzz" +version = "0.0.1" +dependencies = [ + "honggfuzz", + "miniscript", + "regex", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "362385356d610bd1e5a408ddf8d022041774b683f345a1d2cfcb4f60f8ae2db5" +dependencies = [ + "ahash", +] + +[[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.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "848e9c511092e0daa0a35a63e8e6e475a3e8f870741448b9f6028d69b142f18e" +dependencies = [ + "lazy_static", + "memmap2", + "rustc_version", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "jsonrpc" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd8d6b3f301ba426b30feca834a2a18d48d5b54e5065496b5c1b05537bee3639" +dependencies = [ + "base64", + "serde", + "serde_json", +] + +[[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.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "log" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" +dependencies = [ + "cfg-if 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "miniscript" +version = "10.2.2" +dependencies = [ + "base64", + "bitcoin", + "bitcoin-private", + "hashbrown", + "secp256k1", + "serde", + "serde_test", +] + +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + +[[package]] +name = "ppv-lite86" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" + +[[package]] +name = "proc-macro2" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "regex" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[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 = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f60a296fed15c3edbbe9aa83b646531459e565c525b0ab628deb1a4b28e4180" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_test" +version = "1.0.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "641666500e4e6fba7b91b73651a375cb53579468ab3c38389289b802797cad94" +dependencies = [ + "serde", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439d9a7c00f98b1b5ee730039bf5b1f9203d508690e3c76b509e7ad59f8f7c99" +dependencies = [ + "libc", + "rand 0.4.6", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "4.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae" +dependencies = [ + "either", + "lazy_static", + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 929b508f5..f431ebb7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ base64 = ["bitcoin/base64"] [dependencies] bitcoin = { version = "0.30.0", default-features = false } hashbrown = { version = "0.11", optional = true } -internals = { package = "bitcoin-private", version = "0.1.0", default_features = false } +internals = { package = "bitcoin-private", version = "0.1.0", default-features = false } # Do NOT use this as a feature! Use the `serde` feature instead. actual-serde = { package = "serde", version = "1.0.103", optional = true } diff --git a/bitcoind-tests/Cargo.toml b/bitcoind-tests/Cargo.toml index 57eb1c530..300e96d66 100644 --- a/bitcoind-tests/Cargo.toml +++ b/bitcoind-tests/Cargo.toml @@ -12,4 +12,4 @@ miniscript = {path = "../"} bitcoind = { version = "0.30.0" } actual-rand = { package = "rand", version = "0.8.4"} secp256k1 = {version = "0.27.0", features = ["rand-std"]} -internals = { package = "bitcoin-private", version = "0.1.0", default_features = false } \ No newline at end of file +internals = { package = "bitcoin-private", version = "0.1.0", default-features = false } \ No newline at end of file diff --git a/clippy.toml b/clippy.toml index 799264ef1..92cf0149a 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1,9 @@ msrv = "1.41.1" +# PSBT API returns Self as an error type for an large-ish enum +large-error-threshold = 512 +# A couple tests have huge tuples instead of structs. This is fixed +# in a later major rev. For now we just turn down the lint. +type-complexity-threshold = 1000 +# Some internal compiler functions take a gazillion arguments. Again, +# this is fixed in a later major rev so just turn down the lint here. +too-many-arguments-threshold = 9 diff --git a/contrib/test.sh b/contrib/test.sh index eed23e09c..d3fd7805d 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -11,79 +11,69 @@ rustc --version if [ "$DO_FMT" = true ] then rustup component add rustfmt - cargo fmt -- --check + cargo fmt --check fi -# Pin dependencies required to build with Rust 1.41.1 -if cargo --version | grep "1\.41\.0"; then - cargo update -p once_cell --precise 1.13.1 - cargo update -p serde --precise 1.0.156 -fi - -# Pin dependencies required to build with Rust 1.47.0 -if cargo --version | grep "1\.47\.0"; then - cargo update -p once_cell --precise 1.13.1 - cargo update -p serde --precise 1.0.156 -fi +cp Cargo-recent.lock Cargo.lock # Test bitcoind integration tests if told to (this only works with the stable toolchain) if [ "$DO_BITCOIND_TESTS" = true ]; then cd bitcoind-tests BITCOIND_EXE="$(git rev-parse --show-toplevel)/bitcoind-tests/bin/bitcoind" \ - cargo test --verbose + cargo --locked test --verbose # Exit integration tests, do not run other tests. exit 0 fi # Defaults / sanity checks -cargo test +cargo --locked test if [ "$DO_FEATURE_MATRIX" = true ] then # All features - cargo test --features="$FEATURES" + cargo --locked test --features="$FEATURES" # Single features for feature in ${FEATURES} do - cargo test --features="$feature" + cargo --locked test --features="$feature" done # Run all the examples - cargo build --examples - cargo run --example htlc --features=compiler - cargo run --example parse - cargo run --example sign_multisig - cargo run --example verify_tx > /dev/null - cargo run --example psbt - cargo run --example xpub_descriptors - cargo run --example taproot --features=compiler - cargo run --example psbt_sign_finalize --features=base64 + cargo --locked build --examples + cargo --locked run --example htlc --features=compiler + cargo --locked run --example parse + cargo --locked run --example sign_multisig + cargo --locked run --example verify_tx > /dev/null + cargo --locked run --example psbt + cargo --locked run --example xpub_descriptors + cargo --locked run --example taproot --features=compiler + cargo --locked run --example psbt_sign_finalize --features=base64 fi if [ "$DO_NO_STD" = true ] then # Build no_std, to make sure that cfg(test) doesn't hide any issues - cargo build --verbose --no-default-features --features="no-std" + cargo --locked build --verbose --no-default-features --features="no-std" # Test no_std - cargo test --verbose --no-default-features --features="no-std" + cargo --locked test --verbose --no-default-features --features="no-std" # Build all features - cargo build --verbose --no-default-features --features="no-std $FEATURES" + cargo --locked build --verbose --no-default-features --features="no-std $FEATURES" # Build specific features for feature in ${FEATURES} do - cargo build --verbose --no-default-features --features="no-std $feature" + cargo --locked build --verbose --no-default-features --features="no-std $feature" done fi # Bench if told to (this only works with the nightly toolchain) if [ "$DO_BENCH" = true ] then - cargo bench --features="unstable compiler" + cargo --locked bench --features="unstable compiler" fi # Build the docs if told to (this only works with the nightly toolchain) diff --git a/examples/psbt_sign_finalize.rs b/examples/psbt_sign_finalize.rs index 44c397582..ba2d49fdd 100644 --- a/examples/psbt_sign_finalize.rs +++ b/examples/psbt_sign_finalize.rs @@ -17,7 +17,7 @@ fn main() { let secp256k1 = secp256k1::Secp256k1::new(); let s = "wsh(t:or_c(pk(027a3565454fe1b749bccaef22aff72843a9c3efefd7b16ac54537a0c23f0ec0de),v:thresh(1,pkh(032d672a1a91cc39d154d366cd231983661b0785c7f27bc338447565844f4a6813),a:pkh(03417129311ed34c242c012cd0a3e0b9bca0065f742d0dfb63c78083ea6a02d4d9),a:pkh(025a687659658baeabdfc415164528065be7bcaade19342241941e556557f01e28))))#7hut9ukn"; - let bridge_descriptor = Descriptor::from_str(&s).unwrap(); + let bridge_descriptor = Descriptor::from_str(s).unwrap(); //let bridge_descriptor = Descriptor::::from_str(&s).expect("parse descriptor string"); assert!(bridge_descriptor.sanity_check().is_ok()); println!( @@ -97,10 +97,11 @@ fn main() { let (outpoint, witness_utxo) = get_vout(&depo_tx, &bridge_descriptor.script_pubkey()); - let mut txin = TxIn::default(); - txin.previous_output = outpoint; - - txin.sequence = Sequence::from_height(26); //Sequence::MAX; // + let txin = TxIn { + previous_output: outpoint, + sequence: Sequence::from_height(26), + ..TxIn::default() + }; psbt.unsigned_tx.input.push(txin); psbt.unsigned_tx.output.push(TxOut { @@ -147,13 +148,9 @@ fn main() { let pk2 = backup2_private.public_key(&secp256k1); assert!(secp256k1.verify_ecdsa(&msg, &sig2, &pk2.inner).is_ok()); - psbt.inputs[0].partial_sigs.insert( - pk1, - bitcoin::ecdsa::Signature { - sig: sig1, - hash_ty: hash_ty, - }, - ); + psbt.inputs[0] + .partial_sigs + .insert(pk1, bitcoin::ecdsa::Signature { sig: sig1, hash_ty }); println!("{:#?}", psbt); diff --git a/examples/sign_multisig.rs b/examples/sign_multisig.rs index e4b1cac33..2aab29f67 100644 --- a/examples/sign_multisig.rs +++ b/examples/sign_multisig.rs @@ -105,8 +105,8 @@ fn spending_transaction() -> bitcoin::Transaction { } } +#[rustfmt::skip] fn list_of_three_arbitrary_public_keys() -> Vec { - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] vec![ bitcoin::PublicKey::from_slice(&[2; 33]).expect("key 1"), bitcoin::PublicKey::from_slice(&[ diff --git a/examples/taproot.rs b/examples/taproot.rs index 0d64ebeff..5d4b76efd 100644 --- a/examples/taproot.rs +++ b/examples/taproot.rs @@ -138,8 +138,8 @@ fn hardcoded_xonlypubkeys() -> Vec { ], ]; let mut keys: Vec = vec![]; - for idx in 0..4 { - keys.push(XOnlyPublicKey::from_slice(&serialized_keys[idx][..]).unwrap()); + for key in &serialized_keys { + keys.push(XOnlyPublicKey::from_slice(key).unwrap()); } keys } diff --git a/examples/verify_tx.rs b/examples/verify_tx.rs index 9f2387a2f..68cd12035 100644 --- a/examples/verify_tx.rs +++ b/examples/verify_tx.rs @@ -58,15 +58,12 @@ fn main() { for elem in interpreter.iter_assume_sigs() { // Don't bother checking signatures. - match elem.expect("no evaluation error") { - miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => { - let (key, sig) = key_sig - .as_ecdsa() - .expect("expected ecdsa sig, found schnorr sig"); - - println!("Signed with:\n key: {}\n sig: {}", key, sig); - } - _ => {} + if let Ok(miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig }) = elem { + let (key, sig) = key_sig + .as_ecdsa() + .expect("expected ecdsa sig, found schnorr sig"); + + println!("Signed with:\n key: {}\n sig: {}", key, sig); } } @@ -83,12 +80,9 @@ fn main() { let prevouts = sighash::Prevouts::All::(&[]); for elem in interpreter.iter(&secp, &tx, 0, &prevouts) { - match elem.expect("no evaluation error") { - miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig } => { - let (key, sig) = key_sig.as_ecdsa().unwrap(); - println!("Signed with:\n key: {}\n sig: {}", key, sig); - } - _ => {} + if let Ok(miniscript::interpreter::SatisfiedConstraint::PublicKey { key_sig }) = elem { + let (key, sig) = key_sig.as_ecdsa().unwrap(); + println!("Signed with:\n key: {}\n sig: {}", key, sig); } } @@ -116,9 +110,9 @@ fn main() { } /// Returns an arbitrary transaction. +#[rustfmt::skip] fn hard_coded_transaction() -> bitcoin::Transaction { // tx `f27eba163c38ad3f34971198687a3f1882b7ec818599ffe469a8440d82261c98` - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] let tx_bytes = vec![ 0x01, 0x00, 0x00, 0x00, 0x02, 0xc5, 0x11, 0x1d, 0xb7, 0x93, 0x50, 0xc1, 0x70, 0x28, 0x41, 0x39, 0xe8, 0xe3, 0x4e, 0xb0, 0xed, 0xba, 0x64, 0x7b, diff --git a/examples/xpub_descriptors.rs b/examples/xpub_descriptors.rs index f640fad35..d5677f1f6 100644 --- a/examples/xpub_descriptors.rs +++ b/examples/xpub_descriptors.rs @@ -42,7 +42,7 @@ fn p2wsh(secp: &Secp256k1) -> Address { let address = Descriptor::::from_str(&s) .unwrap() - .derived_descriptor(&secp) + .derived_descriptor(secp) .unwrap() .address(Network::Bitcoin) .unwrap(); @@ -65,7 +65,7 @@ fn p2sh_p2wsh(secp: &Secp256k1) -> Address { let address = Descriptor::::from_str(&s) .unwrap() - .derived_descriptor(&secp, 5) + .derived_descriptor(secp, 5) .unwrap() .address(Network::Bitcoin) .unwrap(); diff --git a/fuzz/fuzz_targets/roundtrip_descriptor.rs b/fuzz/fuzz_targets/roundtrip_descriptor.rs index d74569e88..13d54b1b3 100644 --- a/fuzz/fuzz_targets/roundtrip_descriptor.rs +++ b/fuzz/fuzz_targets/roundtrip_descriptor.rs @@ -26,6 +26,6 @@ mod tests { use super::*; #[test] fn test() { - do_test(b"pkh()"); + do_test(b"tr(}4872r1111r(r)"); } } diff --git a/nightly-version b/nightly-version new file mode 100644 index 000000000..ba747383d --- /dev/null +++ b/nightly-version @@ -0,0 +1 @@ +nightly-2025-03-21 diff --git a/src/descriptor/bare.rs b/src/descriptor/bare.rs index 074a21b61..771dd8738 100644 --- a/src/descriptor/bare.rs +++ b/src/descriptor/bare.rs @@ -192,7 +192,7 @@ where where T: Translator, { - Ok(Bare::new(self.ms.translate_pk(t)?).map_err(TranslateErr::OuterError)?) + Bare::new(self.ms.translate_pk(t)?).map_err(TranslateErr::OuterError) } } diff --git a/src/descriptor/checksum.rs b/src/descriptor/checksum.rs index 4613db3fd..23ff72aa2 100644 --- a/src/descriptor/checksum.rs +++ b/src/descriptor/checksum.rs @@ -8,10 +8,10 @@ use core::fmt; use core::iter::FromIterator; +pub use crate::expression::INPUT_CHARSET; use crate::prelude::*; use crate::Error; -const INPUT_CHARSET: &str = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "; const CHECKSUM_CHARSET: &[u8] = b"qpzry9x8gf2tvdw0s3jn54khce6mua7l"; fn poly_mod(mut c: u64, val: u64) -> u64 { diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index ac27202c2..208876370 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -861,8 +861,7 @@ fn parse_xkey_deriv( // step all the vectors of indexes contain a single element. If it did though, one of the // vectors contains more than one element. // Now transform this list of vectors of steps into distinct derivation paths. - .fold(Ok(Vec::new()), |paths, index_list| { - let mut paths = paths?; + .try_fold(Vec::new(), |mut paths, index_list| { let mut index_list = index_list?.into_iter(); let first_index = index_list .next() @@ -951,9 +950,7 @@ impl DescriptorXKey { let (compare_fingerprint, compare_path) = match self.origin { Some((fingerprint, ref path)) => ( fingerprint, - path.into_iter() - .chain(self.derivation_path.into_iter()) - .collect(), + path.into_iter().chain(&self.derivation_path).collect(), ), None => ( self.xkey.xkey_fingerprint(secp), @@ -1190,7 +1187,8 @@ mod test { DescriptorKeyParseError, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, MiniscriptKey, Wildcard, }; - use crate::{prelude::*, DefiniteDescriptorKey}; + use crate::prelude::*; + use crate::DefiniteDescriptorKey; #[test] fn parse_descriptor_key_errors() { diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index 390d86140..8a46ee4fb 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -612,7 +612,7 @@ impl Descriptor { /// See [`at_derivation_index`] and `[derived_descriptor`] for more documentation. /// /// [`at_derivation_index`]: Self::at_derivation_index - /// [`derived_descriptor`]: crate::DerivedDescriptor::derived_descriptor + /// [`derived_descriptor`]: crate::Descriptor::derived_descriptor /// /// # Errors /// @@ -776,7 +776,7 @@ impl Descriptor { /// /// For multipath descriptors it will return as many descriptors as there is /// "parallel" paths. For regular descriptors it will just return itself. - #[allow(clippy::blocks_in_if_conditions)] + #[allow(clippy::blocks_in_conditions)] pub fn into_single_descriptors(self) -> Result>, Error> { // All single-path descriptors contained in this descriptor. let mut descriptors = Vec::new(); @@ -1073,7 +1073,7 @@ mod tests { .push_opcode(opcodes::all::OP_DUP) .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",) + hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",) .unwrap() .to_byte_array() ) @@ -1097,7 +1097,7 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice( - &hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",) + hash160::Hash::from_str("84e9ed95a38613f0527ff685a9928abe2d4754d4",) .unwrap() .to_byte_array() ) @@ -1119,7 +1119,7 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_str("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",) + hash160::Hash::from_str("f1c3b9a431134cb90a500ec06e0067cfa9b8bba7",) .unwrap() .to_byte_array() ) @@ -1142,7 +1142,7 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_str("aa5282151694d3f2f32ace7d00ad38f927a33ac8",) + hash160::Hash::from_str("aa5282151694d3f2f32ace7d00ad38f927a33ac8",) .unwrap() .to_byte_array() ) @@ -1165,7 +1165,7 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice( - &sha256::Hash::from_str( + sha256::Hash::from_str( "\ f9379edc8983152dc781747830075bd5\ 3896e4b0ce5bff73777fd77d124ba085\ @@ -1192,7 +1192,7 @@ mod tests { script::Builder::new() .push_opcode(opcodes::all::OP_HASH160) .push_slice( - &hash160::Hash::from_str("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",) + hash160::Hash::from_str("4bec5d7feeed99e1d0a23fe32a4afe126a7ff07e",) .unwrap() .to_byte_array() ) @@ -1287,7 +1287,7 @@ mod tests { previous_output: bitcoin::OutPoint::default(), script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::from_height(100), - witness: Witness::from_slice(&vec![sigser.clone(), pk.to_bytes(),]), + witness: Witness::from_slice(&[sigser.clone(), pk.to_bytes(),]), } ); assert_eq!(wpkh.unsigned_script_sig(), bitcoin::ScriptBuf::new()); @@ -1297,7 +1297,7 @@ mod tests { let redeem_script = script::Builder::new() .push_opcode(opcodes::all::OP_PUSHBYTES_0) .push_slice( - &hash160::Hash::from_str("d1b2a1faf62e73460af885c687dee3b7189cd8ab") + hash160::Hash::from_str("d1b2a1faf62e73460af885c687dee3b7189cd8ab") .unwrap() .to_byte_array(), ) @@ -1310,7 +1310,7 @@ mod tests { .push_slice(<&PushBytes>::try_from(redeem_script.as_bytes()).unwrap()) .into_script(), sequence: Sequence::from_height(100), - witness: Witness::from_slice(&vec![sigser.clone(), pk.to_bytes(),]), + witness: Witness::from_slice(&[sigser.clone(), pk.to_bytes(),]), } ); assert_eq!( @@ -1347,7 +1347,7 @@ mod tests { previous_output: bitcoin::OutPoint::default(), script_sig: bitcoin::ScriptBuf::new(), sequence: Sequence::from_height(100), - witness: Witness::from_slice(&vec![sigser.clone(), ms.encode().into_bytes(),]), + witness: Witness::from_slice(&[sigser.clone(), ms.encode().into_bytes(),]), } ); assert_eq!(wsh.unsigned_script_sig(), bitcoin::ScriptBuf::new()); @@ -1364,7 +1364,7 @@ mod tests { ) .into_script(), sequence: Sequence::from_height(100), - witness: Witness::from_slice(&vec![sigser.clone(), ms.encode().into_bytes(),]), + witness: Witness::from_slice(&[sigser.clone(), ms.encode().into_bytes(),]), } ); assert_eq!( diff --git a/src/descriptor/sh.rs b/src/descriptor/sh.rs index a421058a7..95a3997d6 100644 --- a/src/descriptor/sh.rs +++ b/src/descriptor/sh.rs @@ -348,13 +348,13 @@ impl Sh { let witness_script = wsh.inner_script().to_v0_p2wsh(); let push_bytes = <&PushBytes>::try_from(witness_script.as_bytes()) .expect("Witness script is not too large"); - script::Builder::new().push_slice(&push_bytes).into_script() + script::Builder::new().push_slice(push_bytes).into_script() } ShInner::Wpkh(ref wpkh) => { let redeem_script = wpkh.script_pubkey(); let push_bytes: &PushBytes = <&PushBytes>::try_from(redeem_script.as_bytes()).expect("Script not too large"); - script::Builder::new().push_slice(&push_bytes).into_script() + script::Builder::new().push_slice(push_bytes).into_script() } ShInner::SortedMulti(..) | ShInner::Ms(..) => ScriptBuf::new(), } diff --git a/src/descriptor/tr.rs b/src/descriptor/tr.rs index 4e0b6a475..c55250c75 100644 --- a/src/descriptor/tr.rs +++ b/src/descriptor/tr.rs @@ -82,11 +82,7 @@ impl Eq for Tr {} impl PartialOrd for Tr { fn partial_cmp(&self, other: &Self) -> Option { - match self.internal_key.partial_cmp(&other.internal_key) { - Some(cmp::Ordering::Equal) => {} - ord => return ord, - } - self.tree.partial_cmp(&other.tree) + Some(self.cmp(other)) } } @@ -122,7 +118,7 @@ impl TapTree { /// Iterates over all miniscripts in DFS walk order compatible with the /// PSBT requirements (BIP 371). - pub fn iter(&self) -> TapTreeIter { + pub fn iter(&self) -> TapTreeIter<'_, Pk> { TapTreeIter { stack: vec![(0, self)], } @@ -192,7 +188,7 @@ impl Tr { /// Iterate over all scripts in merkle tree. If there is no script path, the iterator /// yields [`None`] - pub fn iter_scripts(&self) -> TapTreeIter { + pub fn iter_scripts(&self) -> TapTreeIter<'_, Pk> { match self.tree { Some(ref t) => t.iter(), None => TapTreeIter { stack: vec![] }, @@ -350,7 +346,7 @@ impl Tr { let builder = bitcoin::blockdata::script::Builder::new(); builder .push_opcode(opcodes::all::OP_PUSHNUM_1) - .push_slice(&output_key.serialize()) + .push_slice(output_key.serialize()) .into_script() } @@ -405,8 +401,7 @@ where type Item = (u8, &'a Miniscript); fn next(&mut self) -> Option { - while !self.stack.is_empty() { - let (depth, last) = self.stack.pop().expect("Size checked above"); + while let Some((depth, last)) = self.stack.pop() { match *last { TapTree::Tree(ref l, ref r) => { self.stack.push((depth + 1, r)); @@ -518,12 +513,8 @@ impl fmt::Display for Tr { } // Helper function to parse string into miniscript tree form -fn parse_tr_tree(s: &str) -> Result { - for ch in s.bytes() { - if !ch.is_ascii() { - return Err(Error::Unprintable(ch)); - } - } +fn parse_tr_tree(s: &str) -> Result, Error> { + expression::check_valid_chars(s)?; if s.len() > 3 && &s[..3] == "tr(" && s.as_bytes()[s.len() - 1] == b')' { let rest = &s[3..s.len() - 1]; diff --git a/src/expression.rs b/src/expression.rs index d3363abc4..22a3b53a2 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -8,6 +8,9 @@ use core::str::FromStr; use crate::prelude::*; use crate::{errstr, Error, MAX_RECURSION_DEPTH}; +/// Allowed characters are descriptor strings. +pub const INPUT_CHARSET: &str = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "; + #[derive(Debug)] /// A token of the form `x(...)` or `x` pub struct Tree<'a> { @@ -166,13 +169,7 @@ impl<'a> Tree<'a> { /// Parses a tree from a string #[allow(clippy::should_implement_trait)] // Cannot use std::str::FromStr because of lifetimes. pub fn from_str(s: &'a str) -> Result, Error> { - // Filter out non-ASCII because we byte-index strings all over the - // place and Rust gets very upset when you splinch a string. - for ch in s.bytes() { - if !ch.is_ascii() { - return Err(Error::Unprintable(ch)); - } - } + check_valid_chars(s)?; let (top, rem) = Tree::from_slice(s)?; if rem.is_empty() { @@ -183,6 +180,21 @@ impl<'a> Tree<'a> { } } +/// Filter out non-ASCII because we byte-index strings all over the +/// place and Rust gets very upset when you splinch a string. +pub fn check_valid_chars(s: &str) -> Result<(), Error> { + for ch in s.bytes() { + if !ch.is_ascii() { + return Err(Error::Unprintable(ch)); + } + // TODO: Avoid linear search overhead by using OnceCell to cache this in a BTreeMap. + INPUT_CHARSET + .find(char::from(ch)) + .ok_or_else(|| Error::Unprintable(ch))?; + } + Ok(()) +} + /// Parse a string as a u32, for timelocks or thresholds pub fn parse_num(s: &str) -> Result { if s.len() > 1 { diff --git a/src/interpreter/inner.rs b/src/interpreter/inner.rs index 538cacb7e..8f45049dd 100644 --- a/src/interpreter/inner.rs +++ b/src/interpreter/inner.rs @@ -43,7 +43,7 @@ fn script_from_stack_elem( ) -> Result, Error> { match *elem { stack::Element::Push(sl) => { - Miniscript::parse_with_ext(&bitcoin::Script::from_bytes(sl), &ExtParams::allow_all()) + Miniscript::parse_with_ext(bitcoin::Script::from_bytes(sl), &ExtParams::allow_all()) .map_err(Error::from) } stack::Element::Satisfied => { @@ -453,21 +453,21 @@ mod tests { KeyTestData { pk_spk: bitcoin::ScriptBuf::new_p2pk(&key), pkh_spk: bitcoin::ScriptBuf::new_p2pkh(&pkhash), - pk_sig: script::Builder::new().push_slice(&dummy_sig).into_script(), + pk_sig: script::Builder::new().push_slice(dummy_sig).into_script(), pkh_sig: script::Builder::new() - .push_slice(&dummy_sig) + .push_slice(dummy_sig) .push_key(&key) .into_script(), pkh_sig_justkey: script::Builder::new().push_key(&key).into_script(), wpkh_spk: wpkh_spk.clone(), - wpkh_stack: Witness::from_slice(&vec![dummy_sig_vec.clone(), key.to_bytes()]), - wpkh_stack_justkey: Witness::from_slice(&vec![key.to_bytes()]), + wpkh_stack: Witness::from_slice(&[dummy_sig_vec.clone(), key.to_bytes()]), + wpkh_stack_justkey: Witness::from_slice(&[key.to_bytes()]), sh_wpkh_spk: bitcoin::ScriptBuf::new_p2sh(&wpkh_scripthash), sh_wpkh_sig: script::Builder::new() .push_slice(<&PushBytes>::try_from(wpkh_spk[..].as_bytes()).unwrap()) .into_script(), - sh_wpkh_stack: Witness::from_slice(&vec![dummy_sig_vec, key.to_bytes()]), - sh_wpkh_stack_justkey: Witness::from_slice(&vec![key.to_bytes()]), + sh_wpkh_stack: Witness::from_slice(&[dummy_sig_vec, key.to_bytes()]), + sh_wpkh_stack_justkey: Witness::from_slice(&[key.to_bytes()]), } } } @@ -561,7 +561,7 @@ mod tests { assert_eq!(&err.to_string()[0..12], "parse error:"); // Witness is nonempty - let wit = Witness::from_slice(&vec![vec![]]); + let wit = Witness::from_slice(&[vec![]]); let err = from_txdata(&comp.pk_spk, &comp.pk_sig, &wit).unwrap_err(); assert_eq!(err.to_string(), "legacy spend had nonempty witness"); } @@ -622,7 +622,7 @@ mod tests { assert_eq!(script_code, Some(uncomp.pkh_spk.clone())); // Witness is nonempty - let wit = Witness::from_slice(&vec![vec![]]); + let wit = Witness::from_slice(&[vec![]]); let err = from_txdata(&comp.pkh_spk, &comp.pkh_sig, &wit).unwrap_err(); assert_eq!(err.to_string(), "legacy spend had nonempty witness"); } @@ -785,7 +785,7 @@ mod tests { assert_eq!(&err.to_string()[0..12], "parse error:"); // nonempty witness - let wit = Witness::from_slice(&vec![vec![]]); + let wit = Witness::from_slice(&[vec![]]); let err = from_txdata(&spk, &blank_script, &wit).unwrap_err(); assert_eq!(&err.to_string(), "legacy spend had nonempty witness"); } @@ -821,7 +821,7 @@ mod tests { assert_eq!(script_code, Some(redeem_script)); // nonempty witness - let wit = Witness::from_slice(&vec![vec![]]); + let wit = Witness::from_slice(&[vec![]]); let err = from_txdata(&spk, &script_sig, &wit).unwrap_err(); assert_eq!(&err.to_string(), "legacy spend had nonempty witness"); } @@ -832,7 +832,7 @@ mod tests { let hash = hash160::Hash::hash(&preimage[..]); let (miniscript, witness_script) = ms_inner_script(&format!("hash160({})", hash)); let wit_hash = sha256::Hash::hash(witness_script.as_bytes()).into(); - let wit_stack = Witness::from_slice(&vec![witness_script.to_bytes()]); + let wit_stack = Witness::from_slice(&[witness_script.to_bytes()]); let spk = ScriptBuf::new_v0_p2wsh(&wit_hash); let blank_script = bitcoin::ScriptBuf::new(); @@ -842,7 +842,7 @@ mod tests { assert_eq!(&err.to_string(), "unexpected end of stack"); // with incorrect witness - let wit = Witness::from_slice(&vec![spk.to_bytes()]); + let wit = Witness::from_slice(&[spk.to_bytes()]); let err = from_txdata(&spk, &blank_script, &wit).unwrap_err(); assert_eq!(&err.to_string()[0..12], "parse error:"); @@ -867,7 +867,7 @@ mod tests { let hash = hash160::Hash::hash(&preimage[..]); let (miniscript, witness_script) = ms_inner_script(&format!("hash160({})", hash)); let wit_hash = sha256::Hash::hash(witness_script.as_bytes()).into(); - let wit_stack = Witness::from_slice(&vec![witness_script.to_bytes()]); + let wit_stack = Witness::from_slice(&[witness_script.to_bytes()]); let redeem_script = ScriptBuf::new_v0_p2wsh(&wit_hash); let script_sig = script::Builder::new() @@ -887,7 +887,7 @@ mod tests { assert_eq!(&err.to_string(), "unexpected end of stack"); // with incorrect witness - let wit = Witness::from_slice(&vec![spk.to_bytes()]); + let wit = Witness::from_slice(&[spk.to_bytes()]); let err = from_txdata(&spk, &script_sig, &wit).unwrap_err(); assert_eq!(&err.to_string()[0..12], "parse error:"); diff --git a/src/lib.rs b/src/lib.rs index 23a99c8c7..e938dd219 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -385,7 +385,7 @@ impl TranslateErr { /// - SegwitV0 does not allow uncompressed keys and x_only keys /// - Tapscript does not allow uncompressed keys /// - Translating into multi-path descriptors should have same number of path - /// for all the keys in the descriptor + /// for all the keys in the descriptor /// /// # Panics /// @@ -394,7 +394,10 @@ impl TranslateErr { match self { Self::TranslatorErr(v) => v, Self::OuterError(ref e) => { - panic!("Unexpected Miniscript error when translating: {}\nMessage: {}", e, msg) + panic!( + "Unexpected Miniscript error when translating: {}\nMessage: {}", + e, msg + ) } } } @@ -444,16 +447,6 @@ where T: Translator; } -/// Either a key or keyhash, but both contain Pk -// pub struct ForEach<'a, Pk: MiniscriptKey>(&'a Pk); - -// impl<'a, Pk: MiniscriptKey> ForEach<'a, Pk> { -// /// Convenience method to avoid distinguishing between keys and hashes when these are the same type -// pub fn as_key(&self) -> &'a Pk { -// self.0 -// } -// } - /// Trait describing the ability to iterate over every key pub trait ForEachKey { /// Run a predicate on every key in the descriptor, returning whether diff --git a/src/miniscript/analyzable.rs b/src/miniscript/analyzable.rs index 8b1929a65..2e3b1fa4f 100644 --- a/src/miniscript/analyzable.rs +++ b/src/miniscript/analyzable.rs @@ -18,9 +18,7 @@ use crate::{Miniscript, MiniscriptKey, ScriptContext, Terminal}; /// /// This allows parsing miniscripts if /// 1. It is unsafe(does not require a digital signature to spend it) -/// 2. It contains a unspendable path because of either -/// a. Resource limitations -/// b. Timelock Mixing +/// 2. It contains a unspendable path because of either resource limitations or timelock mixing. /// 3. The script is malleable and thereby some of satisfaction weight /// guarantees are not satisfied. /// 4. It has repeated public keys @@ -126,9 +124,7 @@ impl ExtParams { /// Possible reasons Miniscript guarantees can fail /// We currently mark Miniscript as Non-Analyzable if /// 1. It is unsafe(does not require a digital signature to spend it) -/// 2. It contains a unspendable path because of either -/// a. Resource limitations -/// b. Timelock Mixing +/// 2. It contains a unspendable path because of either resource limitations or timelock mixing. /// 3. The script is malleable and thereby some of satisfaction weight /// guarantees are not satisfied. /// 4. It has repeated publickeys diff --git a/src/miniscript/astelem.rs b/src/miniscript/astelem.rs index d0388554c..a5df22907 100644 --- a/src/miniscript/astelem.rs +++ b/src/miniscript/astelem.rs @@ -607,7 +607,7 @@ impl Terminal { Terminal::RawPkH(ref hash) => builder .push_opcode(opcodes::all::OP_DUP) .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&hash.to_byte_array()) + .push_slice(hash.to_byte_array()) .push_opcode(opcodes::all::OP_EQUALVERIFY), Terminal::After(t) => builder .push_int(absolute::LockTime::from(t).to_consensus_u32() as i64) diff --git a/src/miniscript/context.rs b/src/miniscript/context.rs index 3d820de96..f3563b83c 100644 --- a/src/miniscript/context.rs +++ b/src/miniscript/context.rs @@ -430,9 +430,7 @@ impl ScriptContext for Legacy { } Ok(()) } - Terminal::MultiA(..) => { - return Err(ScriptContextError::MultiANotAllowed); - } + Terminal::MultiA(..) => Err(ScriptContextError::MultiANotAllowed), _ => Ok(()), } } diff --git a/src/miniscript/decode.rs b/src/miniscript/decode.rs index 252b24f1d..f0fa96529 100644 --- a/src/miniscript/decode.rs +++ b/src/miniscript/decode.rs @@ -18,11 +18,10 @@ use sync::Arc; use crate::miniscript::lex::{Token as Tk, TokenIter}; use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG; use crate::miniscript::ScriptContext; -use crate::{prelude::*, Miniscript}; +use crate::prelude::*; #[cfg(doc)] use crate::Descriptor; -use crate::{bitcoin, hash256, AbsLockTime, Error, MiniscriptKey, ToPublicKey}; - +use crate::{bitcoin, hash256, AbsLockTime, Error, Miniscript, MiniscriptKey, ToPublicKey}; /// Trait for parsing keys from byte slices pub trait ParseableKey: Sized + ToPublicKey + private::Sealed { diff --git a/src/miniscript/iter.rs b/src/miniscript/iter.rs index f64b350ec..69175c941 100644 --- a/src/miniscript/iter.rs +++ b/src/miniscript/iter.rs @@ -18,14 +18,14 @@ impl Miniscript { /// Creates a new [Iter] iterator that will iterate over all [Miniscript] items within /// AST by traversing its branches. For the specific algorithm please see /// [Iter::next] function. - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_, Pk, Ctx> { Iter::new(self) } /// Creates a new [PkIter] iterator that will iterate over all plain public keys (and not /// key hash values) present in [Miniscript] items within AST by traversing all its branches. /// For the specific algorithm please see [PkIter::next] function. - pub fn iter_pk(&self) -> PkIter { + pub fn iter_pk(&self) -> PkIter<'_, Pk, Ctx> { PkIter::new(self) } diff --git a/src/miniscript/lex.rs b/src/miniscript/lex.rs index bb06811f9..70b01dbf3 100644 --- a/src/miniscript/lex.rs +++ b/src/miniscript/lex.rs @@ -78,7 +78,7 @@ impl<'s> TokenIter<'s> { } /// Look at the top at Iterator - pub fn peek(&self) -> Option<&'s Token> { + pub fn peek(&self) -> Option<&'s Token<'_>> { self.0.last() } diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index a5959081d..ea7d4187b 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -66,7 +66,6 @@ mod private { phantom: PhantomData, } impl Miniscript { - /// Add type information(Type and Extdata) to Miniscript based on /// `AstElem` fragment. Dependent on display and clone because of Error /// Display code of type_check. @@ -98,7 +97,12 @@ mod private { ty: types::Type, ext: types::extra_props::ExtData, ) -> Miniscript { - Miniscript { node, ty, ext, phantom: PhantomData } + Miniscript { + node, + ty, + ext, + phantom: PhantomData, + } } } } @@ -110,7 +114,7 @@ pub use private::Miniscript; /// by the ast. impl PartialOrd for Miniscript { fn partial_cmp(&self, other: &Miniscript) -> Option { - Some(self.node.cmp(&other.node)) + Some(self.cmp(other)) } } @@ -156,7 +160,6 @@ impl fmt::Display for Miniscript } impl Miniscript { - /// Extracts the `AstElem` representing the root of the miniscript pub fn into_inner(self) -> Terminal { self.node @@ -495,12 +498,11 @@ mod tests { use sync::Arc; use super::{Miniscript, ScriptContext, Segwitv0, Tap}; - use crate::miniscript::types; - use crate::miniscript::Terminal; + use crate::miniscript::{types, Terminal}; use crate::policy::Liftable; - use crate::{prelude::*, Error}; + use crate::prelude::*; use crate::test_utils::{StrKeyTranslator, StrXOnlyKeyTranslator}; - use crate::{hex_script, ExtParams, Satisfier, ToPublicKey, TranslatePk}; + use crate::{hex_script, Error, ExtParams, Satisfier, ToPublicKey, TranslatePk}; type Segwitv0Script = Miniscript; type Tapscript = Miniscript; diff --git a/src/miniscript/ms_tests.rs b/src/miniscript/ms_tests.rs index c357a6a64..19cd19026 100644 --- a/src/miniscript/ms_tests.rs +++ b/src/miniscript/ms_tests.rs @@ -68,7 +68,7 @@ mod tests { } #[test] - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] + #[rustfmt::skip] fn invalid_tests_from_alloy() { invalid_ms("or_b(or_i(0,sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc)),after(1))"); invalid_ms("or_b(s:pk_h(A),after(500000001))"); @@ -5646,7 +5646,7 @@ mod tests { invalid_ms("c:or_b(sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc),pk_k(A))"); } #[test] - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] + #[rustfmt::skip] fn mall_8f1e8_tests_from_alloy() { ms_test("or_d(or_d(sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc),sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc)),after(500000001))", "Bf"); ms_test("andor(sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc),or_d(multi(2,A,B,C),sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc)),after(1))", "B"); @@ -9143,7 +9143,7 @@ mod tests { } #[test] - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] + #[rustfmt::skip] fn main_tests_from_alloy() { ms_test("or_d(or_d(multi(2,A,B,C),or_d(multi(2,D,E,F),multi(2,G,I,J))),multi(2,K,L,M))", "Bdusem"); ms_test("andor(multi(2,A,B,C),or_d(multi(2,D,E,F),sha256(926a54995ca48600920a19bf7bc502ca5f2f7d07e6f804c4f00ebf0325084dbc)),c:pk_h(G))", "Bdusem"); @@ -15044,7 +15044,7 @@ mod tests { } #[test] - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] + #[rustfmt::skip] fn malleable_tests_from_alloy() { ms_test("and_v(v:after(500000001),or_d(j:multi(2,A,B,C),multi(2,D,E,F)))", "usB"); ms_test("or_b(j:multi(2,A,B,C),a:andor(multi(2,D,E,F),multi(2,G,I,J),multi(2,K,L,M)))", "dBesu"); @@ -22076,8 +22076,8 @@ mod tests { // This does not actually test timelock mixing. See: https://github.com/rust-bitcoin/rust-miniscript/issues/514 // for details #[test] + #[rustfmt::skip] fn conflict_tests_from_alloy() { - #[cfg_attr(feature="cargo-fmt", rustfmt_skip)] { ms_test("andor(multi(2,A,B,C),andor(multi(2,D,E,F),after(500000001),n:after(1)),0)","Bedsm"); ms_test("and_v(v:after(500000001),or_d(multi(2,A,B,C),and_b(multi(2,D,E,F),a:after(1))))","Busm"); diff --git a/src/miniscript/satisfy.rs b/src/miniscript/satisfy.rs index 037bdccb1..ff9b04860 100644 --- a/src/miniscript/satisfy.rs +++ b/src/miniscript/satisfy.rs @@ -221,7 +221,7 @@ where } } -impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &'a S { +impl> Satisfier for &'_ S { fn lookup_ecdsa_sig(&self, p: &Pk) -> Option { (**self).lookup_ecdsa_sig(p) } @@ -291,7 +291,7 @@ impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &' } } -impl<'a, Pk: MiniscriptKey + ToPublicKey, S: Satisfier> Satisfier for &'a mut S { +impl> Satisfier for &'_ mut S { fn lookup_ecdsa_sig(&self, p: &Pk) -> Option { (**self).lookup_ecdsa_sig(p) } diff --git a/src/miniscript/types/extra_props.rs b/src/miniscript/types/extra_props.rs index ecd57bbd4..f46a4a591 100644 --- a/src/miniscript/types/extra_props.rs +++ b/src/miniscript/types/extra_props.rs @@ -168,7 +168,7 @@ impl Property for ExtData { timelock_info: TimelockInfo::default(), exec_stack_elem_count_sat: Some(1), exec_stack_elem_count_dissat: None, - tree_height : 0, + tree_height: 0, } } @@ -184,7 +184,7 @@ impl Property for ExtData { timelock_info: TimelockInfo::default(), exec_stack_elem_count_sat: None, exec_stack_elem_count_dissat: Some(1), - tree_height : 0, + tree_height: 0, } } @@ -408,7 +408,7 @@ impl Property for ExtData { timelock_info: self.timelock_info, exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: self.exec_stack_elem_count_dissat, - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -424,7 +424,7 @@ impl Property for ExtData { timelock_info: self.timelock_info, exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: self.exec_stack_elem_count_dissat, - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -440,7 +440,7 @@ impl Property for ExtData { timelock_info: self.timelock_info, exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: self.exec_stack_elem_count_dissat, - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -459,7 +459,7 @@ impl Property for ExtData { // Even all V types push something onto the stack and then remove them exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: Some(1), - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -476,7 +476,7 @@ impl Property for ExtData { timelock_info: self.timelock_info, exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: None, - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -492,7 +492,7 @@ impl Property for ExtData { timelock_info: self.timelock_info, exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: Some(1), - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -509,7 +509,7 @@ impl Property for ExtData { // Technically max(1, self.exec_stack_elem_count_sat), same rationale as cast_dupif exec_stack_elem_count_sat: self.exec_stack_elem_count_sat, exec_stack_elem_count_dissat: self.exec_stack_elem_count_dissat, - tree_height : self.tree_height + 1, + tree_height: self.tree_height + 1, }) } @@ -550,7 +550,7 @@ impl Property for ExtData { l.exec_stack_elem_count_dissat, r.exec_stack_elem_count_dissat.map(|x| x + 1), ), - tree_height : cmp::max(l.tree_height, r.tree_height) + 1, + tree_height: cmp::max(l.tree_height, r.tree_height) + 1, }) } @@ -578,7 +578,7 @@ impl Property for ExtData { r.exec_stack_elem_count_sat, ), exec_stack_elem_count_dissat: None, - tree_height : cmp::max(l.tree_height, r.tree_height) + 1, + tree_height: cmp::max(l.tree_height, r.tree_height) + 1, }) } @@ -627,7 +627,7 @@ impl Property for ExtData { l.exec_stack_elem_count_dissat, r.exec_stack_elem_count_dissat.map(|x| x + 1), ), - tree_height : cmp::max(l.tree_height, r.tree_height) + 1, + tree_height: cmp::max(l.tree_height, r.tree_height) + 1, }) } @@ -665,7 +665,7 @@ impl Property for ExtData { l.exec_stack_elem_count_dissat, r.exec_stack_elem_count_dissat.map(|x| x + 1), ), - tree_height : cmp::max(l.tree_height, r.tree_height) + 1, + tree_height: cmp::max(l.tree_height, r.tree_height) + 1, }; Ok(res) } @@ -697,7 +697,7 @@ impl Property for ExtData { opt_max(r.exec_stack_elem_count_sat, l.exec_stack_elem_count_dissat), ), exec_stack_elem_count_dissat: None, - tree_height : cmp::max(l.tree_height, r.tree_height) + 1, + tree_height: cmp::max(l.tree_height, r.tree_height) + 1, }) } @@ -744,7 +744,7 @@ impl Property for ExtData { l.exec_stack_elem_count_dissat, r.exec_stack_elem_count_dissat, ), - tree_height : cmp::max(l.tree_height, r.tree_height) + 1, + tree_height: cmp::max(l.tree_height, r.tree_height) + 1, }) } @@ -790,7 +790,7 @@ impl Property for ExtData { a.exec_stack_elem_count_dissat, c.exec_stack_elem_count_dissat, ), - tree_height : cmp::max(a.tree_height, cmp::max(b.tree_height, c.tree_height)) + 1, + tree_height: cmp::max(a.tree_height, cmp::max(b.tree_height, c.tree_height)) + 1, }) } @@ -853,11 +853,11 @@ impl Property for ExtData { .iter() .rev() .enumerate() - .fold(Some(0), |acc, (i, &(x, y))| { + .try_fold(0, |acc, (i, &(x, y))| { if i <= k { - opt_add(acc, x) + x.map(|x| acc + x) } else { - opt_add(acc, y) + y.map(|y| acc + y) } }); @@ -866,11 +866,11 @@ impl Property for ExtData { .iter() .rev() .enumerate() - .fold(Some(0), |acc, (i, &(x, y))| { + .try_fold(0, |acc, (i, &(x, y))| { if i <= k { - opt_max(acc, x) + x.map(|x| cmp::max(acc, x)) } else { - opt_max(acc, y) + y.map(|y| cmp::max(acc, y)) } }); @@ -880,26 +880,25 @@ impl Property for ExtData { max_sat_size_vec .iter() .enumerate() - .fold(Some((0, 0)), |acc, (i, &(x, y))| { + .try_fold((0, 0), |acc, (i, &(x, y))| { if i <= k { - opt_tuple_add(acc, x) + x.map(|x| (acc.0 + x.0, acc.1 + x.1)) } else { - opt_tuple_add(acc, y) + y.map(|y| (acc.0 + y.0, acc.1 + y.1)) } }); ops_count_sat_vec.sort_by(sat_minus_dissat); - let op_count_sat = - ops_count_sat_vec - .iter() - .enumerate() - .fold(Some(0), |acc, (i, &(x, y))| { - if i <= k { - opt_add(acc, x) - } else { - opt_add(acc, Some(y)) - } - }); + let op_count_sat = ops_count_sat_vec + .iter() + .enumerate() + .try_fold(0, |acc, (i, &(x, y))| { + if i <= k { + x.map(|x| acc + x) + } else { + Some(acc + y) + } + }); Ok(ExtData { pk_cost: pk_cost + n - 1, //all pk cost + (n-1)*ADD @@ -916,7 +915,7 @@ impl Property for ExtData { timelock_info: TimelockInfo::combine_threshold(k, timelocks), exec_stack_elem_count_sat, exec_stack_elem_count_dissat, - tree_height : max_child_height + 1, + tree_height: max_child_height + 1, }) } @@ -1111,11 +1110,6 @@ fn opt_add(a: Option, b: Option) -> Option { a.and_then(|x| b.map(|y| x + y)) } -/// Returns Some((x0+y0, x1+y1)) is both x and y are Some. Otherwise, returns `None`. -fn opt_tuple_add(a: Option<(usize, usize)>, b: Option<(usize, usize)>) -> Option<(usize, usize)> { - a.and_then(|x| b.map(|(w, s)| (w + x.0, s + x.1))) -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/policy/compiler.rs b/src/policy/compiler.rs index 9b29ee6ba..c25956151 100644 --- a/src/policy/compiler.rs +++ b/src/policy/compiler.rs @@ -25,10 +25,15 @@ type PolicyCache = BTreeMap<(Concrete, OrdF64, Option), BTreeMap>>; ///Ordered f64 for comparison -#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub(crate) struct OrdF64(pub f64); impl Eq for OrdF64 {} +impl PartialOrd for OrdF64 { + fn partial_cmp(&self, other: &OrdF64) -> Option { + Some(self.cmp(other)) + } +} impl Ord for OrdF64 { fn cmp(&self, other: &OrdF64) -> cmp::Ordering { // will panic if given NaN @@ -663,19 +668,16 @@ fn insert_elem( // Check whether the new element is worse than any existing element. If there // is an element which is a subtype of the current element and has better // cost, don't consider this element. - let is_worse = map - .iter() - .map(|(existing_key, existing_elem)| { - let existing_elem_cost = existing_elem.cost_1d(sat_prob, dissat_prob); - existing_key.is_subtype(elem_key) && existing_elem_cost <= elem_cost - }) - .any(|x| x); + let is_worse = map.iter().any(|(existing_key, existing_elem)| { + let existing_elem_cost = existing_elem.cost_1d(sat_prob, dissat_prob); + existing_key.is_subtype(elem_key) && existing_elem_cost <= elem_cost + }); if !is_worse { // If the element is not worse any element in the map, remove elements // whose subtype is the current element and have worse cost. *map = mem::take(map) .into_iter() - .filter(|&(ref existing_key, ref existing_elem)| { + .filter(|(existing_key, existing_elem)| { let existing_elem_cost = existing_elem.cost_1d(sat_prob, dissat_prob); !(elem_key.is_subtype(*existing_key) && existing_elem_cost >= elem_cost) }) @@ -864,7 +866,7 @@ where let rw = subs[1].0 as f64 / total; //and-or - if let (&Concrete::And(ref x), _) = (&subs[0].1, &subs[1].1) { + if let (Concrete::And(x), _) = (&subs[0].1, &subs[1].1) { let mut a1 = best_compilations( policy_cache, &x[0], @@ -887,7 +889,7 @@ where compile_tern!(&mut a1, &mut b2, &mut c, [lw, rw]); compile_tern!(&mut b1, &mut a2, &mut c, [lw, rw]); }; - if let (_, &Concrete::And(ref x)) = (&subs[0].1, &subs[1].1) { + if let (_, Concrete::And(x)) = (&subs[0].1, &subs[1].1) { let mut a1 = best_compilations( policy_cache, &x[0], @@ -959,11 +961,11 @@ where let mut best_es = Vec::with_capacity(n); let mut best_ws = Vec::with_capacity(n); - let mut min_value = (0, f64::INFINITY as f64); + let mut min_value = (0, f64::INFINITY); for (i, ast) in subs.iter().enumerate() { let sp = sat_prob * k_over_n; //Expressions must be dissatisfiable - let dp = Some(dissat_prob.unwrap_or(0 as f64) + (1.0 - k_over_n) * sat_prob); + let dp = Some(dissat_prob.unwrap_or(0.0) + (1.0 - k_over_n) * sat_prob); let be = best(types::Base::B, policy_cache, ast, sp, dp)?; let bw = best(types::Base::W, policy_cache, ast, sp, dp)?; @@ -1162,7 +1164,7 @@ where { best_compilations(policy_cache, policy, sat_prob, dissat_prob)? .into_iter() - .filter(|&(ref key, ref val)| { + .filter(|(key, val)| { key.ty.corr.base == basic_type && key.ty.corr.unit && val.ms.ty.mall.dissat == types::Dissat::Unique @@ -1231,7 +1233,7 @@ mod tests { // artificially create a policy that is problematic and try to compile let pol: SPolicy = Concrete::And(vec![ Concrete::Key("A".to_string()), - Concrete::And(vec![Concrete::after(9), Concrete::after(1000_000_000)]), + Concrete::And(vec![Concrete::after(9), Concrete::after(1_000_000_000)]), ]); assert!(pol.compile::().is_err()); @@ -1303,7 +1305,7 @@ mod tests { let (keys, sig) = pubkeys_and_a_sig(10); let key_pol: Vec = keys.iter().map(|k| Concrete::Key(*k)).collect(); - let policy: BPolicy = Concrete::Key(keys[0].clone()); + let policy: BPolicy = Concrete::Key(keys[0]); let ms: SegwitMiniScript = policy.compile().unwrap(); assert_eq!( ms.encode(), @@ -1390,11 +1392,11 @@ mod tests { HashMap::::new( ); - for i in 0..5 { - left_sat.insert(keys[i], bitcoinsig); + for key in &keys[0..5] { + left_sat.insert(*key, bitcoinsig); } - for i in 5..8 { - right_sat.insert(keys[i].to_pubkeyhash(SigType::Ecdsa), (keys[i], bitcoinsig)); + for key in &keys[5..8] { + right_sat.insert(key.to_pubkeyhash(SigType::Ecdsa), (*key, bitcoinsig)); } assert!(ms.satisfy(no_sat).is_err()); @@ -1503,7 +1505,7 @@ mod tests { (1, Concrete::Threshold(keys_b.len(), keys_b)), ]) .compile(); - let script_size = thresh_res.clone().and_then(|m| Ok(m.script_size())); + let script_size = thresh_res.clone().map(|m| m.script_size()); assert_eq!( thresh_res, Err(CompilerError::LimitsExceeded), @@ -1519,7 +1521,7 @@ mod tests { Concrete::Threshold(keys.len(), keys).compile(); let n_elements = thresh_res .clone() - .and_then(|m| Ok(m.max_satisfaction_witness_elements())); + .map(|m| m.max_satisfaction_witness_elements()); assert_eq!( thresh_res, Err(CompilerError::LimitsExceeded), @@ -1536,7 +1538,7 @@ mod tests { keys.iter().map(|pubkey| Concrete::Key(*pubkey)).collect(); let thresh_res: Result = Concrete::Threshold(keys.len() - 1, keys).compile(); - let ops_count = thresh_res.clone().and_then(|m| Ok(m.ext.ops.op_count())); + let ops_count = thresh_res.clone().map(|m| m.ext.ops.op_count()); assert_eq!( thresh_res, Err(CompilerError::LimitsExceeded), @@ -1548,7 +1550,7 @@ mod tests { let keys: Vec> = keys.iter().map(|pubkey| Concrete::Key(*pubkey)).collect(); let thresh_res = Concrete::Threshold(keys.len() - 1, keys).compile::(); - let ops_count = thresh_res.clone().and_then(|m| Ok(m.ext.ops.op_count())); + let ops_count = thresh_res.clone().map(|m| m.ext.ops.op_count()); assert_eq!( thresh_res, Err(CompilerError::LimitsExceeded), diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index 8a080200e..4b0e975a9 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -306,17 +306,15 @@ impl Policy { Policy::Or(ref subs) => { let total_odds: usize = subs.iter().map(|(ref k, _)| k).sum(); subs.iter() - .map(|(k, ref policy)| { + .flat_map(|(k, ref policy)| { policy.to_tapleaf_prob_vec(prob * *k as f64 / total_odds as f64) }) - .flatten() .collect::>() } Policy::Threshold(k, ref subs) if *k == 1 => { let total_odds = subs.len(); subs.iter() - .map(|policy| policy.to_tapleaf_prob_vec(prob / total_odds as f64)) - .flatten() + .flat_map(|policy| policy.to_tapleaf_prob_vec(prob / total_odds as f64)) .collect::>() } x => vec![(prob, x.clone())], @@ -360,7 +358,7 @@ impl Policy { } } match (internal_key, unspendable_key) { - (Some(ref key), _) => Ok((key.clone(), self.translate_unsatisfiable_pk(&key))), + (Some(ref key), _) => Ok((key.clone(), self.translate_unsatisfiable_pk(key))), (_, Some(key)) => Ok((key, self)), _ => Err(errstr("No viable internal key found.")), } @@ -1103,11 +1101,7 @@ impl_from_str!( Policy, type Err = Error;, fn from_str(s: &str) -> Result, Error> { - for ch in s.as_bytes() { - if *ch < 20 || *ch > 127 { - return Err(Error::Unprintable(*ch)); - } - } + expression::check_valid_chars(s)?; let tree = expression::Tree::from_str(s)?; let policy: Policy = FromTree::from_tree(&tree)?; @@ -1272,7 +1266,7 @@ fn with_huffman_tree( /// any one of the conditions exclusively. #[cfg(feature = "compiler")] fn generate_combination( - policy_vec: &Vec>>, + policy_vec: &[Arc>], prob: f64, k: usize, ) -> Vec<(f64, Arc>)> { diff --git a/src/policy/mod.rs b/src/policy/mod.rs index 83348333d..409bed80e 100644 --- a/src/policy/mod.rs +++ b/src/policy/mod.rs @@ -442,7 +442,7 @@ mod tests { .iter() .zip(node_probabilities.iter()) .collect::>(); - sorted_policy_prob.sort_by(|a, b| (a.1).partial_cmp(&b.1).unwrap()); + sorted_policy_prob.sort_by(|a, b| (a.1).partial_cmp(b.1).unwrap()); let sorted_policies = sorted_policy_prob .into_iter() .map(|(x, _prob)| x) diff --git a/src/policy/semantic.rs b/src/policy/semantic.rs index b188492bb..3888fe765 100644 --- a/src/policy/semantic.rs +++ b/src/policy/semantic.rs @@ -160,7 +160,6 @@ impl Policy { /// A |- B means every satisfaction of A is also a satisfaction of B. /// This implementation will run slow for larger policies but should be sufficient for /// most practical policies. - // This algorithm has a naive implementation. It is possible to optimize this // by memoizing and maintaining a hashmap. pub fn entails(self, other: Policy) -> Result { @@ -311,11 +310,7 @@ impl_from_str!( Policy, type Err = Error;, fn from_str(s: &str) -> Result, Error> { - for ch in s.as_bytes() { - if *ch < 20 || *ch > 127 { - return Err(Error::Unprintable(*ch)); - } - } + expression::check_valid_chars(s)?; let tree = expression::Tree::from_str(s)?; expression::FromTree::from_tree(&tree) diff --git a/src/psbt/finalizer.rs b/src/psbt/finalizer.rs index c0bf447c9..b7110964b 100644 --- a/src/psbt/finalizer.rs +++ b/src/psbt/finalizer.rs @@ -146,7 +146,7 @@ fn get_descriptor(psbt: &Psbt, index: usize) -> Result, In *script_pubkey == addr.script_pubkey() }); match partial_sig_contains_pk { - Some((pk, _sig)) => Descriptor::new_pkh(*pk).map_err(|e| InputError::from(e)), + Some((pk, _sig)) => Descriptor::new_pkh(*pk).map_err(InputError::from), None => Err(InputError::MissingPubkey), } } else if script_pubkey.is_v0_p2wpkh() { @@ -297,7 +297,7 @@ fn interpreter_inp_check>( let cltv = psbt.unsigned_tx.lock_time; let csv = psbt.unsigned_tx.input[index].sequence; let interpreter = - interpreter::Interpreter::from_txdata(&spk, &script_sig, witness, csv, cltv.into()) + interpreter::Interpreter::from_txdata(&spk, script_sig, witness, csv, cltv) .map_err(|e| Error::InputError(InputError::Interpreter(e), index))?; let iter = interpreter.iter(secp, &psbt.unsigned_tx, index, utxos); if let Some(error) = iter.filter_map(Result::err).next() { diff --git a/src/psbt/mod.rs b/src/psbt/mod.rs index 6adf49b63..b972d8566 100644 --- a/src/psbt/mod.rs +++ b/src/psbt/mod.rs @@ -341,8 +341,7 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie return false; } - let lock_time = absolute::LockTime::from(self.psbt.unsigned_tx.lock_time); - + let lock_time = self.psbt.unsigned_tx.lock_time; >::check_after(&lock_time, n) } @@ -393,6 +392,7 @@ impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier for PsbtInputSatisfie } } +#[allow(clippy::ptr_arg)] // this signature is forced by use in `and_then` fn try_vec_as_preimage32(vec: &Vec) -> Option { if vec.len() == 32 { let mut arr = [0u8; 32]; @@ -592,7 +592,7 @@ pub trait PsbtExt { /// /// Based on the sighash /// flag specified in the [`Psbt`] sighash field. If the input sighash flag psbt field is `None` - /// the [`sighash::TapSighashType::Default`](bitcoin::sighash::TapSighashType::Default) is chosen + /// the [`sighash::TapSighashType::Default`] is chosen /// for for taproot spends, otherwise [`EcdsaSighashType::All`](bitcoin::sighash::EcdsaSighashType::All) is chosen. /// If the utxo at `idx` is a taproot output, returns a [`PsbtSighashMsg::TapSighash`] variant. /// If the utxo at `idx` is a pre-taproot segwit output, returns a [`PsbtSighashMsg::SegwitV0Sighash`] variant. @@ -1051,8 +1051,6 @@ trait PsbtFields { fn tap_key_origins( &mut self, ) -> &mut BTreeMap, bip32::KeySource)>; - fn proprietary(&mut self) -> &mut BTreeMap>; - fn unknown(&mut self) -> &mut BTreeMap>; // `tap_tree` only appears in psbt::Output, so it's returned as an option of a mutable ref fn tap_tree(&mut self) -> Option<&mut Option> { @@ -1086,14 +1084,6 @@ impl PsbtFields for psbt::Input { ) -> &mut BTreeMap, bip32::KeySource)> { &mut self.tap_key_origins } - #[allow(dead_code)] - fn proprietary(&mut self) -> &mut BTreeMap> { - &mut self.proprietary - } - #[allow(dead_code)] - fn unknown(&mut self) -> &mut BTreeMap> { - &mut self.unknown - } fn tap_scripts(&mut self) -> Option<&mut BTreeMap> { Some(&mut self.tap_scripts) @@ -1121,14 +1111,6 @@ impl PsbtFields for psbt::Output { ) -> &mut BTreeMap, bip32::KeySource)> { &mut self.tap_key_origins } - #[allow(dead_code)] - fn proprietary(&mut self) -> &mut BTreeMap> { - &mut self.proprietary - } - #[allow(dead_code)] - fn unknown(&mut self) -> &mut BTreeMap> { - &mut self.unknown - } fn tap_tree(&mut self) -> Option<&mut Option> { Some(&mut self.tap_tree) @@ -1671,7 +1653,7 @@ mod tests { #[test] fn test_update_input_checks() { let desc = "tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)"; - let desc = Descriptor::::from_str(&desc).unwrap(); + let desc = Descriptor::::from_str(desc).unwrap(); let mut non_witness_utxo = bitcoin::Transaction { version: 1, @@ -1736,7 +1718,7 @@ mod tests { #[test] fn test_update_output_checks() { let desc = "tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)"; - let desc = Descriptor::::from_str(&desc).unwrap(); + let desc = Descriptor::::from_str(desc).unwrap(); let tx = bitcoin::Transaction { version: 1, diff --git a/src/test_utils.rs b/src/test_utils.rs index dea8aae58..45f344396 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -168,7 +168,7 @@ impl StrXOnlyKeyTranslator { .collect(); let mut pk_map = HashMap::new(); let mut pkh_map = HashMap::new(); - for (i, c) in (b'A'..b'Z').enumerate() { + for (i, c) in (b'A'..=b'Z').enumerate() { let key = String::from_utf8(vec![c]).unwrap(); pk_map.insert(key.clone(), pks[i]); pkh_map.insert(key, pks[i].to_pubkeyhash(SigType::Schnorr)); diff --git a/src/util.rs b/src/util.rs index baf49066e..0564108a3 100644 --- a/src/util.rs +++ b/src/util.rs @@ -26,7 +26,7 @@ pub(crate) fn witness_to_scriptsig(witness: &[Vec]) -> ScriptBuf { } else { let push = <&PushBytes>::try_from(wit.as_slice()) .expect("All pushes in miniscript are <73 bytes"); - b = b.push_slice(&push) + b = b.push_slice(push) } } b.into_script() @@ -55,7 +55,7 @@ impl MsKeyBuilder for script::Builder { { match Ctx::sig_type() { context::SigType::Ecdsa => self.push_key(&key.to_public_key()), - context::SigType::Schnorr => self.push_slice(&key.to_x_only_pubkey().serialize()), + context::SigType::Schnorr => self.push_slice(key.to_x_only_pubkey().serialize()), } } @@ -65,9 +65,9 @@ impl MsKeyBuilder for script::Builder { Ctx: ScriptContext, { match Ctx::sig_type() { - context::SigType::Ecdsa => self.push_slice(&key.to_public_key().pubkey_hash()), + context::SigType::Ecdsa => self.push_slice(key.to_public_key().pubkey_hash()), context::SigType::Schnorr => { - self.push_slice(&PubkeyHash::hash(&key.to_x_only_pubkey().serialize())) + self.push_slice(PubkeyHash::hash(&key.to_x_only_pubkey().serialize())) } } }