Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update bindings for new Listen interface #811

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions c-bindings-gen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
LDK C Bindings Generator
========================

This program parses a Rust crate's AST from a single lib.rs passed in on stdin and generates a
second crate which is C-callable (and carries appropriate annotations for cbindgen). It is usually
invoked via the `genbindings.sh` script in the top-level directory, which converts the lightning
crate into a single file with a call to
`RUSTC_BOOTSTRAP=1 cargo rustc --profile=check -- -Zunstable-options --pretty=expanded`.

`genbindings.sh` requires that you have a rustc installed with the `wasm32-wasi` target available
(eg via the `libstd-rust-dev-wasm32` package on Debian or `rustup target add wasm32-wasi` for those
using rustup), cbindgen installed via `cargo install cbindgen` and in your `PATH`, and `clang`,
`clang++`, `gcc`, and `g++` available in your `PATH`. It uses `valgrind` if it is available to test
the generated bindings thoroughly for memory management issues.
10 changes: 8 additions & 2 deletions c-bindings-gen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,10 +835,16 @@ fn writeln_impl<W: std::io::Write>(w: &mut W, i: &syn::ItemImpl, types: &mut Typ
takes_self = true;
}
}

let mut t_gen_args = String::new();
for (idx, _) in $trait.generics.params.iter().enumerate() {
if idx != 0 { t_gen_args += ", " };
t_gen_args += "_"
}
if takes_self {
write!(w, "unsafe {{ &mut *(this_arg as *mut native{}) }}.{}(", ident, $m.sig.ident).unwrap();
write!(w, "<native{} as {}TraitImport<{}>>::{}(unsafe {{ &mut *(this_arg as *mut native{}) }}, ", ident, $trait.ident, t_gen_args, $m.sig.ident, ident).unwrap();
} else {
write!(w, "{}::{}::{}(", types.orig_crate, resolved_path, $m.sig.ident).unwrap();
write!(w, "<native{} as {}TraitImport<{}>>::{}(", ident, $trait.ident, t_gen_args, $m.sig.ident).unwrap();
}

let mut real_type = "".to_string();
Expand Down
2 changes: 1 addition & 1 deletion c-bindings-gen/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> {
/// Returns true we if can just skip passing this to C entirely
fn no_arg_path_to_rust(&self, full_path: &str) -> &str {
if full_path == "bitcoin::secp256k1::Secp256k1" {
"&bitcoin::secp256k1::Secp256k1::new()"
"secp256k1::SECP256K1"
} else { unimplemented!(); }
}

Expand Down
11 changes: 11 additions & 0 deletions genbindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,16 @@ HOST_PLATFORM="$(rustc --version --verbose | grep "host:")"
if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then
# OSX sed is for some reason not compatible with GNU sed
sed -i '' 's/typedef LDKnative.*Import.*LDKnative.*;//g' include/lightning.h

# stdlib.h doesn't exist in clang's wasm sysroot, and cbindgen
# doesn't actually use it anyway, so drop the import.
sed -i '' 's/#include <stdlib.h>//g' include/lightning.h
else
sed -i 's/typedef LDKnative.*Import.*LDKnative.*;//g' include/lightning.h

# stdlib.h doesn't exist in clang's wasm sysroot, and cbindgen
# doesn't actually use it anyway, so drop the import.
sed -i 's/#include <stdlib.h>//g' include/lightning.h
fi

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

cargo rustc -v --target=wasm32-wasi -- -C embed-bitcode=yes || echo "WARNING: Failed to generate WASM LLVM-bitcode-embedded library"
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"

# Now build with LTO on on both C++ and rust, but without cross-language LTO:
CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C lto
clang++ $CFLAGS -std=c++11 -flto -O2 demo.cpp target/release/libldk.a -ldl
Expand Down
12 changes: 12 additions & 0 deletions lightning-c-bindings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@ crate-type = ["staticlib"

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

[patch.crates-io]
# Rust-Secp256k1 PR 279. Should be dropped once merged.
secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1', rev = '15a0d4195a20355f6b1e8f54c84eba56abc15cbd' }

# Always force panic=abort, further options are set in the genbindings.sh build script
[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"

# We eventually want to join the root workspace, but for now, the bindings generation is
# a bit brittle and we don't want to hold up other developers from making changes just
# because they break the bindings
Expand Down
36 changes: 31 additions & 5 deletions lightning-c-bindings/include/lightning.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>


/**
* An error when accessing the chain via [`Access`].
Expand Down Expand Up @@ -174,8 +174,8 @@ typedef enum LDKSecp256k1Error {
LDKSecp256k1Error_InvalidSecretKey,
LDKSecp256k1Error_InvalidRecoveryId,
LDKSecp256k1Error_InvalidTweak,
LDKSecp256k1Error_TweakCheckFailed,
LDKSecp256k1Error_NotEnoughMemory,
LDKSecp256k1Error_CallbackPanicked,
/**
* Must be last for serialization purposes
*/
Expand Down Expand Up @@ -3451,6 +3451,25 @@ typedef struct LDKAccess {
void (*free)(void *this_arg);
} LDKAccess;

/**
* The `Listen` trait is used to be notified of when blocks have been connected or disconnected
* from the chain.
*
* Useful when needing to replay chain data upon startup or as new chain events occur.
*/
typedef struct LDKListen {
void *this_arg;
/**
* Notifies the listener that a block was added at the given height.
*/
void (*block_connected)(const void *this_arg, struct LDKu8slice block, uint32_t height);
/**
* Notifies the listener that a block was removed at the given height.
*/
void (*block_disconnected)(const void *this_arg, const uint8_t (*header)[80], uint32_t height);
void (*free)(void *this_arg);
} LDKListen;

/**
* The `Filter` trait defines behavior for indicating chain activity of interest pertaining to
* channels.
Expand Down Expand Up @@ -3629,7 +3648,7 @@ typedef struct LDKChannelMessageHandler {
/**
* Handle an incoming shutdown message from the given peer.
*/
void (*handle_shutdown)(const void *this_arg, struct LDKPublicKey their_node_id, const struct LDKShutdown *NONNULL_PTR msg);
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);
/**
* Handle an incoming closing_signed message from the given peer.
*/
Expand Down Expand Up @@ -5117,6 +5136,11 @@ enum LDKAccessError AccessError_clone(const enum LDKAccessError *NONNULL_PTR ori
*/
void Access_free(struct LDKAccess this_ptr);

/**
* Calls the free function if one is set
*/
void Listen_free(struct LDKListen this_ptr);

/**
* Calls the free function if one is set
*/
Expand Down Expand Up @@ -5667,8 +5691,8 @@ void KeysManager_free(struct LDKKeysManager this_ptr);
MUST_USE_RES struct LDKKeysManager KeysManager_new(const uint8_t (*seed)[32], uint64_t starting_time_secs, uint32_t starting_time_nanos);

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

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

struct LDKListen ChannelManager_as_Listen(const struct LDKChannelManager *NONNULL_PTR this_arg);

/**
* Updates channel state based on transactions seen in a connected block.
*/
Expand Down
15 changes: 15 additions & 0 deletions lightning-c-bindings/include/lightningpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,21 @@ class Access {
const LDKAccess* operator &() const { return &self; }
const LDKAccess* operator ->() const { return &self; }
};
class Listen {
private:
LDKListen self;
public:
Listen(const Listen&) = delete;
Listen(Listen&& o) : self(o.self) { memset(&o, 0, sizeof(Listen)); }
Listen(LDKListen&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKListen)); }
operator LDKListen() && { LDKListen res = self; memset(&self, 0, sizeof(LDKListen)); return res; }
~Listen() { Listen_free(self); }
Listen& operator=(Listen&& o) { Listen_free(self); self = o.self; memset(&o, 0, sizeof(Listen)); return *this; }
LDKListen* operator &() { return &self; }
LDKListen* operator ->() { return &self; }
const LDKListen* operator &() const { return &self; }
const LDKListen* operator ->() const { return &self; }
};
class Watch {
private:
LDKWatch self;
Expand Down
8 changes: 4 additions & 4 deletions lightning-c-bindings/src/chain/chainmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,19 @@ pub extern "C" fn ChainMonitor_as_Watch(this_arg: &ChainMonitor) -> crate::chain
use lightning::chain::Watch as WatchTraitImport;
#[must_use]
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 {
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()) });
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()) });
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() };
local_ret
}
#[must_use]
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 {
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()) });
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()) });
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() };
local_ret
}
#[must_use]
extern "C" fn ChainMonitor_Watch_release_pending_monitor_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MonitorEventZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.release_pending_monitor_events();
let mut ret = <nativeChainMonitor as WatchTraitImport<_>>::release_pending_monitor_events(unsafe { &mut *(this_arg as *mut nativeChainMonitor) }, );
let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::chain::channelmonitor::MonitorEvent::native_into(item) }); };
local_ret.into()
}
Expand All @@ -178,7 +178,7 @@ pub extern "C" fn ChainMonitor_as_EventsProvider(this_arg: &ChainMonitor) -> cra
use lightning::util::events::EventsProvider as EventsProviderTraitImport;
#[must_use]
extern "C" fn ChainMonitor_EventsProvider_get_and_clear_pending_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_EventZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.get_and_clear_pending_events();
let mut ret = <nativeChainMonitor as EventsProviderTraitImport<>>::get_and_clear_pending_events(unsafe { &mut *(this_arg as *mut nativeChainMonitor) }, );
let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::Event::native_into(item) }); };
local_ret.into()
}
Expand Down
Loading