From 40b7509553eb31c32af3424581efe27d540c3ffa Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 23 Oct 2020 17:04:45 -0400 Subject: [PATCH] Write tuple getters (and test them, exposing memory leak) --- genbindings.py | 10 +- src/main/jni/bindings.c | 107 ++++++++++++++++++ .../java/org/ldk/HumanObjectPeerTest.java | 24 ++-- 3 files changed, 131 insertions(+), 10 deletions(-) diff --git a/genbindings.py b/genbindings.py index 3283b307..30f14759 100755 --- a/genbindings.py +++ b/genbindings.py @@ -1803,7 +1803,15 @@ class CommonBase { for idx, ty_info in enumerate(tuple_types[alias_match.group(1)][0]): e = chr(ord('a') + idx) out_java.write("\tpublic static native " + ty_info.java_ty + " " + alias_match.group(2) + "_get_" + e + "(long ptr);\n") - # XXX: Write C method! + out_c.write("JNIEXPORT " + ty_info.c_ty + " JNICALL Java_org_ldk_impl_bindings_" + alias_match.group(2).replace("_", "_1") + "_1get_1" + e + "(JNIEnv *_env, jclass _b, jlong ptr) {\n") + out_c.write("\t" + alias_match.group(1) + " *tuple = (" + alias_match.group(1) + "*)ptr;\n") + conv_info = map_type_with_info(ty_info, False, None, False, True) + if conv_info.ret_conv is not None: + out_c.write("\t" + conv_info.ret_conv[0].replace("\n", "\n\t") + "tuple->" + e + conv_info.ret_conv[1].replace("\n", "\n\t") + "\n") + out_c.write("\treturn " + conv_info.ret_conv_name + ";\n") + else: + out_c.write("\treturn tuple->" + e + ";\n") + out_c.write("}\n") elif alias_match.group(1) in result_templ_structs: result_types.add(alias_match.group(2)) human_ty = alias_match.group(2).replace("LDKCResult", "Result") diff --git a/src/main/jni/bindings.c b/src/main/jni/bindings.c index 27a8e615..fecddac2 100644 --- a/src/main/jni/bindings.c +++ b/src/main/jni/bindings.c @@ -471,6 +471,17 @@ JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2TupleTempl_1usize_1_1Tra ret->b = b_conv; return (long)ret; } +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1usizeTransactionZ_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_usize__Transaction *tuple = (LDKC2TupleTempl_usize__Transaction*)ptr; + return tuple->a; +} +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1usizeTransactionZ_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_usize__Transaction *tuple = (LDKC2TupleTempl_usize__Transaction*)ptr; + LDKTransaction *b_copy = MALLOC(sizeof(LDKTransaction), "LDKTransaction"); + *b_copy = tuple->b; + long b_ref = (long)b_copy; + return b_ref; +} JNIEXPORT jboolean JNICALL Java_org_ldk_impl_bindings_LDKCResult_1NoneChannelMonitorUpdateErrZ_1result_1ok (JNIEnv * env, jclass _a, jlong arg) { return ((LDKCResult_NoneChannelMonitorUpdateErrZ*)arg)->result_ok; } @@ -517,6 +528,21 @@ JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2TupleTempl_1OutPoint_1_1 //TODO: Really need to call (*_env)->ReleaseByteArrayElements(_env, b, (int8_t*)b_ref.data, 0); here return (long)ret; } +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1OutPointScriptZ_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_OutPoint__CVec_u8Z *tuple = (LDKC2TupleTempl_OutPoint__CVec_u8Z*)ptr; + LDKOutPoint a_var = tuple->a; + CHECK((((long)a_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this. + CHECK((((long)&a_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this. + long a_ref = (long)a_var.inner & ~1; + return a_ref; +} +JNIEXPORT jbyteArray JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1OutPointScriptZ_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_OutPoint__CVec_u8Z *tuple = (LDKC2TupleTempl_OutPoint__CVec_u8Z*)ptr; + LDKCVec_u8Z b_var = tuple->b; + jbyteArray b_arr = (*_env)->NewByteArray(_env, b_var.datalen); + (*_env)->SetByteArrayRegion(_env, b_arr, 0, b_var.datalen, b_var.data); + return b_arr; +} JNIEXPORT jobject JNICALL Java_org_ldk_impl_bindings_LDKCVecTempl_1TxOut_1arr_1info(JNIEnv *env, jclass _b, jlong ptr) { LDKCVecTempl_TxOut *vec = (LDKCVecTempl_TxOut*)ptr; return (*env)->NewObject(env, slicedef_cls, slicedef_meth, (long)vec->data, (long)vec->datalen, sizeof(LDKTxOut)); @@ -562,12 +588,38 @@ JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2TupleTempl_1ThirtyTwoByt ret->b = b_constr; return (long)ret; } +JNIEXPORT jbyteArray JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1TxidCVec_1TxOutZZ_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut *tuple = (LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut*)ptr; + jbyteArray a_arr = (*_env)->NewByteArray(_env, 32); + (*_env)->SetByteArrayRegion(_env, a_arr, 0, 32, tuple->a.data); + return a_arr; +} +JNIEXPORT jlongArray JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1TxidCVec_1TxOutZZ_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut *tuple = (LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut*)ptr; + LDKCVecTempl_TxOut b_var = tuple->b; + jlongArray b_arr = (*_env)->NewLongArray(_env, b_var.datalen); + jlong *b_arr_ptr = (*_env)->GetPrimitiveArrayCritical(_env, b_arr, NULL); + for (size_t h = 0; h < b_var.datalen; h++) { + long arr_conv_7_ref = (long)&b_var.data[h]; + b_arr_ptr[h] = arr_conv_7_ref; + } + (*_env)->ReleasePrimitiveArrayCritical(_env, b_arr, b_arr_ptr, 0); + return b_arr; +} JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2TupleTempl_1u64_1_1u64_1new(JNIEnv *_env, jclass _b, jlong a, jlong b) { LDKC2TupleTempl_u64__u64* ret = MALLOC(sizeof(LDKC2TupleTempl_u64__u64), "LDKC2TupleTempl_u64__u64"); ret->a = a; ret->b = b; return (long)ret; } +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1u64u64Z_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_u64__u64 *tuple = (LDKC2TupleTempl_u64__u64*)ptr; + return tuple->a; +} +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1u64u64Z_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_u64__u64 *tuple = (LDKC2TupleTempl_u64__u64*)ptr; + return tuple->b; +} JNIEXPORT jobject JNICALL Java_org_ldk_impl_bindings_LDKCVecTempl_1Signature_1arr_1info(JNIEnv *env, jclass _b, jlong ptr) { LDKCVecTempl_Signature *vec = (LDKCVecTempl_Signature*)ptr; return (*env)->NewObject(env, slicedef_cls, slicedef_meth, (long)vec->data, (long)vec->datalen, sizeof(LDKSignature)); @@ -594,6 +646,23 @@ JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2TupleTempl_1Signature_1_ ret->b = b_constr; return (long)ret; } +JNIEXPORT jbyteArray JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1SignatureCVec_1SignatureZZ_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_Signature__CVecTempl_Signature *tuple = (LDKC2TupleTempl_Signature__CVecTempl_Signature*)ptr; + jbyteArray a_arr = (*_env)->NewByteArray(_env, 64); + (*_env)->SetByteArrayRegion(_env, a_arr, 0, 64, tuple->a.compact_form); + return a_arr; +} +JNIEXPORT jobjectArray JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1SignatureCVec_1SignatureZZ_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_Signature__CVecTempl_Signature *tuple = (LDKC2TupleTempl_Signature__CVecTempl_Signature*)ptr; + LDKCVecTempl_Signature b_var = tuple->b; + jobjectArray b_arr = (*_env)->NewObjectArray(_env, b_var.datalen, NULL, NULL); + for (size_t i = 0; i < b_var.datalen; i++) { + jbyteArray arr_conv_8_arr = (*_env)->NewByteArray(_env, 64); + (*_env)->SetByteArrayRegion(_env, arr_conv_8_arr, 0, 64, b_var.data[i].compact_form); + (*_env)->SetObjectArrayElement(_env, b_arr, i, arr_conv_8_arr); + } + return b_arr; +} JNIEXPORT jboolean JNICALL Java_org_ldk_impl_bindings_LDKCResult_1C2Tuple_1SignatureCVec_1SignatureZZNoneZ_1result_1ok (JNIEnv * env, jclass _a, jlong arg) { return ((LDKCResult_C2Tuple_SignatureCVec_SignatureZZNoneZ*)arg)->result_ok; } @@ -769,6 +838,30 @@ JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC3TupleTempl_1ChannelAnnou ret->c = c_conv; return (long)ret; } +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC3Tuple_1ChannelAnnouncementChannelUpdateChannelUpdateZ_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC3TupleTempl_ChannelAnnouncement__ChannelUpdate__ChannelUpdate *tuple = (LDKC3TupleTempl_ChannelAnnouncement__ChannelUpdate__ChannelUpdate*)ptr; + LDKChannelAnnouncement a_var = tuple->a; + CHECK((((long)a_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this. + CHECK((((long)&a_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this. + long a_ref = (long)a_var.inner & ~1; + return a_ref; +} +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC3Tuple_1ChannelAnnouncementChannelUpdateChannelUpdateZ_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC3TupleTempl_ChannelAnnouncement__ChannelUpdate__ChannelUpdate *tuple = (LDKC3TupleTempl_ChannelAnnouncement__ChannelUpdate__ChannelUpdate*)ptr; + LDKChannelUpdate b_var = tuple->b; + CHECK((((long)b_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this. + CHECK((((long)&b_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this. + long b_ref = (long)b_var.inner & ~1; + return b_ref; +} +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC3Tuple_1ChannelAnnouncementChannelUpdateChannelUpdateZ_1get_1c(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC3TupleTempl_ChannelAnnouncement__ChannelUpdate__ChannelUpdate *tuple = (LDKC3TupleTempl_ChannelAnnouncement__ChannelUpdate__ChannelUpdate*)ptr; + LDKChannelUpdate c_var = tuple->c; + CHECK((((long)c_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this. + CHECK((((long)&c_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this. + long c_ref = (long)c_var.inner & ~1; + return c_ref; +} JNIEXPORT jboolean JNICALL Java_org_ldk_impl_bindings_LDKCResult_1NonePeerHandleErrorZ_1result_1ok (JNIEnv * env, jclass _a, jlong arg) { return ((LDKCResult_NonePeerHandleErrorZ*)arg)->result_ok; } @@ -800,6 +893,20 @@ JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2TupleTempl_1HTLCOutputIn ret->b = b_ref; return (long)ret; } +JNIEXPORT jlong JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1HTLCOutputInCommitmentSignatureZ_1get_1a(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_HTLCOutputInCommitment__Signature *tuple = (LDKC2TupleTempl_HTLCOutputInCommitment__Signature*)ptr; + LDKHTLCOutputInCommitment a_var = tuple->a; + CHECK((((long)a_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this. + CHECK((((long)&a_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this. + long a_ref = (long)a_var.inner & ~1; + return a_ref; +} +JNIEXPORT jbyteArray JNICALL Java_org_ldk_impl_bindings_LDKC2Tuple_1HTLCOutputInCommitmentSignatureZ_1get_1b(JNIEnv *_env, jclass _b, jlong ptr) { + LDKC2TupleTempl_HTLCOutputInCommitment__Signature *tuple = (LDKC2TupleTempl_HTLCOutputInCommitment__Signature*)ptr; + jbyteArray b_arr = (*_env)->NewByteArray(_env, 64); + (*_env)->SetByteArrayRegion(_env, b_arr, 0, 64, tuple->b.compact_form); + return b_arr; +} static jclass LDKSpendableOutputDescriptor_StaticOutput_class = NULL; static jmethodID LDKSpendableOutputDescriptor_StaticOutput_meth = NULL; static jclass LDKSpendableOutputDescriptor_DynamicOutputP2WSH_class = NULL; diff --git a/src/test/java/org/ldk/HumanObjectPeerTest.java b/src/test/java/org/ldk/HumanObjectPeerTest.java index 8e7e42f1..fd25481c 100644 --- a/src/test/java/org/ldk/HumanObjectPeerTest.java +++ b/src/test/java/org/ldk/HumanObjectPeerTest.java @@ -86,7 +86,7 @@ class HumanObjectPeerTestInstance { System.gc(); } - void connect_block(Block b, int height) { + TwoTuple[] connect_block(Block b, int height) { byte[] header = Arrays.copyOfRange(b.bitcoinSerialize(), 0, 80); TwoTuple[] txn; if (b.hasTransactions()) { @@ -97,11 +97,12 @@ class HumanObjectPeerTestInstance { txn = new TwoTuple[0]; chan_manager.block_connected(header, txn, height); synchronized (monitors) { + assert monitors.size() == 1; for (ChannelMonitor mon : monitors.values()) { - TwoTuple[] ret = mon.block_connected(header, txn, height, tx_broadcaster, fee_estimator, logger); - assert ret.length == 0; + return mon.block_connected(header, txn, height, tx_broadcaster, fee_estimator, logger); } } + return null; } Route get_route(byte[] dest_node, ChannelDetails[] our_chans) { @@ -227,13 +228,13 @@ class HumanObjectPeerTestInstance { assert ((Event.FundingBroadcastSafe) events[0]).user_channel_id == 42; Block b = new Block(bitcoinj_net, 2, Sha256Hash.ZERO_HASH, Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{funding})); - peer1.connect_block(b, 1); - peer2.connect_block(b, 1); + assert peer1.connect_block(b, 1).length == 0; + assert peer2.connect_block(b, 1).length == 0; for (int height = 2; height < 10; height++) { b = new Block(bitcoinj_net, 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[0])); - peer1.connect_block(b, height); - peer2.connect_block(b, height); + assert peer1.connect_block(b, height).length == 0; + assert peer2.connect_block(b, height).length == 0; } peer1.peer_manager.process_events(); @@ -316,8 +317,13 @@ class HumanObjectPeerTestInstance { assert peer1.broadcast_set.size() == 1; assert peer2.broadcast_set.size() == 0; - //b = new Block(bitcoinj_net, 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, Arrays.asList(new Transaction[]{new Transaction(bitcoinj_net, peer1.broadcast_set.getFirst())})); - //peer2.connect_block(b, 1); + Transaction tx = new Transaction(bitcoinj_net, peer1.broadcast_set.getFirst().get_contents()); + b = new Block(bitcoinj_net, 2, b.getHash(), Sha256Hash.ZERO_HASH, 42, 0, 0, + Arrays.asList(new Transaction[]{tx})); + TwoTuple[] watch_outputs = peer2.connect_block(b, 1); + assert watch_outputs.length == 1; + assert Arrays.equals(watch_outputs[0].a, tx.getTxId().getReversedBytes()); + assert watch_outputs[0].b.length == 1; } bindings.SocketDescriptor_free(descriptor2); -- 2.30.2