From 790aee9b3b963e005e6efccabab0de6487de8e44 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Tue, 17 Oct 2023 12:33:35 -0400 Subject: [PATCH 1/2] feat: upgrade bdk to 1.0.0-alpha.2 This is a big change that updates some of our build infrastructure as well as upgrading the bdk dependency. It adds the simple new_no_persist constructor on the wallet as well as the blocking esplora client. --- .github/workflows/audit.yml | 14 +- .github/workflows/cont_integration.yml | 51 +- .github/workflows/publish-python.yaml | 1 + .github/workflows/test-swift.yaml | 39 +- Cargo.toml | 12 - .../org/bitcoindevkit/AndroidLibTest.kt | 78 +- .../plugins/UniFfiAndroidPlugin.kt | 12 +- Cargo.lock => bdk-ffi/Cargo.lock | 652 ++----- bdk-ffi/Cargo.toml | 28 +- bdk-ffi/src/bdk.udl | 408 +--- bdk-ffi/src/blockchain.rs | 201 -- bdk-ffi/src/database.rs | 14 - bdk-ffi/src/descriptor.rs | 124 +- bdk-ffi/src/esplora.rs | 18 + bdk-ffi/src/keys.rs | 102 +- bdk-ffi/src/lib.rs | 862 ++++---- bdk-ffi/src/psbt.rs | 238 +-- bdk-ffi/src/wallet.rs | 1736 +++++++++-------- .../kotlin/org/bitcoindevkit/JvmLibTest.kt | 82 +- .../bitcoindevkit/plugins/UniFfiJvmPlugin.kt | 21 +- bdk-python/scripts/generate-linux.sh | 2 +- bdk-python/scripts/generate-macos-arm64.sh | 2 +- bdk-python/scripts/generate-macos-x86_64.sh | 3 +- bdk-python/scripts/generate-windows.sh | 2 +- bdk-python/tests/test_bdk.py | 44 +- .../BitcoinDevKitTests.swift | 26 +- bdk-swift/build-local-swift.sh | 10 +- 27 files changed, 2021 insertions(+), 2761 deletions(-) delete mode 100644 Cargo.toml rename Cargo.lock => bdk-ffi/Cargo.lock (66%) delete mode 100644 bdk-ffi/src/blockchain.rs delete mode 100644 bdk-ffi/src/database.rs create mode 100644 bdk-ffi/src/esplora.rs diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 1c0fb429..648c55e2 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -12,8 +12,14 @@ jobs: security_audit: name: Security audit runs-on: ubuntu-20.04 + defaults: + run: + working-directory: bdk-ffi steps: - - uses: actions/checkout@v3 - - uses: actions-rs/audit-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} + - name: "Check out PR branch" + uses: actions/checkout@v3 + + - name: "Run audit" + run: | + cargo install cargo-audit + cargo-audit audit diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index 7ddebf02..7449238f 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -9,22 +9,26 @@ on: jobs: build-test: - name: Build and test + name: "Build and test" runs-on: ubuntu-20.04 + defaults: + run: + working-directory: bdk-ffi strategy: matrix: rust: - - version: 1.71.0 # STABLE + - version: 1.67.0 clippy: true - - version: 1.61.0 # MSRV + # TODO 1: Should we keep this? We'll need to pin dependencies + # - version: 1.61.0 # MSRV steps: - - name: Checkout + - name: "Checkout" uses: actions/checkout@v3 - - name: Generate cache key + - name: "Generate cache key" run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key - - name: Cache + - name: "Cache" uses: actions/cache@v3 with: path: | @@ -33,53 +37,56 @@ jobs: target key: ${{ runner.os }}-cargo-${{ hashFiles('.cache_key') }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} - - name: Set default toolchain + - name: "Set default toolchain" run: rustup default ${{ matrix.rust.version }} - - name: Set profile + - name: "Set profile" run: rustup set profile minimal - - name: Add clippy + - name: "Add clippy" if: ${{ matrix.rust.clippy }} run: rustup component add clippy - - name: Update toolchain + - name: "Update toolchain" run: rustup update - - name: Pin dependencies for MSRV + - name: "Pin dependencies for MSRV" if: matrix.rust.version == '1.61.0' run: | cargo update -p hashlink --precise "0.8.1" cargo update -p tokio --precise "1.29.1" cargo update -p flate2 --precise "1.0.26" - - name: Build + - name: "Build" run: cargo build - - name: Clippy + - name: "Clippy" if: ${{ matrix.rust.clippy }} run: cargo clippy --all-targets --features "uniffi/bindgen-tests" -- -D warnings - - name: Test + - name: "Test" run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test --features uniffi/bindgen-tests fmt: - name: Rust fmt - runs-on: ubuntu-latest + name: "Rust fmt" + runs-on: ubuntu-20.04 + defaults: + run: + working-directory: bdk-ffi steps: - - name: Checkout + - name: "Checkout" uses: actions/checkout@v3 - - name: Set default toolchain + - name: "Set default toolchain" run: rustup default nightly - - name: Set profile + - name: "Set profile" run: rustup set profile minimal - - name: Add rustfmt + - name: "Add rustfmt" run: rustup component add rustfmt - - name: Update toolchain + - name: "Update toolchain" run: rustup update - - name: Check fmt + - name: "Check fmt" run: cargo fmt --all -- --config format_code_in_doc_comments=true --check diff --git a/.github/workflows/publish-python.yaml b/.github/workflows/publish-python.yaml index f0259be8..40e24af7 100644 --- a/.github/workflows/publish-python.yaml +++ b/.github/workflows/publish-python.yaml @@ -29,6 +29,7 @@ jobs: uses: actions/checkout@v3 with: submodules: true + # TODO 2: Other CI workflows use explicit Rust compiler versions, I think we should do the same here - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/.github/workflows/test-swift.yaml b/.github/workflows/test-swift.yaml index e1336a8d..fad668f7 100644 --- a/.github/workflows/test-swift.yaml +++ b/.github/workflows/test-swift.yaml @@ -12,44 +12,15 @@ on: jobs: build: + name: "Build and test" runs-on: macos-12 steps: - - name: Checkout + - name: "Checkout" uses: actions/checkout@v3 - - name: "Set default Rust version to 1.67.0" - run: rustup default 1.67.0 + - name: "Build Swift package" + run: bash ./bdk-swift/build-local-swift.sh - - name: Install Rust targets - run: | - rustup install nightly-x86_64-apple-darwin - rustup component add rust-src --toolchain nightly-x86_64-apple-darwin - rustup target add aarch64-apple-darwin x86_64-apple-darwin - - - name: Run bdk-ffi-bindgen - working-directory: bdk-ffi - run: cargo run --bin uniffi-bindgen generate src/bdk.udl --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit --no-format - - - name: Build bdk-ffi for x86_64-apple-darwin - run: cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-darwin - - - name: Build bdk-ffi for aarch64-apple-darwin - run: cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin - - - name: Create lipo-macos - run: | - mkdir -p target/lipo-macos/release-smaller - lipo target/aarch64-apple-darwin/release-smaller/libbdkffi.a target/x86_64-apple-darwin/release-smaller/libbdkffi.a -create -output target/lipo-macos/release-smaller/libbdkffi.a - - - name: Create bdkFFI.xcframework - working-directory: bdk-swift - run: | - mv Sources/BitcoinDevKit/bdk.swift Sources/BitcoinDevKit/BitcoinDevKit.swift - cp Sources/BitcoinDevKit/bdkFFI.h bdkFFI.xcframework/macos-arm64_x86_64/bdkFFI.framework/Headers - cp ../target/lipo-macos/release-smaller/libbdkffi.a bdkFFI.xcframework/macos-arm64_x86_64/bdkFFI.framework/bdkFFI - rm Sources/BitcoinDevKit/bdkFFI.h - rm Sources/BitcoinDevkit/bdkFFI.modulemap - - - name: Run Swift tests + - name: "Run Swift tests" working-directory: bdk-swift run: swift test diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 2670c018..00000000 --- a/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[workspace] -members = ["bdk-ffi"] -default-members = ["bdk-ffi"] -exclude = ["api-docs", "bdk-android", "bdk-jvm", "bdk-python", "bdk-swift"] - -[profile.release-smaller] -inherits = "release" -opt-level = 'z' # Optimize for size. -lto = true # Enable Link Time Optimization -codegen-units = 1 # Reduce number of codegen units to increase optimizations. -panic = 'abort' # Abort on panic -strip = true # Strip symbols from binary diff --git a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/AndroidLibTest.kt b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/AndroidLibTest.kt index 842131d5..446b4cf2 100644 --- a/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/AndroidLibTest.kt +++ b/bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/AndroidLibTest.kt @@ -18,64 +18,42 @@ import java.io.File */ @RunWith(AndroidJUnit4::class) class AndroidLibTest { - - private fun getTestDataDir(): String { - val context = ApplicationProvider.getApplicationContext() - return context.getDir("bdk-test", MODE_PRIVATE).toString() - } - - private fun cleanupTestDataDir(testDataDir: String) { - File(testDataDir).deleteRecursively() - } - - class LogProgress : Progress { - private val log: Logger = LoggerFactory.getLogger(AndroidLibTest::class.java) - - override fun update(progress: Float, message: String?) { - log.debug("Syncing...") - } + @Test + fun testNetwork() { + val signetNetwork = Network.SIGNET } - private val descriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET) - - private val databaseConfig = DatabaseConfig.Memory - - private val blockchainConfig = BlockchainConfig.Electrum( - ElectrumConfig( - "ssl://electrum.blockstream.info:60002", - null, - 5u, - null, - 100u, - true, - ) - ) - @Test - fun memoryWalletNewAddress() { - val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig) - val address = wallet.getAddress(AddressIndex.New).address.asString() - assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address) + fun testDescriptorBip86() { + val mnemonic = Mnemonic(WordCount.WORDS12) + val descriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null) + val descriptor = Descriptor.newBip86(descriptorSecretKey, KeychainKind.EXTERNAL, Network.TESTNET) } @Test - fun memoryWalletSyncGetBalance() { - val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig) - val blockchain = Blockchain(blockchainConfig) - wallet.sync(blockchain, LogProgress()) - val balance: Balance = wallet.getBalance() - assertTrue(balance.total > 0u) + fun testUsedWallet() { + val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) + val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET) + val (index, address, keychain) = wallet.getAddress(AddressIndex.LastUnused) + println("Address ${address.asString()} at index $index") } @Test - fun sqliteWalletSyncGetBalance() { - val testDataDir = getTestDataDir() + "/bdk-wallet.sqlite" - val databaseConfig = DatabaseConfig.Sqlite(SqliteDbConfiguration(testDataDir)) - val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig) - val blockchain = Blockchain(blockchainConfig) - wallet.sync(blockchain, LogProgress()) - val balance: Balance = wallet.getBalance() - assertTrue(balance.total > 0u) - cleanupTestDataDir(testDataDir) + fun testBalance() { + val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) + val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET) + + assert(wallet.getBalance().total() == 0uL) } + + // @Test + // fun testSyncedBalance() { + // val descriptor = Descriptor("wpkh(tprv8ZgxMBicQKsPf2qfrEygW6fdYseJDDrVnDv26PH5BHdvSuG6ecCbHqLVof9yZcMoM31z9ur3tTYbSnr1WBqbGX97CbXcmp5H6qeMpyvx35B/84h/1h/0h/0/*)", Network.TESTNET) + // val wallet = Wallet.newNoPersist(descriptor, null, Network.TESTNET) + // val esploraClient = EsploraClient("https://mempool.space/testnet/api") + // // val esploraClient = EsploraClient("https://blockstream.info/testnet/api") + // val update = esploraClient.scan(wallet, 10uL, 1uL) + // wallet.applyUpdate(update) + // println("Balance: ${wallet.getBalance().total()}") + // } } diff --git a/bdk-android/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt b/bdk-android/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt index 20200864..186dd939 100644 --- a/bdk-android/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt +++ b/bdk-android/plugins/src/main/kotlin/org/bitcoindevkit/plugins/UniFfiAndroidPlugin.kt @@ -117,15 +117,15 @@ internal class UniFfiAndroidPlugin : Plugin { into("${project.projectDir}/../lib/src/main/jniLibs/") into("arm64-v8a") { - from("${project.projectDir}/../../target/aarch64-linux-android/release-smaller/libbdkffi.so") + from("${project.projectDir}/../../bdk-ffi/target/aarch64-linux-android/release-smaller/libbdkffi.so") } into("x86_64") { - from("${project.projectDir}/../../target/x86_64-linux-android/release-smaller/libbdkffi.so") + from("${project.projectDir}/../../bdk-ffi/target/x86_64-linux-android/release-smaller/libbdkffi.so") } into("armeabi-v7a") { - from("${project.projectDir}/../../target/armv7-linux-androideabi/release-smaller/libbdkffi.so") + from("${project.projectDir}/../../bdk-ffi/target/armv7-linux-androideabi/release-smaller/libbdkffi.so") } doLast { @@ -137,6 +137,12 @@ internal class UniFfiAndroidPlugin : Plugin { val generateAndroidBindings by tasks.register("generateAndroidBindings") { dependsOn(moveNativeAndroidLibs) + // val libraryPath = "${project.projectDir}/../../bdk-ffi/target/aarch64-linux-android/release-smaller/libbdkffi.so" + // workingDir("${project.projectDir}/../../bdk-ffi") + // val cargoArgs: List = listOf("run", "--bin", "uniffi-bindgen", "generate", "--library", libraryPath, "--language", "kotlin", "--out-dir", "../bdk-android/lib/src/main/kotlin", "--no-format") + + // The code above worked for uniffi 0.24.3 using the --library flag + // The code below works for uniffi 0.23.0 workingDir("${project.projectDir}/../../bdk-ffi") val cargoArgs: List = listOf("run", "--bin", "uniffi-bindgen", "generate", "src/bdk.udl", "--language", "kotlin", "--out-dir", "../bdk-android/lib/src/main/kotlin", "--no-format") diff --git a/Cargo.lock b/bdk-ffi/Cargo.lock similarity index 66% rename from Cargo.lock rename to bdk-ffi/Cargo.lock index d42d0cd0..7493e629 100644 --- a/Cargo.lock +++ b/bdk-ffi/Cargo.lock @@ -2,49 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - [[package]] name = "anyhow" version = "1.0.75" @@ -102,17 +65,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.31", -] - [[package]] name = "atty" version = "0.2.14" @@ -130,21 +82,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.13.1" @@ -153,63 +90,57 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" - -[[package]] -name = "base64-compat" -version = "1.0.0" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7" -dependencies = [ - "byteorder", -] +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "bdk" -version = "0.28.2" +version = "1.0.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15adb2017ab6437b6704a779ab8bbefe857612f5af9d84b677a1767f965e099" +checksum = "99559c90df27c7dac369182a47ec96425f71764540765bba6558ea79877e50ee" dependencies = [ - "ahash 0.7.6", - "async-trait", - "bdk-macros", + "bdk_chain", "bip39", "bitcoin", - "bitcoincore-rpc", - "electrum-client", - "esplora-client", "getrandom", "js-sys", "log", "miniscript", "rand", - "rusqlite", "serde", "serde_json", - "sled", - "tokio", ] [[package]] name = "bdk-ffi" -version = "0.30.0" +version = "1.0.0-alpha.2" dependencies = [ "assert_matches", "bdk", + "bdk_esplora", "uniffi", ] [[package]] -name = "bdk-macros" +name = "bdk_chain" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81c1980e50ae23bb6efa9283ae8679d6ea2c6fa6a99fe62533f65f4a25a1a56c" +checksum = "5043c1254d39534da6b2ca67e139aac8e9a4719671ae6b4063ecd2c791179879" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "bitcoin", + "miniscript", + "serde", +] + +[[package]] +name = "bdk_esplora" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "735f8420eecabf7468700b1a12c8dedc36897b33e3851a7ae21397a2ce85c2bd" +dependencies = [ + "bdk_chain", + "esplora-client", ] [[package]] @@ -229,59 +160,57 @@ dependencies = [ [[package]] name = "bip39" -version = "2.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +checksum = "29b9e657de8ff1c3488a4ab77cb51d604eab53415ce34f0bc800f2eac9b13c28" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.11.0", + "rand_core 0.4.2", "serde", "unicode-normalization", ] [[package]] name = "bitcoin" -version = "0.29.2" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +checksum = "4e99ff7289b20a7385f66a0feda78af2fc119d28fb56aea8886a9cd0a4abdd75" dependencies = [ "base64 0.13.1", "bech32", - "bitcoin_hashes", + "bitcoin-private", + "bitcoin_hashes 0.12.0", + "hex_lit", "secp256k1", "serde", ] [[package]] -name = "bitcoin_hashes" -version = "0.11.0" +name = "bitcoin-internals" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" -dependencies = [ - "serde", -] +checksum = "1f9997f8650dd818369931b5672a18dbef95324d0513aa99aae758de8ce86e5b" [[package]] -name = "bitcoincore-rpc" -version = "0.16.0" +name = "bitcoin-private" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0261b2bb7617e0c91b452a837bbd1291fd34ad6990cb8e3ffc28239cc045b5ca" -dependencies = [ - "bitcoincore-rpc-json", - "jsonrpc", - "log", - "serde", - "serde_json", -] +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" [[package]] -name = "bitcoincore-rpc-json" -version = "0.16.0" +name = "bitcoin_hashes" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c231bea28e314879c5aef240f6052e8a72a369e3c9f9b20d9bfbb33ad18029b2" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + +[[package]] +name = "bitcoin_hashes" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" dependencies = [ - "bitcoin", + "bitcoin-private", "serde", - "serde_json", ] [[package]] @@ -292,21 +221,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "camino" @@ -403,75 +332,24 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "electrum-client" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e1e1e452aef3ee772d19cc6272ef642f22ce0f4a9fb715ffe98010934e2ae1" -dependencies = [ - "bitcoin", - "byteorder", - "libc", - "log", - "rustls 0.20.9", - "serde", - "serde_json", - "webpki", - "webpki-roots 0.22.6", - "winapi", -] - [[package]] name = "esplora-client" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "847e59bd6ee1c3f2bdf217118ee3640b97a1b1d8becb55771e67e533b87da66f" +checksum = "0cb1f7f2489cce83bc3bd92784f9ba5271eeb6e729b975895fc541f78cbfcdca" dependencies = [ "bitcoin", + "bitcoin-internals", "log", "serde", "ureq", ] -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -492,25 +370,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "getrandom" version = "0.2.10" @@ -522,12 +381,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - [[package]] name = "glob" version = "0.3.1" @@ -551,25 +404,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" -dependencies = [ - "ahash 0.8.3", - "allocator-api2", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.0", -] - [[package]] name = "heck" version = "0.4.1" @@ -585,12 +419,19 @@ dependencies = [ "libc", ] +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + [[package]] name = "idna" -version = "0.4.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094" dependencies = [ + "matches", "unicode-bidi", "unicode-normalization", ] @@ -602,16 +443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", + "hashbrown", ] [[package]] @@ -629,65 +461,35 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonrpc" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8423b78fc94d12ef1a4a9d13c348c9a78766dda0cc18817adf0faf77e670c8" -dependencies = [ - "base64-compat", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "libc" -version = "0.2.147" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] -name = "libsqlite3-sys" -version = "0.25.2" +name = "log" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] -name = "lock_api" -version = "0.4.10" +name = "matches" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] -name = "log" -version = "0.4.20" +name = "maybe-uninit" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.6.3" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mime" @@ -713,11 +515,12 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniscript" -version = "9.0.2" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b106477a0709e2da253e5559ba4ab20a272f8577f1eefff72f3a905b5d35f5" +checksum = "1eb102b66b2127a872dbcc73095b7b47aeb9d92f7b03c2b2298253ffc82c7594" dependencies = [ "bitcoin", + "bitcoin-private", "serde", ] @@ -740,15 +543,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -761,31 +555,6 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - [[package]] name = "paste" version = "1.0.14" @@ -798,18 +567,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - [[package]] name = "plain" version = "0.2.3" @@ -848,9 +605,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -872,7 +629,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -882,25 +639,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "bitflags", + "getrandom", ] [[package]] @@ -918,38 +672,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rusqlite" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" -dependencies = [ - "bitflags", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.21.7" @@ -958,25 +680,15 @@ checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", - "rustls-webpki 0.101.4", + "rustls-webpki", "sct", ] [[package]] name = "rustls-webpki" -version = "0.100.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.4" +version = "0.101.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" dependencies = [ "ring", "untrusted", @@ -988,12 +700,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "scroll" version = "0.11.0" @@ -1011,7 +717,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.37", ] [[package]] @@ -1026,11 +732,11 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.24.3" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.12.0", "rand", "secp256k1-sys", "serde", @@ -1038,18 +744,18 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.6.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" dependencies = [ "cc", ] [[package]] name = "semver" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" dependencies = [ "serde", ] @@ -1071,14 +777,14 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.37", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -1092,27 +798,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] -name = "sled" -version = "0.34.7" +name = "smallvec" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" dependencies = [ - "crc32fast", - "crossbeam-epoch", - "crossbeam-utils", - "fs2", - "fxhash", - "libc", - "log", - "parking_lot", + "maybe-uninit", ] -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - [[package]] name = "socks" version = "0.3.4" @@ -1155,9 +848,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.31" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -1166,9 +859,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -1181,59 +874,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" -dependencies = [ - "backtrace", - "pin-project-lite", - "tokio-macros", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.31", + "syn 2.0.37", ] [[package]] @@ -1262,17 +918,17 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf" dependencies = [ - "tinyvec", + "smallvec", ] [[package]] @@ -1404,40 +1060,34 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "ureq" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" +checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3" dependencies = [ - "base64 0.21.3", + "base64 0.21.4", "flate2", "log", "once_cell", - "rustls 0.21.7", - "rustls-webpki 0.100.2", + "rustls", + "rustls-webpki", "serde", "serde_json", "socks", "url", - "webpki-roots 0.23.1", + "webpki-roots", ] [[package]] name = "url" -version = "2.4.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" @@ -1471,7 +1121,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.37", "wasm-bindgen-shared", ] @@ -1493,7 +1143,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.37", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1514,33 +1164,11 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.23.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" -dependencies = [ - "rustls-webpki 0.100.2", -] +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "weedle2" @@ -1569,9 +1197,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] diff --git a/bdk-ffi/Cargo.toml b/bdk-ffi/Cargo.toml index 2fceb727..eafaf0cf 100644 --- a/bdk-ffi/Cargo.toml +++ b/bdk-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bdk-ffi" -version = "0.30.0" +version = "1.0.0-alpha.2" authors = ["Steve Myers ", "Sudarsan Balaji "] edition = "2018" license = "MIT OR Apache-2.0" @@ -17,12 +17,30 @@ path = "uniffi-bindgen.rs" default = ["uniffi/cli"] [dependencies] -bdk = { version = "0.28.2", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] } -uniffi = { version = "0.23.0" } +bdk = { version = "1.0.0-alpha.2", features = ["all-keys", "keys-bip39"] } + +# TODO 22: The bdk_esplora crate uses esplora_client which uses reqwest for async. By default it uses the system +# openssl library, which is creating problems for cross-compilation. I'd rather use rustls, but it's hidden +# behind a feature flag. We need to look into whether openssl-sys is really required by bdk or if using rustls +# would work just as well. This here is a temporary workaround which removes the async feature on the bdk_esplora crate. +# See PR #1179 https://github.com/bitcoindevkit/bdk/pull/1179 for the fix in bdk. +# bdk = { git = "https://github.com/thunderbiscuit/bdk.git", branch = "test-rust-tls", version = "1.0.0-alpha.2", features = ["all-keys", "keys-bip39"] } +# bdk_esplora = { git = "https://github.com/thunderbiscuit/bdk.git", branch = "test-rust-tls", version = "0.4.0", package = "bdk_esplora", default-features = false, features = ["std", "blocking", "async-https-rustls"] } + +bdk_esplora = { version = "0.4.0", default-features = false, features = ["std", "blocking"] } +uniffi = { version = "=0.23.0" } [build-dependencies] -uniffi = { version = "0.23.0", features = ["build"] } +uniffi = { version = "=0.23.0", features = ["build"] } [dev-dependencies] -uniffi = { version = "0.23.0", features = ["bindgen-tests"] } +uniffi = { version = "=0.23.0", features = ["bindgen-tests"] } assert_matches = "1.5.0" + +[profile.release-smaller] +inherits = "release" +opt-level = 'z' # Optimize for size. +lto = true # Enable Link Time Optimization +codegen-units = 1 # Reduce number of codegen units to increase optimizations. +panic = "abort" # Abort on panic +strip = "debuginfo" # Partially strip symbols from binary diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 5ca6458a..f5830bb3 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -1,13 +1,21 @@ -namespace bdk { +namespace bdk {}; +// ------------------------------------------------------------------------ +// bdk crate +// ------------------------------------------------------------------------ + +enum KeychainKind { + "External", + "Internal", }; +// ------------------------------------------------------------------------ +// bdk crate - wallet module +// ------------------------------------------------------------------------ + [Error] enum BdkError { - "InvalidU32Bytes", "Generic", - "MissingCachedScripts", - "ScriptDoesntHaveAddressForm", "NoRecipients", "NoUtxosSelected", "OutputBelowDustLimit", @@ -27,25 +35,26 @@ enum BdkError { "SpendingPolicyRequired", "InvalidPolicyPathError", "Signer", - "InvalidNetwork", - "InvalidProgressValue", - "ProgressUpdateError", "InvalidOutpoint", "Descriptor", - "Encode", "Miniscript", "MiniscriptPsbt", "Bip32", - "Secp256k1", - "Json", - "Hex", "Psbt", - "PsbtParse", - "Electrum", - "Esplora", - "Sled", - "Rusqlite", - "Rpc", +}; + +interface Balance { + u64 immature(); + + u64 trusted_pending(); + + u64 untrusted_pending(); + + u64 confirmed(); + + u64 trusted_spendable(); + + u64 total(); }; dictionary AddressInfo { @@ -59,53 +68,33 @@ interface AddressIndex { New(); LastUnused(); Peek(u32 index); - Reset(u32 index); }; -enum Network { - "Bitcoin", - "Testnet", - "Signet", - "Regtest", -}; +interface Wallet { + [Name=new_no_persist, Throws=BdkError] + constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network); -dictionary SledDbConfiguration { - string path; - string tree_name; -}; + AddressInfo get_address(AddressIndex address_index); -dictionary SqliteDbConfiguration { - string path; -}; + Network network(); -dictionary Balance { - u64 immature; - u64 trusted_pending; - u64 untrusted_pending; - u64 confirmed; - u64 spendable; - u64 total; -}; + Balance get_balance(); -[Enum] -interface DatabaseConfig { - Memory(); - Sled(SledDbConfiguration config); - Sqlite(SqliteDbConfiguration config); + [Throws=BdkError] + void apply_update(Update update); }; -dictionary TransactionDetails { - Transaction? transaction; - u64? fee; - u64 received; - u64 sent; - string txid; - BlockTime? confirmation_time; -}; +interface Update {}; -dictionary BlockTime { - u32 height; - u64 timestamp; +// ------------------------------------------------------------------------ +// bdk crate - bitcoin reexports +// ------------------------------------------------------------------------ + +enum Network { + "Bitcoin", + "Testnet", + "Signet", + "Regtest", }; enum WordCount { @@ -116,260 +105,20 @@ enum WordCount { "Words24", }; -dictionary ElectrumConfig { - string url; - string? socks5; - u8 retry; - u8? timeout; - u64 stop_gap; - boolean validate_domain; -}; - -dictionary EsploraConfig { - string base_url; - string? proxy; - u8? concurrency; - u64 stop_gap; - u64? timeout; -}; - -[Enum] -interface Auth { - None(); - UserPass(string username, string password); - Cookie(string file); -}; - -dictionary RpcSyncParams { - u64 start_script_count; - u64 start_time; - boolean force_start_time; - u64 poll_rate_sec; -}; - -dictionary RpcConfig { - string url; - Auth auth; - Network network; - string wallet_name; - RpcSyncParams? sync_params; -}; - -[Enum] -interface BlockchainConfig { - Electrum(ElectrumConfig config); - Esplora(EsploraConfig config); - Rpc(RpcConfig config); -}; - -interface Blockchain { - [Throws=BdkError] - constructor(BlockchainConfig config); - - [Throws=BdkError] - void broadcast([ByRef] Transaction transaction); - - [Throws=BdkError] - FeeRate estimate_fee(u64 target); - - [Throws=BdkError] - u32 get_height(); - - [Throws=BdkError] - string get_block_hash(u32 height); -}; - -callback interface Progress { - void update(f32 progress, string? message); -}; - -dictionary OutPoint { - string txid; - u32 vout; -}; - -dictionary TxIn { - OutPoint previous_output; - Script script_sig; - u32 sequence; - sequence> witness; -}; - -dictionary TxOut { - u64 value; - Script script_pubkey; -}; - -enum KeychainKind { - "External", - "Internal", -}; - -dictionary LocalUtxo { - OutPoint outpoint; - TxOut txout; - KeychainKind keychain; - boolean is_spent; -}; - -dictionary ScriptAmount { - Script script; - u64 amount; -}; - -interface Wallet { +interface Address { [Throws=BdkError] - constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config); + constructor(string address, Network network); Network network(); - [Throws=BdkError] - AddressInfo get_address(AddressIndex address_index); - - [Throws=BdkError] - AddressInfo get_internal_address(AddressIndex address_index); - - [Throws=BdkError] - boolean is_mine(Script script); - - [Throws=BdkError] - sequence list_unspent(); - - [Throws=BdkError] - sequence list_transactions(boolean include_raw); - - [Throws=BdkError] - Balance get_balance(); - - [Throws=BdkError] - boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options); - - [Throws=BdkError] - void sync([ByRef] Blockchain blockchain, Progress? progress); -}; - -interface FeeRate { - [Name=from_sat_per_vb] - constructor(float sat_per_vb); - - float as_sat_per_vb(); -}; - -dictionary SignOptions { - boolean trust_witness_utxo; - u32? assume_height; - boolean allow_all_sighashes; - boolean remove_partial_sigs; - boolean try_finalize; - boolean sign_with_tap_internal_key; - boolean allow_grinding; -}; - -interface Transaction { - [Throws=BdkError] - constructor(sequence transaction_bytes); - - string txid(); - - u64 weight(); - - u64 size(); - - u64 vsize(); - - sequence serialize(); - - boolean is_coin_base(); - - boolean is_explicitly_rbf(); - - boolean is_lock_time_enabled(); - - i32 version(); - - u32 lock_time(); - - sequence input(); - - sequence output(); -}; - -interface PartiallySignedTransaction { - [Throws=BdkError] - constructor(string psbt_base64); - - string serialize(); - - string txid(); - - Transaction extract_tx(); - - [Throws=BdkError] - PartiallySignedTransaction combine(PartiallySignedTransaction other); - - u64? fee_amount(); - - FeeRate? fee_rate(); - - string json_serialize(); -}; - -dictionary TxBuilderResult { - PartiallySignedTransaction psbt; - TransactionDetails transaction_details; -}; - -interface TxBuilder { - constructor(); - - TxBuilder add_recipient(Script script, u64 amount); - - TxBuilder add_unspendable(OutPoint unspendable); - - TxBuilder add_utxo(OutPoint outpoint); - - TxBuilder add_utxos(sequence outpoints); - - TxBuilder do_not_spend_change(); - - TxBuilder manually_selected_only(); - - TxBuilder only_spend_change(); - - TxBuilder unspendable(sequence unspendable); - - TxBuilder fee_rate(float sat_per_vbyte); - - TxBuilder fee_absolute(u64 fee_amount); - - TxBuilder drain_wallet(); - - TxBuilder drain_to(Script script); - - TxBuilder enable_rbf(); - - TxBuilder enable_rbf_with_sequence(u32 nsequence); - - TxBuilder add_data(sequence data); - - TxBuilder set_recipients(sequence recipients); + string to_qr_uri(); - [Throws=BdkError] - TxBuilderResult finish([ByRef] Wallet wallet); + string as_string(); }; -interface BumpFeeTxBuilder { - constructor(string txid, float new_fee_rate); - - BumpFeeTxBuilder allow_shrinking(string address); - - BumpFeeTxBuilder enable_rbf(); - - BumpFeeTxBuilder enable_rbf_with_sequence(u32 nsequence); - - [Throws=BdkError] - PartiallySignedTransaction finish([ByRef] Wallet wallet); -}; +// ------------------------------------------------------------------------ +// bdk crate - descriptor module +// ------------------------------------------------------------------------ interface Mnemonic { constructor(WordCount word_count); @@ -453,55 +202,10 @@ interface Descriptor { string as_string_private(); }; -interface Address { - [Throws=BdkError] - constructor(string address); - - [Name=from_script, Throws=BdkError] - constructor(Script script, Network network); - - Payload payload(); - - Network network(); - - Script script_pubkey(); - - string to_qr_uri(); - - string as_string(); -}; - -[Enum] -interface Payload { - PubkeyHash(sequence pubkey_hash); - - ScriptHash(sequence script_hash); - - WitnessProgram(WitnessVersion version, sequence program); -}; - -enum WitnessVersion { - "V0", - "V1", - "V2", - "V3", - "V4", - "V5", - "V6", - "V7", - "V8", - "V9", - "V10", - "V11", - "V12", - "V13", - "V14", - "V15", - "V16" -}; - -interface Script { - constructor(sequence raw_output_script); +// ------------------------------------------------------------------------ +// bdk_esplora crate +// ------------------------------------------------------------------------ - sequence to_bytes(); +interface EsploraClient { + constructor(string url); }; diff --git a/bdk-ffi/src/blockchain.rs b/bdk-ffi/src/blockchain.rs deleted file mode 100644 index ac418cc0..00000000 --- a/bdk-ffi/src/blockchain.rs +++ /dev/null @@ -1,201 +0,0 @@ -// use crate::BlockchainConfig; -use crate::{BdkError, Transaction}; -use bdk::bitcoin::Network; -use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; -use bdk::blockchain::rpc::Auth as BdkAuth; -use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams; -use bdk::blockchain::Blockchain as BdkBlockchain; -use bdk::blockchain::GetBlockHash; -use bdk::blockchain::GetHeight; -use bdk::blockchain::{ - electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, - rpc::RpcConfig as BdkRpcConfig, ConfigurableBlockchain, -}; -use bdk::FeeRate; -use std::convert::{From, TryFrom}; -use std::path::PathBuf; -use std::sync::{Arc, Mutex, MutexGuard}; - -pub(crate) struct Blockchain { - inner_mutex: Mutex, -} - -impl Blockchain { - pub(crate) fn new(blockchain_config: BlockchainConfig) -> Result { - let any_blockchain_config = match blockchain_config { - BlockchainConfig::Electrum { config } => { - AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { - retry: config.retry, - socks5: config.socks5, - timeout: config.timeout, - url: config.url, - stop_gap: usize::try_from(config.stop_gap).unwrap(), - validate_domain: config.validate_domain, - }) - } - BlockchainConfig::Esplora { config } => { - AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { - base_url: config.base_url, - proxy: config.proxy, - concurrency: config.concurrency, - stop_gap: usize::try_from(config.stop_gap).unwrap(), - timeout: config.timeout, - }) - } - BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig { - url: config.url, - auth: config.auth.into(), - network: config.network, - wallet_name: config.wallet_name, - sync_params: config.sync_params.map(|p| p.into()), - }), - }; - let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; - Ok(Self { - inner_mutex: Mutex::new(blockchain), - }) - } - - pub(crate) fn get_blockchain(&self) -> MutexGuard { - self.inner_mutex.lock().expect("blockchain") - } - - pub(crate) fn broadcast(&self, transaction: &Transaction) -> Result<(), BdkError> { - let tx = &transaction.inner; - self.get_blockchain().broadcast(tx) - } - - pub(crate) fn estimate_fee(&self, target: u64) -> Result, BdkError> { - let result: Result = - self.get_blockchain().estimate_fee(target as usize); - result.map(Arc::new) - } - - pub(crate) fn get_height(&self) -> Result { - self.get_blockchain().get_height() - } - - pub(crate) fn get_block_hash(&self, height: u32) -> Result { - self.get_blockchain() - .get_block_hash(u64::from(height)) - .map(|hash| hash.to_string()) - } -} - -/// Configuration for an ElectrumBlockchain -pub struct ElectrumConfig { - /// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with ssl:// or tcp:// and include a port - /// e.g. ssl://electrum.blockstream.info:60002 - pub url: String, - /// URL of the socks5 proxy server or a Tor service - pub socks5: Option, - /// Request retry count - pub retry: u8, - /// Request timeout (seconds) - pub timeout: Option, - /// Stop searching addresses for transactions after finding an unused gap of this length - pub stop_gap: u64, - /// Validate the domain when using SSL - pub validate_domain: bool, -} - -/// Configuration for an EsploraBlockchain -pub struct EsploraConfig { - /// Base URL of the esplora service - /// e.g. https://blockstream.info/api/ - pub base_url: String, - /// Optional URL of the proxy to use to make requests to the Esplora server - /// The string should be formatted as: ://:@host:. - /// Note that the format of this value and the supported protocols change slightly between the - /// sync version of esplora (using ureq) and the async version (using reqwest). For more - /// details check with the documentation of the two crates. Both of them are compiled with - /// the socks feature enabled. - /// The proxy is ignored when targeting wasm32. - pub proxy: Option, - /// Number of parallel requests sent to the esplora service (default: 4) - pub concurrency: Option, - /// Stop searching addresses for transactions after finding an unused gap of this length. - pub stop_gap: u64, - /// Socket timeout. - pub timeout: Option, -} - -pub enum Auth { - /// No authentication - None, - /// Authentication with username and password, usually [Auth::Cookie] should be preferred - UserPass { - /// Username - username: String, - /// Password - password: String, - }, - /// Authentication with a cookie file - Cookie { - /// Cookie file - file: String, - }, -} - -impl From for BdkAuth { - fn from(auth: Auth) -> Self { - match auth { - Auth::None => BdkAuth::None, - Auth::UserPass { username, password } => BdkAuth::UserPass { username, password }, - Auth::Cookie { file } => BdkAuth::Cookie { - file: PathBuf::from(file), - }, - } - } -} - -/// Sync parameters for Bitcoin Core RPC. -/// -/// In general, BDK tries to sync `scriptPubKey`s cached in `Database` with -/// `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining -/// how the `importdescriptors` RPC calls are to be made. -pub struct RpcSyncParams { - /// The minimum number of scripts to scan for on initial sync. - pub start_script_count: u64, - /// Time in unix seconds in which initial sync will start scanning from (0 to start from genesis). - pub start_time: u64, - /// Forces every sync to use `start_time` as import timestamp. - pub force_start_time: bool, - /// RPC poll rate (in seconds) to get state updates. - pub poll_rate_sec: u64, -} - -impl From for BdkRpcSyncParams { - fn from(params: RpcSyncParams) -> Self { - BdkRpcSyncParams { - start_script_count: params.start_script_count as usize, - start_time: params.start_time, - force_start_time: params.force_start_time, - poll_rate_sec: params.poll_rate_sec, - } - } -} - -/// RpcBlockchain configuration options -pub struct RpcConfig { - /// The bitcoin node url - pub url: String, - /// The bitcoin node authentication mechanism - pub auth: Auth, - /// The network we are using (it will be checked the bitcoin node network matches this) - pub network: Network, - /// The wallet name in the bitcoin node, consider using [crate::wallet::wallet_name_from_descriptor] for this - pub wallet_name: String, - /// Sync parameters - pub sync_params: Option, -} - -/// Type that can contain any of the blockchain configurations defined by the library. -pub enum BlockchainConfig { - /// Electrum client - Electrum { config: ElectrumConfig }, - /// Esplora client - Esplora { config: EsploraConfig }, - /// Bitcoin Core RPC client - Rpc { config: RpcConfig }, -} diff --git a/bdk-ffi/src/database.rs b/bdk-ffi/src/database.rs deleted file mode 100644 index b5b98b86..00000000 --- a/bdk-ffi/src/database.rs +++ /dev/null @@ -1,14 +0,0 @@ -use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration}; - -/// Type that can contain any of the database configurations defined by the library -/// This allows storing a single configuration that can be loaded into an AnyDatabaseConfig -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime -/// will find this particularly useful. -pub enum DatabaseConfig { - /// Memory database has no config - Memory, - /// Simple key-value embedded database based on sled - Sled { config: SledDbConfiguration }, - /// Sqlite embedded database using rusqlite - Sqlite { config: SqliteDbConfiguration }, -} diff --git a/bdk-ffi/src/descriptor.rs b/bdk-ffi/src/descriptor.rs index a8a37037..2e33c847 100644 --- a/bdk-ffi/src/descriptor.rs +++ b/bdk-ffi/src/descriptor.rs @@ -1,29 +1,32 @@ -use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey}; -use bdk::bitcoin::secp256k1::Secp256k1; -use bdk::bitcoin::util::bip32::Fingerprint; -use bdk::bitcoin::Network; -use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap}; -use bdk::keys::{ - DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey, -}; +use bdk::bitcoin::bip32::Fingerprint; +use bdk::bitcoin::key::Secp256k1; +use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor}; +use bdk::keys::DescriptorPublicKey as BdkDescriptorPublicKey; +use bdk::keys::{DescriptorSecretKey as BdkDescriptorSecretKey, KeyMap}; use bdk::template::{ Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public, DescriptorTemplate, }; +use bdk::Error as BdkError; use bdk::KeychainKind; use std::str::FromStr; use std::sync::Arc; +use crate::keys::DescriptorPublicKey; +use crate::keys::DescriptorSecretKey; +use crate::Network; + #[derive(Debug)] -pub(crate) struct Descriptor { - pub(crate) extended_descriptor: ExtendedDescriptor, - pub(crate) key_map: KeyMap, +pub struct Descriptor { + pub extended_descriptor: ExtendedDescriptor, + pub key_map: KeyMap, } impl Descriptor { pub(crate) fn new(descriptor: String, network: Network) -> Result { let secp = Secp256k1::new(); - let (extended_descriptor, key_map) = descriptor.into_wallet_descriptor(&secp, network)?; + let (extended_descriptor, key_map) = + descriptor.into_wallet_descriptor(&secp, network.into())?; Ok(Self { extended_descriptor, key_map, @@ -38,16 +41,20 @@ impl Descriptor { let derivable_key = &secret_key.inner; match derivable_key { + BdkDescriptorSecretKey::Single(_) => { + unreachable!() + } BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; - let (extended_descriptor, key_map, _) = - Bip44(derivable_key, keychain_kind).build(network).unwrap(); + let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind) + .build(network.into()) + .unwrap(); Self { extended_descriptor, key_map, } } - BdkDescriptorSecretKey::Single(_) => { + BdkDescriptorSecretKey::MultiXPrv(_) => { unreachable!() } } @@ -63,11 +70,14 @@ impl Descriptor { let derivable_key = &public_key.inner; match derivable_key { + BdkDescriptorPublicKey::Single(_) => { + unreachable!() + } BdkDescriptorPublicKey::XPub(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; let (extended_descriptor, key_map, _) = Bip44Public(derivable_key, fingerprint, keychain_kind) - .build(network) + .build(network.into()) .unwrap(); Self { @@ -75,7 +85,7 @@ impl Descriptor { key_map, } } - BdkDescriptorPublicKey::Single(_) => { + BdkDescriptorPublicKey::MultiXPub(_) => { unreachable!() } } @@ -89,16 +99,20 @@ impl Descriptor { let derivable_key = &secret_key.inner; match derivable_key { + BdkDescriptorSecretKey::Single(_) => { + unreachable!() + } BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; - let (extended_descriptor, key_map, _) = - Bip49(derivable_key, keychain_kind).build(network).unwrap(); + let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind) + .build(network.into()) + .unwrap(); Self { extended_descriptor, key_map, } } - BdkDescriptorSecretKey::Single(_) => { + BdkDescriptorSecretKey::MultiXPrv(_) => { unreachable!() } } @@ -114,11 +128,14 @@ impl Descriptor { let derivable_key = &public_key.inner; match derivable_key { + BdkDescriptorPublicKey::Single(_) => { + unreachable!() + } BdkDescriptorPublicKey::XPub(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; let (extended_descriptor, key_map, _) = Bip49Public(derivable_key, fingerprint, keychain_kind) - .build(network) + .build(network.into()) .unwrap(); Self { @@ -126,7 +143,7 @@ impl Descriptor { key_map, } } - BdkDescriptorPublicKey::Single(_) => { + BdkDescriptorPublicKey::MultiXPub(_) => { unreachable!() } } @@ -140,16 +157,20 @@ impl Descriptor { let derivable_key = &secret_key.inner; match derivable_key { + BdkDescriptorSecretKey::Single(_) => { + unreachable!() + } BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; - let (extended_descriptor, key_map, _) = - Bip84(derivable_key, keychain_kind).build(network).unwrap(); + let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind) + .build(network.into()) + .unwrap(); Self { extended_descriptor, key_map, } } - BdkDescriptorSecretKey::Single(_) => { + BdkDescriptorSecretKey::MultiXPrv(_) => { unreachable!() } } @@ -165,11 +186,14 @@ impl Descriptor { let derivable_key = &public_key.inner; match derivable_key { + BdkDescriptorPublicKey::Single(_) => { + unreachable!() + } BdkDescriptorPublicKey::XPub(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; let (extended_descriptor, key_map, _) = Bip84Public(derivable_key, fingerprint, keychain_kind) - .build(network) + .build(network.into()) .unwrap(); Self { @@ -177,7 +201,7 @@ impl Descriptor { key_map, } } - BdkDescriptorPublicKey::Single(_) => { + BdkDescriptorPublicKey::MultiXPub(_) => { unreachable!() } } @@ -191,16 +215,20 @@ impl Descriptor { let derivable_key = &secret_key.inner; match derivable_key { + BdkDescriptorSecretKey::Single(_) => { + unreachable!() + } BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; - let (extended_descriptor, key_map, _) = - Bip86(derivable_key, keychain_kind).build(network).unwrap(); + let (extended_descriptor, key_map, _) = Bip86(derivable_key, keychain_kind) + .build(network.into()) + .unwrap(); Self { extended_descriptor, key_map, } } - BdkDescriptorSecretKey::Single(_) => { + BdkDescriptorSecretKey::MultiXPrv(_) => { unreachable!() } } @@ -216,11 +244,14 @@ impl Descriptor { let derivable_key = &public_key.inner; match derivable_key { + BdkDescriptorPublicKey::Single(_) => { + unreachable!() + } BdkDescriptorPublicKey::XPub(descriptor_x_key) => { let derivable_key = descriptor_x_key.xkey; let (extended_descriptor, key_map, _) = Bip86Public(derivable_key, fingerprint, keychain_kind) - .build(network) + .build(network.into()) .unwrap(); Self { @@ -228,7 +259,7 @@ impl Descriptor { key_map, } } - BdkDescriptorPublicKey::Single(_) => { + BdkDescriptorPublicKey::MultiXPub(_) => { unreachable!() } } @@ -245,12 +276,11 @@ impl Descriptor { } } -// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs. -// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk` -// crate. +// // The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs. +// // These tests should not be used to verify `bdk` behavior that is already tested in the `bdk` +// // crate. #[cfg(test)] mod test { - use crate::database::DatabaseConfig; use crate::*; use assert_matches::assert_matches; use bdk::descriptor::DescriptorError::Key; @@ -385,26 +415,4 @@ mod test { bdk::Error::Descriptor(Key(InvalidNetwork)) ) } - #[test] - fn test_wallet_from_descriptor() { - let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet).unwrap(); - let wallet1 = Wallet::new( - Arc::new(Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet).unwrap()), - None, - Network::Testnet, - DatabaseConfig::Memory - ); - let wallet2 = Wallet::new( - Arc::new(descriptor1), - None, - Network::Bitcoin, - DatabaseConfig::Memory, - ); - // Creating a wallet using a Descriptor with an extended key that doesn't match the network provided in the wallet constructor will throw and InvalidNetwork Error - assert!(wallet1.is_ok()); - assert_matches!( - wallet2.unwrap_err(), - bdk::Error::Descriptor(Key(InvalidNetwork)) - ) - } } diff --git a/bdk-ffi/src/esplora.rs b/bdk-ffi/src/esplora.rs new file mode 100644 index 00000000..298b3e6f --- /dev/null +++ b/bdk-ffi/src/esplora.rs @@ -0,0 +1,18 @@ +use bdk_esplora::esplora_client::{BlockingClient, Builder}; + +pub struct EsploraClient(BlockingClient); + +impl EsploraClient { + pub fn new(url: String) -> Self { + let client = Builder::new(url.as_str()).build_blocking().unwrap(); + Self(client) + } + + // pub fn scan(); + + // pub fn sync(); + + // pub fn broadcast(); + + // pub fn estimate_fee(); +} diff --git a/bdk-ffi/src/keys.rs b/bdk-ffi/src/keys.rs index e1eb1e5f..41e01b69 100644 --- a/bdk-ffi/src/keys.rs +++ b/bdk-ffi/src/keys.rs @@ -1,21 +1,24 @@ -use crate::BdkError; - -use bdk::bitcoin::secp256k1::Secp256k1; -use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath; -use bdk::bitcoin::Network; -use bdk::descriptor::DescriptorXKey; -use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount}; +use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath; +use bdk::bitcoin::key::Secp256k1; +use bdk::bitcoin::secp256k1::rand; +use bdk::bitcoin::secp256k1::rand::Rng; +use bdk::keys::bip39::WordCount; +use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic}; use bdk::keys::{ DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey, }; +use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard}; use bdk::miniscript::BareCtx; +use bdk::Error as BdkError; use std::ops::Deref; use std::str::FromStr; use std::sync::{Arc, Mutex}; -/// Mnemonic phrases are a human-readable version of the private keys. -/// Supported number of words are 12, 15, 18, 21 and 24. +use crate::Network; + +// /// Mnemonic phrases are a human-readable version of the private keys. +// /// Supported number of words are 12, 15, 18, 21 and 24. pub(crate) struct Mnemonic { inner: BdkMnemonic, } @@ -23,8 +26,13 @@ pub(crate) struct Mnemonic { impl Mnemonic { /// Generates Mnemonic with a random entropy pub(crate) fn new(word_count: WordCount) -> Self { + // TODO 4: I DON'T KNOW IF THIS IS A DECENT WAY TO GENERATE ENTROPY PLEASE CONFIRM + let mut rng = rand::thread_rng(); + let mut entropy = [0u8; 32]; + rng.fill(&mut entropy); + let generated_key: GeneratedKey<_, BareCtx> = - BdkMnemonic::generate((word_count, Language::English)).unwrap(); + BdkMnemonic::generate_with_entropy((word_count, Language::English), entropy).unwrap(); let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap(); Mnemonic { inner: mnemonic } } @@ -65,7 +73,7 @@ impl DerivationPath { } #[derive(Debug)] -pub(crate) struct DescriptorSecretKey { +pub struct DescriptorSecretKey { pub(crate) inner: BdkDescriptorSecretKey, } @@ -75,9 +83,9 @@ impl DescriptorSecretKey { let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap(); let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey { origin: None, - xkey: xkey.into_xprv(network).unwrap(), + xkey: xkey.into_xprv(network.into()).unwrap(), derivation_path: BdkDerivationPath::master(), - wildcard: bdk::descriptor::Wildcard::Unhardened, + wildcard: Wildcard::Unhardened, }); Self { inner: descriptor_secret_key, @@ -97,6 +105,9 @@ impl DescriptorSecretKey { let descriptor_secret_key = &self.inner; let path = path.inner_mutex.lock().unwrap().deref().clone(); match descriptor_secret_key { + BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic( + "Cannot derive from a single key".to_string(), + )), BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?; let key_source = match descriptor_x_key.origin.clone() { @@ -113,8 +124,8 @@ impl DescriptorSecretKey { inner: derived_descriptor_secret_key, })) } - BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic( - "Cannot derive from a single key".to_string(), + BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic( + "Cannot derive from a multi key".to_string(), )), } } @@ -123,6 +134,9 @@ impl DescriptorSecretKey { let descriptor_secret_key = &self.inner; let path = path.inner_mutex.lock().unwrap().deref().clone(); match descriptor_secret_key { + BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic( + "Cannot extend from a single key".to_string(), + )), BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { let extended_path = descriptor_x_key.derivation_path.extend(path); let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey { @@ -135,8 +149,8 @@ impl DescriptorSecretKey { inner: extended_descriptor_secret_key, })) } - BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic( - "Cannot extend from a single key".to_string(), + BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic( + "Cannot derive from a multi key".to_string(), )), } } @@ -153,10 +167,13 @@ impl DescriptorSecretKey { pub(crate) fn secret_bytes(&self) -> Vec { let inner = &self.inner; let secret_bytes: Vec = match inner.deref() { + BdkDescriptorSecretKey::Single(_) => { + unreachable!() + } BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { descriptor_x_key.xkey.private_key.secret_bytes().to_vec() } - BdkDescriptorSecretKey::Single(_) => { + BdkDescriptorSecretKey::MultiXPrv(_) => { unreachable!() } }; @@ -170,7 +187,7 @@ impl DescriptorSecretKey { } #[derive(Debug)] -pub(crate) struct DescriptorPublicKey { +pub struct DescriptorPublicKey { pub(crate) inner: BdkDescriptorPublicKey, } @@ -189,6 +206,9 @@ impl DescriptorPublicKey { let path = path.inner_mutex.lock().unwrap().deref().clone(); match descriptor_public_key.deref() { + BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic( + "Cannot derive from a single key".to_string(), + )), BdkDescriptorPublicKey::XPub(descriptor_x_key) => { let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?; let key_source = match descriptor_x_key.origin.clone() { @@ -205,8 +225,8 @@ impl DescriptorPublicKey { inner: derived_descriptor_public_key, })) } - BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic( - "Cannot derive from a single key".to_string(), + BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic( + "Cannot derive from a multi xpub".to_string(), )), } } @@ -215,6 +235,9 @@ impl DescriptorPublicKey { let descriptor_public_key = &self.inner; let path = path.inner_mutex.lock().unwrap().deref().clone(); match descriptor_public_key.deref() { + BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic( + "Cannot extend from a single key".to_string(), + )), BdkDescriptorPublicKey::XPub(descriptor_x_key) => { let extended_path = descriptor_x_key.derivation_path.extend(path); let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey { @@ -227,8 +250,8 @@ impl DescriptorPublicKey { inner: extended_descriptor_public_key, })) } - BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic( - "Cannot extend from a single key".to_string(), + BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic( + "Cannot derive from a multi xpub".to_string(), )), } } @@ -237,21 +260,21 @@ impl DescriptorPublicKey { self.inner.to_string() } } - -// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs. -// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk` -// crate. +// +// // The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs. +// // These tests should not be used to verify `bdk` behavior that is already tested in the `bdk` +// // crate. #[cfg(test)] mod test { use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic}; use crate::BdkError; - use bdk::bitcoin::hashes::hex::ToHex; + // use bdk::bitcoin::hashes::hex::ToHex; use bdk::bitcoin::Network; use std::sync::Arc; fn get_inner() -> DescriptorSecretKey { let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap(); - DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None) + DescriptorSecretKey::new(Network::Testnet.into(), Arc::new(mnemonic), None) } fn derive_dsk( @@ -359,13 +382,16 @@ mod test { assert!(derived_dpk.is_err()); } - #[test] - fn test_retrieve_master_secret_key() { - let master_dpk = get_inner(); - let master_private_key = master_dpk.secret_bytes().to_hex(); - assert_eq!( - master_private_key, - "e93315d6ce401eb4db803a56232f0ed3e69b053774e6047df54f1bd00e5ea936" - ) - } + // TODO 7: It appears that the to_hex() method is not available anymore. + // Look into the correct way to pull the hex out of the DescriptorSecretKey. + // Note: ToHex was removed in bitcoin_hashes 0.12.0 + // #[test] + // fn test_retrieve_master_secret_key() { + // let master_dpk = get_inner(); + // let master_private_key = master_dpk.secret_bytes().to_hex(); + // assert_eq!( + // master_private_key, + // "e93315d6ce401eb4db803a56232f0ed3e69b053774e6047df54f1bd00e5ea936" + // ) + // } } diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index 032597ac..02cd0d35 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -1,52 +1,73 @@ -mod blockchain; -mod database; mod descriptor; +mod esplora; mod keys; mod psbt; mod wallet; -use crate::blockchain::{ - Auth, Blockchain, BlockchainConfig, ElectrumConfig, EsploraConfig, RpcConfig, RpcSyncParams, -}; -use crate::database::DatabaseConfig; -use crate::descriptor::Descriptor; -use crate::keys::DerivationPath; -use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic}; -use crate::psbt::PartiallySignedTransaction; -use crate::wallet::SignOptions; -use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet}; -use bdk::bitcoin::blockdata::script::Script as BdkScript; -use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn; -use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut; -use bdk::bitcoin::consensus::Decodable; -use bdk::bitcoin::psbt::serialize::Serialize; -use bdk::bitcoin::util::address::{Payload as BdkPayload, WitnessVersion}; -use bdk::bitcoin::{ - Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid, -}; -use bdk::blockchain::Progress as BdkProgress; -use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration}; -use bdk::keys::bip39::WordCount; +use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked}; +use bdk::bitcoin::Address as BdkAddress; +use bdk::bitcoin::Network as BdkNetwork; use bdk::wallet::AddressIndex as BdkAddressIndex; use bdk::wallet::AddressInfo as BdkAddressInfo; -use bdk::LocalUtxo as BdkLocalUtxo; -use bdk::TransactionDetails as BdkTransactionDetails; -use bdk::{Balance as BdkBalance, BlockTime, Error as BdkError, FeeRate, KeychainKind}; -use std::convert::From; -use std::fmt; -use std::fmt::Debug; -use std::io::Cursor; -use std::str::FromStr; +use bdk::wallet::Balance as BdkBalance; +use bdk::Error as BdkError; +use bdk::KeychainKind; use std::sync::Arc; +// TODO 6: Why are these imports required? +use crate::descriptor::Descriptor; +use crate::esplora::EsploraClient; +use crate::keys::DerivationPath; +use crate::keys::DescriptorPublicKey; +use crate::keys::DescriptorSecretKey; +use crate::keys::Mnemonic; +use crate::wallet::Update; +use crate::wallet::Wallet; +use bdk::keys::bip39::WordCount; +// use bdk_esplora::EsploraExt; + uniffi::include_scaffolding!("bdk"); -/// A output script and an amount of satoshis. -pub struct ScriptAmount { - pub script: Arc