Compare commits

..

63 Commits

Author SHA1 Message Date
thunderbiscuit
60f1aef3e0 chore: bump jvm lib to 0.31.1 2024-04-19 18:42:43 -04:00
thunderbiscuit
7490d8d8b6 chore: bump android lib to 0.31.1 2024-04-19 17:57:35 -04:00
Matthew
5d71773e7f chore: bump library version from 0.31.0 to 0.31.1 2024-03-26 09:51:05 -05:00
Matthew
ebde685f06 fix: update bdk-swift framework info.plist for xcode 15.3 reqs 2024-03-18 13:36:20 -05:00
thunderbiscuit
8d1ecd1d8c Update libraries to official release versions 2024-01-17 14:34:30 -05:00
thunderbiscuit
25a48e0565 feat: add is_valid_for_network method on address type 2024-01-17 11:12:24 -05:00
thunderbiscuit
b305f8f44e feat: upgrade API to match bdk 0.29 2024-01-16 19:38:21 -05:00
thunderbiscuit
ef080130bf chore: pin uniffi to version 0.23.0 2024-01-10 16:17:23 -05:00
thunderbiscuit
e798e1573f chore: update bdk to version 0.29.0 2024-01-10 16:16:58 -05:00
thunderbiscuit
743862fb60 chore: update minor_release template 2023-09-12 11:38:18 -04:00
thunderbiscuit
b7e38b18be chore: bump snapshot and dev versions of libraries 2023-09-12 11:37:17 -04:00
thunderbiscuit
ef73aa3490 docs: add 0.30.0 release to changelog 2023-09-12 11:35:36 -04:00
thunderbiscuit
fbec953149 docs: update docs for new pinned dependency 2023-09-06 14:51:00 -04:00
thunderbiscuit
0b07b8ed05 docs: update Kotlin API docs 2023-09-06 13:52:48 -04:00
thunderbiscuit
b59327e5ea chore: pin flate2 to 1.0.26 when building with 1.61 2023-09-06 10:40:29 -04:00
thunderbiscuit
e6500baae7 chore: update library version to 0.30.0 2023-09-06 10:25:25 -04:00
thunderbiscuit
85f220b953 build: update webpki dependency as per RUSTSEC-2023-0052 2023-09-05 14:38:16 -04:00
thunderbiscuit
106d31c9c3 Refactor: Remove unused Mutex on DescriptorSecretKey inner field 2023-08-18 13:34:28 -04:00
thunderbiscuit
4ae169f860 Refactor: Remove unused Mutex on DescriptorPublicKey inner field 2023-08-18 12:58:11 -04:00
Matthew
7717ebb097 refactor: rename inner field names 2023-08-16 15:37:33 -05:00
Matthew
c3e8469686 feat(descriptor): add bip-86 template 2023-08-11 12:09:21 -05:00
Steve Myers
faf23b7d25 Merge bitcoindevkit/bdk-ffi#389: ci: fix to work with bdk 0.28.2 and msrv 1.61.0
1da01b4a0b ci: change rust stable version to 0.71.0 (Steve Myers)
f1ba03bf50 ci: fix to work with bdk 0.28.1 and msrv 1.61.0 (Steve Myers)

Pull request description:

  ### Description

  Fixes CI to work with BDK 0.28.x and MSRV 1.61.0. For MSRV had to pin two dependencies.

  ### Notes to the reviewers

  I also updated in CI our 'stable" version of rust to be current stable which is `1.71.0`.

  ### Changelog notice

  None, only CI changes.

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  thunderbiscuit:
    ACK 1da01b4a0b.

Tree-SHA512: 72f7d8dbef791daebf3f4d9d92722f1f3780d173501673ca6f47af39dd2102c85944ba603e4e9213d44a294ab1cec43dff82213fe53c5dea663279473be64a15
2023-08-10 14:03:52 -05:00
Steve Myers
1da01b4a0b ci: change rust stable version to 0.71.0 2023-08-10 11:54:33 -05:00
Steve Myers
f1ba03bf50 ci: fix to work with bdk 0.28.1 and msrv 1.61.0 2023-08-10 11:28:36 -05:00
thunderbiscuit
bc182c7164 Update CI actions to their latest versions
* checkout (v3)
* setup-java (v3)
* cache (v3)
* upload-artifact (v3)
* setup-python (v4)
2023-07-05 14:03:42 -04:00
thunderbiscuit
5fc189717d Fix CI bdk-jvm 2023-07-04 16:19:55 -04:00
thunderbiscuit
849bfe79c1 Add Windows target to Kotlin/JVM published library 2023-07-04 12:32:00 -04:00
thunderbiscuit
dc79b78b2d Fix Python readme and integrate new scripts 2023-06-30 16:18:27 -04:00
thunderbiscuit
7cc08f1d6f Fix publishing Python CI workflow 2023-06-30 16:17:46 -04:00
thunderbiscuit
031fcb02da Run Python Windows tests in CI 2023-06-30 16:01:01 -04:00
thunderbiscuit
5f9b5682e5 Use macos-13 image to test and publish Python libraries 2023-06-23 14:42:36 -04:00
thunderbiscuit
d0a7315c9d Remove patch release issue template 2023-06-16 22:28:32 -04:00
thunderbiscuit
0bfc56b0e8 Fix minor release issue template 2023-06-16 22:28:09 -04:00
thunderbiscuit
3dd6c203e8 Bump snapshot and dev versions of libraries 2023-06-16 22:11:12 -04:00
thunderbiscuit
76acbf575b Add release 0.29.0 to changelog 2023-06-16 22:09:14 -04:00
thunderbiscuit
039b64de5c Update JVM readme with specific Rust version 2023-06-15 11:10:28 -04:00
thunderbiscuit
fe7e4e21c0 Update Android readme with specific Rust and NDK versions 2023-06-15 11:09:48 -04:00
thunderbiscuit
77f89afc68 Update library version to 0.29.0 2023-06-15 10:15:23 -04:00
thunderbiscuit
25033f6bd6 Add Kotlin API docs for Script.toBytes 2023-06-12 13:36:50 -04:00
thunderbiscuit
3cb2c2c394 Expose Script.to_bytes() method 2023-06-12 13:36:44 -04:00
Steve Myers
5092987b26 [swift] suppress keyword escape warnings 2023-06-06 14:17:30 -05:00
Steve Myers
aea25dbf21 Update bdk-swift local build script 2023-06-05 16:45:29 -05:00
thunderbiscuit
ed67eba910 Align JVM target version for Kotlin and Java compile tasks
This commit resolves a build error related to mismatched JVM target
versions for the Kotlin and Java compile tasks. Previously, the
'compileJava' task was targeting JVM 11, while the 'compileKotlin'
task was targeting JVM 8.

Both tasks have now been set to target JVM 11, ensuring consistency
and eliminating the build error.
2023-06-05 10:35:23 -04:00
thunderbiscuit
90606b2455 Small style cleanups in JVM Gradle plugin 2023-06-05 10:09:27 -04:00
yellowhatpro
49e8fe461e added support for x86_64-pc-windows-msvc 64-bit MSVC 2023-06-05 10:09:14 -04:00
Matthew
de88184b8c github: add feature request issue template 2023-05-30 15:27:34 -05:00
thunderbiscuit
3be2c0495f Clean up is_mine method body 2023-05-15 09:01:39 -04:00
thunderbiscuit
2c4c64515f Fix Clippy warning 2023-05-03 15:13:22 -04:00
thunderbiscuit
17323d3184 Add Kotlin API docs for isMine method 2023-05-03 14:21:37 -04:00
thunderbiscuit
b382511a9e Add is_mine method on Wallet type
Closes #354
2023-05-03 14:19:50 -04:00
Steve Myers
d3895441d3 Update bdk-swift/build-local-swift.sh for aarch64-apple-ios-sim to use release-smaller profile 2023-05-01 11:37:05 -05:00
Steve Myers
269512a673 Fix bdk-swift/build-local-swift.sh for aarch64-apple-ios-sim 2023-05-01 10:40:07 -05:00
thunderbiscuit
d27206787a Add supported Python library changes to changelog 2023-04-28 09:00:37 -04:00
thunderbiscuit
c1b1fd6f5d Update changelog for 0.28.0 release 2023-04-28 08:57:11 -04:00
thunderbiscuit
7062fbd047 Update minor_release and patch_release templates 2023-04-28 08:56:58 -04:00
thunderbiscuit
0e34a6bacf Bump snapshot and dev versions of libraries 2023-04-28 08:56:47 -04:00
thunderbiscuit
89e85a20cf Fix Python libraries' names to prepare for releasing 2023-04-25 13:53:27 -04:00
David Sterling
d8718c3f05 Update bdk-jvm README build instructions
The current build instructions for bdk-jvm are insufficient for someone to build bdk-jvm from scratch. It's not outlined that JDK 11 and Rust is required on the system.
2023-04-25 13:48:32 -04:00
thunderbiscuit
871a06d1ce Add library build task to Android test CI workflow 2023-04-24 14:17:58 -04:00
thunderbiscuit
b820d6a2ba Remove support for Python 3.6 and 3.7 2023-04-24 13:57:12 -04:00
thunderbiscuit
79d9fa2909 Use ubuntu-20.04 image for all Linux CI runs 2023-04-24 13:53:56 -04:00
thunderbiscuit
a0e0467d39 Add workflow dispatch to all test workflows 2023-04-24 13:52:42 -04:00
thunderbiscuit
f2296704e6 Pin Rust version in CI workflows to 1.67 2023-04-24 13:51:37 -04:00
46 changed files with 1430 additions and 894 deletions

View File

@@ -0,0 +1,17 @@
---
name: Enhancement request
about: Request a new feature or change to an existing feature
title: ''
labels: 'enhancement'
assignees: ''
---
**Describe the enhancement**
<!-- A clear and concise description of what you would like added or changed. -->
**Use case**
<!-- Tell us how you or others will use this new feature or change to an existing feature. -->
**Additional context**
<!-- Add any other context about the enhancement here. -->

View File

@@ -7,77 +7,81 @@ assignees: ''
--- ---
## Create a new minor release ## Create a new minor release
### _Main Workflow_ ## Bumping BDK Rust Version
1. - [ ] Open a PR with an update to `Cargo.toml` to the new bdk release candidate and ensure all CI workflows run correctly. Fix errors if necessary. 1. - [ ] Open a PR with an update to `Cargo.toml` to the new bdk release candidate and ensure all CI workflows run correctly. Fix errors if necessary.
2. - [ ] Once the new bdk release is out, update the PR to replace the release candidate with the full release and merge. 2. - [ ] Once the new bdk release is out, update the PR to replace the release candidate with the full release and merge.
3. - [ ] Update the Android, JVM, Python, and Swift libraries as per the ["**_Sub-Workflows_**" section below](#Sub-Workflows). Open a single PR on master for all of these changes called `Prepare language bindings libraries for 0.X release`
### Specific Libraries' Workflows
#### _Android_
3. - [ ] Update the API docs to reflect the changes in the API
4. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch.
5. - [ ] Build the library and run the tests, and adjust if necessary.
```shell
# start an emulator prior to running the tests
cd ./bdk-android/
./gradlew buildAndroidLib
./gradlew connectedAndroidTest
```
6. - [ ] Update the readme if necessary
#### _JVM_
7. - [ ] Update the API docs to reflect the changes in the API
8. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
9. - [ ] Build the library and run the tests, and adjust if necessary
```shell
cd ./bdk-jvm/
./gradlew buildJvmLib
./gradlew test
```
10. - [ ] Update the readme if necessary
#### _Swift_
11. - [ ] Run the tests and adjust if necessary
```shell
./bdk-swift/build-local-swift.sh
cd ./bdk-swift/
swift test
```
12. - [ ] Update the readme if necessary
#### _Python_
13. - [ ] Delete the `.tox`, `dist`, `build`, and `bdkpython.egg-info` and rust `target` directories to make sure you are building the library from scratch without any caches
14. - [ ] Build the library
```shell
cd ./bdk-python/
pip3 install --requirement requirements.txt
bash ./scripts/generate-macos-arm64.sh # run the script for your particular platform
python3 setup.py --verbose bdist_wheel
```
15. - [ ] Run the tests and adjust if necessary
```shell
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl --force-reinstall
python -m unittest --verbose tests/test_bdk.py
```
16. - [ ] Update the readme and `setup.py` if necessary
### Release Workflow
17. - [ ] Update the Android, JVM, Python, and Swift libraries as per the _Specific Libraries' Workflows_ section above. Open a single PR on master for all of these changes called `Prepare language bindings libraries for 0.X release`. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/315).
18. - [ ] Create a new branch off of `master` called `release/version` 18. - [ ] Create a new branch off of `master` called `release/version`
19. - [ ] Checkout that branch and open a PR to update the Android, JVM, and Python libraries' versions 19. - [ ] Update bdk-android version from `SNAPSHOT` version to release version
- [ ] Update bdk-android version from `SNAPSHOT` version to release version 20. - [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
- [ ] Update bdk-jvm version from `SNAPSHOT` version to release version 21. - [ ] Update bdk-python version from `.dev` version to release version
- [ ] Update bdk-python version from `.dev` version to release version 22. - [ ] Open a PR to that release branch that updates the Android, JVM, and Python libraries' versions in step 19, 20, and 21. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/316).
20. - [ ] Merge the PR updating all of the languages to their release versions 23. - [ ] Get a review and ACK and merge the PR updating all the languages to their release versions
21. - [ ] Create the tag and make sure to add the changelog info to the tag (works better if you prepare the tag message on the side in a text editor) and push it to GitHub. 24. - [ ] Create the tag for the release and make sure to add the changelog info to the tag (works better if you prepare the tag message on the side in a text editor). Push the tag to GitHub.
```sh ```shell
git tag v0.6.0 --sign --edit git tag v0.6.0 --sign --edit
git push upstream v0.6.0 git push upstream v0.6.0
``` ```
22. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one) 25. - [ ] Trigger manual releases for all 4 libraries (for Swift, trigger the release on `master` and simply add the version number in the text field when running the workflow manually. Note that the version number must not contain the `v`, i.e. `0.26.0`)
23. - [ ] Trigger manual releases for all 4 libraries (for Swift, simply add the version number in the text field when running the workflow manually. Note that the version number must not contain the `v`, i.e. `0.26.0`) 26. - [ ] Make sure the released libraries work and contain the artifacts you would expect
24. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0` 27. - [ ] Aggregate all the changelog notices from the PRs and add them to the changelog file
25. - [ ] Build and publish API docs for JVM, Android, and Java on the website 28. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
```bash! 29. - [ ] Apply changes to the minor_release and patch_release issue templates if they need any
30. - [ ] Open a PR on master with the changes in steps 29, 30, and 31. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/317). Get a review and merge the PR.
31. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
32. - [ ] Build and publish API docs for JVM, Android, and Java on the website
```shell
./gradlew dokkaHtml # bdk-jvm (Dokka) ./gradlew dokkaHtml # bdk-jvm (Dokka)
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation) ./gradlew dokkaJavadoc # bdk-jvm (java-style documentation)
./gradlew dokkaHtml # bdk-android (Dokka) ./gradlew dokkaHtml # bdk-android (Dokka)
``` ```
26. - [ ] Tweet about the library 33. - [ ] Post in the announcement channel
27. - [ ] Post in the announcement channel 34. - [ ] Tweet about the library
### _Sub Workflows_
#### _Android_
4. - [ ] Update the API docs to reflect the changes in the API
5. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
6. - [ ] Build the library and run the tests, and adjust if necessary.
```sh
# start an emulator prior to running the tests
cd bdk-android
./gradlew buildAndroidLib
./gradlew connectedAndroidTest
```
7. - [ ] Update the readme if necessary
#### _JVM_
8. - [ ] Update the API docs to reflect the changes in the API
9. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
10. - [ ] Build the library and run the tests, and adjust if necessary
```sh
cd bdk-jvm
./gradlew buildJvmLib
./gradlew test
```
11. - [ ] Update the readme if necessary
#### _Swift_
12. - [ ] Run the tests and adjust if necessary
```sh
./bdk-swift/build-local-swift.sh
cd bdk-swift
swift test
```
13. - [ ] Update the readme if necessary
#### _Python_
14. - [ ] Delete the `.tox`, `dist`, `build`, and `bdkpython.egg-info` and rust `target` directories to make sure you are building the library from scratch without any caches
15. - [ ] Build the library
```shell
pip3 install --requirement requirements.txt
bash ./generate.sh
python3 setup.py --verbose bdist_wheel
```
16. - [ ] Run the tests and adjust if necessary
```shell
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl
python -m unittest --verbose tests/test_bdk.py
```
17. - [ ] Update the readme and `setup.py` if necessary

View File

@@ -1,84 +0,0 @@
---
name: Patch Release
about: Create a new patch release [for release managers only]
title: 'Release MAJOR.MINOR.PATCH+1'
labels: 'release'
assignees: ''
---
# Creating a new patch release
## Bumping BDK Rust Version
1. - [ ] Open a PR with an update to `Cargo.toml` to the new bdk release candidate and ensure all CI workflows run correctly. Fix errors if necessary.
2. - [ ] Once the new bdk release is out, update the PR to replace the release candidate with the full release and merge.
### Specific Libraries' Workflows
#### _Android_
3. - [ ] Update the API docs to reflect the changes in the API
4. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch.
5. - [ ] Build the library and run the tests, and adjust if necessary.
```sh
# start an emulator prior to running the tests
cd ./bdk-android/
./gradlew buildAndroidLib
./gradlew connectedAndroidTest
```
6. - [ ] Update the readme if necessary
#### _JVM_
7. - [ ] Update the API docs to reflect the changes in the API
8. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
9. - [ ] Build the library and run the tests, and adjust if necessary
```sh
cd ./bdk-jvm/
./gradlew buildJvmLib
./gradlew test
```
10. - [ ] Update the readme if necessary
#### _Swift_
11. - [ ] Run the tests and adjust if necessary
```sh
./bdk-swift/build-local-swift.sh
cd ./bdk-swift/
swift test
```
12. - [ ] Update the readme if necessary
#### _Python_
13. - [ ] Delete the `.tox`, `dist`, `build`, and `bdkpython.egg-info` and rust `target` directories to make sure you are building the library from scratch without any caches
14. - [ ] Build the library
```shell
cd ./bdk-python/
pip3 install --requirement requirements.txt
bash ./generate.sh
python3 setup.py --verbose bdist_wheel
```
15. - [ ] Run the tests and adjust if necessary
```shell
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl --force-reinstall
python -m unittest --verbose tests/test_bdk.py
```
16. - [ ] Update the readme and `setup.py` if necessary
### Release Workflow
17. - [ ] Update the Android, JVM, Python, and Swift libraries as per the _Specific Libraries' Workflows_ section above. Open a single PR on master for all of these changes called `Prepare language bindings libraries for 0.X release`
- [ ] Create a new branch off of `master` called `release/version`
18. - [ ] Checkout that branch and open a PR to update the Android, JVM, and Python libraries' versions
- [ ] Update bdk-android version from `SNAPSHOT` version to release version
- [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
- [ ] Update bdk-python version from `.dev` version to release version
19. - [ ] Merge the PR updating all of the languages to their release versions
20. - [ ] Create the tag and make sure to add the changelog info to the tag (works better if you prepare the tag message on the side in a text editor) and push it to GitHub.
```sh
git tag v0.6.0 --sign --edit
git push upstream v0.6.0
```
21. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
22. - [ ] Trigger manual releases for all 4 libraries (for Swift, simply add the version number in the text field when running the workflow manually. Note that the version number must not contain the `v`, i.e. `0.26.0`)
23. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
24. - [ ] Build and publish API docs for JVM, Android, and Java on the website
```bash!
./gradlew dokkaHtml # bdk-jvm (Dokka)
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation)
./gradlew dokkaHtml # bdk-android (Dokka)
```
25. - [ ] Tweet about the library
26. - [ ] Post in the announcement channel

View File

@@ -13,7 +13,7 @@ jobs:
name: Security audit name: Security audit
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions-rs/audit-check@v1 - uses: actions-rs/audit-check@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -14,18 +14,18 @@ jobs:
strategy: strategy:
matrix: matrix:
rust: rust:
- version: 1.63.0 # STABLE - version: 1.71.0 # STABLE
clippy: true clippy: true
- version: 1.61.0 # MSRV - version: 1.61.0 # MSRV
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Generate cache key - name: Generate cache key
run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
- name: Cache - name: Cache
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@@ -46,6 +46,12 @@ jobs:
- name: Update toolchain - name: Update toolchain
run: rustup update run: rustup update
- 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 run: cargo build
@@ -61,7 +67,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Set default toolchain - name: Set default toolchain
run: rustup default nightly run: rustup default nightly

View File

@@ -20,10 +20,10 @@ jobs:
echo "y" | $SDKMANAGER "ndk;21.4.7075529" echo "y" | $SDKMANAGER "ndk;21.4.7075529"
- name: "Check out PR branch" - name: "Check out PR branch"
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: "Cache" - name: "Cache"
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@@ -32,7 +32,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK" - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11

View File

@@ -2,14 +2,14 @@ name: Publish bdk-jvm to Maven Central
on: [workflow_dispatch] on: [workflow_dispatch]
jobs: jobs:
build-jvm-macOS-M1-native-lib: build-macOS-native-libs:
name: "Create M1 and x86_64 JVM native binaries" name: "Create M1 and x86_64 native binaries"
runs-on: macos-12 runs-on: macos-12
steps: steps:
- name: "Checkout publishing branch" - name: "Checkout publishing branch"
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Cache - name: "Cache"
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@@ -18,8 +18,8 @@ jobs:
./target ./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: Set up JDK - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
@@ -27,36 +27,59 @@ jobs:
- name: "Set default Rust version to 1.67.0" - name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0 run: rustup default 1.67.0
- name: Install aarch64 Rust target - name: "Install aarch64 Rust target"
run: rustup target add aarch64-apple-darwin run: rustup target add aarch64-apple-darwin
- name: Build bdk-jvm library - name: "Build bdk-jvm library"
run: | run: |
cd bdk-jvm cd bdk-jvm
./gradlew buildJvmLib ./gradlew buildJvmLib
# build aarch64 + x86_64 native libraries and upload - name: "Upload macOS native libraries for reuse in publishing job"
- name: Upload macOS native libraries for reuse in publishing job
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
# name: no name is required because we upload the entire directory name: artifact-macos
# the default name "artifact" will be used
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-jvm/lib/src/main/resources/ path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-jvm/lib/src/main/resources/
build-jvm-full-library: build-windows-native-lib:
name: "Create Windows native binaries"
runs-on: windows-2022
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v3
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install x86_64-pc-windows-msvc Rust target"
run: rustup target add x86_64-pc-windows-msvc
- name: "Build bdk-jvm library"
run: |
cd bdk-jvm
./gradlew buildJvmLib
- name: "Upload Windows native libraries for reuse in publishing job"
uses: actions/upload-artifact@v3
with:
name: artifact-windows
path: D:\a\bdk-ffi\bdk-ffi\bdk-jvm\lib\src\main\resources\
build-full-library:
name: Create full bdk-jvm library name: Create full bdk-jvm library
needs: [build-jvm-macOS-M1-native-lib] needs: [build-macOS-native-libs, build-windows-native-lib]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout publishing branch - name: "Checkout publishing branch"
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Update bdk-ffi git submodule - name: "Cache"
run: |
git submodule set-url bdk-ffi https://github.com/bitcoindevkit/bdk-ffi.git
git submodule update --init bdk-ffi
- name: Cache
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
@@ -65,8 +88,8 @@ jobs:
./target ./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: Set up JDK - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
@@ -74,20 +97,30 @@ jobs:
- name: "Set default Rust version to 1.67.0" - name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0 run: rustup default 1.67.0
- name: Build bdk-jvm library - name: "Build bdk-jvm library"
run: | run: |
cd bdk-jvm cd bdk-jvm
./gradlew buildJvmLib ./gradlew buildJvmLib
- name: Download macOS native libraries from previous job - name: "Download macOS native binaries from previous job"
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
id: download
with: with:
# download the artifact created in the prior job (named "artifact") name: artifact-macos
name: artifact
path: ./bdk-jvm/lib/src/main/resources/ path: ./bdk-jvm/lib/src/main/resources/
- name: Publish to Maven Central - name: "Download Windows native libraries from previous job"
uses: actions/download-artifact@v3
with:
name: artifact-windows
path: ./bdk-jvm/lib/src/main/resources/
- name: "Upload library code and binaries"
uses: actions/upload-artifact@v3
with:
name: artifact-full
path: ./bdk-jvm/lib/
- name: "Publish to Maven Central"
env: env:
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.PGP_KEY_ID }} ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.PGP_KEY_ID }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET_KEY }} ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET_KEY }}

View File

@@ -1,4 +1,4 @@
name: Build and publish Python wheels name: Publish bdkpython to PyPI
on: [workflow_dispatch] on: [workflow_dispatch]
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which # We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
@@ -7,7 +7,7 @@ on: [workflow_dispatch]
# tries to load glibc and fails because it requires a more recent version. # tries to load glibc and fails because it requires a more recent version.
jobs: jobs:
build-manylinux2014-x86_64-wheel: build-manylinux2014-x86_64-wheels:
name: "Build Manylinux 2014 x86_64 wheel" name: "Build Manylinux 2014 x86_64 wheel"
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
defaults: defaults:
@@ -26,35 +26,29 @@ jobs:
- cp310-cp310 - cp310-cp310
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
with: with:
toolchain: stable toolchain: stable
- name: "Set default Rust version to 1.67.0" - name: "Generate bdk.py and binaries"
run: rustup default 1.67.0 run: bash ./scripts/generate-linux.sh
- name: "Install requirements"
run: ${PYBIN}/pip install -r requirements.txt
- name: "Generate bdk.py"
run: bash generate.sh
- name: "Build wheel" - name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name, # Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information # see issue #350 for more information
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v3
with: with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }} name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-universal-wheel: build-macos-arm64-wheels:
name: "Build macOS universal wheel" name: "Build macOS arm64 wheel"
runs-on: macos-12 runs-on: macos-13
defaults: defaults:
run: run:
working-directory: bdk-python working-directory: bdk-python
@@ -66,33 +60,66 @@ jobs:
- "3.10" - "3.10"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v2
- name: "Install Python"
uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: "Generate bdk.py" - name: "Generate bdk.py and binaries"
run: | run: bash ./scripts/generate-macos-arm64.sh
python3 --version
rustup target add aarch64-apple-darwin
pip3 install --user -r requirements.txt
bash generate.sh
- name: "Build wheel" - name: "Build wheel"
env:
ARCHFLAGS: "-arch x86_64 -arch arm64"
# Specifying the plat-name argument is necessary to build a wheel with the correct name, # Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information # see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_12_0_universal2 --verbose run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
- uses: actions/upload-artifact@v2 - name: "Upload artifacts"
uses: actions/upload-artifact@v3
with: with:
name: bdkpython-macos-${{ matrix.python }} name: bdkpython-macos-arm64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-windows-wheel: build-macos-x86_64-wheels:
name: "Build macOS x86_64 wheel"
runs-on: macos-13
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-macos-x86_64.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
- uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-x86_64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-windows-wheels:
name: "Build Windows wheel" name: "Build Windows wheel"
runs-on: windows-2022 runs-on: windows-2022
defaults: defaults:
@@ -106,23 +133,21 @@ jobs:
- "3.10" - "3.10"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v2 - uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: "Generate bdk.py" - name: "Generate bdk.py and binaries"
run: | run: bash ./scripts/generate-windows.sh
python --version
pip install --user -r requirements.txt
bash generate.sh
- name: "Build wheel" - name: "Build wheel"
run: python setup.py bdist_wheel --verbose run: python setup.py bdist_wheel --verbose
- uses: actions/upload-artifact@v2 - name: "Upload artifacts"
uses: actions/upload-artifact@v3
with: with:
name: bdkpython-win-${{ matrix.python }} name: bdkpython-win-${{ matrix.python }}
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
@@ -133,13 +158,13 @@ jobs:
defaults: defaults:
run: run:
working-directory: bdk-python working-directory: bdk-python
needs: [build-manylinux2014-x86_64-wheel, build-macos-universal-wheel, build-windows-wheel] needs: [build-manylinux2014-x86_64-wheels, build-macos-arm64-wheels, build-macos-x86_64-wheels, build-windows-wheels]
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: "Download artifacts in dist/ directory" - name: "Download artifacts in dist/ directory"
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
path: dist/ path: dist/

View File

@@ -29,10 +29,10 @@ jobs:
echo "y" | $SDKMANAGER "ndk;21.4.7075529" echo "y" | $SDKMANAGER "ndk;21.4.7075529"
- name: "Check out PR branch" - name: "Check out PR branch"
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: "Cache" - name: "Cache"
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@@ -41,7 +41,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK" - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11

View File

@@ -14,11 +14,11 @@ jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Check out PR branch - name: "Check out PR branch"
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Cache - name: "Cache"
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/registry ~/.cargo/registry
@@ -26,8 +26,8 @@ jobs:
./target ./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: Set up JDK - name: "Set up JDK"
uses: actions/setup-java@v2 uses: actions/setup-java@v3
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
@@ -35,7 +35,7 @@ jobs:
- name: "Set default Rust version to 1.67.0" - name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0 run: rustup default 1.67.0
- name: Run JVM tests - name: "Run JVM tests"
run: | run: |
cd bdk-jvm cd bdk-jvm
./gradlew test --console=rich ./gradlew test

View File

@@ -16,7 +16,7 @@ on:
# tries to load glibc and fails because it requires a more recent version. # tries to load glibc and fails because it requires a more recent version.
jobs: jobs:
build-manylinux2014-x86_64-wheel: build-manylinux2014-x86_64-wheels:
name: "Build and test Manylinux 2014 x86_64 wheels" name: "Build and test Manylinux 2014 x86_64 wheels"
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
defaults: defaults:
@@ -35,42 +35,36 @@ jobs:
- cp310-cp310 - cp310-cp310
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
with: with:
toolchain: stable toolchain: stable
- name: "Set default Rust version to 1.67.0" - name: "Generate bdk.py and binaries"
run: rustup default 1.67.0 run: bash ./scripts/generate-linux.sh
- name: "Install requirements"
run: ${PYBIN}/pip install -r requirements.txt
- name: "Generate bdk.py"
run: bash generate.sh
- name: "Build wheel" - name: "Build wheel"
run: ${PYBIN}/python setup.py bdist_wheel --verbose # Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
- name: "Install wheel" - name: "Install wheel"
run: ${PYBIN}/pip install ./dist/*.whl run: ${PYBIN}/pip install ./dist/*.whl
- name: "Run tests" - name: "Run tests"
# Specifying the plat-name argument is necessary to build a wheel with the correct name, run: ${PYBIN}/python -m unittest tests/test_bdk.py --verbose
# see issue #350 for more information
run: ${PYBIN}/python -m unittest tests/test_bdk.py --plat-name manylinux_2_17_x86_64 --verbose
- name: "Upload artifact test" - name: "Upload artifact test"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }} name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-universal-wheel: build-macos-arm64-wheels:
name: "Build and test macOS wheels" name: "Build and test macOS arm64 wheels"
runs-on: macos-12 runs-on: macos-13
defaults: defaults:
run: run:
working-directory: bdk-python working-directory: bdk-python
@@ -81,25 +75,64 @@ jobs:
- "3.9" - "3.9"
- "3.10" - "3.10"
steps: steps:
- name: Checkout - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v2
- name: "Install Python"
uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: "Generate bdk.py" - name: "Generate bdk.py and binaries"
run: | run: bash ./scripts/generate-macos-arm64.sh
python3 --version
rustup target add aarch64-apple-darwin
pip3 install --user -r requirements.txt
bash generate.sh
- name: "Build wheel" - name: "Build wheel"
env: # Specifying the plat-name argument is necessary to build a wheel with the correct name,
ARCHFLAGS: "-arch x86_64 -arch arm64" # see issue #350 for more information
run: python3 setup.py bdist_wheel --verbose run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
# You can't install the arm64 wheel on the CI, so we skip these steps and simply test that the wheel builds
# - name: "Install wheel and run tests"
# run: |
# pip3 install ./dist/*.whl
# python3 -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-arm64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-x86_64-wheels:
name: "Build and test macOS x86_64 wheels"
runs-on: macos-13
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-macos-x86_64.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
- name: "Install wheel" - name: "Install wheel"
run: pip3 install ./dist/*.whl run: pip3 install ./dist/*.whl
@@ -107,7 +140,13 @@ jobs:
- name: "Run tests" - name: "Run tests"
run: python3 -m unittest tests/test_bdk.py --verbose run: python3 -m unittest tests/test_bdk.py --verbose
build-windows-wheel: - name: "Upload artifact test"
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-x86_64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-windows-wheels:
name: "Build and test Windows wheels" name: "Build and test Windows wheels"
runs-on: windows-2022 runs-on: windows-2022
defaults: defaults:
@@ -121,28 +160,30 @@ jobs:
- "3.10" - "3.10"
steps: steps:
- name: "Checkout" - name: "Checkout"
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v2
- name: "Install Python"
uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: "Generate bdk.py" - name: "Generate bdk.py and binaries"
run: | run: bash ./scripts/generate-windows.sh
python --version
pip install --user -r requirements.txt
bash generate.sh
- name: "Build wheel" - name: "Build wheel"
run: python setup.py bdist_wheel --verbose run: python setup.py bdist_wheel --verbose
# TODO: On Windows the pip install ./dist/*.whl step fails with the following error: - name: "Upload artifact test"
# Run pip install ./dist/*.whl uses: actions/upload-artifact@v3
# WARNING: Requirement './dist/*.whl' looks like a filename, but the file does not exist with:
# ERROR: *.whl is not a valid wheel filename.*.whl is not a valid wheel name name: bdkpython-windows-${{ matrix.python }}
# So we skip the installing and the tests and simply test that the wheel builds path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
# - name: Install wheel
# run: pip install ./dist/*.whl - name: "Install dependencies"
# - name: Run tests run: Get-ChildItem 'D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl' | ForEach-Object {pip install $_.FullName}
# run: python -m unittest tests/test_bdk.py --verbose shell: powershell
- name: "Run tests"
run: python -m unittest tests/test_bdk.py --verbose

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: macos-12 runs-on: macos-12
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: "Set default Rust version to 1.67.0" - name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0 run: rustup default 1.67.0
@@ -36,7 +36,7 @@ jobs:
- name: Build bdk-ffi for aarch64-apple-darwin - name: Build bdk-ffi for aarch64-apple-darwin
run: cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin run: cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
- name: Create lipo-ios-sim and lipo-macos - name: Create lipo-macos
run: | run: |
mkdir -p target/lipo-macos/release-smaller 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 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

View File

@@ -1,14 +1,54 @@
# Changelog # Changelog
All notable changes to this project prior to release **0.9.0** are documented in this file. Future Changelog information can also be found in each release's git tag (which can be viewed with `git tag -ln100 "v*"`), as well as on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases) page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
changelog information can be found in each release's git tag and can be viewed with `git tag -ln100 "v*"`.
Changelog info is also documented on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases)
page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.30.0]
This release has a new API and a few internal optimizations and refactorings.
- APIs Added
- Add BIP-86 descriptor templates [#388]
[#388]: https://github.com/bitcoindevkit/bdk-ffi/pull/388
## [0.29.0]
This release has a number of new APIs, and adds support for Windows in bdk-jvm.
Changelog
- Add support for Windows in bdk-jvm [#336]
- Add support for older version of Linux distros in bdk-jvm [#345]
- APIs added
- Expose `is_mine()` method on the `Wallet` type [#355]
- Expose `to_bytes()` method on the `Script` type [#369]
[#336]: https://github.com/bitcoindevkit/bdk-ffi/pull/336
[#345]: https://github.com/bitcoindevkit/bdk-ffi/pull/345
[#355]: https://github.com/bitcoindevkit/bdk-ffi/pull/355
[#369]: https://github.com/bitcoindevkit/bdk-ffi/pull/369
## [v0.28.0]
- Update BDK to version 0.28.0 [#341]
- Drop support of pypy releases of Python libraries [#351]
- Drop support for Python 3.6 and 3.7 [#351]
- Drop support for very old Linux versions that do not support the manylinux_2_17_x86_64 platform tag [#351]
- APIs changed:
- Expose Address payload and network properties. [#325]
- Add SignOptions to Wallet.sign() params. [#326]
- address field on `AddressInfo` type is now of type `Address` [#333]
- new PartiallySignedTransaction.json_serialize() function to get JSON serialized value of all PSBT fields. [#334]
- Add from_script constructor to `Address` type [#337]
[#325]: https://github.com/bitcoindevkit/bdk-ffi/pull/325
[#326]: https://github.com/bitcoindevkit/bdk-ffi/pull/326
[#333]: https://github.com/bitcoindevkit/bdk-ffi/pull/333
[#334]: https://github.com/bitcoindevkit/bdk-ffi/pull/334
[#337]: https://github.com/bitcoindevkit/bdk-ffi/pull/337
[#341]: https://github.com/bitcoindevkit/bdk-ffi/pull/341
[#351]: https://github.com/bitcoindevkit/bdk-ffi/pull/351
## [v0.27.1] ## [v0.27.1]
- Update BDK to latest version 0.27.1 [#312] - Update BDK to version 0.27.1 [#312]
- APIs changed - APIs changed
- `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of the transaction bytes. [#296] - `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of the transaction bytes. [#296]
- `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`. [#296] - `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`. [#296]
@@ -23,7 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#312]: https://github.com/bitcoindevkit/bdk-ffi/pull/312 [#312]: https://github.com/bitcoindevkit/bdk-ffi/pull/312
## [v0.26.0] ## [v0.26.0]
- Update BDK to latest version 0.26.0 [#288] - Update BDK to version 0.26.0 [#288]
- APIs changed - APIs changed
- The descriptor and change_descriptor arguments on the wallet constructor now take a `Descriptor` instead of a `String`. [#260] - The descriptor and change_descriptor arguments on the wallet constructor now take a `Descriptor` instead of a `String`. [#260]
- TxBuilder.drain_to() argument is now `Script` instead of address `String`. [#279] - TxBuilder.drain_to() argument is now `Script` instead of address `String`. [#279]
@@ -46,7 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#288]: https://github.com/bitcoindevkit/bdk-ffi/pull/288 [#288]: https://github.com/bitcoindevkit/bdk-ffi/pull/288
## [v0.25.0] ## [v0.25.0]
- Update BDK to latest version 0.25.0 [#272] - Update BDK to version 0.25.0 [#272]
- APIs Added: - APIs Added:
- from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247] - from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247]
@@ -54,7 +94,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#272]: https://github.com/bitcoindevkit/bdk-ffi/pull/272 [#272]: https://github.com/bitcoindevkit/bdk-ffi/pull/272
## [v0.11.0] ## [v0.11.0]
- Update BDK to latest version 0.24.0 [#221] - Update BDK to version 0.24.0 [#221]
- APIs changed - APIs changed
- The constructor on the DescriptorSecretKey type now takes a Mnemonic instead of a String. - The constructor on the DescriptorSecretKey type now takes a Mnemonic instead of a String.
- APIs added - APIs added
@@ -70,7 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#221]: https://github.com/bitcoindevkit/bdk-ffi/pull/221 [#221]: https://github.com/bitcoindevkit/bdk-ffi/pull/221
## [v0.10.0] ## [v0.10.0]
- Update BDK to latest version 0.23.0 [#204] - Update BDK to version 0.23.0 [#204]
- Update uniffi-rs to latest version 0.21.0 [#216] - Update uniffi-rs to latest version 0.21.0 [#216]
- Breaking Changes - Breaking Changes
- Changed `TxBuilder.finish()` to return new `TxBuilderResult` [#209] - Changed `TxBuilder.finish()` to return new `TxBuilderResult` [#209]
@@ -103,7 +143,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- APIs Added [#154] - APIs Added [#154]
- `generate_mnemonic()`, returns string mnemonic - `generate_mnemonic()`, returns string mnemonic
- `interface DescriptorSecretKey` - `interface DescriptorSecretKey`
- `new(Network, string_mnenoinc, password)`, contructs DescriptorSecretKey - `new(Network, string_mnenoinc, password)`, constructs DescriptorSecretKey
- `derive(DerivationPath)`, derives and returns child DescriptorSecretKey - `derive(DerivationPath)`, derives and returns child DescriptorSecretKey
- `extend(DerivationPath)`, extends and returns DescriptorSecretKey - `extend(DerivationPath)`, extends and returns DescriptorSecretKey
- `as_public()`, returns DescriptorSecretKey as DescriptorPublicKey - `as_public()`, returns DescriptorSecretKey as DescriptorPublicKey
@@ -183,8 +223,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[BIP 0174]:https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#encoding [BIP 0174]:https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#encoding
## [v0.2.0] [v0.30.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.29.0...v0.30.0
[v0.29.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.28.0...v0.29.0
[v0.28.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.27.1...v0.28.0
[v0.27.1]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.26.0...v0.27.1 [v0.27.1]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.26.0...v0.27.1
[v0.26.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.25.0...v0.26.0 [v0.26.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.25.0...v0.26.0
[v0.25.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.11.0...v0.25.0 [v0.25.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.11.0...v0.25.0

571
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,4 +9,4 @@ opt-level = 'z' # Optimize for size.
lto = true # Enable Link Time Optimization lto = true # Enable Link Time Optimization
codegen-units = 1 # Reduce number of codegen units to increase optimizations. codegen-units = 1 # Reduce number of codegen units to increase optimizations.
panic = 'abort' # Abort on panic panic = 'abort' # Abort on panic
strip = true # Strip symbols from binary* strip = true # Strip symbols from binary

View File

@@ -22,6 +22,21 @@ The below directories (a separate repository in the case of bdk-swift) include i
| Swift | iOS, macOS | [bdk-swift (GitHub)] | [Readme bdk-swift] | | | Swift | iOS, macOS | [bdk-swift (GitHub)] | [Readme bdk-swift] | |
| Python | linux, macOS, Windows | [bdk-python (PyPI)] | [Readme bdk-python] | | | Python | linux, macOS, Windows | [bdk-python (PyPI)] | [Readme bdk-python] | |
## Minimum Supported Rust Version (MSRV)
This library should compile with any combination of features with Rust 1.61.0.
To build with the MSRV you will need to pin dependencies as follows:
```shell
# required for sqlite feature, hashlink 0.8.2 has MSRV 1.61.0
cargo update -p hashlink --precise "0.8.1"
# tokio 1.30.0 has MSRV 1.63.0
cargo update -p tokio --precise "1.29.1"
# flate2 1.0.27 and up do not work with Rust 1.61.0, but 1.0.26 does
cargo update -p flate2 --precise "1.0.26"
```
## Contributing ## Contributing
### Adding new structs and functions ### Adding new structs and functions
@@ -49,8 +64,8 @@ See the [UniFFI User Guide](https://mozilla.github.io/uniffi-rs/)
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>") implementation("org.bitcoindevkit:bdk-android:<version>")
} }
``` ```
@@ -60,8 +75,8 @@ dependencies {
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version>") implementation("org.bitcoindevkit:bdk-jvm:<version>")
} }
``` ```

View File

@@ -489,6 +489,9 @@ class Wallet(
*/ */
fun getInternalAddress(addressIndex: AddressIndex): AddressInfo {} fun getInternalAddress(addressIndex: AddressIndex): AddressInfo {}
/** Return whether or not a script is part of this wallet (either internal or external). */
fun isMine(script: Script): Boolean {}
/** Return the wallet's balance, across different categories. See [Balance] for the categories. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */ /** Return the wallet's balance, across different categories. See [Balance] for the categories. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */
fun getBalance(): Balance {} fun getBalance(): Balance {}
@@ -782,6 +785,19 @@ class Descriptor(descriptor: String, network: Network) {
*/ */
fun newBip84Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {} fun newBip84Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/**
* BIP86 template. Expands to wpkh(key/86'/{0,1}'/0'/{0,1}/\*)
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
*/
fun newBip86(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
/**
* BIP86 public template. Expands to wpkh(key/{0,1}/\*)
* This assumes that the key used has already been derived with m/86'/0'/0' for Mainnet or m/86'/1'/0' for Testnet.
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
*/
fun newBip86Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/** Return the public version of the output descriptor. */ /** Return the public version of the output descriptor. */
fun asString(): String {} fun asString(): String {}
@@ -826,7 +842,10 @@ data class TxBuilderResult (
/** /**
* A bitcoin script. * A bitcoin script.
*/ */
class Script(rawOutputScript: List<UByte>) class Script(rawOutputScript: List<UByte>) {
/** Return the script as bytes. */
fun toBytes(): List<UByte> {}
}
/** /**
* A bitcoin address. * A bitcoin address.

View File

@@ -8,8 +8,8 @@ repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>") implementation("org.bitcoindevkit:bdk-android:<version>")
} }
``` ```
@@ -38,8 +38,8 @@ repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} }
dependencies { dependencies {
implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>") implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>")
} }
``` ```
@@ -54,19 +54,23 @@ _Note that Kotlin version `1.6.10` or later is required to build the library._
```shell ```shell
git clone https://github.com/bitcoindevkit/bdk-ffi git clone https://github.com/bitcoindevkit/bdk-ffi
``` ```
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions. 2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions.
3. If building on macOS install required intel and m1 jvm targets 3. Install Rust (note that we are currently building using Rust 1.67.0):
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default 1.67.0
```
4. Install required targets 4. Install required targets
```sh ```sh
rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
``` ```
5. Install Android SDK and Build-Tools for API level 30+ 5. Install Android SDK and Build-Tools for API level 30+
6. Setup `$ANDROID_SDK_ROOT` and `$ANDROID_NDK_ROOT` path variables (which are required by the 6. Setup `$ANDROID_SDK_ROOT` and `$ANDROID_NDK_ROOT` path variables (which are required by the
build tool), for example (NDK major version 21 is required): build tool), for example (note that currently, NDK version 21.4.7075529 is required):
```shell ```shell
export ANDROID_SDK_ROOT=~/Android/Sdk export ANDROID_SDK_ROOT=~/Android/Sdk
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.<NDK_VERSION> export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529
``` ```
7. Build kotlin bindings 7. Build kotlin bindings
```sh ```sh
# build Android library # build Android library

View File

@@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
kotlin.code.style=official kotlin.code.style=official
libraryVersion=0.28.0 libraryVersion=0.31.1

View File

@@ -1,14 +1,12 @@
[package] [package]
name = "bdk-ffi" name = "bdk-ffi"
version = "0.28.0" version = "0.31.1"
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"] authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
edition = "2018" edition = "2018"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
[lib] [lib]
crate-type = ["lib", "staticlib", "cdylib"] crate-type = ["lib", "staticlib", "cdylib"]
#crate-type = ["staticlib", "cdylib"]
#crate-type = ["cdylib"]
name = "bdkffi" name = "bdkffi"
[[bin]] [[bin]]
@@ -19,12 +17,12 @@ path = "uniffi-bindgen.rs"
default = ["uniffi/cli"] default = ["uniffi/cli"]
[dependencies] [dependencies]
bdk = { version = "0.28", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] } bdk = { version = "0.29.0", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
uniffi = { version = "0.23.0" } uniffi = { version = "=0.23.0" }
[build-dependencies] [build-dependencies]
uniffi = { version = "0.23.0", features = ["build"] } uniffi = { version = "=0.23.0", features = ["build"] }
[dev-dependencies] [dev-dependencies]
uniffi = { version = "0.23.0", features = ["bindgen-tests"] } uniffi = { version = "=0.23.0", features = ["bindgen-tests"] }
assert_matches = "1.5.0" assert_matches = "1.5.0"

View File

@@ -46,6 +46,7 @@ enum BdkError {
"Sled", "Sled",
"Rusqlite", "Rusqlite",
"Rpc", "Rpc",
"HardenedIndex"
}; };
dictionary AddressInfo { dictionary AddressInfo {
@@ -221,28 +222,31 @@ interface Wallet {
[Throws=BdkError] [Throws=BdkError]
constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config); constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config);
Network network();
[Throws=BdkError] [Throws=BdkError]
AddressInfo get_address(AddressIndex address_index); AddressInfo get_address(AddressIndex address_index);
[Throws=BdkError] [Throws=BdkError]
AddressInfo get_internal_address(AddressIndex address_index); AddressInfo get_internal_address(AddressIndex address_index);
[Throws=BdkError]
boolean is_mine(Script script);
[Throws=BdkError]
sequence<LocalUtxo> list_unspent();
[Throws=BdkError]
sequence<TransactionDetails> list_transactions(boolean include_raw);
[Throws=BdkError] [Throws=BdkError]
Balance get_balance(); Balance get_balance();
[Throws=BdkError] [Throws=BdkError]
boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options); boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options);
[Throws=BdkError]
sequence<TransactionDetails> list_transactions(boolean include_raw);
Network network();
[Throws=BdkError] [Throws=BdkError]
void sync([ByRef] Blockchain blockchain, Progress? progress); void sync([ByRef] Blockchain blockchain, Progress? progress);
[Throws=BdkError]
sequence<LocalUtxo> list_unspent();
}; };
interface FeeRate { interface FeeRate {
@@ -358,7 +362,7 @@ interface TxBuilder {
interface BumpFeeTxBuilder { interface BumpFeeTxBuilder {
constructor(string txid, float new_fee_rate); constructor(string txid, float new_fee_rate);
BumpFeeTxBuilder allow_shrinking(string address); BumpFeeTxBuilder allow_shrinking(Script script_pubkey);
BumpFeeTxBuilder enable_rbf(); BumpFeeTxBuilder enable_rbf();
@@ -439,6 +443,12 @@ interface Descriptor {
[Name=new_bip84_public] [Name=new_bip84_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network); constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
[Name=new_bip86]
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
[Name=new_bip86_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
string as_string(); string as_string();
string as_string_private(); string as_string_private();
@@ -446,7 +456,7 @@ interface Descriptor {
interface Address { interface Address {
[Throws=BdkError] [Throws=BdkError]
constructor(string address); constructor(string address, Network network);
[Name=from_script, Throws=BdkError] [Name=from_script, Throws=BdkError]
constructor(Script script, Network network); constructor(Script script, Network network);
@@ -459,14 +469,16 @@ interface Address {
string to_qr_uri(); string to_qr_uri();
boolean is_valid_for_network(Network network);
string as_string(); string as_string();
}; };
[Enum] [Enum]
interface Payload { interface Payload {
PubkeyHash(sequence<u8> pubkey_hash); PubkeyHash(string pubkey_hash);
ScriptHash(sequence<u8> script_hash); ScriptHash(string script_hash);
WitnessProgram(WitnessVersion version, sequence<u8> program); WitnessProgram(WitnessVersion version, sequence<u8> program);
}; };
@@ -493,4 +505,6 @@ enum WitnessVersion {
interface Script { interface Script {
constructor(sequence<u8> raw_output_script); constructor(sequence<u8> raw_output_script);
sequence<u8> to_bytes();
}; };

View File

@@ -1,6 +1,6 @@
// use crate::BlockchainConfig; // use crate::BlockchainConfig;
use crate::Network;
use crate::{BdkError, Transaction}; use crate::{BdkError, Transaction};
use bdk::bitcoin::Network;
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
use bdk::blockchain::rpc::Auth as BdkAuth; use bdk::blockchain::rpc::Auth as BdkAuth;
use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams; use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams;
@@ -17,7 +17,7 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
pub(crate) struct Blockchain { pub(crate) struct Blockchain {
blockchain_mutex: Mutex<AnyBlockchain>, inner_mutex: Mutex<AnyBlockchain>,
} }
impl Blockchain { impl Blockchain {
@@ -45,23 +45,23 @@ impl Blockchain {
BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig { BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
url: config.url, url: config.url,
auth: config.auth.into(), auth: config.auth.into(),
network: config.network, network: config.network.into(),
wallet_name: config.wallet_name, wallet_name: config.wallet_name,
sync_params: config.sync_params.map(|p| p.into()), sync_params: config.sync_params.map(|p| p.into()),
}), }),
}; };
let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
Ok(Self { Ok(Self {
blockchain_mutex: Mutex::new(blockchain), inner_mutex: Mutex::new(blockchain),
}) })
} }
pub(crate) fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> { pub(crate) fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> {
self.blockchain_mutex.lock().expect("blockchain") self.inner_mutex.lock().expect("blockchain")
} }
pub(crate) fn broadcast(&self, transaction: &Transaction) -> Result<(), BdkError> { pub(crate) fn broadcast(&self, transaction: &Transaction) -> Result<(), BdkError> {
let tx = &transaction.internal; let tx = &transaction.inner;
self.get_blockchain().broadcast(tx) self.get_blockchain().broadcast(tx)
} }

View File

@@ -1,16 +1,17 @@
use crate::Network;
use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey}; use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey};
use bdk::bitcoin::bip32::Fingerprint;
use bdk::bitcoin::secp256k1::Secp256k1; use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::bitcoin::util::bip32::Fingerprint; use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
use bdk::bitcoin::Network;
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
use bdk::keys::{ use bdk::keys::{
DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey, DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey,
KeyMap,
}; };
use bdk::template::{ use bdk::template::{
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, DescriptorTemplate, Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public,
DescriptorTemplate,
}; };
use bdk::KeychainKind; use bdk::KeychainKind;
use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
@@ -23,7 +24,8 @@ pub(crate) struct Descriptor {
impl Descriptor { impl Descriptor {
pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, BdkError> { pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, BdkError> {
let secp = Secp256k1::new(); 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 { Ok(Self {
extended_descriptor, extended_descriptor,
key_map, key_map,
@@ -35,13 +37,14 @@ impl Descriptor {
keychain_kind: KeychainKind, keychain_kind: KeychainKind,
network: Network, network: Network,
) -> Self { ) -> Self {
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap(); let derivable_key = &secret_key.inner;
match derivable_key.deref() { match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey; let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind)
Bip44(derivable_key, keychain_kind).build(network).unwrap(); .build(network.into())
.unwrap();
Self { Self {
extended_descriptor, extended_descriptor,
key_map, key_map,
@@ -50,6 +53,9 @@ impl Descriptor {
BdkDescriptorSecretKey::Single(_) => { BdkDescriptorSecretKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
} }
} }
@@ -60,14 +66,14 @@ impl Descriptor {
network: Network, network: Network,
) -> Self { ) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap(); let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap(); let derivable_key = &public_key.inner;
match derivable_key.deref() { match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => { BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey; let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = let (extended_descriptor, key_map, _) =
Bip44Public(derivable_key, fingerprint, keychain_kind) Bip44Public(derivable_key, fingerprint, keychain_kind)
.build(network) .build(network.into())
.unwrap(); .unwrap();
Self { Self {
@@ -78,6 +84,9 @@ impl Descriptor {
BdkDescriptorPublicKey::Single(_) => { BdkDescriptorPublicKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
} }
} }
@@ -86,13 +95,14 @@ impl Descriptor {
keychain_kind: KeychainKind, keychain_kind: KeychainKind,
network: Network, network: Network,
) -> Self { ) -> Self {
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap(); let derivable_key = &secret_key.inner;
match derivable_key.deref() { match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey; let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind)
Bip49(derivable_key, keychain_kind).build(network).unwrap(); .build(network.into())
.unwrap();
Self { Self {
extended_descriptor, extended_descriptor,
key_map, key_map,
@@ -101,6 +111,9 @@ impl Descriptor {
BdkDescriptorSecretKey::Single(_) => { BdkDescriptorSecretKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
} }
} }
@@ -111,14 +124,14 @@ impl Descriptor {
network: Network, network: Network,
) -> Self { ) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap(); let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap(); let derivable_key = &public_key.inner;
match derivable_key.deref() { match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => { BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey; let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = let (extended_descriptor, key_map, _) =
Bip49Public(derivable_key, fingerprint, keychain_kind) Bip49Public(derivable_key, fingerprint, keychain_kind)
.build(network) .build(network.into())
.unwrap(); .unwrap();
Self { Self {
@@ -129,6 +142,9 @@ impl Descriptor {
BdkDescriptorPublicKey::Single(_) => { BdkDescriptorPublicKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
} }
} }
@@ -137,13 +153,14 @@ impl Descriptor {
keychain_kind: KeychainKind, keychain_kind: KeychainKind,
network: Network, network: Network,
) -> Self { ) -> Self {
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap(); let derivable_key = &secret_key.inner;
match derivable_key.deref() { match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey; let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind)
Bip84(derivable_key, keychain_kind).build(network).unwrap(); .build(network.into())
.unwrap();
Self { Self {
extended_descriptor, extended_descriptor,
key_map, key_map,
@@ -152,6 +169,9 @@ impl Descriptor {
BdkDescriptorSecretKey::Single(_) => { BdkDescriptorSecretKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
} }
} }
@@ -162,14 +182,14 @@ impl Descriptor {
network: Network, network: Network,
) -> Self { ) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap(); let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap(); let derivable_key = &public_key.inner;
match derivable_key.deref() { match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => { BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey; let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = let (extended_descriptor, key_map, _) =
Bip84Public(derivable_key, fingerprint, keychain_kind) Bip84Public(derivable_key, fingerprint, keychain_kind)
.build(network) .build(network.into())
.unwrap(); .unwrap();
Self { Self {
@@ -180,6 +200,67 @@ impl Descriptor {
BdkDescriptorPublicKey::Single(_) => { BdkDescriptorPublicKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip86(
secret_key: Arc<DescriptorSecretKey>,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = &secret_key.inner;
match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = Bip86(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip86_public(
public_key: Arc<DescriptorPublicKey>,
fingerprint: String,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = &public_key.inner;
match derivable_key {
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.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
} }
} }
@@ -239,17 +320,27 @@ mod test {
.as_public(); .as_public();
println!("Public 84: {}", handmade_public_84.as_string()); println!("Public 84: {}", handmade_public_84.as_string());
// Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/* // Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/*
let handmade_public_86 = master
.derive(Arc::new(
DerivationPath::new("m/86h/1h/0h".to_string()).unwrap(),
))
.unwrap()
.as_public();
println!("Public 86: {}", handmade_public_86.as_string());
// Public 86: [d1d04177/86'/1'/0']tpubDCJzjbcGbdEfXMWaL6QmgVmuSfXkrue7m2YNoacWwyc7a2XjXaKojRqNEbo41CFL3PyYmKdhwg2fkGpLX4SQCbQjCGxAkWHJTw9WEeenrJb/*
let template_private_44 = let template_private_44 =
Descriptor::new_bip44(master.clone(), KeychainKind::External, Network::Testnet); Descriptor::new_bip44(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_49 = let template_private_49 =
Descriptor::new_bip49(master.clone(), KeychainKind::External, Network::Testnet); Descriptor::new_bip49(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_84 = let template_private_84 =
Descriptor::new_bip84(master, KeychainKind::External, Network::Testnet); Descriptor::new_bip84(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_86 =
Descriptor::new_bip86(master, KeychainKind::External, Network::Testnet);
// the extended public keys are the same when creating them manually as they are with the templates // the extended public keys are the same when creating them manually as they are with the templates
println!("Template 49: {}", template_private_49.as_string()); println!("Template 49: {}", template_private_49.as_string());
println!("Template 44: {}", template_private_44.as_string()); println!("Template 44: {}", template_private_44.as_string());
println!("Template 84: {}", template_private_84.as_string()); println!("Template 84: {}", template_private_84.as_string());
// for the public versions of the templates these are incorrect, bug report and fix in bitcoindevkit/bdk#817 and bitcoindevkit/bdk#818 println!("Template 86: {}", template_private_86.as_string());
let template_public_44 = Descriptor::new_bip44_public( let template_public_44 = Descriptor::new_bip44_public(
handmade_public_44, handmade_public_44,
"d1d04177".to_string(), "d1d04177".to_string(),
@@ -268,9 +359,16 @@ mod test {
KeychainKind::External, KeychainKind::External,
Network::Testnet, Network::Testnet,
); );
let template_public_86 = Descriptor::new_bip86_public(
handmade_public_86,
"d1d04177".to_string(),
KeychainKind::External,
Network::Testnet,
);
println!("Template public 49: {}", template_public_49.as_string()); println!("Template public 49: {}", template_public_49.as_string());
println!("Template public 44: {}", template_public_44.as_string()); println!("Template public 44: {}", template_public_44.as_string());
println!("Template public 84: {}", template_public_84.as_string()); println!("Template public 84: {}", template_public_84.as_string());
println!("Template public 86: {}", template_public_86.as_string());
// when using a public key, both as_string and as_string_private return the same string // when using a public key, both as_string and as_string_private return the same string
assert_eq!( assert_eq!(
template_public_44.as_string_private(), template_public_44.as_string_private(),
@@ -284,6 +382,10 @@ mod test {
template_public_84.as_string_private(), template_public_84.as_string_private(),
template_public_84.as_string() template_public_84.as_string()
); );
assert_eq!(
template_public_86.as_string_private(),
template_public_86.as_string()
);
// when using as_string on a private key, we get the same result as when using it on a public key // when using as_string on a private key, we get the same result as when using it on a public key
assert_eq!( assert_eq!(
template_private_44.as_string(), template_private_44.as_string(),
@@ -297,6 +399,10 @@ mod test {
template_private_84.as_string(), template_private_84.as_string(),
template_public_84.as_string() template_public_84.as_string()
); );
assert_eq!(
template_private_86.as_string(),
template_public_86.as_string()
);
} }
#[test] #[test]
fn test_descriptor_from_string() { fn test_descriptor_from_string() {

View File

@@ -1,14 +1,14 @@
use crate::BdkError; use crate::BdkError;
use crate::Network;
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::secp256k1::Secp256k1; 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::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
use bdk::keys::{ use bdk::keys::{
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey, DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey, DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
}; };
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
use bdk::miniscript::BareCtx; use bdk::miniscript::BareCtx;
use std::ops::Deref; use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
@@ -17,7 +17,7 @@ use std::sync::{Arc, Mutex};
/// Mnemonic phrases are a human-readable version of the private keys. /// Mnemonic phrases are a human-readable version of the private keys.
/// Supported number of words are 12, 15, 18, 21 and 24. /// Supported number of words are 12, 15, 18, 21 and 24.
pub(crate) struct Mnemonic { pub(crate) struct Mnemonic {
internal: BdkMnemonic, inner: BdkMnemonic,
} }
impl Mnemonic { impl Mnemonic {
@@ -26,13 +26,13 @@ impl Mnemonic {
let generated_key: GeneratedKey<_, BareCtx> = let generated_key: GeneratedKey<_, BareCtx> =
BdkMnemonic::generate((word_count, Language::English)).unwrap(); BdkMnemonic::generate((word_count, Language::English)).unwrap();
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap(); let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap();
Mnemonic { internal: mnemonic } Mnemonic { inner: mnemonic }
} }
/// Parse a Mnemonic with given string /// Parse a Mnemonic with given string
pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> { pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> {
BdkMnemonic::from_str(&mnemonic) BdkMnemonic::from_str(&mnemonic)
.map(|m| Mnemonic { internal: m }) .map(|m| Mnemonic { inner: m })
.map_err(|e| BdkError::Generic(e.to_string())) .map_err(|e| BdkError::Generic(e.to_string()))
} }
@@ -40,25 +40,25 @@ impl Mnemonic {
/// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length. /// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.
pub(crate) fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> { pub(crate) fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
BdkMnemonic::from_entropy(entropy.as_slice()) BdkMnemonic::from_entropy(entropy.as_slice())
.map(|m| Mnemonic { internal: m }) .map(|m| Mnemonic { inner: m })
.map_err(|e| BdkError::Generic(e.to_string())) .map_err(|e| BdkError::Generic(e.to_string()))
} }
/// Returns Mnemonic as string /// Returns Mnemonic as string
pub(crate) fn as_string(&self) -> String { pub(crate) fn as_string(&self) -> String {
self.internal.to_string() self.inner.to_string()
} }
} }
pub(crate) struct DerivationPath { pub(crate) struct DerivationPath {
derivation_path_mutex: Mutex<BdkDerivationPath>, inner_mutex: Mutex<BdkDerivationPath>,
} }
impl DerivationPath { impl DerivationPath {
pub(crate) fn new(path: String) -> Result<Self, BdkError> { pub(crate) fn new(path: String) -> Result<Self, BdkError> {
BdkDerivationPath::from_str(&path) BdkDerivationPath::from_str(&path)
.map(|x| DerivationPath { .map(|x| DerivationPath {
derivation_path_mutex: Mutex::new(x), inner_mutex: Mutex::new(x),
}) })
.map_err(|e| BdkError::Generic(e.to_string())) .map_err(|e| BdkError::Generic(e.to_string()))
} }
@@ -66,21 +66,21 @@ impl DerivationPath {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct DescriptorSecretKey { pub(crate) struct DescriptorSecretKey {
pub(crate) descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>, pub(crate) inner: BdkDescriptorSecretKey,
} }
impl DescriptorSecretKey { impl DescriptorSecretKey {
pub(crate) fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self { pub(crate) fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
let mnemonic = mnemonic.internal.clone(); let mnemonic = mnemonic.inner.clone();
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap(); let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey { let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: None, origin: None,
xkey: xkey.into_xprv(network).unwrap(), xkey: xkey.into_xprv(network.into()).unwrap(),
derivation_path: BdkDerivationPath::master(), derivation_path: BdkDerivationPath::master(),
wildcard: bdk::descriptor::Wildcard::Unhardened, wildcard: Wildcard::Unhardened,
}); });
Self { Self {
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key), inner: descriptor_secret_key,
} }
} }
@@ -88,15 +88,15 @@ impl DescriptorSecretKey {
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str()) let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
.map_err(|e| BdkError::Generic(e.to_string()))?; .map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Self { Ok(Self {
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key), inner: descriptor_secret_key,
}) })
} }
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> { pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap(); let descriptor_secret_key = &self.inner;
let path = path.derivation_path_mutex.lock().unwrap().deref().clone(); let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key.deref() { match descriptor_secret_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?; let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() { let key_source = match descriptor_x_key.origin.clone() {
@@ -110,19 +110,22 @@ impl DescriptorSecretKey {
wildcard: descriptor_x_key.wildcard, wildcard: descriptor_x_key.wildcard,
}); });
Ok(Arc::new(Self { Ok(Arc::new(Self {
descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key), inner: derived_descriptor_secret_key,
})) }))
} }
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic( BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
"Cannot derive from a single key".to_string(), "Cannot derive from a single key".to_string(),
)), )),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic(
"Cannot derive from a multi key".to_string(),
)),
} }
} }
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> { pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap(); let descriptor_secret_key = &self.inner;
let path = path.derivation_path_mutex.lock().unwrap().deref().clone(); let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key.deref() { match descriptor_secret_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path); let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey { let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
@@ -132,51 +135,52 @@ impl DescriptorSecretKey {
wildcard: descriptor_x_key.wildcard, wildcard: descriptor_x_key.wildcard,
}); });
Ok(Arc::new(Self { Ok(Arc::new(Self {
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key), inner: extended_descriptor_secret_key,
})) }))
} }
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic( BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
"Cannot extend from a single key".to_string(), "Cannot extend from a single key".to_string(),
)), )),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic(
"Cannot extend from a multi key".to_string(),
)),
} }
} }
pub(crate) fn as_public(&self) -> Arc<DescriptorPublicKey> { pub(crate) fn as_public(&self) -> Arc<DescriptorPublicKey> {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let descriptor_public_key = self let descriptor_public_key = self.inner.to_public(&secp).unwrap();
.descriptor_secret_key_mutex
.lock()
.unwrap()
.to_public(&secp)
.unwrap();
Arc::new(DescriptorPublicKey { Arc::new(DescriptorPublicKey {
descriptor_public_key_mutex: Mutex::new(descriptor_public_key), inner: descriptor_public_key,
}) })
} }
/// Get the private key as bytes. /// Get the private key as bytes.
pub(crate) fn secret_bytes(&self) -> Vec<u8> { pub(crate) fn secret_bytes(&self) -> Vec<u8> {
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap(); let inner = &self.inner;
let secret_bytes: Vec<u8> = match descriptor_secret_key.deref() { let secret_bytes: Vec<u8> = match inner {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => { BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
descriptor_x_key.xkey.private_key.secret_bytes().to_vec() descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
} }
BdkDescriptorSecretKey::Single(_) => { BdkDescriptorSecretKey::Single(_) => {
unreachable!() unreachable!()
} }
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}; };
secret_bytes secret_bytes
} }
pub(crate) fn as_string(&self) -> String { pub(crate) fn as_string(&self) -> String {
self.descriptor_secret_key_mutex.lock().unwrap().to_string() self.inner.to_string()
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct DescriptorPublicKey { pub(crate) struct DescriptorPublicKey {
pub(crate) descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>, pub(crate) inner: BdkDescriptorPublicKey,
} }
impl DescriptorPublicKey { impl DescriptorPublicKey {
@@ -184,16 +188,16 @@ impl DescriptorPublicKey {
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str()) let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
.map_err(|e| BdkError::Generic(e.to_string()))?; .map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Self { Ok(Self {
descriptor_public_key_mutex: Mutex::new(descriptor_public_key), inner: descriptor_public_key,
}) })
} }
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> { pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap(); let descriptor_public_key = &self.inner;
let path = path.derivation_path_mutex.lock().unwrap().deref().clone(); let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key.deref() { match descriptor_public_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => { BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?; let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() { let key_source = match descriptor_x_key.origin.clone() {
@@ -207,19 +211,22 @@ impl DescriptorPublicKey {
wildcard: descriptor_x_key.wildcard, wildcard: descriptor_x_key.wildcard,
}); });
Ok(Arc::new(Self { Ok(Arc::new(Self {
descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key), inner: derived_descriptor_public_key,
})) }))
} }
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic( BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
"Cannot derive from a single key".to_string(), "Cannot derive from a single key".to_string(),
)), )),
BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic(
"Cannot derive from a multi key".to_string(),
)),
} }
} }
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> { pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap(); let descriptor_public_key = &self.inner;
let path = path.derivation_path_mutex.lock().unwrap().deref().clone(); let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key.deref() { match descriptor_public_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => { BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path); let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey { let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
@@ -229,17 +236,20 @@ impl DescriptorPublicKey {
wildcard: descriptor_x_key.wildcard, wildcard: descriptor_x_key.wildcard,
}); });
Ok(Arc::new(Self { Ok(Arc::new(Self {
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key), inner: extended_descriptor_public_key,
})) }))
} }
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic( BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
"Cannot extend from a single key".to_string(), "Cannot extend from a single key".to_string(),
)), )),
BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic(
"Cannot extend from a multi key".to_string(),
)),
} }
} }
pub(crate) fn as_string(&self) -> String { pub(crate) fn as_string(&self) -> String {
self.descriptor_public_key_mutex.lock().unwrap().to_string() self.inner.to_string()
} }
} }
@@ -250,11 +260,10 @@ impl DescriptorPublicKey {
mod test { mod test {
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic}; use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::BdkError; use crate::BdkError;
use bdk::bitcoin::hashes::hex::ToHex; use crate::Network;
use bdk::bitcoin::Network;
use std::sync::Arc; use std::sync::Arc;
fn get_descriptor_secret_key() -> DescriptorSecretKey { 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(); 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, Arc::new(mnemonic), None)
} }
@@ -293,14 +302,14 @@ mod test {
#[test] #[test]
fn test_generate_descriptor_secret_key() { fn test_generate_descriptor_secret_key() {
let master_dsk = get_descriptor_secret_key(); let master_dsk = get_inner();
assert_eq!(master_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*"); assert_eq!(master_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*"); assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
} }
#[test] #[test]
fn test_derive_self() { fn test_derive_self() {
let master_dsk = get_descriptor_secret_key(); let master_dsk = get_inner();
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m").unwrap(); let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*"); assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public(); let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
@@ -310,7 +319,7 @@ mod test {
#[test] #[test]
fn test_derive_descriptors_keys() { fn test_derive_descriptors_keys() {
let master_dsk = get_descriptor_secret_key(); let master_dsk = get_inner();
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap(); let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*"); assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public(); let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
@@ -320,7 +329,7 @@ mod test {
#[test] #[test]
fn test_extend_descriptor_keys() { fn test_extend_descriptor_keys() {
let master_dsk = get_descriptor_secret_key(); let master_dsk = get_inner();
let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap(); let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*"); assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public(); let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
@@ -334,7 +343,7 @@ mod test {
} }
#[test] #[test]
fn test_from_str_descriptor_secret_key() { fn test_from_str_inner() {
let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch"; let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*"; let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*";
let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap(); let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap();
@@ -347,8 +356,8 @@ mod test {
} }
#[test] #[test]
fn test_derive_and_extend_descriptor_secret_key() { fn test_derive_and_extend_inner() {
let master_dsk = get_descriptor_secret_key(); let master_dsk = get_inner();
// derive DescriptorSecretKey with path "m/0" from master // derive DescriptorSecretKey with path "m/0" from master
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap(); let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*"); assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
@@ -359,18 +368,8 @@ mod test {
#[test] #[test]
fn test_derive_hardened_path_using_public() { fn test_derive_hardened_path_using_public() {
let master_dpk = get_descriptor_secret_key().as_public(); let master_dpk = get_inner().as_public();
let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h"); let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h");
assert!(derived_dpk.is_err()); assert!(derived_dpk.is_err());
} }
#[test]
fn test_retrieve_master_secret_key() {
let master_dpk = get_descriptor_secret_key();
let master_private_key = master_dpk.secret_bytes().to_hex();
assert_eq!(
master_private_key,
"e93315d6ce401eb4db803a56232f0ed3e69b053774e6047df54f1bd00e5ea936"
)
}
} }

View File

@@ -15,17 +15,19 @@ use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::psbt::PartiallySignedTransaction; use crate::psbt::PartiallySignedTransaction;
use crate::wallet::SignOptions; use crate::wallet::SignOptions;
use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet}; use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet};
use bdk::bitcoin::blockdata::script::Script as BdkScript; use bdk::bitcoin::address::{NetworkUnchecked, Payload as BdkPayload, WitnessVersion};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn; use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn;
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut; use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
use bdk::bitcoin::consensus::encode::serialize;
use bdk::bitcoin::consensus::Decodable; use bdk::bitcoin::consensus::Decodable;
use bdk::bitcoin::psbt::serialize::Serialize; use bdk::bitcoin::network::constants::Network as BdkNetwork;
use bdk::bitcoin::util::address::{Payload as BdkPayload, WitnessVersion};
use bdk::bitcoin::{ use bdk::bitcoin::{
Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid, Address as BdkAddress, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid,
}; };
use bdk::blockchain::Progress as BdkProgress; use bdk::blockchain::Progress as BdkProgress;
use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration}; use bdk::database::any::SledDbConfiguration;
use bdk::database::any::SqliteDbConfiguration;
use bdk::keys::bip39::WordCount; use bdk::keys::bip39::WordCount;
use bdk::wallet::AddressIndex as BdkAddressIndex; use bdk::wallet::AddressIndex as BdkAddressIndex;
use bdk::wallet::AddressInfo as BdkAddressInfo; use bdk::wallet::AddressInfo as BdkAddressInfo;
@@ -41,6 +43,26 @@ use std::sync::Arc;
uniffi::include_scaffolding!("bdk"); uniffi::include_scaffolding!("bdk");
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Script(pub(crate) BdkScriptBuf);
impl Script {
pub fn new(raw_output_script: Vec<u8>) -> Self {
let script: BdkScriptBuf = raw_output_script.into();
Script(script)
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes()
}
}
impl From<BdkScriptBuf> for Script {
fn from(script: BdkScriptBuf) -> Self {
Script(script)
}
}
/// A output script and an amount of satoshis. /// A output script and an amount of satoshis.
pub struct ScriptAmount { pub struct ScriptAmount {
pub script: Arc<Script>, pub script: Arc<Script>,
@@ -202,9 +224,7 @@ impl From<&BdkTxOut> for TxOut {
fn from(tx_out: &BdkTxOut) -> Self { fn from(tx_out: &BdkTxOut) -> Self {
TxOut { TxOut {
value: tx_out.value, value: tx_out.value,
script_pubkey: Arc::new(Script { script_pubkey: Arc::new(Script(tx_out.script_pubkey.clone())),
script: tx_out.script_pubkey.clone(),
}),
} }
} }
} }
@@ -225,9 +245,7 @@ impl From<BdkLocalUtxo> for LocalUtxo {
}, },
txout: TxOut { txout: TxOut {
value: local_utxo.txout.value, value: local_utxo.txout.value,
script_pubkey: Arc::new(Script { script_pubkey: Arc::new(Script(local_utxo.txout.script_pubkey)),
script: local_utxo.txout.script_pubkey,
}),
}, },
keychain: local_utxo.keychain, keychain: local_utxo.keychain,
is_spent: local_utxo.is_spent, is_spent: local_utxo.is_spent,
@@ -274,9 +292,7 @@ impl From<&BdkTxIn> for TxIn {
txid: tx_in.previous_output.txid.to_string(), txid: tx_in.previous_output.txid.to_string(),
vout: tx_in.previous_output.vout, vout: tx_in.previous_output.vout,
}, },
script_sig: Arc::new(Script { script_sig: Arc::new(Script(tx_in.script_sig.clone())),
script: tx_in.script_sig.clone(),
}),
sequence: tx_in.sequence.0, sequence: tx_in.sequence.0,
witness: tx_in.witness.to_vec(), witness: tx_in.witness.to_vec(),
} }
@@ -286,128 +302,144 @@ impl From<&BdkTxIn> for TxIn {
/// A Bitcoin transaction. /// A Bitcoin transaction.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Transaction { pub struct Transaction {
internal: BdkTransaction, inner: BdkTransaction,
} }
impl Transaction { impl Transaction {
fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> { fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
let mut decoder = Cursor::new(transaction_bytes); let mut decoder = Cursor::new(transaction_bytes);
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?; let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
Ok(Transaction { internal: tx }) Ok(Transaction { inner: tx })
} }
fn txid(&self) -> String { fn txid(&self) -> String {
self.internal.txid().to_string() self.inner.txid().to_string()
} }
fn weight(&self) -> u64 { fn weight(&self) -> u64 {
self.internal.weight() as u64 self.inner.weight().to_wu()
} }
fn size(&self) -> u64 { fn size(&self) -> u64 {
self.internal.size() as u64 self.inner.size() as u64
} }
fn vsize(&self) -> u64 { fn vsize(&self) -> u64 {
self.internal.vsize() as u64 self.inner.vsize() as u64
} }
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
self.internal.serialize() serialize(&self.inner)
} }
fn is_coin_base(&self) -> bool { fn is_coin_base(&self) -> bool {
self.internal.is_coin_base() self.inner.is_coin_base()
} }
fn is_explicitly_rbf(&self) -> bool { fn is_explicitly_rbf(&self) -> bool {
self.internal.is_explicitly_rbf() self.inner.is_explicitly_rbf()
} }
fn is_lock_time_enabled(&self) -> bool { fn is_lock_time_enabled(&self) -> bool {
self.internal.is_lock_time_enabled() self.inner.is_lock_time_enabled()
} }
fn version(&self) -> i32 { fn version(&self) -> i32 {
self.internal.version self.inner.version
} }
fn lock_time(&self) -> u32 { fn lock_time(&self) -> u32 {
self.internal.lock_time.0 self.inner.lock_time.to_consensus_u32()
} }
fn input(&self) -> Vec<TxIn> { fn input(&self) -> Vec<TxIn> {
self.internal.input.iter().map(|x| x.into()).collect() self.inner.input.iter().map(|x| x.into()).collect()
} }
fn output(&self) -> Vec<TxOut> { fn output(&self) -> Vec<TxOut> {
self.internal.output.iter().map(|x| x.into()).collect() self.inner.output.iter().map(|x| x.into()).collect()
} }
} }
impl From<BdkTransaction> for Transaction { impl From<BdkTransaction> for Transaction {
fn from(tx: BdkTransaction) -> Self { fn from(tx: BdkTransaction) -> Self {
Transaction { internal: tx } Transaction { inner: tx }
} }
} }
/// A Bitcoin address. /// A Bitcoin address.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Address { pub struct Address {
address: BdkAddress, inner: BdkAddress,
} }
impl Address { impl Address {
fn new(address: String) -> Result<Self, BdkError> { pub fn new(address: String, network: Network) -> Result<Self, BdkError> {
BdkAddress::from_str(address.as_str()) let parsed_address = address
.map(|a| Address { address: a }) .parse::<bdk::bitcoin::Address<NetworkUnchecked>>()
.map_err(|e| BdkError::Generic(e.to_string())) .map_err(|e| BdkError::Generic(e.to_string()))?;
let network_checked_address = parsed_address
.require_network(network.into())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Address {
inner: network_checked_address,
})
} }
/// alternative constructor /// alternative constructor
fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> { fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
BdkAddress::from_script(&script.script, network) BdkAddress::from_script(&script.0, network.into())
.map(|a| Address { address: a }) .map(|a| Address { inner: a })
.map_err(|e| BdkError::Generic(e.to_string())) .map_err(|e| BdkError::Generic(e.to_string()))
} }
fn payload(&self) -> Payload { fn payload(&self) -> Payload {
match &self.address.payload.clone() { match &self.inner.payload.clone() {
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash { BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
pubkey_hash: pubkey_hash.to_vec(), pubkey_hash: pubkey_hash.to_string(),
}, },
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash { BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
script_hash: script_hash.to_vec(), script_hash: script_hash.to_string(),
}, },
BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram { BdkPayload::WitnessProgram(witness_program) => Payload::WitnessProgram {
version: *version, version: witness_program.version(),
program: program.clone(), program: Vec::from(witness_program.program().as_bytes()),
}, },
_ => panic!("Unsupported address payload type"),
} }
} }
fn network(&self) -> Network { fn network(&self) -> Network {
self.address.network self.inner.network.into()
} }
fn script_pubkey(&self) -> Arc<Script> { fn script_pubkey(&self) -> Arc<Script> {
Arc::new(Script { Arc::new(Script(self.inner.script_pubkey()))
script: self.address.script_pubkey(),
})
} }
fn to_qr_uri(&self) -> String { fn to_qr_uri(&self) -> String {
self.address.to_qr_uri() self.inner.to_qr_uri()
}
pub fn is_valid_for_network(&self, network: Network) -> bool {
let address_str = self.inner.to_string();
if let Ok(unchecked_address) = address_str.parse::<BdkAddress<NetworkUnchecked>>() {
unchecked_address.is_valid_for_network(network.into())
} else {
false
}
} }
fn as_string(&self) -> String { fn as_string(&self) -> String {
self.address.to_string() self.inner.to_string()
} }
} }
impl From<BdkAddress> for Address { impl From<BdkAddress> for Address {
fn from(address: BdkAddress) -> Self { fn from(address: BdkAddress) -> Self {
Address { address } Address { inner: address }
} }
} }
@@ -415,9 +447,9 @@ impl From<BdkAddress> for Address {
#[derive(Debug)] #[derive(Debug)]
pub enum Payload { pub enum Payload {
/// P2PKH address. /// P2PKH address.
PubkeyHash { pubkey_hash: Vec<u8> }, PubkeyHash { pubkey_hash: String },
/// P2SH address. /// P2SH address.
ScriptHash { script_hash: Vec<u8> }, ScriptHash { script_hash: String },
/// Segwit address. /// Segwit address.
WitnessProgram { WitnessProgram {
/// The witness program version. /// The witness program version.
@@ -427,25 +459,6 @@ pub enum Payload {
}, },
} }
/// A Bitcoin script.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Script {
script: BdkScript,
}
impl Script {
fn new(raw_output_script: Vec<u8>) -> Self {
let script: BdkScript = BdkScript::from(raw_output_script);
Script { script }
}
}
impl From<BdkScript> for Script {
fn from(bdk_script: BdkScript) -> Self {
Script { script: bdk_script }
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum RbfValue { enum RbfValue {
Default, Default,
@@ -459,6 +472,37 @@ pub struct TxBuilderResult {
pub transaction_details: TransactionDetails, pub transaction_details: TransactionDetails,
} }
#[derive(PartialEq, Debug)]
pub enum Network {
Bitcoin,
Testnet,
Signet,
Regtest,
}
impl From<Network> for BdkNetwork {
fn from(network: Network) -> Self {
match network {
Network::Bitcoin => BdkNetwork::Bitcoin,
Network::Testnet => BdkNetwork::Testnet,
Network::Signet => BdkNetwork::Signet,
Network::Regtest => BdkNetwork::Regtest,
}
}
}
impl From<BdkNetwork> for Network {
fn from(network: BdkNetwork) -> Self {
match network {
BdkNetwork::Bitcoin => Network::Bitcoin,
BdkNetwork::Testnet => Network::Testnet,
BdkNetwork::Signet => Network::Signet,
BdkNetwork::Regtest => Network::Regtest,
_ => panic!("Network {} not supported", network),
}
}
}
uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send); uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs. // The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
@@ -466,30 +510,33 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
// crate. // crate.
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::Transaction;
use crate::Network::Regtest; use crate::Network::Regtest;
use crate::{Address, Payload}; use crate::{Address, Payload};
use assert_matches::assert_matches; use assert_matches::assert_matches;
use bdk::bitcoin::address::WitnessVersion;
use bdk::bitcoin::hashes::hex::FromHex; use bdk::bitcoin::hashes::hex::FromHex;
use bdk::bitcoin::util::address::WitnessVersion; use bdk::bitcoin::Network;
// Verify that bdk-ffi Transaction can be created from valid bytes and serialized back into the same bytes. // Verify that bdk-ffi Transaction can be created from valid bytes and serialized back into the same bytes.
#[test] // #[test]
fn test_transaction_serde() { // fn test_transaction_serde() {
let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap(); // let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap();
let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap(); // let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap();
let serialized_tx_to_bytes = new_tx_from_bytes.serialize(); // let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
assert_eq!(test_tx_bytes, serialized_tx_to_bytes); // assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
} // }
// Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes. // Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes.
#[test] #[test]
fn test_address_witness_program() { fn test_address_witness_program() {
let address = let address = Address::new(
Address::new("bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string()).unwrap(); "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string(),
Network::Regtest.into(),
)
.unwrap();
let payload = address.payload(); let payload = address.payload();
assert_matches!(payload, Payload::WitnessProgram { version, program } => { assert_matches!(payload, Payload::WitnessProgram { version, program } => {
assert_eq!(version,WitnessVersion::V0); assert_eq!(version, WitnessVersion::V0);
assert_eq!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap()); assert_eq!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap());
}); });
assert_eq!(address.network(), Regtest); assert_eq!(address.network(), Regtest);

View File

@@ -1,5 +1,4 @@
use bdk::bitcoin::hashes::hex::ToHex; use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoincore_rpc::jsonrpc::serde_json; use bdk::bitcoincore_rpc::jsonrpc::serde_json;
use bdk::psbt::PsbtUtils; use bdk::psbt::PsbtUtils;
use std::ops::Deref; use std::ops::Deref;
@@ -10,7 +9,7 @@ use crate::{BdkError, FeeRate, Transaction};
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct PartiallySignedTransaction { pub(crate) struct PartiallySignedTransaction {
pub(crate) internal: Mutex<BdkPartiallySignedTransaction>, pub(crate) inner: Mutex<BdkPartiallySignedTransaction>,
} }
impl PartiallySignedTransaction { impl PartiallySignedTransaction {
@@ -18,24 +17,24 @@ impl PartiallySignedTransaction {
let psbt: BdkPartiallySignedTransaction = let psbt: BdkPartiallySignedTransaction =
BdkPartiallySignedTransaction::from_str(&psbt_base64)?; BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
Ok(PartiallySignedTransaction { Ok(PartiallySignedTransaction {
internal: Mutex::new(psbt), inner: Mutex::new(psbt),
}) })
} }
pub(crate) fn serialize(&self) -> String { pub(crate) fn serialize(&self) -> String {
let psbt = self.internal.lock().unwrap().clone(); let psbt = self.inner.lock().unwrap().clone();
psbt.to_string() psbt.to_string()
} }
pub(crate) fn txid(&self) -> String { pub(crate) fn txid(&self) -> String {
let tx = self.internal.lock().unwrap().clone().extract_tx(); let tx = self.inner.lock().unwrap().clone().extract_tx();
let txid = tx.txid(); let txid = tx.txid();
txid.to_hex() txid.to_string()
} }
/// Return the transaction. /// Return the transaction.
pub(crate) fn extract_tx(&self) -> Arc<Transaction> { pub(crate) fn extract_tx(&self) -> Arc<Transaction> {
let tx = self.internal.lock().unwrap().clone().extract_tx(); let tx = self.inner.lock().unwrap().clone().extract_tx();
Arc::new(tx.into()) Arc::new(tx.into())
} }
@@ -46,19 +45,19 @@ impl PartiallySignedTransaction {
&self, &self,
other: Arc<PartiallySignedTransaction>, other: Arc<PartiallySignedTransaction>,
) -> Result<Arc<PartiallySignedTransaction>, BdkError> { ) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
let other_psbt = other.internal.lock().unwrap().clone(); let other_psbt = other.inner.lock().unwrap().clone();
let mut original_psbt = self.internal.lock().unwrap().clone(); let mut original_psbt = self.inner.lock().unwrap().clone();
original_psbt.combine(other_psbt)?; original_psbt.combine(other_psbt)?;
Ok(Arc::new(PartiallySignedTransaction { Ok(Arc::new(PartiallySignedTransaction {
internal: Mutex::new(original_psbt), inner: Mutex::new(original_psbt),
})) }))
} }
/// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats. /// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
/// If the PSBT is missing a TxOut for an input returns None. /// If the PSBT is missing a TxOut for an input returns None.
pub(crate) fn fee_amount(&self) -> Option<u64> { pub(crate) fn fee_amount(&self) -> Option<u64> {
self.internal.lock().unwrap().fee_amount() self.inner.lock().unwrap().fee_amount()
} }
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the /// The transaction's fee rate. This value will only be accurate if calculated AFTER the
@@ -66,12 +65,12 @@ impl PartiallySignedTransaction {
/// transaction. /// transaction.
/// If the PSBT is missing a TxOut for an input returns None. /// If the PSBT is missing a TxOut for an input returns None.
pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> { pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> {
self.internal.lock().unwrap().fee_rate().map(Arc::new) self.inner.lock().unwrap().fee_rate().map(Arc::new)
} }
/// Serialize the PSBT data structure as a String of JSON. /// Serialize the PSBT data structure as a String of JSON.
pub(crate) fn json_serialize(&self) -> String { pub(crate) fn json_serialize(&self) -> String {
let psbt = self.internal.lock().unwrap(); let psbt = self.inner.lock().unwrap();
serde_json::to_string(psbt.deref()).unwrap() serde_json::to_string(psbt.deref()).unwrap()
} }
} }
@@ -82,6 +81,7 @@ impl PartiallySignedTransaction {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::wallet::{TxBuilder, Wallet}; use crate::wallet::{TxBuilder, Wallet};
use crate::Network;
use bdk::wallet::get_funded_wallet; use bdk::wallet::get_funded_wallet;
use std::sync::Mutex; use std::sync::Mutex;
@@ -90,10 +90,10 @@ mod test {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"; let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh); let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet { let test_wallet = Wallet {
wallet_mutex: Mutex::new(funded_wallet), inner_mutex: Mutex::new(funded_wallet),
}; };
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string(); let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let drain_to_script = crate::Address::new(drain_to_address) let drain_to_script = crate::Address::new(drain_to_address, Network::Testnet)
.unwrap() .unwrap()
.script_pubkey(); .script_pubkey();
@@ -103,7 +103,7 @@ mod test {
.drain_to(drain_to_script.clone()); .drain_to(drain_to_script.clone());
//dbg!(&tx_builder); //dbg!(&tx_builder);
assert!(tx_builder.drain_wallet); assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_script.script.clone())); assert_eq!(tx_builder.drain_to, Some(drain_to_script.0.clone()));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap(); let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();

View File

@@ -1,5 +1,6 @@
use bdk::bitcoin::blockdata::script::Script as BdkScript; use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Sequence, Txid}; use bdk::bitcoin::script::PushBytesBuf;
use bdk::bitcoin::{OutPoint as BdkOutPoint, Sequence, Txid};
use bdk::database::any::AnyDatabase; use bdk::database::any::AnyDatabase;
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
use bdk::wallet::tx_builder::ChangeSpendPolicy; use bdk::wallet::tx_builder::ChangeSpendPolicy;
@@ -8,6 +9,7 @@ use bdk::{
SyncOptions as BdkSyncOptions, Wallet as BdkWallet, SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
}; };
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::TryFrom;
use std::ops::Deref; use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
@@ -16,6 +18,7 @@ use crate::blockchain::Blockchain;
use crate::database::DatabaseConfig; use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor; use crate::descriptor::Descriptor;
use crate::psbt::PartiallySignedTransaction; use crate::psbt::PartiallySignedTransaction;
use crate::Network;
use crate::{ use crate::{
AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder, AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder,
RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult, RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult,
@@ -23,7 +26,7 @@ use crate::{
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Wallet { pub(crate) struct Wallet {
pub(crate) wallet_mutex: Mutex<BdkWallet<AnyDatabase>>, pub(crate) inner_mutex: Mutex<BdkWallet<AnyDatabase>>,
} }
/// A Bitcoin wallet. /// A Bitcoin wallet.
@@ -50,19 +53,26 @@ impl Wallet {
let wallet_mutex = Mutex::new(BdkWallet::new( let wallet_mutex = Mutex::new(BdkWallet::new(
&descriptor, &descriptor,
change_descriptor.as_ref(), change_descriptor.as_ref(),
network, network.into(),
database, database,
)?); )?);
Ok(Wallet { wallet_mutex }) Ok(Wallet {
inner_mutex: wallet_mutex,
})
} }
pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> { pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> {
self.wallet_mutex.lock().expect("wallet") self.inner_mutex.lock().expect("wallet")
} }
/// Get the Bitcoin network the wallet is using. /// Get the Bitcoin network the wallet is using.
pub(crate) fn network(&self) -> Network { pub(crate) fn network(&self) -> Network {
self.get_wallet().network() self.get_wallet().network().into()
}
/// Return whether or not a script is part of this wallet (either internal or external).
pub(crate) fn is_mine(&self, script: Arc<Script>) -> Result<bool, BdkError> {
self.get_wallet().is_mine(&script.0)
} }
/// Sync the internal database with the blockchain. /// Sync the internal database with the blockchain.
@@ -126,7 +136,7 @@ impl Wallet {
psbt: &PartiallySignedTransaction, psbt: &PartiallySignedTransaction,
sign_options: Option<SignOptions>, sign_options: Option<SignOptions>,
) -> Result<bool, BdkError> { ) -> Result<bool, BdkError> {
let mut psbt = psbt.internal.lock().unwrap(); let mut psbt = psbt.inner.lock().unwrap();
self.get_wallet().sign( self.get_wallet().sign(
&mut psbt, &mut psbt,
sign_options.map(SignOptions::into).unwrap_or_default(), sign_options.map(SignOptions::into).unwrap_or_default(),
@@ -233,7 +243,7 @@ impl From<SignOptions> for BdkSignOptions {
/// Each method on the TxBuilder returns an instance of a new TxBuilder with the option set/added. /// Each method on the TxBuilder returns an instance of a new TxBuilder with the option set/added.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct TxBuilder { pub(crate) struct TxBuilder {
pub(crate) recipients: Vec<(BdkScript, u64)>, pub(crate) recipients: Vec<(BdkScriptBuf, u64)>,
pub(crate) utxos: Vec<OutPoint>, pub(crate) utxos: Vec<OutPoint>,
pub(crate) unspendable: HashSet<OutPoint>, pub(crate) unspendable: HashSet<OutPoint>,
pub(crate) change_policy: ChangeSpendPolicy, pub(crate) change_policy: ChangeSpendPolicy,
@@ -241,7 +251,7 @@ pub(crate) struct TxBuilder {
pub(crate) fee_rate: Option<f32>, pub(crate) fee_rate: Option<f32>,
pub(crate) fee_absolute: Option<u64>, pub(crate) fee_absolute: Option<u64>,
pub(crate) drain_wallet: bool, pub(crate) drain_wallet: bool,
pub(crate) drain_to: Option<BdkScript>, pub(crate) drain_to: Option<BdkScriptBuf>,
pub(crate) rbf: Option<RbfValue>, pub(crate) rbf: Option<RbfValue>,
pub(crate) data: Vec<u8>, pub(crate) data: Vec<u8>,
} }
@@ -265,8 +275,8 @@ impl TxBuilder {
/// Add a recipient to the internal list. /// Add a recipient to the internal list.
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> { pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
let mut recipients: Vec<(BdkScript, u64)> = self.recipients.clone(); let mut recipients: Vec<(BdkScriptBuf, u64)> = self.recipients.clone();
recipients.append(&mut vec![(script.script.clone(), amount)]); recipients.append(&mut vec![(script.0.clone(), amount)]);
Arc::new(TxBuilder { Arc::new(TxBuilder {
recipients, recipients,
..self.clone() ..self.clone()
@@ -276,7 +286,7 @@ impl TxBuilder {
pub(crate) fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> { pub(crate) fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> {
let recipients = recipients let recipients = recipients
.iter() .iter()
.map(|script_amount| (script_amount.script.script.clone(), script_amount.amount)) .map(|script_amount| (script_amount.script.0.clone(), script_amount.amount))
.collect(); .collect();
Arc::new(TxBuilder { Arc::new(TxBuilder {
recipients, recipients,
@@ -381,7 +391,7 @@ impl TxBuilder {
/// to allow this output to be reduced to pay for the extra fees. /// to allow this output to be reduced to pay for the extra fees.
pub(crate) fn drain_to(&self, script: Arc<Script>) -> Arc<Self> { pub(crate) fn drain_to(&self, script: Arc<Script>) -> Arc<Self> {
Arc::new(TxBuilder { Arc::new(TxBuilder {
drain_to: Some(script.script.clone()), drain_to: Some(script.0.clone()),
..self.clone() ..self.clone()
}) })
} }
@@ -456,14 +466,17 @@ impl TxBuilder {
} }
} }
if !&self.data.is_empty() { if !&self.data.is_empty() {
tx_builder.add_data(self.data.as_slice()); let push_bytes = PushBytesBuf::try_from(self.data.clone()).map_err(|_| {
BdkError::Generic("Failed to convert data to PushBytes".to_string())
})?;
tx_builder.add_data(&push_bytes);
} }
tx_builder tx_builder
.finish() .finish()
.map(|(psbt, tx_details)| TxBuilderResult { .map(|(psbt, tx_details)| TxBuilderResult {
psbt: Arc::new(PartiallySignedTransaction { psbt: Arc::new(PartiallySignedTransaction {
internal: Mutex::new(psbt), inner: Mutex::new(psbt),
}), }),
transaction_details: TransactionDetails::from(tx_details), transaction_details: TransactionDetails::from(tx_details),
}) })
@@ -475,7 +488,7 @@ impl TxBuilder {
pub(crate) struct BumpFeeTxBuilder { pub(crate) struct BumpFeeTxBuilder {
pub(crate) txid: String, pub(crate) txid: String,
pub(crate) fee_rate: f32, pub(crate) fee_rate: f32,
pub(crate) allow_shrinking: Option<String>, pub(crate) allow_shrinking: Option<Arc<Script>>,
pub(crate) rbf: Option<RbfValue>, pub(crate) rbf: Option<RbfValue>,
} }
@@ -494,9 +507,9 @@ impl BumpFeeTxBuilder {
/// shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved /// shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved
/// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey /// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey
/// cant be found among the recipients of the transaction we are bumping. /// cant be found among the recipients of the transaction we are bumping.
pub(crate) fn allow_shrinking(&self, address: String) -> Arc<Self> { pub(crate) fn allow_shrinking(&self, script_pubkey: Arc<Script>) -> Arc<Self> {
Arc::new(Self { Arc::new(Self {
allow_shrinking: Some(address), allow_shrinking: Some(script_pubkey),
..self.clone() ..self.clone()
}) })
} }
@@ -529,10 +542,7 @@ impl BumpFeeTxBuilder {
let mut tx_builder = wallet.build_fee_bump(txid)?; let mut tx_builder = wallet.build_fee_bump(txid)?;
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate)); tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
if let Some(allow_shrinking) = &self.allow_shrinking { if let Some(allow_shrinking) = &self.allow_shrinking {
let address = BdkAddress::from_str(allow_shrinking) tx_builder.allow_shrinking(allow_shrinking.0.clone())?;
.map_err(|e| BdkError::Generic(e.to_string()))?;
let script = address.script_pubkey();
tx_builder.allow_shrinking(script)?;
} }
if let Some(rbf) = &self.rbf { if let Some(rbf) = &self.rbf {
match *rbf { match *rbf {
@@ -547,7 +557,7 @@ impl BumpFeeTxBuilder {
tx_builder tx_builder
.finish() .finish()
.map(|(psbt, _)| PartiallySignedTransaction { .map(|(psbt, _)| PartiallySignedTransaction {
internal: Mutex::new(psbt), inner: Mutex::new(psbt),
}) })
.map(Arc::new) .map(Arc::new)
} }
@@ -560,9 +570,14 @@ impl BumpFeeTxBuilder {
mod test { mod test {
use crate::database::DatabaseConfig; use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor; use crate::descriptor::Descriptor;
use crate::keys::{DescriptorSecretKey, Mnemonic};
use crate::wallet::{AddressIndex, TxBuilder, Wallet}; use crate::wallet::{AddressIndex, TxBuilder, Wallet};
use bdk::bitcoin::{Address, Network}; use crate::Network;
use crate::Script;
use assert_matches::assert_matches;
use bdk::bitcoin::Address;
use bdk::wallet::get_funded_wallet; use bdk::wallet::get_funded_wallet;
use bdk::KeychainKind;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@@ -571,20 +586,20 @@ mod test {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"; let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh); let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet { let test_wallet = Wallet {
wallet_mutex: Mutex::new(funded_wallet), inner_mutex: Mutex::new(funded_wallet),
}; };
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string(); let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let drain_to_script = crate::Address::new(drain_to_address) let drain_to_script = crate::Address::new(drain_to_address, Network::Testnet)
.unwrap() .unwrap()
.script_pubkey(); .script_pubkey();
let tx_builder = TxBuilder::new() let tx_builder = TxBuilder::new()
.drain_wallet() .drain_wallet()
.drain_to(drain_to_script.clone()); .drain_to(drain_to_script.clone());
assert!(tx_builder.drain_wallet); assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_script.script.clone())); assert_eq!(tx_builder.drain_to, Some(drain_to_script.0.clone()));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap(); let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
let psbt = tx_builder_result.psbt.internal.lock().unwrap().clone(); let psbt = tx_builder_result.psbt.inner.lock().unwrap().clone();
let tx_details = tx_builder_result.transaction_details; let tx_details = tx_builder_result.transaction_details;
// confirm one input with 50,000 sats // confirm one input with 50,000 sats
@@ -612,12 +627,14 @@ mod test {
.cloned() .cloned()
.unwrap() .unwrap()
.script_pubkey, .script_pubkey,
Network::Testnet, Network::Testnet.into(),
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
output_address, output_address,
Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt").unwrap() Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")
.unwrap()
.assume_checked()
); );
let output_value = psbt.unsigned_tx.output.get(0).cloned().unwrap().value; let output_value = psbt.unsigned_tx.output.get(0).cloned().unwrap().value;
assert_eq!(output_value, 49_890_u64); // input - fee assert_eq!(output_value, 49_890_u64); // input - fee
@@ -802,4 +819,47 @@ mod test {
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k" "bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
); );
} }
#[test]
fn test_is_mine() {
// is_mine should return true for addresses generated by the wallet
let mnemonic: 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();
let secret_key: DescriptorSecretKey =
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None);
let descriptor: Descriptor = Descriptor::new_bip84(
Arc::new(secret_key),
KeychainKind::External,
Network::Testnet,
);
let wallet: Wallet = Wallet::new(
Arc::new(descriptor),
None,
Network::Testnet,
DatabaseConfig::Memory,
)
.unwrap();
let address = wallet.get_address(AddressIndex::New).unwrap();
let script: Arc<Script> = address.address.script_pubkey();
let is_mine_1: bool = wallet.is_mine(script).unwrap();
assert!(is_mine_1);
// is_mine returns false when provided a script that is not in the wallet
let other_wpkh = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)";
let other_descriptor = Descriptor::new(other_wpkh.to_string(), Network::Testnet).unwrap();
let other_wallet = Wallet::new(
Arc::new(other_descriptor),
None,
Network::Testnet,
DatabaseConfig::Memory,
)
.unwrap();
let other_address = other_wallet.get_address(AddressIndex::New).unwrap();
let other_script: Arc<Script> = other_address.address.script_pubkey();
let is_mine_2: bool = wallet.is_mine(other_script).unwrap();
assert_matches!(is_mine_2, false);
}
} }

View File

@@ -1,4 +1,4 @@
# bdk-android # bdk-jvm
This project builds a .jar package for the JVM platform that provide Kotlin language bindings for the [`bdk`] library. The Kotlin language bindings are created by the `bdk-ffi` project which is included in the root of this repository. This project builds a .jar package for the JVM platform that provide Kotlin language bindings for the [`bdk`] library. The Kotlin language bindings are created by the `bdk-ffi` project which is included in the root of this repository.
## How to Use ## How to Use
@@ -25,8 +25,8 @@ val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8
val databaseConfig = DatabaseConfig.Memory val databaseConfig = DatabaseConfig.Memory
val blockchainConfig = BlockchainConfig.Electrum( val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true) ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true)
) )
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig) val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
val newAddress = wallet.getAddress(AddressIndex.LastUnused) val newAddress = wallet.getAddress(AddressIndex.LastUnused)
``` ```
@@ -38,32 +38,39 @@ repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} }
dependencies { dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>") implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>")
} }
``` ```
## Example Projects ## Example Projects
* [Tatooine Faucet](https://github.com/thunderbiscuit/tatooine) * [Tatooine Faucet](https://github.com/thunderbiscuit/tatooine)
## How to build ## How to build
_Note that Kotlin version `1.6.10` or later is required to build the library._ _Note that Kotlin version `1.6.10` or later is required to build the library._
1. Install JDK 11. It must be version 11 (not 17), otherwise it won't build. For example, with SDKMAN!:
1. Clone this repository. ```shell
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 11.0.19-tem
```
2. Install Rust (note that we are currently building using Rust 1.67.0):
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default 1.67.0
```
3. Clone this repository.
```shell ```shell
git clone https://github.com/bitcoindevkit/bdk-ffi git clone https://github.com/bitcoindevkit/bdk-ffi
``` ```
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions. 4. If building on macOS install required intel and m1 jvm targets
3. If building on macOS install required intel and m1 jvm targets
```sh ```sh
rustup target add x86_64-apple-darwin aarch64-apple-darwin rustup target add x86_64-apple-darwin aarch64-apple-darwin
``` ```
4. Build kotlin bindings 5. Build kotlin bindings
```sh ```sh
# build JVM library ./gradlew buildJvmLib
./gradlew buildJvmLib ```
```
## How to publish to your local Maven repo ## How to publish to your local Maven repo
```shell ```shell

View File

@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx1536m org.gradle.jvmargs=-Xmx1536m
android.enableJetifier=true android.enableJetifier=true
kotlin.code.style=official kotlin.code.style=official
libraryVersion=0.28.0 libraryVersion=0.31.1

View File

@@ -20,8 +20,8 @@ repositories {
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_11
withSourcesJar() withSourcesJar()
withJavadocJar() withJavadocJar()
} }
@@ -107,4 +107,8 @@ signing {
// binaries before running the tests // binaries before running the tests
tasks.withType<KotlinCompile> { tasks.withType<KotlinCompile> {
dependsOn("buildJvmLib") dependsOn("buildJvmLib")
kotlinOptions {
jvmTarget = "11"
}
} }

View File

@@ -4,11 +4,13 @@ package org.bitcoindevkit.plugins
val operatingSystem: OS = when { val operatingSystem: OS = when {
System.getProperty("os.name").contains("mac", ignoreCase = true) -> OS.MAC System.getProperty("os.name").contains("mac", ignoreCase = true) -> OS.MAC
System.getProperty("os.name").contains("linux", ignoreCase = true) -> OS.LINUX System.getProperty("os.name").contains("linux", ignoreCase = true) -> OS.LINUX
System.getProperty("os.name").contains("windows", ignoreCase = true) -> OS.WINDOWS
else -> OS.OTHER else -> OS.OTHER
} }
enum class OS { enum class OS {
MAC, MAC,
LINUX, LINUX,
WINDOWS,
OTHER, OTHER,
} }

View File

@@ -27,13 +27,20 @@ internal class UniFfiJvmPlugin : Plugin<Project> {
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-apple-darwin") val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-apple-darwin")
args(cargoArgs) args(cargoArgs)
} }
} else if(operatingSystem == OS.LINUX) { } else if (operatingSystem == OS.LINUX) {
exec { exec {
workingDir("${project.projectDir}/../../bdk-ffi") workingDir("${project.projectDir}/../../bdk-ffi")
executable("cargo") executable("cargo")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-unknown-linux-gnu") val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-unknown-linux-gnu")
args(cargoArgs) args(cargoArgs)
} }
} else if (operatingSystem == OS.WINDOWS) {
exec {
workingDir("${project.projectDir}/../../bdk-ffi")
executable("cargo")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-pc-windows-msvc")
args(cargoArgs)
}
} }
} }
@@ -70,13 +77,25 @@ internal class UniFfiJvmPlugin : Plugin<Project> {
ext = "so" ext = "so"
) )
) )
} else if (operatingSystem == OS.WINDOWS) {
libsToCopy.add(
CopyMetadata(
targetDir = "x86_64-pc-windows-msvc",
resDir = "win32-x86-64",
ext = "dll"
)
)
}
val libName = when (operatingSystem) {
OS.WINDOWS -> "bdkffi"
else -> "libbdkffi"
} }
libsToCopy.forEach { libsToCopy.forEach {
doFirst { doFirst {
copy { copy {
with(it) { with(it) {
from("${project.projectDir}/../../target/${this.targetDir}/release-smaller/libbdkffi.${this.ext}") from("${project.projectDir}/../../target/${this.targetDir}/release-smaller/${libName}.${this.ext}")
into("${project.projectDir}/../../bdk-jvm/lib/src/main/resources/${this.resDir}/") into("${project.projectDir}/../../bdk-jvm/lib/src/main/resources/${this.resDir}/")
} }
} }

View File

@@ -1,2 +1,3 @@
include ./src/bdkpython/libbdkffi.dylib include ./src/bdkpython/libbdkffi.dylib
include ./src/bdkpython/libbdkffi.so include ./src/bdkpython/libbdkffi.so
include ./src/bdkpython/bdkffi.dll

View File

@@ -12,9 +12,9 @@ pip install bdkpython
## Run the tests ## Run the tests
```shell ```shell
pip install --requirement requirements.txt pip install --requirement requirements.txt
bash ./generate.sh bash ./scripts/generate-linux.sh # here you should run the script appropriate for your platform
python setup.py bdist_wheel --verbose python setup.py bdist_wheel --verbose
pip install ./dist/bdkpython-<yourversion>-py3-none-any.whl --force-reinstall pip install ./dist/bdkpython-<yourversion>.whl --force-reinstall
python -m unittest --verbose tests/test_bdk.py python -m unittest --verbose tests/test_bdk.py
``` ```
@@ -23,26 +23,14 @@ python -m unittest --verbose tests/test_bdk.py
# Install dependencies # Install dependencies
pip install --requirement requirements.txt pip install --requirement requirements.txt
# Generate the bindings # Generate the bindings (use the script appropriate for your platform)
bash generate.sh bash ./scripts/generate-linux.sh
# Build the wheel # Build the wheel
python setup.py --verbose bdist_wheel python setup.py --verbose bdist_wheel
``` ```
## Run tox to build and test locally
```shell
# install dev requirements
pip install --requirement requirements-dev.txt
# build bindings glue code (located at ./src/bdkpython/bdk.py)
source ./generate.sh
# build and test
tox -vv
```
## Install locally ## Install locally
```shell ```shell
pip install ./dist/bdkpython-<yourversion>-py3-none-any.whl pip install ./dist/bdkpython-<yourversion>.whl
``` ```

View File

@@ -1,24 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
OS=$(uname -s)
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
cargo build --profile release-smaller
case $OS in
"Darwin")
echo "Copying macOS libbdkffi.dylib..."
cp ../target/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
;;
"Linux")
echo "Copying linux libbdkffi.so..."
cp ../target/release-smaller/libbdkffi.so ../bdk-python/src/bdkpython/libbdkffi.so
;;
esac
cd ../bdk-python/
echo "All done!"

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
${PYBIN}/python --version
${PYBIN}/pip install -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup default 1.67.0
cargo build --profile release-smaller
echo "Copying linux libbdkffi.so..."
cp ../target/release-smaller/libbdkffi.so ../bdk-python/src/bdkpython/libbdkffi.so
echo "All done!"

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
python3 --version
pip install --user -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup default 1.67.0
rustup target add aarch64-apple-darwin
cargo build --profile release-smaller --target aarch64-apple-darwin
echo "Copying libraries libbdkffi.dylib..."
cp ../target/aarch64-apple-darwin/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
echo "All done!"

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
python3 --version
pip install --user -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup target add x86_64-apple-darwin
cargo build --profile release-smaller --target x86_64-apple-darwin
echo "Copying libraries libbdkffi.dylib..."
cp ../target/x86_64-apple-darwin/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
echo "All done!"

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
python3 --version
pip install --user -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup default 1.67.0
rustup target add x86_64-pc-windows-msvc
cargo build --profile release-smaller --target x86_64-pc-windows-msvc
echo "Copying libraries bdkffi.dll..."
cp ../target/x86_64-pc-windows-msvc/release-smaller/bdkffi.dll ../bdk-python/src/bdkpython/bdkffi.dll
echo "All done!"

View File

@@ -51,7 +51,7 @@ print(f"Wallet balance is: {balance.total}")
setup( setup(
name="bdkpython", name="bdkpython",
version="0.28.3", version="0.31.0",
description="The Python language bindings for the Bitcoin Development Kit", description="The Python language bindings for the Bitcoin Development Kit",
long_description=LONG_DESCRIPTION, long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
@@ -62,7 +62,6 @@ setup(
url="https://github.com/bitcoindevkit/bdk-ffi", url="https://github.com/bitcoindevkit/bdk-ffi",
author="Alekos Filini <alekos.filini@gmail.com>, Steve Myers <steve@notmandatory.org>", author="Alekos Filini <alekos.filini@gmail.com>, Steve Myers <steve@notmandatory.org>",
license="MIT or Apache 2.0", license="MIT or Apache 2.0",
# This is required to ensure the library name includes the python version, abi, and platform tags # This is required to ensure the library name includes the python version, abi, and platform tags
# See issue #350 for more information # See issue #350 for more information
has_ext_modules=lambda: True, has_ext_modules=lambda: True,

View File

@@ -29,7 +29,9 @@ let package = Package(
.binaryTarget(name: "bdkFFI", path: "./bdkFFI.xcframework"), .binaryTarget(name: "bdkFFI", path: "./bdkFFI.xcframework"),
.target( .target(
name: "BitcoinDevKit", name: "BitcoinDevKit",
dependencies: ["bdkFFI"]), dependencies: ["bdkFFI"],
swiftSettings: [.unsafeFlags(["-suppress-warnings"])]
),
.testTarget( .testTarget(
name: "BitcoinDevKitTests", name: "BitcoinDevKitTests",
dependencies: ["BitcoinDevKit"]), dependencies: ["BitcoinDevKit"]),

View File

@@ -16,6 +16,8 @@
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>macos</string> <string>macos</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
</dict> </dict>
<dict> <dict>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
@@ -31,6 +33,8 @@
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key> <key>SupportedPlatformVariant</key>
<string>simulator</string> <string>simulator</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
</dict> </dict>
<dict> <dict>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
@@ -43,6 +47,8 @@
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
</dict> </dict>
</array> </array>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.bitcoindevkit.bdkFFI</string>
<key>CFBundleName</key>
<string>bdkFFI</string>
<key>CFBundleVersion</key>
<string>0.31.1</string>
<key>CFBundleShortVersionString</key>
<string>0.31.1</string>
<key>CFBundleExecutable</key>
<string>bdkFFI</string>
<key>MinimumOSVersion</key>
<string>100</string>
</dict>
</plist>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.bitcoindevkit.bdkFFI</string>
<key>CFBundleName</key>
<string>bdkFFI</string>
<key>CFBundleVersion</key>
<string>0.31.1</string>
<key>CFBundleShortVersionString</key>
<string>0.31.1</string>
<key>CFBundleExecutable</key>
<string>bdkFFI</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
</dict>
</plist>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.bitcoindevkit.bdkFFI</string>
<key>CFBundleName</key>
<string>bdkFFI</string>
<key>CFBundleVersion</key>
<string>0.31.1</string>
<key>CFBundleShortVersionString</key>
<string>0.31.1</string>
<key>CFBundleExecutable</key>
<string>bdkFFI</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
</dict>
</plist>

View File

@@ -5,10 +5,10 @@
# #
# Run the script from the repo root directory, ie: ./bdk-swift/build-local-swift.sh # Run the script from the repo root directory, ie: ./bdk-swift/build-local-swift.sh
rustup install nightly-x86_64-apple-darwin rustup install nightly-2023-04-10
rustup component add rust-src --toolchain nightly-x86_64-apple-darwin rustup component add rust-src --toolchain nightly-2023-04-10
rustup target add aarch64-apple-ios x86_64-apple-ios rustup target add aarch64-apple-ios x86_64-apple-ios
rustup target add aarch64-apple-ios-sim --toolchain nightly rustup target add aarch64-apple-ios-sim --toolchain nightly-2023-04-10
rustup target add aarch64-apple-darwin x86_64-apple-darwin rustup target add aarch64-apple-darwin x86_64-apple-darwin
pushd bdk-ffi pushd bdk-ffi
@@ -20,10 +20,10 @@ cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-da
cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-ios cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-ios
cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-ios cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-ios
cargo +nightly build --package bdk-ffi --release -Z build-std --target aarch64-apple-ios-sim cargo +nightly-2023-04-10 build --package bdk-ffi --profile release-smaller --target aarch64-apple-ios-sim
mkdir -p target/lipo-ios-sim/release-smaller mkdir -p target/lipo-ios-sim/release-smaller
lipo target/aarch64-apple-ios-sim/release/libbdkffi.a target/x86_64-apple-ios/release-smaller/libbdkffi.a -create -output target/lipo-ios-sim/release-smaller/libbdkffi.a lipo target/aarch64-apple-ios-sim/release-smaller/libbdkffi.a target/x86_64-apple-ios/release-smaller/libbdkffi.a -create -output target/lipo-ios-sim/release-smaller/libbdkffi.a
mkdir -p target/lipo-macos/release-smaller 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 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