Skip to content

Commit 64bcaa6

Browse files
authored
Merge pull request #74 from TheBlueMatt/2022-01-ts-hu-files
[TypeScript] Make Basic "Human" Object Construction Work
2 parents 2a65456 + 7d372e4 commit 64bcaa6

File tree

447 files changed

+38367
-33116
lines changed

Some content is hidden

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

447 files changed

+38367
-33116
lines changed

.github/workflows/build.yml

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
# Thus, we install the binary nodejs from nodejs.org and test with that.
5151
curl https://nodejs.org/dist/v16.13.1/node-v16.13.1-linux-x64.tar.xz > nodejs.tar.xz
5252
tar xvvf nodejs.tar.xz
53-
export PATH=$(echo node-*/bin):$PATH
53+
export PATH=$(pwd)/$(echo node-*/bin):$PATH
5454
./genbindings.sh ./ldk-c-bindings/ wasm false false
5555
- name: Build and Test TS Bindings for Web
5656
run: |
@@ -63,9 +63,10 @@ jobs:
6363
mkdir -p $HOME/.cache/ms-playwright # `playwright install` is too dumb to create this for us
6464
chmod -R 777 $HOME/
6565
npx playwright install
66-
export PATH=$(echo node-*/bin):$PATH
66+
export PATH=$(pwd)/$(echo node-*/bin):$PATH
67+
cd ts
6768
python3 -m http.server &
68-
node ts/test/browser.mjs
69+
node test/browser.mjs
6970
- name: Check latest TS files are in git
7071
run: |
7172
git diff --exit-code
@@ -104,8 +105,6 @@ jobs:
104105
- name: Rebuild C bindings, and check the sample app builds + links
105106
run: |
106107
cd ldk-c-bindings
107-
# Reset the Cargo.toml file so that git describe doesn't think we're "-dirty"
108-
git checkout lightning-c-bindings/Cargo.toml
109108
./genbindings.sh ../rust-lightning true
110109
- name: Build Java Debug Bindings
111110
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
@@ -114,6 +113,49 @@ jobs:
114113
mv liblightningjni_debug_Linux-amd64.so liblightningjni.so
115114
export ASAN_OPTIONS=detect_leaks=0
116115
LD_PRELOAD=/usr/lib/llvm-11/lib/clang/11.0.1/lib/linux/libclang_rt.asan-x86_64.so LD_LIBRARY_PATH=. mvn test
116+
- name: Build Java Release Bindings
117+
run: |
118+
./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
119+
- name: Check latest headers are in git
120+
run: |
121+
git checkout pom.xml
122+
git diff --exit-code
123+
124+
java_determinism:
125+
runs-on: ubuntu-latest
126+
# Ubuntu's version of rustc uses its own LLVM instead of being a real native package.
127+
# This leaves us with an incompatible LLVM version when linking. Instead, use a real OS.
128+
container: debian:bullseye
129+
strategy:
130+
fail-fast: false
131+
steps:
132+
- name: Install native Rust toolchain, Valgrind, and build utilitis
133+
run: |
134+
apt-get update
135+
apt-get -y dist-upgrade
136+
apt-get -y install cargo valgrind lld git g++ clang openjdk-11-jdk maven faketime zip unzip llvm curl
137+
- name: Checkout source code
138+
uses: actions/checkout@v2
139+
with:
140+
fetch-depth: 0
141+
- name: Install cbindgen
142+
run: cargo install --force cbindgen
143+
- name: Checkout Rust-Lightning and LDK-C-Bindings git
144+
run: |
145+
git config --global user.email "[email protected]"
146+
git config --global user.name "LDK CI"
147+
# Note this is a different endpoint, as we need one non-upstream commit!
148+
git clone https://git.bitcoin.ninja/rust-lightning
149+
cd rust-lightning
150+
git checkout origin/2021-03-java-bindings-base
151+
cd ..
152+
git clone https://github.com/lightningdevkit/ldk-c-bindings
153+
cd ldk-c-bindings
154+
git checkout 0.0.104
155+
- name: Rebuild C bindings, and check the sample app builds + links
156+
run: |
157+
cd ldk-c-bindings
158+
./genbindings.sh ../rust-lightning true
117159
- name: Checkout latest MacOS binaries
118160
run: |
119161
export LDK_GARBAGECOLLECTED_GIT_OVERRIDE="$(git describe --tag HEAD)"
@@ -135,10 +177,6 @@ jobs:
135177
./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
136178
- name: Build deterministic release jar
137179
run: ./build-release-jar.sh
138-
- name: Check latest headers are in git
139-
run: |
140-
git checkout pom.xml
141-
git diff --exit-code
142180
- name: Check latest library and jars are in bins repo
143181
run: |
144182
export LDK_GARBAGECOLLECTED_GIT_OVERRIDE="$(git describe --tag HEAD)"

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ To build for Apple M1 (ie aarch64-apple-darwin), you probably want something lik
3939
Status
4040
======
4141

42-
The TypeScript Bindings are still in early development and generated code contains syntax errors.
42+
## Java
4343

4444
While the underlying library and C bindings are relatively mature, the Java bindings should be
4545
considered beta quality and some issues may still appear. Specifically, because the Java bindings
@@ -53,6 +53,17 @@ exit there will likely be many false positives. While it will require some compl
5353
are likely some use-after-free or unkonwn-free bugs remaining. The debug-mode build links LLVM
5454
address sanitizer and will print diagnostic information in case of such issues.
5555

56+
## TypeScript
57+
58+
The TypeScript bindings are functionally complete, but should be considered early alpha quality.
59+
Some functions may error spuriously due to oversights or missing implementations.
60+
61+
The TypeScript bindings require modern web standards, including support for `FinalizationRegistry`
62+
and `WeakRef` (Chrome 84, Firefox 79, Safari 14.1/iOS 14.5 and Node 14.6) and WASM BigInt support
63+
(Chrome 85, Firefox 78, Safari 14.1/iOS 14.5, and Node ??).
64+
65+
## General
66+
5667
The only known issue resulting in a use-after-free bug requires custom a custom ChannelKeys instance
5768
created as a part of a new channel. After the channel is created, the ChannelKeys object will not
5869
be freed while the parent ChannelManager exists, however if the ChannelManager is garbage collected

gen_type_mapping.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ def _do_map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, hold
4747
(set_pfx, set_sfx) = self.consts.set_native_arr_contents(arr_name + "_arr", arr_len, ty_info)
4848
ret_conv = ("int8_tArray " + arr_name + "_arr = " + self.consts.create_native_arr_call(arr_len, ty_info) + ";\n" + set_pfx, "")
4949
arg_conv_cleanup = None
50-
from_hu_conv = None
5150
if not arr_len.isdigit():
5251
arg_conv = ty_info.rust_obj + " " + arr_name + "_ref;\n"
5352
arg_conv = arg_conv + arr_name + "_ref." + arr_len + " = " + self.consts.get_native_arr_len_call[0] + arr_name + self.consts.get_native_arr_len_call[1] + ";\n"
@@ -65,26 +64,34 @@ def _do_map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, hold
6564
ret_conv = (ret_conv[0], ret_conv[1] + pfx + arr_name + "_var." + ty_info.arr_access + sfx + ";")
6665
if not holds_ref and ty_info.rust_obj != "LDKu8slice":
6766
ret_conv = (ret_conv[0], ret_conv[1] + "\n" + ty_info.rust_obj.replace("LDK", "") + "_free(" + arr_name + "_var);")
67+
from_hu_conv = self.consts.primitive_arr_from_hu(ty_info.subty, None, arr_name)
68+
to_hu_conv = self.consts.primitive_arr_to_hu(ty_info.subty, None, arr_name, arr_name + "_conv")
6869
elif ty_info.rust_obj is not None:
6970
arg_conv = ty_info.rust_obj + " " + arr_name + "_ref;\n"
7071
arg_conv = arg_conv + "CHECK(" + self.consts.get_native_arr_len_call[0] + arr_name + self.consts.get_native_arr_len_call[1] + " == " + arr_len + ");\n"
7172
arg_conv = arg_conv + self.consts.get_native_arr_contents(arr_name, arr_name + "_ref." + ty_info.arr_access, arr_len, ty_info, True) + ";"
7273
ret_conv = (ret_conv[0], "." + ty_info.arr_access + set_sfx + ";")
73-
from_hu_conv = ("InternalUtils.check_arr_len(" + arr_name + ", " + arr_len + ")", "")
74+
from_hu_conv = self.consts.primitive_arr_from_hu(ty_info.subty, arr_len, arr_name)
75+
to_hu_conv = self.consts.primitive_arr_to_hu(ty_info.subty, None, arr_name, arr_name + "_conv")
7476
else:
7577
arg_conv = "unsigned char " + arr_name + "_arr[" + arr_len + "];\n"
7678
arg_conv = arg_conv + "CHECK(" + self.consts.get_native_arr_len_call[0] + arr_name + self.consts.get_native_arr_len_call[1] + " == " + arr_len + ");\n"
7779
arg_conv = arg_conv + self.consts.get_native_arr_contents(arr_name, arr_name + "_arr", arr_len, ty_info, True) + ";\n"
7880
arg_conv = arg_conv + "unsigned char (*" + arr_name + "_ref)[" + arr_len + "] = &" + arr_name + "_arr;"
7981
ret_conv = (ret_conv[0] + "*", set_sfx + ";")
80-
from_hu_conv = ("InternalUtils.check_arr_len(" + arr_name + ", " + arr_len + ")", "")
82+
from_hu_conv = self.consts.primitive_arr_from_hu(ty_info.subty, arr_len, arr_name)
83+
to_hu_conv = self.consts.primitive_arr_to_hu(ty_info.subty, None, arr_name, arr_name + "_conv")
84+
to_hu_conv_name = None
85+
if to_hu_conv is not None:
86+
to_hu_conv_name = arr_name + "_conv"
8187
return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
8288
arg_conv = arg_conv, arg_conv_name = arr_name + "_ref", arg_conv_cleanup = arg_conv_cleanup,
83-
ret_conv = ret_conv, ret_conv_name = arr_name + "_arr", to_hu_conv = None, to_hu_conv_name = None,
89+
ret_conv = ret_conv, ret_conv_name = arr_name + "_arr",
90+
to_hu_conv = to_hu_conv, to_hu_conv_name = to_hu_conv_name,
8491
from_hu_conv = from_hu_conv)
8592
else:
8693
assert not arr_len.isdigit() # fixed length arrays not implemented
87-
assert ty_info.java_ty[len(ty_info.java_ty) - 2:] == "[]"
94+
assert ty_info.java_hu_ty[len(ty_info.java_hu_ty) - 2:] == "[]"
8895
if arr_name == "":
8996
arr_name = "ret"
9097
conv_name = arr_name + "_conv_" + str(len(ty_info.java_hu_ty))
@@ -183,24 +190,30 @@ def _do_map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, hold
183190
to_hu_conv = None
184191
to_hu_conv_name = None
185192
if subty.to_hu_conv is not None:
186-
to_hu_conv = self.consts.var_decl_statement(ty_info.java_hu_ty, conv_name + "_arr", self.consts.constr_hu_array(ty_info, arr_name + ".length"))
187-
to_hu_conv += ";\n" + self.consts.for_n_in_range(idxc, "0", arr_name + ".length") + "\n"
188-
to_hu_conv += "\t" + self.consts.var_decl_statement(subty.java_ty, conv_name, arr_name + "[" + idxc + "]") + ";\n"
193+
to_hu_conv = self.consts.var_decl_statement(self.consts.c_type_map["uint32_t"][0], conv_name + "_len", self.consts.get_java_arr_len(arr_name)) + ";\n"
194+
to_hu_conv += self.consts.var_decl_statement(ty_info.java_hu_ty, conv_name + "_arr", self.consts.constr_hu_array(ty_info, conv_name + "_len"))
195+
to_hu_conv += ";\n" + self.consts.for_n_in_range(idxc, "0", conv_name + "_len") + "\n"
196+
to_hu_conv += "\t" + self.consts.var_decl_statement(subty.java_ty, conv_name, self.consts.get_java_arr_elem(subty, arr_name, idxc)) + ";\n"
189197
to_hu_conv += "\t" + subty.to_hu_conv.replace("\n", "\n\t") + "\n"
190198
to_hu_conv += "\t" + conv_name + "_arr[" + idxc + "] = " + subty.to_hu_conv_name + ";\n}"
191199
to_hu_conv_name = conv_name + "_arr"
192-
from_hu_conv = None
200+
from_hu_conv = self.consts.primitive_arr_from_hu(ty_info.subty, None, arr_name)
193201
if subty.from_hu_conv is not None:
194202
hu_conv_b = ""
195203
if subty.from_hu_conv[1] != "":
196204
iterator = self.consts.for_n_in_arr(conv_name, arr_name, subty)
197205
hu_conv_b = iterator[0] + subty.from_hu_conv[1] + ";" + iterator[1]
198-
from_hu_conv = (self.consts.map_hu_array_elems(arr_name, conv_name, ty_info, subty), hu_conv_b)
206+
if from_hu_conv is not None:
207+
arr_conv = self.consts.primitive_arr_from_hu(ty_info.subty, None, self.consts.map_hu_array_elems(arr_name, conv_name, ty_info, subty))
208+
assert arr_conv[1] == ""
209+
from_hu_conv = (arr_conv[0], hu_conv_b)
210+
else:
211+
from_hu_conv = (self.consts.map_hu_array_elems(arr_name, conv_name, ty_info, subty), hu_conv_b)
199212

200213
return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
201214
arg_conv = arg_conv, arg_conv_name = arg_conv_name, arg_conv_cleanup = arg_conv_cleanup,
202215
ret_conv = ret_conv, ret_conv_name = arr_name + "_arr", to_hu_conv = to_hu_conv, to_hu_conv_name = to_hu_conv_name, from_hu_conv = from_hu_conv)
203-
elif ty_info.java_ty == "String":
216+
elif ty_info.java_fn_ty_arg == "Ljava/lang/String;":
204217
assert not is_nullable
205218
if not is_free:
206219
arg_conv = "LDKStr " + ty_info.var_name + "_conv = " + self.consts.str_ref_to_c_call(ty_info.var_name) + ";"
@@ -209,6 +222,7 @@ def _do_map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, hold
209222
arg_conv = "LDKStr dummy = { .chars = NULL, .len = 0, .chars_is_owned = false };"
210223
arg_conv_name = "dummy"
211224
if ty_info.arr_access is None:
225+
assert False
212226
return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
213227
arg_conv = arg_conv, arg_conv_name = arg_conv_name, arg_conv_cleanup = None,
214228
ret_conv = ("const char* " + ty_info.var_name + "_str = ",
@@ -219,11 +233,17 @@ def _do_map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, hold
219233
free_str = ""
220234
if not holds_ref:
221235
free_str = "\nStr_free(" + ty_info.var_name + "_str);"
236+
to_hu_conv = self.consts.str_to_hu_conv(ty_info.var_name)
237+
to_hu_conv_name = None
238+
if to_hu_conv is not None:
239+
to_hu_conv_name = ty_info.var_name + "_conv"
222240
return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
223241
arg_conv = arg_conv, arg_conv_name = arg_conv_name, arg_conv_cleanup = None,
224242
ret_conv = ("LDKStr " + ty_info.var_name + "_str = ",
225243
";\njstring " + ty_info.var_name + "_conv = " + self.consts.str_ref_to_native_call(ty_info.var_name + "_str." + ty_info.arr_access, ty_info.var_name + "_str." + ty_info.arr_len) + ";" + free_str),
226-
ret_conv_name = ty_info.var_name + "_conv", to_hu_conv = None, to_hu_conv_name = None, from_hu_conv = None)
244+
ret_conv_name = ty_info.var_name + "_conv",
245+
to_hu_conv=to_hu_conv, to_hu_conv_name=to_hu_conv_name,
246+
from_hu_conv = self.consts.str_from_hu_conv(ty_info.var_name))
227247
elif ty_info.var_name == "" and not print_void:
228248
# We don't have a parameter name, and want one, just call it arg
229249
if not ty_info.is_native_primitive:
@@ -534,9 +554,12 @@ def _do_map_type_with_info(self, ty_info, print_void, ret_arr_len, is_free, hold
534554
to_hu_conv = self.consts.var_decl_statement(ty_info.java_hu_ty, "ret_hu_conv", "new " + ty_info.java_hu_ty + "(null, " + ty_info.var_name + ")") + ";\n" + self.consts.add_ref("ret_hu_conv", "this") + ";",
535555
to_hu_conv_name = "ret_hu_conv",
536556
from_hu_conv = (ty_info.var_name + " == null ? 0 : " + self.consts.get_ptr(ty_info.var_name), self.consts.add_ref("this", ty_info.var_name)))
557+
ret_conv = ("uint64_t ret_" + ty_info.var_name + " = (uint64_t)", ";")
558+
if holds_ref:
559+
ret_conv = (ret_conv[0], " | 1;")
537560
return ConvInfo(ty_info = ty_info, arg_name = ty_info.var_name,
538561
arg_conv = ty_info.rust_obj + "* " + ty_info.var_name + "_conv = (" + ty_info.rust_obj + "*)(" + ty_info.var_name + " & ~1);",
539562
arg_conv_name = ty_info.var_name + "_conv", arg_conv_cleanup = None,
540-
ret_conv = ("uint64_t ret_" + ty_info.var_name + " = (uint64_t)", ";"), ret_conv_name = "ret_" + ty_info.var_name,
563+
ret_conv = ret_conv, ret_conv_name = "ret_" + ty_info.var_name,
541564
to_hu_conv = "TODO 3", to_hu_conv_name = None, from_hu_conv = None) # its a pointer, no conv needed
542565
assert False # We should have handled every case by now.

0 commit comments

Comments
 (0)