lightningdevkit / ldk-garbagecollected Goto Github PK
View Code? Open in Web Editor NEWLDK Bindings for Garbage-Collected Languages
License: Other
LDK Bindings for Garbage-Collected Languages
License: Other
At least in (BlockHash, ChannelMonitor).get_b()
which currently clones the monitor itself.
Some users are looking at routing-node/server-side ldk-garbagecollected so we probably need this.
It should be an option of some form, instead it tries to read the transaction output directly, resulting in a segfault if its None.
I got an error message when launching a simple android app with ldk-java from MavenCentral repository.
Do I need to put liblightningjni.so by hand?
Codes about ldk are very simple, it just calls Logger in org.ldk.structs.
Building the app and installing to an emulator device are successful but launching is failed.
Enviroment
Error message
2022-06-30 14:02:39.650 6653-6653/com.example.test_ldk_java W/System.err: Failed to load LDK native library.
2022-06-30 14:02:39.650 6653-6653/com.example.test_ldk_java W/System.err: System LDK native library load failed with: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.test_ldk_java-mjFe7aYsOrS-s4ZaofGTbA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.test_ldk_java-mjFe7aYsOrS-s4ZaofGTbA==/lib/x86, /system/lib]]] couldn't find "liblightningjni.so"
2022-06-30 14:02:39.650 6653-6653/com.example.test_ldk_java W/System.err: Resource-based LDK native library load failed with: java.lang.NullPointerException
2022-06-30 14:02:39.650 6653-6653/com.example.test_ldk_java D/AndroidRuntime: Shutting down VM
2022-06-30 14:02:39.652 6653-6653/com.example.test_ldk_java E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test_ldk_java, PID: 6653
java.lang.ExceptionInInitializerError
at org.ldk.impl.bindings.LDKLogger_new(Native Method)
at org.ldk.structs.Logger.<init>(Logger.java:18)
at org.ldk.structs.Logger.new_impl(Logger.java:36)
at com.example.test_ldk_java.MainActivity.<init>(MainActivity.java:28)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2831)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.IllegalArgumentException: java.lang.NullPointerException
at org.ldk.impl.bindings.<clinit>(bindings.java:39)
at org.ldk.impl.bindings.LDKLogger_new(Native Method)
at org.ldk.structs.Logger.<init>(Logger.java:18)
at org.ldk.structs.Logger.new_impl(Logger.java:36)
at com.example.test_ldk_java.MainActivity.<init>(MainActivity.java:28)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2831)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.nio.file.Files.copy(Files.java:2984)
at org.ldk.impl.bindings.<clinit>(bindings.java:33)
at org.ldk.impl.bindings.LDKLogger_new(Native Method)
at org.ldk.structs.Logger.<init>(Logger.java:18)
at org.ldk.structs.Logger.new_impl(Logger.java:36)
at com.example.test_ldk_java.MainActivity.<init>(MainActivity.java:28)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2831)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
File Diff from activity base
$ diff build.gradle.org build.gradle
42a43,44
>
> implementation 'org.lightningdevkit:ldk-java:0.0.106.0'
$ diff MainActivity.java.org MainActivity.java
20a21,22
> import org.ldk.structs.Logger;
>
25a28,29
> final private Logger logger = Logger.new_impl(System.out::println)
>
Code Files I changed from activity base
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.test_ldk_java"
minSdk 22
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment:2.4.2'
implementation 'androidx.navigation:navigation-ui:2.4.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'org.lightningdevkit:ldk-java:0.0.106.0'
}
package com.example.test_ldk_java;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.test_ldk_java.databinding.ActivityMainBinding;
import android.view.Menu;
import android.view.MenuItem;
import org.ldk.structs.Logger;
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration appBarConfiguration;
private ActivityMainBinding binding;
final private Logger logger = Logger.new_impl(System.out::println);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
binding.fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
}
galderz wrote up some excellent feedback on how to make the Java API more Java-y, which we should work on, at galderz/ldk-me-a-node#1
A few of the methods seem to create problems on the native side of things. Here is an example of an error I get:
❯ ./kldk
Hello, thundernode!
Kldk ❯❯❯ startnode
Kldk starting...
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGILL (0x4) at pc=0x0000000131a289ad, pid=41586, tid=11523
#
# JRE version: OpenJDK Runtime Environment Temurin-11.0.14+9 (11.0.14+9) (build 11.0.14+9)
# Java VM: OpenJDK 64-Bit Server VM Temurin-11.0.14+9 (11.0.14+9, mixed mode, tiered, compressed oops, g1 gc, bsd-amd64)
# Problematic frame:
# C [liblightningjni.so+0x1d69ad] NetworkGraph_new+0xd
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/tb/repos/k-ldk-node/app/build/install/kldk/bin/hs_err_pid41586.log
#
# If you would like to submit a bug report, please visit:
# https://github.com/adoptium/adoptium-support/issues
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
zsh: abort ./kldk
To reproduce, simply fire up the kdlk
node here on an M1 and run the startnode
command.
The error above happens at the networkGraph
initialization step, but commenting that out allows us to find similar errors happening on the userConfig
or the transactionFilter
steps:
# Problematic frame:
# C [liblightningjni.so+0x272078] UserConfig_default+0x28
# Problematic frame:
# C [liblightningjni.so+0x4028c7] COption_FilterZ_some+0x7
v0.0.99-2
Invalid sub-millisatoshi precision is parsed as valid.
lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu7hqtk93pkf7sw55rdv4k9z2vj050rxdr6za9ekfs3nlt5lr89jqpdmxsmlj9urqumg0h9wzpqecw7th56tdms40p2ny9q4ddvjsedzcplva53s
Signature is not recoverable. - results in panic
lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaxtrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspk28uwq
thread '<unnamed>' panicked at 'no other error may occur', rust-lightning/lightning-invoice/src/lib.rs:1062:23
stack backtrace:
0: 0x1384da962 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h5b5b7de1c79b4b45
1: 0x138267ffe - core::fmt::write::h65ec8c8a6aa7b549
2: 0x1384da21a - std::io::Write::write_fmt::hc52e560ab9e57db4
3: 0x1384d9d87 - std::panicking::default_hook::{{closure}}::h0974624c30a6e2b5
4: 0x1384d8d3a - std::panicking::rust_panic_with_hook::h1cdaa4b48d8ea4a1
5: 0x1384cffe7 - std::panicking::begin_panic::{{closure}}::h36f2c3c139495592
6: 0x1384cffb2 - std::sys_common::backtrace::__rust_end_short_backtrace::hcd7d6a4a9bfbbba4
7: 0x138577f4d - std::panicking::begin_panic::h778967c1427c2624
8: 0x1384cc916 - lightning_invoice::Invoice::from_signed::hece781edd974c5de
9: 0x138428dc8 - _Invoice_from_str
10: 0x138561efa - _Java_org_ldk_impl_bindings_Invoice_1from_1str
This keeps coming up, and I think we can actually do it via a separate artifact.
Docs are basically not being copied at all right now. We should have docs in TS.
Are the any intentions on creating the batteries helpers as seen for java for the TypeScript bindings?
https://github.com/lightningdevkit/ldk-garbagecollected/tree/main/src/main/java/org/ldk/batteries
Looking for some input on an issue I'm having around peer connections using the typescript bindings. I've gotten all the steps setup as per the tutorials, but on connecting to a node I receive the following logs from the peermanager.
var address = ldk.NetAddress.constructor_ipv4([127,0,0,1],9735);
peer_manager.new_outbound_connection(Buffer.from('0374f296fbe03d451d9bd182ae7fc797a2432b112717b029607b4e3c623a9282f9', 'hex'), socket, address);
I can see comms between the TS node and my remote Polar LND node, and imagine the handshake is happening as per the loggers output.
Been trying to inspect the traffic between these, but can confirm the remote node is responding via a protocol analyser. Trying to get https://github.com/nayutaco/lightning-dissector working so I can inspect the network communication to identify the responses being receive from the LND node, but for now here's my code for connecting.
lightning::ln::peer_handler: Finished noise handshake for connection with 0374f296fbe03d451d9bd182ae7fc797a2432b112717b029607b4e3c623a9282f9
lightning::ln::peer_handler: Enqueueing message Init { features: [170, 81, 2, 8, 0, 160], remote_network_address: Some(IPv4 { addr: [7, 38, 95, 94], port: 35745 }) } to 0374f296fbe03d451d9bd182ae7fc797a2432b112717b029607b4e3c623a9282f9
The tuple return by the remote server looks bizarre [7, 38, 95, 94] and from what I can see this is derived from the socket itself. After receiving these however peermanager.get_peer_node_ids() returns an empty array []. I am unable to use lightning-net-tokio (rust) or the NioPeer (java), so using a raw nodejs socket which is managed through the SockerDescriptor interface.
Randomly browsing this project, not sure if the warning in README still applies - if it does, I believe it should be repeated on https://lightningdevkit.org/tutorials/build_a_node_in_java/ so that people don't burn themselves. If it doesn't it should be removed from README.
"Got function call on incorrect JS object!" Should say something about the specific method we were looking for.
While using the Java/Kotlin bindings I noticed we have a number of "weirdly" named structs e.g Result_InvoiceNoneZ
Result_NoneChannelMonitorUpdateErrZ
, Option_C2Tuple_usizeTransactionZZ
and Result_NetworkGraphDecodeErrorZ
. I imagine this is something to do with how our bindings are generated using Rust, but worth addressing since the syntax is a lot different stylistically.
Without X-Lang LTO Release builds fail, at least in the llvm-dis step which will fail if the LLVM version doesn't match the rustc version.
We've had some memory leaks for about as long as we've not had any known crashes, but we should work more on whittling them down. The README says this:
There are some known memory leaks, which are relatively modest in the existing test suite (around 1MB for 128 node constructions and 64 full channel constructions and payments sent), but which may be less moderate in certain usages
If a user's method throws an exception in a Rust -> Java call we will usually end up with a SEGFAULT. There's not a ton we can do to fix that, but we should at least check the state and debug-log and explicitly panic instead of continuing on.
I'm told you cannot create a ChannelCounterparty object in java, that seems stupid.
We have a great leadk-detection framework. We should get it to run in TS and then have it run in tests after some timeout.
It looks like none of these are exposed at all.
Looks like the paths
field of a Route
is not exposed via a getter, only a setter. We need to expose it via both.
cause it should be.
This is required by a user to mock out payments and ChannelManager
.
TxOut
is manually constructed so we should have constructors.
at
and check that other languages are doing it right.
Probably should be in the C bindings, maybe there's a loose patch for this already.
There's really no explination for why things fail when it fails, which we should fix.
We should have a debug build for android, and if we do it should also support i686.
Several times we've had null
s creep in from user code and cause us to do something scary like a 0-ptr deref, which leaves users confused and frustrated, eg https://github.com/orgs/lightningdevkit/discussions/1820. We really should instead null check and call jni->FatalError
, even though its a bit more code, because it makes users much happier.
05-08 21:47:20.040 5594 5638 F m.example.rnldk: [runtime.cc:683](http://runtime.cc:683/)] JNI DETECTED ERROR IN APPLICATION: illegal class name 'Ljava/lang/String;'
05-08 21:47:20.040 5594 5638 F m.example.rnldk: [runtime.cc:683](http://runtime.cc:683/)] (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')
05-08 21:47:20.040 5594 5638 F m.example.rnldk: [runtime.cc:683](http://runtime.cc:683/)] in call to FindClass
05-08 21:47:20.040 5594 5638 F m.example.rnldk: [runtime.cc:683](http://runtime.cc:683/)] from void org.ldk.impl.bindings.init_class_cache()
We should be able to read this as a ChannelMonitor
in bindings, this may mean a chunk of work to expose deref.
I'm not sure what's involved in this.
I've tried to build the bindings locally but I got some errors:
With debug=true
:
❯ ./genbindings.sh /opt/matt-rust-lightning "-I/opt/java-11/include/ -I/opt/java-11/include/linux/" true false
Creating Java bindings...
Building Java bindings...
Creating TS bindings...
Building TS bindings...
clang-11: error: no such file or directory: '/opt/matt-rust-lightning/lightning-c-bindings/target/wasm32-wasi/debug/libldk.a'
With debug=false
:
❯ ./genbindings.sh /opt/matt-rust-lightning "-I/opt/java-11/include/ -I/opt/java-11/include/linux/" true false
Creating Java bindings...
Building Java bindings...
Creating TS bindings...
Building TS bindings...
clang-11: error: no such file or directory: '/opt/matt-rust-lightning/lightning-c-bindings/target/wasm32-wasi/debug/libldk.a'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.