Skip to content

Commit b0c50b8

Browse files
authored
Merge pull request #18 from TheBlueMatt/main
Update to latest upstream C bindings with Invoice support
2 parents 8b39819 + b6cc096 commit b0c50b8

File tree

350 files changed

+94032
-69015
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

350 files changed

+94032
-69015
lines changed

.github/workflows/build.yml

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ jobs:
1818
apt-get -y install cargo libstd-rust-dev-wasm32 valgrind lld git g++ clang openjdk-11-jdk maven
1919
- name: Checkout source code
2020
uses: actions/checkout@v2
21+
with:
22+
fetch-depth: 0
2123
- name: Install cbindgen
2224
run: cargo install --force cbindgen
2325
- name: Checkout Rust-Lightning and LDK-C-Bindings git
2426
run: |
27+
git config --global user.email "[email protected]"
28+
git config --global user.name "LDK CI"
2529
git clone https://github.com/rust-bitcoin/rust-lightning
2630
cd rust-lightning
2731
git remote add matt https://git.bitcoin.ninja/rust-lightning
@@ -33,10 +37,16 @@ jobs:
3337
run: |
3438
cd ldk-c-bindings
3539
./genbindings.sh ../rust-lightning false
36-
mv target/wasm32-wasi ./
40+
mv lightning-c-bindings/target/wasm32-wasi ./
3741
cd ..
3842
- name: Rebuild C bindings, and check the sample app builds + links
39-
run: cd ldk-c-bindings && ./genbindings.sh ../rust-lightning true && mv wasm32-wasi target/ && cd ..
43+
run: |
44+
cd ldk-c-bindings
45+
# Reset the Cargo.toml file so that git describe doesn't think we're "-dirty"
46+
git checkout lightning-c-bindings/Cargo.toml
47+
./genbindings.sh ../rust-lightning true
48+
mv wasm32-wasi lightning-c-bindings/target/
49+
cd ..
4050
- name: Build Java/TS Debug Bindings
4151
run: ./genbindings.sh ./ldk-c-bindings/ "-I/usr/lib/jvm/java-11-openjdk-amd64/include/ -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux/" true false
4252
- name: Run Java Tests against Debug Bindings
@@ -49,7 +59,20 @@ jobs:
4959
mvn test
5060
git checkout liblightningjni.so
5161
- name: Build Java/TS Release Bindings
52-
run: ./genbindings.sh ./ldk-c-bindings/ "-I/usr/lib/jvm/java-11-openjdk-amd64/include/ -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux/" false false
62+
run: |
63+
# We assume the top commit is just a bindings update commit, so we
64+
# check out the previous commit to use as the commit we git describe.
65+
# If the top commit is a merge commit, we need to get the last merge
66+
# head and assume the latest bindings are built against its parent.
67+
COMMIT_PARENTS=$(git show -s --pretty=format:%P HEAD)
68+
if [ "${#COMMIT_PARENTS}" = 40 ]; then
69+
export LDK_GARBAGECOLLECTED_GIT_OVERRIDE="$(git describe --tag HEAD^1)"
70+
else
71+
MERGE_HEAD=$(git show --pretty=format:%P HEAD | ( for last in $(cat /dev/stdin); do true; done; echo $last ))
72+
export LDK_GARBAGECOLLECTED_GIT_OVERRIDE="$(git describe --tag $MERGE_HEAD^1)"
73+
fi
74+
echo "Using $LDK_GARBAGECOLLECTED_GIT_OVERRIDE as git version"
75+
./genbindings.sh ./ldk-c-bindings/ "-I/usr/lib/jvm/java-11-openjdk-amd64/include/ -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux/" false false
5376
- name: Check latest headers are in git
5477
run: |
5578
# For some reason the debug library is not deterministic, this may be fixed in a future rustc

gen_type_mapping.py

Lines changed: 35 additions & 24 deletions
Large diffs are not rendered by default.

genbindings.py

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python3
2-
import sys, re
2+
import os, sys, re, subprocess
33

44
if len(sys.argv) < 7:
55
print("USAGE: /path/to/lightning.h /path/to/bindings/output /path/to/bindings/ /path/to/bindings/output.c debug lang")
@@ -33,6 +33,10 @@
3333

3434
consts = Consts(DEBUG, target=target)
3535

36+
local_git_version = os.getenv("LDK_GARBAGECOLLECTED_GIT_OVERRIDE")
37+
if local_git_version is None:
38+
local_git_version = subprocess.check_output(["git", "describe", '--tag', '--dirty']).decode("utf-8").strip()
39+
3640
from bindingstypes import *
3741

3842
c_file = ""
@@ -121,6 +125,11 @@ def java_c_types(fn_arg, ret_arr_len):
121125
assert var_is_arr_regex.match(fn_arg[8:])
122126
rust_obj = "LDKSignature"
123127
arr_access = "compact_form"
128+
elif fn_arg.startswith("LDKRecoverableSignature"):
129+
fn_arg = "uint8_t (*" + fn_arg[25:] + ")[68]"
130+
assert var_is_arr_regex.match(fn_arg[8:])
131+
rust_obj = "LDKRecoverableSignature"
132+
arr_access = "serialized_form"
124133
elif fn_arg.startswith("LDKThreeBytes"):
125134
fn_arg = "uint8_t (*" + fn_arg[14:] + ")[3]"
126135
assert var_is_arr_regex.match(fn_arg[8:])
@@ -136,6 +145,11 @@ def java_c_types(fn_arg, ret_arr_len):
136145
assert var_is_arr_regex.match(fn_arg[8:])
137146
rust_obj = "LDKSixteenBytes"
138147
arr_access = "data"
148+
elif fn_arg.startswith("LDKTwentyBytes"):
149+
fn_arg = "uint8_t (*" + fn_arg[15:] + ")[20]"
150+
assert var_is_arr_regex.match(fn_arg[8:])
151+
rust_obj = "LDKTwentyBytes"
152+
arr_access = "data"
139153
elif fn_arg.startswith("LDKTenBytes"):
140154
fn_arg = "uint8_t (*" + fn_arg[12:] + ")[10]"
141155
assert var_is_arr_regex.match(fn_arg[8:])
@@ -210,6 +224,13 @@ def java_c_types(fn_arg, ret_arr_len):
210224
fn_ty_arg = "B"
211225
fn_arg = fn_arg[7:].strip()
212226
is_primitive = True
227+
elif fn_arg.startswith("LDKu5"):
228+
java_ty = consts.c_type_map['uint8_t'][0]
229+
java_hu_ty = "UInt5"
230+
rust_obj = "LDKu5"
231+
c_ty = "int8_t"
232+
fn_ty_arg = "B"
233+
fn_arg = fn_arg[6:].strip()
213234
elif fn_arg.startswith("uint16_t"):
214235
mapped_type = consts.c_type_map['uint16_t']
215236
java_ty = mapped_type[0]
@@ -243,6 +264,7 @@ def java_c_types(fn_arg, ret_arr_len):
243264
fn_ty_arg = "Ljava/lang/String;"
244265
fn_arg = fn_arg[6:].strip()
245266
elif fn_arg.startswith("LDKStr"):
267+
rust_obj = "LDKStr"
246268
java_ty = "String"
247269
c_ty = "jstring"
248270
fn_ty_arg = "Ljava/lang/String;"
@@ -252,9 +274,11 @@ def java_c_types(fn_arg, ret_arr_len):
252274
else:
253275
ma = var_ty_regex.match(fn_arg)
254276
if ma.group(1).strip() in unitary_enums:
255-
java_ty = ma.group(1).strip()
277+
assert ma.group(1).strip().startswith("LDK")
278+
java_ty = ma.group(1).strip()[3:]
279+
java_hu_ty = java_ty
256280
c_ty = consts.result_c_ty
257-
fn_ty_arg = "Lorg/ldk/enums/" + ma.group(1).strip() + ";"
281+
fn_ty_arg = "Lorg/ldk/enums/" + java_ty + ";"
258282
fn_arg = ma.group(2).strip()
259283
rust_obj = ma.group(1).strip()
260284
elif ma.group(1).strip().startswith("LDKC2Tuple"):
@@ -382,6 +406,7 @@ def java_c_types(fn_arg, ret_arr_len):
382406
def map_fn(line, re_match, ret_arr_len, c_call_string, doc_comment):
383407
method_return_type = re_match.group(1)
384408
method_name = re_match.group(2)
409+
orig_method_name = str(method_name)
385410
method_comma_separated_arguments = re_match.group(3)
386411
method_arguments = method_comma_separated_arguments.split(',')
387412

@@ -391,17 +416,20 @@ def map_fn(line, re_match, ret_arr_len, c_call_string, doc_comment):
391416
else:
392417
struct_meth = method_name.split("_")[0]
393418

394-
return_type_info = type_mapping_generator.map_type(method_return_type, True, ret_arr_len, False, False)
419+
return_type_info = type_mapping_generator.map_type(method_return_type.strip() + " ret", True, ret_arr_len, False, False)
395420

396421
argument_types = []
397422
default_constructor_args = {}
398423
takes_self = False
424+
takes_self_ptr = False
399425
args_known = True
400426

401427
for argument_index, argument in enumerate(method_arguments):
402428
argument_conversion_info = type_mapping_generator.map_type(argument, False, None, is_free, True)
403429
if argument_index == 0 and argument_conversion_info.java_hu_ty == struct_meth:
404430
takes_self = True
431+
if argument_conversion_info.ty_info.is_ptr:
432+
takes_self_ptr = True
405433
if argument_conversion_info.arg_conv is not None and "Warning" in argument_conversion_info.arg_conv:
406434
if argument_conversion_info.rust_obj in constructor_fns:
407435
assert not is_free
@@ -416,10 +444,14 @@ def map_fn(line, re_match, ret_arr_len, c_call_string, doc_comment):
416444
default_constructor_args[argument_conversion_info.arg_name] = []
417445
default_constructor_args[argument_conversion_info.arg_name].append(explode_arg_conv)
418446
argument_types.append(argument_conversion_info)
447+
if not takes_self and return_type_info.java_hu_ty != struct_meth:
448+
if not return_type_info.java_hu_ty.startswith("Result_" + struct_meth):
449+
method_name = orig_method_name
450+
struct_meth = ""
419451

420452
out_java.write("\t// " + line)
421453
(out_java_delta, out_c_delta, out_java_struct_delta) = \
422-
consts.map_function(argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, args_known, type_mapping_generator, doc_comment)
454+
consts.map_function(argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_ptr, args_known, type_mapping_generator, doc_comment)
423455
out_java.write(out_java_delta)
424456

425457
if is_free:
@@ -451,14 +483,23 @@ def map_fn(line, re_match, ret_arr_len, c_call_string, doc_comment):
451483
or expected_struct in complex_enums or expected_cstruct in complex_enums
452484
or expected_cstruct in result_types) and not is_free:
453485
out_java_struct = open(f"{sys.argv[3]}/structs/{struct_meth}{consts.file_ext}", "a")
454-
elif method_name.startswith("C2Tuple_") and method_name.endswith("_read"):
455-
struct_meth = method_name.rsplit("_", 1)[0]
456-
out_java_struct = open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a")
457-
if out_java_struct is not None:
458486
out_java_struct.write(out_java_struct_delta)
487+
elif (not is_free and not method_name.endswith("_clone") and
488+
not method_name.startswith("_") and
489+
method_name != "check_platform" and method_name != "Result_read" and
490+
not expected_struct in unitary_enums and
491+
((not method_name.startswith("C2Tuple_") and not method_name.startswith("C3Tuple_"))
492+
or method_name.endswith("_read"))):
493+
out_java_struct = open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a")
494+
for line in out_java_struct_delta.splitlines():
495+
if not line.strip().startswith("this."):
496+
out_java_struct.write(line + "\n")
497+
else:
498+
out_java_struct.write("\t\t// " + line.strip() + "\n")
459499

460500
def map_unitary_enum(struct_name, field_lines, enum_doc_comment):
461-
with open(f"{sys.argv[3]}/enums/{struct_name}{consts.file_ext}", "w") as out_java_enum:
501+
assert struct_name.startswith("LDK")
502+
with open(f"{sys.argv[3]}/enums/{struct_name[3:]}{consts.file_ext}", "w") as out_java_enum:
462503
unitary_enums.add(struct_name)
463504
for idx, struct_line in enumerate(field_lines):
464505
if idx == 0:
@@ -469,7 +510,8 @@ def map_unitary_enum(struct_name, field_lines, enum_doc_comment):
469510
assert(struct_line == "} %s;" % struct_name)
470511
elif idx == len(field_lines) - 1:
471512
assert(struct_line == "")
472-
(c_out, native_file_out, native_out) = consts.native_c_unitary_enum_map(struct_name, [x.strip().strip(",") for x in field_lines[1:-3]], enum_doc_comment)
513+
assert struct_name.startswith("LDK")
514+
(c_out, native_file_out, native_out) = consts.native_c_unitary_enum_map(struct_name[3:], [x.strip().strip(",") for x in field_lines[1:-3]], enum_doc_comment)
473515
write_c(c_out)
474516
out_java_enum.write(native_file_out)
475517
out_java.write(native_out)
@@ -495,7 +537,7 @@ def map_complex_enum(struct_name, union_enum_items, inline_enum_variants, enum_d
495537
if "LDK" + variant_name in union_enum_items:
496538
enum_var_lines = union_enum_items["LDK" + variant_name]
497539
for idx, field in enumerate(enum_var_lines):
498-
if idx != 0 and idx < len(enum_var_lines) - 2:
540+
if idx != 0 and idx < len(enum_var_lines) - 2 and field.strip() != "":
499541
fields.append(type_mapping_generator.map_type(field.strip(' ;'), False, None, False, True))
500542
enum_variants.append(ComplexEnumVariantInfo(variant_name, fields, False))
501543
elif camel_to_snake(variant_name) in inline_enum_variants:
@@ -528,7 +570,7 @@ def map_trait(struct_name, field_var_lines, trait_fn_lines, trait_doc_comment):
528570

529571
field_fns = []
530572
for fn_docs, fn_line in trait_fn_lines:
531-
ret_ty_info = type_mapping_generator.map_type(fn_line.group(2), True, None, False, False)
573+
ret_ty_info = type_mapping_generator.map_type(fn_line.group(2).strip() + " ret", True, None, False, False)
532574
is_const = fn_line.group(4) is not None
533575

534576
arg_tys = []
@@ -675,7 +717,7 @@ def map_tuple(struct_name, field_lines):
675717
write_c("\tret->" + e + " = " + e + ";\n")
676718
if ty_info.arg_conv_cleanup is not None:
677719
write_c("\t//TODO: Really need to call " + ty_info.arg_conv_cleanup + " here\n")
678-
write_c("\treturn (long)ret;\n")
720+
write_c("\treturn (uint64_t)ret;\n")
679721
write_c("}\n")
680722

681723
for idx, ty_info in enumerate(ty_list):
@@ -691,7 +733,7 @@ def map_tuple(struct_name, field_lines):
691733
write_c("\treturn tuple->" + e + ";\n")
692734
write_c("}\n")
693735

694-
out_java.write(consts.bindings_header)
736+
out_java.write(consts.bindings_header.replace('<git_version_ldk_garbagecollected>', local_git_version))
695737

696738
with open(f"{sys.argv[3]}/structs/CommonBase{consts.file_ext}", "w") as out_java_struct:
697739
out_java_struct.write(consts.common_base)
@@ -835,7 +877,7 @@ def map_tuple(struct_name, field_lines):
835877
if cleanup is not None:
836878
write_c("\t\t" + cleanup + ";\n")
837879
write_c("\t}\n")
838-
write_c("\treturn (long)ret;\n")
880+
write_c("\treturn (uint64_t)ret;\n")
839881
write_c("}\n")
840882

841883
if ty_info.is_native_primitive:
@@ -871,6 +913,8 @@ def map_tuple(struct_name, field_lines):
871913
line = line.strip()
872914
if line.startswith("struct "):
873915
line = line[7:]
916+
elif line.startswith("enum "):
917+
line = line[5:]
874918
split = line.split(" ")
875919
assert len(split) == 2
876920
tuple_variants[split[1].strip(";")] = split[0]
@@ -948,7 +992,7 @@ def map_tuple(struct_name, field_lines):
948992
out_java_struct.write("}\n")
949993

950994
with open(sys.argv[4], "w") as out_c:
951-
out_c.write(consts.c_file_pfx)
995+
out_c.write(consts.c_file_pfx.replace('<git_version_ldk_garbagecollected>', local_git_version))
952996
out_c.write(consts.init_str())
953997
out_c.write(c_file)
954998
with open(f"{sys.argv[3]}/structs/UtilMethods{consts.file_ext}", "a") as util:

genbindings.sh

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,17 @@ fi
1818

1919
set -e
2020

21+
if [ "$LDK_GARBAGECOLLECTED_GIT_OVERRIDE" = "" ]; then
22+
export LDK_GARBAGECOLLECTED_GIT_OVERRIDE=$(git describe --tag --dirty)
23+
fi
24+
2125
cp "$1/lightning-c-bindings/include/lightning.h" ./
22-
sed -i "s/TransactionOutputs/C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ/g" ./lightning.h
26+
if [ "$(rustc --version --verbose | grep "host:")" = "host: x86_64-apple-darwin" ]; then
27+
# OSX sed is for some reason not compatible with GNU sed
28+
sed -i '' "s/TransactionOutputs/C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ/g" ./lightning.h
29+
else
30+
sed -i "s/TransactionOutputs/C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ/g" ./lightning.h
31+
fi
2332

2433
echo "Creating Java bindings..."
2534
mkdir -p src/main/java/org/ldk/{enums,structs}
@@ -37,7 +46,7 @@ javac -h src/main/jni src/main/java/org/ldk/enums/*.java src/main/java/org/ldk/i
3746
rm src/main/java/org/ldk/enums/*.class src/main/java/org/ldk/impl/bindings*.class
3847

3948
echo "Building Java bindings..."
40-
COMPILE="$COMMON_COMPILE -Isrc/main/jni -pthread -ldl -Wl,--no-undefined -shared -fPIC"
49+
COMPILE="$COMMON_COMPILE -march=sandybridge -Isrc/main/jni -pthread -ldl -Wl,--no-undefined -shared -fPIC"
4150
if [ "$3" = "true" ]; then
4251
$COMPILE -o liblightningjni_debug.so -g -fsanitize=address -shared-libasan -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,reallocarray -Wl,-wrap,malloc -Wl,-wrap,free -rdynamic -I"$1"/lightning-c-bindings/include/ $2 src/main/jni/bindings.c "$1"/lightning-c-bindings/target/debug/libldk.a -lm
4352
else

0 commit comments

Comments
 (0)