Skip to content

Commit 59d2040

Browse files
authored
Merge pull request #811 from TheBlueMatt/2021-02-bindings-rust-bump
Update bindings for new Listen interface
2 parents 9fba7c9 + ee9ceb4 commit 59d2040

File tree

15 files changed

+243
-88
lines changed

15 files changed

+243
-88
lines changed

c-bindings-gen/README.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
LDK C Bindings Generator
2+
========================
3+
4+
This program parses a Rust crate's AST from a single lib.rs passed in on stdin and generates a
5+
second crate which is C-callable (and carries appropriate annotations for cbindgen). It is usually
6+
invoked via the `genbindings.sh` script in the top-level directory, which converts the lightning
7+
crate into a single file with a call to
8+
`RUSTC_BOOTSTRAP=1 cargo rustc --profile=check -- -Zunstable-options --pretty=expanded`.
9+
10+
`genbindings.sh` requires that you have a rustc installed with the `wasm32-wasi` target available
11+
(eg via the `libstd-rust-dev-wasm32` package on Debian or `rustup target add wasm32-wasi` for those
12+
using rustup), cbindgen installed via `cargo install cbindgen` and in your `PATH`, and `clang`,
13+
`clang++`, `gcc`, and `g++` available in your `PATH`. It uses `valgrind` if it is available to test
14+
the generated bindings thoroughly for memory management issues.

c-bindings-gen/src/main.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -835,10 +835,16 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
835835
takes_self = true;
836836
}
837837
}
838+
839+
let mut t_gen_args = String::new();
840+
for (idx, _) in $trait.generics.params.iter().enumerate() {
841+
if idx != 0 { t_gen_args += ", " };
842+
t_gen_args += "_"
843+
}
838844
if takes_self {
839-
write!(w, "unsafe {{ &mut *(this_arg as *mut native{}) }}.{}(", ident, $m.sig.ident).unwrap();
845+
write!(w, "<native{} as {}TraitImport<{}>>::{}(unsafe {{ &mut *(this_arg as *mut native{}) }}, ", ident, $trait.ident, t_gen_args, $m.sig.ident, ident).unwrap();
840846
} else {
841-
write!(w, "{}::{}::{}(", types.orig_crate, resolved_path, $m.sig.ident).unwrap();
847+
write!(w, "<native{} as {}TraitImport<{}>>::{}(", ident, $trait.ident, t_gen_args, $m.sig.ident).unwrap();
842848
}
843849

844850
let mut real_type = "".to_string();

c-bindings-gen/src/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
587587
/// Returns true we if can just skip passing this to C entirely
588588
fn no_arg_path_to_rust(&self, full_path: &str) -> &str {
589589
if full_path == "bitcoin::secp256k1::Secp256k1" {
590-
"&bitcoin::secp256k1::Secp256k1::new()"
590+
"secp256k1::SECP256K1"
591591
} else { unimplemented!(); }
592592
}
593593

genbindings.sh

+11
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,16 @@ HOST_PLATFORM="$(rustc --version --verbose | grep "host:")"
4444
if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then
4545
# OSX sed is for some reason not compatible with GNU sed
4646
sed -i '' 's/typedef LDKnative.*Import.*LDKnative.*;//g' include/lightning.h
47+
48+
# stdlib.h doesn't exist in clang's wasm sysroot, and cbindgen
49+
# doesn't actually use it anyway, so drop the import.
50+
sed -i '' 's/#include <stdlib.h>//g' include/lightning.h
4751
else
4852
sed -i 's/typedef LDKnative.*Import.*LDKnative.*;//g' include/lightning.h
53+
54+
# stdlib.h doesn't exist in clang's wasm sysroot, and cbindgen
55+
# doesn't actually use it anyway, so drop the import.
56+
sed -i 's/#include <stdlib.h>//g' include/lightning.h
4957
fi
5058

5159
# Finally, sanity-check the generated C and C++ bindings with demo apps:
@@ -171,6 +179,9 @@ else
171179
echo "WARNING: Can't use address sanitizer on non-Linux, non-OSX non-x86 platforms"
172180
fi
173181

182+
cargo rustc -v --target=wasm32-wasi -- -C embed-bitcode=yes || echo "WARNING: Failed to generate WASM LLVM-bitcode-embedded library"
183+
CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release --target=wasm32-wasi -- -C opt-level=s -C linker-plugin-lto -C lto || echo "WARNING: Failed to generate WASM LLVM-bitcode-embedded optimized library"
184+
174185
# Now build with LTO on on both C++ and rust, but without cross-language LTO:
175186
CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C lto
176187
clang++ $CFLAGS -std=c++11 -flto -O2 demo.cpp target/release/libldk.a -ldl

lightning-c-bindings/Cargo.toml

+12
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,20 @@ crate-type = ["staticlib"
1616

1717
[dependencies]
1818
bitcoin = "0.26"
19+
secp256k1 = { version = "0.20.1", features = ["global-context-less-secure"] }
1920
lightning = { version = "0.0.12", path = "../lightning" }
2021

22+
[patch.crates-io]
23+
# Rust-Secp256k1 PR 279. Should be dropped once merged.
24+
secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1', rev = '15a0d4195a20355f6b1e8f54c84eba56abc15cbd' }
25+
26+
# Always force panic=abort, further options are set in the genbindings.sh build script
27+
[profile.dev]
28+
panic = "abort"
29+
30+
[profile.release]
31+
panic = "abort"
32+
2133
# We eventually want to join the root workspace, but for now, the bindings generation is
2234
# a bit brittle and we don't want to hold up other developers from making changes just
2335
# because they break the bindings

lightning-c-bindings/include/lightning.h

+31-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <stdarg.h>
88
#include <stdbool.h>
99
#include <stdint.h>
10-
#include <stdlib.h>
10+
1111

1212
/**
1313
* An error when accessing the chain via [`Access`].
@@ -174,8 +174,8 @@ typedef enum LDKSecp256k1Error {
174174
LDKSecp256k1Error_InvalidSecretKey,
175175
LDKSecp256k1Error_InvalidRecoveryId,
176176
LDKSecp256k1Error_InvalidTweak,
177+
LDKSecp256k1Error_TweakCheckFailed,
177178
LDKSecp256k1Error_NotEnoughMemory,
178-
LDKSecp256k1Error_CallbackPanicked,
179179
/**
180180
* Must be last for serialization purposes
181181
*/
@@ -3451,6 +3451,25 @@ typedef struct LDKAccess {
34513451
void (*free)(void *this_arg);
34523452
} LDKAccess;
34533453

3454+
/**
3455+
* The `Listen` trait is used to be notified of when blocks have been connected or disconnected
3456+
* from the chain.
3457+
*
3458+
* Useful when needing to replay chain data upon startup or as new chain events occur.
3459+
*/
3460+
typedef struct LDKListen {
3461+
void *this_arg;
3462+
/**
3463+
* Notifies the listener that a block was added at the given height.
3464+
*/
3465+
void (*block_connected)(const void *this_arg, struct LDKu8slice block, uint32_t height);
3466+
/**
3467+
* Notifies the listener that a block was removed at the given height.
3468+
*/
3469+
void (*block_disconnected)(const void *this_arg, const uint8_t (*header)[80], uint32_t height);
3470+
void (*free)(void *this_arg);
3471+
} LDKListen;
3472+
34543473
/**
34553474
* The `Filter` trait defines behavior for indicating chain activity of interest pertaining to
34563475
* channels.
@@ -3629,7 +3648,7 @@ typedef struct LDKChannelMessageHandler {
36293648
/**
36303649
* Handle an incoming shutdown message from the given peer.
36313650
*/
3632-
void (*handle_shutdown)(const void *this_arg, struct LDKPublicKey their_node_id, const struct LDKShutdown *NONNULL_PTR msg);
3651+
void (*handle_shutdown)(const void *this_arg, struct LDKPublicKey their_node_id, const struct LDKInitFeatures *NONNULL_PTR their_features, const struct LDKShutdown *NONNULL_PTR msg);
36333652
/**
36343653
* Handle an incoming closing_signed message from the given peer.
36353654
*/
@@ -5117,6 +5136,11 @@ enum LDKAccessError AccessError_clone(const enum LDKAccessError *NONNULL_PTR ori
51175136
*/
51185137
void Access_free(struct LDKAccess this_ptr);
51195138

5139+
/**
5140+
* Calls the free function if one is set
5141+
*/
5142+
void Listen_free(struct LDKListen this_ptr);
5143+
51205144
/**
51215145
* Calls the free function if one is set
51225146
*/
@@ -5667,8 +5691,8 @@ void KeysManager_free(struct LDKKeysManager this_ptr);
56675691
MUST_USE_RES struct LDKKeysManager KeysManager_new(const uint8_t (*seed)[32], uint64_t starting_time_secs, uint32_t starting_time_nanos);
56685692

56695693
/**
5670-
* Derive an old set of Sign for per-channel secrets based on a key derivation
5671-
* parameters.
5694+
* Derive an old Sign containing per-channel secrets based on a key derivation parameters.
5695+
*
56725696
* Key derivation parameters are accessible through a per-channel secrets
56735697
* Sign::channel_keys_id and is provided inside DynamicOuputP2WSH in case of
56745698
* onchain output detection for which a corresponding delayed_payment_key must be derived.
@@ -6029,6 +6053,8 @@ struct LDKMessageSendEventsProvider ChannelManager_as_MessageSendEventsProvider(
60296053

60306054
struct LDKEventsProvider ChannelManager_as_EventsProvider(const struct LDKChannelManager *NONNULL_PTR this_arg);
60316055

6056+
struct LDKListen ChannelManager_as_Listen(const struct LDKChannelManager *NONNULL_PTR this_arg);
6057+
60326058
/**
60336059
* Updates channel state based on transactions seen in a connected block.
60346060
*/

lightning-c-bindings/include/lightningpp.hpp

+15
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,21 @@ class Access {
702702
const LDKAccess* operator &() const { return &self; }
703703
const LDKAccess* operator ->() const { return &self; }
704704
};
705+
class Listen {
706+
private:
707+
LDKListen self;
708+
public:
709+
Listen(const Listen&) = delete;
710+
Listen(Listen&& o) : self(o.self) { memset(&o, 0, sizeof(Listen)); }
711+
Listen(LDKListen&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKListen)); }
712+
operator LDKListen() && { LDKListen res = self; memset(&self, 0, sizeof(LDKListen)); return res; }
713+
~Listen() { Listen_free(self); }
714+
Listen& operator=(Listen&& o) { Listen_free(self); self = o.self; memset(&o, 0, sizeof(Listen)); return *this; }
715+
LDKListen* operator &() { return &self; }
716+
LDKListen* operator ->() { return &self; }
717+
const LDKListen* operator &() const { return &self; }
718+
const LDKListen* operator ->() const { return &self; }
719+
};
705720
class Watch {
706721
private:
707722
LDKWatch self;

lightning-c-bindings/src/chain/chainmonitor.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -140,19 +140,19 @@ pub extern "C" fn ChainMonitor_as_Watch(this_arg: &ChainMonitor) -> crate::chain
140140
use lightning::chain::Watch as WatchTraitImport;
141141
#[must_use]
142142
extern "C" fn ChainMonitor_Watch_watch_channel(this_arg: *const c_void, mut funding_outpoint: crate::chain::transaction::OutPoint, mut monitor: crate::chain::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ {
143-
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.watch_channel(*unsafe { Box::from_raw(funding_outpoint.take_inner()) }, *unsafe { Box::from_raw(monitor.take_inner()) });
143+
let mut ret = <nativeChainMonitor as WatchTraitImport<_>>::watch_channel(unsafe { &mut *(this_arg as *mut nativeChainMonitor) }, *unsafe { Box::from_raw(funding_outpoint.take_inner()) }, *unsafe { Box::from_raw(monitor.take_inner()) });
144144
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::chain::channelmonitor::ChannelMonitorUpdateErr::native_into(e) }).into() };
145145
local_ret
146146
}
147147
#[must_use]
148148
extern "C" fn ChainMonitor_Watch_update_channel(this_arg: *const c_void, mut funding_txo: crate::chain::transaction::OutPoint, mut update: crate::chain::channelmonitor::ChannelMonitorUpdate) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ {
149-
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.update_channel(*unsafe { Box::from_raw(funding_txo.take_inner()) }, *unsafe { Box::from_raw(update.take_inner()) });
149+
let mut ret = <nativeChainMonitor as WatchTraitImport<_>>::update_channel(unsafe { &mut *(this_arg as *mut nativeChainMonitor) }, *unsafe { Box::from_raw(funding_txo.take_inner()) }, *unsafe { Box::from_raw(update.take_inner()) });
150150
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::chain::channelmonitor::ChannelMonitorUpdateErr::native_into(e) }).into() };
151151
local_ret
152152
}
153153
#[must_use]
154154
extern "C" fn ChainMonitor_Watch_release_pending_monitor_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MonitorEventZ {
155-
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.release_pending_monitor_events();
155+
let mut ret = <nativeChainMonitor as WatchTraitImport<_>>::release_pending_monitor_events(unsafe { &mut *(this_arg as *mut nativeChainMonitor) }, );
156156
let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::chain::channelmonitor::MonitorEvent::native_into(item) }); };
157157
local_ret.into()
158158
}
@@ -178,7 +178,7 @@ pub extern "C" fn ChainMonitor_as_EventsProvider(this_arg: &ChainMonitor) -> cra
178178
use lightning::util::events::EventsProvider as EventsProviderTraitImport;
179179
#[must_use]
180180
extern "C" fn ChainMonitor_EventsProvider_get_and_clear_pending_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_EventZ {
181-
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.get_and_clear_pending_events();
181+
let mut ret = <nativeChainMonitor as EventsProviderTraitImport<>>::get_and_clear_pending_events(unsafe { &mut *(this_arg as *mut nativeChainMonitor) }, );
182182
let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::Event::native_into(item) }); };
183183
local_ret.into()
184184
}

0 commit comments

Comments
 (0)