Giter Site home page Giter Site logo

bdk-jni's Introduction

bdk-jni

CI Status

⚠️⚠️ Notice ⚠️⚠️

This library is now unmaintained and was deprecated in favor of the newest bdk-android and bdk-jvm libraries. Please consider this repository an archive only.



Overview

This repository is home of two libraries, bdk-jvm and bdk-android. You can build bdk-jvm without building bdk-android, but bdk-android relies on the artifact built in bdk-jvm to function, so if you are building for Android you need to compile both libraries. Both rely on the test-fixtures project for testing.

Building both libraries

The minimum JDK version required to build this library is JDK 11. Make sure your JAVA_HOME env variable is set and java --version displays version 11 or above. The Rust version used to compile this library is 1.53.0.

If you haven't installed rust android targets first add those to your environment using rustup

rustup target add x86_64-apple-darwin x86_64-unknown-linux-gnu x86_64-linux-android aarch64-linux-android armv7-linux-androideabi i686-linux-android

Then make sure that you have an Android NDK installed (our Github CI is using 21.4.7075529, and that you have an ANDROID_NDK_HOME env variable set before you start building the library. Usually, if installed through the sdkmanager, your ANDROID_NDK_HOME will look more or less like this: /home/<user>/Android/Sdk/ndk/<version>/.

export ANDROID_NDK_HOME=/home/<user>/Android/Sdk/ndk/<NDK version, ie. 21.4.7075529>

Build and unit test jvm .jar and build android .aar libraries with:

./gradlew build

Test android .aar library connected unit tests with:

./gradlew :android:connectedDebugAndroidTest

Gradle will build automatically the native library with rust for all 4 platforms using NDK. You can choose to build only for a specific platform by setting the env variable BUILD_TARGETS to a comma-separated list containing one or more of the following items:

  • aarch64
  • armv7
  • x86_64
  • i686

The output aar library is available at ./android/build/outputs/aar.

To run the tests first launch a local android emulator from the Android Studio IDE or via the command line. If starting from the command line you will also need to set the ANDROID_SDK_ROOT env variable.

export ANDROID_SDK_ROOT=</home/<user>/Android/Sdk or where ever your Sdk is installed>

Publish .aar and .jar files to local maven repository

Use the below command to publish the jvm .jar and android .aar files generated by this project to your local maven2 repository (~/.m2/repository/org/bitcoindevkit/bdkjni/bdk-):

./gradlew :jvm:publishToMavenLocal
./gradlew :android:publishToMavenLocal

Once published you will see two new artifacts in your local maven repository:

~/.m2/repository/org/bitcoindevkit/bdkjni/bdk-jvm/<version>/bdk-jvm-<version>.jar
~/.m2/repository/org/bitcoindevkit/bdkjni/bdk-android/<version>/bdk-android-<version>.aar
~/.m2/repository/org/bitcoindevkit/bdkjni/bdk-android-debug/<version>/bdk-android-debug-<version>.aar

When you include the bdk-android.aar or bdk-android-debug.aar library in a local Android project the bdk-jvm.jar will also be included as a transitive dependency. To include dependencies from your local maven repository add mavenLocal() to the allprojects section of your project build.gradle file:

allprojects {
    repositories {
        mavenLocal()
        ...
    }
}

At the moment we recommend using the bdk-android-debug version of the library so it can be debugged and used locally in the IDE. Because you added your local Maven repository to your build.gradle file, you can now simply add bdk-android or bdk-android-debug to your app/build.gradle dependencies:

dependencies {
    implementation 'org.bitcoindevkit.bdkjni:bdk-android-debug:0.2.1-dev'
    ...
}

Using the bdk-jvm library

The bdk-jvm library will attempt to load the native library (the libbdk_jni.so file) when you call the Lib.load() method. You must put the native library in the path it searches by default or you provide a custom paths in order for the library to find the native library. Do do this, you can either:

  1. Run the app without doing anything special and see the error thrown. You can then place the native library for your architecture (located in the /native-libs/target/<your architecture>/debug/ directory) in one of those locations
  2. Define a LD_LIBRARY_PATH environment variable with a path to a location where you put the native library file
  3. Call your application from the command line while providing a java.library.path variable.

Build just the native library

If you only want to build the native library, maybe for one single platform, you can do so with something like:

CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="aarch64-linux-android21-clang" CC="aarch64-linux-android21-clang" cargo build --target=aarch64-linux-android

Make sure that the compiler from the NDK is in your PATH

If the library is built in debug mode, there should already be a symlink from ./target/debug//libbdk_jni.so to the jniLibs directory, otherwise manually copy the shared object.

License

Licensed under either of

at your option.

bdk-jni's People

Contributors

afilini avatar darthbenro008 avatar lvaccaro avatar notmandatory avatar thunderbiscuit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

bdk-jni's Issues

Questions around building library for server-side Kotlin/Java

Just wondering how much work it would be to build the library into a .jar file that could be used for server-side JVM work.

I was working through a tutorial for ktor and figured I'd try to use bdk-jni for it, but then realized we currently only build for the Android platform. I'd be happy to help and learn.

Do you think that's possible slash worthy of time spent on it?

Bug related to errors thrown by bdk-jni

I am finding an odd behaviour with bdk-jni both in BDWallet and Padawan Wallet, the only native Android apps leveraging the bitcoindevkit at the moment (that I know of... let me know if there are others you know of, as I'll go and test the bug on those apps as well).

Whenever one interacts with the library and the library returns an error (say by trying to build a transaction with invalid inputs, like wrong address or insufficient funds), the wallet will return the error but then crash (I'm not exactly sure it cashes per se, I just know it's not there when you go back). The next call by the app to the library (for example building a new transaction or requesting a receive address) will not work and will crash the app, since the pointer to the native library is now pointing to something that isn't there. To be clear, as long as you use the library in a way that doesn't require it to throw any errors, it will keep working.

Reproduce the issue

You can reproduce this issue a few different ways:

  1. Download v0.4.0, v0.5.0, or v0.6.0 of Padawan. Make a transaction with more funds than you possess. Then go to the receive screen and try to generate a new address.
  2. Build BDWallet. Make a transaction with more funds than you possess. Then go to the receive screen and try to generate a new address.
  3. Build the bug/bitcoindevkit branch of Padawan. The branch adds a button to reset the wallet if it's been "destroyed" by the bug, and prints some small stuff to the logcat to help debug.

Expose get_unused_address method from bdk

Exposing this method in bdk-android and bdk-jvm would ensure that the users don't end up on very far indexes for new addresses without using them, and helps working with Electrum servers without requiring a very high stop gap.

This is related to issue bitcoindevkit/bdk#390 (not a fix per se but would help with keeping used addresses close together, and therefore the calls to Electrum servers).

Possible race condition related error related to sync and balance calls

When making multiple successive Kotlin co-routines calls in the same (IO) thread with the sync and getBalance commands, the Rust side call function receives either nothing or garbage characters instead of the json command message string send by the Kotlin side.

I suspect it has something to do with the sync command taking longer and/or not having a return value.

"Delete wallet" functionality discussion

Just wanted to bring it up as feature that would be nice to have down the road.

The sled database used by bdk currently cannot be cleared/deleted using the library, which means wallet builders using bdk-jni have to look at other solutions to implement a "delete your wallet" functionality in their apps.

Does reference in Cargo.toml exist?

when building with

./gradlew build

the line in Cargo.toml:

magical-bitcoin-wallet = { git = "https://github.com/MagicalBitcoin/magical-bitcoin-wallet.git", rev = "b771b17" }

gives

Updating git repository `https://github.com/MagicalBitcoin/magical-bitcoin-wallet.git`
error: failed to get `magical-bitcoin-wallet` as a dependency of package `magical-bitcoin-wallet-jni v0.1.0 (/mnt/c/Users/User/Downloads/magical-bitcoin-wallet-jni)`

Caused by:
  failed to load source for dependency `magical-bitcoin-wallet`

Caused by:
  Unable to update https://github.com/MagicalBitcoin/magical-bitcoin-wallet.git?rev=b771b17

Caused by:
  revspec 'b771b17' not found; class=Reference (4); code=NotFound (-3)

Build release version of native library

The Rust libraries we build are all of type debug. I'm wondering if we could optimize them by building the release versions. Reducing the size of the libraries that need to be bundled with the Android apps would be a big win (the apps are currently around 40MB each when you release separate APKs for each architecture, and 145MB for the universal APK).

The JVM debug library is 111MB on my local setup, and the release version is 24.2MB. Quite the difference. Let me know if there is a reason why we should keep building them in debug mode.

[Feature] Create GitHub Actions to make `library-release.aar` readily downloadable

As discussed in discord, instead of publishing it to Maven Repository, we can create 2 GitHub actions.

GitHub Action A (Builder):

  • Will run on every push to master branch
  • Will generate a .zip file that will contain library-release.aar which then can be unzipped to app/libs and can be linked via gradle

GitHub Action B (Releaser):

  • Will run on every tag push
  • Automatically build master branch, create a release
  • Upload the generated library.aar readily downloadable for users

Both of these actions will allow users to directly download the .aar instead of building them manually.

This Issue will also house a documentation change in README.md

Current build on master branch breaks because of failed tests

Issue lies here:

// jvm/src/test/java/org/bitcoindevkit/bdkjni/JvmLibTest.kt

class JvmLibTest : LibTest() {
    override fun getTestDataDir(): String {
        return Paths.get(System.getProperty("java.io.tmpdir"), "bdk-test").toString()
    }
}

Temporary fix is to add @Before annotation here:

// test-fixtures/src/main/java/org/bitcoindevkit/bdkjni/LibTest.kt

@Before
fun cleanupTestDataDir() {
    File(getTestDataDir()).deleteRecursively()
}

Long-term fix I'm not sure.

Relicensing MIT + Apache

This issue is based on a similar issue from the LDK project.

There is an open PR #40 that includes a commit to dual licensing BDK-JNI under MIT and Apache 2.0 instead of only MIT. Both licenses are simple and permissive, making it easy for open source and commercial projects to adopt BDK-JNI. The primary advantages of dual licensing are:

  1. the Apache 2.0 licenses provides additional "patent use" permission
  2. most Rust crates are dual licensed under MIT and Apache 2.0
  3. the BDK project is dual license MIT and Apache 2.0 so will make the license more compatible

To go forward with this change we need anyone who's made significant contributions before to sign off. I've listed all of the folks who show up in git shortlog below. If we don't get everyone that may be OK, but we'll need to go back and check that their contributions were relatively minor.

If you're on the below list and agree with this change please add a comment with "I hereby re-license my previous contributions to BDK under Apache 2.0 in addition to the existing MIT license."

List of small updates for the library

While playing around the library for #37, I made a list of small upkeep items that would be good to tackle in order to bring the library up to date. This is an issue to keep track of them and discuss some of the specifics.

Tooling

  • 1. Gradle wrapper is a full version behind (6.6.1, latest is 7.1.1)
  • 2. Gradle plugin is a full version behind (3.6.1, latest is 4.2.2)
  • 3. Kotlin version is 1.4.0, latest is 1.5.21
  • 4. Kotlin Gradle plugin should be updated to match Kotlin version

Files Layout

  • 5. The fact that bdk-jni relies on a Rust crate to build a native library file which the bdk-jvm and bdk-android libraries rely on is, IMO, very much an internal implementation detail. Yet the crate sits at the root of the repository, which I find is more confusing than anything, because it brings the Cargo.toml and Cargo.lock files and the src directory right at the top. I propose we pull the crate one layer down into its own directory.

Documentation

  • 6. The documentation is not yet very explicit when it comes to building just the bdk-jvm or the bdk-android libraries. I think we should expect future user to arrive to the repository with the mind to build one of them (their need is probably either JVM or Android, not both at the same time). The fact is that bdk-android indeed requires bdk-jvm to be built and published for it to work, but that's not obvious from the outset and should should be explained (as a new user, I'd be looking at the docs thinking: "why are they getting me to compile everything for all architectures and all the Android stuff when I really just want to build the bdk-jvm library for a linux cloud server?"). The JVM library can be build by itself and does not require bdk-android. The docs are still not very clear on this.
  • 7. The docs mention that you need JDK 14 or later to build, but I've been using 11.0.11 with success. Java 11 is the latest LTS (and more popular). I think if we can indeed build with 11 (I wonder if I might have not tried everything or if there was a particular reason for JDK 14, let me know), we should mention it in the docs.
  • 8. The docs should mention the Rust version required to build.

Other

  • 9. The license should be updated to be MIT/Apache 2.0

BDK-JNi gives error when we change the descriptor but not the name of wallet

When I initialise a wallet like this
walletPtr = Lib().constructor( WalletConstructor( name = name, network = Network.testnet, path = getDataDir(), descriptor = descriptor, change_descriptor = change_descriptor, electrum_url = electrumURL, electrum_proxy = null, ) )
And later on change the descriptor but not the name, it throws error something like you can't create wallet as it is already taken.
If I change the name the error disappears. Can anyone explain what is happening and if those name's are getting reserved then how to delete/free them?

cc @thunderbiscuit

Building into a jar library

This issue is to discuss the process of updating the library to produce a JVM compatible library of bdk-jni and to assemble related links.

Update error handling with `thiserror` macro

The project currently uses BDKJNIError enum for errors and JNIError struct to serialize errors to the JNI callers. The thiserror macro can be used to derive std::error::Error trait for BDKJNIError errors. It should also be possible to chain Results with .andThen to simplify and separate json serialization and error handling from the main app logic.

Small feedback on the readme

I'm building bdk-jni right now and I just wanted to share some small feedback I have regarding the readme. Note that I am building on an Ubuntu 20.04 distro.

  1. The first codeblock is meant for MacOS users. Its first line could be a comment mentioning it:
# macOS
sudo mv openjdk-15_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines/
cd /Library/Java/JavaVirtualMachines/
sudo tar -xzf openjdk-15_osx-x64_bin.tar.gz
sudo rm openjdk-15_osx-x64_bin.tar.gz

  1. My first try at building the library failed, with gradle returning the following error message:
> SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable 
or by setting the sdk.dir path in your project's local properties file at '/home/username/repos/bdk-jni/local.properties'.

I did build the library a few weeks back and didn't get this problem (is the reliance on this environment variable new?). The readme could mention that the user needs to have that local variable defined, and an example as to where it usually is (just like you have it for the ndk, which is great).

  1. It was unclear to me which library I should use for testing in my app. Both the release and the debug versions are built and available my local maven repository. Maybe one line about this just to explain which one to use for what situation?

  1. The instructions recommend adding mavenLocal() to the repositories section of my build.gradle file, but I found 2 such sections in my file (under buildscript and allprojects). After looking at the BDWallet equivalent file, I knew I needed to put it in both places, but that could be added to the text to remove that little bit of confusion.

Otherwise working great! Will continue to gather feedback as I work my way through it.

I'm happy to open the PR to fix those little nits if you'd like.

Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.