Merge pull request #618 from TheBlueMatt/2020-05-sample-c-bindings

C/C++ Bindings
This commit is contained in:
Matt Corallo 2020-09-10 19:23:39 -07:00 committed by GitHub
commit 253af8dd61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 26438 additions and 9 deletions

View file

@ -17,11 +17,16 @@ jobs:
include:
- toolchain: stable
build-net-tokio: true
build-bindings: true
- toolchain: beta
build-net-tokio: true
build-bindings: true
- toolchain: 1.39.0
build-net-tokio: true
build-bindings: true
coverage: true
- toolchain: 1.34.2
build-bindings: true
runs-on: ubuntu-latest
steps:
- name: Checkout source code
@ -38,6 +43,9 @@ jobs:
- name: Build on Rust ${{ matrix.toolchain }}
if: "! matrix.build-net-tokio"
run: RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always -p lightning
- name: Build bindings on Rust ${{ matrix.toolchain }}
if: matrix.build-bindings
run: RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always -p lightning-c-bindings
- name: Test on Rust ${{ matrix.toolchain }} with net-tokio
if: matrix.build-net-tokio
run: RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always
@ -98,3 +106,48 @@ jobs:
run: cd fuzz && cargo test --verbose --color always
- name: Run fuzzers
run: cd fuzz && ./ci-fuzz.sh
check_bindings:
runs-on: ubuntu-latest
# Ubuntu's version of rustc uses its own LLVM instead of being a real native package.
# This leaves us with an incompatible LLVM version when linking. Instead, use a real OS.
# We further (temporarily) use Debian experimental since testing links rustc against the
# brand-new llvm-10, but clang/llvm still default to LLVM 9.
container: debian:experimental
env:
TOOLCHAIN: stable
steps:
- name: Install native Rust toolchain, Valgrind, and build utilitis
run: |
echo 'Package: llvm llvm-runtime clang lld' > /etc/apt/preferences.d/99-llvm10
echo 'Pin: release n=experimental' >> /etc/apt/preferences.d/99-llvm10
echo 'Pin-Priority: 995' >> /etc/apt/preferences.d/99-llvm10
apt-get update
apt-get -y dist-upgrade
apt-get -y install cargo valgrind lld git g++ clang
- name: Checkout source code
uses: actions/checkout@v2
- name: Install cbindgen
run: cargo install --force cbindgen
- name: Rebuild bindings, and check the sample app builds + links
run: ./genbindings.sh
- name: Check that the latest bindings are in git
run: |
if [ "$(git diff)" != "" ]; then
# cbindgen's bindings output order can be FS-dependant, so check that the lines are all the same:
mv lightning-c-bindings/include/lightning.h lightning-c-bindings/include/lightning.h.new
git checkout lightning-c-bindings/include/lightning.h
cat lightning-c-bindings/include/lightning.h | sort > lightning-c-bindings/include/lightning.h.sorted
cat lightning-c-bindings/include/lightning.h.new | sort > lightning-c-bindings/include/lightning.h.new.sorted
diff lightning-c-bindings/include/lightning.h.sorted lightning-c-bindings/include/lightning.h.new.sorted
#
mv lightning-c-bindings/include/lightningpp.hpp lightning-c-bindings/include/lightningpp.hpp.new
git checkout lightning-c-bindings/include/lightningpp.hpp
cat lightning-c-bindings/include/lightningpp.hpp | sort > lightning-c-bindings/include/lightningpp.hpp.sorted
cat lightning-c-bindings/include/lightningpp.hpp.new | sort > lightning-c-bindings/include/lightningpp.hpp.new.sorted
diff lightning-c-bindings/include/lightningpp.hpp.sorted lightning-c-bindings/include/lightningpp.hpp.new.sorted
#
[ "$(diff lightning-c-bindings/include/lightning.h.sorted lightning-c-bindings/include/lightning.h.new.sorted)" != "" ] && exit 2
[ "$(diff lightning-c-bindings/include/lightningpp.hpp.sorted lightning-c-bindings/include/lightningpp.hpp.new.sorted)" != "" ] && exit 3
git diff --exit-code
fi

View file

@ -3,8 +3,17 @@
members = [
"lightning",
"lightning-net-tokio",
"lightning-c-bindings",
]
# Our tests do actual crypo and lots of work, the tradeoff for -O1 is well worth it
[profile.dev]
[profile.test]
opt-level = 1
[profile.dev]
panic = "abort"
[profile.release]
opt-level = 3
lto = true
panic = "abort"

12
c-bindings-gen/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "c-bindings-gen"
version = "0.0.1"
authors = ["Matt Corallo"]
edition = "2018"
[dependencies]
syn = { version = "1", features = ["full", "extra-traits"] }
proc-macro2 = "1"
# We're not in the workspace as we're just a binary code generator:
[workspace]

View file

@ -0,0 +1,373 @@
//! Printing logic for basic blocks of Rust-mapped code - parts of functions and declarations but
//! not the full mapping logic.
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use proc_macro2::{TokenTree, Span};
use crate::types::*;
/// Writes out a C++ wrapper class for the given type, which contains various utilities to access
/// the underlying C-mapped type safely avoiding some common memory management issues by handling
/// resource-freeing and prevending accidental raw copies.
pub fn write_cpp_wrapper(cpp_header_file: &mut File, ty: &str, has_destructor: bool) {
writeln!(cpp_header_file, "class {} {{", ty).unwrap();
writeln!(cpp_header_file, "private:").unwrap();
writeln!(cpp_header_file, "\tLDK{} self;", ty).unwrap();
writeln!(cpp_header_file, "public:").unwrap();
writeln!(cpp_header_file, "\t{}(const {}&) = delete;", ty, ty).unwrap();
if has_destructor {
writeln!(cpp_header_file, "\t~{}() {{ {}_free(self); }}", ty, ty).unwrap();
}
writeln!(cpp_header_file, "\t{}({}&& o) : self(o.self) {{ memset(&o, 0, sizeof({})); }}", ty, ty, ty).unwrap();
writeln!(cpp_header_file, "\t{}(LDK{}&& m_self) : self(m_self) {{ memset(&m_self, 0, sizeof(LDK{})); }}", ty, ty, ty).unwrap();
writeln!(cpp_header_file, "\toperator LDK{}() {{ LDK{} res = self; memset(&self, 0, sizeof(LDK{})); return res; }}", ty, ty, ty).unwrap();
writeln!(cpp_header_file, "\tLDK{}* operator &() {{ return &self; }}", ty).unwrap();
writeln!(cpp_header_file, "\tLDK{}* operator ->() {{ return &self; }}", ty).unwrap();
writeln!(cpp_header_file, "\tconst LDK{}* operator &() const {{ return &self; }}", ty).unwrap();
writeln!(cpp_header_file, "\tconst LDK{}* operator ->() const {{ return &self; }}", ty).unwrap();
writeln!(cpp_header_file, "}};").unwrap();
}
/// Prints the docs from a given attribute list unless its tagged no export
pub fn writeln_docs<W: std::io::Write>(w: &mut W, attrs: &[syn::Attribute], prefix: &str) {
for attr in attrs.iter() {
let tokens_clone = attr.tokens.clone();
let mut token_iter = tokens_clone.into_iter();
if let Some(token) = token_iter.next() {
match token {
TokenTree::Punct(c) if c.as_char() == '=' => {
// syn gets '=' from '///' or '//!' as it is syntax for #[doc = ""]
},
TokenTree::Group(_) => continue, // eg #[derive()]
_ => unimplemented!(),
}
} else { continue; }
match attr.style {
syn::AttrStyle::Inner(_) => {
match token_iter.next().unwrap() {
TokenTree::Literal(lit) => {
// Drop the first and last chars from lit as they are always "
let doc = format!("{}", lit);
writeln!(w, "{}//!{}", prefix, &doc[1..doc.len() - 1]).unwrap();
},
_ => unimplemented!(),
}
},
syn::AttrStyle::Outer => {
match token_iter.next().unwrap() {
TokenTree::Literal(lit) => {
// Drop the first and last chars from lit as they are always "
let doc = format!("{}", lit);
writeln!(w, "{}///{}", prefix, &doc[1..doc.len() - 1]).unwrap();
},
_ => unimplemented!(),
}
},
}
}
}
/// Print the parameters in a method declaration, starting after the open parenthesis, through and
/// including the closing parenthesis and return value, but not including the open bracket or any
/// trailing semicolons.
///
/// Usable both for a function definition and declaration.
///
/// this_param is used when returning Self or accepting a self parameter, and should be the
/// concrete, mapped type.
pub fn write_method_params<W: std::io::Write>(w: &mut W, sig: &syn::Signature, associated_types: &HashMap<&syn::Ident, &syn::Ident>, this_param: &str, types: &mut TypeResolver, generics: Option<&GenericTypes>, self_ptr: bool, fn_decl: bool) {
if sig.constness.is_some() || sig.asyncness.is_some() || sig.unsafety.is_some() ||
sig.abi.is_some() || sig.variadic.is_some() {
unimplemented!();
}
if sig.generics.lt_token.is_some() {
for generic in sig.generics.params.iter() {
match generic {
syn::GenericParam::Type(_)|syn::GenericParam::Lifetime(_) => {
// We ignore these, if they're not on skipped args, we'll blow up
// later, and lifetimes we just hope the C client enforces.
},
_ => unimplemented!(),
}
}
}
let mut first_arg = true;
let mut num_unused = 0;
for inp in sig.inputs.iter() {
match inp {
syn::FnArg::Receiver(recv) => {
if !recv.attrs.is_empty() || recv.reference.is_none() { unimplemented!(); }
write!(w, "this_arg: {}{}",
match (self_ptr, recv.mutability.is_some()) {
(true, true) => "*mut ",
(true, false) => "*const ",
(false, true) => "&mut ",
(false, false) => "&",
}, this_param).unwrap();
assert!(first_arg);
first_arg = false;
},
syn::FnArg::Typed(arg) => {
if types.skip_arg(&*arg.ty, generics) { continue; }
if !arg.attrs.is_empty() { unimplemented!(); }
let mut is_ref = if let syn::Type::Reference(_) = *arg.ty { true } else { false };
if let syn::Type::Reference(syn::TypeReference { ref elem, .. }) = *arg.ty {
if let syn::Type::Slice(_) = &**elem {
// Slices are mapped to non-ref Vec types, so we want them to be mut
// letting us drain(..) the underlying Vec.
is_ref = false;
}
}
match &*arg.pat {
syn::Pat::Ident(ident) => {
if !ident.attrs.is_empty() || ident.subpat.is_some() {
unimplemented!();
}
write!(w, "{}{}{}: ", if first_arg { "" } else { ", " }, if is_ref || !fn_decl { "" } else { "mut " }, ident.ident).unwrap();
first_arg = false;
},
syn::Pat::Wild(wild) => {
if !wild.attrs.is_empty() { unimplemented!(); }
write!(w, "{}unused_{}: ", if first_arg { "" } else { ", " }, num_unused).unwrap();
num_unused += 1;
},
_ => unimplemented!(),
}
types.write_c_type(w, &*arg.ty, generics, false);
}
}
}
write!(w, ")").unwrap();
match &sig.output {
syn::ReturnType::Type(_, rtype) => {
write!(w, " -> ").unwrap();
if let Some(mut remaining_path) = first_seg_self(&*rtype) {
if let Some(associated_seg) = get_single_remaining_path_seg(&mut remaining_path) {
// We're returning an associated type in a trait impl. Its probably a safe bet
// that its also a trait, so just return the trait type.
let real_type = associated_types.get(associated_seg).unwrap();
types.write_c_type(w, &syn::Type::Path(syn::TypePath { qself: None,
path: syn::PathSegment {
ident: (*real_type).clone(),
arguments: syn::PathArguments::None
}.into()
}), generics, true);
} else {
write!(w, "{}", this_param).unwrap();
}
} else {
if let syn::Type::Reference(r) = &**rtype {
// We can't return a reference, cause we allocate things on the stack.
types.write_c_type(w, &*r.elem, generics, true);
} else {
types.write_c_type(w, &*rtype, generics, true);
}
}
},
_ => {},
}
}
/// Print the main part of a method declaration body, starting with a newline after the function
/// open bracket and converting each function parameter to or from C-mapped types. Ends with "let
/// mut ret = " assuming the next print will be the unmapped Rust function to call followed by the
/// parameters we mapped to/from C here.
pub fn write_method_var_decl_body<W: std::io::Write>(w: &mut W, sig: &syn::Signature, extra_indent: &str, types: &TypeResolver, generics: Option<&GenericTypes>, to_c: bool) {
let mut num_unused = 0;
for inp in sig.inputs.iter() {
match inp {
syn::FnArg::Receiver(_) => {},
syn::FnArg::Typed(arg) => {
if types.skip_arg(&*arg.ty, generics) { continue; }
if !arg.attrs.is_empty() { unimplemented!(); }
macro_rules! write_new_var {
($ident: expr, $ty: expr) => {
if to_c {
if types.write_to_c_conversion_new_var(w, &$ident, &$ty, generics, false) {
write!(w, "\n\t{}", extra_indent).unwrap();
}
} else {
if types.write_from_c_conversion_new_var(w, &$ident, &$ty, generics) {
write!(w, "\n\t{}", extra_indent).unwrap();
}
}
}
}
match &*arg.pat {
syn::Pat::Ident(ident) => {
if !ident.attrs.is_empty() || ident.subpat.is_some() {
unimplemented!();
}
write_new_var!(ident.ident, *arg.ty);
},
syn::Pat::Wild(w) => {
if !w.attrs.is_empty() { unimplemented!(); }
write_new_var!(syn::Ident::new(&format!("unused_{}", num_unused), Span::call_site()), *arg.ty);
num_unused += 1;
},
_ => unimplemented!(),
}
}
}
}
match &sig.output {
syn::ReturnType::Type(_, _) => {
write!(w, "let mut ret = ").unwrap();
},
_ => {},
}
}
/// Prints the parameters in a method call, starting after the open parenthesis and ending with a
/// final return statement returning the method's result. Should be followed by a single closing
/// bracket.
///
/// The return value is expected to be bound to a variable named `ret` which is available after a
/// method-call-ending semicolon.
pub fn write_method_call_params<W: std::io::Write>(w: &mut W, sig: &syn::Signature, associated_types: &HashMap<&syn::Ident, &syn::Ident>, extra_indent: &str, types: &TypeResolver, generics: Option<&GenericTypes>, this_type: &str, to_c: bool) {
let mut first_arg = true;
let mut num_unused = 0;
for inp in sig.inputs.iter() {
match inp {
syn::FnArg::Receiver(recv) => {
if !recv.attrs.is_empty() || recv.reference.is_none() { unimplemented!(); }
if to_c {
write!(w, "self.this_arg").unwrap();
first_arg = false;
}
},
syn::FnArg::Typed(arg) => {
if types.skip_arg(&*arg.ty, generics) {
if !to_c {
if !first_arg {
write!(w, ", ").unwrap();
}
first_arg = false;
types.no_arg_to_rust(w, &*arg.ty, generics);
}
continue;
}
if !arg.attrs.is_empty() { unimplemented!(); }
macro_rules! write_ident {
($ident: expr) => {
if !first_arg {
write!(w, ", ").unwrap();
}
first_arg = false;
if to_c {
types.write_to_c_conversion_inline_prefix(w, &*arg.ty, generics, false);
write!(w, "{}", $ident).unwrap();
types.write_to_c_conversion_inline_suffix(w, &*arg.ty, generics, false);
} else {
types.write_from_c_conversion_prefix(w, &*arg.ty, generics);
write!(w, "{}", $ident).unwrap();
types.write_from_c_conversion_suffix(w, &*arg.ty, generics);
}
}
}
match &*arg.pat {
syn::Pat::Ident(ident) => {
if !ident.attrs.is_empty() || ident.subpat.is_some() {
unimplemented!();
}
write_ident!(ident.ident);
},
syn::Pat::Wild(w) => {
if !w.attrs.is_empty() { unimplemented!(); }
write_ident!(format!("unused_{}", num_unused));
num_unused += 1;
},
_ => unimplemented!(),
}
}
}
}
write!(w, ")").unwrap();
match &sig.output {
syn::ReturnType::Type(_, rtype) => {
write!(w, ";\n\t{}", extra_indent).unwrap();
if to_c && first_seg_self(&*rtype).is_some() {
// Assume rather blindly that we're returning an associated trait from a C fn call to a Rust trait object.
write!(w, "ret").unwrap();
} else if !to_c && first_seg_self(&*rtype).is_some() {
if let Some(mut remaining_path) = first_seg_self(&*rtype) {
if let Some(associated_seg) = get_single_remaining_path_seg(&mut remaining_path) {
let real_type = associated_types.get(associated_seg).unwrap();
if let Some(t) = types.crate_types.traits.get(&types.maybe_resolve_ident(&real_type).unwrap()) {
// We're returning an associated trait from a Rust fn call to a C trait
// object.
writeln!(w, "let mut rust_obj = {} {{ inner: Box::into_raw(Box::new(ret)), is_owned: true }};", this_type).unwrap();
writeln!(w, "\t{}let mut ret = {}_as_{}(&rust_obj);", extra_indent, this_type, t.ident).unwrap();
writeln!(w, "\t{}// We want to free rust_obj when ret gets drop()'d, not rust_obj, so wipe rust_obj's pointer and set ret's free() fn", extra_indent).unwrap();
writeln!(w, "\t{}rust_obj.inner = std::ptr::null_mut();", extra_indent).unwrap();
writeln!(w, "\t{}ret.free = Some({}_free_void);", extra_indent, this_type).unwrap();
writeln!(w, "\t{}ret", extra_indent).unwrap();
return;
}
}
}
write!(w, "{} {{ inner: Box::into_raw(Box::new(ret)), is_owned: true }}", this_type).unwrap();
} else if to_c {
let new_var = types.write_from_c_conversion_new_var(w, &syn::Ident::new("ret", Span::call_site()), rtype, generics);
if new_var {
write!(w, "\n\t{}", extra_indent).unwrap();
}
types.write_from_c_conversion_prefix(w, &*rtype, generics);
write!(w, "ret").unwrap();
types.write_from_c_conversion_suffix(w, &*rtype, generics);
} else {
let ret_returned = if let syn::Type::Reference(_) = &**rtype { true } else { false };
let new_var = types.write_to_c_conversion_new_var(w, &syn::Ident::new("ret", Span::call_site()), &rtype, generics, true);
if new_var {
write!(w, "\n\t{}", extra_indent).unwrap();
}
types.write_to_c_conversion_inline_prefix(w, &rtype, generics, true);
write!(w, "{}ret", if ret_returned && !new_var { "*" } else { "" }).unwrap();
types.write_to_c_conversion_inline_suffix(w, &rtype, generics, true);
}
}
_ => {},
}
}
/// Prints concrete generic parameters for a struct/trait/function, including the less-than and
/// greater-than symbols, if any generic parameters are defined.
pub fn maybe_write_generics<W: std::io::Write>(w: &mut W, generics: &syn::Generics, types: &TypeResolver, concrete_lifetimes: bool) {
let mut gen_types = GenericTypes::new();
assert!(gen_types.learn_generics(generics, types));
if !generics.params.is_empty() {
write!(w, "<").unwrap();
for (idx, generic) in generics.params.iter().enumerate() {
match generic {
syn::GenericParam::Type(type_param) => {
let mut printed_param = false;
for bound in type_param.bounds.iter() {
if let syn::TypeParamBound::Trait(trait_bound) = bound {
assert_simple_bound(&trait_bound);
write!(w, "{}{}", if idx != 0 { ", " } else { "" }, gen_types.maybe_resolve_ident(&type_param.ident).unwrap()).unwrap();
if printed_param {
unimplemented!("Can't print generic params that have multiple non-lifetime bounds");
}
printed_param = true;
}
}
},
syn::GenericParam::Lifetime(lt) => {
if concrete_lifetimes {
write!(w, "'static").unwrap();
} else {
write!(w, "{}'{}", if idx != 0 { ", " } else { "" }, lt.lifetime.ident).unwrap();
}
},
_ => unimplemented!(),
}
}
write!(w, ">").unwrap();
}
}

1283
c-bindings-gen/src/main.rs Normal file

File diff suppressed because it is too large Load diff

2021
c-bindings-gen/src/types.rs Normal file

File diff suppressed because it is too large Load diff

189
genbindings.sh Executable file
View file

@ -0,0 +1,189 @@
#!/usr/bin/env bash
set -e
set -x
# Generate (and reasonably test) C bindings
# First build the latest c-bindings-gen binary
cd c-bindings-gen && cargo build && cd ..
# Then wipe all the existing C bindings (because we're being run in the right directory)
# note that we keep the few manually-generated files first:
mv lightning-c-bindings/src/c_types/mod.rs ./
mv lightning-c-bindings/src/bitcoin ./
rm -rf lightning-c-bindings/src
mkdir -p lightning-c-bindings/src/c_types/
mv ./mod.rs lightning-c-bindings/src/c_types/
mv ./bitcoin lightning-c-bindings/src/
# Finally, run the c-bindings-gen binary, building fresh bindings.
SRC="$(pwd)/lightning/src"
OUT="$(pwd)/lightning-c-bindings/src"
OUT_TEMPL="$(pwd)/lightning-c-bindings/src/c_types/derived.rs"
OUT_F="$(pwd)/lightning-c-bindings/include/rust_types.h"
OUT_CPP="$(pwd)/lightning-c-bindings/include/lightningpp.hpp"
RUST_BACKTRACE=1 ./c-bindings-gen/target/debug/c-bindings-gen $SRC/ $OUT/ lightning $OUT_TEMPL $OUT_F $OUT_CPP
# Now cd to lightning-c-bindings, build the generated bindings, and call cbindgen to build a C header file
PATH="$PATH:~/.cargo/bin"
cd lightning-c-bindings
cargo build
cbindgen -v --config cbindgen.toml -o include/lightning.h >/dev/null 2>&1
HOST_PLATFORM="$(rustc --version --verbose | grep "host:")"
# cbindgen is relatively braindead when exporting typedefs -
# it happily exports all our typedefs for private types, even with the
# generics we specified in C mode! So we drop all those types manually here.
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
else
sed -i 's/typedef LDKnative.*Import.*LDKnative.*;//g' include/lightning.h
fi
# Finally, sanity-check the generated C and C++ bindings with demo apps:
# Naively run the C demo app:
gcc -Wall -g -pthread demo.c ../target/debug/liblightning.a -ldl
./a.out
# And run the C++ demo app in valgrind to test memory model correctness and lack of leaks.
g++ -std=c++11 -Wall -g -pthread demo.cpp -L../target/debug/ -llightning -ldl
if [ -x "`which valgrind`" ]; then
LD_LIBRARY_PATH=../target/debug/ valgrind --error-exitcode=4 --memcheck:leak-check=full --show-leak-kinds=all ./a.out
echo
else
echo "WARNING: Please install valgrind for more testing"
fi
# Test a statically-linked C++ version, tracking the resulting binary size and runtime
# across debug, LTO, and cross-language LTO builds (using the same compiler each time).
clang++ -std=c++11 -Wall -pthread demo.cpp ../target/debug/liblightning.a -ldl
./a.out >/dev/null
echo " C++ Bin size and runtime w/o optimization:"
ls -lha a.out
time ./a.out > /dev/null
# Then, check with memory sanitizer, if we're on Linux and have rustc nightly
if [ "$HOST_PLATFORM" = "host: x86_64-unknown-linux-gnu" ]; then
if cargo +nightly --version >/dev/null 2>&1; then
LLVM_V=$(rustc +nightly --version --verbose | grep "LLVM version" | awk '{ print substr($3, 0, 2); }')
if [ -x "$(which clang-$LLVM_V)" ]; then
cargo +nightly clean
cargo +nightly rustc -Zbuild-std --target x86_64-unknown-linux-gnu -v -- -Zsanitizer=memory -Zsanitizer-memory-track-origins -Cforce-frame-pointers=yes
mv ../target/x86_64-unknown-linux-gnu/debug/liblightning.* ../target/debug/
# Sadly, std doesn't seem to compile into something that is memsan-safe as of Aug 2020,
# so we'll always fail, not to mention we may be linking against git rustc LLVM which
# may differ from clang-llvm, so just allow everything here to fail.
set +e
# First the C demo app...
clang-$LLVM_V -std=c++11 -fsanitize=memory -fsanitize-memory-track-origins -Wall -g -pthread demo.c ../target/debug/liblightning.a -ldl
./a.out
# ...then the C++ demo app
clang++-$LLVM_V -std=c++11 -fsanitize=memory -fsanitize-memory-track-origins -Wall -g -pthread demo.cpp ../target/debug/liblightning.a -ldl
./a.out >/dev/null
# restore exit-on-failure
set -e
else
echo "WARNING: Can't use memory sanitizer without clang-$LLVM_V"
fi
else
echo "WARNING: Can't use memory sanitizer without rustc nightly"
fi
else
echo "WARNING: Can't use memory sanitizer on non-Linux, non-x86 platforms"
fi
RUSTC_LLVM_V=$(rustc --version --verbose | grep "LLVM version" | awk '{ print substr($3, 0, 2); }' | tr -d '.')
if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then
# Apple is special, as always, and decided that they must ensure that there is no way to identify
# the LLVM version used. Why? Just to make your life hard.
# This list is taken from https://en.wikipedia.org/wiki/Xcode
APPLE_CLANG_V=$(clang --version | head -n1 | awk '{ print $4 }')
if [ "$APPLE_CLANG_V" = "10.0.0" ]; then
CLANG_LLVM_V="6"
elif [ "$APPLE_CLANG_V" = "10.0.1" ]; then
CLANG_LLVM_V="7"
elif [ "$APPLE_CLANG_V" = "11.0.0" ]; then
CLANG_LLVM_V="8"
elif [ "$APPLE_CLANG_V" = "11.0.3" ]; then
CLANG_LLVM_V="9"
elif [ "$APPLE_CLANG_V" = "12.0.0" ]; then
CLANG_LLVM_V="10"
else
echo "WARNING: Unable to identify Apple clang LLVM version"
CLANG_LLVM_V="0"
fi
else
CLANG_LLVM_V=$(clang --version | head -n1 | awk '{ print substr($4, 0, 2); }' | tr -d '.')
fi
if [ "$CLANG_LLVM_V" = "$RUSTC_LLVM_V" ]; then
CLANG=clang
CLANGPP=clang++
elif [ "$(which clang-$RUSTC_LLVM_V)" != "" ]; then
CLANG="$(which clang-$RUSTC_LLVM_V)"
CLANGPP="$(which clang++-$RUSTC_LLVM_V)"
fi
if [ "$CLANG" != "" -a "$CLANGPP" = "" ]; then
echo "WARNING: It appears you have a clang-$RUSTC_LLVM_V but not clang++-$RUSTC_LLVM_V. This is common, but leaves us unable to compile C++ with LLVM $RUSTC_LLVM_V"
echo "You should create a symlink called clang++-$RUSTC_LLVM_V pointing to $CLANG in $(dirname $CLANG)"
fi
# Finally, if we're on OSX or on Linux, build the final debug binary with address sanitizer (and leave it there)
if [ "$HOST_PLATFORM" = "host: x86_64-unknown-linux-gnu" -o "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then
if [ "$CLANGPP" != "" ]; then
if [ "$HOST_PLATFORM" = "host: x86_64-apple-darwin" ]; then
# OSX sed is for some reason not compatible with GNU sed
sed -i .bk 's/,"cdylib"]/]/g' Cargo.toml
else
sed -i.bk 's/,"cdylib"]/]/g' Cargo.toml
fi
RUSTC_BOOTSTRAP=1 cargo rustc -v -- -Zsanitizer=address -Cforce-frame-pointers=yes || ( mv Cargo.toml.bk Cargo.toml; exit 1)
mv Cargo.toml.bk Cargo.toml
# First the C demo app...
$CLANG -fsanitize=address -Wall -g -pthread demo.c ../target/debug/liblightning.a -ldl
ASAN_OPTIONS='detect_leaks=1 detect_invalid_pointer_pairs=1 detect_stack_use_after_return=1' ./a.out
# ...then the C++ demo app
$CLANGPP -std=c++11 -fsanitize=address -Wall -g -pthread demo.cpp ../target/debug/liblightning.a -ldl
ASAN_OPTIONS='detect_leaks=1 detect_invalid_pointer_pairs=1 detect_stack_use_after_return=1' ./a.out >/dev/null
else
echo "WARNING: Please install clang-$RUSTC_LLVM_V and clang++-$RUSTC_LLVM_V to build with address sanitizer"
fi
else
echo "WARNING: Can't use address sanitizer on non-Linux, non-OSX non-x86 platforms"
fi
# Now build with LTO on on both C++ and rust, but without cross-language LTO:
cargo rustc -v --release -- -C lto
clang++ -std=c++11 -Wall -flto -O2 -pthread demo.cpp ../target/release/liblightning.a -ldl
echo "C++ Bin size and runtime with only RL (LTO) optimized:"
ls -lha a.out
time ./a.out > /dev/null
if [ "$HOST_PLATFORM" != "host: x86_64-apple-darwin" -a "$CLANGPP" != "" ]; then
# Finally, test cross-language LTO. Note that this will fail if rustc and clang++
# build against different versions of LLVM (eg when rustc is installed via rustup
# or Ubuntu packages). This should work fine on Distros which do more involved
# packaging than simply shipping the rustup binaries (eg Debian should Just Work
# here).
cargo rustc -v --release -- -C linker-plugin-lto -C lto -C link-arg=-fuse-ld=lld
$CLANGPP -Wall -std=c++11 -flto -fuse-ld=lld -O2 -pthread demo.cpp ../target/release/liblightning.a -ldl
echo "C++ Bin size and runtime with cross-language LTO:"
ls -lha a.out
time ./a.out > /dev/null
else
echo "WARNING: Building with cross-language LTO is not avilable on OSX or without clang-$RUSTC_LLVM_V"
fi

View file

@ -0,0 +1,19 @@
[package]
name = "lightning-c-bindings"
version = "0.0.1"
authors = ["Matt Corallo"]
license = "Apache-2.0"
edition = "2018"
description = """
Utilities to fetch the chain from Bitcoin Core REST/RPC Interfaces and feed them into Rust Lightning.
"""
[lib]
name = "lightning"
crate-type = ["staticlib"
# Note that the following line is matched exactly by genbindings to turn off dylib creation
,"cdylib"]
[dependencies]
bitcoin = "0.24"
lightning = { version = "0.0.11", path = "../lightning" }

View file

@ -0,0 +1,229 @@
The wrapper crate and C/C++ Headers in this folder are auto-generated from the Rust-Lightning
source by the c-bindings-gen crate contained in the source tree and
[cbindgen](https://github.com/eqrion/cbindgen). They are intended to be used as a base for building
language-specific bindings, and are thus incredibly low-level and may be difficult to work with
directly.
In other words, if you're reading this, you're either writing bindings for a new language, or
you're in the wrong place - individual language bindings should come with their own documentation.
LDK C Bindings
==============
The C bindings available at include/lightning.h require inclusion of include/rust_types.h first.
All of the Rust-Lightning types are mapped into C equivalents which take a few forms, with the C
type getting an `LDK` prefix to their native Rust type names.
#### Structs
Structs are mapped into a simple wrapper containing a pointer to the native Rust-Lightning object
and a flag to indicate whether the object is owned or only a reference. Such mappings usually
generate a `X_free` function which must be called to release the allocated resources. Note that
calling `X_free` will do nothing if the underlying pointer is NULL or if the `is_owned` flag is not
set.
You MUST NOT create such wrapper structs manually, relying instead on constructors which have been
mapped from equivalent Rust constructors.
Note that, thanks to the is-owned flag and the pointer being NULLable, such structs effectively
represent `RustType`, `&RustType`, and `Option<RustType>`. Check the corresponding Rust
documentation for the function or struct you are using to ensure you use the correct call semantics.
The passed struct must match the call semantics or an assertion failure or NULL pointer dereference
may occur.
For example, this is the mapping of ChannelManager.
```c
typedef struct MUST_USE_STRUCT LDKChannelManager {
/** ... */
LDKnativeChannelManager *inner;
bool is_owned;
} LDKChannelManager;
```
#### Traits
Traits are mapped into a concrete struct containing a void pointer (named `this_arg` and a jump
table listing the functions which the trait must implement. The void pointer may be set to any value
and is never interpreted (or dereferenced) by the bindings logic in any way. It is passed as the
first argument to all function calls in the trait. You may wish to use it as a pointer to your own
internal data structure, though it may also occasionally make sense to e.g. cast a file descriptor
into a void pointer and use it to track a socket.
This should remind you of a C++ vtable, only written out by hand and with the class only containing
a pointer, instead of the regular class data.
Each trait additionally contains `free` and `clone` function pointers, which may be NULL. The `free`
function is passed the void pointer when the object is `Drop`ed in Rust. The `clone` function is
passed the void pointer when the object is `Clone`ed in Rust, returning a new void pointer for the
new object. If the `free` pointer is NULL, you will not receive any notification when the trait
object is no longer needed. If the `clone` pointer is NULL, we assume that the trait object may be
`memcpy()`'d to create copies. Note that if you release resources with `free` without implementing
`clone`, you will likely end up with use-after-free bugs (as copies of the original this_arg value
may still exist, unbeknownst to you).
For example, `LDKSocketDescriptor` is mapped as follows:
```c
typedef struct LDKSocketDescriptor {
void *this_arg;
/** ... */
uintptr_t (*send_data)(void *this_arg, LDKu8slice data, bool resume_read);
/** ... */
void (*disconnect_socket)(void *this_arg);
bool (*eq)(const void *this_arg, const void *other_arg);
uint64_t (*hash)(const void *this_arg);
void *(*clone)(const void *this_arg);
void (*free)(void *this_arg);
} LDKSocketDescriptor;
```
##### Rust Trait Implementations
Rust structs that implement a trait result in the generation of an `X_as_Y` function, which takes a
C struct wrapping the Rust native object and returns a generated trait object. Such generated
objects are only valid as long as the original Rust native object has not been `free`'d or moved as
a part of a Rust function call (ie continues to be owned by the C struct). For example, to use an
`LDKInMemoryChannelKeys` as a `ChannelKeys`, `InMemoryChannelKeys_as_ChannelKeys` is exposed:
```c
LDKChannelKeys InMemoryChannelKeys_as_ChannelKeys(const LDKInMemoryChannelKeys *this_arg);
```
#### Enums
Rust "unitary" enums are mapped simply as an equivalent C enum; however, some Rust enums have
variants which contain payloads. Such enums are mapped automatically by cbindgen as a tag which
indicates the type and a union which holds the relevant fields for a given tag. An `X_free` function
is provided for the enum as a whole which automatically frees the correct fields for a give tag, and
a `Sentinel` tag is provided which causes the free function to do nothing (but which must never
appear in an enum when accessed by Rust code). The `Sentinel` tag is used by the C++ wrapper classes
to allow moving the ownership of an enum while invalidating the old copy.
For example, the unitary enum `LDKChannelMonitorUpdateErr` is mapped as follows:
```c
typedef enum LDKChannelMonitorUpdateErr {
/** .. */
LDKChannelMonitorUpdateErr_TemporaryFailure,
/** .. */
LDKChannelMonitorUpdateErr_PermanentFailure,
/** .. */
LDKChannelMonitorUpdateErr_Sentinel,
} LDKChannelMonitorUpdateErr;
```
and the non-unitary enum LDKErrorAction is mapped as follows:
```c
typedef enum LDKErrorAction_Tag {
/** .. */
LDKErrorAction_DisconnectPeer,
/** .. */
LDKErrorAction_IgnoreError,
/** .. */
LDKErrorAction_SendErrorMessage,
/** .. */
LDKErrorAction_Sentinel,
} LDKErrorAction_Tag;
typedef struct LDKErrorAction_LDKDisconnectPeer_Body {
LDKErrorMessage msg;
} LDKErrorAction_LDKDisconnectPeer_Body;
typedef struct LDKErrorAction_LDKSendErrorMessage_Body {
LDKErrorMessage msg;
} LDKErrorAction_LDKSendErrorMessage_Body;
typedef struct LDKErrorAction {
LDKErrorAction_Tag tag;
union {
LDKErrorAction_LDKDisconnectPeer_Body disconnect_peer;
LDKErrorAction_LDKSendErrorMessage_Body send_error_message;
};
} LDKErrorAction;
```
#### Functions
Struct member functions are mapped as `Struct_function_name` and take a pointer to the mapped struct
as their first argument. Free-standing functions are mapped simply as `function_name` and take the
relevant mapped type arguments.
Functions which return `&OpaqueRustType` and which return `OpaqueRustType` are both mapped to a
function returning an owned wrapper struct. The `is_owned` flag (see above) will be set to indicate
that the pointed-to Rust object is owned or only a reference. Thus, when implementing a function
which Rust will call or calling a Rust function, you should check the Rust documentation for the
function to determine whether an owned or referenced object is expected or returned.
Similarly, when a function takes an `Option<RustType>` as a parameter or a return value, the C type
is the same as if it took only `RustType`, with the `inner` field set to NULL to indicate None. For
example, `ChannelManager_create_channel` takes an `Option<LDKUserConfig>` not an `LDKUserConfig`,
but its definition is:
```c
MUST_USE_RES ... ChannelManager_create_channel(const LDKChannelManager *this_arg, ..., LDKUserConfig override_config);
```
#### Containers
Various containers (Tuples, Vecs, Results, etc) are mapped into C structs of the form
`LDKCContainerType_ContainerElementsZ`. Inner fields are often pointers, and in the case of
primitive types, these may be allocated in C using the system allocator. See [the Rust docs on your
platform's default System allocator](https://doc.rust-lang.org/std/alloc/struct.System.html) for
which allocator you must use. Recursive containers are possible, and simply replace the
`ContainerElements` part with `InnerContainerType_InnerContainerElementsZ`, eg
`LDKCResult_C2Tuple_SignatureCVec_SignatureZZNoneZ` represents a
`Result<(Signature, Vec<Signature>), ()>`.
#### Notes
As the bindings are auto-generated, the best resource for documentation on them is the native Rust
docs available via `cargo doc` or [docs.rs/lightning](https://docs.rs/lightning).
The memory model is largely the Rust memory model and not a native C-like memory model. Thus,
function parameters are largely only ever passed by reference or by move, with pass-by-copy
semantics only applying to primitive types. However, because the underlying types are largely
pointers, the same function signature may imply two different memory ownership semantics. Thus, you
MUST read the Rust documentation while using the C bindings. For functions which take arguments
where ownership is moved to the function scope, the corresponding `X_free` function MUST NOT be
called on the object, whereas for all other objects, `X_free` MUST be used to free resources.
LDK C++ Bindings
================
The C++ bindings available at include/lightningpp.hpp require extern "C" inclusion of lightning.h
and rust_types.h first. They represent thin wrappers around the C types which provide a few
C++-isms to make memory model correctness easier to achieve. They provide:
* automated destructors which call the relevant `X_free` C functions,
* move constructors both from C++ classes and the original C struct, with the original object
cleared to ensure destruction/`X_free` calls do not cause a double-free.
* Move semantics via the () operator, returning the original C struct and clearing the C++ object.
This allows calls such as `C_function(cpp_object)` which work as expected with move semantics.
In general, you should prefer to use the C++ bindings if possible, as they make memory leaks and
other violations somewhat easier to avoid. Note that, because the C functions are not redefined in
C++, all functions return the C type. Thus, you must bind returned values to the equivalent C++ type
(replacing `LDKX` with `LDK::X`) to ensure the destructor is properly run. A demonstration of such
usage is available at [demo.cpp](demo.cpp).
Gotchas
=======
There are a few gotchas around future changes to Rust-Lightning which the bindings may not support.
These include:
* Any trait method which returns a reference to a struct or inner variable cannot be called in
parallel. This is because such functions always return a local variable stored inside the trait,
with a call through a function pointer to get the local variable set correctly. Automatically
generated setter functions have comments describing the potential race conditions in their
definition.
For example, the `ChannelKeys::pubkeys() -> &ChannelPublicKeys` function is mapped as this:
```c
typedef struct LDKChannelKeys {
...
LDKChannelPublicKeys pubkeys;
/** ... */
void (*set_pubkeys)(const LDKChannelKeys*);
...
} LDKChannelKeys;
```
**It is highly recommended that you test any code which relies on the C (or C++) bindings in
valgrind, AddressSanitizer, MemorySanitizer, or other similar tools to ensure correctness.**
Note that after running `genbindings.sh`, if possible, the static lib in target/debug (eg
target/debug/liblightning.a) will be linked with address sanitizer. In order to build against it,
you will need to link with `clang` with `-fsanitize=address` with the same version of LLVM as
`rustc`'s LLVM. If `genbindings.sh` failed to find a matching `clang` or you are building on an
unsupported platform, a warning noting that address sanitizer is not available will be printed.

View file

@ -0,0 +1,552 @@
# The language to output bindings in
#
# possible values: "C", "C++"
#
# default: "C++"
language = "C"
# Options for wrapping the contents of the header:
# An optional string of text to output at the beginning of the generated file
# default: doesn't emit anything
header = "/* Text to put at the beginning of the generated file. Probably a license. */"
# An optional string of text to output at the end of the generated file
# default: doesn't emit anything
trailer = "/* Text to put at the end of the generated file */"
# An optional name to use as an include guard
# default: doesn't emit an include guard
# include_guard = "mozilla_wr_bindings_h"
# An optional string of text to output between major sections of the generated
# file as a warning against manual editing
#
# default: doesn't emit anything
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
# Whether to include a comment with the version of cbindgen used to generate the file
# default: false
include_version = true
# An optional namespace to output around the generated bindings
# default: doesn't emit a namespace
namespace = "LDK"
# An optional list of namespaces to output around the generated bindings
# default: []
namespaces = []
# An optional list of namespaces to declare as using with "using namespace"
# default: []
using_namespaces = []
# A list of sys headers to #include (with angle brackets)
# default: []
# sys_includes = ["stdio", "string"]
# sys_includes = ["stdint"]
# A list of headers to #include (with quotes)
# default: []
# includes = ["my_great_lib.h"]
# Whether cbindgen's default C/C++ standard imports should be suppressed. These
# imports are included by default because our generated headers tend to require
# them (e.g. for uint32_t). Currently, the generated imports are:
#
# * for C: <stdarg.h>, <stdbool.h>, <stdint.h>, <stdlib.h>, <uchar.h>
#
# * for C++: <cstdarg>, <cstdint>, <cstdlib>, <new>, <cassert> (depending on config)
#
# default: false
no_includes = false
# Code Style Options
# The style to use for curly braces
#
# possible values: "SameLine", "NextLine"
#
# default: "SameLine"
braces = "SameLine"
# The desired length of a line to use when formatting lines
# default: 100
line_length = 80
# The amount of spaces to indent by
# default: 2
tab_width = 3
# How the generated documentation should be commented.
#
# possible values:
# * "c": /* like this */
# * "c99": // like this
# * "c++": /// like this
# * "doxy": like C, but with leading *'s on each line
# * "auto": "c++" if that's the language, "doxy" otherwise
#
# default: "auto"
documentation_style = "doxy"
# Codegen Options
# When generating a C header, the kind of declaration style to use for structs
# or enums.
#
# possible values:
# * "type": typedef struct { ... } MyType;
# * "tag": struct MyType { ... };
# * "both": typedef struct MyType { ... } MyType;
#
# default: "both"
style = "both"
# A list of substitutions for converting cfg's to ifdefs. cfgs which aren't
# defined here will just be discarded.
#
# e.g.
# `#[cfg(target = "freebsd")] ...`
# becomes
# `#if defined(DEFINE_FREEBSD) ... #endif`
[defines]
"target_os = freebsd" = "DEFINE_FREEBSD"
"feature = serde" = "DEFINE_SERDE"
[export]
# A list of additional items to always include in the generated bindings if they're
# found but otherwise don't appear to be used by the public API.
#
# default: []
# include = ["MyOrphanStruct", "MyGreatTypeRename"]
# A list of items to not include in the generated bindings
# default: []
# exclude = ["Bad"]
# A prefix to add before the name of every item
# default: no prefix is added
prefix = "LDK"
# Types of items that we'll generate. If empty, then all types of item are emitted.
#
# possible items: (TODO: explain these in detail)
# * "constants":
# * "globals":
# * "enums":
# * "structs":
# * "unions":
# * "typedefs":
# * "opaque":
# * "functions":
#
# default: []
item_types = ["constants", "globals", "enums", "structs", "unions", "typedefs", "opaque", "functions"]
# Whether applying rules in export.rename prevents export.prefix from applying.
#
# e.g. given this toml:
#
# [export]
# prefix = "capi_"
# [export.rename]
# "MyType" = "my_cool_type"
#
# You get the following results:
#
# renaming_overrides_prefixing = true:
# "MyType" => "my_cool_type"
#
# renaming_overrides_prefixing = false:
# "MyType => capi_my_cool_type"
#
# default: false
renaming_overrides_prefixing = true
# Table of name conversions to apply to item names (lhs becomes rhs)
# [export.rename]
# "MyType" = "my_cool_type"
# "my_function" = "BetterFunctionName"
# Table of things to prepend to the body of any struct, union, or enum that has the
# given name. This can be used to add things like methods which don't change ABI,
# mark fields private, etc
[export.pre_body]
"MyType" = """
MyType() = delete;
private:
"""
# Table of things to append to the body of any struct, union, or enum that has the
# given name. This can be used to add things like methods which don't change ABI.
[export.body]
"MyType" = """
void cppMethod() const;
"""
[layout]
# A string that should come before the name of any type which has been marked
# as `#[repr(packed)]`. For instance, "__attribute__((packed))" would be a
# reasonable value if targeting gcc/clang. A more portable solution would
# involve emitting the name of a macro which you define in a platform-specific
# way. e.g. "PACKED"
#
# default: `#[repr(packed)]` types will be treated as opaque, since it would
# be unsafe for C callers to use a incorrectly laid-out union.
packed = "PACKED"
# A string that should come before the name of any type which has been marked
# as `#[repr(align(n))]`. This string must be a function-like macro which takes
# a single argument (the requested alignment, `n`). For instance, a macro
# `#define`d as `ALIGNED(n)` in `header` which translates to
# `__attribute__((aligned(n)))` would be a reasonable value if targeting
# gcc/clang.
#
# default: `#[repr(align(n))]` types will be treated as opaque, since it
# could be unsafe for C callers to use a incorrectly-aligned union.
aligned_n = "ALIGNED"
[fn]
# An optional prefix to put before every function declaration
# default: no prefix added
# prefix = "WR_START_FUNC"
# An optional postfix to put after any function declaration
# default: no postix added
# postfix = "WR_END_FUNC"
# How to format function arguments
#
# possible values:
# * "horizontal": place all arguments on the same line
# * "vertical": place each argument on its own line
# * "auto": only use vertical if horizontal would exceed line_length
#
# default: "auto"
args = "horizontal"
# An optional string that should prefix function declarations which have been
# marked as `#[must_use]`. For instance, "__attribute__((warn_unused_result))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "MUST_USE_FUNC"
# default: nothing is emitted for must_use functions
must_use = "MUST_USE_RES"
# An optional string that, if present, will be used to generate Swift function
# and method signatures for generated functions, for example "CF_SWIFT_NAME".
# If no such macro is available in your toolchain, you can define one using the
# `header` option in cbindgen.toml
# default: no swift_name function attributes are generated
# swift_name_macro = "CF_SWIFT_NAME"
# A rule to use to rename function argument names. The renaming assumes the input
# is the Rust standard snake_case, however it accepts all the different rename_args
# inputs. This means many options here are no-ops or redundant.
#
# possible values (that actually do something):
# * "CamelCase": my_arg => myArg
# * "PascalCase": my_arg => MyArg
# * "GeckoCase": my_arg => aMyArg
# * "ScreamingSnakeCase": my_arg => MY_ARG
# * "None": apply no renaming
#
# technically possible values (that shouldn't have a purpose here):
# * "SnakeCase": apply no renaming
# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?)
# * "UpperCase": same as ScreamingSnakeCase in this context
# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context
#
# default: "None"
rename_args = "None"
# This rule specifies if the order of functions will be sorted in some way.
#
# "Name": sort by the name of the function
# "None": keep order in which the functions have been parsed
#
# default: "Name"
sort_by = "None"
[struct]
# A rule to use to rename struct field names. The renaming assumes the input is
# the Rust standard snake_case, however it acccepts all the different rename_args
# inputs. This means many options here are no-ops or redundant.
#
# possible values (that actually do something):
# * "CamelCase": my_arg => myArg
# * "PascalCase": my_arg => MyArg
# * "GeckoCase": my_arg => mMyArg
# * "ScreamingSnakeCase": my_arg => MY_ARG
# * "None": apply no renaming
#
# technically possible values (that shouldn't have a purpose here):
# * "SnakeCase": apply no renaming
# * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?)
# * "UpperCase": same as ScreamingSnakeCase in this context
# * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context
#
# default: "None"
rename_fields = "None"
# An optional string that should come before the name of any struct which has been
# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "MUST_USE_STRUCT"
#
# default: nothing is emitted for must_use structs
must_use = "MUST_USE_STRUCT"
# Whether a Rust type with associated consts should emit those consts inside the
# type's body. Otherwise they will be emitted trailing and with the type's name
# prefixed. This does nothing if the target is C, or if
# [const]allow_static_const = false
#
# default: false
# associated_constants_in_body: false
# Whether to derive a simple constructor that takes a value for every field.
# default: false
derive_constructor = true
# Whether to derive an operator== for all structs
# default: false
derive_eq = false
# Whether to derive an operator!= for all structs
# default: false
derive_neq = false
# Whether to derive an operator< for all structs
# default: false
derive_lt = false
# Whether to derive an operator<= for all structs
# default: false
derive_lte = false
# Whether to derive an operator> for all structs
# default: false
derive_gt = false
# Whether to derive an operator>= for all structs
# default: false
derive_gte = false
[enum]
# A rule to use to rename enum variants, and the names of any fields those
# variants have. This should probably be split up into two separate options, but
# for now, they're the same! See the documentation for `[struct]rename_fields`
# for how this applies to fields. Renaming of the variant assumes that the input
# is the Rust standard PascalCase. In the case of QualifiedScreamingSnakeCase,
# it also assumed that the enum's name is PascalCase.
#
# possible values (that actually do something):
# * "CamelCase": MyVariant => myVariant
# * "SnakeCase": MyVariant => my_variant
# * "ScreamingSnakeCase": MyVariant => MY_VARIANT
# * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT
# * "LowerCase": MyVariant => myvariant
# * "UpperCase": MyVariant => MYVARIANT
# * "None": apply no renaming
#
# technically possible values (that shouldn't have a purpose for the variants):
# * "PascalCase": apply no renaming
# * "GeckoCase": apply no renaming
#
# default: "None"
rename_variants = "None"
# Whether an extra "sentinel" enum variant should be added to all generated enums.
# Firefox uses this for their IPC serialization library.
#
# WARNING: if the sentinel is ever passed into Rust, behaviour will be Undefined.
# Rust does not know about this value, and will assume it cannot happen.
#
# default: false
add_sentinel = true
# Whether enum variant names should be prefixed with the name of the enum.
# default: false
prefix_with_name = true
# Whether to emit enums using "enum class" when targeting C++.
# default: true
enum_class = true
# Whether to generate static `::MyVariant(..)` constructors and `bool IsMyVariant()`
# methods for enums with fields.
#
# default: false
derive_helper_methods = false
# Whether to generate `const MyVariant& AsMyVariant() const` methods for enums with fields.
# default: false
derive_const_casts = false
# Whether to generate `MyVariant& AsMyVariant()` methods for enums with fields
# default: false
derive_mut_casts = false
# The name of the macro/function to use for asserting `IsMyVariant()` in the body of
# derived `AsMyVariant()` cast methods.
#
# default: "assert" (but also causes `<cassert>` to be included by default)
cast_assert_name = "MOZ_RELEASE_ASSERT"
# An optional string that should come before the name of any enum which has been
# marked as `#[must_use]`. For instance, "__attribute__((warn_unused))"
# would be a reasonable value if targeting gcc/clang. A more portable solution
# would involve emitting the name of a macro which you define in a
# platform-specific way. e.g. "MUST_USE_ENUM"
#
# Note that this refers to the *output* type. That means this will not apply to an enum
# with fields, as it will be emitted as a struct. `[struct]must_use` will apply there.
#
# default: nothing is emitted for must_use enums
must_use = "MUST_USE_ENUM"
# Whether enums with fields should generate destructors. This exists so that generic
# enums can be properly instantiated with payloads that are C++ types with
# destructors. This isn't necessary for structs because C++ has rules to
# automatically derive the correct constructors and destructors for those types.
#
# Care should be taken with this option, as Rust and C++ cannot
# properly interoperate with eachother's notions of destructors. Also, this may
# change the ABI for the type. Either your destructor-full enums must live
# exclusively within C++, or they must only be passed by-reference between
# C++ and Rust.
#
# default: false
derive_tagged_enum_destructor = false
# Whether enums with fields should generate copy-constructor. See the discussion on
# derive_tagged_enum_destructor for why this is both useful and very dangerous.
#
# default: false
derive_tagged_enum_copy_constructor = false
# Whether enums with fields should generate copy-assignment operators.
#
# This depends on also deriving copy-constructors, and it is highly encouraged
# for this to be set to true.
#
# default: false
derive_tagged_enum_copy_assignment = false
# Whether enums with fields should generate an empty, private destructor.
# This allows the auto-generated constructor functions to compile, if there are
# non-trivially constructible members. This falls in the same family of
# dangerousness as `derive_tagged_enum_copy_constructor` and co.
#
# default: false
private_default_tagged_enum_constructor = false
[const]
# Whether a generated constant can be a static const in C++ mode. I have no
# idea why you would turn this off.
#
# default: true
allow_static_const = true
# Whether a generated constant can be constexpr in C++ mode.
#
# default: false
[macro_expansion]
# Whether bindings should be generated for instances of the bitflags! macro.
# default: false
bitflags = true
# Options for how your Rust library should be parsed
[parse]
# Whether to parse dependent crates and include their types in the output
# default: false
parse_deps = true
# A white list of crate names that are allowed to be parsed. If this is defined,
# only crates found in this list will ever be parsed.
#
# default: there is no whitelist (NOTE: this is the opposite of [])
include = ["webrender", "webrender_traits"]
# A black list of crate names that are not allowed to be parsed.
# default: []
exclude = ["libc"]
# Whether to use a new temporary target directory when running `rustc --pretty=expanded`.
# This may be required for some build processes.
#
# default: false
clean = false
# Which crates other than the top-level binding crate we should generate
# bindings for.
#
# default: []
extra_bindings = ["my_awesome_dep"]
[parse.expand]
# A list of crate names that should be run through `cargo expand` before
# parsing to expand any macros. Note that if a crate is named here, it
# will always be parsed, even if the blacklist/whitelist says it shouldn't be.
#
# default: []
crates = ["euclid"]
# If enabled, use the `--all-features` option when expanding. Ignored when
# `features` is set. For backwards-compatibility, this is forced on if
# `expand = ["euclid"]` shorthand is used.
#
# default: false
all_features = false
# When `all_features` is disabled and this is also disabled, use the
# `--no-default-features` option when expanding.
#
# default: true
default_features = true
# A list of feature names that should be used when running `cargo expand`. This
# combines with `default_features` like in your `Cargo.toml`. Note that the features
# listed here are features for the current crate being built, *not* the crates
# being expanded. The crate's `Cargo.toml` must take care of enabling the
# appropriate features in its dependencies
#
# default: []
features = ["cbindgen"]

View file

@ -0,0 +1,96 @@
#include "include/rust_types.h"
#include "include/lightning.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
void print_log(const void *this_arg, const char *record) {
printf("%s", record);
}
uint32_t get_fee(const void *this_arg, LDKConfirmationTarget target) {
if (target == LDKConfirmationTarget_Background) {
return 253;
} else {
return 507;
}
}
void broadcast_tx(const void *this_arg, LDKTransaction tx) {
//TODO
}
LDKCResult_NoneChannelMonitorUpdateErrZ add_channel_monitor(const void *this_arg, LDKOutPoint funding_txo, LDKChannelMonitor monitor) {
return CResult_NoneChannelMonitorUpdateErrZ_ok();
}
LDKCResult_NoneChannelMonitorUpdateErrZ update_channel_monitor(const void *this_arg, LDKOutPoint funding_txo, LDKChannelMonitorUpdate monitor) {
return CResult_NoneChannelMonitorUpdateErrZ_ok();
}
LDKCVec_MonitorEventZ monitors_pending_monitor_events(const void *this_arg) {
LDKCVec_MonitorEventZ empty_htlc_vec = {
.data = NULL,
.datalen = 0,
};
return empty_htlc_vec;
}
int main() {
uint8_t node_seed[32];
memset(node_seed, 0, 32);
LDKNetwork net = LDKNetwork_Bitcoin;
LDKLogger logger = {
.this_arg = NULL,
.log = print_log,
.free = NULL,
};
LDKFeeEstimator fee_est = {
.this_arg = NULL,
.get_est_sat_per_1000_weight = get_fee,
.free = NULL
};
LDKManyChannelMonitor mon = {
.this_arg = NULL,
.add_monitor = add_channel_monitor,
.update_monitor = update_channel_monitor,
.get_and_clear_pending_monitor_events = monitors_pending_monitor_events,
.free = NULL,
};
LDKBroadcasterInterface broadcast = {
broadcast.this_arg = NULL,
broadcast.broadcast_transaction = broadcast_tx,
.free = NULL,
};
LDKKeysManager keys = KeysManager_new(&node_seed, net, 0, 0);
LDKKeysInterface keys_source = KeysManager_as_KeysInterface(&keys);
LDKUserConfig config = UserConfig_default();
LDKChannelManager cm = ChannelManager_new(net, fee_est, mon, broadcast, logger, keys_source, config, 0);
LDKCVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm);
assert((unsigned long)channels.data < 4096); // There's an offset, but it should still be an offset against null in the 0 page
assert(channels.datalen == 0);
CVec_ChannelDetailsZ_free(channels);
LDKEventsProvider prov = ChannelManager_as_EventsProvider(&cm);
LDKCVec_EventZ events = (prov.get_and_clear_pending_events)(prov.this_arg);
assert((unsigned long)events.data < 4096); // There's an offset, but it should still be an offset against null in the 0 page
assert(events.datalen == 0);
ChannelManager_free(cm);
KeysManager_free(keys);
// Check that passing empty vecs to rust doesn't blow it up:
LDKCVec_MonitorEventZ empty_htlc_vec = {
.data = NULL,
.datalen = 0,
};
CVec_MonitorEventZ_free(empty_htlc_vec);
}

View file

@ -0,0 +1,556 @@
extern "C" {
#include "include/rust_types.h"
#include "include/lightning.h"
}
#include "include/lightningpp.hpp"
#include <assert.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <chrono>
#include <functional>
#include <thread>
#include <mutex>
#include <vector>
const uint8_t valid_node_announcement[] = {
0x94, 0xe4, 0xf5, 0x61, 0x41, 0x24, 0x7d, 0x90, 0x23, 0xa0, 0xc8, 0x34, 0x8c, 0xc4, 0xca, 0x51,
0xd8, 0x17, 0x59, 0xff, 0x7d, 0xac, 0x8c, 0x9b, 0x63, 0x29, 0x1c, 0xe6, 0x12, 0x12, 0x93, 0xbd,
0x66, 0x4d, 0x6b, 0x9c, 0xfb, 0x35, 0xda, 0x16, 0x06, 0x3d, 0xf0, 0x8f, 0x8a, 0x39, 0x99, 0xa2,
0xf2, 0x5d, 0x12, 0x0f, 0x2b, 0x42, 0x1b, 0x8b, 0x9a, 0xfe, 0x33, 0x0c, 0xeb, 0x33, 0x5e, 0x52,
0xee, 0x99, 0xa1, 0x07, 0x06, 0xed, 0xf8, 0x48, 0x7a, 0xc6, 0xe5, 0xf5, 0x5e, 0x01, 0x3a, 0x41,
0x2f, 0x18, 0x94, 0x8a, 0x3b, 0x0a, 0x52, 0x3f, 0xbf, 0x61, 0xa9, 0xc5, 0x4f, 0x70, 0xee, 0xb8,
0x79, 0x23, 0xbb, 0x1a, 0x44, 0x7d, 0x91, 0xe6, 0x2a, 0xbc, 0xa1, 0x07, 0xbc, 0x65, 0x3b, 0x02,
0xd9, 0x1d, 0xb2, 0xf2, 0x3a, 0xcb, 0x75, 0x79, 0xc6, 0x66, 0xd8, 0xc1, 0x71, 0x29, 0xdf, 0x04,
0x60, 0xf4, 0xbf, 0x07, 0x7b, 0xb9, 0xc2, 0x11, 0x94, 0x6a, 0x28, 0xc2, 0xdd, 0xd8, 0x7b, 0x44,
0x8f, 0x08, 0xe3, 0xc8, 0xd8, 0xf4, 0x81, 0xb0, 0x9f, 0x94, 0xcb, 0xc8, 0xc1, 0x3c, 0xc2, 0x6e,
0x31, 0x26, 0xfc, 0x33, 0x16, 0x3b, 0xe0, 0xde, 0xa1, 0x16, 0x21, 0x9f, 0x89, 0xdd, 0x97, 0xa4,
0x41, 0xf2, 0x9f, 0x19, 0xb1, 0xae, 0x82, 0xf7, 0x85, 0x9a, 0xb7, 0x8f, 0xb7, 0x52, 0x7a, 0x72,
0xf1, 0x5e, 0x89, 0xe1, 0x8a, 0xcd, 0x40, 0xb5, 0x8e, 0xc3, 0xca, 0x42, 0x76, 0xa3, 0x6e, 0x1b,
0xf4, 0x87, 0x35, 0x30, 0x58, 0x43, 0x04, 0xd9, 0x2c, 0x50, 0x54, 0x55, 0x47, 0x6f, 0x70, 0x9b,
0x42, 0x1f, 0x91, 0xfc, 0xa1, 0xdb, 0x72, 0x53, 0x96, 0xc8, 0xe5, 0xcd, 0x0e, 0xcb, 0xa0, 0xfe,
0x6b, 0x08, 0x77, 0x48, 0xb7, 0xad, 0x4a, 0x69, 0x7c, 0xdc, 0xd8, 0x04, 0x28, 0x35, 0x9b, 0x73,
0x00, 0x00, 0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce,
0xc3, 0xae, 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, 0x01, 0xea, 0x33, 0x09, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5b, 0xe5, 0xe9, 0x47, 0x82,
0x09, 0x67, 0x4a, 0x96, 0xe6, 0x0f, 0x1f, 0x03, 0x7f, 0x61, 0x76, 0x54, 0x0f, 0xd0, 0x01, 0xfa,
0x1d, 0x64, 0x69, 0x47, 0x70, 0xc5, 0x6a, 0x77, 0x09, 0xc4, 0x2c, 0x03, 0x5c, 0x4e, 0x0d, 0xec,
0x72, 0x15, 0xe2, 0x68, 0x33, 0x93, 0x87, 0x30, 0xe5, 0xe5, 0x05, 0xaa, 0x62, 0x50, 0x4d, 0xa8,
0x5b, 0xa5, 0x71, 0x06, 0xa4, 0x6b, 0x5a, 0x24, 0x04, 0xfc, 0x9d, 0x8e, 0x02, 0xba, 0x72, 0xa6,
0xe8, 0xba, 0x53, 0xe8, 0xb9, 0x71, 0xad, 0x0c, 0x98, 0x23, 0x96, 0x8a, 0xef, 0x4d, 0x78, 0xce,
0x8a, 0xf2, 0x55, 0xab, 0x43, 0xdf, 0xf8, 0x30, 0x03, 0xc9, 0x02, 0xfb, 0x8d, 0x02, 0x16, 0x34,
0x5b, 0xf8, 0x31, 0x16, 0x4a, 0x03, 0x75, 0x8e, 0xae, 0xa5, 0xe8, 0xb6, 0x6f, 0xee, 0x2b, 0xe7,
0x71, 0x0b, 0x8f, 0x19, 0x0e, 0xe8, 0x80, 0x24, 0x90, 0x32, 0xa2, 0x9e, 0xd6, 0x6e
};
// A simple block containing only one transaction (which is the channel-open transaction for the
// channel we'll create). This was originally created by printing additional data in a simple
// rust-lightning unit test.
const uint8_t channel_open_block[] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xa2, 0x47, 0xd2, 0xf8, 0xd4, 0xe0, 0x6a, 0x3f, 0xf9, 0x7a, 0x9a, 0x34,
0xbb, 0xa9, 0x96, 0xde, 0x63, 0x84, 0x5a, 0xce, 0xcf, 0x98, 0xb8, 0xbb, 0x75, 0x4c, 0x4f, 0x7d,
0xee, 0x4c, 0xa9, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x40, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x20, 0x12, 0x70,
0x44, 0x41, 0x40, 0xaf, 0xc5, 0x72, 0x97, 0xc8, 0x69, 0xba, 0x04, 0xdb, 0x28, 0x7b, 0xd7, 0x32,
0x07, 0x33, 0x3a, 0x4a, 0xc2, 0xc5, 0x56, 0x06, 0x05, 0x65, 0xd7, 0xa8, 0xcf, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00
};
// The first transaction in the block is header (80 bytes) + transaction count (1 byte) into the block data.
const uint8_t *channel_open_tx = channel_open_block + 81;
const uint8_t channel_open_txid[] = {
0x5f, 0xa9, 0x4c, 0xee, 0x7d, 0x4f, 0x4c, 0x75, 0xbb, 0xb8, 0x98, 0xcf, 0xce, 0x5a, 0x84, 0x63,
0xde, 0x96, 0xa9, 0xbb, 0x34, 0x9a, 0x7a, 0xf9, 0x3f, 0x6a, 0xe0, 0xd4, 0xf8, 0xd2, 0x47, 0xa2
};
// Two blocks built on top of channel_open_block:
const uint8_t block_1[] = {
0x01, 0x00, 0x00, 0x00, 0x65, 0x8e, 0xf1, 0x90, 0x88, 0xfa, 0x13, 0x9c, 0x6a, 0xea, 0xf7, 0xc1,
0x5a, 0xdd, 0x52, 0x4d, 0x3c, 0x48, 0x03, 0xb3, 0x9b, 0x25, 0x4f, 0x02, 0x79, 0x05, 0x90, 0xe0,
0xc4, 0x8d, 0xa0, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
const uint8_t block_2[] = {
0x01, 0x00, 0x00, 0x00, 0xf2, 0x08, 0x87, 0x51, 0xcb, 0xb1, 0x1a, 0x51, 0x76, 0x01, 0x6c, 0x5d,
0x76, 0x26, 0x54, 0x6f, 0xd9, 0xbd, 0xa6, 0xa5, 0xe9, 0x4b, 0x21, 0x6e, 0xda, 0xa3, 0x64, 0x23,
0xcd, 0xf1, 0xe2, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
const LDKThirtyTwoBytes payment_preimage_1 = {
.data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1 }
};
const LDKThirtyTwoBytes payment_hash_1 = {
.data = {
0xdc, 0xb1, 0xac, 0x4a, 0x5d, 0xe3, 0x70, 0xca, 0xd0, 0x91, 0xc1, 0x3f, 0x13, 0xae, 0xe2, 0xf9,
0x36, 0xc2, 0x78, 0xfa, 0x05, 0xd2, 0x64, 0x65, 0x3c, 0x0c, 0x13, 0x21, 0x85, 0x2a, 0x35, 0xe8
}
};
void print_log(const void *this_arg, const char *record) {
printf("%p - %s\n", this_arg, record);
}
uint32_t get_fee(const void *this_arg, LDKConfirmationTarget target) {
if (target == LDKConfirmationTarget_Background) {
return 253;
} else {
return 507;
}
// Note that we don't call _free() on target, but that's OK, its unitary
}
static int num_txs_broadcasted = 0; // Technically a race, but ints are atomic on x86
void broadcast_tx(const void *this_arg, LDKTransaction tx) {
num_txs_broadcasted += 1;
//TODO
}
struct NodeMonitors {
std::mutex mut;
std::vector<std::pair<LDK::OutPoint, LDK::ChannelMonitor>> mons;
LDKChainWatchInterfaceUtil* watch_util;
LDKLogger* logger;
};
void NodeMonitors_free(void *this_arg) {
NodeMonitors* arg = (NodeMonitors*) this_arg;
delete arg;
}
LDKCResult_NoneChannelMonitorUpdateErrZ add_channel_monitor(const void *this_arg, LDKOutPoint funding_txo_arg, LDKChannelMonitor monitor_arg) {
// First bind the args to C++ objects so they auto-free
LDK::ChannelMonitor mon(std::move(monitor_arg));
LDK::OutPoint funding_txo(std::move(funding_txo_arg));
NodeMonitors* arg = (NodeMonitors*) this_arg;
std::unique_lock<std::mutex> l(arg->mut);
LDK::ChainWatchInterface watch = ChainWatchInterfaceUtil_as_ChainWatchInterface(arg->watch_util);
LDK::C2Tuple_OutPointScriptZ funding_info = ChannelMonitor_get_funding_txo(&mon);
LDKThirtyTwoBytes funding_txid;
memcpy(funding_txid.data, OutPoint_get_txid(funding_info->a), 32);
LDK::C2Tuple_Txidu32Z outpoint(C2Tuple_Txidu32Z_new(funding_txid, OutPoint_get_index(funding_info->a)));
watch->install_watch_outpoint(watch->this_arg, outpoint, LDKu8slice {
.data = funding_info->b->data,
.datalen = funding_info->b->datalen,
});
watch->install_watch_tx(watch->this_arg, &funding_txid.data, LDKu8slice {
.data = funding_info->b->data,
.datalen = funding_info->b->datalen,
});
arg->mons.push_back(std::make_pair(std::move(funding_txo), std::move(mon)));
return CResult_NoneChannelMonitorUpdateErrZ_ok();
}
static int mons_updated = 0; // Technically a race, but ints are atomic on x86.
LDKCResult_NoneChannelMonitorUpdateErrZ update_channel_monitor(const void *this_arg, LDKOutPoint funding_txo_arg, LDKChannelMonitorUpdate monitor_arg) {
// First bind the args to C++ objects so they auto-free
LDK::ChannelMonitorUpdate update(std::move(monitor_arg));
LDK::OutPoint funding_txo(std::move(funding_txo_arg));
NodeMonitors* arg = (NodeMonitors*) this_arg;
std::unique_lock<std::mutex> l(arg->mut);
bool updated = false;
for (auto& mon : arg->mons) {
if (OutPoint_get_index(&mon.first) == OutPoint_get_index(&funding_txo) &&
!memcmp(OutPoint_get_txid(&mon.first), OutPoint_get_txid(&funding_txo), 32)) {
updated = true;
LDKBroadcasterInterface broadcaster = {
.broadcast_transaction = broadcast_tx,
};
LDK::CResult_NoneMonitorUpdateErrorZ res = ChannelMonitor_update_monitor(&mon.second, update, &broadcaster, arg->logger);
assert(res->result_ok);
}
}
assert(updated);
mons_updated += 1;
return CResult_NoneChannelMonitorUpdateErrZ_ok();
}
LDKCVec_MonitorEventZ monitors_pending_monitor_events(const void *this_arg) {
NodeMonitors* arg = (NodeMonitors*) this_arg;
std::unique_lock<std::mutex> l(arg->mut);
if (arg->mons.size() == 0) {
return LDKCVec_MonitorEventZ {
.data = NULL,
.datalen = 0,
};
} else {
// We only ever actually have one channel per node, plus concatenating two
// Rust Vecs to each other from C++ will require a bit of effort.
assert(arg->mons.size() == 1);
return ChannelMonitor_get_and_clear_pending_monitor_events(&arg->mons[0].second);
}
}
uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) {
return write((int)((long)this_arg), data.data, data.datalen);
}
void sock_disconnect_socket(void *this_arg) {
close((int)((long)this_arg));
}
bool sock_eq(const void *this_arg, const void *other_arg) {
return this_arg == other_arg;
}
uint64_t sock_hash(const void *this_arg) {
return (uint64_t)this_arg;
}
void sock_read_data_thread(int rdfd, LDKSocketDescriptor *peer_descriptor, LDKPeerManager *pm) {
unsigned char buf[1024];
LDKu8slice data;
data.data = buf;
ssize_t readlen = 0;
while ((readlen = read(rdfd, buf, 1024)) > 0) {
data.datalen = readlen;
LDK::CResult_boolPeerHandleErrorZ res = PeerManager_read_event(&*pm, peer_descriptor, data);
if (!res->result_ok) {
peer_descriptor->disconnect_socket(peer_descriptor->this_arg);
return;
}
PeerManager_process_events(pm);
}
PeerManager_socket_disconnected(&*pm, peer_descriptor);
}
int main() {
uint8_t node_seed[32];
memset(&node_seed, 0, 32);
LDKPublicKey null_pk;
memset(&null_pk, 0, sizeof(null_pk));
LDKNetwork network = LDKNetwork_Testnet;
// Trait implementations:
LDKFeeEstimator fee_est {
.this_arg = NULL,
.get_est_sat_per_1000_weight = get_fee,
.free = NULL,
};
LDKBroadcasterInterface broadcast {
.this_arg = NULL,
.broadcast_transaction = broadcast_tx,
.free = NULL,
};
// Instantiate classes for node 1:
LDKLogger logger1 {
.this_arg = (void*)1,
.log = print_log,
.free = NULL,
};
LDK::ChainWatchInterfaceUtil chain1 = ChainWatchInterfaceUtil_new(network);
LDK::BlockNotifier blocks1 = BlockNotifier_new(ChainWatchInterfaceUtil_as_ChainWatchInterface(&chain1));
LDKManyChannelMonitor mon1 {
.this_arg = new NodeMonitors { .watch_util = &chain1, .logger = &logger1 },
.add_monitor = add_channel_monitor,
.update_monitor = update_channel_monitor,
.get_and_clear_pending_monitor_events = monitors_pending_monitor_events,
.free = NodeMonitors_free,
};
LDK::KeysManager keys1 = KeysManager_new(&node_seed, network, 0, 0);
LDK::KeysInterface keys_source1 = KeysManager_as_KeysInterface(&keys1);
LDKSecretKey node_secret1 = keys_source1->get_node_secret(keys_source1->this_arg);
LDK::UserConfig config1 = UserConfig_default();
LDK::ChannelManager cm1 = ChannelManager_new(network, fee_est, mon1, broadcast, logger1, KeysManager_as_KeysInterface(&keys1), config1, 0);
BlockNotifier_register_listener(&blocks1, ChannelManager_as_ChainListener(&cm1));
LDK::CVec_ChannelDetailsZ channels = ChannelManager_list_channels(&cm1);
assert(channels->datalen == 0);
LDK::NetGraphMsgHandler net_graph1 = NetGraphMsgHandler_new(ChainWatchInterfaceUtil_as_ChainWatchInterface(&chain1), logger1);
LDK::MessageHandler msg_handler1 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm1), NetGraphMsgHandler_as_RoutingMessageHandler(&net_graph1));
LDKThirtyTwoBytes random_bytes = keys_source1->get_secure_random_bytes(keys_source1->this_arg);
LDK::PeerManager net1 = PeerManager_new(msg_handler1, node_secret1, &random_bytes.data, logger1);
// Demo getting a channel key and check that its returning real pubkeys:
LDK::ChannelKeys chan_keys1 = keys_source1->get_channel_keys(keys_source1->this_arg, false, 42);
chan_keys1->set_pubkeys(&chan_keys1); // Make sure pubkeys is defined
LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_keys1->pubkeys);
assert(memcmp(&payment_point, &null_pk, sizeof(null_pk)));
// Instantiate classes for node 2:
LDKLogger logger2 {
.this_arg = (void*)2,
.log = print_log,
.free = NULL,
};
LDK::ChainWatchInterfaceUtil chain2 = ChainWatchInterfaceUtil_new(network);
LDK::BlockNotifier blocks2 = BlockNotifier_new(ChainWatchInterfaceUtil_as_ChainWatchInterface(&chain2));
LDKManyChannelMonitor mon2 {
.this_arg = new NodeMonitors { .watch_util = &chain2, .logger = &logger2 },
.add_monitor = add_channel_monitor,
.update_monitor = update_channel_monitor,
.get_and_clear_pending_monitor_events = monitors_pending_monitor_events,
.free = NodeMonitors_free,
};
memset(&node_seed, 1, 32);
LDK::KeysManager keys2 = KeysManager_new(&node_seed, network, 0, 0);
LDK::KeysInterface keys_source2 = KeysManager_as_KeysInterface(&keys2);
LDKSecretKey node_secret2 = keys_source2->get_node_secret(keys_source2->this_arg);
LDK::ChannelHandshakeConfig handshake_config2 = ChannelHandshakeConfig_default();
ChannelHandshakeConfig_set_minimum_depth(&handshake_config2, 2);
LDK::UserConfig config2 = UserConfig_default();
UserConfig_set_own_channel_config(&config2, handshake_config2);
LDK::ChannelManager cm2 = ChannelManager_new(network, fee_est, mon2, broadcast, logger2, KeysManager_as_KeysInterface(&keys2), config2, 0);
BlockNotifier_register_listener(&blocks2, ChannelManager_as_ChainListener(&cm2));
LDK::CVec_ChannelDetailsZ channels2 = ChannelManager_list_channels(&cm2);
assert(channels2->datalen == 0);
LDK::NetGraphMsgHandler net_graph2 = NetGraphMsgHandler_new(ChainWatchInterfaceUtil_as_ChainWatchInterface(&chain2), logger2);
LDK::RoutingMessageHandler net_msgs2 = NetGraphMsgHandler_as_RoutingMessageHandler(&net_graph2);
LDK::ChannelAnnouncement chan_ann = ChannelAnnouncement_read(LDKu8slice { .data = valid_node_announcement, .datalen = sizeof(valid_node_announcement) });
LDK::CResult_boolLightningErrorZ ann_res = net_msgs2->handle_channel_announcement(net_msgs2->this_arg, &chan_ann);
assert(ann_res->result_ok);
LDK::MessageHandler msg_handler2 = MessageHandler_new(ChannelManager_as_ChannelMessageHandler(&cm2), net_msgs2);
LDKThirtyTwoBytes random_bytes2 = keys_source2->get_secure_random_bytes(keys_source2->this_arg);
LDK::PeerManager net2 = PeerManager_new(msg_handler2, node_secret2, &random_bytes2.data, logger2);
// Open a connection!
int pipefds_1_to_2[2];
int pipefds_2_to_1[2];
assert(!pipe(pipefds_1_to_2));
assert(!pipe(pipefds_2_to_1));
LDKSocketDescriptor sock1 {
.this_arg = (void*)(long)pipefds_1_to_2[1],
.send_data = sock_send_data,
.disconnect_socket = sock_disconnect_socket,
.eq = sock_eq,
.hash = sock_hash,
.clone = NULL,
.free = NULL,
};
LDKSocketDescriptor sock2 {
.this_arg = (void*)(long)pipefds_2_to_1[1],
.send_data = sock_send_data,
.disconnect_socket = sock_disconnect_socket,
.eq = sock_eq,
.hash = sock_hash,
.clone = NULL,
.free = NULL,
};
std::thread t1(&sock_read_data_thread, pipefds_2_to_1[0], &sock1, &net1);
std::thread t2(&sock_read_data_thread, pipefds_1_to_2[0], &sock2, &net2);
// Note that we have to bind the result to a C++ class to make sure it gets free'd
LDK::CResult_CVec_u8ZPeerHandleErrorZ con_res = PeerManager_new_outbound_connection(&net1, ChannelManager_get_our_node_id(&cm2), sock1);
assert(con_res->result_ok);
LDK::CResult_NonePeerHandleErrorZ con_res2 = PeerManager_new_inbound_connection(&net2, sock2);
assert(con_res2->result_ok);
auto writelen = write(pipefds_1_to_2[1], con_res->contents.result->data, con_res->contents.result->datalen);
assert(writelen > 0 && uint64_t(writelen) == con_res->contents.result->datalen);
while (true) {
// Wait for the initial handshakes to complete...
LDK::CVec_PublicKeyZ peers_1 = PeerManager_get_peer_node_ids(&net1);
LDK::CVec_PublicKeyZ peers_2 = PeerManager_get_peer_node_ids(&net2);
if (peers_1->datalen == 1 && peers_2->datalen ==1) { break; }
std::this_thread::yield();
}
// Note that we have to bind the result to a C++ class to make sure it gets free'd
LDK::CResult_NoneAPIErrorZ res = ChannelManager_create_channel(&cm1, ChannelManager_get_our_node_id(&cm2), 40000, 1000, 42, config1);
assert(res->result_ok);
PeerManager_process_events(&net1);
LDK::CVec_ChannelDetailsZ new_channels = ChannelManager_list_channels(&cm1);
assert(new_channels->datalen == 1);
LDKPublicKey chan_open_pk = ChannelDetails_get_remote_network_id(&new_channels->data[0]);
assert(!memcmp(chan_open_pk.compressed_form, ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
while (true) {
LDK::CVec_ChannelDetailsZ new_channels_2 = ChannelManager_list_channels(&cm2);
if (new_channels_2->datalen == 1) {
// Sample getting our counterparty's init features (which used to be hard to do without a memory leak):
const LDK::InitFeatures init_feats = ChannelDetails_get_counterparty_features(&new_channels_2->data[0]);
assert(init_feats->inner != NULL);
break;
}
std::this_thread::yield();
}
LDKEventsProvider ev1 = ChannelManager_as_EventsProvider(&cm1);
while (true) {
LDK::CVec_EventZ events = ev1.get_and_clear_pending_events(ev1.this_arg);
if (events->datalen == 1) {
assert(events->data[0].tag == LDKEvent_FundingGenerationReady);
assert(events->data[0].funding_generation_ready.user_channel_id == 42);
assert(events->data[0].funding_generation_ready.channel_value_satoshis == 40000);
assert(events->data[0].funding_generation_ready.output_script.datalen == 34);
assert(!memcmp(events->data[0].funding_generation_ready.output_script.data, channel_open_tx + 58, 34));
LDKThirtyTwoBytes txid;
for (int i = 0; i < 32; i++) { txid.data[i] = channel_open_txid[31-i]; }
LDK::OutPoint outp = OutPoint_new(txid, 0);
ChannelManager_funding_transaction_generated(&cm1, &events->data[0].funding_generation_ready.temporary_channel_id.data, outp);
break;
}
std::this_thread::yield();
}
// We observe when the funding signed messages have been exchanged by
// waiting for two monitors to be registered.
PeerManager_process_events(&net1);
while (true) {
LDK::CVec_EventZ events = ev1.get_and_clear_pending_events(ev1.this_arg);
if (events->datalen == 1) {
assert(events->data[0].tag == LDKEvent_FundingBroadcastSafe);
assert(events->data[0].funding_broadcast_safe.user_channel_id == 42);
break;
}
std::this_thread::yield();
}
BlockNotifier_block_connected(&blocks1, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
BlockNotifier_block_connected(&blocks2, LDKu8slice { .data = channel_open_block, .datalen = sizeof(channel_open_block) }, 1);
BlockNotifier_block_connected(&blocks1, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
BlockNotifier_block_connected(&blocks2, LDKu8slice { .data = block_1, .datalen = sizeof(block_1) }, 2);
BlockNotifier_block_connected(&blocks1, LDKu8slice { .data = block_2, .datalen = sizeof(block_2) }, 3);
BlockNotifier_block_connected(&blocks2, LDKu8slice { .data = block_2, .datalen = sizeof(block_2) }, 3);
PeerManager_process_events(&net1);
PeerManager_process_events(&net2);
// Now send funds from 1 to 2!
while (true) {
LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
if (outbound_channels->datalen == 1) {
const LDKChannelDetails *channel = &outbound_channels->data[0];
// Note that the channel ID is the same as the channel txid reversed as the output index is 0
uint8_t expected_chan_id[32];
for (int i = 0; i < 32; i++) { expected_chan_id[i] = channel_open_txid[31-i]; }
assert(!memcmp(ChannelDetails_get_channel_id(channel), expected_chan_id, 32));
assert(!memcmp(ChannelDetails_get_remote_network_id(channel).compressed_form,
ChannelManager_get_our_node_id(&cm2).compressed_form, 33));
assert(ChannelDetails_get_channel_value_satoshis(channel) == 40000);
// We opened the channel with 1000 push_msat:
assert(ChannelDetails_get_outbound_capacity_msat(channel) == 40000*1000 - 1000);
assert(ChannelDetails_get_inbound_capacity_msat(channel) == 1000);
assert(ChannelDetails_get_is_live(channel));
break;
}
std::this_thread::yield();
}
LDK::CVec_ChannelDetailsZ outbound_channels = ChannelManager_list_usable_channels(&cm1);
LDKThirtyTwoBytes payment_secret;
memset(payment_secret.data, 0x42, 32);
{
LDK::LockedNetworkGraph graph_2_locked = NetGraphMsgHandler_read_locked_graph(&net_graph2);
LDK::NetworkGraph graph_2_ref = LockedNetworkGraph_graph(&graph_2_locked);
LDK::CResult_RouteLightningErrorZ route = get_route(ChannelManager_get_our_node_id(&cm1), &graph_2_ref, ChannelManager_get_our_node_id(&cm2), &outbound_channels, LDKCVec_RouteHintZ {
.data = NULL, .datalen = 0
}, 5000, 10, logger1);
assert(route->result_ok);
LDK::CResult_NonePaymentSendFailureZ send_res = ChannelManager_send_payment(&cm1, route->contents.result, payment_hash_1, payment_secret);
assert(send_res->result_ok);
}
mons_updated = 0;
PeerManager_process_events(&net1);
while (mons_updated != 4) {
std::this_thread::yield();
}
// Check that we received the payment!
LDKEventsProvider ev2 = ChannelManager_as_EventsProvider(&cm2);
while (true) {
LDK::CVec_EventZ events = ev2.get_and_clear_pending_events(ev2.this_arg);
if (events->datalen == 1) {
assert(events->data[0].tag == LDKEvent_PendingHTLCsForwardable);
break;
}
std::this_thread::yield();
}
ChannelManager_process_pending_htlc_forwards(&cm2);
PeerManager_process_events(&net2);
mons_updated = 0;
{
LDK::CVec_EventZ events = ev2.get_and_clear_pending_events(ev2.this_arg);
assert(events->datalen == 1);
assert(events->data[0].tag == LDKEvent_PaymentReceived);
assert(!memcmp(events->data[0].payment_received.payment_hash.data, payment_hash_1.data, 32));
assert(!memcmp(events->data[0].payment_received.payment_secret.data, payment_secret.data, 32));
assert(events->data[0].payment_received.amt == 5000);
assert(ChannelManager_claim_funds(&cm2, payment_preimage_1, payment_secret, 5000));
}
PeerManager_process_events(&net2);
// Wait until we've passed through a full set of monitor updates (ie new preimage + CS/RAA messages)
while (mons_updated != 5) {
std::this_thread::yield();
}
{
LDK::CVec_EventZ events = ev1.get_and_clear_pending_events(ev1.this_arg);
assert(events->datalen == 1);
assert(events->data[0].tag == LDKEvent_PaymentSent);
assert(!memcmp(events->data[0].payment_sent.payment_preimage.data, payment_preimage_1.data, 32));
}
// Close the channel.
uint8_t chan_id[32];
for (int i = 0; i < 32; i++) { chan_id[i] = channel_open_txid[31-i]; }
LDK::CResult_NoneAPIErrorZ close_res = ChannelManager_close_channel(&cm1, &chan_id);
assert(close_res->result_ok);
PeerManager_process_events(&net1);
num_txs_broadcasted = 0;
while (num_txs_broadcasted != 2) {
std::this_thread::yield();
}
LDK::CVec_ChannelDetailsZ chans_after_close1 = ChannelManager_list_channels(&cm1);
assert(chans_after_close1->datalen == 0);
LDK::CVec_ChannelDetailsZ chans_after_close2 = ChannelManager_list_channels(&cm2);
assert(chans_after_close2->datalen == 0);
close(pipefds_1_to_2[0]);
close(pipefds_2_to_1[0]);
close(pipefds_1_to_2[1]);
close(pipefds_2_to_1[1]);
t1.join();
t2.join();
// Few extra random tests:
LDKSecretKey sk;
memset(&sk, 42, 32);
LDKC2Tuple_u64u64Z kdiv_params;
kdiv_params.a = (uint64_t*) malloc(8);
kdiv_params.b = (uint64_t*) malloc(8);
*kdiv_params.a = 42;
*kdiv_params.b = 42;
LDK::InMemoryChannelKeys keys = InMemoryChannelKeys_new(sk, sk, sk, sk, sk, random_bytes, 42, kdiv_params);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,154 @@
#if defined(__GNUC__)
#define MUST_USE_STRUCT __attribute__((warn_unused))
#else
#define MUST_USE_STRUCT
#endif
#if defined(__GNUC__)
#define MUST_USE_RES __attribute__((warn_unused_result))
#else
#define MUST_USE_RES
#endif
struct nativeChannelHandshakeConfigOpaque;
typedef struct nativeChannelHandshakeConfigOpaque LDKnativeChannelHandshakeConfig;
struct nativeChannelHandshakeLimitsOpaque;
typedef struct nativeChannelHandshakeLimitsOpaque LDKnativeChannelHandshakeLimits;
struct nativeChannelConfigOpaque;
typedef struct nativeChannelConfigOpaque LDKnativeChannelConfig;
struct nativeUserConfigOpaque;
typedef struct nativeUserConfigOpaque LDKnativeUserConfig;
struct nativeChainWatchedUtilOpaque;
typedef struct nativeChainWatchedUtilOpaque LDKnativeChainWatchedUtil;
struct nativeBlockNotifierOpaque;
typedef struct nativeBlockNotifierOpaque LDKnativeBlockNotifier;
struct nativeChainWatchInterfaceUtilOpaque;
typedef struct nativeChainWatchInterfaceUtilOpaque LDKnativeChainWatchInterfaceUtil;
struct nativeOutPointOpaque;
typedef struct nativeOutPointOpaque LDKnativeOutPoint;
struct LDKChannelKeys;
typedef struct LDKChannelKeys LDKChannelKeys;
struct nativeInMemoryChannelKeysOpaque;
typedef struct nativeInMemoryChannelKeysOpaque LDKnativeInMemoryChannelKeys;
struct nativeKeysManagerOpaque;
typedef struct nativeKeysManagerOpaque LDKnativeKeysManager;
struct nativeChannelManagerOpaque;
typedef struct nativeChannelManagerOpaque LDKnativeChannelManager;
struct nativeChannelDetailsOpaque;
typedef struct nativeChannelDetailsOpaque LDKnativeChannelDetails;
struct nativePaymentSendFailureOpaque;
typedef struct nativePaymentSendFailureOpaque LDKnativePaymentSendFailure;
struct nativeChannelManagerReadArgsOpaque;
typedef struct nativeChannelManagerReadArgsOpaque LDKnativeChannelManagerReadArgs;
struct nativeChannelMonitorUpdateOpaque;
typedef struct nativeChannelMonitorUpdateOpaque LDKnativeChannelMonitorUpdate;
struct nativeMonitorUpdateErrorOpaque;
typedef struct nativeMonitorUpdateErrorOpaque LDKnativeMonitorUpdateError;
struct nativeMonitorEventOpaque;
typedef struct nativeMonitorEventOpaque LDKnativeMonitorEvent;
struct nativeHTLCUpdateOpaque;
typedef struct nativeHTLCUpdateOpaque LDKnativeHTLCUpdate;
struct nativeChannelMonitorOpaque;
typedef struct nativeChannelMonitorOpaque LDKnativeChannelMonitor;
struct nativeDecodeErrorOpaque;
typedef struct nativeDecodeErrorOpaque LDKnativeDecodeError;
struct nativeInitOpaque;
typedef struct nativeInitOpaque LDKnativeInit;
struct nativeErrorMessageOpaque;
typedef struct nativeErrorMessageOpaque LDKnativeErrorMessage;
struct nativePingOpaque;
typedef struct nativePingOpaque LDKnativePing;
struct nativePongOpaque;
typedef struct nativePongOpaque LDKnativePong;
struct nativeOpenChannelOpaque;
typedef struct nativeOpenChannelOpaque LDKnativeOpenChannel;
struct nativeAcceptChannelOpaque;
typedef struct nativeAcceptChannelOpaque LDKnativeAcceptChannel;
struct nativeFundingCreatedOpaque;
typedef struct nativeFundingCreatedOpaque LDKnativeFundingCreated;
struct nativeFundingSignedOpaque;
typedef struct nativeFundingSignedOpaque LDKnativeFundingSigned;
struct nativeFundingLockedOpaque;
typedef struct nativeFundingLockedOpaque LDKnativeFundingLocked;
struct nativeShutdownOpaque;
typedef struct nativeShutdownOpaque LDKnativeShutdown;
struct nativeClosingSignedOpaque;
typedef struct nativeClosingSignedOpaque LDKnativeClosingSigned;
struct nativeUpdateAddHTLCOpaque;
typedef struct nativeUpdateAddHTLCOpaque LDKnativeUpdateAddHTLC;
struct nativeUpdateFulfillHTLCOpaque;
typedef struct nativeUpdateFulfillHTLCOpaque LDKnativeUpdateFulfillHTLC;
struct nativeUpdateFailHTLCOpaque;
typedef struct nativeUpdateFailHTLCOpaque LDKnativeUpdateFailHTLC;
struct nativeUpdateFailMalformedHTLCOpaque;
typedef struct nativeUpdateFailMalformedHTLCOpaque LDKnativeUpdateFailMalformedHTLC;
struct nativeCommitmentSignedOpaque;
typedef struct nativeCommitmentSignedOpaque LDKnativeCommitmentSigned;
struct nativeRevokeAndACKOpaque;
typedef struct nativeRevokeAndACKOpaque LDKnativeRevokeAndACK;
struct nativeUpdateFeeOpaque;
typedef struct nativeUpdateFeeOpaque LDKnativeUpdateFee;
struct nativeDataLossProtectOpaque;
typedef struct nativeDataLossProtectOpaque LDKnativeDataLossProtect;
struct nativeChannelReestablishOpaque;
typedef struct nativeChannelReestablishOpaque LDKnativeChannelReestablish;
struct nativeAnnouncementSignaturesOpaque;
typedef struct nativeAnnouncementSignaturesOpaque LDKnativeAnnouncementSignatures;
struct nativeUnsignedNodeAnnouncementOpaque;
typedef struct nativeUnsignedNodeAnnouncementOpaque LDKnativeUnsignedNodeAnnouncement;
struct nativeNodeAnnouncementOpaque;
typedef struct nativeNodeAnnouncementOpaque LDKnativeNodeAnnouncement;
struct nativeUnsignedChannelAnnouncementOpaque;
typedef struct nativeUnsignedChannelAnnouncementOpaque LDKnativeUnsignedChannelAnnouncement;
struct nativeChannelAnnouncementOpaque;
typedef struct nativeChannelAnnouncementOpaque LDKnativeChannelAnnouncement;
struct nativeUnsignedChannelUpdateOpaque;
typedef struct nativeUnsignedChannelUpdateOpaque LDKnativeUnsignedChannelUpdate;
struct nativeChannelUpdateOpaque;
typedef struct nativeChannelUpdateOpaque LDKnativeChannelUpdate;
struct nativeLightningErrorOpaque;
typedef struct nativeLightningErrorOpaque LDKnativeLightningError;
struct nativeCommitmentUpdateOpaque;
typedef struct nativeCommitmentUpdateOpaque LDKnativeCommitmentUpdate;
struct nativeMessageHandlerOpaque;
typedef struct nativeMessageHandlerOpaque LDKnativeMessageHandler;
struct nativePeerHandleErrorOpaque;
typedef struct nativePeerHandleErrorOpaque LDKnativePeerHandleError;
struct nativePeerManagerOpaque;
typedef struct nativePeerManagerOpaque LDKnativePeerManager;
struct nativeTxCreationKeysOpaque;
typedef struct nativeTxCreationKeysOpaque LDKnativeTxCreationKeys;
struct nativePreCalculatedTxCreationKeysOpaque;
typedef struct nativePreCalculatedTxCreationKeysOpaque LDKnativePreCalculatedTxCreationKeys;
struct nativeChannelPublicKeysOpaque;
typedef struct nativeChannelPublicKeysOpaque LDKnativeChannelPublicKeys;
struct nativeHTLCOutputInCommitmentOpaque;
typedef struct nativeHTLCOutputInCommitmentOpaque LDKnativeHTLCOutputInCommitment;
struct nativeLocalCommitmentTransactionOpaque;
typedef struct nativeLocalCommitmentTransactionOpaque LDKnativeLocalCommitmentTransaction;
struct nativeInitFeaturesOpaque;
typedef struct nativeInitFeaturesOpaque LDKnativeInitFeatures;
struct nativeNodeFeaturesOpaque;
typedef struct nativeNodeFeaturesOpaque LDKnativeNodeFeatures;
struct nativeChannelFeaturesOpaque;
typedef struct nativeChannelFeaturesOpaque LDKnativeChannelFeatures;
struct nativeRouteHopOpaque;
typedef struct nativeRouteHopOpaque LDKnativeRouteHop;
struct nativeRouteOpaque;
typedef struct nativeRouteOpaque LDKnativeRoute;
struct nativeRouteHintOpaque;
typedef struct nativeRouteHintOpaque LDKnativeRouteHint;
struct nativeNetworkGraphOpaque;
typedef struct nativeNetworkGraphOpaque LDKnativeNetworkGraph;
struct nativeLockedNetworkGraphOpaque;
typedef struct nativeLockedNetworkGraphOpaque LDKnativeLockedNetworkGraph;
struct nativeNetGraphMsgHandlerOpaque;
typedef struct nativeNetGraphMsgHandlerOpaque LDKnativeNetGraphMsgHandler;
struct nativeDirectionalChannelInfoOpaque;
typedef struct nativeDirectionalChannelInfoOpaque LDKnativeDirectionalChannelInfo;
struct nativeChannelInfoOpaque;
typedef struct nativeChannelInfoOpaque LDKnativeChannelInfo;
struct nativeRoutingFeesOpaque;
typedef struct nativeRoutingFeesOpaque LDKnativeRoutingFees;
struct nativeNodeAnnouncementInfoOpaque;
typedef struct nativeNodeAnnouncementInfoOpaque LDKnativeNodeAnnouncementInfo;
struct nativeNodeInfoOpaque;
typedef struct nativeNodeInfoOpaque LDKnativeNodeInfo;

View file

@ -0,0 +1 @@
pub mod network;

View file

@ -0,0 +1,18 @@
use bitcoin::network::constants::Network as BitcoinNetwork;
#[repr(C)]
pub enum Network {
Bitcoin,
Testnet,
Regtest,
}
impl Network {
pub(crate) fn into_bitcoin(&self) -> BitcoinNetwork {
match self {
Network::Bitcoin => BitcoinNetwork::Bitcoin,
Network::Testnet => BitcoinNetwork::Testnet,
Network::Regtest => BitcoinNetwork::Regtest,
}
}
}

View file

@ -0,0 +1,405 @@
#[no_mangle]
pub type CVec_SpendableOutputDescriptorZ = crate::c_types::CVecTempl<crate::chain::keysinterface::SpendableOutputDescriptor>;
#[no_mangle]
pub static CVec_SpendableOutputDescriptorZ_free: extern "C" fn(CVec_SpendableOutputDescriptorZ) = crate::c_types::CVecTempl_free::<crate::chain::keysinterface::SpendableOutputDescriptor>;
#[no_mangle]
pub type CVec_MessageSendEventZ = crate::c_types::CVecTempl<crate::util::events::MessageSendEvent>;
#[no_mangle]
pub static CVec_MessageSendEventZ_free: extern "C" fn(CVec_MessageSendEventZ) = crate::c_types::CVecTempl_free::<crate::util::events::MessageSendEvent>;
#[no_mangle]
pub type CVec_EventZ = crate::c_types::CVecTempl<crate::util::events::Event>;
#[no_mangle]
pub static CVec_EventZ_free: extern "C" fn(CVec_EventZ) = crate::c_types::CVecTempl_free::<crate::util::events::Event>;
#[no_mangle]
pub type C2Tuple_Txidu32Z = crate::c_types::C2TupleTempl<crate::c_types::ThirtyTwoBytes, u32>;
#[no_mangle]
pub static C2Tuple_Txidu32Z_free: extern "C" fn(C2Tuple_Txidu32Z) = crate::c_types::C2TupleTempl_free::<crate::c_types::ThirtyTwoBytes, u32>;
#[no_mangle]
pub extern "C" fn C2Tuple_Txidu32Z_new(a: crate::c_types::ThirtyTwoBytes, b: u32) -> C2Tuple_Txidu32Z {
C2Tuple_Txidu32Z {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
}
}
#[no_mangle]
pub type C2Tuple_Scriptu64Z = crate::c_types::C2TupleTempl<crate::c_types::derived::CVec_u8Z, u64>;
#[no_mangle]
pub static C2Tuple_Scriptu64Z_free: extern "C" fn(C2Tuple_Scriptu64Z) = crate::c_types::C2TupleTempl_free::<crate::c_types::derived::CVec_u8Z, u64>;
#[no_mangle]
pub extern "C" fn C2Tuple_Scriptu64Z_new(a: crate::c_types::derived::CVec_u8Z, b: u64) -> C2Tuple_Scriptu64Z {
C2Tuple_Scriptu64Z {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
}
}
#[no_mangle]
pub type CResult_C2Tuple_Scriptu64ZChainErrorZ = crate::c_types::CResultTempl<crate::c_types::C2TupleTempl<crate::c_types::derived::CVec_u8Z, u64>, crate::chain::chaininterface::ChainError>;
#[no_mangle]
pub static CResult_C2Tuple_Scriptu64ZChainErrorZ_free: extern "C" fn(CResult_C2Tuple_Scriptu64ZChainErrorZ) = crate::c_types::CResultTempl_free::<crate::c_types::C2TupleTempl<crate::c_types::derived::CVec_u8Z, u64>, crate::chain::chaininterface::ChainError>;
#[no_mangle]
pub static CResult_C2Tuple_Scriptu64ZChainErrorZ_ok: extern "C" fn (C2Tuple_Scriptu64Z) -> CResult_C2Tuple_Scriptu64ZChainErrorZ =
crate::c_types::CResultTempl::<crate::c_types::C2TupleTempl<crate::c_types::derived::CVec_u8Z, u64>, crate::chain::chaininterface::ChainError>::ok;
#[no_mangle]
pub static CResult_C2Tuple_Scriptu64ZChainErrorZ_err: extern "C" fn (crate::chain::chaininterface::ChainError) -> CResult_C2Tuple_Scriptu64ZChainErrorZ =
crate::c_types::CResultTempl::<crate::c_types::C2TupleTempl<crate::c_types::derived::CVec_u8Z, u64>, crate::chain::chaininterface::ChainError>::err;
#[no_mangle]
pub type CVec_usizeZ = crate::c_types::CVecTempl<usize>;
#[no_mangle]
pub static CVec_usizeZ_free: extern "C" fn(CVec_usizeZ) = crate::c_types::CVecTempl_free::<usize>;
#[no_mangle]
pub type CVec_TransactionZ = crate::c_types::CVecTempl<crate::c_types::derived::CVec_u8Z>;
#[no_mangle]
pub static CVec_TransactionZ_free: extern "C" fn(CVec_TransactionZ) = crate::c_types::CVecTempl_free::<crate::c_types::derived::CVec_u8Z>;
#[no_mangle]
pub type C2Tuple_u64u64Z = crate::c_types::C2TupleTempl<u64, u64>;
#[no_mangle]
pub static C2Tuple_u64u64Z_free: extern "C" fn(C2Tuple_u64u64Z) = crate::c_types::C2TupleTempl_free::<u64, u64>;
#[no_mangle]
pub extern "C" fn C2Tuple_u64u64Z_new(a: u64, b: u64) -> C2Tuple_u64u64Z {
C2Tuple_u64u64Z {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
}
}
#[no_mangle]
pub type CVec_HTLCOutputInCommitmentZ = crate::c_types::CVecTempl<crate::ln::chan_utils::HTLCOutputInCommitment>;
#[no_mangle]
pub static CVec_HTLCOutputInCommitmentZ_free: extern "C" fn(CVec_HTLCOutputInCommitmentZ) = crate::c_types::CVecTempl_free::<crate::ln::chan_utils::HTLCOutputInCommitment>;
#[no_mangle]
pub type CVec_SignatureZ = crate::c_types::CVecTempl<crate::c_types::Signature>;
#[no_mangle]
pub static CVec_SignatureZ_free: extern "C" fn(CVec_SignatureZ) = crate::c_types::CVecTempl_free::<crate::c_types::Signature>;
#[no_mangle]
pub type C2Tuple_SignatureCVec_SignatureZZ = crate::c_types::C2TupleTempl<crate::c_types::Signature, crate::c_types::CVecTempl<crate::c_types::Signature>>;
#[no_mangle]
pub static C2Tuple_SignatureCVec_SignatureZZ_free: extern "C" fn(C2Tuple_SignatureCVec_SignatureZZ) = crate::c_types::C2TupleTempl_free::<crate::c_types::Signature, crate::c_types::CVecTempl<crate::c_types::Signature>>;
#[no_mangle]
pub extern "C" fn C2Tuple_SignatureCVec_SignatureZZ_new(a: crate::c_types::Signature, b: crate::c_types::derived::CVec_SignatureZ) -> C2Tuple_SignatureCVec_SignatureZZ {
C2Tuple_SignatureCVec_SignatureZZ {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
}
}
#[no_mangle]
pub type CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ = crate::c_types::CResultTempl<crate::c_types::C2TupleTempl<crate::c_types::Signature, crate::c_types::CVecTempl<crate::c_types::Signature>>, u8>;
#[no_mangle]
pub static CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ_free: extern "C" fn(CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ) = crate::c_types::CResultTempl_free::<crate::c_types::C2TupleTempl<crate::c_types::Signature, crate::c_types::CVecTempl<crate::c_types::Signature>>, u8>;
#[no_mangle]
pub static CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ_ok: extern "C" fn (C2Tuple_SignatureCVec_SignatureZZ) -> CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ =
crate::c_types::CResultTempl::<crate::c_types::C2TupleTempl<crate::c_types::Signature, crate::c_types::CVecTempl<crate::c_types::Signature>>, u8>::ok;
#[no_mangle]
pub extern "C" fn CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ_err() -> CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ {
crate::c_types::CResultTempl::err(0)
}
#[no_mangle]
pub type CResult_SignatureNoneZ = crate::c_types::CResultTempl<crate::c_types::Signature, u8>;
#[no_mangle]
pub static CResult_SignatureNoneZ_free: extern "C" fn(CResult_SignatureNoneZ) = crate::c_types::CResultTempl_free::<crate::c_types::Signature, u8>;
#[no_mangle]
pub static CResult_SignatureNoneZ_ok: extern "C" fn (crate::c_types::Signature) -> CResult_SignatureNoneZ =
crate::c_types::CResultTempl::<crate::c_types::Signature, u8>::ok;
#[no_mangle]
pub extern "C" fn CResult_SignatureNoneZ_err() -> CResult_SignatureNoneZ {
crate::c_types::CResultTempl::err(0)
}
#[no_mangle]
pub type CResult_CVec_SignatureZNoneZ = crate::c_types::CResultTempl<crate::c_types::CVecTempl<crate::c_types::Signature>, u8>;
#[no_mangle]
pub static CResult_CVec_SignatureZNoneZ_free: extern "C" fn(CResult_CVec_SignatureZNoneZ) = crate::c_types::CResultTempl_free::<crate::c_types::CVecTempl<crate::c_types::Signature>, u8>;
#[no_mangle]
pub static CResult_CVec_SignatureZNoneZ_ok: extern "C" fn (CVec_SignatureZ) -> CResult_CVec_SignatureZNoneZ =
crate::c_types::CResultTempl::<crate::c_types::CVecTempl<crate::c_types::Signature>, u8>::ok;
#[no_mangle]
pub extern "C" fn CResult_CVec_SignatureZNoneZ_err() -> CResult_CVec_SignatureZNoneZ {
crate::c_types::CResultTempl::err(0)
}
#[no_mangle]
pub type CResult_NoneAPIErrorZ = crate::c_types::CResultTempl<u8, crate::util::errors::APIError>;
#[no_mangle]
pub static CResult_NoneAPIErrorZ_free: extern "C" fn(CResult_NoneAPIErrorZ) = crate::c_types::CResultTempl_free::<u8, crate::util::errors::APIError>;
#[no_mangle]
pub extern "C" fn CResult_NoneAPIErrorZ_ok() -> CResult_NoneAPIErrorZ {
crate::c_types::CResultTempl::ok(0)
}
#[no_mangle]
pub static CResult_NoneAPIErrorZ_err: extern "C" fn (crate::util::errors::APIError) -> CResult_NoneAPIErrorZ =
crate::c_types::CResultTempl::<u8, crate::util::errors::APIError>::err;
#[no_mangle]
pub type CVec_ChannelDetailsZ = crate::c_types::CVecTempl<crate::ln::channelmanager::ChannelDetails>;
#[no_mangle]
pub static CVec_ChannelDetailsZ_free: extern "C" fn(CVec_ChannelDetailsZ) = crate::c_types::CVecTempl_free::<crate::ln::channelmanager::ChannelDetails>;
#[no_mangle]
pub type CResult_NonePaymentSendFailureZ = crate::c_types::CResultTempl<u8, crate::ln::channelmanager::PaymentSendFailure>;
#[no_mangle]
pub static CResult_NonePaymentSendFailureZ_free: extern "C" fn(CResult_NonePaymentSendFailureZ) = crate::c_types::CResultTempl_free::<u8, crate::ln::channelmanager::PaymentSendFailure>;
#[no_mangle]
pub extern "C" fn CResult_NonePaymentSendFailureZ_ok() -> CResult_NonePaymentSendFailureZ {
crate::c_types::CResultTempl::ok(0)
}
#[no_mangle]
pub static CResult_NonePaymentSendFailureZ_err: extern "C" fn (crate::ln::channelmanager::PaymentSendFailure) -> CResult_NonePaymentSendFailureZ =
crate::c_types::CResultTempl::<u8, crate::ln::channelmanager::PaymentSendFailure>::err;
#[no_mangle]
pub type CVec_NetAddressZ = crate::c_types::CVecTempl<crate::ln::msgs::NetAddress>;
#[no_mangle]
pub static CVec_NetAddressZ_free: extern "C" fn(CVec_NetAddressZ) = crate::c_types::CVecTempl_free::<crate::ln::msgs::NetAddress>;
#[no_mangle]
pub type CVec_ChannelMonitorZ = crate::c_types::CVecTempl<crate::ln::channelmonitor::ChannelMonitor>;
#[no_mangle]
pub static CVec_ChannelMonitorZ_free: extern "C" fn(CVec_ChannelMonitorZ) = crate::c_types::CVecTempl_free::<crate::ln::channelmonitor::ChannelMonitor>;
#[no_mangle]
pub type CResult_NoneChannelMonitorUpdateErrZ = crate::c_types::CResultTempl<u8, crate::ln::channelmonitor::ChannelMonitorUpdateErr>;
#[no_mangle]
pub static CResult_NoneChannelMonitorUpdateErrZ_free: extern "C" fn(CResult_NoneChannelMonitorUpdateErrZ) = crate::c_types::CResultTempl_free::<u8, crate::ln::channelmonitor::ChannelMonitorUpdateErr>;
#[no_mangle]
pub extern "C" fn CResult_NoneChannelMonitorUpdateErrZ_ok() -> CResult_NoneChannelMonitorUpdateErrZ {
crate::c_types::CResultTempl::ok(0)
}
#[no_mangle]
pub static CResult_NoneChannelMonitorUpdateErrZ_err: extern "C" fn (crate::ln::channelmonitor::ChannelMonitorUpdateErr) -> CResult_NoneChannelMonitorUpdateErrZ =
crate::c_types::CResultTempl::<u8, crate::ln::channelmonitor::ChannelMonitorUpdateErr>::err;
#[no_mangle]
pub type CVec_MonitorEventZ = crate::c_types::CVecTempl<crate::ln::channelmonitor::MonitorEvent>;
#[no_mangle]
pub static CVec_MonitorEventZ_free: extern "C" fn(CVec_MonitorEventZ) = crate::c_types::CVecTempl_free::<crate::ln::channelmonitor::MonitorEvent>;
#[no_mangle]
pub type CResult_NoneMonitorUpdateErrorZ = crate::c_types::CResultTempl<u8, crate::ln::channelmonitor::MonitorUpdateError>;
#[no_mangle]
pub static CResult_NoneMonitorUpdateErrorZ_free: extern "C" fn(CResult_NoneMonitorUpdateErrorZ) = crate::c_types::CResultTempl_free::<u8, crate::ln::channelmonitor::MonitorUpdateError>;
#[no_mangle]
pub extern "C" fn CResult_NoneMonitorUpdateErrorZ_ok() -> CResult_NoneMonitorUpdateErrorZ {
crate::c_types::CResultTempl::ok(0)
}
#[no_mangle]
pub static CResult_NoneMonitorUpdateErrorZ_err: extern "C" fn (crate::ln::channelmonitor::MonitorUpdateError) -> CResult_NoneMonitorUpdateErrorZ =
crate::c_types::CResultTempl::<u8, crate::ln::channelmonitor::MonitorUpdateError>::err;
#[no_mangle]
pub type C2Tuple_OutPointScriptZ = crate::c_types::C2TupleTempl<crate::chain::transaction::OutPoint, crate::c_types::derived::CVec_u8Z>;
#[no_mangle]
pub static C2Tuple_OutPointScriptZ_free: extern "C" fn(C2Tuple_OutPointScriptZ) = crate::c_types::C2TupleTempl_free::<crate::chain::transaction::OutPoint, crate::c_types::derived::CVec_u8Z>;
#[no_mangle]
pub extern "C" fn C2Tuple_OutPointScriptZ_new(a: crate::chain::transaction::OutPoint, b: crate::c_types::derived::CVec_u8Z) -> C2Tuple_OutPointScriptZ {
C2Tuple_OutPointScriptZ {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
}
}
#[no_mangle]
pub type CVec_UpdateAddHTLCZ = crate::c_types::CVecTempl<crate::ln::msgs::UpdateAddHTLC>;
#[no_mangle]
pub static CVec_UpdateAddHTLCZ_free: extern "C" fn(CVec_UpdateAddHTLCZ) = crate::c_types::CVecTempl_free::<crate::ln::msgs::UpdateAddHTLC>;
#[no_mangle]
pub type CVec_UpdateFulfillHTLCZ = crate::c_types::CVecTempl<crate::ln::msgs::UpdateFulfillHTLC>;
#[no_mangle]
pub static CVec_UpdateFulfillHTLCZ_free: extern "C" fn(CVec_UpdateFulfillHTLCZ) = crate::c_types::CVecTempl_free::<crate::ln::msgs::UpdateFulfillHTLC>;
#[no_mangle]
pub type CVec_UpdateFailHTLCZ = crate::c_types::CVecTempl<crate::ln::msgs::UpdateFailHTLC>;
#[no_mangle]
pub static CVec_UpdateFailHTLCZ_free: extern "C" fn(CVec_UpdateFailHTLCZ) = crate::c_types::CVecTempl_free::<crate::ln::msgs::UpdateFailHTLC>;
#[no_mangle]
pub type CVec_UpdateFailMalformedHTLCZ = crate::c_types::CVecTempl<crate::ln::msgs::UpdateFailMalformedHTLC>;
#[no_mangle]
pub static CVec_UpdateFailMalformedHTLCZ_free: extern "C" fn(CVec_UpdateFailMalformedHTLCZ) = crate::c_types::CVecTempl_free::<crate::ln::msgs::UpdateFailMalformedHTLC>;
#[no_mangle]
pub type CResult_boolLightningErrorZ = crate::c_types::CResultTempl<bool, crate::ln::msgs::LightningError>;
#[no_mangle]
pub static CResult_boolLightningErrorZ_free: extern "C" fn(CResult_boolLightningErrorZ) = crate::c_types::CResultTempl_free::<bool, crate::ln::msgs::LightningError>;
#[no_mangle]
pub static CResult_boolLightningErrorZ_ok: extern "C" fn (bool) -> CResult_boolLightningErrorZ =
crate::c_types::CResultTempl::<bool, crate::ln::msgs::LightningError>::ok;
#[no_mangle]
pub static CResult_boolLightningErrorZ_err: extern "C" fn (crate::ln::msgs::LightningError) -> CResult_boolLightningErrorZ =
crate::c_types::CResultTempl::<bool, crate::ln::msgs::LightningError>::err;
#[no_mangle]
pub type C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ = crate::c_types::C3TupleTempl<crate::ln::msgs::ChannelAnnouncement, crate::ln::msgs::ChannelUpdate, crate::ln::msgs::ChannelUpdate>;
#[no_mangle]
pub static C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ_free: extern "C" fn(C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ) = crate::c_types::C3TupleTempl_free::<crate::ln::msgs::ChannelAnnouncement, crate::ln::msgs::ChannelUpdate, crate::ln::msgs::ChannelUpdate>;
#[no_mangle]
pub extern "C" fn C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ_new(a: crate::ln::msgs::ChannelAnnouncement, b: crate::ln::msgs::ChannelUpdate, c: crate::ln::msgs::ChannelUpdate) -> C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ {
C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
c: Box::into_raw(Box::new(c)),
}
}
#[no_mangle]
pub type CVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ = crate::c_types::CVecTempl<crate::c_types::C3TupleTempl<crate::ln::msgs::ChannelAnnouncement, crate::ln::msgs::ChannelUpdate, crate::ln::msgs::ChannelUpdate>>;
#[no_mangle]
pub static CVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ_free: extern "C" fn(CVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ) = crate::c_types::CVecTempl_free::<crate::c_types::C3TupleTempl<crate::ln::msgs::ChannelAnnouncement, crate::ln::msgs::ChannelUpdate, crate::ln::msgs::ChannelUpdate>>;
#[no_mangle]
pub type CVec_NodeAnnouncementZ = crate::c_types::CVecTempl<crate::ln::msgs::NodeAnnouncement>;
#[no_mangle]
pub static CVec_NodeAnnouncementZ_free: extern "C" fn(CVec_NodeAnnouncementZ) = crate::c_types::CVecTempl_free::<crate::ln::msgs::NodeAnnouncement>;
#[no_mangle]
pub type CVec_PublicKeyZ = crate::c_types::CVecTempl<crate::c_types::PublicKey>;
#[no_mangle]
pub static CVec_PublicKeyZ_free: extern "C" fn(CVec_PublicKeyZ) = crate::c_types::CVecTempl_free::<crate::c_types::PublicKey>;
#[no_mangle]
pub type CVec_u8Z = crate::c_types::CVecTempl<u8>;
#[no_mangle]
pub static CVec_u8Z_free: extern "C" fn(CVec_u8Z) = crate::c_types::CVecTempl_free::<u8>;
#[no_mangle]
pub type CResult_CVec_u8ZPeerHandleErrorZ = crate::c_types::CResultTempl<crate::c_types::CVecTempl<u8>, crate::ln::peer_handler::PeerHandleError>;
#[no_mangle]
pub static CResult_CVec_u8ZPeerHandleErrorZ_free: extern "C" fn(CResult_CVec_u8ZPeerHandleErrorZ) = crate::c_types::CResultTempl_free::<crate::c_types::CVecTempl<u8>, crate::ln::peer_handler::PeerHandleError>;
#[no_mangle]
pub static CResult_CVec_u8ZPeerHandleErrorZ_ok: extern "C" fn (CVec_u8Z) -> CResult_CVec_u8ZPeerHandleErrorZ =
crate::c_types::CResultTempl::<crate::c_types::CVecTempl<u8>, crate::ln::peer_handler::PeerHandleError>::ok;
#[no_mangle]
pub static CResult_CVec_u8ZPeerHandleErrorZ_err: extern "C" fn (crate::ln::peer_handler::PeerHandleError) -> CResult_CVec_u8ZPeerHandleErrorZ =
crate::c_types::CResultTempl::<crate::c_types::CVecTempl<u8>, crate::ln::peer_handler::PeerHandleError>::err;
#[no_mangle]
pub type CResult_NonePeerHandleErrorZ = crate::c_types::CResultTempl<u8, crate::ln::peer_handler::PeerHandleError>;
#[no_mangle]
pub static CResult_NonePeerHandleErrorZ_free: extern "C" fn(CResult_NonePeerHandleErrorZ) = crate::c_types::CResultTempl_free::<u8, crate::ln::peer_handler::PeerHandleError>;
#[no_mangle]
pub extern "C" fn CResult_NonePeerHandleErrorZ_ok() -> CResult_NonePeerHandleErrorZ {
crate::c_types::CResultTempl::ok(0)
}
#[no_mangle]
pub static CResult_NonePeerHandleErrorZ_err: extern "C" fn (crate::ln::peer_handler::PeerHandleError) -> CResult_NonePeerHandleErrorZ =
crate::c_types::CResultTempl::<u8, crate::ln::peer_handler::PeerHandleError>::err;
#[no_mangle]
pub type CResult_boolPeerHandleErrorZ = crate::c_types::CResultTempl<bool, crate::ln::peer_handler::PeerHandleError>;
#[no_mangle]
pub static CResult_boolPeerHandleErrorZ_free: extern "C" fn(CResult_boolPeerHandleErrorZ) = crate::c_types::CResultTempl_free::<bool, crate::ln::peer_handler::PeerHandleError>;
#[no_mangle]
pub static CResult_boolPeerHandleErrorZ_ok: extern "C" fn (bool) -> CResult_boolPeerHandleErrorZ =
crate::c_types::CResultTempl::<bool, crate::ln::peer_handler::PeerHandleError>::ok;
#[no_mangle]
pub static CResult_boolPeerHandleErrorZ_err: extern "C" fn (crate::ln::peer_handler::PeerHandleError) -> CResult_boolPeerHandleErrorZ =
crate::c_types::CResultTempl::<bool, crate::ln::peer_handler::PeerHandleError>::err;
#[no_mangle]
pub type CResult_SecretKeySecpErrorZ = crate::c_types::CResultTempl<crate::c_types::SecretKey, crate::c_types::Secp256k1Error>;
#[no_mangle]
pub static CResult_SecretKeySecpErrorZ_free: extern "C" fn(CResult_SecretKeySecpErrorZ) = crate::c_types::CResultTempl_free::<crate::c_types::SecretKey, crate::c_types::Secp256k1Error>;
#[no_mangle]
pub static CResult_SecretKeySecpErrorZ_ok: extern "C" fn (crate::c_types::SecretKey) -> CResult_SecretKeySecpErrorZ =
crate::c_types::CResultTempl::<crate::c_types::SecretKey, crate::c_types::Secp256k1Error>::ok;
#[no_mangle]
pub static CResult_SecretKeySecpErrorZ_err: extern "C" fn (crate::c_types::Secp256k1Error) -> CResult_SecretKeySecpErrorZ =
crate::c_types::CResultTempl::<crate::c_types::SecretKey, crate::c_types::Secp256k1Error>::err;
#[no_mangle]
pub type CResult_PublicKeySecpErrorZ = crate::c_types::CResultTempl<crate::c_types::PublicKey, crate::c_types::Secp256k1Error>;
#[no_mangle]
pub static CResult_PublicKeySecpErrorZ_free: extern "C" fn(CResult_PublicKeySecpErrorZ) = crate::c_types::CResultTempl_free::<crate::c_types::PublicKey, crate::c_types::Secp256k1Error>;
#[no_mangle]
pub static CResult_PublicKeySecpErrorZ_ok: extern "C" fn (crate::c_types::PublicKey) -> CResult_PublicKeySecpErrorZ =
crate::c_types::CResultTempl::<crate::c_types::PublicKey, crate::c_types::Secp256k1Error>::ok;
#[no_mangle]
pub static CResult_PublicKeySecpErrorZ_err: extern "C" fn (crate::c_types::Secp256k1Error) -> CResult_PublicKeySecpErrorZ =
crate::c_types::CResultTempl::<crate::c_types::PublicKey, crate::c_types::Secp256k1Error>::err;
#[no_mangle]
pub type CResult_TxCreationKeysSecpErrorZ = crate::c_types::CResultTempl<crate::ln::chan_utils::TxCreationKeys, crate::c_types::Secp256k1Error>;
#[no_mangle]
pub static CResult_TxCreationKeysSecpErrorZ_free: extern "C" fn(CResult_TxCreationKeysSecpErrorZ) = crate::c_types::CResultTempl_free::<crate::ln::chan_utils::TxCreationKeys, crate::c_types::Secp256k1Error>;
#[no_mangle]
pub static CResult_TxCreationKeysSecpErrorZ_ok: extern "C" fn (crate::ln::chan_utils::TxCreationKeys) -> CResult_TxCreationKeysSecpErrorZ =
crate::c_types::CResultTempl::<crate::ln::chan_utils::TxCreationKeys, crate::c_types::Secp256k1Error>::ok;
#[no_mangle]
pub static CResult_TxCreationKeysSecpErrorZ_err: extern "C" fn (crate::c_types::Secp256k1Error) -> CResult_TxCreationKeysSecpErrorZ =
crate::c_types::CResultTempl::<crate::ln::chan_utils::TxCreationKeys, crate::c_types::Secp256k1Error>::err;
#[no_mangle]
pub type C2Tuple_HTLCOutputInCommitmentSignatureZ = crate::c_types::C2TupleTempl<crate::ln::chan_utils::HTLCOutputInCommitment, crate::c_types::Signature>;
#[no_mangle]
pub static C2Tuple_HTLCOutputInCommitmentSignatureZ_free: extern "C" fn(C2Tuple_HTLCOutputInCommitmentSignatureZ) = crate::c_types::C2TupleTempl_free::<crate::ln::chan_utils::HTLCOutputInCommitment, crate::c_types::Signature>;
#[no_mangle]
pub extern "C" fn C2Tuple_HTLCOutputInCommitmentSignatureZ_new(a: crate::ln::chan_utils::HTLCOutputInCommitment, b: crate::c_types::Signature) -> C2Tuple_HTLCOutputInCommitmentSignatureZ {
C2Tuple_HTLCOutputInCommitmentSignatureZ {
a: Box::into_raw(Box::new(a)),
b: Box::into_raw(Box::new(b)),
}
}
#[no_mangle]
pub type CVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ = crate::c_types::CVecTempl<crate::c_types::C2TupleTempl<crate::ln::chan_utils::HTLCOutputInCommitment, crate::c_types::Signature>>;
#[no_mangle]
pub static CVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ_free: extern "C" fn(CVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ) = crate::c_types::CVecTempl_free::<crate::c_types::C2TupleTempl<crate::ln::chan_utils::HTLCOutputInCommitment, crate::c_types::Signature>>;
#[no_mangle]
pub type CVec_RouteHopZ = crate::c_types::CVecTempl<crate::routing::router::RouteHop>;
#[no_mangle]
pub static CVec_RouteHopZ_free: extern "C" fn(CVec_RouteHopZ) = crate::c_types::CVecTempl_free::<crate::routing::router::RouteHop>;
#[no_mangle]
pub type CVec_CVec_RouteHopZZ = crate::c_types::CVecTempl<crate::c_types::CVecTempl<crate::routing::router::RouteHop>>;
#[no_mangle]
pub static CVec_CVec_RouteHopZZ_free: extern "C" fn(CVec_CVec_RouteHopZZ) = crate::c_types::CVecTempl_free::<crate::c_types::CVecTempl<crate::routing::router::RouteHop>>;
#[no_mangle]
pub type CVec_RouteHintZ = crate::c_types::CVecTempl<crate::routing::router::RouteHint>;
#[no_mangle]
pub static CVec_RouteHintZ_free: extern "C" fn(CVec_RouteHintZ) = crate::c_types::CVecTempl_free::<crate::routing::router::RouteHint>;
#[no_mangle]
pub type CResult_RouteLightningErrorZ = crate::c_types::CResultTempl<crate::routing::router::Route, crate::ln::msgs::LightningError>;
#[no_mangle]
pub static CResult_RouteLightningErrorZ_free: extern "C" fn(CResult_RouteLightningErrorZ) = crate::c_types::CResultTempl_free::<crate::routing::router::Route, crate::ln::msgs::LightningError>;
#[no_mangle]
pub static CResult_RouteLightningErrorZ_ok: extern "C" fn (crate::routing::router::Route) -> CResult_RouteLightningErrorZ =
crate::c_types::CResultTempl::<crate::routing::router::Route, crate::ln::msgs::LightningError>::ok;
#[no_mangle]
pub static CResult_RouteLightningErrorZ_err: extern "C" fn (crate::ln::msgs::LightningError) -> CResult_RouteLightningErrorZ =
crate::c_types::CResultTempl::<crate::routing::router::Route, crate::ln::msgs::LightningError>::err;
#[no_mangle]
pub type CVec_u64Z = crate::c_types::CVecTempl<u64>;
#[no_mangle]
pub static CVec_u64Z_free: extern "C" fn(CVec_u64Z) = crate::c_types::CVecTempl_free::<u64>;

View file

@ -0,0 +1,419 @@
pub mod derived;
use bitcoin::Script as BitcoinScript;
use bitcoin::Transaction as BitcoinTransaction;
use bitcoin::secp256k1::key::PublicKey as SecpPublicKey;
use bitcoin::secp256k1::key::SecretKey as SecpSecretKey;
use bitcoin::secp256k1::Signature as SecpSignature;
use bitcoin::secp256k1::Error as SecpError;
#[derive(Clone)]
#[repr(C)]
pub struct PublicKey {
pub compressed_form: [u8; 33],
}
impl PublicKey {
pub(crate) fn from_rust(pk: &SecpPublicKey) -> Self {
Self {
compressed_form: pk.serialize(),
}
}
pub(crate) fn into_rust(&self) -> SecpPublicKey {
SecpPublicKey::from_slice(&self.compressed_form).unwrap()
}
pub(crate) fn is_null(&self) -> bool { self.compressed_form[..] == [0; 33][..] }
pub(crate) fn null() -> Self { Self { compressed_form: [0; 33] } }
}
#[repr(C)]
pub struct SecretKey {
pub bytes: [u8; 32],
}
impl SecretKey {
// from_rust isn't implemented for a ref since we just return byte array refs directly
pub(crate) fn from_rust(sk: SecpSecretKey) -> Self {
let mut bytes = [0; 32];
bytes.copy_from_slice(&sk[..]);
Self { bytes }
}
pub(crate) fn into_rust(&self) -> SecpSecretKey {
SecpSecretKey::from_slice(&self.bytes).unwrap()
}
}
#[repr(C)]
pub struct Signature {
pub compact_form: [u8; 64],
}
impl Signature {
pub(crate) fn from_rust(pk: &SecpSignature) -> Self {
Self {
compact_form: pk.serialize_compact(),
}
}
pub(crate) fn into_rust(&self) -> SecpSignature {
SecpSignature::from_compact(&self.compact_form).unwrap()
}
pub(crate) fn is_null(&self) -> bool { self.compact_form[..] == [0; 64][..] }
pub(crate) fn null() -> Self { Self { compact_form: [0; 64] } }
}
#[repr(C)]
pub enum Secp256k1Error {
IncorrectSignature,
InvalidMessage,
InvalidPublicKey,
InvalidSignature,
InvalidSecretKey,
InvalidRecoveryId,
InvalidTweak,
NotEnoughMemory,
CallbackPanicked,
}
impl Secp256k1Error {
pub(crate) fn from_rust(err: SecpError) -> Self {
match err {
SecpError::IncorrectSignature => Secp256k1Error::IncorrectSignature,
SecpError::InvalidMessage => Secp256k1Error::InvalidMessage,
SecpError::InvalidPublicKey => Secp256k1Error::InvalidPublicKey,
SecpError::InvalidSignature => Secp256k1Error::InvalidSignature,
SecpError::InvalidSecretKey => Secp256k1Error::InvalidSecretKey,
SecpError::InvalidRecoveryId => Secp256k1Error::InvalidRecoveryId,
SecpError::InvalidTweak => Secp256k1Error::InvalidTweak,
SecpError::NotEnoughMemory => Secp256k1Error::NotEnoughMemory,
}
}
}
#[repr(C)]
/// A reference to a serialized transaction, in (pointer, length) form.
/// This type does *not* own its own memory, so access to it after, eg, the call in which it was
/// provided to you are invalid.
pub struct Transaction {
pub data: *const u8,
pub datalen: usize,
}
impl Transaction {
pub(crate) fn into_bitcoin(&self) -> BitcoinTransaction {
if self.datalen == 0 { panic!("0-length buffer can never represent a valid Transaction"); }
::bitcoin::consensus::encode::deserialize(unsafe { std::slice::from_raw_parts(self.data, self.datalen) }).unwrap()
}
pub(crate) fn from_slice(s: &[u8]) -> Self {
Self {
data: s.as_ptr(),
datalen: s.len(),
}
}
}
#[repr(C)]
#[derive(Clone)]
/// A transaction output including a scriptPubKey and value.
/// This type *does* own its own memory, so must be free'd appropriately.
pub struct TxOut {
pub script_pubkey: derived::CVec_u8Z,
pub value: u64,
}
impl TxOut {
pub(crate) fn into_rust(mut self) -> ::bitcoin::blockdata::transaction::TxOut {
::bitcoin::blockdata::transaction::TxOut {
script_pubkey: self.script_pubkey.into_rust().into(),
value: self.value,
}
}
pub(crate) fn from_rust(txout: ::bitcoin::blockdata::transaction::TxOut) -> Self {
Self {
script_pubkey: CVecTempl::from(txout.script_pubkey.into_bytes()),
value: txout.value
}
}
}
#[no_mangle]
pub extern "C" fn TxOut_free(_res: TxOut) { }
#[repr(C)]
pub struct u8slice {
pub data: *const u8,
pub datalen: usize
}
impl u8slice {
pub(crate) fn from_slice(s: &[u8]) -> Self {
Self {
data: s.as_ptr(),
datalen: s.len(),
}
}
pub(crate) fn to_slice(&self) -> &[u8] {
if self.datalen == 0 { return &[]; }
unsafe { std::slice::from_raw_parts(self.data, self.datalen) }
}
}
#[repr(C)]
pub struct usizeslice {
pub data: *const usize,
pub datalen: usize
}
impl usizeslice {
pub(crate) fn from_slice(s: &[usize]) -> Self {
Self {
data: s.as_ptr(),
datalen: s.len(),
}
}
pub(crate) fn to_slice(&self) -> &[usize] {
if self.datalen == 0 { return &[]; }
unsafe { std::slice::from_raw_parts(self.data, self.datalen) }
}
}
#[repr(C)]
#[derive(Copy, Clone)]
/// Arbitrary 32 bytes, which could represent one of a few different things. You probably want to
/// look up the corresponding function in rust-lightning's docs.
pub struct ThirtyTwoBytes {
pub data: [u8; 32],
}
impl ThirtyTwoBytes {
pub(crate) fn null() -> Self {
Self { data: [0; 32] }
}
}
#[repr(C)]
pub struct ThreeBytes { pub data: [u8; 3], }
#[derive(Clone)]
#[repr(C)]
pub struct FourBytes { pub data: [u8; 4], }
#[derive(Clone)]
#[repr(C)]
pub struct TenBytes { pub data: [u8; 10], }
#[derive(Clone)]
#[repr(C)]
pub struct SixteenBytes { pub data: [u8; 16], }
pub(crate) struct VecWriter(pub Vec<u8>);
impl lightning::util::ser::Writer for VecWriter {
fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
self.0.extend_from_slice(buf);
Ok(())
}
fn size_hint(&mut self, size: usize) {
self.0.reserve_exact(size);
}
}
pub(crate) fn serialize_obj<I: lightning::util::ser::Writeable>(i: &I) -> derived::CVec_u8Z {
let mut out = VecWriter(Vec::new());
i.write(&mut out).unwrap();
CVecTempl::from(out.0)
}
pub(crate) fn deserialize_obj<I: lightning::util::ser::Readable>(s: u8slice) -> Result<I, lightning::ln::msgs::DecodeError> {
I::read(&mut s.to_slice())
}
#[repr(C)]
#[derive(Copy, Clone)]
/// A Rust str object, ie a reference to a UTF8-valid string.
/// This is *not* null-terminated so cannot be used directly as a C string!
pub struct Str {
pub chars: *const u8,
pub len: usize
}
impl Into<Str> for &'static str {
fn into(self) -> Str {
Str { chars: self.as_ptr(), len: self.len() }
}
}
impl Into<&'static str> for Str {
fn into(self) -> &'static str {
if self.len == 0 { return ""; }
std::str::from_utf8(unsafe { std::slice::from_raw_parts(self.chars, self.len) }).unwrap()
}
}
// Note that the C++ headers memset(0) all the Templ types to avoid deallocation!
// Thus, they must gracefully handle being completely null in _free.
// TODO: Integer/bool primitives should avoid the pointer indirection for underlying types
// everywhere in the containers.
#[repr(C)]
pub union CResultPtr<O, E> {
pub result: *mut O,
pub err: *mut E,
}
#[repr(C)]
pub struct CResultTempl<O, E> {
pub contents: CResultPtr<O, E>,
pub result_ok: bool,
}
impl<O, E> CResultTempl<O, E> {
pub(crate) extern "C" fn ok(o: O) -> Self {
CResultTempl {
contents: CResultPtr {
result: Box::into_raw(Box::new(o)),
},
result_ok: true,
}
}
pub(crate) extern "C" fn err(e: E) -> Self {
CResultTempl {
contents: CResultPtr {
err: Box::into_raw(Box::new(e)),
},
result_ok: false,
}
}
}
pub extern "C" fn CResultTempl_free<O, E>(_res: CResultTempl<O, E>) { }
impl<O, E> Drop for CResultTempl<O, E> {
fn drop(&mut self) {
if self.result_ok {
if unsafe { !self.contents.result.is_null() } {
unsafe { Box::from_raw(self.contents.result) };
}
} else if unsafe { !self.contents.err.is_null() } {
unsafe { Box::from_raw(self.contents.err) };
}
}
}
#[repr(C)]
pub struct CVecTempl<T> {
pub data: *mut T,
pub datalen: usize
}
impl<T> CVecTempl<T> {
pub(crate) fn into_rust(&mut self) -> Vec<T> {
if self.datalen == 0 { return Vec::new(); }
let ret = unsafe { Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) }.into();
self.data = std::ptr::null_mut();
self.datalen = 0;
ret
}
pub(crate) fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts_mut(self.data, self.datalen) }
}
}
impl<T> From<Vec<T>> for CVecTempl<T> {
fn from(v: Vec<T>) -> Self {
let datalen = v.len();
let data = Box::into_raw(v.into_boxed_slice());
CVecTempl { datalen, data: unsafe { (*data).as_mut_ptr() } }
}
}
pub extern "C" fn CVecTempl_free<T>(_res: CVecTempl<T>) { }
impl<T> Drop for CVecTempl<T> {
fn drop(&mut self) {
if self.datalen == 0 { return; }
unsafe { Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.datalen)) };
}
}
impl<T: Clone> Clone for CVecTempl<T> {
fn clone(&self) -> Self {
let mut res = Vec::new();
if self.datalen == 0 { return Self::from(res); }
res.clone_from_slice(unsafe { std::slice::from_raw_parts_mut(self.data, self.datalen) });
Self::from(res)
}
}
#[repr(C)]
pub struct C2TupleTempl<A, B> {
pub a: *mut A,
pub b: *mut B,
}
impl<A, B> From<(A, B)> for C2TupleTempl<A, B> {
fn from(tup: (A, B)) -> Self {
Self {
a: Box::into_raw(Box::new(tup.0)),
b: Box::into_raw(Box::new(tup.1)),
}
}
}
impl<A, B> C2TupleTempl<A, B> {
pub(crate) fn to_rust(mut self) -> (A, B) {
let res = (unsafe { *Box::from_raw(self.a) }, unsafe { *Box::from_raw(self.b) });
self.a = std::ptr::null_mut();
self.b = std::ptr::null_mut();
res
}
}
pub extern "C" fn C2TupleTempl_free<A, B>(_res: C2TupleTempl<A, B>) { }
impl<A, B> Drop for C2TupleTempl<A, B> {
fn drop(&mut self) {
if !self.a.is_null() {
unsafe { Box::from_raw(self.a) };
}
if !self.b.is_null() {
unsafe { Box::from_raw(self.b) };
}
}
}
impl <A: Clone, B: Clone> Clone for C2TupleTempl<A, B> {
fn clone(&self) -> Self {
Self {
a: Box::into_raw(Box::new(unsafe { &*self.a }.clone())),
b: Box::into_raw(Box::new(unsafe { &*self.b }.clone()))
}
}
}
#[repr(C)]
pub struct C3TupleTempl<A, B, C> {
pub a: *mut A,
pub b: *mut B,
pub c: *mut C,
}
impl<A, B, C> From<(A, B, C)> for C3TupleTempl<A, B, C> {
fn from(tup: (A, B, C)) -> Self {
Self {
a: Box::into_raw(Box::new(tup.0)),
b: Box::into_raw(Box::new(tup.1)),
c: Box::into_raw(Box::new(tup.2)),
}
}
}
impl<A, B, C> C3TupleTempl<A, B, C> {
pub(crate) fn to_rust(mut self) -> (A, B, C) {
let res = (unsafe { *Box::from_raw(self.a) }, unsafe { *Box::from_raw(self.b) }, unsafe { *Box::from_raw(self.c) });
self.a = std::ptr::null_mut();
self.b = std::ptr::null_mut();
self.c = std::ptr::null_mut();
res
}
}
pub extern "C" fn C3TupleTempl_free<A, B, C>(_res: C3TupleTempl<A, B, C>) { }
impl<A, B, C> Drop for C3TupleTempl<A, B, C> {
fn drop(&mut self) {
if !self.a.is_null() {
unsafe { Box::from_raw(self.a) };
}
if !self.b.is_null() {
unsafe { Box::from_raw(self.b) };
}
if !self.c.is_null() {
unsafe { Box::from_raw(self.c) };
}
}
}
/// Utility to make it easy to set a pointer to null and get its original value in line.
pub(crate) trait TakePointer<T> {
fn take_ptr(&mut self) -> T;
}
impl<T> TakePointer<*const T> for *const T {
fn take_ptr(&mut self) -> *const T {
let ret = *self;
*self = std::ptr::null();
ret
}
}
impl<T> TakePointer<*mut T> for *mut T {
fn take_ptr(&mut self) -> *mut T {
let ret = *self;
*self = std::ptr::null_mut();
ret
}
}

View file

@ -0,0 +1,606 @@
//! Traits and utility impls which allow other parts of rust-lightning to interact with the
//! blockchain.
//!
//! Includes traits for monitoring and receiving notifications of new blocks and block
//! disconnections, transaction broadcasting, and feerate information requests.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
/// Used to give chain error details upstream
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum ChainError {
/// Client doesn't support UTXO lookup (but the chain hash matches our genesis block hash)
NotSupported,
/// Chain isn't the one watched
NotWatched,
/// Tx doesn't exist or is unconfirmed
UnknownTx,
}
use lightning::chain::chaininterface::ChainError as nativeChainError;
impl ChainError {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeChainError {
match self {
ChainError::NotSupported => nativeChainError::NotSupported,
ChainError::NotWatched => nativeChainError::NotWatched,
ChainError::UnknownTx => nativeChainError::UnknownTx,
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeChainError {
match self {
ChainError::NotSupported => nativeChainError::NotSupported,
ChainError::NotWatched => nativeChainError::NotWatched,
ChainError::UnknownTx => nativeChainError::UnknownTx,
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeChainError) -> Self {
match native {
nativeChainError::NotSupported => ChainError::NotSupported,
nativeChainError::NotWatched => ChainError::NotWatched,
nativeChainError::UnknownTx => ChainError::UnknownTx,
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeChainError) -> Self {
match native {
nativeChainError::NotSupported => ChainError::NotSupported,
nativeChainError::NotWatched => ChainError::NotWatched,
nativeChainError::UnknownTx => ChainError::UnknownTx,
}
}
}
/// An interface to request notification of certain scripts as they appear the
/// chain.
///
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
/// called from inside the library in response to ChainListener events, P2P events, or timer
/// events).
#[repr(C)]
pub struct ChainWatchInterface {
pub this_arg: *mut c_void,
/// Provides a txid/random-scriptPubKey-in-the-tx which much be watched for.
pub install_watch_tx: extern "C" fn (this_arg: *const c_void, txid: *const [u8; 32], script_pub_key: crate::c_types::u8slice),
/// Provides an outpoint which must be watched for, providing any transactions which spend the
/// given outpoint.
pub install_watch_outpoint: extern "C" fn (this_arg: *const c_void, outpoint: crate::c_types::derived::C2Tuple_Txidu32Z, out_script: crate::c_types::u8slice),
/// Indicates that a listener needs to see all transactions.
pub watch_all_txn: extern "C" fn (this_arg: *const c_void),
/// Gets the script and value in satoshis for a given unspent transaction output given a
/// short_channel_id (aka unspent_tx_output_identier). For BTC/tBTC channels the top three
/// bytes are the block height, the next 3 the transaction index within the block, and the
/// final two the output within the transaction.
#[must_use]
pub get_chain_utxo: extern "C" fn (this_arg: *const c_void, genesis_hash: crate::c_types::ThirtyTwoBytes, unspent_tx_output_identifier: u64) -> crate::c_types::derived::CResult_C2Tuple_Scriptu64ZChainErrorZ,
/// Gets the list of transaction indices within a given block that the ChainWatchInterface is
/// watching for.
#[must_use]
pub filter_block: extern "C" fn (this_arg: *const c_void, block: crate::c_types::u8slice) -> crate::c_types::derived::CVec_usizeZ,
/// Returns a usize that changes when the ChainWatchInterface's watched data is modified.
/// Users of `filter_block` should pre-save a copy of `reentered`'s return value and use it to
/// determine whether they need to re-filter a given block.
#[must_use]
pub reentered: extern "C" fn (this_arg: *const c_void) -> usize,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Sync for ChainWatchInterface {}
unsafe impl Send for ChainWatchInterface {}
use lightning::chain::chaininterface::ChainWatchInterface as rustChainWatchInterface;
impl rustChainWatchInterface for ChainWatchInterface {
fn install_watch_tx(&self, txid: &bitcoin::hash_types::Txid, script_pub_key: &bitcoin::blockdata::script::Script) {
(self.install_watch_tx)(self.this_arg, txid.as_inner(), crate::c_types::u8slice::from_slice(&script_pub_key[..]))
}
fn install_watch_outpoint(&self, outpoint: (bitcoin::hash_types::Txid, u32), out_script: &bitcoin::blockdata::script::Script) {
let (mut orig_outpoint_0, mut orig_outpoint_1) = outpoint; let mut local_outpoint = (crate::c_types::ThirtyTwoBytes { data: orig_outpoint_0.into_inner() }, orig_outpoint_1).into();
(self.install_watch_outpoint)(self.this_arg, local_outpoint, crate::c_types::u8slice::from_slice(&out_script[..]))
}
fn watch_all_txn(&self) {
(self.watch_all_txn)(self.this_arg)
}
fn get_chain_utxo(&self, genesis_hash: bitcoin::hash_types::BlockHash, unspent_tx_output_identifier: u64) -> Result<(bitcoin::blockdata::script::Script, u64), lightning::chain::chaininterface::ChainError> {
let mut ret = (self.get_chain_utxo)(self.this_arg, crate::c_types::ThirtyTwoBytes { data: genesis_hash.into_inner() }, unspent_tx_output_identifier);
let mut local_ret = match ret.result_ok { true => Ok( { let (mut orig_ret_0_0, mut orig_ret_0_1) = (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).to_rust(); let mut local_ret_0 = (::bitcoin::blockdata::script::Script::from(orig_ret_0_0.into_rust()), orig_ret_0_1); local_ret_0 }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })};
local_ret
}
fn filter_block(&self, block: &bitcoin::blockdata::block::Block) -> Vec<usize> {
let mut local_block = ::bitcoin::consensus::encode::serialize(block);
let mut ret = (self.filter_block)(self.this_arg, crate::c_types::u8slice::from_slice(&local_block));
let mut local_ret = Vec::new(); for mut item in ret.into_rust().drain(..) { local_ret.push( { item }); };
local_ret
}
fn reentered(&self) -> usize {
let mut ret = (self.reentered)(self.this_arg);
ret
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for ChainWatchInterface {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn ChainWatchInterface_free(this_ptr: ChainWatchInterface) { }
impl Drop for ChainWatchInterface {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
/// An interface to send a transaction to the Bitcoin network.
#[repr(C)]
pub struct BroadcasterInterface {
pub this_arg: *mut c_void,
/// Sends a transaction out to (hopefully) be mined.
pub broadcast_transaction: extern "C" fn (this_arg: *const c_void, tx: crate::c_types::Transaction),
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Sync for BroadcasterInterface {}
unsafe impl Send for BroadcasterInterface {}
use lightning::chain::chaininterface::BroadcasterInterface as rustBroadcasterInterface;
impl rustBroadcasterInterface for BroadcasterInterface {
fn broadcast_transaction(&self, tx: &bitcoin::blockdata::transaction::Transaction) {
let mut local_tx = ::bitcoin::consensus::encode::serialize(tx);
(self.broadcast_transaction)(self.this_arg, crate::c_types::Transaction::from_slice(&local_tx))
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for BroadcasterInterface {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn BroadcasterInterface_free(this_ptr: BroadcasterInterface) { }
impl Drop for BroadcasterInterface {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
/// A trait indicating a desire to listen for events from the chain
#[repr(C)]
pub struct ChainListener {
pub this_arg: *mut c_void,
/// Notifies a listener that a block was connected.
///
/// The txn_matched array should be set to references to transactions which matched the
/// relevant installed watch outpoints/txn, or the full set of transactions in the block.
///
/// Note that if txn_matched includes only matched transactions, and a new
/// transaction/outpoint is watched during a block_connected call, the block *must* be
/// re-scanned with the new transaction/outpoints and block_connected should be called
/// again with the same header and (at least) the new transactions.
///
/// Note that if non-new transaction/outpoints are be registered during a call, a second call
/// *must not* happen.
///
/// This also means those counting confirmations using block_connected callbacks should watch
/// for duplicate headers and not count them towards confirmations!
pub block_connected: extern "C" fn (this_arg: *const c_void, header: *const [u8; 80], height: u32, txn_matched: crate::c_types::derived::CVec_TransactionZ, indexes_of_txn_matched: crate::c_types::usizeslice),
/// Notifies a listener that a block was disconnected.
/// Unlike block_connected, this *must* never be called twice for the same disconnect event.
/// Height must be the one of the block which was disconnected (not new height of the best chain)
pub block_disconnected: extern "C" fn (this_arg: *const c_void, header: *const [u8; 80], disconnected_height: u32),
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Sync for ChainListener {}
unsafe impl Send for ChainListener {}
use lightning::chain::chaininterface::ChainListener as rustChainListener;
impl rustChainListener for ChainListener {
fn block_connected(&self, header: &bitcoin::blockdata::block::BlockHeader, height: u32, txn_matched: &[&bitcoin::blockdata::transaction::Transaction], indexes_of_txn_matched: &[usize]) {
let mut local_header = { let mut s = [0u8; 80]; s[..].copy_from_slice(&::bitcoin::consensus::encode::serialize(header)); s };
let mut local_txn_matched = Vec::new(); for item in txn_matched.iter() { local_txn_matched.push( { let mut local_txn_matched_0 = ::bitcoin::consensus::encode::serialize(&**item); local_txn_matched_0.into() }); };
let mut local_indexes_of_txn_matched = crate::c_types::usizeslice::from_slice(indexes_of_txn_matched);
(self.block_connected)(self.this_arg, &local_header, height, local_txn_matched.into(), local_indexes_of_txn_matched)
}
fn block_disconnected(&self, header: &bitcoin::blockdata::block::BlockHeader, disconnected_height: u32) {
let mut local_header = { let mut s = [0u8; 80]; s[..].copy_from_slice(&::bitcoin::consensus::encode::serialize(header)); s };
(self.block_disconnected)(self.this_arg, &local_header, disconnected_height)
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for ChainListener {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn ChainListener_free(this_ptr: ChainListener) { }
impl Drop for ChainListener {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
/// An enum that represents the speed at which we want a transaction to confirm used for feerate
/// estimation.
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum ConfirmationTarget {
/// We are happy with this transaction confirming slowly when feerate drops some.
Background,
/// We'd like this transaction to confirm without major delay, but 12-18 blocks is fine.
Normal,
/// We'd like this transaction to confirm in the next few blocks.
HighPriority,
}
use lightning::chain::chaininterface::ConfirmationTarget as nativeConfirmationTarget;
impl ConfirmationTarget {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeConfirmationTarget {
match self {
ConfirmationTarget::Background => nativeConfirmationTarget::Background,
ConfirmationTarget::Normal => nativeConfirmationTarget::Normal,
ConfirmationTarget::HighPriority => nativeConfirmationTarget::HighPriority,
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeConfirmationTarget {
match self {
ConfirmationTarget::Background => nativeConfirmationTarget::Background,
ConfirmationTarget::Normal => nativeConfirmationTarget::Normal,
ConfirmationTarget::HighPriority => nativeConfirmationTarget::HighPriority,
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeConfirmationTarget) -> Self {
match native {
nativeConfirmationTarget::Background => ConfirmationTarget::Background,
nativeConfirmationTarget::Normal => ConfirmationTarget::Normal,
nativeConfirmationTarget::HighPriority => ConfirmationTarget::HighPriority,
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeConfirmationTarget) -> Self {
match native {
nativeConfirmationTarget::Background => ConfirmationTarget::Background,
nativeConfirmationTarget::Normal => ConfirmationTarget::Normal,
nativeConfirmationTarget::HighPriority => ConfirmationTarget::HighPriority,
}
}
}
/// A trait which should be implemented to provide feerate information on a number of time
/// horizons.
///
/// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
/// called from inside the library in response to ChainListener events, P2P events, or timer
/// events).
#[repr(C)]
pub struct FeeEstimator {
pub this_arg: *mut c_void,
/// Gets estimated satoshis of fee required per 1000 Weight-Units.
///
/// Must be no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later round-downs
/// don't put us below 1 satoshi-per-byte).
///
/// This translates to:
/// * satoshis-per-byte * 250
/// * ceil(satoshis-per-kbyte / 4)
#[must_use]
pub get_est_sat_per_1000_weight: extern "C" fn (this_arg: *const c_void, confirmation_target: crate::chain::chaininterface::ConfirmationTarget) -> u32,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Sync for FeeEstimator {}
unsafe impl Send for FeeEstimator {}
use lightning::chain::chaininterface::FeeEstimator as rustFeeEstimator;
impl rustFeeEstimator for FeeEstimator {
fn get_est_sat_per_1000_weight(&self, confirmation_target: lightning::chain::chaininterface::ConfirmationTarget) -> u32 {
let mut ret = (self.get_est_sat_per_1000_weight)(self.this_arg, crate::chain::chaininterface::ConfirmationTarget::native_into(confirmation_target));
ret
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for FeeEstimator {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn FeeEstimator_free(this_ptr: FeeEstimator) { }
impl Drop for FeeEstimator {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
#[no_mangle]
pub static MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = lightning::chain::chaininterface::MIN_RELAY_FEE_SAT_PER_1000_WEIGHT;
use lightning::chain::chaininterface::ChainWatchedUtil as nativeChainWatchedUtilImport;
type nativeChainWatchedUtil = nativeChainWatchedUtilImport;
/// Utility for tracking registered txn/outpoints and checking for matches
#[must_use]
#[repr(C)]
pub struct ChainWatchedUtil {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChainWatchedUtil,
pub is_owned: bool,
}
impl Drop for ChainWatchedUtil {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChainWatchedUtil_free(this_ptr: ChainWatchedUtil) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChainWatchedUtil_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChainWatchedUtil); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChainWatchedUtil {
pub(crate) fn take_ptr(mut self) -> *mut nativeChainWatchedUtil {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Constructs an empty (watches nothing) ChainWatchedUtil
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchedUtil_new() -> ChainWatchedUtil {
let mut ret = lightning::chain::chaininterface::ChainWatchedUtil::new();
ChainWatchedUtil { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Registers a tx for monitoring, returning true if it was a new tx and false if we'd already
/// been watching for it.
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchedUtil_register_tx(this_arg: &mut ChainWatchedUtil, txid: *const [u8; 32], script_pub_key: crate::c_types::u8slice) -> bool {
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChainWatchedUtil)) }.register_tx(&::bitcoin::hash_types::Txid::from_slice(&unsafe { &*txid }[..]).unwrap(), &::bitcoin::blockdata::script::Script::from(Vec::from(script_pub_key.to_slice())));
ret
}
/// Registers an outpoint for monitoring, returning true if it was a new outpoint and false if
/// we'd already been watching for it
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchedUtil_register_outpoint(this_arg: &mut ChainWatchedUtil, mut outpoint: crate::c_types::derived::C2Tuple_Txidu32Z, _script_pub_key: crate::c_types::u8slice) -> bool {
let (mut orig_outpoint_0, mut orig_outpoint_1) = outpoint.to_rust(); let mut local_outpoint = (::bitcoin::hash_types::Txid::from_slice(&orig_outpoint_0.data[..]).unwrap(), orig_outpoint_1);
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChainWatchedUtil)) }.register_outpoint(local_outpoint, &::bitcoin::blockdata::script::Script::from(Vec::from(_script_pub_key.to_slice())));
ret
}
/// Sets us to match all transactions, returning true if this is a new setting and false if
/// we'd already been set to match everything.
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchedUtil_watch_all(this_arg: &mut ChainWatchedUtil) -> bool {
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChainWatchedUtil)) }.watch_all();
ret
}
/// Checks if a given transaction matches the current filter.
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchedUtil_does_match_tx(this_arg: &ChainWatchedUtil, tx: crate::c_types::Transaction) -> bool {
let mut ret = unsafe { &*this_arg.inner }.does_match_tx(&tx.into_bitcoin());
ret
}
use lightning::chain::chaininterface::BlockNotifier as nativeBlockNotifierImport;
type nativeBlockNotifier = nativeBlockNotifierImport<'static, crate::chain::chaininterface::ChainListener, crate::chain::chaininterface::ChainWatchInterface>;
/// Utility for notifying listeners about new blocks, and handling block rescans if new watch
/// data is registered.
///
/// Rather than using a plain BlockNotifier, it is preferable to use either a BlockNotifierArc
/// or a BlockNotifierRef for conciseness. See their documentation for more details, but essentially
/// you should default to using a BlockNotifierRef, and use a BlockNotifierArc instead when you
/// require ChainListeners with static lifetimes, such as when you're using lightning-net-tokio.
#[must_use]
#[repr(C)]
pub struct BlockNotifier {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeBlockNotifier,
pub is_owned: bool,
}
impl Drop for BlockNotifier {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn BlockNotifier_free(this_ptr: BlockNotifier) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn BlockNotifier_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeBlockNotifier); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl BlockNotifier {
pub(crate) fn take_ptr(mut self) -> *mut nativeBlockNotifier {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Constructs a new BlockNotifier without any listeners.
#[must_use]
#[no_mangle]
pub extern "C" fn BlockNotifier_new(mut chain_monitor: crate::chain::chaininterface::ChainWatchInterface) -> crate::chain::chaininterface::BlockNotifier {
let mut ret = lightning::chain::chaininterface::BlockNotifier::new(chain_monitor);
crate::chain::chaininterface::BlockNotifier { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Register the given listener to receive events.
#[no_mangle]
pub extern "C" fn BlockNotifier_register_listener(this_arg: &BlockNotifier, mut listener: crate::chain::chaininterface::ChainListener) {
unsafe { &*this_arg.inner }.register_listener(listener)
}
/// Notify listeners that a block was connected given a full, unfiltered block.
///
/// Handles re-scanning the block and calling block_connected again if listeners register new
/// watch data during the callbacks for you (see ChainListener::block_connected for more info).
#[no_mangle]
pub extern "C" fn BlockNotifier_block_connected(this_arg: &BlockNotifier, block: crate::c_types::u8slice, mut height: u32) {
unsafe { &*this_arg.inner }.block_connected(&::bitcoin::consensus::encode::deserialize(block.to_slice()).unwrap(), height)
}
/// Notify listeners that a block was connected, given pre-filtered list of transactions in the
/// block which matched the filter (probably using does_match_tx).
///
/// Returns true if notified listeners registered additional watch data (implying that the
/// block must be re-scanned and this function called again prior to further block_connected
/// calls, see ChainListener::block_connected for more info).
#[must_use]
#[no_mangle]
pub extern "C" fn BlockNotifier_block_connected_checked(this_arg: &BlockNotifier, header: *const [u8; 80], mut height: u32, mut txn_matched: crate::c_types::derived::CVec_TransactionZ, mut indexes_of_txn_matched: crate::c_types::usizeslice) -> bool {
let mut local_txn_matched = Vec::new(); for mut item in txn_matched.into_rust().drain(..) { local_txn_matched.push( { ::bitcoin::consensus::encode::deserialize(&item.into_rust()[..]).unwrap() }); };
let mut ret = unsafe { &*this_arg.inner }.block_connected_checked(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height, &local_txn_matched.iter().collect::<Vec<_>>()[..], indexes_of_txn_matched.to_slice());
ret
}
/// Notify listeners that a block was disconnected.
#[no_mangle]
pub extern "C" fn BlockNotifier_block_disconnected(this_arg: &BlockNotifier, header: *const [u8; 80], mut disconnected_height: u32) {
unsafe { &*this_arg.inner }.block_disconnected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), disconnected_height)
}
use lightning::chain::chaininterface::ChainWatchInterfaceUtil as nativeChainWatchInterfaceUtilImport;
type nativeChainWatchInterfaceUtil = nativeChainWatchInterfaceUtilImport;
/// Utility to capture some common parts of ChainWatchInterface implementors.
///
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
#[must_use]
#[repr(C)]
pub struct ChainWatchInterfaceUtil {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChainWatchInterfaceUtil,
pub is_owned: bool,
}
impl Drop for ChainWatchInterfaceUtil {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChainWatchInterfaceUtil_free(this_ptr: ChainWatchInterfaceUtil) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChainWatchInterfaceUtil_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChainWatchInterfaceUtil); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChainWatchInterfaceUtil {
pub(crate) fn take_ptr(mut self) -> *mut nativeChainWatchInterfaceUtil {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
#[no_mangle]
pub extern "C" fn ChainWatchInterfaceUtil_as_ChainWatchInterface(this_arg: *const ChainWatchInterfaceUtil) -> crate::chain::chaininterface::ChainWatchInterface {
crate::chain::chaininterface::ChainWatchInterface {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
install_watch_tx: ChainWatchInterfaceUtil_ChainWatchInterface_install_watch_tx,
install_watch_outpoint: ChainWatchInterfaceUtil_ChainWatchInterface_install_watch_outpoint,
watch_all_txn: ChainWatchInterfaceUtil_ChainWatchInterface_watch_all_txn,
get_chain_utxo: ChainWatchInterfaceUtil_ChainWatchInterface_get_chain_utxo,
filter_block: ChainWatchInterfaceUtil_ChainWatchInterface_filter_block,
reentered: ChainWatchInterfaceUtil_ChainWatchInterface_reentered,
}
}
use lightning::chain::chaininterface::ChainWatchInterface as ChainWatchInterfaceTraitImport;
extern "C" fn ChainWatchInterfaceUtil_ChainWatchInterface_install_watch_tx(this_arg: *const c_void, txid: *const [u8; 32], script_pub_key: crate::c_types::u8slice) {
unsafe { &mut *(this_arg as *mut nativeChainWatchInterfaceUtil) }.install_watch_tx(&::bitcoin::hash_types::Txid::from_slice(&unsafe { &*txid }[..]).unwrap(), &::bitcoin::blockdata::script::Script::from(Vec::from(script_pub_key.to_slice())))
}
extern "C" fn ChainWatchInterfaceUtil_ChainWatchInterface_install_watch_outpoint(this_arg: *const c_void, mut outpoint: crate::c_types::derived::C2Tuple_Txidu32Z, out_script: crate::c_types::u8slice) {
let (mut orig_outpoint_0, mut orig_outpoint_1) = outpoint.to_rust(); let mut local_outpoint = (::bitcoin::hash_types::Txid::from_slice(&orig_outpoint_0.data[..]).unwrap(), orig_outpoint_1);
unsafe { &mut *(this_arg as *mut nativeChainWatchInterfaceUtil) }.install_watch_outpoint(local_outpoint, &::bitcoin::blockdata::script::Script::from(Vec::from(out_script.to_slice())))
}
extern "C" fn ChainWatchInterfaceUtil_ChainWatchInterface_watch_all_txn(this_arg: *const c_void) {
unsafe { &mut *(this_arg as *mut nativeChainWatchInterfaceUtil) }.watch_all_txn()
}
#[must_use]
extern "C" fn ChainWatchInterfaceUtil_ChainWatchInterface_get_chain_utxo(this_arg: *const c_void, mut genesis_hash: crate::c_types::ThirtyTwoBytes, mut _unspent_tx_output_identifier: u64) -> crate::c_types::derived::CResult_C2Tuple_Scriptu64ZChainErrorZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainWatchInterfaceUtil) }.get_chain_utxo(::bitcoin::hash_types::BlockHash::from_slice(&genesis_hash.data[..]).unwrap(), _unspent_tx_output_identifier);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { let (mut orig_ret_0_0, mut orig_ret_0_1) = o; let mut local_ret_0 = (orig_ret_0_0.into_bytes().into(), orig_ret_0_1).into(); local_ret_0 }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::chain::chaininterface::ChainError::native_into(e) }) };
local_ret
}
#[must_use]
extern "C" fn ChainWatchInterfaceUtil_ChainWatchInterface_filter_block(this_arg: *const c_void, block: crate::c_types::u8slice) -> crate::c_types::derived::CVec_usizeZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainWatchInterfaceUtil) }.filter_block(&::bitcoin::consensus::encode::deserialize(block.to_slice()).unwrap());
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { item }); };
local_ret.into()
}
#[must_use]
extern "C" fn ChainWatchInterfaceUtil_ChainWatchInterface_reentered(this_arg: *const c_void) -> usize {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChainWatchInterfaceUtil) }.reentered();
ret
}
/// Creates a new ChainWatchInterfaceUtil for the given network
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchInterfaceUtil_new(mut network: crate::bitcoin::network::Network) -> crate::chain::chaininterface::ChainWatchInterfaceUtil {
let mut ret = lightning::chain::chaininterface::ChainWatchInterfaceUtil::new(network.into_bitcoin());
crate::chain::chaininterface::ChainWatchInterfaceUtil { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Checks if a given transaction matches the current filter.
#[must_use]
#[no_mangle]
pub extern "C" fn ChainWatchInterfaceUtil_does_match_tx(this_arg: &ChainWatchInterfaceUtil, tx: crate::c_types::Transaction) -> bool {
let mut ret = unsafe { &*this_arg.inner }.does_match_tx(&tx.into_bitcoin());
ret
}

View file

@ -0,0 +1,938 @@
//! keysinterface provides keys into rust-lightning and defines some useful enums which describe
//! spendable on-chain outputs which the user owns and is responsible for using just as any other
//! on-chain output which is theirs.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
/// When on-chain outputs are created by rust-lightning (which our counterparty is not able to
/// claim at any point in the future) an event is generated which you must track and be able to
/// spend on-chain. The information needed to do this is provided in this enum, including the
/// outpoint describing which txid and output index is available, the full output which exists at
/// that txid/index, and any keys or other information required to sign.
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum SpendableOutputDescriptor {
/// An output to a script which was provided via KeysInterface, thus you should already know
/// how to spend it. No keys are provided as rust-lightning was never given any keys - only the
/// script_pubkey as it appears in the output.
/// These may include outputs from a transaction punishing our counterparty or claiming an HTLC
/// on-chain using the payment preimage or after it has timed out.
StaticOutput {
outpoint: crate::chain::transaction::OutPoint,
output: crate::c_types::TxOut,
},
/// An output to a P2WSH script which can be spent with a single signature after a CSV delay.
///
/// The witness in the spending input should be:
/// <BIP 143 signature> <empty vector> (MINIMALIF standard rule) <provided witnessScript>
///
/// Note that the nSequence field in the spending input must be set to to_self_delay
/// (which means the transaction is not broadcastable until at least to_self_delay
/// blocks after the outpoint confirms).
///
/// These are generally the result of a \"revocable\" output to us, spendable only by us unless
/// it is an output from an old state which we broadcast (which should never happen).
///
/// To derive the delayed_payment key which is used to sign for this input, you must pass the
/// local delayed_payment_base_key (ie the private key which corresponds to the pubkey in
/// ChannelKeys::pubkeys().delayed_payment_basepoint) and the provided per_commitment_point to
/// chan_utils::derive_private_key. The public key can be generated without the secret key
/// using chan_utils::derive_public_key and only the delayed_payment_basepoint which appears in
/// ChannelKeys::pubkeys().
///
/// To derive the remote_revocation_pubkey provided here (which is used in the witness
/// script generation), you must pass the remote revocation_basepoint (which appears in the
/// call to ChannelKeys::on_accept) and the provided per_commitment point
/// to chan_utils::derive_public_revocation_key.
///
/// The witness script which is hashed and included in the output script_pubkey may be
/// regenerated by passing the revocation_pubkey (derived as above), our delayed_payment pubkey
/// (derived as above), and the to_self_delay contained here to
/// chan_utils::get_revokeable_redeemscript.
DynamicOutputP2WSH {
outpoint: crate::chain::transaction::OutPoint,
per_commitment_point: crate::c_types::PublicKey,
to_self_delay: u16,
output: crate::c_types::TxOut,
key_derivation_params: crate::c_types::derived::C2Tuple_u64u64Z,
remote_revocation_pubkey: crate::c_types::PublicKey,
},
/// An output to a P2WPKH, spendable exclusively by our payment key (ie the private key which
/// corresponds to the public key in ChannelKeys::pubkeys().payment_point).
/// The witness in the spending input, is, thus, simply:
/// <BIP 143 signature> <payment key>
///
/// These are generally the result of our counterparty having broadcast the current state,
/// allowing us to claim the non-HTLC-encumbered outputs immediately.
StaticOutputRemotePayment {
outpoint: crate::chain::transaction::OutPoint,
output: crate::c_types::TxOut,
key_derivation_params: crate::c_types::derived::C2Tuple_u64u64Z,
},
}
use lightning::chain::keysinterface::SpendableOutputDescriptor as nativeSpendableOutputDescriptor;
impl SpendableOutputDescriptor {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeSpendableOutputDescriptor {
match self {
SpendableOutputDescriptor::StaticOutput {ref outpoint, ref output, } => {
let mut outpoint_nonref = (*outpoint).clone();
let mut output_nonref = (*output).clone();
nativeSpendableOutputDescriptor::StaticOutput {
outpoint: *unsafe { Box::from_raw(outpoint_nonref.take_ptr()) },
output: output_nonref.into_rust(),
}
},
SpendableOutputDescriptor::DynamicOutputP2WSH {ref outpoint, ref per_commitment_point, ref to_self_delay, ref output, ref key_derivation_params, ref remote_revocation_pubkey, } => {
let mut outpoint_nonref = (*outpoint).clone();
let mut per_commitment_point_nonref = (*per_commitment_point).clone();
let mut to_self_delay_nonref = (*to_self_delay).clone();
let mut output_nonref = (*output).clone();
let mut key_derivation_params_nonref = (*key_derivation_params).clone();
let (mut orig_key_derivation_params_nonref_0, mut orig_key_derivation_params_nonref_1) = key_derivation_params_nonref.to_rust(); let mut local_key_derivation_params_nonref = (orig_key_derivation_params_nonref_0, orig_key_derivation_params_nonref_1);
let mut remote_revocation_pubkey_nonref = (*remote_revocation_pubkey).clone();
nativeSpendableOutputDescriptor::DynamicOutputP2WSH {
outpoint: *unsafe { Box::from_raw(outpoint_nonref.take_ptr()) },
per_commitment_point: per_commitment_point_nonref.into_rust(),
to_self_delay: to_self_delay_nonref,
output: output_nonref.into_rust(),
key_derivation_params: local_key_derivation_params_nonref,
remote_revocation_pubkey: remote_revocation_pubkey_nonref.into_rust(),
}
},
SpendableOutputDescriptor::StaticOutputRemotePayment {ref outpoint, ref output, ref key_derivation_params, } => {
let mut outpoint_nonref = (*outpoint).clone();
let mut output_nonref = (*output).clone();
let mut key_derivation_params_nonref = (*key_derivation_params).clone();
let (mut orig_key_derivation_params_nonref_0, mut orig_key_derivation_params_nonref_1) = key_derivation_params_nonref.to_rust(); let mut local_key_derivation_params_nonref = (orig_key_derivation_params_nonref_0, orig_key_derivation_params_nonref_1);
nativeSpendableOutputDescriptor::StaticOutputRemotePayment {
outpoint: *unsafe { Box::from_raw(outpoint_nonref.take_ptr()) },
output: output_nonref.into_rust(),
key_derivation_params: local_key_derivation_params_nonref,
}
},
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeSpendableOutputDescriptor {
match self {
SpendableOutputDescriptor::StaticOutput {mut outpoint, mut output, } => {
nativeSpendableOutputDescriptor::StaticOutput {
outpoint: *unsafe { Box::from_raw(outpoint.take_ptr()) },
output: output.into_rust(),
}
},
SpendableOutputDescriptor::DynamicOutputP2WSH {mut outpoint, mut per_commitment_point, mut to_self_delay, mut output, mut key_derivation_params, mut remote_revocation_pubkey, } => {
let (mut orig_key_derivation_params_0, mut orig_key_derivation_params_1) = key_derivation_params.to_rust(); let mut local_key_derivation_params = (orig_key_derivation_params_0, orig_key_derivation_params_1);
nativeSpendableOutputDescriptor::DynamicOutputP2WSH {
outpoint: *unsafe { Box::from_raw(outpoint.take_ptr()) },
per_commitment_point: per_commitment_point.into_rust(),
to_self_delay: to_self_delay,
output: output.into_rust(),
key_derivation_params: local_key_derivation_params,
remote_revocation_pubkey: remote_revocation_pubkey.into_rust(),
}
},
SpendableOutputDescriptor::StaticOutputRemotePayment {mut outpoint, mut output, mut key_derivation_params, } => {
let (mut orig_key_derivation_params_0, mut orig_key_derivation_params_1) = key_derivation_params.to_rust(); let mut local_key_derivation_params = (orig_key_derivation_params_0, orig_key_derivation_params_1);
nativeSpendableOutputDescriptor::StaticOutputRemotePayment {
outpoint: *unsafe { Box::from_raw(outpoint.take_ptr()) },
output: output.into_rust(),
key_derivation_params: local_key_derivation_params,
}
},
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeSpendableOutputDescriptor) -> Self {
match native {
nativeSpendableOutputDescriptor::StaticOutput {ref outpoint, ref output, } => {
let mut outpoint_nonref = (*outpoint).clone();
let mut output_nonref = (*output).clone();
SpendableOutputDescriptor::StaticOutput {
outpoint: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(outpoint_nonref)), is_owned: true },
output: crate::c_types::TxOut::from_rust(output_nonref),
}
},
nativeSpendableOutputDescriptor::DynamicOutputP2WSH {ref outpoint, ref per_commitment_point, ref to_self_delay, ref output, ref key_derivation_params, ref remote_revocation_pubkey, } => {
let mut outpoint_nonref = (*outpoint).clone();
let mut per_commitment_point_nonref = (*per_commitment_point).clone();
let mut to_self_delay_nonref = (*to_self_delay).clone();
let mut output_nonref = (*output).clone();
let mut key_derivation_params_nonref = (*key_derivation_params).clone();
let (mut orig_key_derivation_params_nonref_0, mut orig_key_derivation_params_nonref_1) = key_derivation_params_nonref; let mut local_key_derivation_params_nonref = (orig_key_derivation_params_nonref_0, orig_key_derivation_params_nonref_1).into();
let mut remote_revocation_pubkey_nonref = (*remote_revocation_pubkey).clone();
SpendableOutputDescriptor::DynamicOutputP2WSH {
outpoint: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(outpoint_nonref)), is_owned: true },
per_commitment_point: crate::c_types::PublicKey::from_rust(&per_commitment_point_nonref),
to_self_delay: to_self_delay_nonref,
output: crate::c_types::TxOut::from_rust(output_nonref),
key_derivation_params: local_key_derivation_params_nonref,
remote_revocation_pubkey: crate::c_types::PublicKey::from_rust(&remote_revocation_pubkey_nonref),
}
},
nativeSpendableOutputDescriptor::StaticOutputRemotePayment {ref outpoint, ref output, ref key_derivation_params, } => {
let mut outpoint_nonref = (*outpoint).clone();
let mut output_nonref = (*output).clone();
let mut key_derivation_params_nonref = (*key_derivation_params).clone();
let (mut orig_key_derivation_params_nonref_0, mut orig_key_derivation_params_nonref_1) = key_derivation_params_nonref; let mut local_key_derivation_params_nonref = (orig_key_derivation_params_nonref_0, orig_key_derivation_params_nonref_1).into();
SpendableOutputDescriptor::StaticOutputRemotePayment {
outpoint: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(outpoint_nonref)), is_owned: true },
output: crate::c_types::TxOut::from_rust(output_nonref),
key_derivation_params: local_key_derivation_params_nonref,
}
},
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeSpendableOutputDescriptor) -> Self {
match native {
nativeSpendableOutputDescriptor::StaticOutput {mut outpoint, mut output, } => {
SpendableOutputDescriptor::StaticOutput {
outpoint: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(outpoint)), is_owned: true },
output: crate::c_types::TxOut::from_rust(output),
}
},
nativeSpendableOutputDescriptor::DynamicOutputP2WSH {mut outpoint, mut per_commitment_point, mut to_self_delay, mut output, mut key_derivation_params, mut remote_revocation_pubkey, } => {
let (mut orig_key_derivation_params_0, mut orig_key_derivation_params_1) = key_derivation_params; let mut local_key_derivation_params = (orig_key_derivation_params_0, orig_key_derivation_params_1).into();
SpendableOutputDescriptor::DynamicOutputP2WSH {
outpoint: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(outpoint)), is_owned: true },
per_commitment_point: crate::c_types::PublicKey::from_rust(&per_commitment_point),
to_self_delay: to_self_delay,
output: crate::c_types::TxOut::from_rust(output),
key_derivation_params: local_key_derivation_params,
remote_revocation_pubkey: crate::c_types::PublicKey::from_rust(&remote_revocation_pubkey),
}
},
nativeSpendableOutputDescriptor::StaticOutputRemotePayment {mut outpoint, mut output, mut key_derivation_params, } => {
let (mut orig_key_derivation_params_0, mut orig_key_derivation_params_1) = key_derivation_params; let mut local_key_derivation_params = (orig_key_derivation_params_0, orig_key_derivation_params_1).into();
SpendableOutputDescriptor::StaticOutputRemotePayment {
outpoint: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(outpoint)), is_owned: true },
output: crate::c_types::TxOut::from_rust(output),
key_derivation_params: local_key_derivation_params,
}
},
}
}
}
#[no_mangle]
pub extern "C" fn SpendableOutputDescriptor_free(this_ptr: SpendableOutputDescriptor) { }
/// Set of lightning keys needed to operate a channel as described in BOLT 3.
///
/// Signing services could be implemented on a hardware wallet. In this case,
/// the current ChannelKeys would be a front-end on top of a communication
/// channel connected to your secure device and lightning key material wouldn't
/// reside on a hot server. Nevertheless, a this deployment would still need
/// to trust the ChannelManager to avoid loss of funds as this latest component
/// could ask to sign commitment transaction with HTLCs paying to attacker pubkeys.
///
/// A more secure iteration would be to use hashlock (or payment points) to pair
/// invoice/incoming HTLCs with outgoing HTLCs to implement a no-trust-ChannelManager
/// at the price of more state and computation on the hardware wallet side. In the future,
/// we are looking forward to design such interface.
///
/// In any case, ChannelMonitor or fallback watchtowers are always going to be trusted
/// to act, as liveness and breach reply correctness are always going to be hard requirements
/// of LN security model, orthogonal of key management issues.
///
/// If you're implementing a custom signer, you almost certainly want to implement
/// Readable/Writable to serialize out a unique reference to this set of keys so
/// that you can serialize the full ChannelManager object.
///
#[repr(C)]
pub struct ChannelKeys {
pub this_arg: *mut c_void,
/// Gets the per-commitment point for a specific commitment number
///
/// Note that the commitment number starts at (1 << 48) - 1 and counts backwards.
#[must_use]
pub get_per_commitment_point: extern "C" fn (this_arg: *const c_void, idx: u64) -> crate::c_types::PublicKey,
/// Gets the commitment secret for a specific commitment number as part of the revocation process
///
/// An external signer implementation should error here if the commitment was already signed
/// and should refuse to sign it in the future.
///
/// May be called more than once for the same index.
///
/// Note that the commitment number starts at (1 << 48) - 1 and counts backwards.
/// TODO: return a Result so we can signal a validation error
#[must_use]
pub release_commitment_secret: extern "C" fn (this_arg: *const c_void, idx: u64) -> crate::c_types::ThirtyTwoBytes,
/// Gets the local channel public keys and basepoints
pub pubkeys: crate::ln::chan_utils::ChannelPublicKeys,
/// Fill in the pubkeys field as a reference to it will be given to Rust after this returns
/// Note that this takes a pointer to this object, not the this_ptr like other methods do
/// This function pointer may be NULL if pubkeys is filled in when this object is created and never needs updating.
pub set_pubkeys: Option<extern "C" fn(&ChannelKeys)>,
/// Gets arbitrary identifiers describing the set of keys which are provided back to you in
/// some SpendableOutputDescriptor types. These should be sufficient to identify this
/// ChannelKeys object uniquely and lookup or re-derive its keys.
#[must_use]
pub key_derivation_params: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::C2Tuple_u64u64Z,
/// Create a signature for a remote commitment transaction and associated HTLC transactions.
///
/// Note that if signing fails or is rejected, the channel will be force-closed.
#[must_use]
pub sign_remote_commitment: extern "C" fn (this_arg: *const c_void, feerate_per_kw: u32, commitment_tx: crate::c_types::Transaction, keys: &crate::ln::chan_utils::PreCalculatedTxCreationKeys, htlcs: crate::c_types::derived::CVec_HTLCOutputInCommitmentZ) -> crate::c_types::derived::CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ,
/// Create a signature for a local commitment transaction. This will only ever be called with
/// the same local_commitment_tx (or a copy thereof), though there are currently no guarantees
/// that it will not be called multiple times.
/// An external signer implementation should check that the commitment has not been revoked.
#[must_use]
pub sign_local_commitment: extern "C" fn (this_arg: *const c_void, local_commitment_tx: &crate::ln::chan_utils::LocalCommitmentTransaction) -> crate::c_types::derived::CResult_SignatureNoneZ,
/// Create a signature for each HTLC transaction spending a local commitment transaction.
///
/// Unlike sign_local_commitment, this may be called multiple times with *different*
/// local_commitment_tx values. While this will never be called with a revoked
/// local_commitment_tx, it is possible that it is called with the second-latest
/// local_commitment_tx (only if we haven't yet revoked it) if some watchtower/secondary
/// ChannelMonitor decided to broadcast before it had been updated to the latest.
///
/// Either an Err should be returned, or a Vec with one entry for each HTLC which exists in
/// local_commitment_tx. For those HTLCs which have transaction_output_index set to None
/// (implying they were considered dust at the time the commitment transaction was negotiated),
/// a corresponding None should be included in the return value. All other positions in the
/// return value must contain a signature.
#[must_use]
pub sign_local_commitment_htlc_transactions: extern "C" fn (this_arg: *const c_void, local_commitment_tx: &crate::ln::chan_utils::LocalCommitmentTransaction) -> crate::c_types::derived::CResult_CVec_SignatureZNoneZ,
/// Create a signature for the given input in a transaction spending an HTLC or commitment
/// transaction output when our counterparty broadcasts an old state.
///
/// A justice transaction may claim multiples outputs at the same time if timelocks are
/// similar, but only a signature for the input at index `input` should be signed for here.
/// It may be called multiples time for same output(s) if a fee-bump is needed with regards
/// to an upcoming timelock expiration.
///
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
///
/// per_commitment_key is revocation secret which was provided by our counterparty when they
/// revoked the state which they eventually broadcast. It's not a _local_ secret key and does
/// not allow the spending of any funds by itself (you need our local revocation_secret to do
/// so).
///
/// htlc holds HTLC elements (hash, timelock) if the output being spent is a HTLC output, thus
/// changing the format of the witness script (which is committed to in the BIP 143
/// signatures).
#[must_use]
pub sign_justice_transaction: extern "C" fn (this_arg: *const c_void, justice_tx: crate::c_types::Transaction, input: usize, amount: u64, per_commitment_key: *const [u8; 32], htlc: &crate::ln::chan_utils::HTLCOutputInCommitment) -> crate::c_types::derived::CResult_SignatureNoneZ,
/// Create a signature for a claiming transaction for a HTLC output on a remote commitment
/// transaction, either offered or received.
///
/// Such a transaction may claim multiples offered outputs at same time if we know the
/// preimage for each when we create it, but only the input at index `input` should be
/// signed for here. It may be called multiple times for same output(s) if a fee-bump is
/// needed with regards to an upcoming timelock expiration.
///
/// Witness_script is either a offered or received script as defined in BOLT3 for HTLC
/// outputs.
///
/// Amount is value of the output spent by this input, committed to in the BIP 143 signature.
///
/// Per_commitment_point is the dynamic point corresponding to the channel state
/// detected onchain. It has been generated by our counterparty and is used to derive
/// channel state keys, which are then included in the witness script and committed to in the
/// BIP 143 signature.
#[must_use]
pub sign_remote_htlc_transaction: extern "C" fn (this_arg: *const c_void, htlc_tx: crate::c_types::Transaction, input: usize, amount: u64, per_commitment_point: crate::c_types::PublicKey, htlc: &crate::ln::chan_utils::HTLCOutputInCommitment) -> crate::c_types::derived::CResult_SignatureNoneZ,
/// Create a signature for a (proposed) closing transaction.
///
/// Note that, due to rounding, there may be one \"missing\" satoshi, and either party may have
/// chosen to forgo their output as dust.
#[must_use]
pub sign_closing_transaction: extern "C" fn (this_arg: *const c_void, closing_tx: crate::c_types::Transaction) -> crate::c_types::derived::CResult_SignatureNoneZ,
/// Signs a channel announcement message with our funding key, proving it comes from one
/// of the channel participants.
///
/// Note that if this fails or is rejected, the channel will not be publicly announced and
/// our counterparty may (though likely will not) close the channel on us for violating the
/// protocol.
#[must_use]
pub sign_channel_announcement: extern "C" fn (this_arg: *const c_void, msg: &crate::ln::msgs::UnsignedChannelAnnouncement) -> crate::c_types::derived::CResult_SignatureNoneZ,
/// Set the remote channel basepoints and remote/local to_self_delay.
/// This is done immediately on incoming channels and as soon as the channel is accepted on outgoing channels.
///
/// We bind local_to_self_delay late here for API convenience.
///
/// Will be called before any signatures are applied.
pub on_accept: extern "C" fn (this_arg: *mut c_void, channel_points: &crate::ln::chan_utils::ChannelPublicKeys, remote_to_self_delay: u16, local_to_self_delay: u16),
pub clone: Option<extern "C" fn (this_arg: *const c_void) -> *mut c_void>,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Send for ChannelKeys {}
impl Clone for ChannelKeys {
fn clone(&self) -> Self {
Self {
this_arg: if let Some(f) = self.clone { (f)(self.this_arg) } else { self.this_arg },
get_per_commitment_point: self.get_per_commitment_point.clone(),
release_commitment_secret: self.release_commitment_secret.clone(),
pubkeys: self.pubkeys.clone(),
set_pubkeys: self.set_pubkeys.clone(),
key_derivation_params: self.key_derivation_params.clone(),
sign_remote_commitment: self.sign_remote_commitment.clone(),
sign_local_commitment: self.sign_local_commitment.clone(),
sign_local_commitment_htlc_transactions: self.sign_local_commitment_htlc_transactions.clone(),
sign_justice_transaction: self.sign_justice_transaction.clone(),
sign_remote_htlc_transaction: self.sign_remote_htlc_transaction.clone(),
sign_closing_transaction: self.sign_closing_transaction.clone(),
sign_channel_announcement: self.sign_channel_announcement.clone(),
on_accept: self.on_accept.clone(),
clone: self.clone.clone(),
free: self.free.clone(),
}
}
}
use lightning::chain::keysinterface::ChannelKeys as rustChannelKeys;
impl rustChannelKeys for ChannelKeys {
fn get_per_commitment_point<T:bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification>(&self, idx: u64, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> bitcoin::secp256k1::key::PublicKey {
let mut ret = (self.get_per_commitment_point)(self.this_arg, idx);
ret.into_rust()
}
fn release_commitment_secret(&self, idx: u64) -> [u8; 32] {
let mut ret = (self.release_commitment_secret)(self.this_arg, idx);
ret.data
}
fn pubkeys(&self) -> &lightning::ln::chan_utils::ChannelPublicKeys {
if let Some(f) = self.set_pubkeys {
(f)(self);
}
unsafe { &*self.pubkeys.inner }
}
fn key_derivation_params(&self) -> (u64, u64) {
let mut ret = (self.key_derivation_params)(self.this_arg);
let (mut orig_ret_0, mut orig_ret_1) = ret.to_rust(); let mut local_ret = (orig_ret_0, orig_ret_1);
local_ret
}
fn sign_remote_commitment<T:bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &bitcoin::blockdata::transaction::Transaction, keys: &lightning::ln::chan_utils::PreCalculatedTxCreationKeys, htlcs: &[&lightning::ln::chan_utils::HTLCOutputInCommitment], _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<(bitcoin::secp256k1::Signature, Vec<bitcoin::secp256k1::Signature>), ()> {
let mut local_commitment_tx = ::bitcoin::consensus::encode::serialize(commitment_tx);
let mut local_htlcs = Vec::new(); for item in htlcs.iter() { local_htlcs.push( { crate::ln::chan_utils::HTLCOutputInCommitment { inner: unsafe { ( (&(**item) as *const _) as *mut _) }, is_owned: false } }); };
let mut ret = (self.sign_remote_commitment)(self.this_arg, feerate_per_kw, crate::c_types::Transaction::from_slice(&local_commitment_tx), &crate::ln::chan_utils::PreCalculatedTxCreationKeys { inner: unsafe { (keys as *const _) as *mut _ }, is_owned: false }, local_htlcs.into());
let mut local_ret = match ret.result_ok { true => Ok( { let (mut orig_ret_0_0, mut orig_ret_0_1) = (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).to_rust(); let mut local_orig_ret_0_1 = Vec::new(); for mut item in orig_ret_0_1.into_rust().drain(..) { local_orig_ret_0_1.push( { item.into_rust() }); }; let mut local_ret_0 = (orig_ret_0_0.into_rust(), local_orig_ret_0_1); local_ret_0 }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn sign_local_commitment<T:bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification>(&self, local_commitment_tx: &lightning::ln::chan_utils::LocalCommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<bitcoin::secp256k1::Signature, ()> {
let mut ret = (self.sign_local_commitment)(self.this_arg, &crate::ln::chan_utils::LocalCommitmentTransaction { inner: unsafe { (local_commitment_tx as *const _) as *mut _ }, is_owned: false });
let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn sign_local_commitment_htlc_transactions<T:bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification>(&self, local_commitment_tx: &lightning::ln::chan_utils::LocalCommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<Vec<Option<bitcoin::secp256k1::Signature>>, ()> {
let mut ret = (self.sign_local_commitment_htlc_transactions)(self.this_arg, &crate::ln::chan_utils::LocalCommitmentTransaction { inner: unsafe { (local_commitment_tx as *const _) as *mut _ }, is_owned: false });
let mut local_ret = match ret.result_ok { true => Ok( { let mut local_ret_0 = Vec::new(); for mut item in (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust().drain(..) { local_ret_0.push( { let mut local_ret_0_0 = if item.is_null() { None } else { Some( { item.into_rust() }) }; local_ret_0_0 }); }; local_ret_0 }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn sign_justice_transaction<T:bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification>(&self, justice_tx: &bitcoin::blockdata::transaction::Transaction, input: usize, amount: u64, per_commitment_key: &bitcoin::secp256k1::key::SecretKey, htlc: &Option<lightning::ln::chan_utils::HTLCOutputInCommitment>, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<bitcoin::secp256k1::Signature, ()> {
let mut local_justice_tx = ::bitcoin::consensus::encode::serialize(justice_tx);
let mut local_htlc = &crate::ln::chan_utils::HTLCOutputInCommitment { inner: unsafe { (if htlc.is_none() { std::ptr::null() } else { { (htlc.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
let mut ret = (self.sign_justice_transaction)(self.this_arg, crate::c_types::Transaction::from_slice(&local_justice_tx), input, amount, per_commitment_key.as_ref(), local_htlc);
let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn sign_remote_htlc_transaction<T:bitcoin::secp256k1::Signing + bitcoin::secp256k1::Verification>(&self, htlc_tx: &bitcoin::blockdata::transaction::Transaction, input: usize, amount: u64, per_commitment_point: &bitcoin::secp256k1::key::PublicKey, htlc: &lightning::ln::chan_utils::HTLCOutputInCommitment, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<bitcoin::secp256k1::Signature, ()> {
let mut local_htlc_tx = ::bitcoin::consensus::encode::serialize(htlc_tx);
let mut ret = (self.sign_remote_htlc_transaction)(self.this_arg, crate::c_types::Transaction::from_slice(&local_htlc_tx), input, amount, crate::c_types::PublicKey::from_rust(&per_commitment_point), &crate::ln::chan_utils::HTLCOutputInCommitment { inner: unsafe { (htlc as *const _) as *mut _ }, is_owned: false });
let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn sign_closing_transaction<T:bitcoin::secp256k1::Signing>(&self, closing_tx: &bitcoin::blockdata::transaction::Transaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<bitcoin::secp256k1::Signature, ()> {
let mut local_closing_tx = ::bitcoin::consensus::encode::serialize(closing_tx);
let mut ret = (self.sign_closing_transaction)(self.this_arg, crate::c_types::Transaction::from_slice(&local_closing_tx));
let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn sign_channel_announcement<T:bitcoin::secp256k1::Signing>(&self, msg: &lightning::ln::msgs::UnsignedChannelAnnouncement, _secp_ctx: &bitcoin::secp256k1::Secp256k1<T>) -> Result<bitcoin::secp256k1::Signature, ()> {
let mut ret = (self.sign_channel_announcement)(self.this_arg, &crate::ln::msgs::UnsignedChannelAnnouncement { inner: unsafe { (msg as *const _) as *mut _ }, is_owned: false });
let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })};
local_ret
}
fn on_accept(&mut self, channel_points: &lightning::ln::chan_utils::ChannelPublicKeys, remote_to_self_delay: u16, local_to_self_delay: u16) {
(self.on_accept)(self.this_arg, &crate::ln::chan_utils::ChannelPublicKeys { inner: unsafe { (channel_points as *const _) as *mut _ }, is_owned: false }, remote_to_self_delay, local_to_self_delay)
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for ChannelKeys {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn ChannelKeys_free(this_ptr: ChannelKeys) { }
impl Drop for ChannelKeys {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
/// A trait to describe an object which can get user secrets and key material.
#[repr(C)]
pub struct KeysInterface {
pub this_arg: *mut c_void,
/// Get node secret key (aka node_id or network_key)
#[must_use]
pub get_node_secret: extern "C" fn (this_arg: *const c_void) -> crate::c_types::SecretKey,
/// Get destination redeemScript to encumber static protocol exit points.
#[must_use]
pub get_destination_script: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_u8Z,
/// Get shutdown_pubkey to use as PublicKey at channel closure
#[must_use]
pub get_shutdown_pubkey: extern "C" fn (this_arg: *const c_void) -> crate::c_types::PublicKey,
/// Get a new set of ChannelKeys for per-channel secrets. These MUST be unique even if you
/// restarted with some stale data!
#[must_use]
pub get_channel_keys: extern "C" fn (this_arg: *const c_void, inbound: bool, channel_value_satoshis: u64) -> crate::chain::keysinterface::ChannelKeys,
/// Gets a unique, cryptographically-secure, random 32 byte value. This is used for encrypting
/// onion packets and for temporary channel IDs. There is no requirement that these be
/// persisted anywhere, though they must be unique across restarts.
#[must_use]
pub get_secure_random_bytes: extern "C" fn (this_arg: *const c_void) -> crate::c_types::ThirtyTwoBytes,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Send for KeysInterface {}
unsafe impl Sync for KeysInterface {}
use lightning::chain::keysinterface::KeysInterface as rustKeysInterface;
impl rustKeysInterface for KeysInterface {
type ChanKeySigner = crate::chain::keysinterface::ChannelKeys;
fn get_node_secret(&self) -> bitcoin::secp256k1::key::SecretKey {
let mut ret = (self.get_node_secret)(self.this_arg);
ret.into_rust()
}
fn get_destination_script(&self) -> bitcoin::blockdata::script::Script {
let mut ret = (self.get_destination_script)(self.this_arg);
::bitcoin::blockdata::script::Script::from(ret.into_rust())
}
fn get_shutdown_pubkey(&self) -> bitcoin::secp256k1::key::PublicKey {
let mut ret = (self.get_shutdown_pubkey)(self.this_arg);
ret.into_rust()
}
fn get_channel_keys(&self, inbound: bool, channel_value_satoshis: u64) -> Self::ChanKeySigner {
let mut ret = (self.get_channel_keys)(self.this_arg, inbound, channel_value_satoshis);
ret
}
fn get_secure_random_bytes(&self) -> [u8; 32] {
let mut ret = (self.get_secure_random_bytes)(self.this_arg);
ret.data
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for KeysInterface {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn KeysInterface_free(this_ptr: KeysInterface) { }
impl Drop for KeysInterface {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
use lightning::chain::keysinterface::InMemoryChannelKeys as nativeInMemoryChannelKeysImport;
type nativeInMemoryChannelKeys = nativeInMemoryChannelKeysImport;
/// A simple implementation of ChannelKeys that just keeps the private keys in memory.
#[must_use]
#[repr(C)]
pub struct InMemoryChannelKeys {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeInMemoryChannelKeys,
pub is_owned: bool,
}
impl Drop for InMemoryChannelKeys {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_free(this_ptr: InMemoryChannelKeys) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn InMemoryChannelKeys_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeInMemoryChannelKeys); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl InMemoryChannelKeys {
pub(crate) fn take_ptr(mut self) -> *mut nativeInMemoryChannelKeys {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for InMemoryChannelKeys {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn InMemoryChannelKeys_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeInMemoryChannelKeys)).clone() })) as *mut c_void
}
/// Private key of anchor tx
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_get_funding_key(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.funding_key;
(*inner_val).as_ref()
}
/// Private key of anchor tx
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_set_funding_key(this_ptr: &mut InMemoryChannelKeys, mut val: crate::c_types::SecretKey) {
unsafe { &mut *this_ptr.inner }.funding_key = val.into_rust();
}
/// Local secret key for blinded revocation pubkey
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_get_revocation_base_key(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.revocation_base_key;
(*inner_val).as_ref()
}
/// Local secret key for blinded revocation pubkey
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_set_revocation_base_key(this_ptr: &mut InMemoryChannelKeys, mut val: crate::c_types::SecretKey) {
unsafe { &mut *this_ptr.inner }.revocation_base_key = val.into_rust();
}
/// Local secret key used for our balance in remote-broadcasted commitment transactions
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_get_payment_key(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.payment_key;
(*inner_val).as_ref()
}
/// Local secret key used for our balance in remote-broadcasted commitment transactions
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_set_payment_key(this_ptr: &mut InMemoryChannelKeys, mut val: crate::c_types::SecretKey) {
unsafe { &mut *this_ptr.inner }.payment_key = val.into_rust();
}
/// Local secret key used in HTLC tx
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_get_delayed_payment_base_key(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.delayed_payment_base_key;
(*inner_val).as_ref()
}
/// Local secret key used in HTLC tx
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_set_delayed_payment_base_key(this_ptr: &mut InMemoryChannelKeys, mut val: crate::c_types::SecretKey) {
unsafe { &mut *this_ptr.inner }.delayed_payment_base_key = val.into_rust();
}
/// Local htlc secret key used in commitment tx htlc outputs
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_get_htlc_base_key(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.htlc_base_key;
(*inner_val).as_ref()
}
/// Local htlc secret key used in commitment tx htlc outputs
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_set_htlc_base_key(this_ptr: &mut InMemoryChannelKeys, mut val: crate::c_types::SecretKey) {
unsafe { &mut *this_ptr.inner }.htlc_base_key = val.into_rust();
}
/// Commitment seed
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_get_commitment_seed(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.commitment_seed;
&(*inner_val)
}
/// Commitment seed
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_set_commitment_seed(this_ptr: &mut InMemoryChannelKeys, mut val: crate::c_types::ThirtyTwoBytes) {
unsafe { &mut *this_ptr.inner }.commitment_seed = val.data;
}
/// Create a new InMemoryChannelKeys
#[must_use]
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_new(mut funding_key: crate::c_types::SecretKey, mut revocation_base_key: crate::c_types::SecretKey, mut payment_key: crate::c_types::SecretKey, mut delayed_payment_base_key: crate::c_types::SecretKey, mut htlc_base_key: crate::c_types::SecretKey, mut commitment_seed: crate::c_types::ThirtyTwoBytes, mut channel_value_satoshis: u64, mut key_derivation_params: crate::c_types::derived::C2Tuple_u64u64Z) -> crate::chain::keysinterface::InMemoryChannelKeys {
let (mut orig_key_derivation_params_0, mut orig_key_derivation_params_1) = key_derivation_params.to_rust(); let mut local_key_derivation_params = (orig_key_derivation_params_0, orig_key_derivation_params_1);
let mut ret = lightning::chain::keysinterface::InMemoryChannelKeys::new(&bitcoin::secp256k1::Secp256k1::new(), funding_key.into_rust(), revocation_base_key.into_rust(), payment_key.into_rust(), delayed_payment_base_key.into_rust(), htlc_base_key.into_rust(), commitment_seed.data, channel_value_satoshis, local_key_derivation_params);
crate::chain::keysinterface::InMemoryChannelKeys { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Remote pubkeys.
/// Will panic if on_accept wasn't called.
#[must_use]
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_remote_pubkeys(this_arg: &InMemoryChannelKeys) -> crate::ln::chan_utils::ChannelPublicKeys {
let mut ret = unsafe { &*this_arg.inner }.remote_pubkeys();
crate::ln::chan_utils::ChannelPublicKeys { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false }
}
/// The to_self_delay value specified by our counterparty and applied on locally-broadcastable
/// transactions, ie the amount of time that we have to wait to recover our funds if we
/// broadcast a transaction. You'll likely want to pass this to the
/// ln::chan_utils::build*_transaction functions when signing local transactions.
/// Will panic if on_accept wasn't called.
#[must_use]
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_remote_to_self_delay(this_arg: &InMemoryChannelKeys) -> u16 {
let mut ret = unsafe { &*this_arg.inner }.remote_to_self_delay();
ret
}
/// The to_self_delay value specified by us and applied on transactions broadcastable
/// by our counterparty, ie the amount of time that they have to wait to recover their funds
/// if they broadcast a transaction.
/// Will panic if on_accept wasn't called.
#[must_use]
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_local_to_self_delay(this_arg: &InMemoryChannelKeys) -> u16 {
let mut ret = unsafe { &*this_arg.inner }.local_to_self_delay();
ret
}
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_as_ChannelKeys(this_arg: *const InMemoryChannelKeys) -> crate::chain::keysinterface::ChannelKeys {
crate::chain::keysinterface::ChannelKeys {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
get_per_commitment_point: InMemoryChannelKeys_ChannelKeys_get_per_commitment_point,
release_commitment_secret: InMemoryChannelKeys_ChannelKeys_release_commitment_secret,
pubkeys: crate::ln::chan_utils::ChannelPublicKeys { inner: std::ptr::null_mut(), is_owned: true },
set_pubkeys: Some(InMemoryChannelKeys_ChannelKeys_set_pubkeys),
key_derivation_params: InMemoryChannelKeys_ChannelKeys_key_derivation_params,
sign_remote_commitment: InMemoryChannelKeys_ChannelKeys_sign_remote_commitment,
sign_local_commitment: InMemoryChannelKeys_ChannelKeys_sign_local_commitment,
sign_local_commitment_htlc_transactions: InMemoryChannelKeys_ChannelKeys_sign_local_commitment_htlc_transactions,
sign_justice_transaction: InMemoryChannelKeys_ChannelKeys_sign_justice_transaction,
sign_remote_htlc_transaction: InMemoryChannelKeys_ChannelKeys_sign_remote_htlc_transaction,
sign_closing_transaction: InMemoryChannelKeys_ChannelKeys_sign_closing_transaction,
sign_channel_announcement: InMemoryChannelKeys_ChannelKeys_sign_channel_announcement,
on_accept: InMemoryChannelKeys_ChannelKeys_on_accept,
clone: Some(InMemoryChannelKeys_clone_void),
}
}
use lightning::chain::keysinterface::ChannelKeys as ChannelKeysTraitImport;
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_get_per_commitment_point(this_arg: *const c_void, mut idx: u64) -> crate::c_types::PublicKey {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.get_per_commitment_point(idx, &bitcoin::secp256k1::Secp256k1::new());
crate::c_types::PublicKey::from_rust(&ret)
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_release_commitment_secret(this_arg: *const c_void, mut idx: u64) -> crate::c_types::ThirtyTwoBytes {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.release_commitment_secret(idx);
crate::c_types::ThirtyTwoBytes { data: ret }
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_pubkeys(this_arg: *const c_void) -> crate::ln::chan_utils::ChannelPublicKeys {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.pubkeys();
crate::ln::chan_utils::ChannelPublicKeys { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false }
}
extern "C" fn InMemoryChannelKeys_ChannelKeys_set_pubkeys(trait_self_arg: &ChannelKeys) {
// This is a bit race-y in the general case, but for our specific use-cases today, we're safe
// Specifically, we must ensure that the first time we're called it can never be in parallel
if trait_self_arg.pubkeys.inner.is_null() {
unsafe { &mut *(trait_self_arg as *const ChannelKeys as *mut ChannelKeys) }.pubkeys = InMemoryChannelKeys_ChannelKeys_pubkeys(trait_self_arg.this_arg);
}
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_key_derivation_params(this_arg: *const c_void) -> crate::c_types::derived::C2Tuple_u64u64Z {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.key_derivation_params();
let (mut orig_ret_0, mut orig_ret_1) = ret; let mut local_ret = (orig_ret_0, orig_ret_1).into();
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_remote_commitment(this_arg: *const c_void, mut feerate_per_kw: u32, commitment_tx: crate::c_types::Transaction, pre_keys: &crate::ln::chan_utils::PreCalculatedTxCreationKeys, mut htlcs: crate::c_types::derived::CVec_HTLCOutputInCommitmentZ) -> crate::c_types::derived::CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ {
let mut local_htlcs = Vec::new(); for mut item in htlcs.as_slice().iter() { local_htlcs.push( { unsafe { &*item.inner } }); };
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_remote_commitment(feerate_per_kw, &commitment_tx.into_bitcoin(), unsafe { &*pre_keys.inner }, &local_htlcs[..], &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { let (mut orig_ret_0_0, mut orig_ret_0_1) = o; let mut local_orig_ret_0_1 = Vec::new(); for item in orig_ret_0_1.drain(..) { local_orig_ret_0_1.push( { crate::c_types::Signature::from_rust(&item) }); }; let mut local_ret_0 = (crate::c_types::Signature::from_rust(&orig_ret_0_0), local_orig_ret_0_1.into()).into(); local_ret_0 }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_local_commitment(this_arg: *const c_void, local_commitment_tx: &crate::ln::chan_utils::LocalCommitmentTransaction) -> crate::c_types::derived::CResult_SignatureNoneZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_local_commitment(unsafe { &*local_commitment_tx.inner }, &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_local_commitment_htlc_transactions(this_arg: *const c_void, local_commitment_tx: &crate::ln::chan_utils::LocalCommitmentTransaction) -> crate::c_types::derived::CResult_CVec_SignatureZNoneZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_local_commitment_htlc_transactions(unsafe { &*local_commitment_tx.inner }, &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { let mut local_ret_0 = Vec::new(); for item in o.drain(..) { local_ret_0.push( { let mut local_ret_0_0 = if item.is_none() { crate::c_types::Signature::null() } else { { crate::c_types::Signature::from_rust(&(item.unwrap())) } }; local_ret_0_0 }); }; local_ret_0.into() }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_justice_transaction(this_arg: *const c_void, justice_tx: crate::c_types::Transaction, mut input: usize, mut amount: u64, per_commitment_key: *const [u8; 32], htlc: &crate::ln::chan_utils::HTLCOutputInCommitment) -> crate::c_types::derived::CResult_SignatureNoneZ {
let mut local_htlc = if htlc.inner.is_null() { None } else { Some((* { unsafe { &*htlc.inner } }).clone()) };
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_justice_transaction(&justice_tx.into_bitcoin(), input, amount, &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *per_commitment_key}[..]).unwrap(), &local_htlc, &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_remote_htlc_transaction(this_arg: *const c_void, htlc_tx: crate::c_types::Transaction, mut input: usize, mut amount: u64, per_commitment_point: crate::c_types::PublicKey, htlc: &crate::ln::chan_utils::HTLCOutputInCommitment) -> crate::c_types::derived::CResult_SignatureNoneZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_remote_htlc_transaction(&htlc_tx.into_bitcoin(), input, amount, &per_commitment_point.into_rust(), unsafe { &*htlc.inner }, &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_closing_transaction(this_arg: *const c_void, closing_tx: crate::c_types::Transaction) -> crate::c_types::derived::CResult_SignatureNoneZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_closing_transaction(&closing_tx.into_bitcoin(), &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[must_use]
extern "C" fn InMemoryChannelKeys_ChannelKeys_sign_channel_announcement(this_arg: *const c_void, msg: &crate::ln::msgs::UnsignedChannelAnnouncement) -> crate::c_types::derived::CResult_SignatureNoneZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.sign_channel_announcement(unsafe { &*msg.inner }, &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
extern "C" fn InMemoryChannelKeys_ChannelKeys_on_accept(this_arg: *mut c_void, channel_pubkeys: &crate::ln::chan_utils::ChannelPublicKeys, mut remote_to_self_delay: u16, mut local_to_self_delay: u16) {
unsafe { &mut *(this_arg as *mut nativeInMemoryChannelKeys) }.on_accept(unsafe { &*channel_pubkeys.inner }, remote_to_self_delay, local_to_self_delay)
}
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_write(obj: *const InMemoryChannelKeys) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn InMemoryChannelKeys_read(ser: crate::c_types::u8slice) -> InMemoryChannelKeys {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
InMemoryChannelKeys { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
InMemoryChannelKeys { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::chain::keysinterface::KeysManager as nativeKeysManagerImport;
type nativeKeysManager = nativeKeysManagerImport;
/// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key
/// and derives keys from that.
///
/// Your node_id is seed/0'
/// ChannelMonitor closes may use seed/1'
/// Cooperative closes may use seed/2'
/// The two close keys may be needed to claim on-chain funds!
#[must_use]
#[repr(C)]
pub struct KeysManager {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeKeysManager,
pub is_owned: bool,
}
impl Drop for KeysManager {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn KeysManager_free(this_ptr: KeysManager) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn KeysManager_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeKeysManager); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl KeysManager {
pub(crate) fn take_ptr(mut self) -> *mut nativeKeysManager {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Constructs a KeysManager from a 32-byte seed. If the seed is in some way biased (eg your
/// CSRNG is busted) this may panic (but more importantly, you will possibly lose funds).
/// starting_time isn't strictly required to actually be a time, but it must absolutely,
/// without a doubt, be unique to this instance. ie if you start multiple times with the same
/// seed, starting_time must be unique to each run. Thus, the easiest way to achieve this is to
/// simply use the current time (with very high precision).
///
/// The seed MUST be backed up safely prior to use so that the keys can be re-created, however,
/// obviously, starting_time should be unique every time you reload the library - it is only
/// used to generate new ephemeral key data (which will be stored by the individual channel if
/// necessary).
///
/// Note that the seed is required to recover certain on-chain funds independent of
/// ChannelMonitor data, though a current copy of ChannelMonitor data is also required for any
/// channel, and some on-chain during-closing funds.
///
/// Note that until the 0.1 release there is no guarantee of backward compatibility between
/// versions. Once the library is more fully supported, the docs will be updated to include a
/// detailed description of the guarantee.
#[must_use]
#[no_mangle]
pub extern "C" fn KeysManager_new(seed: *const [u8; 32], mut network: crate::bitcoin::network::Network, mut starting_time_secs: u64, mut starting_time_nanos: u32) -> KeysManager {
let mut ret = lightning::chain::keysinterface::KeysManager::new(unsafe { &*seed}, network.into_bitcoin(), starting_time_secs, starting_time_nanos);
KeysManager { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Derive an old set of ChannelKeys for per-channel secrets based on a key derivation
/// parameters.
/// Key derivation parameters are accessible through a per-channel secrets
/// ChannelKeys::key_derivation_params and is provided inside DynamicOuputP2WSH in case of
/// onchain output detection for which a corresponding delayed_payment_key must be derived.
#[must_use]
#[no_mangle]
pub extern "C" fn KeysManager_derive_channel_keys(this_arg: &KeysManager, mut channel_value_satoshis: u64, mut params_1: u64, mut params_2: u64) -> crate::chain::keysinterface::InMemoryChannelKeys {
let mut ret = unsafe { &*this_arg.inner }.derive_channel_keys(channel_value_satoshis, params_1, params_2);
crate::chain::keysinterface::InMemoryChannelKeys { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
#[no_mangle]
pub extern "C" fn KeysManager_as_KeysInterface(this_arg: *const KeysManager) -> crate::chain::keysinterface::KeysInterface {
crate::chain::keysinterface::KeysInterface {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
get_node_secret: KeysManager_KeysInterface_get_node_secret,
get_destination_script: KeysManager_KeysInterface_get_destination_script,
get_shutdown_pubkey: KeysManager_KeysInterface_get_shutdown_pubkey,
get_channel_keys: KeysManager_KeysInterface_get_channel_keys,
get_secure_random_bytes: KeysManager_KeysInterface_get_secure_random_bytes,
}
}
use lightning::chain::keysinterface::KeysInterface as KeysInterfaceTraitImport;
#[must_use]
extern "C" fn KeysManager_KeysInterface_get_node_secret(this_arg: *const c_void) -> crate::c_types::SecretKey {
let mut ret = unsafe { &mut *(this_arg as *mut nativeKeysManager) }.get_node_secret();
crate::c_types::SecretKey::from_rust(ret)
}
#[must_use]
extern "C" fn KeysManager_KeysInterface_get_destination_script(this_arg: *const c_void) -> crate::c_types::derived::CVec_u8Z {
let mut ret = unsafe { &mut *(this_arg as *mut nativeKeysManager) }.get_destination_script();
ret.into_bytes().into()
}
#[must_use]
extern "C" fn KeysManager_KeysInterface_get_shutdown_pubkey(this_arg: *const c_void) -> crate::c_types::PublicKey {
let mut ret = unsafe { &mut *(this_arg as *mut nativeKeysManager) }.get_shutdown_pubkey();
crate::c_types::PublicKey::from_rust(&ret)
}
#[must_use]
extern "C" fn KeysManager_KeysInterface_get_channel_keys(this_arg: *const c_void, mut _inbound: bool, mut channel_value_satoshis: u64) -> crate::chain::keysinterface::ChannelKeys {
let mut ret = unsafe { &mut *(this_arg as *mut nativeKeysManager) }.get_channel_keys(_inbound, channel_value_satoshis);
let mut rust_obj = InMemoryChannelKeys { inner: Box::into_raw(Box::new(ret)), is_owned: true };
let mut ret = InMemoryChannelKeys_as_ChannelKeys(&rust_obj);
// We want to free rust_obj when ret gets drop()'d, not rust_obj, so wipe rust_obj's pointer and set ret's free() fn
rust_obj.inner = std::ptr::null_mut();
ret.free = Some(InMemoryChannelKeys_free_void);
ret
}
#[must_use]
extern "C" fn KeysManager_KeysInterface_get_secure_random_bytes(this_arg: *const c_void) -> crate::c_types::ThirtyTwoBytes {
let mut ret = unsafe { &mut *(this_arg as *mut nativeKeysManager) }.get_secure_random_bytes();
crate::c_types::ThirtyTwoBytes { data: ret }
}

View file

@ -0,0 +1,9 @@
//! Structs and traits which allow other parts of rust-lightning to interact with the blockchain.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
pub mod chaininterface;
pub mod transaction;
pub mod keysinterface;

View file

@ -0,0 +1,110 @@
//! Contains simple structs describing parts of transactions on the chain.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::chain::transaction::OutPoint as nativeOutPointImport;
type nativeOutPoint = nativeOutPointImport;
/// A reference to a transaction output.
///
/// Differs from bitcoin::blockdata::transaction::OutPoint as the index is a u16 instead of u32
/// due to LN's restrictions on index values. Should reduce (possibly) unsafe conversions this way.
#[must_use]
#[repr(C)]
pub struct OutPoint {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeOutPoint,
pub is_owned: bool,
}
impl Drop for OutPoint {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn OutPoint_free(this_ptr: OutPoint) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn OutPoint_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeOutPoint); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl OutPoint {
pub(crate) fn take_ptr(mut self) -> *mut nativeOutPoint {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for OutPoint {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn OutPoint_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeOutPoint)).clone() })) as *mut c_void
}
/// The referenced transaction's txid.
#[no_mangle]
pub extern "C" fn OutPoint_get_txid(this_ptr: &OutPoint) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.txid;
(*inner_val).as_inner()
}
/// The referenced transaction's txid.
#[no_mangle]
pub extern "C" fn OutPoint_set_txid(this_ptr: &mut OutPoint, mut val: crate::c_types::ThirtyTwoBytes) {
unsafe { &mut *this_ptr.inner }.txid = ::bitcoin::hash_types::Txid::from_slice(&val.data[..]).unwrap();
}
/// The index of the referenced output in its transaction's vout.
#[no_mangle]
pub extern "C" fn OutPoint_get_index(this_ptr: &OutPoint) -> u16 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.index;
(*inner_val)
}
/// The index of the referenced output in its transaction's vout.
#[no_mangle]
pub extern "C" fn OutPoint_set_index(this_ptr: &mut OutPoint, mut val: u16) {
unsafe { &mut *this_ptr.inner }.index = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn OutPoint_new(mut txid_arg: crate::c_types::ThirtyTwoBytes, mut index_arg: u16) -> OutPoint {
OutPoint { inner: Box::into_raw(Box::new(nativeOutPoint {
txid: ::bitcoin::hash_types::Txid::from_slice(&txid_arg.data[..]).unwrap(),
index: index_arg,
})), is_owned: true }
}
/// Convert an `OutPoint` to a lightning channel id.
#[must_use]
#[no_mangle]
pub extern "C" fn OutPoint_to_channel_id(this_arg: &OutPoint) -> crate::c_types::ThirtyTwoBytes {
let mut ret = unsafe { &*this_arg.inner }.to_channel_id();
crate::c_types::ThirtyTwoBytes { data: ret }
}
#[no_mangle]
pub extern "C" fn OutPoint_write(obj: *const OutPoint) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn OutPoint_read(ser: crate::c_types::u8slice) -> OutPoint {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
OutPoint { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
OutPoint { inner: std::ptr::null_mut(), is_owned: true }
}
}

View file

@ -0,0 +1,24 @@
//!lightning
//! Rust-Lightning, not Rusty's Lightning!
//!
//! A full-featured but also flexible lightning implementation, in library form. This allows the
//! user (you) to decide how they wish to use it instead of being a fully self-contained daemon.
//! This means there is no built-in threading/execution environment and it's up to the user to
//! figure out how best to make networking happen/timers fire/things get written to disk/keys get
//! generated/etc. This makes it a good candidate for tight integration into an existing wallet
//! instead of having a rather-separate lightning appendage to a wallet.
#![allow(unknown_lints)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(unused_parens)]
#![allow(unused_unsafe)]
#![allow(unused_braces)]
mod c_types;
mod bitcoin;
pub mod util;
pub mod chain;
pub mod ln;
pub mod routing;

View file

@ -0,0 +1,745 @@
//! Various utilities for building scripts and deriving keys related to channels. These are
//! largely of interest for those implementing chain::keysinterface::ChannelKeys message signing
//! by hand.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
/// Build the commitment secret from the seed and the commitment number
#[no_mangle]
pub extern "C" fn build_commitment_secret(commitment_seed: *const [u8; 32], mut idx: u64) -> crate::c_types::ThirtyTwoBytes {
let mut ret = lightning::ln::chan_utils::build_commitment_secret(unsafe { &*commitment_seed}, idx);
crate::c_types::ThirtyTwoBytes { data: ret }
}
/// Derives a per-commitment-transaction private key (eg an htlc key or delayed_payment key)
/// from the base secret and the per_commitment_point.
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
#[no_mangle]
pub extern "C" fn derive_private_key(per_commitment_point: crate::c_types::PublicKey, base_secret: *const [u8; 32]) -> crate::c_types::derived::CResult_SecretKeySecpErrorZ {
let mut ret = lightning::ln::chan_utils::derive_private_key(&bitcoin::secp256k1::Secp256k1::new(), &per_commitment_point.into_rust(), &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *base_secret}[..]).unwrap());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::SecretKey::from_rust(o) }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::c_types::Secp256k1Error::from_rust(e) }) };
local_ret
}
/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
/// from the base point and the per_commitment_key. This is the public equivalent of
/// derive_private_key - using only public keys to derive a public key instead of private keys.
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
#[no_mangle]
pub extern "C" fn derive_public_key(per_commitment_point: crate::c_types::PublicKey, base_point: crate::c_types::PublicKey) -> crate::c_types::derived::CResult_PublicKeySecpErrorZ {
let mut ret = lightning::ln::chan_utils::derive_public_key(&bitcoin::secp256k1::Secp256k1::new(), &per_commitment_point.into_rust(), &base_point.into_rust());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::PublicKey::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::c_types::Secp256k1Error::from_rust(e) }) };
local_ret
}
/// Derives a per-commitment-transaction revocation key from its constituent parts.
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
#[no_mangle]
pub extern "C" fn derive_private_revocation_key(per_commitment_secret: *const [u8; 32], revocation_base_secret: *const [u8; 32]) -> crate::c_types::derived::CResult_SecretKeySecpErrorZ {
let mut ret = lightning::ln::chan_utils::derive_private_revocation_key(&bitcoin::secp256k1::Secp256k1::new(), &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *per_commitment_secret}[..]).unwrap(), &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *revocation_base_secret}[..]).unwrap());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::SecretKey::from_rust(o) }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::c_types::Secp256k1Error::from_rust(e) }) };
local_ret
}
/// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
/// public key instead of private keys.
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
#[no_mangle]
pub extern "C" fn derive_public_revocation_key(per_commitment_point: crate::c_types::PublicKey, revocation_base_point: crate::c_types::PublicKey) -> crate::c_types::derived::CResult_PublicKeySecpErrorZ {
let mut ret = lightning::ln::chan_utils::derive_public_revocation_key(&bitcoin::secp256k1::Secp256k1::new(), &per_commitment_point.into_rust(), &revocation_base_point.into_rust());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::PublicKey::from_rust(&o) }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::c_types::Secp256k1Error::from_rust(e) }) };
local_ret
}
use lightning::ln::chan_utils::TxCreationKeys as nativeTxCreationKeysImport;
type nativeTxCreationKeys = nativeTxCreationKeysImport;
/// The set of public keys which are used in the creation of one commitment transaction.
/// These are derived from the channel base keys and per-commitment data.
///
/// These keys are assumed to be good, either because the code derived them from
/// channel basepoints via the new function, or they were obtained via
/// PreCalculatedTxCreationKeys.trust_key_derivation because we trusted the source of the
/// pre-calculated keys.
#[must_use]
#[repr(C)]
pub struct TxCreationKeys {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeTxCreationKeys,
pub is_owned: bool,
}
impl Drop for TxCreationKeys {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn TxCreationKeys_free(this_ptr: TxCreationKeys) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn TxCreationKeys_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeTxCreationKeys); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl TxCreationKeys {
pub(crate) fn take_ptr(mut self) -> *mut nativeTxCreationKeys {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for TxCreationKeys {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn TxCreationKeys_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeTxCreationKeys)).clone() })) as *mut c_void
}
/// The per-commitment public key which was used to derive the other keys.
#[no_mangle]
pub extern "C" fn TxCreationKeys_get_per_commitment_point(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.per_commitment_point;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The per-commitment public key which was used to derive the other keys.
#[no_mangle]
pub extern "C" fn TxCreationKeys_set_per_commitment_point(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.per_commitment_point = val.into_rust();
}
/// The revocation key which is used to allow the owner of the commitment transaction to
/// provide their counterparty the ability to punish them if they broadcast an old state.
#[no_mangle]
pub extern "C" fn TxCreationKeys_get_revocation_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.revocation_key;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The revocation key which is used to allow the owner of the commitment transaction to
/// provide their counterparty the ability to punish them if they broadcast an old state.
#[no_mangle]
pub extern "C" fn TxCreationKeys_set_revocation_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.revocation_key = val.into_rust();
}
/// A's HTLC Key
#[no_mangle]
pub extern "C" fn TxCreationKeys_get_a_htlc_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.a_htlc_key;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// A's HTLC Key
#[no_mangle]
pub extern "C" fn TxCreationKeys_set_a_htlc_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.a_htlc_key = val.into_rust();
}
/// B's HTLC Key
#[no_mangle]
pub extern "C" fn TxCreationKeys_get_b_htlc_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.b_htlc_key;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// B's HTLC Key
#[no_mangle]
pub extern "C" fn TxCreationKeys_set_b_htlc_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.b_htlc_key = val.into_rust();
}
/// A's Payment Key (which isn't allowed to be spent from for some delay)
#[no_mangle]
pub extern "C" fn TxCreationKeys_get_a_delayed_payment_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.a_delayed_payment_key;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// A's Payment Key (which isn't allowed to be spent from for some delay)
#[no_mangle]
pub extern "C" fn TxCreationKeys_set_a_delayed_payment_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.a_delayed_payment_key = val.into_rust();
}
#[must_use]
#[no_mangle]
pub extern "C" fn TxCreationKeys_new(mut per_commitment_point_arg: crate::c_types::PublicKey, mut revocation_key_arg: crate::c_types::PublicKey, mut a_htlc_key_arg: crate::c_types::PublicKey, mut b_htlc_key_arg: crate::c_types::PublicKey, mut a_delayed_payment_key_arg: crate::c_types::PublicKey) -> TxCreationKeys {
TxCreationKeys { inner: Box::into_raw(Box::new(nativeTxCreationKeys {
per_commitment_point: per_commitment_point_arg.into_rust(),
revocation_key: revocation_key_arg.into_rust(),
a_htlc_key: a_htlc_key_arg.into_rust(),
b_htlc_key: b_htlc_key_arg.into_rust(),
a_delayed_payment_key: a_delayed_payment_key_arg.into_rust(),
})), is_owned: true }
}
#[no_mangle]
pub extern "C" fn TxCreationKeys_write(obj: *const TxCreationKeys) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn TxCreationKeys_read(ser: crate::c_types::u8slice) -> TxCreationKeys {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
TxCreationKeys { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
TxCreationKeys { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::ln::chan_utils::PreCalculatedTxCreationKeys as nativePreCalculatedTxCreationKeysImport;
type nativePreCalculatedTxCreationKeys = nativePreCalculatedTxCreationKeysImport;
/// The per-commitment point and a set of pre-calculated public keys used for transaction creation
/// in the signer.
/// The pre-calculated keys are an optimization, because ChannelKeys has enough
/// information to re-derive them.
#[must_use]
#[repr(C)]
pub struct PreCalculatedTxCreationKeys {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativePreCalculatedTxCreationKeys,
pub is_owned: bool,
}
impl Drop for PreCalculatedTxCreationKeys {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn PreCalculatedTxCreationKeys_free(this_ptr: PreCalculatedTxCreationKeys) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn PreCalculatedTxCreationKeys_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativePreCalculatedTxCreationKeys); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl PreCalculatedTxCreationKeys {
pub(crate) fn take_ptr(mut self) -> *mut nativePreCalculatedTxCreationKeys {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Create a new PreCalculatedTxCreationKeys from TxCreationKeys
#[must_use]
#[no_mangle]
pub extern "C" fn PreCalculatedTxCreationKeys_new(mut keys: crate::ln::chan_utils::TxCreationKeys) -> PreCalculatedTxCreationKeys {
let mut ret = lightning::ln::chan_utils::PreCalculatedTxCreationKeys::new(*unsafe { Box::from_raw(keys.take_ptr()) });
PreCalculatedTxCreationKeys { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// The pre-calculated transaction creation public keys.
/// An external validating signer should not trust these keys.
#[must_use]
#[no_mangle]
pub extern "C" fn PreCalculatedTxCreationKeys_trust_key_derivation(this_arg: &PreCalculatedTxCreationKeys) -> crate::ln::chan_utils::TxCreationKeys {
let mut ret = unsafe { &*this_arg.inner }.trust_key_derivation();
crate::ln::chan_utils::TxCreationKeys { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false }
}
/// The transaction per-commitment point
#[must_use]
#[no_mangle]
pub extern "C" fn PreCalculatedTxCreationKeys_per_commitment_point(this_arg: &PreCalculatedTxCreationKeys) -> crate::c_types::PublicKey {
let mut ret = unsafe { &*this_arg.inner }.per_commitment_point();
crate::c_types::PublicKey::from_rust(&*ret)
}
use lightning::ln::chan_utils::ChannelPublicKeys as nativeChannelPublicKeysImport;
type nativeChannelPublicKeys = nativeChannelPublicKeysImport;
/// One counterparty's public keys which do not change over the life of a channel.
#[must_use]
#[repr(C)]
pub struct ChannelPublicKeys {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelPublicKeys,
pub is_owned: bool,
}
impl Drop for ChannelPublicKeys {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_free(this_ptr: ChannelPublicKeys) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelPublicKeys_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelPublicKeys); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelPublicKeys {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelPublicKeys {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for ChannelPublicKeys {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn ChannelPublicKeys_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelPublicKeys)).clone() })) as *mut c_void
}
/// The public key which is used to sign all commitment transactions, as it appears in the
/// on-chain channel lock-in 2-of-2 multisig output.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_get_funding_pubkey(this_ptr: &ChannelPublicKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.funding_pubkey;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The public key which is used to sign all commitment transactions, as it appears in the
/// on-chain channel lock-in 2-of-2 multisig output.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_set_funding_pubkey(this_ptr: &mut ChannelPublicKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.funding_pubkey = val.into_rust();
}
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
/// revocation keys. This is combined with the per-commitment-secret generated by the
/// counterparty to create a secret which the counterparty can reveal to revoke previous
/// states.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_get_revocation_basepoint(this_ptr: &ChannelPublicKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.revocation_basepoint;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
/// revocation keys. This is combined with the per-commitment-secret generated by the
/// counterparty to create a secret which the counterparty can reveal to revoke previous
/// states.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_set_revocation_basepoint(this_ptr: &mut ChannelPublicKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.revocation_basepoint = val.into_rust();
}
/// The public key which receives our immediately spendable primary channel balance in
/// remote-broadcasted commitment transactions. This key is static across every commitment
/// transaction.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_get_payment_point(this_ptr: &ChannelPublicKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.payment_point;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The public key which receives our immediately spendable primary channel balance in
/// remote-broadcasted commitment transactions. This key is static across every commitment
/// transaction.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_set_payment_point(this_ptr: &mut ChannelPublicKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.payment_point = val.into_rust();
}
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives non-HTLC-encumbered funds which are only available for spending
/// after some delay (or can be claimed via the revocation path).
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_get_delayed_payment_basepoint(this_ptr: &ChannelPublicKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.delayed_payment_basepoint;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives non-HTLC-encumbered funds which are only available for spending
/// after some delay (or can be claimed via the revocation path).
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_set_delayed_payment_basepoint(this_ptr: &mut ChannelPublicKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.delayed_payment_basepoint = val.into_rust();
}
/// The base point which is used (with derive_public_key) to derive a per-commitment public key
/// which is used to encumber HTLC-in-flight outputs.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_get_htlc_basepoint(this_ptr: &ChannelPublicKeys) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.htlc_basepoint;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The base point which is used (with derive_public_key) to derive a per-commitment public key
/// which is used to encumber HTLC-in-flight outputs.
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_set_htlc_basepoint(this_ptr: &mut ChannelPublicKeys, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.htlc_basepoint = val.into_rust();
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_new(mut funding_pubkey_arg: crate::c_types::PublicKey, mut revocation_basepoint_arg: crate::c_types::PublicKey, mut payment_point_arg: crate::c_types::PublicKey, mut delayed_payment_basepoint_arg: crate::c_types::PublicKey, mut htlc_basepoint_arg: crate::c_types::PublicKey) -> ChannelPublicKeys {
ChannelPublicKeys { inner: Box::into_raw(Box::new(nativeChannelPublicKeys {
funding_pubkey: funding_pubkey_arg.into_rust(),
revocation_basepoint: revocation_basepoint_arg.into_rust(),
payment_point: payment_point_arg.into_rust(),
delayed_payment_basepoint: delayed_payment_basepoint_arg.into_rust(),
htlc_basepoint: htlc_basepoint_arg.into_rust(),
})), is_owned: true }
}
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_write(obj: *const ChannelPublicKeys) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn ChannelPublicKeys_read(ser: crate::c_types::u8slice) -> ChannelPublicKeys {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
ChannelPublicKeys { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
ChannelPublicKeys { inner: std::ptr::null_mut(), is_owned: true }
}
}
/// Create a new TxCreationKeys from channel base points and the per-commitment point
#[must_use]
#[no_mangle]
pub extern "C" fn TxCreationKeys_derive_new(per_commitment_point: crate::c_types::PublicKey, a_delayed_payment_base: crate::c_types::PublicKey, a_htlc_base: crate::c_types::PublicKey, b_revocation_base: crate::c_types::PublicKey, b_htlc_base: crate::c_types::PublicKey) -> crate::c_types::derived::CResult_TxCreationKeysSecpErrorZ {
let mut ret = lightning::ln::chan_utils::TxCreationKeys::derive_new(&bitcoin::secp256k1::Secp256k1::new(), &per_commitment_point.into_rust(), &a_delayed_payment_base.into_rust(), &a_htlc_base.into_rust(), &b_revocation_base.into_rust(), &b_htlc_base.into_rust());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::ln::chan_utils::TxCreationKeys { inner: Box::into_raw(Box::new(o)), is_owned: true } }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::c_types::Secp256k1Error::from_rust(e) }) };
local_ret
}
/// A script either spendable by the revocation
/// key or the delayed_payment_key and satisfying the relative-locktime OP_CSV constrain.
/// Encumbering a `to_local` output on a commitment transaction or 2nd-stage HTLC transactions.
#[no_mangle]
pub extern "C" fn get_revokeable_redeemscript(revocation_key: crate::c_types::PublicKey, mut to_self_delay: u16, delayed_payment_key: crate::c_types::PublicKey) -> crate::c_types::derived::CVec_u8Z {
let mut ret = lightning::ln::chan_utils::get_revokeable_redeemscript(&revocation_key.into_rust(), to_self_delay, &delayed_payment_key.into_rust());
ret.into_bytes().into()
}
use lightning::ln::chan_utils::HTLCOutputInCommitment as nativeHTLCOutputInCommitmentImport;
type nativeHTLCOutputInCommitment = nativeHTLCOutputInCommitmentImport;
/// Information about an HTLC as it appears in a commitment transaction
#[must_use]
#[repr(C)]
pub struct HTLCOutputInCommitment {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeHTLCOutputInCommitment,
pub is_owned: bool,
}
impl Drop for HTLCOutputInCommitment {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_free(this_ptr: HTLCOutputInCommitment) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn HTLCOutputInCommitment_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeHTLCOutputInCommitment); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl HTLCOutputInCommitment {
pub(crate) fn take_ptr(mut self) -> *mut nativeHTLCOutputInCommitment {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for HTLCOutputInCommitment {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn HTLCOutputInCommitment_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeHTLCOutputInCommitment)).clone() })) as *mut c_void
}
/// Whether the HTLC was \"offered\" (ie outbound in relation to this commitment transaction).
/// Note that this is not the same as whether it is ountbound *from us*. To determine that you
/// need to compare this value to whether the commitment transaction in question is that of
/// the remote party or our own.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_get_offered(this_ptr: &HTLCOutputInCommitment) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.offered;
(*inner_val)
}
/// Whether the HTLC was \"offered\" (ie outbound in relation to this commitment transaction).
/// Note that this is not the same as whether it is ountbound *from us*. To determine that you
/// need to compare this value to whether the commitment transaction in question is that of
/// the remote party or our own.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_set_offered(this_ptr: &mut HTLCOutputInCommitment, mut val: bool) {
unsafe { &mut *this_ptr.inner }.offered = val;
}
/// The value, in msat, of the HTLC. The value as it appears in the commitment transaction is
/// this divided by 1000.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_get_amount_msat(this_ptr: &HTLCOutputInCommitment) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.amount_msat;
(*inner_val)
}
/// The value, in msat, of the HTLC. The value as it appears in the commitment transaction is
/// this divided by 1000.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_set_amount_msat(this_ptr: &mut HTLCOutputInCommitment, mut val: u64) {
unsafe { &mut *this_ptr.inner }.amount_msat = val;
}
/// The CLTV lock-time at which this HTLC expires.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_get_cltv_expiry(this_ptr: &HTLCOutputInCommitment) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.cltv_expiry;
(*inner_val)
}
/// The CLTV lock-time at which this HTLC expires.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_set_cltv_expiry(this_ptr: &mut HTLCOutputInCommitment, mut val: u32) {
unsafe { &mut *this_ptr.inner }.cltv_expiry = val;
}
/// The hash of the preimage which unlocks this HTLC.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_get_payment_hash(this_ptr: &HTLCOutputInCommitment) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.payment_hash;
&(*inner_val).0
}
/// The hash of the preimage which unlocks this HTLC.
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_set_payment_hash(this_ptr: &mut HTLCOutputInCommitment, mut val: crate::c_types::ThirtyTwoBytes) {
unsafe { &mut *this_ptr.inner }.payment_hash = ::lightning::ln::channelmanager::PaymentHash(val.data);
}
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_write(obj: *const HTLCOutputInCommitment) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn HTLCOutputInCommitment_read(ser: crate::c_types::u8slice) -> HTLCOutputInCommitment {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
HTLCOutputInCommitment { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
HTLCOutputInCommitment { inner: std::ptr::null_mut(), is_owned: true }
}
}
/// note here that 'a_revocation_key' is generated using b_revocation_basepoint and a's
/// commitment secret. 'htlc' does *not* need to have its previous_output_index filled.
#[no_mangle]
pub extern "C" fn get_htlc_redeemscript(htlc: &crate::ln::chan_utils::HTLCOutputInCommitment, keys: &crate::ln::chan_utils::TxCreationKeys) -> crate::c_types::derived::CVec_u8Z {
let mut ret = lightning::ln::chan_utils::get_htlc_redeemscript(unsafe { &*htlc.inner }, unsafe { &*keys.inner });
ret.into_bytes().into()
}
/// Gets the redeemscript for a funding output from the two funding public keys.
/// Note that the order of funding public keys does not matter.
#[no_mangle]
pub extern "C" fn make_funding_redeemscript(a: crate::c_types::PublicKey, b: crate::c_types::PublicKey) -> crate::c_types::derived::CVec_u8Z {
let mut ret = lightning::ln::chan_utils::make_funding_redeemscript(&a.into_rust(), &b.into_rust());
ret.into_bytes().into()
}
/// panics if htlc.transaction_output_index.is_none()!
#[no_mangle]
pub extern "C" fn build_htlc_transaction(prev_hash: *const [u8; 32], mut feerate_per_kw: u32, mut to_self_delay: u16, htlc: &crate::ln::chan_utils::HTLCOutputInCommitment, a_delayed_payment_key: crate::c_types::PublicKey, revocation_key: crate::c_types::PublicKey) -> crate::c_types::derived::CVec_u8Z {
let mut ret = lightning::ln::chan_utils::build_htlc_transaction(&::bitcoin::hash_types::Txid::from_slice(&unsafe { &*prev_hash }[..]).unwrap(), feerate_per_kw, to_self_delay, unsafe { &*htlc.inner }, &a_delayed_payment_key.into_rust(), &revocation_key.into_rust());
let mut local_ret = ::bitcoin::consensus::encode::serialize(&ret);
local_ret.into()
}
use lightning::ln::chan_utils::LocalCommitmentTransaction as nativeLocalCommitmentTransactionImport;
type nativeLocalCommitmentTransaction = nativeLocalCommitmentTransactionImport;
/// We use this to track local commitment transactions and put off signing them until we are ready
/// to broadcast. This class can be used inside a signer implementation to generate a signature
/// given the relevant secret key.
#[must_use]
#[repr(C)]
pub struct LocalCommitmentTransaction {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeLocalCommitmentTransaction,
pub is_owned: bool,
}
impl Drop for LocalCommitmentTransaction {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_free(this_ptr: LocalCommitmentTransaction) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn LocalCommitmentTransaction_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeLocalCommitmentTransaction); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl LocalCommitmentTransaction {
pub(crate) fn take_ptr(mut self) -> *mut nativeLocalCommitmentTransaction {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for LocalCommitmentTransaction {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn LocalCommitmentTransaction_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeLocalCommitmentTransaction)).clone() })) as *mut c_void
}
/// The commitment transaction itself, in unsigned form.
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_get_unsigned_tx(this_ptr: &LocalCommitmentTransaction) -> crate::c_types::derived::CVec_u8Z {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.unsigned_tx;
let mut local_inner_val = ::bitcoin::consensus::encode::serialize(inner_val);
local_inner_val.into()
}
/// The commitment transaction itself, in unsigned form.
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_set_unsigned_tx(this_ptr: &mut LocalCommitmentTransaction, mut val: crate::c_types::derived::CVec_u8Z) {
unsafe { &mut *this_ptr.inner }.unsigned_tx = ::bitcoin::consensus::encode::deserialize(&val.into_rust()[..]).unwrap();
}
/// Our counterparty's signature for the transaction, above.
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_get_their_sig(this_ptr: &LocalCommitmentTransaction) -> crate::c_types::Signature {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.their_sig;
crate::c_types::Signature::from_rust(&(*inner_val))
}
/// Our counterparty's signature for the transaction, above.
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_set_their_sig(this_ptr: &mut LocalCommitmentTransaction, mut val: crate::c_types::Signature) {
unsafe { &mut *this_ptr.inner }.their_sig = val.into_rust();
}
/// The feerate paid per 1000-weight-unit in this commitment transaction. This value is
/// controlled by the channel initiator.
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_get_feerate_per_kw(this_ptr: &LocalCommitmentTransaction) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.feerate_per_kw;
(*inner_val)
}
/// The feerate paid per 1000-weight-unit in this commitment transaction. This value is
/// controlled by the channel initiator.
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_set_feerate_per_kw(this_ptr: &mut LocalCommitmentTransaction, mut val: u32) {
unsafe { &mut *this_ptr.inner }.feerate_per_kw = val;
}
/// The HTLCs and remote htlc signatures which were included in this commitment transaction.
///
/// Note that this includes all HTLCs, including ones which were considered dust and not
/// actually included in the transaction as it appears on-chain, but who's value is burned as
/// fees and not included in the to_local or to_remote outputs.
///
/// The remote HTLC signatures in the second element will always be set for non-dust HTLCs, ie
/// those for which transaction_output_index.is_some().
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_set_per_htlc(this_ptr: &mut LocalCommitmentTransaction, mut val: crate::c_types::derived::CVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ) {
let mut local_val = Vec::new(); for mut item in val.into_rust().drain(..) { local_val.push( { let (mut orig_val_0_0, mut orig_val_0_1) = item.to_rust(); let mut local_orig_val_0_1 = if orig_val_0_1.is_null() { None } else { Some( { orig_val_0_1.into_rust() }) }; let mut local_val_0 = (*unsafe { Box::from_raw(orig_val_0_0.take_ptr()) }, local_orig_val_0_1); local_val_0 }); };
unsafe { &mut *this_ptr.inner }.per_htlc = local_val;
}
/// Generate a new LocalCommitmentTransaction based on a raw commitment transaction,
/// remote signature and both parties keys.
///
/// The unsigned transaction outputs must be consistent with htlc_data. This function
/// only checks that the shape and amounts are consistent, but does not check the scriptPubkey.
#[must_use]
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_new_missing_local_sig(mut unsigned_tx: crate::c_types::derived::CVec_u8Z, mut their_sig: crate::c_types::Signature, our_funding_key: crate::c_types::PublicKey, their_funding_key: crate::c_types::PublicKey, mut local_keys: crate::ln::chan_utils::TxCreationKeys, mut feerate_per_kw: u32, mut htlc_data: crate::c_types::derived::CVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ) -> crate::ln::chan_utils::LocalCommitmentTransaction {
let mut local_htlc_data = Vec::new(); for mut item in htlc_data.into_rust().drain(..) { local_htlc_data.push( { let (mut orig_htlc_data_0_0, mut orig_htlc_data_0_1) = item.to_rust(); let mut local_orig_htlc_data_0_1 = if orig_htlc_data_0_1.is_null() { None } else { Some( { orig_htlc_data_0_1.into_rust() }) }; let mut local_htlc_data_0 = (*unsafe { Box::from_raw(orig_htlc_data_0_0.take_ptr()) }, local_orig_htlc_data_0_1); local_htlc_data_0 }); };
let mut ret = lightning::ln::chan_utils::LocalCommitmentTransaction::new_missing_local_sig(::bitcoin::consensus::encode::deserialize(&unsigned_tx.into_rust()[..]).unwrap(), their_sig.into_rust(), &our_funding_key.into_rust(), &their_funding_key.into_rust(), *unsafe { Box::from_raw(local_keys.take_ptr()) }, feerate_per_kw, local_htlc_data);
crate::ln::chan_utils::LocalCommitmentTransaction { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// The pre-calculated transaction creation public keys.
/// An external validating signer should not trust these keys.
#[must_use]
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_trust_key_derivation(this_arg: &LocalCommitmentTransaction) -> crate::ln::chan_utils::TxCreationKeys {
let mut ret = unsafe { &*this_arg.inner }.trust_key_derivation();
crate::ln::chan_utils::TxCreationKeys { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false }
}
/// Get the txid of the local commitment transaction contained in this
/// LocalCommitmentTransaction
#[must_use]
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_txid(this_arg: &LocalCommitmentTransaction) -> crate::c_types::ThirtyTwoBytes {
let mut ret = unsafe { &*this_arg.inner }.txid();
crate::c_types::ThirtyTwoBytes { data: ret.into_inner() }
}
/// Gets our signature for the contained commitment transaction given our funding private key.
///
/// Funding key is your key included in the 2-2 funding_outpoint lock. Should be provided
/// by your ChannelKeys.
/// Funding redeemscript is script locking funding_outpoint. This is the mutlsig script
/// between your own funding key and your counterparty's. Currently, this is provided in
/// ChannelKeys::sign_local_commitment() calls directly.
/// Channel value is amount locked in funding_outpoint.
#[must_use]
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_get_local_sig(this_arg: &LocalCommitmentTransaction, funding_key: *const [u8; 32], funding_redeemscript: crate::c_types::u8slice, mut channel_value_satoshis: u64) -> crate::c_types::Signature {
let mut ret = unsafe { &*this_arg.inner }.get_local_sig(&::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *funding_key}[..]).unwrap(), &::bitcoin::blockdata::script::Script::from(Vec::from(funding_redeemscript.to_slice())), channel_value_satoshis, &bitcoin::secp256k1::Secp256k1::new());
crate::c_types::Signature::from_rust(&ret)
}
/// Get a signature for each HTLC which was included in the commitment transaction (ie for
/// which HTLCOutputInCommitment::transaction_output_index.is_some()).
///
/// The returned Vec has one entry for each HTLC, and in the same order. For HTLCs which were
/// considered dust and not included, a None entry exists, for all others a signature is
/// included.
#[must_use]
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_get_htlc_sigs(this_arg: &LocalCommitmentTransaction, htlc_base_key: *const [u8; 32], mut local_csv: u16) -> crate::c_types::derived::CResult_CVec_SignatureZNoneZ {
let mut ret = unsafe { &*this_arg.inner }.get_htlc_sigs(&::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *htlc_base_key}[..]).unwrap(), local_csv, &bitcoin::secp256k1::Secp256k1::new());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { let mut local_ret_0 = Vec::new(); for item in o.drain(..) { local_ret_0.push( { let mut local_ret_0_0 = if item.is_none() { crate::c_types::Signature::null() } else { { crate::c_types::Signature::from_rust(&(item.unwrap())) } }; local_ret_0_0 }); }; local_ret_0.into() }), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }) };
local_ret
}
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_write(obj: *const LocalCommitmentTransaction) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn LocalCommitmentTransaction_read(ser: crate::c_types::u8slice) -> LocalCommitmentTransaction {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
LocalCommitmentTransaction { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
LocalCommitmentTransaction { inner: std::ptr::null_mut(), is_owned: true }
}
}

View file

@ -0,0 +1,842 @@
//! The top-level channel management and payment tracking stuff lives here.
//!
//! The ChannelManager is the main chunk of logic implementing the lightning protocol and is
//! responsible for tracking which channels are open, HTLCs are in flight and reestablishing those
//! upon reconnect to the relevant peer(s).
//!
//! It does not manage routing logic (see routing::router::get_route for that) nor does it manage constructing
//! on-chain transactions (it only monitors the chain to watch for any force-closes that might
//! imply it needs to fail HTLCs/payments/channels it manages).
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::ln::channelmanager::ChannelManager as nativeChannelManagerImport;
type nativeChannelManager = nativeChannelManagerImport<crate::chain::keysinterface::ChannelKeys, crate::ln::channelmonitor::ManyChannelMonitor, crate::chain::chaininterface::BroadcasterInterface, crate::chain::keysinterface::KeysInterface, crate::chain::chaininterface::FeeEstimator, crate::util::logger::Logger>;
/// Manager which keeps track of a number of channels and sends messages to the appropriate
/// channel, also tracking HTLC preimages and forwarding onion packets appropriately.
///
/// Implements ChannelMessageHandler, handling the multi-channel parts and passing things through
/// to individual Channels.
///
/// Implements Writeable to write out all channel state to disk. Implies peer_disconnected() for
/// all peers during write/read (though does not modify this instance, only the instance being
/// serialized). This will result in any channels which have not yet exchanged funding_created (ie
/// called funding_transaction_generated for outbound channels).
///
/// Note that you can be a bit lazier about writing out ChannelManager than you can be with
/// ChannelMonitors. With ChannelMonitors you MUST write each monitor update out to disk before
/// returning from ManyChannelMonitor::add_/update_monitor, with ChannelManagers, writing updates
/// happens out-of-band (and will prevent any other ChannelManager operations from occurring during
/// the serialization process). If the deserialized version is out-of-date compared to the
/// ChannelMonitors passed by reference to read(), those channels will be force-closed based on the
/// ChannelMonitor state and no funds will be lost (mod on-chain transaction fees).
///
/// Note that the deserializer is only implemented for (Sha256dHash, ChannelManager), which
/// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
/// the \"reorg path\" (ie call block_disconnected() until you get to a common block and then call
/// block_connected() to step towards your best block) upon deserialization before using the
/// object!
///
/// Note that ChannelManager is responsible for tracking liveness of its channels and generating
/// ChannelUpdate messages informing peers that the channel is temporarily disabled. To avoid
/// spam due to quick disconnection/reconnection, updates are not sent until the channel has been
/// offline for a full minute. In order to track this, you must call
/// timer_chan_freshness_every_min roughly once per minute, though it doesn't have to be perfect.
///
/// Rather than using a plain ChannelManager, it is preferable to use either a SimpleArcChannelManager
/// a SimpleRefChannelManager, for conciseness. See their documentation for more details, but
/// essentially you should default to using a SimpleRefChannelManager, and use a
/// SimpleArcChannelManager when you require a ChannelManager with a static lifetime, such as when
/// you're using lightning-net-tokio.
#[must_use]
#[repr(C)]
pub struct ChannelManager {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelManager,
pub is_owned: bool,
}
impl Drop for ChannelManager {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelManager_free(this_ptr: ChannelManager) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelManager_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelManager); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelManager {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelManager {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::ln::channelmanager::ChannelDetails as nativeChannelDetailsImport;
type nativeChannelDetails = nativeChannelDetailsImport;
/// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
#[must_use]
#[repr(C)]
pub struct ChannelDetails {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelDetails,
pub is_owned: bool,
}
impl Drop for ChannelDetails {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelDetails_free(this_ptr: ChannelDetails) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelDetails_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelDetails); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelDetails {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelDetails {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
/// thereafter this is the txid of the funding transaction xor the funding transaction output).
/// Note that this means this value is *not* persistent - it can change once during the
/// lifetime of the channel.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_channel_id(this_ptr: &ChannelDetails) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.channel_id;
&(*inner_val)
}
/// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
/// thereafter this is the txid of the funding transaction xor the funding transaction output).
/// Note that this means this value is *not* persistent - it can change once during the
/// lifetime of the channel.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_channel_id(this_ptr: &mut ChannelDetails, mut val: crate::c_types::ThirtyTwoBytes) {
unsafe { &mut *this_ptr.inner }.channel_id = val.data;
}
/// The node_id of our counterparty
#[no_mangle]
pub extern "C" fn ChannelDetails_get_remote_network_id(this_ptr: &ChannelDetails) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.remote_network_id;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The node_id of our counterparty
#[no_mangle]
pub extern "C" fn ChannelDetails_set_remote_network_id(this_ptr: &mut ChannelDetails, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.remote_network_id = val.into_rust();
}
/// The Features the channel counterparty provided upon last connection.
/// Useful for routing as it is the most up-to-date copy of the counterparty's features and
/// many routing-relevant features are present in the init context.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_counterparty_features(this_ptr: &ChannelDetails) -> crate::ln::features::InitFeatures {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.counterparty_features;
crate::ln::features::InitFeatures { inner: &mut (*inner_val), is_owned: false }
}
/// The Features the channel counterparty provided upon last connection.
/// Useful for routing as it is the most up-to-date copy of the counterparty's features and
/// many routing-relevant features are present in the init context.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_counterparty_features(this_ptr: &mut ChannelDetails, mut val: crate::ln::features::InitFeatures) {
unsafe { &mut *this_ptr.inner }.counterparty_features = *unsafe { Box::from_raw(val.take_ptr()) };
}
/// The value, in satoshis, of this channel as appears in the funding output
#[no_mangle]
pub extern "C" fn ChannelDetails_get_channel_value_satoshis(this_ptr: &ChannelDetails) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.channel_value_satoshis;
(*inner_val)
}
/// The value, in satoshis, of this channel as appears in the funding output
#[no_mangle]
pub extern "C" fn ChannelDetails_set_channel_value_satoshis(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.channel_value_satoshis = val;
}
/// The user_id passed in to create_channel, or 0 if the channel was inbound.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_user_id(this_ptr: &ChannelDetails) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.user_id;
(*inner_val)
}
/// The user_id passed in to create_channel, or 0 if the channel was inbound.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_user_id(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.user_id = val;
}
/// The available outbound capacity for sending HTLCs to the remote peer. This does not include
/// any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
/// available for inclusion in new outbound HTLCs). This further does not include any pending
/// outgoing HTLCs which are awaiting some other resolution to be sent.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_outbound_capacity_msat(this_ptr: &ChannelDetails) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.outbound_capacity_msat;
(*inner_val)
}
/// The available outbound capacity for sending HTLCs to the remote peer. This does not include
/// any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
/// available for inclusion in new outbound HTLCs). This further does not include any pending
/// outgoing HTLCs which are awaiting some other resolution to be sent.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_outbound_capacity_msat(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.outbound_capacity_msat = val;
}
/// The available inbound capacity for the remote peer to send HTLCs to us. This does not
/// include any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
/// available for inclusion in new inbound HTLCs).
/// Note that there are some corner cases not fully handled here, so the actual available
/// inbound capacity may be slightly higher than this.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_inbound_capacity_msat(this_ptr: &ChannelDetails) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.inbound_capacity_msat;
(*inner_val)
}
/// The available inbound capacity for the remote peer to send HTLCs to us. This does not
/// include any pending HTLCs which are not yet fully resolved (and, thus, who's balance is not
/// available for inclusion in new inbound HTLCs).
/// Note that there are some corner cases not fully handled here, so the actual available
/// inbound capacity may be slightly higher than this.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_inbound_capacity_msat(this_ptr: &mut ChannelDetails, mut val: u64) {
unsafe { &mut *this_ptr.inner }.inbound_capacity_msat = val;
}
/// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
/// the peer is connected, and (c) no monitor update failure is pending resolution.
#[no_mangle]
pub extern "C" fn ChannelDetails_get_is_live(this_ptr: &ChannelDetails) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.is_live;
(*inner_val)
}
/// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
/// the peer is connected, and (c) no monitor update failure is pending resolution.
#[no_mangle]
pub extern "C" fn ChannelDetails_set_is_live(this_ptr: &mut ChannelDetails, mut val: bool) {
unsafe { &mut *this_ptr.inner }.is_live = val;
}
use lightning::ln::channelmanager::PaymentSendFailure as nativePaymentSendFailureImport;
type nativePaymentSendFailure = nativePaymentSendFailureImport;
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
/// Err() type describing which state the payment is in, see the description of individual enum
/// states for more.
#[must_use]
#[repr(C)]
pub struct PaymentSendFailure {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativePaymentSendFailure,
pub is_owned: bool,
}
impl Drop for PaymentSendFailure {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn PaymentSendFailure_free(this_ptr: PaymentSendFailure) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn PaymentSendFailure_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativePaymentSendFailure); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl PaymentSendFailure {
pub(crate) fn take_ptr(mut self) -> *mut nativePaymentSendFailure {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Constructs a new ChannelManager to hold several channels and route between them.
///
/// This is the main \"logic hub\" for all channel-related actions, and implements
/// ChannelMessageHandler.
///
/// Non-proportional fees are fixed according to our risk using the provided fee estimator.
///
/// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
///
/// Users must provide the current blockchain height from which to track onchain channel
/// funding outpoints and send payments with reliable timelocks.
///
/// Users need to notify the new ChannelManager when a new block is connected or
/// disconnected using its `block_connected` and `block_disconnected` methods.
/// However, rather than calling these methods directly, the user should register
/// the ChannelManager as a listener to the BlockNotifier and call the BlockNotifier's
/// `block_(dis)connected` methods, which will notify all registered listeners in one
/// go.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_new(mut network: crate::bitcoin::network::Network, mut fee_est: crate::chain::chaininterface::FeeEstimator, mut monitor: crate::ln::channelmonitor::ManyChannelMonitor, mut tx_broadcaster: crate::chain::chaininterface::BroadcasterInterface, mut logger: crate::util::logger::Logger, mut keys_manager: crate::chain::keysinterface::KeysInterface, mut config: crate::util::config::UserConfig, mut current_blockchain_height: usize) -> ChannelManager {
let mut ret = lightning::ln::channelmanager::ChannelManager::new(network.into_bitcoin(), fee_est, monitor, tx_broadcaster, logger, keys_manager, *unsafe { Box::from_raw(config.take_ptr()) }, current_blockchain_height);
ChannelManager { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Creates a new outbound channel to the given remote node and with the given value.
///
/// user_id will be provided back as user_channel_id in FundingGenerationReady and
/// FundingBroadcastSafe events to allow tracking of which events correspond with which
/// create_channel call. Note that user_channel_id defaults to 0 for inbound channels, so you
/// may wish to avoid using 0 for user_id here.
///
/// If successful, will generate a SendOpenChannel message event, so you should probably poll
/// PeerManager::process_events afterwards.
///
/// Raises APIError::APIMisuseError when channel_value_satoshis > 2**24 or push_msat is
/// greater than channel_value_satoshis * 1k or channel_value_satoshis is < 1000.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_create_channel(this_arg: &ChannelManager, mut their_network_key: crate::c_types::PublicKey, mut channel_value_satoshis: u64, mut push_msat: u64, mut user_id: u64, mut override_config: crate::util::config::UserConfig) -> crate::c_types::derived::CResult_NoneAPIErrorZ {
let mut local_override_config = if override_config.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(override_config.take_ptr()) } }) };
let mut ret = unsafe { &*this_arg.inner }.create_channel(their_network_key.into_rust(), channel_value_satoshis, push_msat, user_id, local_override_config);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::util::errors::APIError::native_into(e) }) };
local_ret
}
/// Gets the list of open channels, in random order. See ChannelDetail field documentation for
/// more information.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_list_channels(this_arg: &ChannelManager) -> crate::c_types::derived::CVec_ChannelDetailsZ {
let mut ret = unsafe { &*this_arg.inner }.list_channels();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::ln::channelmanager::ChannelDetails { inner: Box::into_raw(Box::new(item)), is_owned: true } }); };
local_ret.into()
}
/// Gets the list of usable channels, in random order. Useful as an argument to
/// get_route to ensure non-announced channels are used.
///
/// These are guaranteed to have their is_live value set to true, see the documentation for
/// ChannelDetails::is_live for more info on exactly what the criteria are.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_list_usable_channels(this_arg: &ChannelManager) -> crate::c_types::derived::CVec_ChannelDetailsZ {
let mut ret = unsafe { &*this_arg.inner }.list_usable_channels();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::ln::channelmanager::ChannelDetails { inner: Box::into_raw(Box::new(item)), is_owned: true } }); };
local_ret.into()
}
/// Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs
/// will be accepted on the given channel, and after additional timeout/the closing of all
/// pending HTLCs, the channel will be closed on chain.
///
/// May generate a SendShutdown message event on success, which should be relayed.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_close_channel(this_arg: &ChannelManager, channel_id: *const [u8; 32]) -> crate::c_types::derived::CResult_NoneAPIErrorZ {
let mut ret = unsafe { &*this_arg.inner }.close_channel(unsafe { &*channel_id});
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::util::errors::APIError::native_into(e) }) };
local_ret
}
/// Force closes a channel, immediately broadcasting the latest local commitment transaction to
/// the chain and rejecting new HTLCs on the given channel.
#[no_mangle]
pub extern "C" fn ChannelManager_force_close_channel(this_arg: &ChannelManager, channel_id: *const [u8; 32]) {
unsafe { &*this_arg.inner }.force_close_channel(unsafe { &*channel_id})
}
/// Force close all channels, immediately broadcasting the latest local commitment transaction
/// for each to the chain and rejecting new HTLCs on each.
#[no_mangle]
pub extern "C" fn ChannelManager_force_close_all_channels(this_arg: &ChannelManager) {
unsafe { &*this_arg.inner }.force_close_all_channels()
}
/// Sends a payment along a given route.
///
/// Value parameters are provided via the last hop in route, see documentation for RouteHop
/// fields for more info.
///
/// Note that if the payment_hash already exists elsewhere (eg you're sending a duplicative
/// payment), we don't do anything to stop you! We always try to ensure that if the provided
/// next hop knows the preimage to payment_hash they can claim an additional amount as
/// specified in the last hop in the route! Thus, you should probably do your own
/// payment_preimage tracking (which you should already be doing as they represent \"proof of
/// payment\") and prevent double-sends yourself.
///
/// May generate SendHTLCs message(s) event on success, which should be relayed.
///
/// Each path may have a different return value, and PaymentSendValue may return a Vec with
/// each entry matching the corresponding-index entry in the route paths, see
/// PaymentSendFailure for more info.
///
/// In general, a path may raise:
/// * APIError::RouteError when an invalid route or forwarding parameter (cltv_delta, fee,
/// node public key) is specified.
/// * APIError::ChannelUnavailable if the next-hop channel is not available for updates
/// (including due to previous monitor update failure or new permanent monitor update
/// failure).
/// * APIError::MonitorUpdateFailed if a new monitor update failure prevented sending the
/// relevant updates.
///
/// Note that depending on the type of the PaymentSendFailure the HTLC may have been
/// irrevocably committed to on our end. In such a case, do NOT retry the payment with a
/// different route unless you intend to pay twice!
///
/// payment_secret is unrelated to payment_hash (or PaymentPreimage) and exists to authenticate
/// the sender to the recipient and prevent payment-probing (deanonymization) attacks. For
/// newer nodes, it will be provided to you in the invoice. If you do not have one, the Route
/// must not contain multiple paths as multi-path payments require a recipient-provided
/// payment_secret.
/// If a payment_secret *is* provided, we assume that the invoice had the payment_secret feature
/// bit set (either as required or as available). If multiple paths are present in the Route,
/// we assume the invoice had the basic_mpp feature set.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_send_payment(this_arg: &ChannelManager, route: &crate::routing::router::Route, mut payment_hash: crate::c_types::ThirtyTwoBytes, payment_secret: crate::c_types::ThirtyTwoBytes) -> crate::c_types::derived::CResult_NonePaymentSendFailureZ {
let mut local_payment_secret = if payment_secret.data == [0; 32] { None } else { Some( { ::lightning::ln::channelmanager::PaymentSecret(payment_secret.data) }) };
let mut ret = unsafe { &*this_arg.inner }.send_payment(unsafe { &*route.inner }, ::lightning::ln::channelmanager::PaymentHash(payment_hash.data), &local_payment_secret);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::channelmanager::PaymentSendFailure { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
/// Call this upon creation of a funding transaction for the given channel.
///
/// Note that ALL inputs in the transaction pointed to by funding_txo MUST spend SegWit outputs
/// or your counterparty can steal your funds!
///
/// Panics if a funding transaction has already been provided for this channel.
///
/// May panic if the funding_txo is duplicative with some other channel (note that this should
/// be trivially prevented by using unique funding transaction keys per-channel).
#[no_mangle]
pub extern "C" fn ChannelManager_funding_transaction_generated(this_arg: &ChannelManager, temporary_channel_id: *const [u8; 32], mut funding_txo: crate::chain::transaction::OutPoint) {
unsafe { &*this_arg.inner }.funding_transaction_generated(unsafe { &*temporary_channel_id}, *unsafe { Box::from_raw(funding_txo.take_ptr()) })
}
/// Generates a signed node_announcement from the given arguments and creates a
/// BroadcastNodeAnnouncement event. Note that such messages will be ignored unless peers have
/// seen a channel_announcement from us (ie unless we have public channels open).
///
/// RGB is a node \"color\" and alias is a printable human-readable string to describe this node
/// to humans. They carry no in-protocol meaning.
///
/// addresses represent the set (possibly empty) of socket addresses on which this node accepts
/// incoming connections. These will be broadcast to the network, publicly tying these
/// addresses together. If you wish to preserve user privacy, addresses should likely contain
/// only Tor Onion addresses.
///
/// Panics if addresses is absurdly large (more than 500).
#[no_mangle]
pub extern "C" fn ChannelManager_broadcast_node_announcement(this_arg: &ChannelManager, mut rgb: crate::c_types::ThreeBytes, mut alias: crate::c_types::ThirtyTwoBytes, mut addresses: crate::c_types::derived::CVec_NetAddressZ) {
let mut local_addresses = Vec::new(); for mut item in addresses.into_rust().drain(..) { local_addresses.push( { item.into_native() }); };
unsafe { &*this_arg.inner }.broadcast_node_announcement(rgb.data, alias.data, local_addresses)
}
/// Processes HTLCs which are pending waiting on random forward delay.
///
/// Should only really ever be called in response to a PendingHTLCsForwardable event.
/// Will likely generate further events.
#[no_mangle]
pub extern "C" fn ChannelManager_process_pending_htlc_forwards(this_arg: &ChannelManager) {
unsafe { &*this_arg.inner }.process_pending_htlc_forwards()
}
/// If a peer is disconnected we mark any channels with that peer as 'disabled'.
/// After some time, if channels are still disabled we need to broadcast a ChannelUpdate
/// to inform the network about the uselessness of these channels.
///
/// This method handles all the details, and must be called roughly once per minute.
#[no_mangle]
pub extern "C" fn ChannelManager_timer_chan_freshness_every_min(this_arg: &ChannelManager) {
unsafe { &*this_arg.inner }.timer_chan_freshness_every_min()
}
/// Indicates that the preimage for payment_hash is unknown or the received amount is incorrect
/// after a PaymentReceived event, failing the HTLC back to its origin and freeing resources
/// along the path (including in our own channel on which we received it).
/// Returns false if no payment was found to fail backwards, true if the process of failing the
/// HTLC backwards has been started.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_fail_htlc_backwards(this_arg: &ChannelManager, payment_hash: *const [u8; 32], payment_secret: crate::c_types::ThirtyTwoBytes) -> bool {
let mut local_payment_secret = if payment_secret.data == [0; 32] { None } else { Some( { ::lightning::ln::channelmanager::PaymentSecret(payment_secret.data) }) };
let mut ret = unsafe { &*this_arg.inner }.fail_htlc_backwards(&::lightning::ln::channelmanager::PaymentHash(unsafe { *payment_hash }), &local_payment_secret);
ret
}
/// Provides a payment preimage in response to a PaymentReceived event, returning true and
/// generating message events for the net layer to claim the payment, if possible. Thus, you
/// should probably kick the net layer to go send messages if this returns true!
///
/// You must specify the expected amounts for this HTLC, and we will only claim HTLCs
/// available within a few percent of the expected amount. This is critical for several
/// reasons : a) it avoids providing senders with `proof-of-payment` (in the form of the
/// payment_preimage without having provided the full value and b) it avoids certain
/// privacy-breaking recipient-probing attacks which may reveal payment activity to
/// motivated attackers.
///
/// Note that the privacy concerns in (b) are not relevant in payments with a payment_secret
/// set. Thus, for such payments we will claim any payments which do not under-pay.
///
/// May panic if called except in response to a PaymentReceived event.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_claim_funds(this_arg: &ChannelManager, mut payment_preimage: crate::c_types::ThirtyTwoBytes, payment_secret: crate::c_types::ThirtyTwoBytes, mut expected_amount: u64) -> bool {
let mut local_payment_secret = if payment_secret.data == [0; 32] { None } else { Some( { ::lightning::ln::channelmanager::PaymentSecret(payment_secret.data) }) };
let mut ret = unsafe { &*this_arg.inner }.claim_funds(::lightning::ln::channelmanager::PaymentPreimage(payment_preimage.data), &local_payment_secret, expected_amount);
ret
}
/// Gets the node_id held by this ChannelManager
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManager_get_our_node_id(this_arg: &ChannelManager) -> crate::c_types::PublicKey {
let mut ret = unsafe { &*this_arg.inner }.get_our_node_id();
crate::c_types::PublicKey::from_rust(&ret)
}
/// Restores a single, given channel to normal operation after a
/// ChannelMonitorUpdateErr::TemporaryFailure was returned from a channel monitor update
/// operation.
///
/// All ChannelMonitor updates up to and including highest_applied_update_id must have been
/// fully committed in every copy of the given channels' ChannelMonitors.
///
/// Note that there is no effect to calling with a highest_applied_update_id other than the
/// current latest ChannelMonitorUpdate and one call to this function after multiple
/// ChannelMonitorUpdateErr::TemporaryFailures is fine. The highest_applied_update_id field
/// exists largely only to prevent races between this and concurrent update_monitor calls.
///
/// Thus, the anticipated use is, at a high level:
/// 1) You register a ManyChannelMonitor with this ChannelManager,
/// 2) it stores each update to disk, and begins updating any remote (eg watchtower) copies of
/// said ChannelMonitors as it can, returning ChannelMonitorUpdateErr::TemporaryFailures
/// any time it cannot do so instantly,
/// 3) update(s) are applied to each remote copy of a ChannelMonitor,
/// 4) once all remote copies are updated, you call this function with the update_id that
/// completed, and once it is the latest the Channel will be re-enabled.
#[no_mangle]
pub extern "C" fn ChannelManager_channel_monitor_updated(this_arg: &ChannelManager, funding_txo: &crate::chain::transaction::OutPoint, mut highest_applied_update_id: u64) {
unsafe { &*this_arg.inner }.channel_monitor_updated(unsafe { &*funding_txo.inner }, highest_applied_update_id)
}
#[no_mangle]
pub extern "C" fn ChannelManager_as_MessageSendEventsProvider(this_arg: *const ChannelManager) -> crate::util::events::MessageSendEventsProvider {
crate::util::events::MessageSendEventsProvider {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
get_and_clear_pending_msg_events: ChannelManager_MessageSendEventsProvider_get_and_clear_pending_msg_events,
}
}
use lightning::util::events::MessageSendEventsProvider as MessageSendEventsProviderTraitImport;
#[must_use]
extern "C" fn ChannelManager_MessageSendEventsProvider_get_and_clear_pending_msg_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChannelManager) }.get_and_clear_pending_msg_events();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); };
local_ret.into()
}
#[no_mangle]
pub extern "C" fn ChannelManager_as_EventsProvider(this_arg: *const ChannelManager) -> crate::util::events::EventsProvider {
crate::util::events::EventsProvider {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
get_and_clear_pending_events: ChannelManager_EventsProvider_get_and_clear_pending_events,
}
}
use lightning::util::events::EventsProvider as EventsProviderTraitImport;
#[must_use]
extern "C" fn ChannelManager_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 nativeChannelManager) }.get_and_clear_pending_events();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::util::events::Event::native_into(item) }); };
local_ret.into()
}
#[no_mangle]
pub extern "C" fn ChannelManager_as_ChainListener(this_arg: *const ChannelManager) -> crate::chain::chaininterface::ChainListener {
crate::chain::chaininterface::ChainListener {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
block_connected: ChannelManager_ChainListener_block_connected,
block_disconnected: ChannelManager_ChainListener_block_disconnected,
}
}
use lightning::chain::chaininterface::ChainListener as ChainListenerTraitImport;
extern "C" fn ChannelManager_ChainListener_block_connected(this_arg: *const c_void, header: *const [u8; 80], mut height: u32, mut txn_matched: crate::c_types::derived::CVec_TransactionZ, mut indexes_of_txn_matched: crate::c_types::usizeslice) {
let mut local_txn_matched = Vec::new(); for mut item in txn_matched.into_rust().drain(..) { local_txn_matched.push( { ::bitcoin::consensus::encode::deserialize(&item.into_rust()[..]).unwrap() }); };
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.block_connected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height, &local_txn_matched.iter().collect::<Vec<_>>()[..], indexes_of_txn_matched.to_slice())
}
extern "C" fn ChannelManager_ChainListener_block_disconnected(this_arg: *const c_void, header: *const [u8; 80], unused_0: u32) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.block_disconnected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), unused_0)
}
#[no_mangle]
pub extern "C" fn ChannelManager_as_ChannelMessageHandler(this_arg: *const ChannelManager) -> crate::ln::msgs::ChannelMessageHandler {
crate::ln::msgs::ChannelMessageHandler {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
handle_open_channel: ChannelManager_ChannelMessageHandler_handle_open_channel,
handle_accept_channel: ChannelManager_ChannelMessageHandler_handle_accept_channel,
handle_funding_created: ChannelManager_ChannelMessageHandler_handle_funding_created,
handle_funding_signed: ChannelManager_ChannelMessageHandler_handle_funding_signed,
handle_funding_locked: ChannelManager_ChannelMessageHandler_handle_funding_locked,
handle_shutdown: ChannelManager_ChannelMessageHandler_handle_shutdown,
handle_closing_signed: ChannelManager_ChannelMessageHandler_handle_closing_signed,
handle_update_add_htlc: ChannelManager_ChannelMessageHandler_handle_update_add_htlc,
handle_update_fulfill_htlc: ChannelManager_ChannelMessageHandler_handle_update_fulfill_htlc,
handle_update_fail_htlc: ChannelManager_ChannelMessageHandler_handle_update_fail_htlc,
handle_update_fail_malformed_htlc: ChannelManager_ChannelMessageHandler_handle_update_fail_malformed_htlc,
handle_commitment_signed: ChannelManager_ChannelMessageHandler_handle_commitment_signed,
handle_revoke_and_ack: ChannelManager_ChannelMessageHandler_handle_revoke_and_ack,
handle_update_fee: ChannelManager_ChannelMessageHandler_handle_update_fee,
handle_announcement_signatures: ChannelManager_ChannelMessageHandler_handle_announcement_signatures,
peer_disconnected: ChannelManager_ChannelMessageHandler_peer_disconnected,
peer_connected: ChannelManager_ChannelMessageHandler_peer_connected,
handle_channel_reestablish: ChannelManager_ChannelMessageHandler_handle_channel_reestablish,
handle_error: ChannelManager_ChannelMessageHandler_handle_error,
MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
get_and_clear_pending_msg_events: ChannelManager_ChannelMessageHandler_get_and_clear_pending_msg_events,
},
}
}
use lightning::ln::msgs::ChannelMessageHandler as ChannelMessageHandlerTraitImport;
extern "C" fn ChannelManager_ChannelMessageHandler_handle_open_channel(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, mut their_features: crate::ln::features::InitFeatures, msg: &crate::ln::msgs::OpenChannel) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_open_channel(&their_node_id.into_rust(), *unsafe { Box::from_raw(their_features.take_ptr()) }, unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_accept_channel(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, mut their_features: crate::ln::features::InitFeatures, msg: &crate::ln::msgs::AcceptChannel) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_accept_channel(&their_node_id.into_rust(), *unsafe { Box::from_raw(their_features.take_ptr()) }, unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_funding_created(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::FundingCreated) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_funding_created(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_funding_signed(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::FundingSigned) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_funding_signed(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_funding_locked(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::FundingLocked) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_funding_locked(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_shutdown(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::Shutdown) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_shutdown(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_closing_signed(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ClosingSigned) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_closing_signed(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_update_add_htlc(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::UpdateAddHTLC) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_update_add_htlc(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_update_fulfill_htlc(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::UpdateFulfillHTLC) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_update_fulfill_htlc(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_update_fail_htlc(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::UpdateFailHTLC) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_update_fail_htlc(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_update_fail_malformed_htlc(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::UpdateFailMalformedHTLC) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_update_fail_malformed_htlc(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_commitment_signed(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::CommitmentSigned) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_commitment_signed(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_revoke_and_ack(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::RevokeAndACK) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_revoke_and_ack(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_update_fee(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::UpdateFee) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_update_fee(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_announcement_signatures(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::AnnouncementSignatures) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_announcement_signatures(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_channel_reestablish(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ChannelReestablish) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_channel_reestablish(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_peer_disconnected(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, mut no_connection_possible: bool) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.peer_disconnected(&their_node_id.into_rust(), no_connection_possible)
}
extern "C" fn ChannelManager_ChannelMessageHandler_peer_connected(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, init_msg: &crate::ln::msgs::Init) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.peer_connected(&their_node_id.into_rust(), unsafe { &*init_msg.inner })
}
extern "C" fn ChannelManager_ChannelMessageHandler_handle_error(this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ErrorMessage) {
unsafe { &mut *(this_arg as *mut nativeChannelManager) }.handle_error(&their_node_id.into_rust(), unsafe { &*msg.inner })
}
use lightning::util::events::MessageSendEventsProvider as nativeMessageSendEventsProviderTrait;
#[must_use]
extern "C" fn ChannelManager_ChannelMessageHandler_get_and_clear_pending_msg_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeChannelManager) }.get_and_clear_pending_msg_events();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); };
local_ret.into()
}
use lightning::ln::channelmanager::ChannelManagerReadArgs as nativeChannelManagerReadArgsImport;
type nativeChannelManagerReadArgs = nativeChannelManagerReadArgsImport<'static, crate::chain::keysinterface::ChannelKeys, crate::ln::channelmonitor::ManyChannelMonitor, crate::chain::chaininterface::BroadcasterInterface, crate::chain::keysinterface::KeysInterface, crate::chain::chaininterface::FeeEstimator, crate::util::logger::Logger>;
/// Arguments for the creation of a ChannelManager that are not deserialized.
///
/// At a high-level, the process for deserializing a ChannelManager and resuming normal operation
/// is:
/// 1) Deserialize all stored ChannelMonitors.
/// 2) Deserialize the ChannelManager by filling in this struct and calling <(Sha256dHash,
/// ChannelManager)>::read(reader, args).
/// This may result in closing some Channels if the ChannelMonitor is newer than the stored
/// ChannelManager state to ensure no loss of funds. Thus, transactions may be broadcasted.
/// 3) Register all relevant ChannelMonitor outpoints with your chain watch mechanism using
/// ChannelMonitor::get_monitored_outpoints and ChannelMonitor::get_funding_txo().
/// 4) Reconnect blocks on your ChannelMonitors.
/// 5) Move the ChannelMonitors into your local ManyChannelMonitor.
/// 6) Disconnect/connect blocks on the ChannelManager.
/// 7) Register the new ChannelManager with your ChainWatchInterface.
#[must_use]
#[repr(C)]
pub struct ChannelManagerReadArgs {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelManagerReadArgs,
pub is_owned: bool,
}
impl Drop for ChannelManagerReadArgs {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_free(this_ptr: ChannelManagerReadArgs) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelManagerReadArgs_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelManagerReadArgs); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelManagerReadArgs {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelManagerReadArgs {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// The keys provider which will give us relevant keys. Some keys will be loaded during
/// deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_get_keys_manager(this_ptr: &ChannelManagerReadArgs) -> *const crate::chain::keysinterface::KeysInterface {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.keys_manager;
&(*inner_val)
}
/// The keys provider which will give us relevant keys. Some keys will be loaded during
/// deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_set_keys_manager(this_ptr: &mut ChannelManagerReadArgs, mut val: crate::chain::keysinterface::KeysInterface) {
unsafe { &mut *this_ptr.inner }.keys_manager = val;
}
/// The fee_estimator for use in the ChannelManager in the future.
///
/// No calls to the FeeEstimator will be made during deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_get_fee_estimator(this_ptr: &ChannelManagerReadArgs) -> *const crate::chain::chaininterface::FeeEstimator {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fee_estimator;
&(*inner_val)
}
/// The fee_estimator for use in the ChannelManager in the future.
///
/// No calls to the FeeEstimator will be made during deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_set_fee_estimator(this_ptr: &mut ChannelManagerReadArgs, mut val: crate::chain::chaininterface::FeeEstimator) {
unsafe { &mut *this_ptr.inner }.fee_estimator = val;
}
/// The ManyChannelMonitor for use in the ChannelManager in the future.
///
/// No calls to the ManyChannelMonitor will be made during deserialization. It is assumed that
/// you have deserialized ChannelMonitors separately and will add them to your
/// ManyChannelMonitor after deserializing this ChannelManager.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_get_monitor(this_ptr: &ChannelManagerReadArgs) -> *const crate::ln::channelmonitor::ManyChannelMonitor {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.monitor;
&(*inner_val)
}
/// The ManyChannelMonitor for use in the ChannelManager in the future.
///
/// No calls to the ManyChannelMonitor will be made during deserialization. It is assumed that
/// you have deserialized ChannelMonitors separately and will add them to your
/// ManyChannelMonitor after deserializing this ChannelManager.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_set_monitor(this_ptr: &mut ChannelManagerReadArgs, mut val: crate::ln::channelmonitor::ManyChannelMonitor) {
unsafe { &mut *this_ptr.inner }.monitor = val;
}
/// The BroadcasterInterface which will be used in the ChannelManager in the future and may be
/// used to broadcast the latest local commitment transactions of channels which must be
/// force-closed during deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_get_tx_broadcaster(this_ptr: &ChannelManagerReadArgs) -> *const crate::chain::chaininterface::BroadcasterInterface {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.tx_broadcaster;
&(*inner_val)
}
/// The BroadcasterInterface which will be used in the ChannelManager in the future and may be
/// used to broadcast the latest local commitment transactions of channels which must be
/// force-closed during deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_set_tx_broadcaster(this_ptr: &mut ChannelManagerReadArgs, mut val: crate::chain::chaininterface::BroadcasterInterface) {
unsafe { &mut *this_ptr.inner }.tx_broadcaster = val;
}
/// The Logger for use in the ChannelManager and which may be used to log information during
/// deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_get_logger(this_ptr: &ChannelManagerReadArgs) -> *const crate::util::logger::Logger {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.logger;
&(*inner_val)
}
/// The Logger for use in the ChannelManager and which may be used to log information during
/// deserialization.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_set_logger(this_ptr: &mut ChannelManagerReadArgs, mut val: crate::util::logger::Logger) {
unsafe { &mut *this_ptr.inner }.logger = val;
}
/// Default settings used for new channels. Any existing channels will continue to use the
/// runtime settings which were stored when the ChannelManager was serialized.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_get_default_config(this_ptr: &ChannelManagerReadArgs) -> crate::util::config::UserConfig {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.default_config;
crate::util::config::UserConfig { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false }
}
/// Default settings used for new channels. Any existing channels will continue to use the
/// runtime settings which were stored when the ChannelManager was serialized.
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_set_default_config(this_ptr: &mut ChannelManagerReadArgs, mut val: crate::util::config::UserConfig) {
unsafe { &mut *this_ptr.inner }.default_config = *unsafe { Box::from_raw(val.take_ptr()) };
}
/// Simple utility function to create a ChannelManagerReadArgs which creates the monitor
/// HashMap for you. This is primarily useful for C bindings where it is not practical to
/// populate a HashMap directly from C.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelManagerReadArgs_new(mut keys_manager: crate::chain::keysinterface::KeysInterface, mut fee_estimator: crate::chain::chaininterface::FeeEstimator, mut monitor: crate::ln::channelmonitor::ManyChannelMonitor, mut tx_broadcaster: crate::chain::chaininterface::BroadcasterInterface, mut logger: crate::util::logger::Logger, mut default_config: crate::util::config::UserConfig, mut channel_monitors: crate::c_types::derived::CVec_ChannelMonitorZ) -> ChannelManagerReadArgs {
let mut local_channel_monitors = Vec::new(); for mut item in channel_monitors.into_rust().drain(..) { local_channel_monitors.push( { unsafe { &mut *item.inner } }); };
let mut ret = lightning::ln::channelmanager::ChannelManagerReadArgs::new(keys_manager, fee_estimator, monitor, tx_broadcaster, logger, *unsafe { Box::from_raw(default_config.take_ptr()) }, local_channel_monitors);
ChannelManagerReadArgs { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}

View file

@ -0,0 +1,550 @@
//! The logic to monitor for on-chain transactions and create the relevant claim responses lives
//! here.
//!
//! ChannelMonitor objects are generated by ChannelManager in response to relevant
//! messages/actions, and MUST be persisted to disk (and, preferably, remotely) before progress can
//! be made in responding to certain messages, see ManyChannelMonitor for more.
//!
//! Note that ChannelMonitors are an important part of the lightning trust model and a copy of the
//! latest ChannelMonitor must always be actively monitoring for chain updates (and no out-of-date
//! ChannelMonitors should do so). Thus, if you're building rust-lightning into an HSM or other
//! security-domain-separated system design, you should consider having multiple paths for
//! ChannelMonitors to get out of the HSM and onto monitoring devices.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::ln::channelmonitor::ChannelMonitorUpdate as nativeChannelMonitorUpdateImport;
type nativeChannelMonitorUpdate = nativeChannelMonitorUpdateImport;
/// An update generated by the underlying Channel itself which contains some new information the
/// ChannelMonitor should be made aware of.
#[must_use]
#[repr(C)]
pub struct ChannelMonitorUpdate {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelMonitorUpdate,
pub is_owned: bool,
}
impl Drop for ChannelMonitorUpdate {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelMonitorUpdate_free(this_ptr: ChannelMonitorUpdate) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelMonitorUpdate_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelMonitorUpdate); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelMonitorUpdate {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelMonitorUpdate {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for ChannelMonitorUpdate {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn ChannelMonitorUpdate_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelMonitorUpdate)).clone() })) as *mut c_void
}
/// The sequence number of this update. Updates *must* be replayed in-order according to this
/// sequence number (and updates may panic if they are not). The update_id values are strictly
/// increasing and increase by one for each new update.
///
/// This sequence number is also used to track up to which points updates which returned
/// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given
/// ChannelMonitor when ChannelManager::channel_monitor_updated is called.
#[no_mangle]
pub extern "C" fn ChannelMonitorUpdate_get_update_id(this_ptr: &ChannelMonitorUpdate) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.update_id;
(*inner_val)
}
/// The sequence number of this update. Updates *must* be replayed in-order according to this
/// sequence number (and updates may panic if they are not). The update_id values are strictly
/// increasing and increase by one for each new update.
///
/// This sequence number is also used to track up to which points updates which returned
/// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given
/// ChannelMonitor when ChannelManager::channel_monitor_updated is called.
#[no_mangle]
pub extern "C" fn ChannelMonitorUpdate_set_update_id(this_ptr: &mut ChannelMonitorUpdate, mut val: u64) {
unsafe { &mut *this_ptr.inner }.update_id = val;
}
#[no_mangle]
pub extern "C" fn ChannelMonitorUpdate_write(obj: *const ChannelMonitorUpdate) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn ChannelMonitorUpdate_read(ser: crate::c_types::u8slice) -> ChannelMonitorUpdate {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
ChannelMonitorUpdate { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
ChannelMonitorUpdate { inner: std::ptr::null_mut(), is_owned: true }
}
}
/// An error enum representing a failure to persist a channel monitor update.
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum ChannelMonitorUpdateErr {
/// Used to indicate a temporary failure (eg connection to a watchtower or remote backup of
/// our state failed, but is expected to succeed at some point in the future).
///
/// Such a failure will \"freeze\" a channel, preventing us from revoking old states or
/// submitting new commitment transactions to the remote party. Once the update(s) which failed
/// have been successfully applied, ChannelManager::channel_monitor_updated can be used to
/// restore the channel to an operational state.
///
/// Note that a given ChannelManager will *never* re-generate a given ChannelMonitorUpdate. If
/// you return a TemporaryFailure you must ensure that it is written to disk safely before
/// writing out the latest ChannelManager state.
///
/// Even when a channel has been \"frozen\" updates to the ChannelMonitor can continue to occur
/// (eg if an inbound HTLC which we forwarded was claimed upstream resulting in us attempting
/// to claim it on this channel) and those updates must be applied wherever they can be. At
/// least one such updated ChannelMonitor must be persisted otherwise PermanentFailure should
/// be returned to get things on-chain ASAP using only the in-memory copy. Obviously updates to
/// the channel which would invalidate previous ChannelMonitors are not made when a channel has
/// been \"frozen\".
///
/// Note that even if updates made after TemporaryFailure succeed you must still call
/// channel_monitor_updated to ensure you have the latest monitor and re-enable normal channel
/// operation.
///
/// Note that the update being processed here will not be replayed for you when you call
/// ChannelManager::channel_monitor_updated, so you must store the update itself along
/// with the persisted ChannelMonitor on your own local disk prior to returning a
/// TemporaryFailure. You may, of course, employ a journaling approach, storing only the
/// ChannelMonitorUpdate on disk without updating the monitor itself, replaying the journal at
/// reload-time.
///
/// For deployments where a copy of ChannelMonitors and other local state are backed up in a
/// remote location (with local copies persisted immediately), it is anticipated that all
/// updates will return TemporaryFailure until the remote copies could be updated.
TemporaryFailure,
/// Used to indicate no further channel monitor updates will be allowed (eg we've moved on to a
/// different watchtower and cannot update with all watchtowers that were previously informed
/// of this channel). This will force-close the channel in question (which will generate one
/// final ChannelMonitorUpdate which must be delivered to at least one ChannelMonitor copy).
///
/// Should also be used to indicate a failure to update the local persisted copy of the channel
/// monitor.
PermanentFailure,
}
use lightning::ln::channelmonitor::ChannelMonitorUpdateErr as nativeChannelMonitorUpdateErr;
impl ChannelMonitorUpdateErr {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeChannelMonitorUpdateErr {
match self {
ChannelMonitorUpdateErr::TemporaryFailure => nativeChannelMonitorUpdateErr::TemporaryFailure,
ChannelMonitorUpdateErr::PermanentFailure => nativeChannelMonitorUpdateErr::PermanentFailure,
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeChannelMonitorUpdateErr {
match self {
ChannelMonitorUpdateErr::TemporaryFailure => nativeChannelMonitorUpdateErr::TemporaryFailure,
ChannelMonitorUpdateErr::PermanentFailure => nativeChannelMonitorUpdateErr::PermanentFailure,
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeChannelMonitorUpdateErr) -> Self {
match native {
nativeChannelMonitorUpdateErr::TemporaryFailure => ChannelMonitorUpdateErr::TemporaryFailure,
nativeChannelMonitorUpdateErr::PermanentFailure => ChannelMonitorUpdateErr::PermanentFailure,
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeChannelMonitorUpdateErr) -> Self {
match native {
nativeChannelMonitorUpdateErr::TemporaryFailure => ChannelMonitorUpdateErr::TemporaryFailure,
nativeChannelMonitorUpdateErr::PermanentFailure => ChannelMonitorUpdateErr::PermanentFailure,
}
}
}
use lightning::ln::channelmonitor::MonitorUpdateError as nativeMonitorUpdateErrorImport;
type nativeMonitorUpdateError = nativeMonitorUpdateErrorImport;
/// General Err type for ChannelMonitor actions. Generally, this implies that the data provided is
/// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::update_monitor this
/// means you tried to update a monitor for a different channel or the ChannelMonitorUpdate was
/// corrupted.
/// Contains a human-readable error message.
#[must_use]
#[repr(C)]
pub struct MonitorUpdateError {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeMonitorUpdateError,
pub is_owned: bool,
}
impl Drop for MonitorUpdateError {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn MonitorUpdateError_free(this_ptr: MonitorUpdateError) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn MonitorUpdateError_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeMonitorUpdateError); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl MonitorUpdateError {
pub(crate) fn take_ptr(mut self) -> *mut nativeMonitorUpdateError {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::ln::channelmonitor::MonitorEvent as nativeMonitorEventImport;
type nativeMonitorEvent = nativeMonitorEventImport;
/// An event to be processed by the ChannelManager.
#[must_use]
#[repr(C)]
pub struct MonitorEvent {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeMonitorEvent,
pub is_owned: bool,
}
impl Drop for MonitorEvent {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn MonitorEvent_free(this_ptr: MonitorEvent) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn MonitorEvent_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeMonitorEvent); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl MonitorEvent {
pub(crate) fn take_ptr(mut self) -> *mut nativeMonitorEvent {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::ln::channelmonitor::HTLCUpdate as nativeHTLCUpdateImport;
type nativeHTLCUpdate = nativeHTLCUpdateImport;
/// Simple structure send back by ManyChannelMonitor in case of HTLC detected onchain from a
/// forward channel and from which info are needed to update HTLC in a backward channel.
#[must_use]
#[repr(C)]
pub struct HTLCUpdate {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeHTLCUpdate,
pub is_owned: bool,
}
impl Drop for HTLCUpdate {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn HTLCUpdate_free(this_ptr: HTLCUpdate) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn HTLCUpdate_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeHTLCUpdate); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl HTLCUpdate {
pub(crate) fn take_ptr(mut self) -> *mut nativeHTLCUpdate {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for HTLCUpdate {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn HTLCUpdate_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeHTLCUpdate)).clone() })) as *mut c_void
}
#[no_mangle]
pub extern "C" fn HTLCUpdate_write(obj: *const HTLCUpdate) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn HTLCUpdate_read(ser: crate::c_types::u8slice) -> HTLCUpdate {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
HTLCUpdate { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
HTLCUpdate { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::ln::channelmonitor::ChannelMonitor as nativeChannelMonitorImport;
type nativeChannelMonitor = nativeChannelMonitorImport<crate::chain::keysinterface::ChannelKeys>;
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
/// on-chain transactions to ensure no loss of funds occurs.
///
/// You MUST ensure that no ChannelMonitors for a given channel anywhere contain out-of-date
/// information and are actively monitoring the chain.
///
/// Pending Events or updated HTLCs which have not yet been read out by
/// get_and_clear_pending_monitor_events or get_and_clear_pending_events are serialized to disk and
/// reloaded at deserialize-time. Thus, you must ensure that, when handling events, all events
/// gotten are fully handled before re-serializing the new state.
#[must_use]
#[repr(C)]
pub struct ChannelMonitor {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelMonitor,
pub is_owned: bool,
}
impl Drop for ChannelMonitor {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelMonitor_free(this_ptr: ChannelMonitor) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelMonitor_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelMonitor); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelMonitor {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelMonitor {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
/// events to it, while also taking any add/update_monitor events and passing them to some remote
/// server(s).
///
/// In general, you must always have at least one local copy in memory, which must never fail to
/// update (as it is responsible for broadcasting the latest state in case the channel is closed),
/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails
/// to update (eg out-of-memory or some other condition), you must immediately shut down without
/// taking any further action such as writing the current state to disk. This should likely be
/// accomplished via panic!() or abort().
///
/// Note that any updates to a channel's monitor *must* be applied to each instance of the
/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If
/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions
/// which we have revoked, allowing our counterparty to claim all funds in the channel!
///
/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or
/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather
/// than calling these methods directly, the user should register implementors as listeners to the
/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
/// all registered listeners in one go.
#[repr(C)]
pub struct ManyChannelMonitor {
pub this_arg: *mut c_void,
/// Adds a monitor for the given `funding_txo`.
///
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
/// callbacks with the funding transaction, or any spends of it.
///
/// Further, the implementer must also ensure that each output returned in
/// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about
/// any spends of any of the outputs.
///
/// Any spends of outputs which should have been registered which aren't passed to
/// ChannelMonitors via block_connected may result in FUNDS LOSS.
#[must_use]
pub add_monitor: extern "C" fn (this_arg: *const c_void, funding_txo: crate::chain::transaction::OutPoint, monitor: crate::ln::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ,
/// Updates a monitor for the given `funding_txo`.
///
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
/// callbacks with the funding transaction, or any spends of it.
///
/// Further, the implementer must also ensure that each output returned in
/// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about
/// any spends of any of the outputs.
///
/// Any spends of outputs which should have been registered which aren't passed to
/// ChannelMonitors via block_connected may result in FUNDS LOSS.
#[must_use]
pub update_monitor: extern "C" fn (this_arg: *const c_void, funding_txo: crate::chain::transaction::OutPoint, monitor: crate::ln::channelmonitor::ChannelMonitorUpdate) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ,
/// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
/// with success or failure.
///
/// You should probably just call through to
/// ChannelMonitor::get_and_clear_pending_monitor_events() for each ChannelMonitor and return
/// the full list.
#[must_use]
pub get_and_clear_pending_monitor_events: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_MonitorEventZ,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Send for ManyChannelMonitor {}
unsafe impl Sync for ManyChannelMonitor {}
use lightning::ln::channelmonitor::ManyChannelMonitor as rustManyChannelMonitor;
impl rustManyChannelMonitor for ManyChannelMonitor {
type Keys = crate::chain::keysinterface::ChannelKeys;
fn add_monitor(&self, funding_txo: lightning::chain::transaction::OutPoint, monitor: lightning::ln::channelmonitor::ChannelMonitor<Self::Keys>) -> Result<(), lightning::ln::channelmonitor::ChannelMonitorUpdateErr> {
let mut ret = (self.add_monitor)(self.this_arg, crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(funding_txo)), is_owned: true }, crate::ln::channelmonitor::ChannelMonitor { inner: Box::into_raw(Box::new(monitor)), is_owned: true });
let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(ret.contents.result.take_ptr()) })*/ }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })};
local_ret
}
fn update_monitor(&self, funding_txo: lightning::chain::transaction::OutPoint, monitor: lightning::ln::channelmonitor::ChannelMonitorUpdate) -> Result<(), lightning::ln::channelmonitor::ChannelMonitorUpdateErr> {
let mut ret = (self.update_monitor)(self.this_arg, crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(funding_txo)), is_owned: true }, crate::ln::channelmonitor::ChannelMonitorUpdate { inner: Box::into_raw(Box::new(monitor)), is_owned: true });
let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(ret.contents.result.take_ptr()) })*/ }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })};
local_ret
}
fn get_and_clear_pending_monitor_events(&self) -> Vec<lightning::ln::channelmonitor::MonitorEvent> {
let mut ret = (self.get_and_clear_pending_monitor_events)(self.this_arg);
let mut local_ret = Vec::new(); for mut item in ret.into_rust().drain(..) { local_ret.push( { *unsafe { Box::from_raw(item.take_ptr()) } }); };
local_ret
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for ManyChannelMonitor {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn ManyChannelMonitor_free(this_ptr: ManyChannelMonitor) { }
impl Drop for ManyChannelMonitor {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
/// Updates a ChannelMonitor on the basis of some new information provided by the Channel
/// itself.
///
/// panics if the given update is not the next update by update_id.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelMonitor_update_monitor(this_arg: &mut ChannelMonitor, mut updates: crate::ln::channelmonitor::ChannelMonitorUpdate, broadcaster: &crate::chain::chaininterface::BroadcasterInterface, logger: &crate::util::logger::Logger) -> crate::c_types::derived::CResult_NoneMonitorUpdateErrorZ {
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.update_monitor(*unsafe { Box::from_raw(updates.take_ptr()) }, broadcaster, logger);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::channelmonitor::MonitorUpdateError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
/// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
/// ChannelMonitor.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelMonitor_get_latest_update_id(this_arg: &ChannelMonitor) -> u64 {
let mut ret = unsafe { &*this_arg.inner }.get_latest_update_id();
ret
}
/// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelMonitor_get_funding_txo(this_arg: &ChannelMonitor) -> crate::c_types::derived::C2Tuple_OutPointScriptZ {
let mut ret = unsafe { &*this_arg.inner }.get_funding_txo();
let (ref orig_ret_0, ref orig_ret_1) = ret; let mut local_ret = (crate::chain::transaction::OutPoint { inner: unsafe { ( (&(*orig_ret_0) as *const _) as *mut _) }, is_owned: false }, orig_ret_1.clone().into_bytes().into()).into();
local_ret
}
/// Get the list of HTLCs who's status has been updated on chain. This should be called by
/// ChannelManager via ManyChannelMonitor::get_and_clear_pending_monitor_events().
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelMonitor_get_and_clear_pending_monitor_events(this_arg: &mut ChannelMonitor) -> crate::c_types::derived::CVec_MonitorEventZ {
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.get_and_clear_pending_monitor_events();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::ln::channelmonitor::MonitorEvent { inner: Box::into_raw(Box::new(item)), is_owned: true } }); };
local_ret.into()
}
/// Gets the list of pending events which were generated by previous actions, clearing the list
/// in the process.
///
/// This is called by ManyChannelMonitor::get_and_clear_pending_events() and is equivalent to
/// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do
/// no internal locking in ChannelMonitors.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelMonitor_get_and_clear_pending_events(this_arg: &mut ChannelMonitor) -> crate::c_types::derived::CVec_EventZ {
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.get_and_clear_pending_events();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::util::events::Event::native_into(item) }); };
local_ret.into()
}
/// Used by ChannelManager deserialization to broadcast the latest local state if its copy of
/// the Channel was out-of-date. You may use it to get a broadcastable local toxic tx in case of
/// fallen-behind, i.e when receiving a channel_reestablish with a proof that our remote side knows
/// a higher revocation secret than the local commitment number we are aware of. Broadcasting these
/// transactions are UNSAFE, as they allow remote side to punish you. Nevertheless you may want to
/// broadcast them if remote don't close channel with his higher commitment transaction after a
/// substantial amount of time (a month or even a year) to get back funds. Best may be to contact
/// out-of-band the other node operator to coordinate with him if option is available to you.
/// In any-case, choice is up to the user.
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelMonitor_get_latest_local_commitment_txn(this_arg: &mut ChannelMonitor, logger: &crate::util::logger::Logger) -> crate::c_types::derived::CVec_TransactionZ {
let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.get_latest_local_commitment_txn(logger);
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { let mut local_ret_0 = ::bitcoin::consensus::encode::serialize(&item); local_ret_0.into() }); };
local_ret.into()
}

View file

@ -0,0 +1,136 @@
//! Feature flag definitions for the Lightning protocol according to [BOLT #9].
//!
//! Lightning nodes advertise a supported set of operation through feature flags. Features are
//! applicable for a specific context as indicated in some [messages]. [`Features`] encapsulates
//! behavior for specifying and checking feature flags for a particular context. Each feature is
//! defined internally by a trait specifying the corresponding flags (i.e., even and odd bits). A
//! [`Context`] is used to parameterize [`Features`] and defines which features it can support.
//!
//! Whether a feature is considered \"known\" or \"unknown\" is relative to the implementation, whereas
//! the term \"supports\" is used in reference to a particular set of [`Features`]. That is, a node
//! supports a feature if it advertises the feature (as either required or optional) to its peers.
//! And the implementation can interpret a feature if the feature is known to it.
//!
//! [BOLT #9]: https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md
//! [messages]: ../msgs/index.html
//! [`Features`]: struct.Features.html
//! [`Context`]: sealed/trait.Context.html
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::ln::features::InitFeatures as nativeInitFeaturesImport;
type nativeInitFeatures = nativeInitFeaturesImport;
/// Features used within an `init` message.
#[must_use]
#[repr(C)]
pub struct InitFeatures {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeInitFeatures,
pub is_owned: bool,
}
impl Drop for InitFeatures {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn InitFeatures_free(this_ptr: InitFeatures) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn InitFeatures_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeInitFeatures); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl InitFeatures {
pub(crate) fn take_ptr(mut self) -> *mut nativeInitFeatures {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::ln::features::NodeFeatures as nativeNodeFeaturesImport;
type nativeNodeFeatures = nativeNodeFeaturesImport;
/// Features used within a `node_announcement` message.
#[must_use]
#[repr(C)]
pub struct NodeFeatures {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeNodeFeatures,
pub is_owned: bool,
}
impl Drop for NodeFeatures {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn NodeFeatures_free(this_ptr: NodeFeatures) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn NodeFeatures_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeNodeFeatures); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl NodeFeatures {
pub(crate) fn take_ptr(mut self) -> *mut nativeNodeFeatures {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::ln::features::ChannelFeatures as nativeChannelFeaturesImport;
type nativeChannelFeatures = nativeChannelFeaturesImport;
/// Features used within a `channel_announcement` message.
#[must_use]
#[repr(C)]
pub struct ChannelFeatures {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelFeatures,
pub is_owned: bool,
}
impl Drop for ChannelFeatures {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelFeatures_free(this_ptr: ChannelFeatures) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelFeatures_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelFeatures); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelFeatures {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelFeatures {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}

View file

@ -0,0 +1,21 @@
//! High level lightning structs and impls live here.
//!
//! You probably want to create a channelmanager::ChannelManager, and a routing::NetGraphMsgHandler first.
//! Then, you probably want to pass them both on to a peer_handler::PeerManager and use that to
//! create/manage connections and call get_and_clear_pending_events after each action, handling
//! them appropriately.
//!
//! When you want to open/close a channel or send a payment, call into your ChannelManager and when
//! you want to learn things about the network topology (eg get a route for sending a payment),
//! call into your NetGraphMsgHandler.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
pub mod channelmanager;
pub mod channelmonitor;
pub mod msgs;
pub mod peer_handler;
pub mod chan_utils;
pub mod features;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,406 @@
//! Top level peer message handling and socket handling logic lives here.
//!
//! Instead of actually servicing sockets ourselves we require that you implement the
//! SocketDescriptor interface and use that to receive actions which you should perform on the
//! socket, and call into PeerManager with bytes read from the socket. The PeerManager will then
//! call into the provided message handlers (probably a ChannelManager and NetGraphmsgHandler) with messages
//! they should handle, and encoding/sending response messages.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::ln::peer_handler::MessageHandler as nativeMessageHandlerImport;
type nativeMessageHandler = nativeMessageHandlerImport<crate::ln::msgs::ChannelMessageHandler, crate::ln::msgs::RoutingMessageHandler>;
/// Provides references to trait impls which handle different types of messages.
#[must_use]
#[repr(C)]
pub struct MessageHandler {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeMessageHandler,
pub is_owned: bool,
}
impl Drop for MessageHandler {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn MessageHandler_free(this_ptr: MessageHandler) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn MessageHandler_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeMessageHandler); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl MessageHandler {
pub(crate) fn take_ptr(mut self) -> *mut nativeMessageHandler {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// A message handler which handles messages specific to channels. Usually this is just a
/// ChannelManager object.
#[no_mangle]
pub extern "C" fn MessageHandler_get_chan_handler(this_ptr: &MessageHandler) -> *const crate::ln::msgs::ChannelMessageHandler {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.chan_handler;
&(*inner_val)
}
/// A message handler which handles messages specific to channels. Usually this is just a
/// ChannelManager object.
#[no_mangle]
pub extern "C" fn MessageHandler_set_chan_handler(this_ptr: &mut MessageHandler, mut val: crate::ln::msgs::ChannelMessageHandler) {
unsafe { &mut *this_ptr.inner }.chan_handler = val;
}
/// A message handler which handles messages updating our knowledge of the network channel
/// graph. Usually this is just a NetGraphMsgHandlerMonitor object.
#[no_mangle]
pub extern "C" fn MessageHandler_get_route_handler(this_ptr: &MessageHandler) -> *const crate::ln::msgs::RoutingMessageHandler {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.route_handler;
&(*inner_val)
}
/// A message handler which handles messages updating our knowledge of the network channel
/// graph. Usually this is just a NetGraphMsgHandlerMonitor object.
#[no_mangle]
pub extern "C" fn MessageHandler_set_route_handler(this_ptr: &mut MessageHandler, mut val: crate::ln::msgs::RoutingMessageHandler) {
unsafe { &mut *this_ptr.inner }.route_handler = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn MessageHandler_new(mut chan_handler_arg: crate::ln::msgs::ChannelMessageHandler, mut route_handler_arg: crate::ln::msgs::RoutingMessageHandler) -> MessageHandler {
MessageHandler { inner: Box::into_raw(Box::new(nativeMessageHandler {
chan_handler: chan_handler_arg,
route_handler: route_handler_arg,
})), is_owned: true }
}
/// Provides an object which can be used to send data to and which uniquely identifies a connection
/// to a remote host. You will need to be able to generate multiple of these which meet Eq and
/// implement Hash to meet the PeerManager API.
///
/// For efficiency, Clone should be relatively cheap for this type.
///
/// You probably want to just extend an int and put a file descriptor in a struct and implement
/// send_data. Note that if you are using a higher-level net library that may call close() itself,
/// be careful to ensure you don't have races whereby you might register a new connection with an
/// fd which is the same as a previous one which has yet to be removed via
/// PeerManager::socket_disconnected().
#[repr(C)]
pub struct SocketDescriptor {
pub this_arg: *mut c_void,
/// Attempts to send some data from the given slice to the peer.
///
/// Returns the amount of data which was sent, possibly 0 if the socket has since disconnected.
/// Note that in the disconnected case, socket_disconnected must still fire and further write
/// attempts may occur until that time.
///
/// If the returned size is smaller than data.len(), a write_available event must
/// trigger the next time more data can be written. Additionally, until the a send_data event
/// completes fully, no further read_events should trigger on the same peer!
///
/// If a read_event on this descriptor had previously returned true (indicating that read
/// events should be paused to prevent DoS in the send buffer), resume_read may be set
/// indicating that read events on this descriptor should resume. A resume_read of false does
/// *not* imply that further read events should be paused.
#[must_use]
pub send_data: extern "C" fn (this_arg: *mut c_void, data: crate::c_types::u8slice, resume_read: bool) -> usize,
/// Disconnect the socket pointed to by this SocketDescriptor. Once this function returns, no
/// more calls to write_buffer_space_avail, read_event or socket_disconnected may be made with
/// this descriptor. No socket_disconnected call should be generated as a result of this call,
/// though races may occur whereby disconnect_socket is called after a call to
/// socket_disconnected but prior to socket_disconnected returning.
pub disconnect_socket: extern "C" fn (this_arg: *mut c_void),
pub eq: extern "C" fn (this_arg: *const c_void, other_arg: *const c_void) -> bool,
pub hash: extern "C" fn (this_arg: *const c_void) -> u64,
pub clone: Option<extern "C" fn (this_arg: *const c_void) -> *mut c_void>,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
impl std::cmp::Eq for SocketDescriptor {}
impl std::cmp::PartialEq for SocketDescriptor {
fn eq(&self, o: &Self) -> bool { (self.eq)(self.this_arg, o.this_arg) }
}
impl std::hash::Hash for SocketDescriptor {
fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) { hasher.write_u64((self.hash)(self.this_arg)) }
}
impl Clone for SocketDescriptor {
fn clone(&self) -> Self {
Self {
this_arg: if let Some(f) = self.clone { (f)(self.this_arg) } else { self.this_arg },
send_data: self.send_data.clone(),
disconnect_socket: self.disconnect_socket.clone(),
eq: self.eq.clone(),
hash: self.hash.clone(),
clone: self.clone.clone(),
free: self.free.clone(),
}
}
}
use lightning::ln::peer_handler::SocketDescriptor as rustSocketDescriptor;
impl rustSocketDescriptor for SocketDescriptor {
fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize {
let mut local_data = crate::c_types::u8slice::from_slice(data);
let mut ret = (self.send_data)(self.this_arg, local_data, resume_read);
ret
}
fn disconnect_socket(&mut self) {
(self.disconnect_socket)(self.this_arg)
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for SocketDescriptor {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn SocketDescriptor_free(this_ptr: SocketDescriptor) { }
impl Drop for SocketDescriptor {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
use lightning::ln::peer_handler::PeerHandleError as nativePeerHandleErrorImport;
type nativePeerHandleError = nativePeerHandleErrorImport;
/// Error for PeerManager errors. If you get one of these, you must disconnect the socket and
/// generate no further read_event/write_buffer_space_avail calls for the descriptor, only
/// triggering a single socket_disconnected call (unless it was provided in response to a
/// new_*_connection event, in which case no such socket_disconnected() must be called and the
/// socket silently disconencted).
#[must_use]
#[repr(C)]
pub struct PeerHandleError {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativePeerHandleError,
pub is_owned: bool,
}
impl Drop for PeerHandleError {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn PeerHandleError_free(this_ptr: PeerHandleError) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn PeerHandleError_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativePeerHandleError); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl PeerHandleError {
pub(crate) fn take_ptr(mut self) -> *mut nativePeerHandleError {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Used to indicate that we probably can't make any future connections to this peer, implying
/// we should go ahead and force-close any channels we have with it.
#[no_mangle]
pub extern "C" fn PeerHandleError_get_no_connection_possible(this_ptr: &PeerHandleError) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.no_connection_possible;
(*inner_val)
}
/// Used to indicate that we probably can't make any future connections to this peer, implying
/// we should go ahead and force-close any channels we have with it.
#[no_mangle]
pub extern "C" fn PeerHandleError_set_no_connection_possible(this_ptr: &mut PeerHandleError, mut val: bool) {
unsafe { &mut *this_ptr.inner }.no_connection_possible = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn PeerHandleError_new(mut no_connection_possible_arg: bool) -> PeerHandleError {
PeerHandleError { inner: Box::into_raw(Box::new(nativePeerHandleError {
no_connection_possible: no_connection_possible_arg,
})), is_owned: true }
}
use lightning::ln::peer_handler::PeerManager as nativePeerManagerImport;
type nativePeerManager = nativePeerManagerImport<crate::ln::peer_handler::SocketDescriptor, crate::ln::msgs::ChannelMessageHandler, crate::ln::msgs::RoutingMessageHandler, crate::util::logger::Logger>;
/// A PeerManager manages a set of peers, described by their SocketDescriptor and marshalls socket
/// events into messages which it passes on to its MessageHandlers.
///
/// Rather than using a plain PeerManager, it is preferable to use either a SimpleArcPeerManager
/// a SimpleRefPeerManager, for conciseness. See their documentation for more details, but
/// essentially you should default to using a SimpleRefPeerManager, and use a
/// SimpleArcPeerManager when you require a PeerManager with a static lifetime, such as when
/// you're using lightning-net-tokio.
#[must_use]
#[repr(C)]
pub struct PeerManager {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativePeerManager,
pub is_owned: bool,
}
impl Drop for PeerManager {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn PeerManager_free(this_ptr: PeerManager) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn PeerManager_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativePeerManager); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl PeerManager {
pub(crate) fn take_ptr(mut self) -> *mut nativePeerManager {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Constructs a new PeerManager with the given message handlers and node_id secret key
/// ephemeral_random_data is used to derive per-connection ephemeral keys and must be
/// cryptographically secure random bytes.
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_new(mut message_handler: crate::ln::peer_handler::MessageHandler, mut our_node_secret: crate::c_types::SecretKey, ephemeral_random_data: *const [u8; 32], mut logger: crate::util::logger::Logger) -> PeerManager {
let mut ret = lightning::ln::peer_handler::PeerManager::new(*unsafe { Box::from_raw(message_handler.take_ptr()) }, our_node_secret.into_rust(), unsafe { &*ephemeral_random_data}, logger);
PeerManager { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Get the list of node ids for peers which have completed the initial handshake.
///
/// For outbound connections, this will be the same as the their_node_id parameter passed in to
/// new_outbound_connection, however entries will only appear once the initial handshake has
/// completed and we are sure the remote peer has the private key for the given node_id.
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_get_peer_node_ids(this_arg: &PeerManager) -> crate::c_types::derived::CVec_PublicKeyZ {
let mut ret = unsafe { &*this_arg.inner }.get_peer_node_ids();
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::c_types::PublicKey::from_rust(&item) }); };
local_ret.into()
}
/// Indicates a new outbound connection has been established to a node with the given node_id.
/// Note that if an Err is returned here you MUST NOT call socket_disconnected for the new
/// descriptor but must disconnect the connection immediately.
///
/// Returns a small number of bytes to send to the remote node (currently always 50).
///
/// Panics if descriptor is duplicative with some other descriptor which has not yet had a
/// socket_disconnected().
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_new_outbound_connection(this_arg: &PeerManager, mut their_node_id: crate::c_types::PublicKey, mut descriptor: crate::ln::peer_handler::SocketDescriptor) -> crate::c_types::derived::CResult_CVec_u8ZPeerHandleErrorZ {
let mut ret = unsafe { &*this_arg.inner }.new_outbound_connection(their_node_id.into_rust(), descriptor);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { let mut local_ret_0 = Vec::new(); for item in o.drain(..) { local_ret_0.push( { item }); }; local_ret_0.into() }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::peer_handler::PeerHandleError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
/// Indicates a new inbound connection has been established.
///
/// May refuse the connection by returning an Err, but will never write bytes to the remote end
/// (outbound connector always speaks first). Note that if an Err is returned here you MUST NOT
/// call socket_disconnected for the new descriptor but must disconnect the connection
/// immediately.
///
/// Panics if descriptor is duplicative with some other descriptor which has not yet had
/// socket_disconnected called.
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_new_inbound_connection(this_arg: &PeerManager, mut descriptor: crate::ln::peer_handler::SocketDescriptor) -> crate::c_types::derived::CResult_NonePeerHandleErrorZ {
let mut ret = unsafe { &*this_arg.inner }.new_inbound_connection(descriptor);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::peer_handler::PeerHandleError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
/// Indicates that there is room to write data to the given socket descriptor.
///
/// May return an Err to indicate that the connection should be closed.
///
/// Will most likely call send_data on the descriptor passed in (or the descriptor handed into
/// new_*\\_connection) before returning. Thus, be very careful with reentrancy issues! The
/// invariants around calling write_buffer_space_avail in case a write did not fully complete
/// must still hold - be ready to call write_buffer_space_avail again if a write call generated
/// here isn't sufficient! Panics if the descriptor was not previously registered in a
/// new_\\*_connection event.
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_write_buffer_space_avail(this_arg: &PeerManager, descriptor: &mut crate::ln::peer_handler::SocketDescriptor) -> crate::c_types::derived::CResult_NonePeerHandleErrorZ {
let mut ret = unsafe { &*this_arg.inner }.write_buffer_space_avail(descriptor);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::peer_handler::PeerHandleError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
/// Indicates that data was read from the given socket descriptor.
///
/// May return an Err to indicate that the connection should be closed.
///
/// Will *not* call back into send_data on any descriptors to avoid reentrancy complexity.
/// Thus, however, you almost certainly want to call process_events() after any read_event to
/// generate send_data calls to handle responses.
///
/// If Ok(true) is returned, further read_events should not be triggered until a send_data call
/// on this file descriptor has resume_read set (preventing DoS issues in the send buffer).
///
/// Panics if the descriptor was not previously registered in a new_*_connection event.
#[must_use]
#[no_mangle]
pub extern "C" fn PeerManager_read_event(this_arg: &PeerManager, peer_descriptor: &mut crate::ln::peer_handler::SocketDescriptor, mut data: crate::c_types::u8slice) -> crate::c_types::derived::CResult_boolPeerHandleErrorZ {
let mut ret = unsafe { &*this_arg.inner }.read_event(peer_descriptor, data.to_slice());
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { o }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::peer_handler::PeerHandleError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
/// Checks for any events generated by our handlers and processes them. Includes sending most
/// response messages as well as messages generated by calls to handler functions directly (eg
/// functions like ChannelManager::process_pending_htlc_forward or send_payment).
#[no_mangle]
pub extern "C" fn PeerManager_process_events(this_arg: &PeerManager) {
unsafe { &*this_arg.inner }.process_events()
}
/// Indicates that the given socket descriptor's connection is now closed.
///
/// This must only be called if the socket has been disconnected by the peer or your own
/// decision to disconnect it and must NOT be called in any case where other parts of this
/// library (eg PeerHandleError, explicit disconnect_socket calls) instruct you to disconnect
/// the peer.
///
/// Panics if the descriptor was not previously registered in a successful new_*_connection event.
#[no_mangle]
pub extern "C" fn PeerManager_socket_disconnected(this_arg: &PeerManager, descriptor: &crate::ln::peer_handler::SocketDescriptor) {
unsafe { &*this_arg.inner }.socket_disconnected(descriptor)
}
/// This function should be called roughly once every 30 seconds.
/// It will send pings to each peer and disconnect those which did not respond to the last round of pings.
/// Will most likely call send_data on all of the registered descriptors, thus, be very careful with reentrancy issues!
#[no_mangle]
pub extern "C" fn PeerManager_timer_tick_occured(this_arg: &PeerManager) {
unsafe { &*this_arg.inner }.timer_tick_occured()
}

View file

@ -0,0 +1,8 @@
//! Structs and impls for receiving messages about the network and storing the topology live here.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
pub mod router;
pub mod network_graph;

View file

@ -0,0 +1,795 @@
//! The top-level network map tracking logic lives here.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::routing::network_graph::NetworkGraph as nativeNetworkGraphImport;
type nativeNetworkGraph = nativeNetworkGraphImport;
/// Represents the network as nodes and channels between them
#[must_use]
#[repr(C)]
pub struct NetworkGraph {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeNetworkGraph,
pub is_owned: bool,
}
impl Drop for NetworkGraph {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn NetworkGraph_free(this_ptr: NetworkGraph) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn NetworkGraph_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeNetworkGraph); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl NetworkGraph {
pub(crate) fn take_ptr(mut self) -> *mut nativeNetworkGraph {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::routing::network_graph::LockedNetworkGraph as nativeLockedNetworkGraphImport;
type nativeLockedNetworkGraph = nativeLockedNetworkGraphImport<'static>;
/// A simple newtype for RwLockReadGuard<'a, NetworkGraph>.
/// This exists only to make accessing a RwLock<NetworkGraph> possible from
/// the C bindings, as it can be done directly in Rust code.
#[must_use]
#[repr(C)]
pub struct LockedNetworkGraph {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeLockedNetworkGraph,
pub is_owned: bool,
}
impl Drop for LockedNetworkGraph {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn LockedNetworkGraph_free(this_ptr: LockedNetworkGraph) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn LockedNetworkGraph_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeLockedNetworkGraph); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl LockedNetworkGraph {
pub(crate) fn take_ptr(mut self) -> *mut nativeLockedNetworkGraph {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
use lightning::routing::network_graph::NetGraphMsgHandler as nativeNetGraphMsgHandlerImport;
type nativeNetGraphMsgHandler = nativeNetGraphMsgHandlerImport<crate::chain::chaininterface::ChainWatchInterface, crate::util::logger::Logger>;
/// Receives and validates network updates from peers,
/// stores authentic and relevant data as a network graph.
/// This network graph is then used for routing payments.
/// Provides interface to help with initial routing sync by
/// serving historical announcements.
#[must_use]
#[repr(C)]
pub struct NetGraphMsgHandler {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeNetGraphMsgHandler,
pub is_owned: bool,
}
impl Drop for NetGraphMsgHandler {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn NetGraphMsgHandler_free(this_ptr: NetGraphMsgHandler) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn NetGraphMsgHandler_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeNetGraphMsgHandler); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl NetGraphMsgHandler {
pub(crate) fn take_ptr(mut self) -> *mut nativeNetGraphMsgHandler {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Creates a new tracker of the actual state of the network of channels and nodes,
/// assuming a fresh network graph.
/// Chain monitor is used to make sure announced channels exist on-chain,
/// channel data is correct, and that the announcement is signed with
/// channel owners' keys.
#[must_use]
#[no_mangle]
pub extern "C" fn NetGraphMsgHandler_new(mut chain_monitor: crate::chain::chaininterface::ChainWatchInterface, mut logger: crate::util::logger::Logger) -> NetGraphMsgHandler {
let mut ret = lightning::routing::network_graph::NetGraphMsgHandler::new(chain_monitor, logger);
NetGraphMsgHandler { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Creates a new tracker of the actual state of the network of channels and nodes,
/// assuming an existing Network Graph.
#[must_use]
#[no_mangle]
pub extern "C" fn NetGraphMsgHandler_from_net_graph(mut chain_monitor: crate::chain::chaininterface::ChainWatchInterface, mut logger: crate::util::logger::Logger, mut network_graph: crate::routing::network_graph::NetworkGraph) -> NetGraphMsgHandler {
let mut ret = lightning::routing::network_graph::NetGraphMsgHandler::from_net_graph(chain_monitor, logger, *unsafe { Box::from_raw(network_graph.take_ptr()) });
NetGraphMsgHandler { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Take a read lock on the network_graph and return it in the C-bindings
/// newtype helper. This is likely only useful when called via the C
/// bindings as you can call `self.network_graph.read().unwrap()` in Rust
/// yourself.
#[must_use]
#[no_mangle]
pub extern "C" fn NetGraphMsgHandler_read_locked_graph(this_arg: &NetGraphMsgHandler) -> crate::routing::network_graph::LockedNetworkGraph {
let mut ret = unsafe { &*this_arg.inner }.read_locked_graph();
crate::routing::network_graph::LockedNetworkGraph { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Get a reference to the NetworkGraph which this read-lock contains.
#[must_use]
#[no_mangle]
pub extern "C" fn LockedNetworkGraph_graph(this_arg: &LockedNetworkGraph) -> crate::routing::network_graph::NetworkGraph {
let mut ret = unsafe { &*this_arg.inner }.graph();
crate::routing::network_graph::NetworkGraph { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false }
}
#[no_mangle]
pub extern "C" fn NetGraphMsgHandler_as_RoutingMessageHandler(this_arg: *const NetGraphMsgHandler) -> crate::ln::msgs::RoutingMessageHandler {
crate::ln::msgs::RoutingMessageHandler {
this_arg: unsafe { (*this_arg).inner as *mut c_void },
free: None,
handle_node_announcement: NetGraphMsgHandler_RoutingMessageHandler_handle_node_announcement,
handle_channel_announcement: NetGraphMsgHandler_RoutingMessageHandler_handle_channel_announcement,
handle_channel_update: NetGraphMsgHandler_RoutingMessageHandler_handle_channel_update,
handle_htlc_fail_channel_update: NetGraphMsgHandler_RoutingMessageHandler_handle_htlc_fail_channel_update,
get_next_channel_announcements: NetGraphMsgHandler_RoutingMessageHandler_get_next_channel_announcements,
get_next_node_announcements: NetGraphMsgHandler_RoutingMessageHandler_get_next_node_announcements,
should_request_full_sync: NetGraphMsgHandler_RoutingMessageHandler_should_request_full_sync,
}
}
use lightning::ln::msgs::RoutingMessageHandler as RoutingMessageHandlerTraitImport;
#[must_use]
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_handle_node_announcement(this_arg: *const c_void, msg: &crate::ln::msgs::NodeAnnouncement) -> crate::c_types::derived::CResult_boolLightningErrorZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.handle_node_announcement(unsafe { &*msg.inner });
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { o }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::msgs::LightningError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
#[must_use]
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_handle_channel_announcement(this_arg: *const c_void, msg: &crate::ln::msgs::ChannelAnnouncement) -> crate::c_types::derived::CResult_boolLightningErrorZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.handle_channel_announcement(unsafe { &*msg.inner });
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { o }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::msgs::LightningError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_handle_htlc_fail_channel_update(this_arg: *const c_void, update: &crate::ln::msgs::HTLCFailChannelUpdate) {
unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.handle_htlc_fail_channel_update(&update.to_native())
}
#[must_use]
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_handle_channel_update(this_arg: *const c_void, msg: &crate::ln::msgs::ChannelUpdate) -> crate::c_types::derived::CResult_boolLightningErrorZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.handle_channel_update(unsafe { &*msg.inner });
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { o }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::msgs::LightningError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}
#[must_use]
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_get_next_channel_announcements(this_arg: *const c_void, mut starting_point: u64, mut batch_amount: u8) -> crate::c_types::derived::CVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ {
let mut ret = unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.get_next_channel_announcements(starting_point, batch_amount);
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { let (mut orig_ret_0_0, mut orig_ret_0_1, mut orig_ret_0_2) = item; let mut local_orig_ret_0_1 = crate::ln::msgs::ChannelUpdate { inner: if orig_ret_0_1.is_none() { std::ptr::null_mut() } else { { Box::into_raw(Box::new((orig_ret_0_1.unwrap()))) } }, is_owned: true }; let mut local_orig_ret_0_2 = crate::ln::msgs::ChannelUpdate { inner: if orig_ret_0_2.is_none() { std::ptr::null_mut() } else { { Box::into_raw(Box::new((orig_ret_0_2.unwrap()))) } }, is_owned: true }; let mut local_ret_0 = (crate::ln::msgs::ChannelAnnouncement { inner: Box::into_raw(Box::new(orig_ret_0_0)), is_owned: true }, local_orig_ret_0_1, local_orig_ret_0_2).into(); local_ret_0 }); };
local_ret.into()
}
#[must_use]
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_get_next_node_announcements(this_arg: *const c_void, mut starting_point: crate::c_types::PublicKey, mut batch_amount: u8) -> crate::c_types::derived::CVec_NodeAnnouncementZ {
let mut local_starting_point_base = if starting_point.is_null() { None } else { Some( { starting_point.into_rust() }) }; let mut local_starting_point = local_starting_point_base.as_ref();
let mut ret = unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.get_next_node_announcements(local_starting_point, batch_amount);
let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { crate::ln::msgs::NodeAnnouncement { inner: Box::into_raw(Box::new(item)), is_owned: true } }); };
local_ret.into()
}
#[must_use]
extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_should_request_full_sync(this_arg: *const c_void, _node_id: crate::c_types::PublicKey) -> bool {
let mut ret = unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }.should_request_full_sync(&_node_id.into_rust());
ret
}
use lightning::routing::network_graph::DirectionalChannelInfo as nativeDirectionalChannelInfoImport;
type nativeDirectionalChannelInfo = nativeDirectionalChannelInfoImport;
/// Details about one direction of a channel. Received
/// within a channel update.
#[must_use]
#[repr(C)]
pub struct DirectionalChannelInfo {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeDirectionalChannelInfo,
pub is_owned: bool,
}
impl Drop for DirectionalChannelInfo {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_free(this_ptr: DirectionalChannelInfo) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn DirectionalChannelInfo_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeDirectionalChannelInfo); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl DirectionalChannelInfo {
pub(crate) fn take_ptr(mut self) -> *mut nativeDirectionalChannelInfo {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// When the last update to the channel direction was issued.
/// Value is opaque, as set in the announcement.
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_get_last_update(this_ptr: &DirectionalChannelInfo) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.last_update;
(*inner_val)
}
/// When the last update to the channel direction was issued.
/// Value is opaque, as set in the announcement.
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_set_last_update(this_ptr: &mut DirectionalChannelInfo, mut val: u32) {
unsafe { &mut *this_ptr.inner }.last_update = val;
}
/// Whether the channel can be currently used for payments (in this one direction).
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_get_enabled(this_ptr: &DirectionalChannelInfo) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.enabled;
(*inner_val)
}
/// Whether the channel can be currently used for payments (in this one direction).
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_set_enabled(this_ptr: &mut DirectionalChannelInfo, mut val: bool) {
unsafe { &mut *this_ptr.inner }.enabled = val;
}
/// The difference in CLTV values that you must have when routing through this channel.
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_get_cltv_expiry_delta(this_ptr: &DirectionalChannelInfo) -> u16 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.cltv_expiry_delta;
(*inner_val)
}
/// The difference in CLTV values that you must have when routing through this channel.
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_set_cltv_expiry_delta(this_ptr: &mut DirectionalChannelInfo, mut val: u16) {
unsafe { &mut *this_ptr.inner }.cltv_expiry_delta = val;
}
/// The minimum value, which must be relayed to the next hop via the channel
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_get_htlc_minimum_msat(this_ptr: &DirectionalChannelInfo) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.htlc_minimum_msat;
(*inner_val)
}
/// The minimum value, which must be relayed to the next hop via the channel
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_set_htlc_minimum_msat(this_ptr: &mut DirectionalChannelInfo, mut val: u64) {
unsafe { &mut *this_ptr.inner }.htlc_minimum_msat = val;
}
/// Most recent update for the channel received from the network
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_get_last_update_message(this_ptr: &DirectionalChannelInfo) -> crate::ln::msgs::ChannelUpdate {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.last_update_message;
let mut local_inner_val = crate::ln::msgs::ChannelUpdate { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// Most recent update for the channel received from the network
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_set_last_update_message(this_ptr: &mut DirectionalChannelInfo, mut val: crate::ln::msgs::ChannelUpdate) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.last_update_message = local_val;
}
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_write(obj: *const DirectionalChannelInfo) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn DirectionalChannelInfo_read(ser: crate::c_types::u8slice) -> DirectionalChannelInfo {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
DirectionalChannelInfo { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
DirectionalChannelInfo { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::routing::network_graph::ChannelInfo as nativeChannelInfoImport;
type nativeChannelInfo = nativeChannelInfoImport;
/// Details about a channel (both directions).
/// Received within a channel announcement.
#[must_use]
#[repr(C)]
pub struct ChannelInfo {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelInfo,
pub is_owned: bool,
}
impl Drop for ChannelInfo {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelInfo_free(this_ptr: ChannelInfo) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelInfo_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelInfo); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelInfo {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelInfo {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// Source node of the first direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_get_node_one(this_ptr: &ChannelInfo) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.node_one;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// Source node of the first direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_set_node_one(this_ptr: &mut ChannelInfo, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.node_one = val.into_rust();
}
/// Details about the first direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_get_one_to_two(this_ptr: &ChannelInfo) -> crate::routing::network_graph::DirectionalChannelInfo {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.one_to_two;
let mut local_inner_val = crate::routing::network_graph::DirectionalChannelInfo { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// Details about the first direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_set_one_to_two(this_ptr: &mut ChannelInfo, mut val: crate::routing::network_graph::DirectionalChannelInfo) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.one_to_two = local_val;
}
/// Source node of the second direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_get_node_two(this_ptr: &ChannelInfo) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.node_two;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// Source node of the second direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_set_node_two(this_ptr: &mut ChannelInfo, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.node_two = val.into_rust();
}
/// Details about the second direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_get_two_to_one(this_ptr: &ChannelInfo) -> crate::routing::network_graph::DirectionalChannelInfo {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.two_to_one;
let mut local_inner_val = crate::routing::network_graph::DirectionalChannelInfo { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// Details about the second direction of a channel
#[no_mangle]
pub extern "C" fn ChannelInfo_set_two_to_one(this_ptr: &mut ChannelInfo, mut val: crate::routing::network_graph::DirectionalChannelInfo) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.two_to_one = local_val;
}
/// An initial announcement of the channel
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
#[no_mangle]
pub extern "C" fn ChannelInfo_get_announcement_message(this_ptr: &ChannelInfo) -> crate::ln::msgs::ChannelAnnouncement {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.announcement_message;
let mut local_inner_val = crate::ln::msgs::ChannelAnnouncement { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// An initial announcement of the channel
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
#[no_mangle]
pub extern "C" fn ChannelInfo_set_announcement_message(this_ptr: &mut ChannelInfo, mut val: crate::ln::msgs::ChannelAnnouncement) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.announcement_message = local_val;
}
#[no_mangle]
pub extern "C" fn ChannelInfo_write(obj: *const ChannelInfo) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn ChannelInfo_read(ser: crate::c_types::u8slice) -> ChannelInfo {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
ChannelInfo { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
ChannelInfo { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::routing::network_graph::RoutingFees as nativeRoutingFeesImport;
type nativeRoutingFees = nativeRoutingFeesImport;
/// Fees for routing via a given channel or a node
#[must_use]
#[repr(C)]
pub struct RoutingFees {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeRoutingFees,
pub is_owned: bool,
}
impl Drop for RoutingFees {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn RoutingFees_free(this_ptr: RoutingFees) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn RoutingFees_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeRoutingFees); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl RoutingFees {
pub(crate) fn take_ptr(mut self) -> *mut nativeRoutingFees {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for RoutingFees {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn RoutingFees_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRoutingFees)).clone() })) as *mut c_void
}
/// Flat routing fee in satoshis
#[no_mangle]
pub extern "C" fn RoutingFees_get_base_msat(this_ptr: &RoutingFees) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.base_msat;
(*inner_val)
}
/// Flat routing fee in satoshis
#[no_mangle]
pub extern "C" fn RoutingFees_set_base_msat(this_ptr: &mut RoutingFees, mut val: u32) {
unsafe { &mut *this_ptr.inner }.base_msat = val;
}
/// Liquidity-based routing fee in millionths of a routed amount.
/// In other words, 10000 is 1%.
#[no_mangle]
pub extern "C" fn RoutingFees_get_proportional_millionths(this_ptr: &RoutingFees) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.proportional_millionths;
(*inner_val)
}
/// Liquidity-based routing fee in millionths of a routed amount.
/// In other words, 10000 is 1%.
#[no_mangle]
pub extern "C" fn RoutingFees_set_proportional_millionths(this_ptr: &mut RoutingFees, mut val: u32) {
unsafe { &mut *this_ptr.inner }.proportional_millionths = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn RoutingFees_new(mut base_msat_arg: u32, mut proportional_millionths_arg: u32) -> RoutingFees {
RoutingFees { inner: Box::into_raw(Box::new(nativeRoutingFees {
base_msat: base_msat_arg,
proportional_millionths: proportional_millionths_arg,
})), is_owned: true }
}
#[no_mangle]
pub extern "C" fn RoutingFees_read(ser: crate::c_types::u8slice) -> RoutingFees {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
RoutingFees { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
RoutingFees { inner: std::ptr::null_mut(), is_owned: true }
}
}
#[no_mangle]
pub extern "C" fn RoutingFees_write(obj: *const RoutingFees) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
use lightning::routing::network_graph::NodeAnnouncementInfo as nativeNodeAnnouncementInfoImport;
type nativeNodeAnnouncementInfo = nativeNodeAnnouncementInfoImport;
/// Information received in the latest node_announcement from this node.
#[must_use]
#[repr(C)]
pub struct NodeAnnouncementInfo {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeNodeAnnouncementInfo,
pub is_owned: bool,
}
impl Drop for NodeAnnouncementInfo {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_free(this_ptr: NodeAnnouncementInfo) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn NodeAnnouncementInfo_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeNodeAnnouncementInfo); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl NodeAnnouncementInfo {
pub(crate) fn take_ptr(mut self) -> *mut nativeNodeAnnouncementInfo {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// When the last known update to the node state was issued.
/// Value is opaque, as set in the announcement.
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_get_last_update(this_ptr: &NodeAnnouncementInfo) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.last_update;
(*inner_val)
}
/// When the last known update to the node state was issued.
/// Value is opaque, as set in the announcement.
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_set_last_update(this_ptr: &mut NodeAnnouncementInfo, mut val: u32) {
unsafe { &mut *this_ptr.inner }.last_update = val;
}
/// Color assigned to the node
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_get_rgb(this_ptr: &NodeAnnouncementInfo) -> *const [u8; 3] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.rgb;
&(*inner_val)
}
/// Color assigned to the node
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_set_rgb(this_ptr: &mut NodeAnnouncementInfo, mut val: crate::c_types::ThreeBytes) {
unsafe { &mut *this_ptr.inner }.rgb = val.data;
}
/// Moniker assigned to the node.
/// May be invalid or malicious (eg control chars),
/// should not be exposed to the user.
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_get_alias(this_ptr: &NodeAnnouncementInfo) -> *const [u8; 32] {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.alias;
&(*inner_val)
}
/// Moniker assigned to the node.
/// May be invalid or malicious (eg control chars),
/// should not be exposed to the user.
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_set_alias(this_ptr: &mut NodeAnnouncementInfo, mut val: crate::c_types::ThirtyTwoBytes) {
unsafe { &mut *this_ptr.inner }.alias = val.data;
}
/// Internet-level addresses via which one can connect to the node
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_set_addresses(this_ptr: &mut NodeAnnouncementInfo, mut val: crate::c_types::derived::CVec_NetAddressZ) {
let mut local_val = Vec::new(); for mut item in val.into_rust().drain(..) { local_val.push( { item.into_native() }); };
unsafe { &mut *this_ptr.inner }.addresses = local_val;
}
/// An initial announcement of the node
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_get_announcement_message(this_ptr: &NodeAnnouncementInfo) -> crate::ln::msgs::NodeAnnouncement {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.announcement_message;
let mut local_inner_val = crate::ln::msgs::NodeAnnouncement { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// An initial announcement of the node
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_set_announcement_message(this_ptr: &mut NodeAnnouncementInfo, mut val: crate::ln::msgs::NodeAnnouncement) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.announcement_message = local_val;
}
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_write(obj: *const NodeAnnouncementInfo) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn NodeAnnouncementInfo_read(ser: crate::c_types::u8slice) -> NodeAnnouncementInfo {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
NodeAnnouncementInfo { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
NodeAnnouncementInfo { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::routing::network_graph::NodeInfo as nativeNodeInfoImport;
type nativeNodeInfo = nativeNodeInfoImport;
/// Details about a node in the network, known from the network announcement.
#[must_use]
#[repr(C)]
pub struct NodeInfo {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeNodeInfo,
pub is_owned: bool,
}
impl Drop for NodeInfo {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn NodeInfo_free(this_ptr: NodeInfo) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn NodeInfo_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeNodeInfo); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl NodeInfo {
pub(crate) fn take_ptr(mut self) -> *mut nativeNodeInfo {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// All valid channels a node has announced
#[no_mangle]
pub extern "C" fn NodeInfo_set_channels(this_ptr: &mut NodeInfo, mut val: crate::c_types::derived::CVec_u64Z) {
let mut local_val = Vec::new(); for mut item in val.into_rust().drain(..) { local_val.push( { item }); };
unsafe { &mut *this_ptr.inner }.channels = local_val;
}
/// Lowest fees enabling routing via any of the enabled, known channels to a node.
/// The two fields (flat and proportional fee) are independent,
/// meaning they don't have to refer to the same channel.
#[no_mangle]
pub extern "C" fn NodeInfo_get_lowest_inbound_channel_fees(this_ptr: &NodeInfo) -> crate::routing::network_graph::RoutingFees {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.lowest_inbound_channel_fees;
let mut local_inner_val = crate::routing::network_graph::RoutingFees { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// Lowest fees enabling routing via any of the enabled, known channels to a node.
/// The two fields (flat and proportional fee) are independent,
/// meaning they don't have to refer to the same channel.
#[no_mangle]
pub extern "C" fn NodeInfo_set_lowest_inbound_channel_fees(this_ptr: &mut NodeInfo, mut val: crate::routing::network_graph::RoutingFees) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.lowest_inbound_channel_fees = local_val;
}
/// More information about a node from node_announcement.
/// Optional because we store a Node entry after learning about it from
/// a channel announcement, but before receiving a node announcement.
#[no_mangle]
pub extern "C" fn NodeInfo_get_announcement_info(this_ptr: &NodeInfo) -> crate::routing::network_graph::NodeAnnouncementInfo {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.announcement_info;
let mut local_inner_val = crate::routing::network_graph::NodeAnnouncementInfo { inner: unsafe { (if inner_val.is_none() { std::ptr::null() } else { { (inner_val.as_ref().unwrap()) } } as *const _) as *mut _ }, is_owned: false };
local_inner_val
}
/// More information about a node from node_announcement.
/// Optional because we store a Node entry after learning about it from
/// a channel announcement, but before receiving a node announcement.
#[no_mangle]
pub extern "C" fn NodeInfo_set_announcement_info(this_ptr: &mut NodeInfo, mut val: crate::routing::network_graph::NodeAnnouncementInfo) {
let mut local_val = if val.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(val.take_ptr()) } }) };
unsafe { &mut *this_ptr.inner }.announcement_info = local_val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn NodeInfo_new(mut channels_arg: crate::c_types::derived::CVec_u64Z, mut lowest_inbound_channel_fees_arg: crate::routing::network_graph::RoutingFees, mut announcement_info_arg: crate::routing::network_graph::NodeAnnouncementInfo) -> NodeInfo {
let mut local_channels_arg = Vec::new(); for mut item in channels_arg.into_rust().drain(..) { local_channels_arg.push( { item }); };
let mut local_lowest_inbound_channel_fees_arg = if lowest_inbound_channel_fees_arg.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(lowest_inbound_channel_fees_arg.take_ptr()) } }) };
let mut local_announcement_info_arg = if announcement_info_arg.inner.is_null() { None } else { Some( { *unsafe { Box::from_raw(announcement_info_arg.take_ptr()) } }) };
NodeInfo { inner: Box::into_raw(Box::new(nativeNodeInfo {
channels: local_channels_arg,
lowest_inbound_channel_fees: local_lowest_inbound_channel_fees_arg,
announcement_info: local_announcement_info_arg,
})), is_owned: true }
}
#[no_mangle]
pub extern "C" fn NodeInfo_write(obj: *const NodeInfo) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn NodeInfo_read(ser: crate::c_types::u8slice) -> NodeInfo {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
NodeInfo { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
NodeInfo { inner: std::ptr::null_mut(), is_owned: true }
}
}
#[no_mangle]
pub extern "C" fn NetworkGraph_write(obj: *const NetworkGraph) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn NetworkGraph_read(ser: crate::c_types::u8slice) -> NetworkGraph {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
NetworkGraph { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
NetworkGraph { inner: std::ptr::null_mut(), is_owned: true }
}
}
/// Creates a new, empty, network graph.
#[must_use]
#[no_mangle]
pub extern "C" fn NetworkGraph_new() -> crate::routing::network_graph::NetworkGraph {
let mut ret = lightning::routing::network_graph::NetworkGraph::new();
crate::routing::network_graph::NetworkGraph { inner: Box::into_raw(Box::new(ret)), is_owned: true }
}
/// Close a channel if a corresponding HTLC fail was sent.
/// If permanent, removes a channel from the local storage.
/// May cause the removal of nodes too, if this was their last channel.
/// If not permanent, makes channels unavailable for routing.
#[no_mangle]
pub extern "C" fn NetworkGraph_close_channel_from_update(this_arg: &mut NetworkGraph, mut short_channel_id: u64, mut is_permanent: bool) {
unsafe { &mut (*(this_arg.inner as *mut nativeNetworkGraph)) }.close_channel_from_update(short_channel_id, is_permanent)
}

View file

@ -0,0 +1,318 @@
//! The top-level routing/network map tracking logic lives here.
//!
//! You probably want to create a NetGraphMsgHandler and use that as your RoutingMessageHandler and then
//! interrogate it to get routes for your own payments.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::routing::router::RouteHop as nativeRouteHopImport;
type nativeRouteHop = nativeRouteHopImport;
/// A hop in a route
#[must_use]
#[repr(C)]
pub struct RouteHop {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeRouteHop,
pub is_owned: bool,
}
impl Drop for RouteHop {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn RouteHop_free(this_ptr: RouteHop) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn RouteHop_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeRouteHop); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl RouteHop {
pub(crate) fn take_ptr(mut self) -> *mut nativeRouteHop {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for RouteHop {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn RouteHop_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRouteHop)).clone() })) as *mut c_void
}
/// The node_id of the node at this hop.
#[no_mangle]
pub extern "C" fn RouteHop_get_pubkey(this_ptr: &RouteHop) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.pubkey;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The node_id of the node at this hop.
#[no_mangle]
pub extern "C" fn RouteHop_set_pubkey(this_ptr: &mut RouteHop, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.pubkey = val.into_rust();
}
/// The channel that should be used from the previous hop to reach this node.
#[no_mangle]
pub extern "C" fn RouteHop_get_short_channel_id(this_ptr: &RouteHop) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.short_channel_id;
(*inner_val)
}
/// The channel that should be used from the previous hop to reach this node.
#[no_mangle]
pub extern "C" fn RouteHop_set_short_channel_id(this_ptr: &mut RouteHop, mut val: u64) {
unsafe { &mut *this_ptr.inner }.short_channel_id = val;
}
/// The fee taken on this hop. For the last hop, this should be the full value of the payment.
#[no_mangle]
pub extern "C" fn RouteHop_get_fee_msat(this_ptr: &RouteHop) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fee_msat;
(*inner_val)
}
/// The fee taken on this hop. For the last hop, this should be the full value of the payment.
#[no_mangle]
pub extern "C" fn RouteHop_set_fee_msat(this_ptr: &mut RouteHop, mut val: u64) {
unsafe { &mut *this_ptr.inner }.fee_msat = val;
}
/// The CLTV delta added for this hop. For the last hop, this should be the full CLTV value
/// expected at the destination, in excess of the current block height.
#[no_mangle]
pub extern "C" fn RouteHop_get_cltv_expiry_delta(this_ptr: &RouteHop) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.cltv_expiry_delta;
(*inner_val)
}
/// The CLTV delta added for this hop. For the last hop, this should be the full CLTV value
/// expected at the destination, in excess of the current block height.
#[no_mangle]
pub extern "C" fn RouteHop_set_cltv_expiry_delta(this_ptr: &mut RouteHop, mut val: u32) {
unsafe { &mut *this_ptr.inner }.cltv_expiry_delta = val;
}
use lightning::routing::router::Route as nativeRouteImport;
type nativeRoute = nativeRouteImport;
/// A route directs a payment from the sender (us) to the recipient. If the recipient supports MPP,
/// it can take multiple paths. Each path is composed of one or more hops through the network.
#[must_use]
#[repr(C)]
pub struct Route {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeRoute,
pub is_owned: bool,
}
impl Drop for Route {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn Route_free(this_ptr: Route) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn Route_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeRoute); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl Route {
pub(crate) fn take_ptr(mut self) -> *mut nativeRoute {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for Route {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn Route_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRoute)).clone() })) as *mut c_void
}
/// The list of routes taken for a single (potentially-)multi-part payment. The pubkey of the
/// last RouteHop in each path must be the same.
/// Each entry represents a list of hops, NOT INCLUDING our own, where the last hop is the
/// destination. Thus, this must always be at least length one. While the maximum length of any
/// given path is variable, keeping the length of any path to less than 20 should currently
/// ensure it is viable.
#[no_mangle]
pub extern "C" fn Route_set_paths(this_ptr: &mut Route, mut val: crate::c_types::derived::CVec_CVec_RouteHopZZ) {
let mut local_val = Vec::new(); for mut item in val.into_rust().drain(..) { local_val.push( { let mut local_val_0 = Vec::new(); for mut item in item.into_rust().drain(..) { local_val_0.push( { *unsafe { Box::from_raw(item.take_ptr()) } }); }; local_val_0 }); };
unsafe { &mut *this_ptr.inner }.paths = local_val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn Route_new(mut paths_arg: crate::c_types::derived::CVec_CVec_RouteHopZZ) -> Route {
let mut local_paths_arg = Vec::new(); for mut item in paths_arg.into_rust().drain(..) { local_paths_arg.push( { let mut local_paths_arg_0 = Vec::new(); for mut item in item.into_rust().drain(..) { local_paths_arg_0.push( { *unsafe { Box::from_raw(item.take_ptr()) } }); }; local_paths_arg_0 }); };
Route { inner: Box::into_raw(Box::new(nativeRoute {
paths: local_paths_arg,
})), is_owned: true }
}
#[no_mangle]
pub extern "C" fn Route_write(obj: *const Route) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn Route_read(ser: crate::c_types::u8slice) -> Route {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
Route { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
Route { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::routing::router::RouteHint as nativeRouteHintImport;
type nativeRouteHint = nativeRouteHintImport;
/// A channel descriptor which provides a last-hop route to get_route
#[must_use]
#[repr(C)]
pub struct RouteHint {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeRouteHint,
pub is_owned: bool,
}
impl Drop for RouteHint {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn RouteHint_free(this_ptr: RouteHint) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn RouteHint_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeRouteHint); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl RouteHint {
pub(crate) fn take_ptr(mut self) -> *mut nativeRouteHint {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
/// The node_id of the non-target end of the route
#[no_mangle]
pub extern "C" fn RouteHint_get_src_node_id(this_ptr: &RouteHint) -> crate::c_types::PublicKey {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.src_node_id;
crate::c_types::PublicKey::from_rust(&(*inner_val))
}
/// The node_id of the non-target end of the route
#[no_mangle]
pub extern "C" fn RouteHint_set_src_node_id(this_ptr: &mut RouteHint, mut val: crate::c_types::PublicKey) {
unsafe { &mut *this_ptr.inner }.src_node_id = val.into_rust();
}
/// The short_channel_id of this channel
#[no_mangle]
pub extern "C" fn RouteHint_get_short_channel_id(this_ptr: &RouteHint) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.short_channel_id;
(*inner_val)
}
/// The short_channel_id of this channel
#[no_mangle]
pub extern "C" fn RouteHint_set_short_channel_id(this_ptr: &mut RouteHint, mut val: u64) {
unsafe { &mut *this_ptr.inner }.short_channel_id = val;
}
/// The fees which must be paid to use this channel
#[no_mangle]
pub extern "C" fn RouteHint_get_fees(this_ptr: &RouteHint) -> crate::routing::network_graph::RoutingFees {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fees;
crate::routing::network_graph::RoutingFees { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false }
}
/// The fees which must be paid to use this channel
#[no_mangle]
pub extern "C" fn RouteHint_set_fees(this_ptr: &mut RouteHint, mut val: crate::routing::network_graph::RoutingFees) {
unsafe { &mut *this_ptr.inner }.fees = *unsafe { Box::from_raw(val.take_ptr()) };
}
/// The difference in CLTV values between this node and the next node.
#[no_mangle]
pub extern "C" fn RouteHint_get_cltv_expiry_delta(this_ptr: &RouteHint) -> u16 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.cltv_expiry_delta;
(*inner_val)
}
/// The difference in CLTV values between this node and the next node.
#[no_mangle]
pub extern "C" fn RouteHint_set_cltv_expiry_delta(this_ptr: &mut RouteHint, mut val: u16) {
unsafe { &mut *this_ptr.inner }.cltv_expiry_delta = val;
}
/// The minimum value, in msat, which must be relayed to the next hop.
#[no_mangle]
pub extern "C" fn RouteHint_get_htlc_minimum_msat(this_ptr: &RouteHint) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.htlc_minimum_msat;
(*inner_val)
}
/// The minimum value, in msat, which must be relayed to the next hop.
#[no_mangle]
pub extern "C" fn RouteHint_set_htlc_minimum_msat(this_ptr: &mut RouteHint, mut val: u64) {
unsafe { &mut *this_ptr.inner }.htlc_minimum_msat = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn RouteHint_new(mut src_node_id_arg: crate::c_types::PublicKey, mut short_channel_id_arg: u64, mut fees_arg: crate::routing::network_graph::RoutingFees, mut cltv_expiry_delta_arg: u16, mut htlc_minimum_msat_arg: u64) -> RouteHint {
RouteHint { inner: Box::into_raw(Box::new(nativeRouteHint {
src_node_id: src_node_id_arg.into_rust(),
short_channel_id: short_channel_id_arg,
fees: *unsafe { Box::from_raw(fees_arg.take_ptr()) },
cltv_expiry_delta: cltv_expiry_delta_arg,
htlc_minimum_msat: htlc_minimum_msat_arg,
})), is_owned: true }
}
/// Gets a route from us to the given target node.
///
/// Extra routing hops between known nodes and the target will be used if they are included in
/// last_hops.
///
/// If some channels aren't announced, it may be useful to fill in a first_hops with the
/// results from a local ChannelManager::list_usable_channels() call. If it is filled in, our
/// view of our local channels (from net_graph_msg_handler) will be ignored, and only those in first_hops
/// will be used.
///
/// Panics if first_hops contains channels without short_channel_ids
/// (ChannelManager::list_usable_channels will never include such channels).
///
/// The fees on channels from us to next-hops are ignored (as they are assumed to all be
/// equal), however the enabled/disabled bit on such channels as well as the htlc_minimum_msat
/// *is* checked as they may change based on the receiving node.
#[no_mangle]
pub extern "C" fn get_route(our_node_id: crate::c_types::PublicKey, network: &crate::routing::network_graph::NetworkGraph, target: crate::c_types::PublicKey, mut first_hops: *mut crate::c_types::derived::CVec_ChannelDetailsZ, mut last_hops: crate::c_types::derived::CVec_RouteHintZ, mut final_value_msat: u64, mut final_cltv: u32, mut logger: crate::util::logger::Logger) -> crate::c_types::derived::CResult_RouteLightningErrorZ {
let mut local_first_hops_base = if first_hops.is_null() { None } else { Some( { let mut local_first_hops_0 = Vec::new(); for mut item in unsafe { &mut *first_hops }.as_slice().iter() { local_first_hops_0.push( { unsafe { &*item.inner } }); }; local_first_hops_0 }) }; let mut local_first_hops = local_first_hops_base.as_ref().map(|a| &a[..]);
let mut local_last_hops = Vec::new(); for mut item in last_hops.as_slice().iter() { local_last_hops.push( { unsafe { &*item.inner } }); };
let mut ret = lightning::routing::router::get_route(&our_node_id.into_rust(), unsafe { &*network.inner }, &target.into_rust(), local_first_hops, &local_last_hops[..], final_value_msat, final_cltv, logger);
let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::routing::router::Route { inner: Box::into_raw(Box::new(o)), is_owned: true } }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::msgs::LightningError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) };
local_ret
}

View file

@ -0,0 +1,687 @@
//! Various user-configurable channel limits and settings which ChannelManager
//! applies for you.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
use lightning::util::config::ChannelHandshakeConfig as nativeChannelHandshakeConfigImport;
type nativeChannelHandshakeConfig = nativeChannelHandshakeConfigImport;
/// Configuration we set when applicable.
///
/// Default::default() provides sane defaults.
#[must_use]
#[repr(C)]
pub struct ChannelHandshakeConfig {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelHandshakeConfig,
pub is_owned: bool,
}
impl Drop for ChannelHandshakeConfig {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_free(this_ptr: ChannelHandshakeConfig) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelHandshakeConfig_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelHandshakeConfig); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelHandshakeConfig {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelHandshakeConfig {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for ChannelHandshakeConfig {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn ChannelHandshakeConfig_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelHandshakeConfig)).clone() })) as *mut c_void
}
/// Confirmations we will wait for before considering the channel locked in.
/// Applied only for inbound channels (see ChannelHandshakeLimits::max_minimum_depth for the
/// equivalent limit applied to outbound channels).
///
/// Default value: 6.
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_get_minimum_depth(this_ptr: &ChannelHandshakeConfig) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.minimum_depth;
(*inner_val)
}
/// Confirmations we will wait for before considering the channel locked in.
/// Applied only for inbound channels (see ChannelHandshakeLimits::max_minimum_depth for the
/// equivalent limit applied to outbound channels).
///
/// Default value: 6.
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_set_minimum_depth(this_ptr: &mut ChannelHandshakeConfig, mut val: u32) {
unsafe { &mut *this_ptr.inner }.minimum_depth = val;
}
/// Set to the amount of time we require our counterparty to wait to claim their money.
///
/// It's one of the main parameter of our security model. We (or one of our watchtowers) MUST
/// be online to check for peer having broadcast a revoked transaction to steal our funds
/// at least once every our_to_self_delay blocks.
///
/// Meanwhile, asking for a too high delay, we bother peer to freeze funds for nothing in
/// case of an honest unilateral channel close, which implicitly decrease the economic value of
/// our channel.
///
/// Default value: BREAKDOWN_TIMEOUT (currently 144), we enforce it as a minimum at channel
/// opening so you can tweak config to ask for more security, not less.
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_get_our_to_self_delay(this_ptr: &ChannelHandshakeConfig) -> u16 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.our_to_self_delay;
(*inner_val)
}
/// Set to the amount of time we require our counterparty to wait to claim their money.
///
/// It's one of the main parameter of our security model. We (or one of our watchtowers) MUST
/// be online to check for peer having broadcast a revoked transaction to steal our funds
/// at least once every our_to_self_delay blocks.
///
/// Meanwhile, asking for a too high delay, we bother peer to freeze funds for nothing in
/// case of an honest unilateral channel close, which implicitly decrease the economic value of
/// our channel.
///
/// Default value: BREAKDOWN_TIMEOUT (currently 144), we enforce it as a minimum at channel
/// opening so you can tweak config to ask for more security, not less.
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_set_our_to_self_delay(this_ptr: &mut ChannelHandshakeConfig, mut val: u16) {
unsafe { &mut *this_ptr.inner }.our_to_self_delay = val;
}
/// Set to the smallest value HTLC we will accept to process.
///
/// This value is sent to our counterparty on channel-open and we close the channel any time
/// our counterparty misbehaves by sending us an HTLC with a value smaller than this.
///
/// Default value: 1. If the value is less than 1, it is ignored and set to 1, as is required
/// by the protocol.
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_get_our_htlc_minimum_msat(this_ptr: &ChannelHandshakeConfig) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.our_htlc_minimum_msat;
(*inner_val)
}
/// Set to the smallest value HTLC we will accept to process.
///
/// This value is sent to our counterparty on channel-open and we close the channel any time
/// our counterparty misbehaves by sending us an HTLC with a value smaller than this.
///
/// Default value: 1. If the value is less than 1, it is ignored and set to 1, as is required
/// by the protocol.
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_set_our_htlc_minimum_msat(this_ptr: &mut ChannelHandshakeConfig, mut val: u64) {
unsafe { &mut *this_ptr.inner }.our_htlc_minimum_msat = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_new(mut minimum_depth_arg: u32, mut our_to_self_delay_arg: u16, mut our_htlc_minimum_msat_arg: u64) -> ChannelHandshakeConfig {
ChannelHandshakeConfig { inner: Box::into_raw(Box::new(nativeChannelHandshakeConfig {
minimum_depth: minimum_depth_arg,
our_to_self_delay: our_to_self_delay_arg,
our_htlc_minimum_msat: our_htlc_minimum_msat_arg,
})), is_owned: true }
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelHandshakeConfig_default() -> ChannelHandshakeConfig {
ChannelHandshakeConfig { inner: Box::into_raw(Box::new(Default::default())), is_owned: true }
}
use lightning::util::config::ChannelHandshakeLimits as nativeChannelHandshakeLimitsImport;
type nativeChannelHandshakeLimits = nativeChannelHandshakeLimitsImport;
/// Optional channel limits which are applied during channel creation.
///
/// These limits are only applied to our counterparty's limits, not our own.
///
/// Use 0/<type>::max_value() as appropriate to skip checking.
///
/// Provides sane defaults for most configurations.
///
/// Most additional limits are disabled except those with which specify a default in individual
/// field documentation. Note that this may result in barely-usable channels, but since they
/// are applied mostly only to incoming channels that's not much of a problem.
#[must_use]
#[repr(C)]
pub struct ChannelHandshakeLimits {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelHandshakeLimits,
pub is_owned: bool,
}
impl Drop for ChannelHandshakeLimits {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_free(this_ptr: ChannelHandshakeLimits) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelHandshakeLimits_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelHandshakeLimits); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelHandshakeLimits {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelHandshakeLimits {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for ChannelHandshakeLimits {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn ChannelHandshakeLimits_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelHandshakeLimits)).clone() })) as *mut c_void
}
/// Minimum allowed satoshis when a channel is funded, this is supplied by the sender and so
/// only applies to inbound channels.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_min_funding_satoshis(this_ptr: &ChannelHandshakeLimits) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.min_funding_satoshis;
(*inner_val)
}
/// Minimum allowed satoshis when a channel is funded, this is supplied by the sender and so
/// only applies to inbound channels.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_min_funding_satoshis(this_ptr: &mut ChannelHandshakeLimits, mut val: u64) {
unsafe { &mut *this_ptr.inner }.min_funding_satoshis = val;
}
/// The remote node sets a limit on the minimum size of HTLCs we can send to them. This allows
/// you to limit the maximum minimum-size they can require.
///
/// Default value: u64::max_value.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_max_htlc_minimum_msat(this_ptr: &ChannelHandshakeLimits) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.max_htlc_minimum_msat;
(*inner_val)
}
/// The remote node sets a limit on the minimum size of HTLCs we can send to them. This allows
/// you to limit the maximum minimum-size they can require.
///
/// Default value: u64::max_value.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_max_htlc_minimum_msat(this_ptr: &mut ChannelHandshakeLimits, mut val: u64) {
unsafe { &mut *this_ptr.inner }.max_htlc_minimum_msat = val;
}
/// The remote node sets a limit on the maximum value of pending HTLCs to them at any given
/// time to limit their funds exposure to HTLCs. This allows you to set a minimum such value.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_min_max_htlc_value_in_flight_msat(this_ptr: &ChannelHandshakeLimits) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.min_max_htlc_value_in_flight_msat;
(*inner_val)
}
/// The remote node sets a limit on the maximum value of pending HTLCs to them at any given
/// time to limit their funds exposure to HTLCs. This allows you to set a minimum such value.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_min_max_htlc_value_in_flight_msat(this_ptr: &mut ChannelHandshakeLimits, mut val: u64) {
unsafe { &mut *this_ptr.inner }.min_max_htlc_value_in_flight_msat = val;
}
/// The remote node will require we keep a certain amount in direct payment to ourselves at all
/// time, ensuring that we are able to be punished if we broadcast an old state. This allows to
/// you limit the amount which we will have to keep to ourselves (and cannot use for HTLCs).
///
/// Default value: u64::max_value.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_max_channel_reserve_satoshis(this_ptr: &ChannelHandshakeLimits) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.max_channel_reserve_satoshis;
(*inner_val)
}
/// The remote node will require we keep a certain amount in direct payment to ourselves at all
/// time, ensuring that we are able to be punished if we broadcast an old state. This allows to
/// you limit the amount which we will have to keep to ourselves (and cannot use for HTLCs).
///
/// Default value: u64::max_value.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_max_channel_reserve_satoshis(this_ptr: &mut ChannelHandshakeLimits, mut val: u64) {
unsafe { &mut *this_ptr.inner }.max_channel_reserve_satoshis = val;
}
/// The remote node sets a limit on the maximum number of pending HTLCs to them at any given
/// time. This allows you to set a minimum such value.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_min_max_accepted_htlcs(this_ptr: &ChannelHandshakeLimits) -> u16 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.min_max_accepted_htlcs;
(*inner_val)
}
/// The remote node sets a limit on the maximum number of pending HTLCs to them at any given
/// time. This allows you to set a minimum such value.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_min_max_accepted_htlcs(this_ptr: &mut ChannelHandshakeLimits, mut val: u16) {
unsafe { &mut *this_ptr.inner }.min_max_accepted_htlcs = val;
}
/// Outputs below a certain value will not be added to on-chain transactions. The dust value is
/// required to always be higher than this value so this only applies to HTLC outputs (and
/// potentially to-self outputs before any payments have been made).
/// Thus, HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain.
/// This setting allows you to set a minimum dust limit for their commitment transactions,
/// reflecting the reality that tiny outputs are not considered standard transactions and will
/// not propagate through the Bitcoin network.
///
/// Default value: 546, the current dust limit on the Bitcoin network.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_min_dust_limit_satoshis(this_ptr: &ChannelHandshakeLimits) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.min_dust_limit_satoshis;
(*inner_val)
}
/// Outputs below a certain value will not be added to on-chain transactions. The dust value is
/// required to always be higher than this value so this only applies to HTLC outputs (and
/// potentially to-self outputs before any payments have been made).
/// Thus, HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain.
/// This setting allows you to set a minimum dust limit for their commitment transactions,
/// reflecting the reality that tiny outputs are not considered standard transactions and will
/// not propagate through the Bitcoin network.
///
/// Default value: 546, the current dust limit on the Bitcoin network.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_min_dust_limit_satoshis(this_ptr: &mut ChannelHandshakeLimits, mut val: u64) {
unsafe { &mut *this_ptr.inner }.min_dust_limit_satoshis = val;
}
/// Maximum allowed threshold above which outputs will not be generated in their commitment
/// transactions.
/// HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain.
///
/// Default value: u64::max_value.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_max_dust_limit_satoshis(this_ptr: &ChannelHandshakeLimits) -> u64 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.max_dust_limit_satoshis;
(*inner_val)
}
/// Maximum allowed threshold above which outputs will not be generated in their commitment
/// transactions.
/// HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain.
///
/// Default value: u64::max_value.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_max_dust_limit_satoshis(this_ptr: &mut ChannelHandshakeLimits, mut val: u64) {
unsafe { &mut *this_ptr.inner }.max_dust_limit_satoshis = val;
}
/// Before a channel is usable the funding transaction will need to be confirmed by at least a
/// certain number of blocks, specified by the node which is not the funder (as the funder can
/// assume they aren't going to double-spend themselves).
/// This config allows you to set a limit on the maximum amount of time to wait.
///
/// Default value: 144, or roughly one day and only applies to outbound channels.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_max_minimum_depth(this_ptr: &ChannelHandshakeLimits) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.max_minimum_depth;
(*inner_val)
}
/// Before a channel is usable the funding transaction will need to be confirmed by at least a
/// certain number of blocks, specified by the node which is not the funder (as the funder can
/// assume they aren't going to double-spend themselves).
/// This config allows you to set a limit on the maximum amount of time to wait.
///
/// Default value: 144, or roughly one day and only applies to outbound channels.
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_max_minimum_depth(this_ptr: &mut ChannelHandshakeLimits, mut val: u32) {
unsafe { &mut *this_ptr.inner }.max_minimum_depth = val;
}
/// Set to force the incoming channel to match our announced channel preference in
/// ChannelConfig.
///
/// Default value: true, to make the default that no announced channels are possible (which is
/// appropriate for any nodes which are not online very reliably).
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_force_announced_channel_preference(this_ptr: &ChannelHandshakeLimits) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.force_announced_channel_preference;
(*inner_val)
}
/// Set to force the incoming channel to match our announced channel preference in
/// ChannelConfig.
///
/// Default value: true, to make the default that no announced channels are possible (which is
/// appropriate for any nodes which are not online very reliably).
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_force_announced_channel_preference(this_ptr: &mut ChannelHandshakeLimits, mut val: bool) {
unsafe { &mut *this_ptr.inner }.force_announced_channel_preference = val;
}
/// Set to the amount of time we're willing to wait to claim money back to us.
///
/// Not checking this value would be a security issue, as our peer would be able to set it to
/// max relative lock-time (a year) and we would \"lose\" money as it would be locked for a long time.
///
/// Default value: MAX_LOCAL_BREAKDOWN_TIMEOUT (1008), which we also enforce as a maximum value
/// so you can tweak config to reduce the loss of having useless locked funds (if your peer accepts)
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_get_their_to_self_delay(this_ptr: &ChannelHandshakeLimits) -> u16 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.their_to_self_delay;
(*inner_val)
}
/// Set to the amount of time we're willing to wait to claim money back to us.
///
/// Not checking this value would be a security issue, as our peer would be able to set it to
/// max relative lock-time (a year) and we would \"lose\" money as it would be locked for a long time.
///
/// Default value: MAX_LOCAL_BREAKDOWN_TIMEOUT (1008), which we also enforce as a maximum value
/// so you can tweak config to reduce the loss of having useless locked funds (if your peer accepts)
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_set_their_to_self_delay(this_ptr: &mut ChannelHandshakeLimits, mut val: u16) {
unsafe { &mut *this_ptr.inner }.their_to_self_delay = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_new(mut min_funding_satoshis_arg: u64, mut max_htlc_minimum_msat_arg: u64, mut min_max_htlc_value_in_flight_msat_arg: u64, mut max_channel_reserve_satoshis_arg: u64, mut min_max_accepted_htlcs_arg: u16, mut min_dust_limit_satoshis_arg: u64, mut max_dust_limit_satoshis_arg: u64, mut max_minimum_depth_arg: u32, mut force_announced_channel_preference_arg: bool, mut their_to_self_delay_arg: u16) -> ChannelHandshakeLimits {
ChannelHandshakeLimits { inner: Box::into_raw(Box::new(nativeChannelHandshakeLimits {
min_funding_satoshis: min_funding_satoshis_arg,
max_htlc_minimum_msat: max_htlc_minimum_msat_arg,
min_max_htlc_value_in_flight_msat: min_max_htlc_value_in_flight_msat_arg,
max_channel_reserve_satoshis: max_channel_reserve_satoshis_arg,
min_max_accepted_htlcs: min_max_accepted_htlcs_arg,
min_dust_limit_satoshis: min_dust_limit_satoshis_arg,
max_dust_limit_satoshis: max_dust_limit_satoshis_arg,
max_minimum_depth: max_minimum_depth_arg,
force_announced_channel_preference: force_announced_channel_preference_arg,
their_to_self_delay: their_to_self_delay_arg,
})), is_owned: true }
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelHandshakeLimits_default() -> ChannelHandshakeLimits {
ChannelHandshakeLimits { inner: Box::into_raw(Box::new(Default::default())), is_owned: true }
}
use lightning::util::config::ChannelConfig as nativeChannelConfigImport;
type nativeChannelConfig = nativeChannelConfigImport;
/// Options which apply on a per-channel basis and may change at runtime or based on negotiation
/// with our counterparty.
#[must_use]
#[repr(C)]
pub struct ChannelConfig {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeChannelConfig,
pub is_owned: bool,
}
impl Drop for ChannelConfig {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn ChannelConfig_free(this_ptr: ChannelConfig) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn ChannelConfig_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeChannelConfig); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl ChannelConfig {
pub(crate) fn take_ptr(mut self) -> *mut nativeChannelConfig {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for ChannelConfig {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn ChannelConfig_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelConfig)).clone() })) as *mut c_void
}
/// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
/// This may be allowed to change at runtime in a later update, however doing so must result in
/// update messages sent to notify all nodes of our updated relay fee.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelConfig_get_fee_proportional_millionths(this_ptr: &ChannelConfig) -> u32 {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fee_proportional_millionths;
(*inner_val)
}
/// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
/// This may be allowed to change at runtime in a later update, however doing so must result in
/// update messages sent to notify all nodes of our updated relay fee.
///
/// Default value: 0.
#[no_mangle]
pub extern "C" fn ChannelConfig_set_fee_proportional_millionths(this_ptr: &mut ChannelConfig, mut val: u32) {
unsafe { &mut *this_ptr.inner }.fee_proportional_millionths = val;
}
/// Set to announce the channel publicly and notify all nodes that they can route via this
/// channel.
///
/// This should only be set to true for nodes which expect to be online reliably.
///
/// As the node which funds a channel picks this value this will only apply for new outbound
/// channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
///
/// This cannot be changed after the initial channel handshake.
///
/// Default value: false.
#[no_mangle]
pub extern "C" fn ChannelConfig_get_announced_channel(this_ptr: &ChannelConfig) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.announced_channel;
(*inner_val)
}
/// Set to announce the channel publicly and notify all nodes that they can route via this
/// channel.
///
/// This should only be set to true for nodes which expect to be online reliably.
///
/// As the node which funds a channel picks this value this will only apply for new outbound
/// channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
///
/// This cannot be changed after the initial channel handshake.
///
/// Default value: false.
#[no_mangle]
pub extern "C" fn ChannelConfig_set_announced_channel(this_ptr: &mut ChannelConfig, mut val: bool) {
unsafe { &mut *this_ptr.inner }.announced_channel = val;
}
/// When set, we commit to an upfront shutdown_pubkey at channel open. If our counterparty
/// supports it, they will then enforce the mutual-close output to us matches what we provided
/// at intialization, preventing us from closing to an alternate pubkey.
///
/// This is set to true by default to provide a slight increase in security, though ultimately
/// any attacker who is able to take control of a channel can just as easily send the funds via
/// lightning payments, so we never require that our counterparties support this option.
///
/// This cannot be changed after a channel has been initialized.
///
/// Default value: true.
#[no_mangle]
pub extern "C" fn ChannelConfig_get_commit_upfront_shutdown_pubkey(this_ptr: &ChannelConfig) -> bool {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.commit_upfront_shutdown_pubkey;
(*inner_val)
}
/// When set, we commit to an upfront shutdown_pubkey at channel open. If our counterparty
/// supports it, they will then enforce the mutual-close output to us matches what we provided
/// at intialization, preventing us from closing to an alternate pubkey.
///
/// This is set to true by default to provide a slight increase in security, though ultimately
/// any attacker who is able to take control of a channel can just as easily send the funds via
/// lightning payments, so we never require that our counterparties support this option.
///
/// This cannot be changed after a channel has been initialized.
///
/// Default value: true.
#[no_mangle]
pub extern "C" fn ChannelConfig_set_commit_upfront_shutdown_pubkey(this_ptr: &mut ChannelConfig, mut val: bool) {
unsafe { &mut *this_ptr.inner }.commit_upfront_shutdown_pubkey = val;
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelConfig_new(mut fee_proportional_millionths_arg: u32, mut announced_channel_arg: bool, mut commit_upfront_shutdown_pubkey_arg: bool) -> ChannelConfig {
ChannelConfig { inner: Box::into_raw(Box::new(nativeChannelConfig {
fee_proportional_millionths: fee_proportional_millionths_arg,
announced_channel: announced_channel_arg,
commit_upfront_shutdown_pubkey: commit_upfront_shutdown_pubkey_arg,
})), is_owned: true }
}
#[must_use]
#[no_mangle]
pub extern "C" fn ChannelConfig_default() -> ChannelConfig {
ChannelConfig { inner: Box::into_raw(Box::new(Default::default())), is_owned: true }
}
#[no_mangle]
pub extern "C" fn ChannelConfig_write(obj: *const ChannelConfig) -> crate::c_types::derived::CVec_u8Z {
crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) })
}
#[no_mangle]
pub extern "C" fn ChannelConfig_read(ser: crate::c_types::u8slice) -> ChannelConfig {
if let Ok(res) = crate::c_types::deserialize_obj(ser) {
ChannelConfig { inner: Box::into_raw(Box::new(res)), is_owned: true }
} else {
ChannelConfig { inner: std::ptr::null_mut(), is_owned: true }
}
}
use lightning::util::config::UserConfig as nativeUserConfigImport;
type nativeUserConfig = nativeUserConfigImport;
/// Top-level config which holds ChannelHandshakeLimits and ChannelConfig.
///
/// Default::default() provides sane defaults for most configurations
/// (but currently with 0 relay fees!)
#[must_use]
#[repr(C)]
pub struct UserConfig {
/// Nearly everyhwere, inner must be non-null, however in places where
/// the Rust equivalent takes an Option, it may be set to null to indicate None.
pub inner: *mut nativeUserConfig,
pub is_owned: bool,
}
impl Drop for UserConfig {
fn drop(&mut self) {
if self.is_owned && !self.inner.is_null() {
let _ = unsafe { Box::from_raw(self.inner) };
}
}
}
#[no_mangle]
pub extern "C" fn UserConfig_free(this_ptr: UserConfig) { }
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
extern "C" fn UserConfig_free_void(this_ptr: *mut c_void) {
unsafe { let _ = Box::from_raw(this_ptr as *mut nativeUserConfig); }
}
#[allow(unused)]
/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy
impl UserConfig {
pub(crate) fn take_ptr(mut self) -> *mut nativeUserConfig {
assert!(self.is_owned);
let ret = self.inner;
self.inner = std::ptr::null_mut();
ret
}
}
impl Clone for UserConfig {
fn clone(&self) -> Self {
Self {
inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())),
is_owned: true,
}
}
}
#[allow(unused)]
/// Used only if an object of this type is returned as a trait impl by a method
pub(crate) extern "C" fn UserConfig_clone_void(this_ptr: *const c_void) -> *mut c_void {
Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUserConfig)).clone() })) as *mut c_void
}
/// Channel config that we propose to our counterparty.
#[no_mangle]
pub extern "C" fn UserConfig_get_own_channel_config(this_ptr: &UserConfig) -> crate::util::config::ChannelHandshakeConfig {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.own_channel_config;
crate::util::config::ChannelHandshakeConfig { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false }
}
/// Channel config that we propose to our counterparty.
#[no_mangle]
pub extern "C" fn UserConfig_set_own_channel_config(this_ptr: &mut UserConfig, mut val: crate::util::config::ChannelHandshakeConfig) {
unsafe { &mut *this_ptr.inner }.own_channel_config = *unsafe { Box::from_raw(val.take_ptr()) };
}
/// Limits applied to our counterparty's proposed channel config settings.
#[no_mangle]
pub extern "C" fn UserConfig_get_peer_channel_config_limits(this_ptr: &UserConfig) -> crate::util::config::ChannelHandshakeLimits {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.peer_channel_config_limits;
crate::util::config::ChannelHandshakeLimits { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false }
}
/// Limits applied to our counterparty's proposed channel config settings.
#[no_mangle]
pub extern "C" fn UserConfig_set_peer_channel_config_limits(this_ptr: &mut UserConfig, mut val: crate::util::config::ChannelHandshakeLimits) {
unsafe { &mut *this_ptr.inner }.peer_channel_config_limits = *unsafe { Box::from_raw(val.take_ptr()) };
}
/// Channel config which affects behavior during channel lifetime.
#[no_mangle]
pub extern "C" fn UserConfig_get_channel_options(this_ptr: &UserConfig) -> crate::util::config::ChannelConfig {
let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.channel_options;
crate::util::config::ChannelConfig { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false }
}
/// Channel config which affects behavior during channel lifetime.
#[no_mangle]
pub extern "C" fn UserConfig_set_channel_options(this_ptr: &mut UserConfig, mut val: crate::util::config::ChannelConfig) {
unsafe { &mut *this_ptr.inner }.channel_options = *unsafe { Box::from_raw(val.take_ptr()) };
}
#[must_use]
#[no_mangle]
pub extern "C" fn UserConfig_new(mut own_channel_config_arg: crate::util::config::ChannelHandshakeConfig, mut peer_channel_config_limits_arg: crate::util::config::ChannelHandshakeLimits, mut channel_options_arg: crate::util::config::ChannelConfig) -> UserConfig {
UserConfig { inner: Box::into_raw(Box::new(nativeUserConfig {
own_channel_config: *unsafe { Box::from_raw(own_channel_config_arg.take_ptr()) },
peer_channel_config_limits: *unsafe { Box::from_raw(peer_channel_config_limits_arg.take_ptr()) },
channel_options: *unsafe { Box::from_raw(channel_options_arg.take_ptr()) },
})), is_owned: true }
}
#[must_use]
#[no_mangle]
pub extern "C" fn UserConfig_default() -> UserConfig {
UserConfig { inner: Box::into_raw(Box::new(Default::default())), is_owned: true }
}

View file

@ -0,0 +1,162 @@
//! Error types live here.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
/// Indicates an error on the client's part (usually some variant of attempting to use too-low or
/// too-high values)
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum APIError {
/// Indicates the API was wholly misused (see err for more). Cases where these can be returned
/// are documented, but generally indicates some precondition of a function was violated.
APIMisuseError {
err: crate::c_types::derived::CVec_u8Z,
},
/// Due to a high feerate, we were unable to complete the request.
/// For example, this may be returned if the feerate implies we cannot open a channel at the
/// requested value, but opening a larger channel would succeed.
FeeRateTooHigh {
err: crate::c_types::derived::CVec_u8Z,
feerate: u32,
},
/// A malformed Route was provided (eg overflowed value, node id mismatch, overly-looped route,
/// too-many-hops, etc).
RouteError {
err: crate::c_types::Str,
},
/// We were unable to complete the request as the Channel required to do so is unable to
/// complete the request (or was not found). This can take many forms, including disconnected
/// peer, channel at capacity, channel shutting down, etc.
ChannelUnavailable {
err: crate::c_types::derived::CVec_u8Z,
},
/// An attempt to call add/update_monitor returned an Err (ie you did this!), causing the
/// attempted action to fail.
MonitorUpdateFailed,
}
use lightning::util::errors::APIError as nativeAPIError;
impl APIError {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeAPIError {
match self {
APIError::APIMisuseError {ref err, } => {
let mut err_nonref = (*err).clone();
nativeAPIError::APIMisuseError {
err: String::from_utf8(err_nonref.into_rust()).unwrap(),
}
},
APIError::FeeRateTooHigh {ref err, ref feerate, } => {
let mut err_nonref = (*err).clone();
let mut feerate_nonref = (*feerate).clone();
nativeAPIError::FeeRateTooHigh {
err: String::from_utf8(err_nonref.into_rust()).unwrap(),
feerate: feerate_nonref,
}
},
APIError::RouteError {ref err, } => {
let mut err_nonref = (*err).clone();
nativeAPIError::RouteError {
err: err_nonref.into(),
}
},
APIError::ChannelUnavailable {ref err, } => {
let mut err_nonref = (*err).clone();
nativeAPIError::ChannelUnavailable {
err: String::from_utf8(err_nonref.into_rust()).unwrap(),
}
},
APIError::MonitorUpdateFailed => nativeAPIError::MonitorUpdateFailed,
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeAPIError {
match self {
APIError::APIMisuseError {mut err, } => {
nativeAPIError::APIMisuseError {
err: String::from_utf8(err.into_rust()).unwrap(),
}
},
APIError::FeeRateTooHigh {mut err, mut feerate, } => {
nativeAPIError::FeeRateTooHigh {
err: String::from_utf8(err.into_rust()).unwrap(),
feerate: feerate,
}
},
APIError::RouteError {mut err, } => {
nativeAPIError::RouteError {
err: err.into(),
}
},
APIError::ChannelUnavailable {mut err, } => {
nativeAPIError::ChannelUnavailable {
err: String::from_utf8(err.into_rust()).unwrap(),
}
},
APIError::MonitorUpdateFailed => nativeAPIError::MonitorUpdateFailed,
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeAPIError) -> Self {
match native {
nativeAPIError::APIMisuseError {ref err, } => {
let mut err_nonref = (*err).clone();
APIError::APIMisuseError {
err: err_nonref.into_bytes().into(),
}
},
nativeAPIError::FeeRateTooHigh {ref err, ref feerate, } => {
let mut err_nonref = (*err).clone();
let mut feerate_nonref = (*feerate).clone();
APIError::FeeRateTooHigh {
err: err_nonref.into_bytes().into(),
feerate: feerate_nonref,
}
},
nativeAPIError::RouteError {ref err, } => {
let mut err_nonref = (*err).clone();
APIError::RouteError {
err: err_nonref.into(),
}
},
nativeAPIError::ChannelUnavailable {ref err, } => {
let mut err_nonref = (*err).clone();
APIError::ChannelUnavailable {
err: err_nonref.into_bytes().into(),
}
},
nativeAPIError::MonitorUpdateFailed => APIError::MonitorUpdateFailed,
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeAPIError) -> Self {
match native {
nativeAPIError::APIMisuseError {mut err, } => {
APIError::APIMisuseError {
err: err.into_bytes().into(),
}
},
nativeAPIError::FeeRateTooHigh {mut err, mut feerate, } => {
APIError::FeeRateTooHigh {
err: err.into_bytes().into(),
feerate: feerate,
}
},
nativeAPIError::RouteError {mut err, } => {
APIError::RouteError {
err: err.into(),
}
},
nativeAPIError::ChannelUnavailable {mut err, } => {
APIError::ChannelUnavailable {
err: err.into_bytes().into(),
}
},
nativeAPIError::MonitorUpdateFailed => APIError::MonitorUpdateFailed,
}
}
}
#[no_mangle]
pub extern "C" fn APIError_free(this_ptr: APIError) { }

View file

@ -0,0 +1,937 @@
//! Events are returned from various bits in the library which indicate some action must be taken
//! by the client.
//!
//! Because we don't have a built-in runtime, it's up to the client to call events at a time in the
//! future, as well as generate and broadcast funding transactions handle payment preimages and a
//! few other things.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
/// An Event which you should probably take some action in response to.
///
/// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use
/// them directly as they don't round-trip exactly (for example FundingGenerationReady is never
/// written as it makes no sense to respond to it after reconnecting to peers).
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum Event {
/// Used to indicate that the client should generate a funding transaction with the given
/// parameters and then call ChannelManager::funding_transaction_generated.
/// Generated in ChannelManager message handling.
/// Note that *all inputs* in the funding transaction must spend SegWit outputs or your
/// counterparty can steal your funds!
FundingGenerationReady {
temporary_channel_id: crate::c_types::ThirtyTwoBytes,
channel_value_satoshis: u64,
output_script: crate::c_types::derived::CVec_u8Z,
user_channel_id: u64,
},
/// Used to indicate that the client may now broadcast the funding transaction it created for a
/// channel. Broadcasting such a transaction prior to this event may lead to our counterparty
/// trivially stealing all funds in the funding transaction!
FundingBroadcastSafe {
funding_txo: crate::chain::transaction::OutPoint,
user_channel_id: u64,
},
/// Indicates we've received money! Just gotta dig out that payment preimage and feed it to
/// ChannelManager::claim_funds to get it....
/// Note that if the preimage is not known or the amount paid is incorrect, you should call
/// ChannelManager::fail_htlc_backwards to free up resources for this HTLC and avoid
/// network congestion.
/// The amount paid should be considered 'incorrect' when it is less than or more than twice
/// the amount expected.
/// If you fail to call either ChannelManager::claim_funds or
/// ChannelManager::fail_htlc_backwards within the HTLC's timeout, the HTLC will be
/// automatically failed.
PaymentReceived {
payment_hash: crate::c_types::ThirtyTwoBytes,
payment_secret: crate::c_types::ThirtyTwoBytes,
amt: u64,
},
/// Indicates an outbound payment we made succeeded (ie it made it all the way to its target
/// and we got back the payment preimage for it).
/// Note that duplicative PaymentSent Events may be generated - it is your responsibility to
/// deduplicate them by payment_preimage (which MUST be unique)!
PaymentSent {
payment_preimage: crate::c_types::ThirtyTwoBytes,
},
/// Indicates an outbound payment we made failed. Probably some intermediary node dropped
/// something. You may wish to retry with a different route.
/// Note that duplicative PaymentFailed Events may be generated - it is your responsibility to
/// deduplicate them by payment_hash (which MUST be unique)!
PaymentFailed {
payment_hash: crate::c_types::ThirtyTwoBytes,
rejected_by_dest: bool,
},
/// Used to indicate that ChannelManager::process_pending_htlc_forwards should be called at a
/// time in the future.
PendingHTLCsForwardable {
time_forwardable: u64,
},
/// Used to indicate that an output was generated on-chain which you should know how to spend.
/// Such an output will *not* ever be spent by rust-lightning, and are not at risk of your
/// counterparty spending them due to some kind of timeout. Thus, you need to store them
/// somewhere and spend them when you create on-chain transactions.
SpendableOutputs {
outputs: crate::c_types::derived::CVec_SpendableOutputDescriptorZ,
},
}
use lightning::util::events::Event as nativeEvent;
impl Event {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeEvent {
match self {
Event::FundingGenerationReady {ref temporary_channel_id, ref channel_value_satoshis, ref output_script, ref user_channel_id, } => {
let mut temporary_channel_id_nonref = (*temporary_channel_id).clone();
let mut channel_value_satoshis_nonref = (*channel_value_satoshis).clone();
let mut output_script_nonref = (*output_script).clone();
let mut user_channel_id_nonref = (*user_channel_id).clone();
nativeEvent::FundingGenerationReady {
temporary_channel_id: temporary_channel_id_nonref.data,
channel_value_satoshis: channel_value_satoshis_nonref,
output_script: ::bitcoin::blockdata::script::Script::from(output_script_nonref.into_rust()),
user_channel_id: user_channel_id_nonref,
}
},
Event::FundingBroadcastSafe {ref funding_txo, ref user_channel_id, } => {
let mut funding_txo_nonref = (*funding_txo).clone();
let mut user_channel_id_nonref = (*user_channel_id).clone();
nativeEvent::FundingBroadcastSafe {
funding_txo: *unsafe { Box::from_raw(funding_txo_nonref.take_ptr()) },
user_channel_id: user_channel_id_nonref,
}
},
Event::PaymentReceived {ref payment_hash, ref payment_secret, ref amt, } => {
let mut payment_hash_nonref = (*payment_hash).clone();
let mut payment_secret_nonref = (*payment_secret).clone();
let mut local_payment_secret_nonref = if payment_secret_nonref.data == [0; 32] { None } else { Some( { ::lightning::ln::channelmanager::PaymentSecret(payment_secret_nonref.data) }) };
let mut amt_nonref = (*amt).clone();
nativeEvent::PaymentReceived {
payment_hash: ::lightning::ln::channelmanager::PaymentHash(payment_hash_nonref.data),
payment_secret: local_payment_secret_nonref,
amt: amt_nonref,
}
},
Event::PaymentSent {ref payment_preimage, } => {
let mut payment_preimage_nonref = (*payment_preimage).clone();
nativeEvent::PaymentSent {
payment_preimage: ::lightning::ln::channelmanager::PaymentPreimage(payment_preimage_nonref.data),
}
},
Event::PaymentFailed {ref payment_hash, ref rejected_by_dest, } => {
let mut payment_hash_nonref = (*payment_hash).clone();
let mut rejected_by_dest_nonref = (*rejected_by_dest).clone();
nativeEvent::PaymentFailed {
payment_hash: ::lightning::ln::channelmanager::PaymentHash(payment_hash_nonref.data),
rejected_by_dest: rejected_by_dest_nonref,
}
},
Event::PendingHTLCsForwardable {ref time_forwardable, } => {
let mut time_forwardable_nonref = (*time_forwardable).clone();
nativeEvent::PendingHTLCsForwardable {
time_forwardable: std::time::Duration::from_secs(time_forwardable_nonref),
}
},
Event::SpendableOutputs {ref outputs, } => {
let mut outputs_nonref = (*outputs).clone();
let mut local_outputs_nonref = Vec::new(); for mut item in outputs_nonref.into_rust().drain(..) { local_outputs_nonref.push( { item.into_native() }); };
nativeEvent::SpendableOutputs {
outputs: local_outputs_nonref,
}
},
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeEvent {
match self {
Event::FundingGenerationReady {mut temporary_channel_id, mut channel_value_satoshis, mut output_script, mut user_channel_id, } => {
nativeEvent::FundingGenerationReady {
temporary_channel_id: temporary_channel_id.data,
channel_value_satoshis: channel_value_satoshis,
output_script: ::bitcoin::blockdata::script::Script::from(output_script.into_rust()),
user_channel_id: user_channel_id,
}
},
Event::FundingBroadcastSafe {mut funding_txo, mut user_channel_id, } => {
nativeEvent::FundingBroadcastSafe {
funding_txo: *unsafe { Box::from_raw(funding_txo.take_ptr()) },
user_channel_id: user_channel_id,
}
},
Event::PaymentReceived {mut payment_hash, mut payment_secret, mut amt, } => {
let mut local_payment_secret = if payment_secret.data == [0; 32] { None } else { Some( { ::lightning::ln::channelmanager::PaymentSecret(payment_secret.data) }) };
nativeEvent::PaymentReceived {
payment_hash: ::lightning::ln::channelmanager::PaymentHash(payment_hash.data),
payment_secret: local_payment_secret,
amt: amt,
}
},
Event::PaymentSent {mut payment_preimage, } => {
nativeEvent::PaymentSent {
payment_preimage: ::lightning::ln::channelmanager::PaymentPreimage(payment_preimage.data),
}
},
Event::PaymentFailed {mut payment_hash, mut rejected_by_dest, } => {
nativeEvent::PaymentFailed {
payment_hash: ::lightning::ln::channelmanager::PaymentHash(payment_hash.data),
rejected_by_dest: rejected_by_dest,
}
},
Event::PendingHTLCsForwardable {mut time_forwardable, } => {
nativeEvent::PendingHTLCsForwardable {
time_forwardable: std::time::Duration::from_secs(time_forwardable),
}
},
Event::SpendableOutputs {mut outputs, } => {
let mut local_outputs = Vec::new(); for mut item in outputs.into_rust().drain(..) { local_outputs.push( { item.into_native() }); };
nativeEvent::SpendableOutputs {
outputs: local_outputs,
}
},
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeEvent) -> Self {
match native {
nativeEvent::FundingGenerationReady {ref temporary_channel_id, ref channel_value_satoshis, ref output_script, ref user_channel_id, } => {
let mut temporary_channel_id_nonref = (*temporary_channel_id).clone();
let mut channel_value_satoshis_nonref = (*channel_value_satoshis).clone();
let mut output_script_nonref = (*output_script).clone();
let mut user_channel_id_nonref = (*user_channel_id).clone();
Event::FundingGenerationReady {
temporary_channel_id: crate::c_types::ThirtyTwoBytes { data: temporary_channel_id_nonref },
channel_value_satoshis: channel_value_satoshis_nonref,
output_script: output_script_nonref.into_bytes().into(),
user_channel_id: user_channel_id_nonref,
}
},
nativeEvent::FundingBroadcastSafe {ref funding_txo, ref user_channel_id, } => {
let mut funding_txo_nonref = (*funding_txo).clone();
let mut user_channel_id_nonref = (*user_channel_id).clone();
Event::FundingBroadcastSafe {
funding_txo: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(funding_txo_nonref)), is_owned: true },
user_channel_id: user_channel_id_nonref,
}
},
nativeEvent::PaymentReceived {ref payment_hash, ref payment_secret, ref amt, } => {
let mut payment_hash_nonref = (*payment_hash).clone();
let mut payment_secret_nonref = (*payment_secret).clone();
let mut local_payment_secret_nonref = if payment_secret_nonref.is_none() { crate::c_types::ThirtyTwoBytes::null() } else { { crate::c_types::ThirtyTwoBytes { data: (payment_secret_nonref.unwrap()).0 } } };
let mut amt_nonref = (*amt).clone();
Event::PaymentReceived {
payment_hash: crate::c_types::ThirtyTwoBytes { data: payment_hash_nonref.0 },
payment_secret: local_payment_secret_nonref,
amt: amt_nonref,
}
},
nativeEvent::PaymentSent {ref payment_preimage, } => {
let mut payment_preimage_nonref = (*payment_preimage).clone();
Event::PaymentSent {
payment_preimage: crate::c_types::ThirtyTwoBytes { data: payment_preimage_nonref.0 },
}
},
nativeEvent::PaymentFailed {ref payment_hash, ref rejected_by_dest, } => {
let mut payment_hash_nonref = (*payment_hash).clone();
let mut rejected_by_dest_nonref = (*rejected_by_dest).clone();
Event::PaymentFailed {
payment_hash: crate::c_types::ThirtyTwoBytes { data: payment_hash_nonref.0 },
rejected_by_dest: rejected_by_dest_nonref,
}
},
nativeEvent::PendingHTLCsForwardable {ref time_forwardable, } => {
let mut time_forwardable_nonref = (*time_forwardable).clone();
Event::PendingHTLCsForwardable {
time_forwardable: time_forwardable_nonref.as_secs(),
}
},
nativeEvent::SpendableOutputs {ref outputs, } => {
let mut outputs_nonref = (*outputs).clone();
let mut local_outputs_nonref = Vec::new(); for item in outputs_nonref.drain(..) { local_outputs_nonref.push( { crate::chain::keysinterface::SpendableOutputDescriptor::native_into(item) }); };
Event::SpendableOutputs {
outputs: local_outputs_nonref.into(),
}
},
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeEvent) -> Self {
match native {
nativeEvent::FundingGenerationReady {mut temporary_channel_id, mut channel_value_satoshis, mut output_script, mut user_channel_id, } => {
Event::FundingGenerationReady {
temporary_channel_id: crate::c_types::ThirtyTwoBytes { data: temporary_channel_id },
channel_value_satoshis: channel_value_satoshis,
output_script: output_script.into_bytes().into(),
user_channel_id: user_channel_id,
}
},
nativeEvent::FundingBroadcastSafe {mut funding_txo, mut user_channel_id, } => {
Event::FundingBroadcastSafe {
funding_txo: crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(funding_txo)), is_owned: true },
user_channel_id: user_channel_id,
}
},
nativeEvent::PaymentReceived {mut payment_hash, mut payment_secret, mut amt, } => {
let mut local_payment_secret = if payment_secret.is_none() { crate::c_types::ThirtyTwoBytes::null() } else { { crate::c_types::ThirtyTwoBytes { data: (payment_secret.unwrap()).0 } } };
Event::PaymentReceived {
payment_hash: crate::c_types::ThirtyTwoBytes { data: payment_hash.0 },
payment_secret: local_payment_secret,
amt: amt,
}
},
nativeEvent::PaymentSent {mut payment_preimage, } => {
Event::PaymentSent {
payment_preimage: crate::c_types::ThirtyTwoBytes { data: payment_preimage.0 },
}
},
nativeEvent::PaymentFailed {mut payment_hash, mut rejected_by_dest, } => {
Event::PaymentFailed {
payment_hash: crate::c_types::ThirtyTwoBytes { data: payment_hash.0 },
rejected_by_dest: rejected_by_dest,
}
},
nativeEvent::PendingHTLCsForwardable {mut time_forwardable, } => {
Event::PendingHTLCsForwardable {
time_forwardable: time_forwardable.as_secs(),
}
},
nativeEvent::SpendableOutputs {mut outputs, } => {
let mut local_outputs = Vec::new(); for item in outputs.drain(..) { local_outputs.push( { crate::chain::keysinterface::SpendableOutputDescriptor::native_into(item) }); };
Event::SpendableOutputs {
outputs: local_outputs.into(),
}
},
}
}
}
#[no_mangle]
pub extern "C" fn Event_free(this_ptr: Event) { }
/// An event generated by ChannelManager which indicates a message should be sent to a peer (or
/// broadcast to most peers).
/// These events are handled by PeerManager::process_events if you are using a PeerManager.
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum MessageSendEvent {
/// Used to indicate that we've accepted a channel open and should send the accept_channel
/// message provided to the given peer.
SendAcceptChannel {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::AcceptChannel,
},
/// Used to indicate that we've initiated a channel open and should send the open_channel
/// message provided to the given peer.
SendOpenChannel {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::OpenChannel,
},
/// Used to indicate that a funding_created message should be sent to the peer with the given node_id.
SendFundingCreated {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::FundingCreated,
},
/// Used to indicate that a funding_signed message should be sent to the peer with the given node_id.
SendFundingSigned {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::FundingSigned,
},
/// Used to indicate that a funding_locked message should be sent to the peer with the given node_id.
SendFundingLocked {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::FundingLocked,
},
/// Used to indicate that an announcement_signatures message should be sent to the peer with the given node_id.
SendAnnouncementSignatures {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::AnnouncementSignatures,
},
/// Used to indicate that a series of HTLC update messages, as well as a commitment_signed
/// message should be sent to the peer with the given node_id.
UpdateHTLCs {
node_id: crate::c_types::PublicKey,
updates: crate::ln::msgs::CommitmentUpdate,
},
/// Used to indicate that a revoke_and_ack message should be sent to the peer with the given node_id.
SendRevokeAndACK {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::RevokeAndACK,
},
/// Used to indicate that a closing_signed message should be sent to the peer with the given node_id.
SendClosingSigned {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::ClosingSigned,
},
/// Used to indicate that a shutdown message should be sent to the peer with the given node_id.
SendShutdown {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::Shutdown,
},
/// Used to indicate that a channel_reestablish message should be sent to the peer with the given node_id.
SendChannelReestablish {
node_id: crate::c_types::PublicKey,
msg: crate::ln::msgs::ChannelReestablish,
},
/// Used to indicate that a channel_announcement and channel_update should be broadcast to all
/// peers (except the peer with node_id either msg.contents.node_id_1 or msg.contents.node_id_2).
///
/// Note that after doing so, you very likely (unless you did so very recently) want to call
/// ChannelManager::broadcast_node_announcement to trigger a BroadcastNodeAnnouncement event.
/// This ensures that any nodes which see our channel_announcement also have a relevant
/// node_announcement, including relevant feature flags which may be important for routing
/// through or to us.
BroadcastChannelAnnouncement {
msg: crate::ln::msgs::ChannelAnnouncement,
update_msg: crate::ln::msgs::ChannelUpdate,
},
/// Used to indicate that a node_announcement should be broadcast to all peers.
BroadcastNodeAnnouncement {
msg: crate::ln::msgs::NodeAnnouncement,
},
/// Used to indicate that a channel_update should be broadcast to all peers.
BroadcastChannelUpdate {
msg: crate::ln::msgs::ChannelUpdate,
},
/// Broadcast an error downstream to be handled
HandleError {
node_id: crate::c_types::PublicKey,
action: crate::ln::msgs::ErrorAction,
},
/// When a payment fails we may receive updates back from the hop where it failed. In such
/// cases this event is generated so that we can inform the network graph of this information.
PaymentFailureNetworkUpdate {
update: crate::ln::msgs::HTLCFailChannelUpdate,
},
}
use lightning::util::events::MessageSendEvent as nativeMessageSendEvent;
impl MessageSendEvent {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeMessageSendEvent {
match self {
MessageSendEvent::SendAcceptChannel {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendAcceptChannel {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendOpenChannel {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendOpenChannel {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendFundingCreated {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendFundingCreated {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendFundingSigned {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendFundingSigned {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendFundingLocked {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendFundingLocked {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendAnnouncementSignatures {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendAnnouncementSignatures {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::UpdateHTLCs {ref node_id, ref updates, } => {
let mut node_id_nonref = (*node_id).clone();
let mut updates_nonref = (*updates).clone();
nativeMessageSendEvent::UpdateHTLCs {
node_id: node_id_nonref.into_rust(),
updates: *unsafe { Box::from_raw(updates_nonref.take_ptr()) },
}
},
MessageSendEvent::SendRevokeAndACK {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendRevokeAndACK {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendClosingSigned {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendClosingSigned {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendShutdown {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendShutdown {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::SendChannelReestablish {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::SendChannelReestablish {
node_id: node_id_nonref.into_rust(),
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::BroadcastChannelAnnouncement {ref msg, ref update_msg, } => {
let mut msg_nonref = (*msg).clone();
let mut update_msg_nonref = (*update_msg).clone();
nativeMessageSendEvent::BroadcastChannelAnnouncement {
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
update_msg: *unsafe { Box::from_raw(update_msg_nonref.take_ptr()) },
}
},
MessageSendEvent::BroadcastNodeAnnouncement {ref msg, } => {
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::BroadcastNodeAnnouncement {
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::BroadcastChannelUpdate {ref msg, } => {
let mut msg_nonref = (*msg).clone();
nativeMessageSendEvent::BroadcastChannelUpdate {
msg: *unsafe { Box::from_raw(msg_nonref.take_ptr()) },
}
},
MessageSendEvent::HandleError {ref node_id, ref action, } => {
let mut node_id_nonref = (*node_id).clone();
let mut action_nonref = (*action).clone();
nativeMessageSendEvent::HandleError {
node_id: node_id_nonref.into_rust(),
action: action_nonref.into_native(),
}
},
MessageSendEvent::PaymentFailureNetworkUpdate {ref update, } => {
let mut update_nonref = (*update).clone();
nativeMessageSendEvent::PaymentFailureNetworkUpdate {
update: update_nonref.into_native(),
}
},
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeMessageSendEvent {
match self {
MessageSendEvent::SendAcceptChannel {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendAcceptChannel {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendOpenChannel {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendOpenChannel {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendFundingCreated {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendFundingCreated {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendFundingSigned {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendFundingSigned {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendFundingLocked {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendFundingLocked {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendAnnouncementSignatures {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendAnnouncementSignatures {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::UpdateHTLCs {mut node_id, mut updates, } => {
nativeMessageSendEvent::UpdateHTLCs {
node_id: node_id.into_rust(),
updates: *unsafe { Box::from_raw(updates.take_ptr()) },
}
},
MessageSendEvent::SendRevokeAndACK {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendRevokeAndACK {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendClosingSigned {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendClosingSigned {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendShutdown {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendShutdown {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::SendChannelReestablish {mut node_id, mut msg, } => {
nativeMessageSendEvent::SendChannelReestablish {
node_id: node_id.into_rust(),
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::BroadcastChannelAnnouncement {mut msg, mut update_msg, } => {
nativeMessageSendEvent::BroadcastChannelAnnouncement {
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
update_msg: *unsafe { Box::from_raw(update_msg.take_ptr()) },
}
},
MessageSendEvent::BroadcastNodeAnnouncement {mut msg, } => {
nativeMessageSendEvent::BroadcastNodeAnnouncement {
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::BroadcastChannelUpdate {mut msg, } => {
nativeMessageSendEvent::BroadcastChannelUpdate {
msg: *unsafe { Box::from_raw(msg.take_ptr()) },
}
},
MessageSendEvent::HandleError {mut node_id, mut action, } => {
nativeMessageSendEvent::HandleError {
node_id: node_id.into_rust(),
action: action.into_native(),
}
},
MessageSendEvent::PaymentFailureNetworkUpdate {mut update, } => {
nativeMessageSendEvent::PaymentFailureNetworkUpdate {
update: update.into_native(),
}
},
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeMessageSendEvent) -> Self {
match native {
nativeMessageSendEvent::SendAcceptChannel {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendAcceptChannel {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::AcceptChannel { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendOpenChannel {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendOpenChannel {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::OpenChannel { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendFundingCreated {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendFundingCreated {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::FundingCreated { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendFundingSigned {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendFundingSigned {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::FundingSigned { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendFundingLocked {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendFundingLocked {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::FundingLocked { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendAnnouncementSignatures {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendAnnouncementSignatures {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::AnnouncementSignatures { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::UpdateHTLCs {ref node_id, ref updates, } => {
let mut node_id_nonref = (*node_id).clone();
let mut updates_nonref = (*updates).clone();
MessageSendEvent::UpdateHTLCs {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
updates: crate::ln::msgs::CommitmentUpdate { inner: Box::into_raw(Box::new(updates_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendRevokeAndACK {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendRevokeAndACK {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::RevokeAndACK { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendClosingSigned {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendClosingSigned {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::ClosingSigned { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendShutdown {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendShutdown {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::Shutdown { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::SendChannelReestablish {ref node_id, ref msg, } => {
let mut node_id_nonref = (*node_id).clone();
let mut msg_nonref = (*msg).clone();
MessageSendEvent::SendChannelReestablish {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
msg: crate::ln::msgs::ChannelReestablish { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::BroadcastChannelAnnouncement {ref msg, ref update_msg, } => {
let mut msg_nonref = (*msg).clone();
let mut update_msg_nonref = (*update_msg).clone();
MessageSendEvent::BroadcastChannelAnnouncement {
msg: crate::ln::msgs::ChannelAnnouncement { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
update_msg: crate::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(update_msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::BroadcastNodeAnnouncement {ref msg, } => {
let mut msg_nonref = (*msg).clone();
MessageSendEvent::BroadcastNodeAnnouncement {
msg: crate::ln::msgs::NodeAnnouncement { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::BroadcastChannelUpdate {ref msg, } => {
let mut msg_nonref = (*msg).clone();
MessageSendEvent::BroadcastChannelUpdate {
msg: crate::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(msg_nonref)), is_owned: true },
}
},
nativeMessageSendEvent::HandleError {ref node_id, ref action, } => {
let mut node_id_nonref = (*node_id).clone();
let mut action_nonref = (*action).clone();
MessageSendEvent::HandleError {
node_id: crate::c_types::PublicKey::from_rust(&node_id_nonref),
action: crate::ln::msgs::ErrorAction::native_into(action_nonref),
}
},
nativeMessageSendEvent::PaymentFailureNetworkUpdate {ref update, } => {
let mut update_nonref = (*update).clone();
MessageSendEvent::PaymentFailureNetworkUpdate {
update: crate::ln::msgs::HTLCFailChannelUpdate::native_into(update_nonref),
}
},
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeMessageSendEvent) -> Self {
match native {
nativeMessageSendEvent::SendAcceptChannel {mut node_id, mut msg, } => {
MessageSendEvent::SendAcceptChannel {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::AcceptChannel { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendOpenChannel {mut node_id, mut msg, } => {
MessageSendEvent::SendOpenChannel {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::OpenChannel { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendFundingCreated {mut node_id, mut msg, } => {
MessageSendEvent::SendFundingCreated {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::FundingCreated { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendFundingSigned {mut node_id, mut msg, } => {
MessageSendEvent::SendFundingSigned {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::FundingSigned { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendFundingLocked {mut node_id, mut msg, } => {
MessageSendEvent::SendFundingLocked {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::FundingLocked { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendAnnouncementSignatures {mut node_id, mut msg, } => {
MessageSendEvent::SendAnnouncementSignatures {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::AnnouncementSignatures { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::UpdateHTLCs {mut node_id, mut updates, } => {
MessageSendEvent::UpdateHTLCs {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
updates: crate::ln::msgs::CommitmentUpdate { inner: Box::into_raw(Box::new(updates)), is_owned: true },
}
},
nativeMessageSendEvent::SendRevokeAndACK {mut node_id, mut msg, } => {
MessageSendEvent::SendRevokeAndACK {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::RevokeAndACK { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendClosingSigned {mut node_id, mut msg, } => {
MessageSendEvent::SendClosingSigned {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::ClosingSigned { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendShutdown {mut node_id, mut msg, } => {
MessageSendEvent::SendShutdown {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::Shutdown { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::SendChannelReestablish {mut node_id, mut msg, } => {
MessageSendEvent::SendChannelReestablish {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
msg: crate::ln::msgs::ChannelReestablish { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::BroadcastChannelAnnouncement {mut msg, mut update_msg, } => {
MessageSendEvent::BroadcastChannelAnnouncement {
msg: crate::ln::msgs::ChannelAnnouncement { inner: Box::into_raw(Box::new(msg)), is_owned: true },
update_msg: crate::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(update_msg)), is_owned: true },
}
},
nativeMessageSendEvent::BroadcastNodeAnnouncement {mut msg, } => {
MessageSendEvent::BroadcastNodeAnnouncement {
msg: crate::ln::msgs::NodeAnnouncement { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::BroadcastChannelUpdate {mut msg, } => {
MessageSendEvent::BroadcastChannelUpdate {
msg: crate::ln::msgs::ChannelUpdate { inner: Box::into_raw(Box::new(msg)), is_owned: true },
}
},
nativeMessageSendEvent::HandleError {mut node_id, mut action, } => {
MessageSendEvent::HandleError {
node_id: crate::c_types::PublicKey::from_rust(&node_id),
action: crate::ln::msgs::ErrorAction::native_into(action),
}
},
nativeMessageSendEvent::PaymentFailureNetworkUpdate {mut update, } => {
MessageSendEvent::PaymentFailureNetworkUpdate {
update: crate::ln::msgs::HTLCFailChannelUpdate::native_into(update),
}
},
}
}
}
#[no_mangle]
pub extern "C" fn MessageSendEvent_free(this_ptr: MessageSendEvent) { }
/// A trait indicating an object may generate message send events
#[repr(C)]
pub struct MessageSendEventsProvider {
pub this_arg: *mut c_void,
/// Gets the list of pending events which were generated by previous actions, clearing the list
/// in the process.
#[must_use]
pub get_and_clear_pending_msg_events: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
use lightning::util::events::MessageSendEventsProvider as rustMessageSendEventsProvider;
impl rustMessageSendEventsProvider for MessageSendEventsProvider {
fn get_and_clear_pending_msg_events(&self) -> Vec<lightning::util::events::MessageSendEvent> {
let mut ret = (self.get_and_clear_pending_msg_events)(self.this_arg);
let mut local_ret = Vec::new(); for mut item in ret.into_rust().drain(..) { local_ret.push( { item.into_native() }); };
local_ret
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for MessageSendEventsProvider {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn MessageSendEventsProvider_free(this_ptr: MessageSendEventsProvider) { }
impl Drop for MessageSendEventsProvider {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}
/// A trait indicating an object may generate events
#[repr(C)]
pub struct EventsProvider {
pub this_arg: *mut c_void,
/// Gets the list of pending events which were generated by previous actions, clearing the list
/// in the process.
#[must_use]
pub get_and_clear_pending_events: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_EventZ,
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
use lightning::util::events::EventsProvider as rustEventsProvider;
impl rustEventsProvider for EventsProvider {
fn get_and_clear_pending_events(&self) -> Vec<lightning::util::events::Event> {
let mut ret = (self.get_and_clear_pending_events)(self.this_arg);
let mut local_ret = Vec::new(); for mut item in ret.into_rust().drain(..) { local_ret.push( { item.into_native() }); };
local_ret
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for EventsProvider {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn EventsProvider_free(this_ptr: EventsProvider) { }
impl Drop for EventsProvider {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}

View file

@ -0,0 +1,121 @@
//! Log traits live here, which are called throughout the library to provide useful information for
//! debugging purposes.
//!
//! There is currently 2 ways to filter log messages. First one, by using compilation features, e.g \"max_level_off\".
//! The second one, client-side by implementing check against Record Level field.
//! Each module may have its own Logger or share one.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
/// An enum representing the available verbosity levels of the logger.
#[must_use]
#[derive(Clone)]
#[repr(C)]
pub enum Level {
///Designates logger being silent
Off,
/// Designates very serious errors
Error,
/// Designates hazardous situations
Warn,
/// Designates useful information
Info,
/// Designates lower priority information
Debug,
/// Designates very low priority, often extremely verbose, information
Trace,
}
use lightning::util::logger::Level as nativeLevel;
impl Level {
#[allow(unused)]
pub(crate) fn to_native(&self) -> nativeLevel {
match self {
Level::Off => nativeLevel::Off,
Level::Error => nativeLevel::Error,
Level::Warn => nativeLevel::Warn,
Level::Info => nativeLevel::Info,
Level::Debug => nativeLevel::Debug,
Level::Trace => nativeLevel::Trace,
}
}
#[allow(unused)]
pub(crate) fn into_native(self) -> nativeLevel {
match self {
Level::Off => nativeLevel::Off,
Level::Error => nativeLevel::Error,
Level::Warn => nativeLevel::Warn,
Level::Info => nativeLevel::Info,
Level::Debug => nativeLevel::Debug,
Level::Trace => nativeLevel::Trace,
}
}
#[allow(unused)]
pub(crate) fn from_native(native: &nativeLevel) -> Self {
match native {
nativeLevel::Off => Level::Off,
nativeLevel::Error => Level::Error,
nativeLevel::Warn => Level::Warn,
nativeLevel::Info => Level::Info,
nativeLevel::Debug => Level::Debug,
nativeLevel::Trace => Level::Trace,
}
}
#[allow(unused)]
pub(crate) fn native_into(native: nativeLevel) -> Self {
match native {
nativeLevel::Off => Level::Off,
nativeLevel::Error => Level::Error,
nativeLevel::Warn => Level::Warn,
nativeLevel::Info => Level::Info,
nativeLevel::Debug => Level::Debug,
nativeLevel::Trace => Level::Trace,
}
}
}
/// Returns the most verbose logging level.
#[must_use]
#[no_mangle]
pub extern "C" fn Level_max() -> crate::util::logger::Level {
let mut ret = lightning::util::logger::Level::max();
crate::util::logger::Level::native_into(ret)
}
/// A trait encapsulating the operations required of a logger
#[repr(C)]
pub struct Logger {
pub this_arg: *mut c_void,
/// Logs the `Record`
pub log: extern "C" fn (this_arg: *const c_void, record: *const std::os::raw::c_char),
pub free: Option<extern "C" fn(this_arg: *mut c_void)>,
}
unsafe impl Sync for Logger {}
unsafe impl Send for Logger {}
use lightning::util::logger::Logger as rustLogger;
impl rustLogger for Logger {
fn log(&self, record: &lightning::util::logger::Record) {
let mut local_record = std::ffi::CString::new(format!("{}", record.args)).unwrap();
(self.log)(self.this_arg, local_record.as_ptr())
}
}
// We're essentially a pointer already, or at least a set of pointers, so allow us to be used
// directly as a Deref trait in higher-level structs:
impl std::ops::Deref for Logger {
type Target = Self;
fn deref(&self) -> &Self {
self
}
}
/// Calls the free function if one is set
#[no_mangle]
pub extern "C" fn Logger_free(this_ptr: Logger) { }
impl Drop for Logger {
fn drop(&mut self) {
if let Some(f) = self.free {
f(self.this_arg);
}
}
}

View file

@ -0,0 +1,11 @@
//! Some utility modules live here. See individual sub-modules for more info.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;
pub mod events;
pub mod errors;
pub mod ser;
pub mod logger;
pub mod config;

View file

@ -0,0 +1,7 @@
//! A very simple serialization framework which is used to serialize/deserialize messages as well
//! as ChannelsManagers and ChannelMonitors.
use std::ffi::c_void;
use bitcoin::hashes::Hash;
use crate::c_types::*;

View file

@ -226,6 +226,8 @@ impl ChainWatchedUtil {
/// parameters with static lifetimes). Other times you can afford a reference, which is more
/// efficient, in which case BlockNotifierRef is a more appropriate type. Defining these type
/// aliases prevents issues such as overly long function definitions.
///
/// (C-not exported) as we let clients handle any reference counting they need to do
pub type BlockNotifierArc<C> = Arc<BlockNotifier<'static, Arc<ChainListener>, C>>;
/// BlockNotifierRef is useful when you want a BlockNotifier that points to ChainListeners
@ -273,6 +275,8 @@ impl<'a, CL: Deref + 'a, C: Deref> BlockNotifier<'a, CL, C>
/// If the same listener is registered multiple times, unregistering
/// will remove ALL occurrences of that listener. Comparison is done using
/// the pointer returned by the Deref trait implementation.
///
/// (C-not exported) because the equality check would always fail
pub fn unregister_listener(&self, listener: CL) {
let mut vec = self.listeners.lock().unwrap();
// item is a ref to an abstract thing that dereferences to a ChainListener,

View file

@ -35,6 +35,7 @@ impl OutPoint {
}
/// Converts this OutPoint into the OutPoint field as used by rust-bitcoin
/// (C-not exported) as the same type is used universally in the C bindings for all outpoints
pub fn into_bitcoin_outpoint(self) -> BitcoinOutPoint {
BitcoinOutPoint {
txid: self.txid,

View file

@ -188,7 +188,7 @@ impl Readable for CounterpartyCommitmentSecrets {
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, SecpError> {
let mut sha = Sha256::engine();
sha.input(&per_commitment_point.serialize());
sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize());
@ -205,7 +205,7 @@ pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_co
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, SecpError> {
let mut sha = Sha256::engine();
sha.input(&per_commitment_point.serialize());
sha.input(&base_point.serialize());
@ -219,7 +219,7 @@ pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_com
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, SecpError> {
let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret);
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
@ -252,7 +252,7 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, SecpError> {
let rev_append_commit_hash_key = {
let mut sha = Sha256::engine();
sha.input(&revocation_base_point.serialize());

View file

@ -180,12 +180,15 @@ pub(super) enum HTLCFailReason {
}
/// payment_hash type, use to cross-lock hop
/// (C-not exported) as we just use [u8; 32] directly
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
pub struct PaymentHash(pub [u8;32]);
/// payment_preimage type, use to route payment between hop
/// (C-not exported) as we just use [u8; 32] directly
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
pub struct PaymentPreimage(pub [u8;32]);
/// payment_secret type, use to authenticate sender to the receiver and tie MPP HTLCs together
/// (C-not exported) as we just use [u8; 32] directly
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
pub struct PaymentSecret(pub [u8;32]);
@ -2919,6 +2922,7 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
/// If successful, will generate a UpdateHTLCs event, so you should probably poll
/// PeerManager::process_events afterwards.
/// Note: This API is likely to change!
/// (C-not exported) Cause its doc(hidden) anyway
#[doc(hidden)]
pub fn update_fee(&self, channel_id: [u8;32], feerate_per_kw: u32) -> Result<(), APIError> {
let _ = self.total_consistency_lock.read().unwrap();
@ -3738,7 +3742,6 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T:
F::Target: FeeEstimator,
L::Target: Logger,
{
/// The keys provider which will give us relevant keys. Some keys will be loaded during
/// deserialization.
pub keys_manager: K,
@ -3775,6 +3778,8 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref, T:
///
/// In such cases the latest local transactions will be sent to the tx_broadcaster included in
/// this struct.
///
/// (C-not exported) because we have no HashMap bindings
pub channel_monitors: HashMap<OutPoint, &'a mut ChannelMonitor<ChanSigner>>,
}

View file

@ -180,6 +180,8 @@ impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
///
/// If you're using this for local monitoring of your own channels, you probably want to use
/// `OutPoint` as the key, which will give you a ManyChannelMonitor implementation.
///
/// (C-not exported) due to an unconstrained generic in `Key`
pub struct SimpleManyChannelMonitor<Key, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
@ -1421,6 +1423,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// Gets a list of txids, with their output scripts (in the order they appear in the
/// transaction), which we must learn about spends of via block_connected().
///
/// (C-not exported) because we have no HashMap bindings
pub fn get_outputs_to_watch(&self) -> &HashMap<Txid, Vec<Script>> {
&self.outputs_to_watch
}
@ -1429,6 +1433,8 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
/// Generally useful when deserializing as during normal operation the return values of
/// block_connected are sufficient to ensure all relevant outpoints are being monitored (note
/// that the get_funding_txo outpoint and transaction must also be monitored for!).
///
/// (C-not exported) as there is no practical way to track lifetimes of returned values.
pub fn get_monitored_outpoints(&self) -> Vec<(Txid, u32, &Script)> {
let mut res = Vec::with_capacity(self.remote_commitment_txn_on_chain.len() * 2);
for (ref txid, &(_, ref outputs)) in self.remote_commitment_txn_on_chain.iter() {

View file

@ -279,6 +279,8 @@ mod sealed {
/// Tracks the set of features which a node implements, templated by the context in which it
/// appears.
///
/// (C-not exported) as we map the concrete feature types below directly instead
pub struct Features<T: sealed::Context> {
/// Note that, for convenience, flags is LITTLE endian (despite being big-endian on the wire)
flags: Vec<u8>,

View file

@ -646,6 +646,7 @@ pub enum HTLCFailChannelUpdate {
/// As we wish to serialize these differently from Option<T>s (Options get a tag byte, but
/// OptionalFeild simply gets Present if there are enough bytes to read into it), we have a
/// separate enum type for them.
/// (C-not exported) due to a free generic in T
#[derive(Clone, PartialEq, Debug)]
pub enum OptionalField<T> {
/// Optional field is included in message

View file

@ -260,7 +260,7 @@ pub struct DirectionalChannelInfo {
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
pub last_update_message: Option<msgs::ChannelUpdate>,
pub last_update_message: Option<ChannelUpdate>,
}
impl fmt::Display for DirectionalChannelInfo {
@ -300,7 +300,7 @@ pub struct ChannelInfo {
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
pub announcement_message: Option<msgs::ChannelAnnouncement>,
pub announcement_message: Option<ChannelAnnouncement>,
}
impl fmt::Display for ChannelInfo {
@ -371,7 +371,7 @@ pub struct NodeAnnouncementInfo {
/// Mostly redundant with the data we store in fields explicitly.
/// Everything else is useful only for sending out for initial routing sync.
/// Not stored if contains excess data to prevent DoS.
pub announcement_message: Option<msgs::NodeAnnouncement>
pub announcement_message: Option<NodeAnnouncement>
}
impl Writeable for NodeAnnouncementInfo {
@ -526,13 +526,19 @@ impl fmt::Display for NetworkGraph {
impl NetworkGraph {
/// Returns all known valid channels' short ids along with announced channel info.
///
/// (C-not exported) because we have no mapping for `BTreeMap`s
pub fn get_channels<'a>(&'a self) -> &'a BTreeMap<u64, ChannelInfo> { &self.channels }
/// Returns all known nodes' public keys along with announced node info.
///
/// (C-not exported) because we have no mapping for `BTreeMap`s
pub fn get_nodes<'a>(&'a self) -> &'a BTreeMap<PublicKey, NodeInfo> { &self.nodes }
/// Get network addresses by node id.
/// Returns None if the requested node is completely unknown,
/// or if node announcement for the node was never received.
///
/// (C-not exported) as there is no practical way to track lifetimes of returned values.
pub fn get_addresses<'a>(&'a self, pubkey: &PublicKey) -> Option<&'a Vec<NetAddress>> {
if let Some(node) = self.nodes.get(pubkey) {
if let Some(node_info) = node.announcement_info.as_ref() {

View file

@ -86,6 +86,7 @@ impl Level {
/// A Record, unit of logging output with Metadata to enable filtering
/// Module_path, file, line to inform on log's source
/// (C-not exported) - we convert to a const char* instead
#[derive(Clone,Debug)]
pub struct Record<'a> {
/// The verbosity level of the message.
@ -102,6 +103,7 @@ pub struct Record<'a> {
impl<'a> Record<'a> {
/// Returns a new Record.
/// (C-not exported) as fmt can't be used in C
#[inline]
pub fn new(level: Level, args: fmt::Arguments<'a>, module_path: &'a str, file: &'a str, line: u32) -> Record<'a> {
Record {

View file

@ -37,6 +37,8 @@ const MAX_BUF_SIZE: usize = 64 * 1024;
/// buffers being written into.
/// An impl is provided for any type that also impls std::io::Write which simply ignores size
/// hints.
///
/// (C-not exported) as we only export serialization to/from byte arrays instead
pub trait Writer {
/// Writes the given buf out. See std::io::Write::write_all for more
fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error>;
@ -159,6 +161,8 @@ impl<R: Read> Read for ReadTrackingReader<R> {
}
/// A trait that various rust-lightning types implement allowing them to be written out to a Writer
///
/// (C-not exported) as we only export serialization to/from byte arrays instead
pub trait Writeable {
/// Writes self out to the given Writer
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error>;
@ -186,6 +190,8 @@ impl<'a, T: Writeable> Writeable for &'a T {
}
/// A trait that various rust-lightning types implement allowing them to be read in from a Read
///
/// (C-not exported) as we only export serialization to/from byte arrays instead
pub trait Readable
where Self: Sized
{
@ -195,6 +201,8 @@ pub trait Readable
/// A trait that various higher-level rust-lightning types implement allowing them to be read in
/// from a Read given some additional set of arguments which is required to deserialize.
///
/// (C-not exported) as we only export serialization to/from byte arrays instead
pub trait ReadableArgs<P>
where Self: Sized
{
@ -203,6 +211,8 @@ pub trait ReadableArgs<P>
}
/// A trait that various rust-lightning types implement allowing them to (maybe) be read in from a Read
///
/// (C-not exported) as we only export serialization to/from byte arrays instead
pub trait MaybeReadable
where Self: Sized
{