From: Matt Corallo <649246+TheBlueMatt@users.noreply.github.com> Date: Tue, 13 Apr 2021 01:54:49 +0000 (+0000) Subject: Merge pull request #11 from TheBlueMatt/2021-04-upstream-bump X-Git-Tag: v0.0.98~16 X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=ldk-c-bindings;a=commitdiff_plain;h=76087923a2131ecb054a0787b062443aa09ed0ae;hp=1a31801f2d38663b22ac044ec9bd0b41aa1a02f9 Merge pull request #11 from TheBlueMatt/2021-04-upstream-bump Bump Upstream and clean up supertrait handling --- diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index 1d37bb2..f0c5db3 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -18,13 +18,13 @@ //! It also generates relevant memory-management functions and free-standing functions with //! parameters mapped. -use std::collections::{HashMap, hash_map, HashSet}; +use std::collections::{HashMap, hash_map}; use std::env; use std::fs::File; use std::io::{Read, Write}; use std::process; -use proc_macro2::{TokenTree, TokenStream, Span}; +use proc_macro2::Span; mod types; mod blocks; @@ -35,38 +35,6 @@ use blocks::*; // *** Manually-expanded conversions *** // ************************************* -/// Because we don't expand macros, any code that we need to generated based on their contents has -/// to be completely manual. In this case its all just serialization, so its not too hard. -fn convert_macro(w: &mut W, macro_path: &syn::Path, stream: &TokenStream, types: &TypeResolver) { - assert_eq!(macro_path.segments.len(), 1); - match &format!("{}", macro_path.segments.iter().next().unwrap().ident) as &str { - "impl_writeable" | "impl_writeable_len_match" => { - let struct_for = if let TokenTree::Ident(i) = stream.clone().into_iter().next().unwrap() { i } else { unimplemented!(); }; - if let Some(s) = types.maybe_resolve_ident(&struct_for) { - if !types.crate_types.opaques.get(&s).is_some() { return; } - writeln!(w, "#[no_mangle]").unwrap(); - writeln!(w, "/// Serialize the {} into a byte array which can be read by {}_read", struct_for, struct_for).unwrap(); - writeln!(w, "pub extern \"C\" fn {}_write(obj: &{}) -> crate::c_types::derived::CVec_u8Z {{", struct_for, struct_for).unwrap(); - writeln!(w, "\tcrate::c_types::serialize_obj(unsafe {{ &(*(*obj).inner) }})").unwrap(); - writeln!(w, "}}").unwrap(); - writeln!(w, "#[no_mangle]").unwrap(); - writeln!(w, "pub(crate) extern \"C\" fn {}_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z {{", struct_for).unwrap(); - writeln!(w, "\tcrate::c_types::serialize_obj(unsafe {{ &*(obj as *const native{}) }})", struct_for).unwrap(); - writeln!(w, "}}").unwrap(); - writeln!(w, "#[no_mangle]").unwrap(); - writeln!(w, "/// Read a {} from a byte array, created by {}_write", struct_for, struct_for).unwrap(); - writeln!(w, "pub extern \"C\" fn {}_read(ser: crate::c_types::u8slice) -> {} {{", struct_for, struct_for).unwrap(); - writeln!(w, "\tif let Ok(res) = crate::c_types::deserialize_obj(ser) {{").unwrap(); - writeln!(w, "\t\t{} {{ inner: Box::into_raw(Box::new(res)), is_owned: true }}", struct_for).unwrap(); - writeln!(w, "\t}} else {{").unwrap(); - writeln!(w, "\t\t{} {{ inner: std::ptr::null_mut(), is_owned: true }}", struct_for).unwrap(); - writeln!(w, "\t}}\n}}").unwrap(); - } - }, - _ => {}, - } -} - /// Convert "impl trait_path for for_ty { .. }" for manually-mapped types (ie (de)serialization) fn maybe_convert_trait_impl(w: &mut W, trait_path: &syn::Path, for_ty: &syn::Type, types: &mut TypeResolver, generics: &GenericTypes) { if let Some(t) = types.maybe_resolve_path(&trait_path, Some(generics)) { @@ -211,14 +179,9 @@ fn write_trait_impl_field_assign(w: &mut W, trait_path: &str, } /// Write out the impl block for a defined trait struct which has a supertrait -fn do_write_impl_trait(w: &mut W, trait_path: &str, trait_name: &syn::Ident, for_obj: &str) { +fn do_write_impl_trait(w: &mut W, trait_path: &str, _trait_name: &syn::Ident, for_obj: &str) { +eprintln!("{}", trait_path); match trait_path { - "util::events::MessageSendEventsProvider" => { - writeln!(w, "impl lightning::{} for {} {{", trait_path, for_obj).unwrap(); - writeln!(w, "\tfn get_and_clear_pending_msg_events(&self) -> Vec {{").unwrap(); - writeln!(w, "\t\t::get_and_clear_pending_msg_events(&self.{})", trait_path, trait_path, trait_name).unwrap(); - writeln!(w, "\t}}\n}}").unwrap(); - }, "util::ser::Writeable" => { writeln!(w, "impl lightning::{} for {} {{", trait_path, for_obj).unwrap(); writeln!(w, "\tfn write(&self, w: &mut W) -> Result<(), ::std::io::Error> {{").unwrap(); @@ -289,7 +252,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty writeln!(w, "\t/// An opaque pointer which is passed to your function implementations as an argument.").unwrap(); writeln!(w, "\t/// This has no meaning in the LDK, and can be NULL or any other value.").unwrap(); writeln!(w, "\tpub this_arg: *mut c_void,").unwrap(); - let mut generated_fields = Vec::new(); // Every field's name except this_arg, used in Clone generation + let mut generated_fields = Vec::new(); // Every field's (name, is_clonable) except this_arg, used in Clone generation for item in t.items.iter() { match item { &syn::TraitItem::Method(ref m) => { @@ -304,8 +267,8 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty } if m.default.is_some() { unimplemented!(); } - gen_types.push_ctx(); - assert!(gen_types.learn_generics(&m.sig.generics, types)); + let mut meth_gen_types = gen_types.push_ctx(); + assert!(meth_gen_types.learn_generics(&m.sig.generics, types)); writeln_docs(w, &m.attrs, "\t"); @@ -322,20 +285,19 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty // happen) as well as provide an Option<>al function pointer which is // called when the trait method is called which allows updating on the fly. write!(w, "\tpub {}: ", m.sig.ident).unwrap(); - generated_fields.push(format!("{}", m.sig.ident)); - types.write_c_type(w, &*r.elem, Some(&gen_types), false); + generated_fields.push((format!("{}", m.sig.ident), true)); + types.write_c_type(w, &*r.elem, Some(&meth_gen_types), false); writeln!(w, ",").unwrap(); writeln!(w, "\t/// Fill in the {} field as a reference to it will be given to Rust after this returns", m.sig.ident).unwrap(); writeln!(w, "\t/// Note that this takes a pointer to this object, not the this_ptr like other methods do").unwrap(); writeln!(w, "\t/// This function pointer may be NULL if {} is filled in when this object is created and never needs updating.", m.sig.ident).unwrap(); writeln!(w, "\tpub set_{}: Option,", m.sig.ident, trait_name).unwrap(); - generated_fields.push(format!("set_{}", m.sig.ident)); + generated_fields.push((format!("set_{}", m.sig.ident), true)); // Note that cbindgen will now generate // typedef struct Thing {..., set_thing: (const Thing*), ...} Thing; // which does not compile since Thing is not defined before it is used. writeln!(extra_headers, "struct LDK{};", trait_name).unwrap(); writeln!(extra_headers, "typedef struct LDK{} LDK{};", trait_name, trait_name).unwrap(); - gen_types.pop_ctx(); continue; } // Sadly, this currently doesn't do what we want, but it should be easy to get @@ -344,36 +306,39 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty } write!(w, "\tpub {}: extern \"C\" fn (", m.sig.ident).unwrap(); - generated_fields.push(format!("{}", m.sig.ident)); - write_method_params(w, &m.sig, "c_void", types, Some(&gen_types), true, false); + generated_fields.push((format!("{}", m.sig.ident), true)); + write_method_params(w, &m.sig, "c_void", types, Some(&meth_gen_types), true, false); writeln!(w, ",").unwrap(); - - gen_types.pop_ctx(); }, &syn::TraitItem::Type(_) => {}, _ => unimplemented!(), } } // Add functions which may be required for supertrait implementations. + let mut requires_clone = false; + walk_supertraits!(t, Some(&types), ( + ("Clone", _) => requires_clone = true, + (_, _) => {} + ) ); walk_supertraits!(t, Some(&types), ( ("Clone", _) => { writeln!(w, "\t/// Creates a copy of the object pointed to by this_arg, for a copy of this {}.", trait_name).unwrap(); writeln!(w, "\t/// Note that the ultimate copy of the {} will have all function pointers the same as the original.", trait_name).unwrap(); writeln!(w, "\t/// May be NULL if no action needs to be taken, the this_arg pointer will be copied into the new {}.", trait_name).unwrap(); writeln!(w, "\tpub clone: Option *mut c_void>,").unwrap(); - generated_fields.push("clone".to_owned()); + generated_fields.push(("clone".to_owned(), true)); }, ("std::cmp::Eq", _) => { writeln!(w, "\t/// Checks if two objects are equal given this object's this_arg pointer and another object.").unwrap(); writeln!(w, "\tpub eq: extern \"C\" fn (this_arg: *const c_void, other_arg: &{}) -> bool,", trait_name).unwrap(); writeln!(extra_headers, "typedef struct LDK{} LDK{};", trait_name, trait_name).unwrap(); - generated_fields.push("eq".to_owned()); + generated_fields.push(("eq".to_owned(), true)); }, ("std::hash::Hash", _) => { writeln!(w, "\t/// Calculate a succinct non-cryptographic hash for an object given its this_arg pointer.").unwrap(); writeln!(w, "\t/// This is used, for example, for inclusion of this object in a hash map.").unwrap(); writeln!(w, "\tpub hash: extern \"C\" fn (this_arg: *const c_void) -> u64,").unwrap(); - generated_fields.push("hash".to_owned()); + generated_fields.push(("hash".to_owned(), true)); }, ("Send", _) => {}, ("Sync", _) => {}, (s, i) => { @@ -381,20 +346,125 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty let (docs, name, ret) = convert_trait_impl_field(s); writeln!(w, "\t/// {}", docs).unwrap(); writeln!(w, "\tpub {}: extern \"C\" fn (this_arg: *const c_void) -> {},", name, ret).unwrap(); - name + (name, true) // Assume clonable } else { // For in-crate supertraits, just store a C-mapped copy of the supertrait as a member. - writeln!(w, "/// Implementation of {} for this object.", i).unwrap(); + writeln!(w, "\t/// Implementation of {} for this object.", i).unwrap(); writeln!(w, "\tpub {}: crate::{},", i, s).unwrap(); - format!("{}", i) + let is_clonable = types.is_clonable(s); + if !is_clonable && requires_clone { + writeln!(w, "\t/// Creates a copy of the {}, for a copy of this {}.", i, trait_name).unwrap(); + writeln!(w, "\t/// Because {} doesn't natively support copying itself, you have to provide a full copy implementation here.", i).unwrap(); + writeln!(w, "\tpub {}_clone: extern \"C\" fn (orig_{}: &{}) -> {},", i, i, i, i).unwrap(); + } + (format!("{}", i), is_clonable) }); } ) ); writeln!(w, "\t/// Frees any resources associated with this object given its this_arg pointer.").unwrap(); writeln!(w, "\t/// Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed.").unwrap(); writeln!(w, "\tpub free: Option,").unwrap(); - generated_fields.push("free".to_owned()); + generated_fields.push(("free".to_owned(), true)); writeln!(w, "}}").unwrap(); + + macro_rules! impl_trait_for_c { + ($t: expr, $impl_accessor: expr, $type_resolver: expr) => { + for item in $t.items.iter() { + match item { + syn::TraitItem::Method(m) => { + if let ExportStatus::TestOnly = export_status(&m.attrs) { continue; } + if m.default.is_some() { unimplemented!(); } + if m.sig.constness.is_some() || m.sig.asyncness.is_some() || m.sig.unsafety.is_some() || + m.sig.abi.is_some() || m.sig.variadic.is_some() { + unimplemented!(); + } + let mut meth_gen_types = gen_types.push_ctx(); + assert!(meth_gen_types.learn_generics(&m.sig.generics, $type_resolver)); + write!(w, "\tfn {}", m.sig.ident).unwrap(); + $type_resolver.write_rust_generic_param(w, Some(&meth_gen_types), m.sig.generics.params.iter()); + write!(w, "(").unwrap(); + for inp in m.sig.inputs.iter() { + match inp { + syn::FnArg::Receiver(recv) => { + if !recv.attrs.is_empty() || recv.reference.is_none() { unimplemented!(); } + write!(w, "&").unwrap(); + if let Some(lft) = &recv.reference.as_ref().unwrap().1 { + write!(w, "'{} ", lft.ident).unwrap(); + } + if recv.mutability.is_some() { + write!(w, "mut self").unwrap(); + } else { + write!(w, "self").unwrap(); + } + }, + syn::FnArg::Typed(arg) => { + if !arg.attrs.is_empty() { unimplemented!(); } + match &*arg.pat { + syn::Pat::Ident(ident) => { + if !ident.attrs.is_empty() || ident.by_ref.is_some() || + ident.mutability.is_some() || ident.subpat.is_some() { + unimplemented!(); + } + write!(w, ", {}{}: ", if $type_resolver.skip_arg(&*arg.ty, Some(&meth_gen_types)) { "_" } else { "" }, ident.ident).unwrap(); + } + _ => unimplemented!(), + } + $type_resolver.write_rust_type(w, Some(&meth_gen_types), &*arg.ty); + } + } + } + write!(w, ")").unwrap(); + match &m.sig.output { + syn::ReturnType::Type(_, rtype) => { + write!(w, " -> ").unwrap(); + $type_resolver.write_rust_type(w, Some(&meth_gen_types), &*rtype) + }, + _ => {}, + } + write!(w, " {{\n\t\t").unwrap(); + match export_status(&m.attrs) { + ExportStatus::NoExport => { + unimplemented!(); + }, + _ => {}, + } + if let syn::ReturnType::Type(_, rtype) = &m.sig.output { + if let syn::Type::Reference(r) = &**rtype { + assert_eq!(m.sig.inputs.len(), 1); // Must only take self! + writeln!(w, "if let Some(f) = self{}.set_{} {{", $impl_accessor, m.sig.ident).unwrap(); + writeln!(w, "\t\t\t(f)(&self{});", $impl_accessor).unwrap(); + write!(w, "\t\t}}\n\t\t").unwrap(); + $type_resolver.write_from_c_conversion_to_ref_prefix(w, &*r.elem, Some(&meth_gen_types)); + write!(w, "self{}.{}", $impl_accessor, m.sig.ident).unwrap(); + $type_resolver.write_from_c_conversion_to_ref_suffix(w, &*r.elem, Some(&meth_gen_types)); + writeln!(w, "\n\t}}").unwrap(); + continue; + } + } + write_method_var_decl_body(w, &m.sig, "\t", $type_resolver, Some(&meth_gen_types), true); + write!(w, "(self{}.{})(", $impl_accessor, m.sig.ident).unwrap(); + write_method_call_params(w, &m.sig, "\t", $type_resolver, Some(&meth_gen_types), "", true); + + writeln!(w, "\n\t}}").unwrap(); + }, + &syn::TraitItem::Type(ref t) => { + if t.default.is_some() || t.generics.lt_token.is_some() { unimplemented!(); } + let mut bounds_iter = t.bounds.iter(); + match bounds_iter.next().unwrap() { + syn::TypeParamBound::Trait(tr) => { + writeln!(w, "\ttype {} = crate::{};", t.ident, $type_resolver.resolve_path(&tr.path, Some(&gen_types))).unwrap(); + }, + _ => unimplemented!(), + } + if bounds_iter.next().is_some() { unimplemented!(); } + }, + _ => unimplemented!(), + } + } + } + } + + // Implement supertraits for the C-mapped struct. walk_supertraits!(t, Some(&types), ( ("Send", _) => writeln!(w, "unsafe impl Send for {} {{}}", trait_name).unwrap(), @@ -414,8 +484,13 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", trait_name, trait_name, trait_name).unwrap(); writeln!(w, "\t{} {{", trait_name).unwrap(); writeln!(w, "\t\tthis_arg: if let Some(f) = orig.clone {{ (f)(orig.this_arg) }} else {{ orig.this_arg }},").unwrap(); - for field in generated_fields.iter() { - writeln!(w, "\t\t{}: orig.{}.clone(),", field, field).unwrap(); + for (field, clonable) in generated_fields.iter() { + if *clonable { + writeln!(w, "\t\t{}: Clone::clone(&orig.{}),", field, field).unwrap(); + } else { + writeln!(w, "\t\t{}: (orig.{}_clone)(&orig.{}),", field, field, field).unwrap(); + writeln!(w, "\t\t{}_clone: orig.{}_clone,", field, field).unwrap(); + } } writeln!(w, "\t}}\n}}").unwrap(); writeln!(w, "impl Clone for {} {{", trait_name).unwrap(); @@ -424,7 +499,23 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty writeln!(w, "\t}}\n}}").unwrap(); }, (s, i) => { - do_write_impl_trait(w, s, i, &trait_name); + if let Some(supertrait) = types.crate_types.traits.get(s) { + let mut module_iter = s.rsplitn(2, "::"); + module_iter.next().unwrap(); + let supertrait_module = module_iter.next().unwrap(); + let imports = ImportResolver::new(supertrait_module, &types.crate_types.lib_ast.modules.get(supertrait_module).unwrap().items); + let resolver = TypeResolver::new("lightning", &supertrait_module, imports, types.crate_types); // TODO: Drop hard-coded crate name here + writeln!(w, "impl lightning::{} for {} {{", s, trait_name).unwrap(); // TODO: Drop hard-coded crate name here + impl_trait_for_c!(supertrait, format!(".{}", i), &resolver); + writeln!(w, "}}").unwrap(); + walk_supertraits!(supertrait, Some(&types), ( + ("Send", _) => writeln!(w, "unsafe impl Send for {} {{}}", trait_name).unwrap(), + ("Sync", _) => writeln!(w, "unsafe impl Sync for {} {{}}", trait_name).unwrap(), + _ => unimplemented!() + ) ); + } else { + do_write_impl_trait(w, s, i, &trait_name); + } } ) ); @@ -433,100 +524,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty write!(w, "impl rust{}", t.ident).unwrap(); maybe_write_generics(w, &t.generics, types, false); writeln!(w, " for {} {{", trait_name).unwrap(); - for item in t.items.iter() { - match item { - syn::TraitItem::Method(m) => { - if let ExportStatus::TestOnly = export_status(&m.attrs) { continue; } - if m.default.is_some() { unimplemented!(); } - if m.sig.constness.is_some() || m.sig.asyncness.is_some() || m.sig.unsafety.is_some() || - m.sig.abi.is_some() || m.sig.variadic.is_some() { - unimplemented!(); - } - gen_types.push_ctx(); - assert!(gen_types.learn_generics(&m.sig.generics, types)); - write!(w, "\tfn {}", m.sig.ident).unwrap(); - types.write_rust_generic_param(w, Some(&gen_types), m.sig.generics.params.iter()); - write!(w, "(").unwrap(); - for inp in m.sig.inputs.iter() { - match inp { - syn::FnArg::Receiver(recv) => { - if !recv.attrs.is_empty() || recv.reference.is_none() { unimplemented!(); } - write!(w, "&").unwrap(); - if let Some(lft) = &recv.reference.as_ref().unwrap().1 { - write!(w, "'{} ", lft.ident).unwrap(); - } - if recv.mutability.is_some() { - write!(w, "mut self").unwrap(); - } else { - write!(w, "self").unwrap(); - } - }, - syn::FnArg::Typed(arg) => { - if !arg.attrs.is_empty() { unimplemented!(); } - match &*arg.pat { - syn::Pat::Ident(ident) => { - if !ident.attrs.is_empty() || ident.by_ref.is_some() || - ident.mutability.is_some() || ident.subpat.is_some() { - unimplemented!(); - } - write!(w, ", {}{}: ", if types.skip_arg(&*arg.ty, Some(&gen_types)) { "_" } else { "" }, ident.ident).unwrap(); - } - _ => unimplemented!(), - } - types.write_rust_type(w, Some(&gen_types), &*arg.ty); - } - } - } - write!(w, ")").unwrap(); - match &m.sig.output { - syn::ReturnType::Type(_, rtype) => { - write!(w, " -> ").unwrap(); - types.write_rust_type(w, Some(&gen_types), &*rtype) - }, - _ => {}, - } - write!(w, " {{\n\t\t").unwrap(); - match export_status(&m.attrs) { - ExportStatus::NoExport => { - unimplemented!(); - }, - _ => {}, - } - if let syn::ReturnType::Type(_, rtype) = &m.sig.output { - if let syn::Type::Reference(r) = &**rtype { - assert_eq!(m.sig.inputs.len(), 1); // Must only take self! - writeln!(w, "if let Some(f) = self.set_{} {{", m.sig.ident).unwrap(); - writeln!(w, "\t\t\t(f)(self);").unwrap(); - write!(w, "\t\t}}\n\t\t").unwrap(); - types.write_from_c_conversion_to_ref_prefix(w, &*r.elem, Some(&gen_types)); - write!(w, "self.{}", m.sig.ident).unwrap(); - types.write_from_c_conversion_to_ref_suffix(w, &*r.elem, Some(&gen_types)); - writeln!(w, "\n\t}}").unwrap(); - gen_types.pop_ctx(); - continue; - } - } - write_method_var_decl_body(w, &m.sig, "\t", types, Some(&gen_types), true); - write!(w, "(self.{})(", m.sig.ident).unwrap(); - write_method_call_params(w, &m.sig, "\t", types, Some(&gen_types), "", true); - - writeln!(w, "\n\t}}").unwrap(); - gen_types.pop_ctx(); - }, - &syn::TraitItem::Type(ref t) => { - if t.default.is_some() || t.generics.lt_token.is_some() { unimplemented!(); } - let mut bounds_iter = t.bounds.iter(); - match bounds_iter.next().unwrap() { - syn::TypeParamBound::Trait(tr) => { - writeln!(w, "\ttype {} = crate::{};", t.ident, types.resolve_path(&tr.path, Some(&gen_types))).unwrap(); - }, - _ => unimplemented!(), - } - if bounds_iter.next().is_some() { unimplemented!(); } - }, - _ => unimplemented!(), - } - } + impl_trait_for_c!(t, "", types); writeln!(w, "}}\n").unwrap(); writeln!(w, "// We're essentially a pointer already, or at least a set of pointers, so allow us to be used").unwrap(); writeln!(w, "// directly as a Deref trait in higher-level structs:").unwrap(); @@ -802,12 +800,12 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ if let syn::Type::Reference(r) = &**rtype { write!(w, "\n\t\t{}{}: ", $indent, $m.sig.ident).unwrap(); types.write_empty_rust_val(Some(&gen_types), w, &*r.elem); - writeln!(w, ",\n{}\t\tset_{}: Some({}_{}_set_{}),", $indent, $m.sig.ident, ident, trait_obj.ident, $m.sig.ident).unwrap(); + writeln!(w, ",\n{}\t\tset_{}: Some({}_{}_set_{}),", $indent, $m.sig.ident, ident, $trait.ident, $m.sig.ident).unwrap(); printed = true; } } if !printed { - write!(w, "{}\t\t{}: {}_{}_{},\n", $indent, $m.sig.ident, ident, trait_obj.ident, $m.sig.ident).unwrap(); + write!(w, "{}\t\t{}: {}_{}_{},\n", $indent, $m.sig.ident, ident, $trait.ident, $m.sig.ident).unwrap(); } } } @@ -819,6 +817,11 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ _ => {}, } } + let mut requires_clone = false; + walk_supertraits!(trait_obj, Some(&types), ( + ("Clone", _) => requires_clone = true, + (_, _) => {} + ) ); walk_supertraits!(trait_obj, Some(&types), ( ("Clone", _) => { writeln!(w, "\t\tclone: Some({}_clone_void),", ident).unwrap(); @@ -839,6 +842,9 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ } } write!(w, "\t\t}},\n").unwrap(); + if !types.is_clonable(s) && requires_clone { + writeln!(w, "\t\t{}_clone: {}_{}_clone,", t, ident, t).unwrap(); + } } else { write_trait_impl_field_assign(w, s, ident); } @@ -859,12 +865,12 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ if let syn::ReturnType::Type(_, _) = &$m.sig.output { writeln!(w, "#[must_use]").unwrap(); } - write!(w, "extern \"C\" fn {}_{}_{}(", ident, trait_obj.ident, $m.sig.ident).unwrap(); - gen_types.push_ctx(); - assert!(gen_types.learn_generics(&$m.sig.generics, types)); - write_method_params(w, &$m.sig, "c_void", types, Some(&gen_types), true, true); + write!(w, "extern \"C\" fn {}_{}_{}(", ident, $trait.ident, $m.sig.ident).unwrap(); + let mut meth_gen_types = gen_types.push_ctx(); + assert!(meth_gen_types.learn_generics(&$m.sig.generics, types)); + write_method_params(w, &$m.sig, "c_void", types, Some(&meth_gen_types), true, true); write!(w, " {{\n\t").unwrap(); - write_method_var_decl_body(w, &$m.sig, "", types, Some(&gen_types), false); + write_method_var_decl_body(w, &$m.sig, "", types, Some(&meth_gen_types), false); let mut takes_self = false; for inp in $m.sig.inputs.iter() { if let syn::FnArg::Receiver(_) = inp { @@ -894,19 +900,18 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ }, _ => {}, } - write_method_call_params(w, &$m.sig, "", types, Some(&gen_types), &real_type, false); - gen_types.pop_ctx(); + write_method_call_params(w, &$m.sig, "", types, Some(&meth_gen_types), &real_type, false); write!(w, "\n}}\n").unwrap(); if let syn::ReturnType::Type(_, rtype) = &$m.sig.output { if let syn::Type::Reference(r) = &**rtype { assert_eq!($m.sig.inputs.len(), 1); // Must only take self - writeln!(w, "extern \"C\" fn {}_{}_set_{}(trait_self_arg: &{}) {{", ident, trait_obj.ident, $m.sig.ident, trait_obj.ident).unwrap(); + writeln!(w, "extern \"C\" fn {}_{}_set_{}(trait_self_arg: &{}) {{", ident, $trait.ident, $m.sig.ident, $trait.ident).unwrap(); writeln!(w, "\t// This is a bit race-y in the general case, but for our specific use-cases today, we're safe").unwrap(); writeln!(w, "\t// Specifically, we must ensure that the first time we're called it can never be in parallel").unwrap(); write!(w, "\tif ").unwrap(); - types.write_empty_rust_val_check(Some(&gen_types), w, &*r.elem, &format!("trait_self_arg.{}", $m.sig.ident)); + types.write_empty_rust_val_check(Some(&meth_gen_types), w, &*r.elem, &format!("trait_self_arg.{}", $m.sig.ident)); writeln!(w, " {{").unwrap(); - writeln!(w, "\t\tunsafe {{ &mut *(trait_self_arg as *const {} as *mut {}) }}.{} = {}_{}_{}(trait_self_arg.this_arg);", trait_obj.ident, trait_obj.ident, $m.sig.ident, ident, trait_obj.ident, $m.sig.ident).unwrap(); + writeln!(w, "\t\tunsafe {{ &mut *(trait_self_arg as *const {} as *mut {}) }}.{} = {}_{}_{}(trait_self_arg.this_arg);", $trait.ident, $trait.ident, $m.sig.ident, ident, $trait.ident, $m.sig.ident).unwrap(); writeln!(w, "\t}}").unwrap(); writeln!(w, "}}").unwrap(); } @@ -924,15 +929,22 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ } } walk_supertraits!(trait_obj, Some(&types), ( - (s, _) => { - if let Some(supertrait_obj) = types.crate_types.traits.get(s).cloned() { - for item in supertrait_obj.items.iter() { - match item { - syn::TraitItem::Method(m) => { - impl_meth!(m, s, supertrait_obj, "\t"); - }, - _ => {}, + (s, t) => { + if let Some(supertrait_obj) = types.crate_types.traits.get(s) { + if !types.is_clonable(s) && requires_clone { + writeln!(w, "extern \"C\" fn {}_{}_clone(orig: &crate::{}) -> crate::{} {{", ident, t, s, s).unwrap(); + writeln!(w, "\tcrate::{} {{", s).unwrap(); + writeln!(w, "\t\tthis_arg: orig.this_arg,").unwrap(); + writeln!(w, "\t\tfree: None,").unwrap(); + for item in supertrait_obj.items.iter() { + match item { + syn::TraitItem::Method(m) => { + write_meth!(m, supertrait_obj, ""); + }, + _ => {}, + } } + write!(w, "\t}}\n}}\n").unwrap(); } } } @@ -990,11 +1002,11 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ DeclType::StructImported => format!("{}", ident), _ => unimplemented!(), }; - gen_types.push_ctx(); - assert!(gen_types.learn_generics(&m.sig.generics, types)); - write_method_params(w, &m.sig, &ret_type, types, Some(&gen_types), false, true); + let mut meth_gen_types = gen_types.push_ctx(); + assert!(meth_gen_types.learn_generics(&m.sig.generics, types)); + write_method_params(w, &m.sig, &ret_type, types, Some(&meth_gen_types), false, true); write!(w, " {{\n\t").unwrap(); - write_method_var_decl_body(w, &m.sig, "", types, Some(&gen_types), false); + write_method_var_decl_body(w, &m.sig, "", types, Some(&meth_gen_types), false); let mut takes_self = false; let mut takes_mut_self = false; for inp in m.sig.inputs.iter() { @@ -1010,8 +1022,7 @@ fn writeln_impl(w: &mut W, i: &syn::ItemImpl, types: &mut Typ } else { write!(w, "{}::{}::{}(", types.orig_crate, resolved_path, m.sig.ident).unwrap(); } - write_method_call_params(w, &m.sig, "", types, Some(&gen_types), &ret_type, false); - gen_types.pop_ctx(); + write_method_call_params(w, &m.sig, "", types, Some(&meth_gen_types), &ret_type, false); writeln!(w, "\n}}\n").unwrap(); } }, @@ -1284,57 +1295,11 @@ fn writeln_fn<'a, 'b, W: std::io::Write>(w: &mut W, f: &'a syn::ItemFn, types: & // ******************************** // *** File/Crate Walking Logic *** // ******************************** -/// A public module -struct ASTModule { - pub attrs: Vec, - pub items: Vec, - pub submods: Vec, -} -/// A struct containing the syn::File AST for each file in the crate. -struct FullLibraryAST { - modules: HashMap, -} -impl FullLibraryAST { - fn load_module(&mut self, module: String, attrs: Vec, mut items: Vec) { - let mut non_mod_items = Vec::with_capacity(items.len()); - let mut submods = Vec::with_capacity(items.len()); - for item in items.drain(..) { - match item { - syn::Item::Mod(m) if m.content.is_some() => { - if export_status(&m.attrs) == ExportStatus::Export { - if let syn::Visibility::Public(_) = m.vis { - let modident = format!("{}", m.ident); - let modname = if module != "" { - module.clone() + "::" + &modident - } else { - modident.clone() - }; - self.load_module(modname, m.attrs, m.content.unwrap().1); - submods.push(modident); - } else { - non_mod_items.push(syn::Item::Mod(m)); - } - } - }, - syn::Item::Mod(_) => panic!("--pretty=expanded output should never have non-body modules"), - _ => { non_mod_items.push(item); } - } - } - self.modules.insert(module, ASTModule { attrs, items: non_mod_items, submods }); - } - - pub fn load_lib(lib: syn::File) -> Self { - assert_eq!(export_status(&lib.attrs), ExportStatus::Export); - let mut res = Self { modules: HashMap::default() }; - res.load_module("".to_owned(), lib.attrs, lib.items); - res - } -} /// Do the Real Work of mapping an original file to C-callable wrappers. Creates a new file at /// `out_path` and fills it with wrapper structs/functions to allow calling the things in the AST /// at `module` from C. -fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a>, out_dir: &str, orig_crate: &str, header_file: &mut File, cpp_header_file: &mut File) { +fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &CrateTypes<'a>, out_dir: &str, orig_crate: &str, header_file: &mut File, cpp_header_file: &mut File) { for (module, astmod) in libast.modules.iter() { let ASTModule { ref attrs, ref items, ref submods } = astmod; assert_eq!(export_status(&attrs), ExportStatus::Export); @@ -1451,11 +1416,7 @@ fn convert_file<'a, 'b>(libast: &'a FullLibraryAST, crate_types: &mut CrateTypes writeln_fn(&mut out, &f, &mut type_resolver); } }, - syn::Item::Macro(m) => { - if m.ident.is_none() { // If its not a macro definition - convert_macro(&mut out, &m.mac.path, &m.mac.tokens, &type_resolver); - } - }, + syn::Item::Macro(_) => {}, syn::Item::Verbatim(_) => {}, syn::Item::ExternCrate(_) => {}, _ => unimplemented!(), @@ -1518,7 +1479,7 @@ fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a let trait_path = format!("{}::{}", module, t.ident); walk_supertraits!(t, None, ( ("Clone", _) => { - crate_types.clonable_types.insert("crate::".to_owned() + &trait_path); + crate_types.set_clonable("crate::".to_owned() + &trait_path); }, (_, _) => {} ) ); @@ -1587,7 +1548,7 @@ fn walk_ast<'a>(ast_storage: &'a FullLibraryAST, crate_types: &mut CrateTypes<'a if let Some(trait_path) = i.trait_.as_ref() { if path_matches_nongeneric(&trait_path.1, &["core", "clone", "Clone"]) { if let Some(full_path) = import_resolver.maybe_resolve_path(&p.path, None) { - crate_types.clonable_types.insert("crate::".to_owned() + &full_path); + crate_types.set_clonable("crate::".to_owned() + &full_path); } } if let Some(tp) = import_resolver.maybe_resolve_path(&trait_path.1, None) { @@ -1645,18 +1606,15 @@ fn main() { // ...then walk the ASTs tracking what types we will map, and how, so that we can resolve them // when parsing other file ASTs... - let mut libtypes = CrateTypes { traits: HashMap::new(), opaques: HashMap::new(), mirrored_enums: HashMap::new(), - type_aliases: HashMap::new(), reverse_alias_map: HashMap::new(), templates_defined: HashMap::default(), - template_file: &mut derived_templates, - clonable_types: HashSet::new(), trait_impls: HashMap::new() }; + let mut libtypes = CrateTypes::new(&mut derived_templates, &libast); walk_ast(&libast, &mut libtypes); // ... finally, do the actual file conversion/mapping, writing out types as we go. - convert_file(&libast, &mut libtypes, &args[1], &args[2], &mut header_file, &mut cpp_header_file); + convert_file(&libast, &libtypes, &args[1], &args[2], &mut header_file, &mut cpp_header_file); // For container templates which we created while walking the crate, make sure we add C++ // mapped types so that C++ users can utilize the auto-destructors available. - for (ty, has_destructor) in libtypes.templates_defined.iter() { + for (ty, has_destructor) in libtypes.templates_defined.borrow().iter() { write_cpp_wrapper(&mut cpp_header_file, ty, *has_destructor); } writeln!(cpp_header_file, "}}").unwrap(); diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 10f83e5..92da872 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -6,6 +6,7 @@ // You may not use this file except in accordance with one or both of these // licenses. +use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::fs::File; use std::io::Write; @@ -159,23 +160,21 @@ pub fn is_enum_opaque(e: &syn::ItemEnum) -> bool { /// It maps both direct types as well as Deref, mapping them via the provided /// TypeResolver's resolve_path function (ie traits map to the concrete jump table, structs to the /// concrete C container struct, etc). -pub struct GenericTypes<'a> { - typed_generics: Vec)>>, +#[must_use] +pub struct GenericTypes<'a, 'b> { + parent: Option<&'b GenericTypes<'b, 'b>>, + typed_generics: HashMap<&'a syn::Ident, (String, Option<&'a syn::Path>)>, } -impl<'a> GenericTypes<'a> { +impl<'a, 'p: 'a> GenericTypes<'a, 'p> { pub fn new() -> Self { - Self { typed_generics: vec![HashMap::new()], } + Self { parent: None, typed_generics: HashMap::new(), } } /// push a new context onto the stack, allowing for a new set of generics to be learned which /// will override any lower contexts, but which will still fall back to resoltion via lower /// contexts. - pub fn push_ctx(&mut self) { - self.typed_generics.push(HashMap::new()); - } - /// pop the latest context off the stack. - pub fn pop_ctx(&mut self) { - self.typed_generics.pop(); + pub fn push_ctx<'c>(&'c self) -> GenericTypes<'a, 'c> { + GenericTypes { parent: Some(self), typed_generics: HashMap::new(), } } /// Learn the generics in generics in the current context, given a TypeResolver. @@ -201,7 +200,7 @@ impl<'a> GenericTypes<'a> { path = "crate::".to_string() + &path; Some(&trait_bound.path) } else { None }; - self.typed_generics.last_mut().unwrap().insert(&type_param.ident, (path, new_ident)); + self.typed_generics.insert(&type_param.ident, (path, new_ident)); } else { return false; } } } @@ -217,7 +216,7 @@ impl<'a> GenericTypes<'a> { if p.qself.is_some() { return false; } if p.path.leading_colon.is_some() { return false; } let mut p_iter = p.path.segments.iter(); - if let Some(gen) = self.typed_generics.last_mut().unwrap().get_mut(&p_iter.next().unwrap().ident) { + if let Some(gen) = self.typed_generics.get_mut(&p_iter.next().unwrap().ident) { if gen.0 != "std::ops::Deref" { return false; } if &format!("{}", p_iter.next().unwrap().ident) != "Target" { return false; } @@ -236,7 +235,7 @@ impl<'a> GenericTypes<'a> { } } } - for (_, (_, ident)) in self.typed_generics.last().unwrap().iter() { + for (_, (_, ident)) in self.typed_generics.iter() { if ident.is_none() { return false; } } true @@ -262,7 +261,7 @@ impl<'a> GenericTypes<'a> { path = "crate::".to_string() + &path; Some(&tr.path) } else { None }; - self.typed_generics.last_mut().unwrap().insert(&t.ident, (path, new_ident)); + self.typed_generics.insert(&t.ident, (path, new_ident)); } else { unimplemented!(); } }, _ => unimplemented!(), @@ -276,21 +275,21 @@ impl<'a> GenericTypes<'a> { /// Attempt to resolve an Ident as a generic parameter and return the full path. pub fn maybe_resolve_ident<'b>(&'b self, ident: &syn::Ident) -> Option<&'b String> { - for gen in self.typed_generics.iter().rev() { - if let Some(res) = gen.get(ident).map(|(a, _)| a) { - return Some(res); - } + if let Some(res) = self.typed_generics.get(ident).map(|(a, _)| a) { + return Some(res); + } + if let Some(parent) = self.parent { + parent.maybe_resolve_ident(ident) + } else { + None } - None } /// Attempt to resolve a Path as a generic parameter and return the full path. as both a string /// and syn::Path. pub fn maybe_resolve_path<'b>(&'b self, path: &syn::Path) -> Option<(&'b String, &'a syn::Path)> { if let Some(ident) = path.get_ident() { - for gen in self.typed_generics.iter().rev() { - if let Some(res) = gen.get(ident).map(|(a, b)| (a, b.unwrap())) { - return Some(res); - } + if let Some(res) = self.typed_generics.get(ident).map(|(a, b)| (a, b.unwrap())) { + return Some(res); } } else { // Associated types are usually specified as "Self::Generic", so we check for that @@ -298,14 +297,16 @@ impl<'a> GenericTypes<'a> { let mut it = path.segments.iter(); if path.segments.len() == 2 && format!("{}", it.next().unwrap().ident) == "Self" { let ident = &it.next().unwrap().ident; - for gen in self.typed_generics.iter().rev() { - if let Some(res) = gen.get(ident).map(|(a, b)| (a, b.unwrap())) { - return Some(res); - } + if let Some(res) = self.typed_generics.get(ident).map(|(a, b)| (a, b.unwrap())) { + return Some(res); } } } - None + if let Some(parent) = self.parent { + parent.maybe_resolve_path(path) + } else { + None + } } } @@ -539,6 +540,53 @@ impl<'mod_lifetime, 'crate_lft: 'mod_lifetime> ImportResolver<'mod_lifetime, 'cr #[allow(deprecated)] pub type NonRandomHash = hash::BuildHasherDefault; +/// A public module +pub struct ASTModule { + pub attrs: Vec, + pub items: Vec, + pub submods: Vec, +} +/// A struct containing the syn::File AST for each file in the crate. +pub struct FullLibraryAST { + pub modules: HashMap, +} +impl FullLibraryAST { + fn load_module(&mut self, module: String, attrs: Vec, mut items: Vec) { + let mut non_mod_items = Vec::with_capacity(items.len()); + let mut submods = Vec::with_capacity(items.len()); + for item in items.drain(..) { + match item { + syn::Item::Mod(m) if m.content.is_some() => { + if export_status(&m.attrs) == ExportStatus::Export { + if let syn::Visibility::Public(_) = m.vis { + let modident = format!("{}", m.ident); + let modname = if module != "" { + module.clone() + "::" + &modident + } else { + modident.clone() + }; + self.load_module(modname, m.attrs, m.content.unwrap().1); + submods.push(modident); + } else { + non_mod_items.push(syn::Item::Mod(m)); + } + } + }, + syn::Item::Mod(_) => panic!("--pretty=expanded output should never have non-body modules"), + _ => { non_mod_items.push(item); } + } + } + self.modules.insert(module, ASTModule { attrs, items: non_mod_items, submods }); + } + + pub fn load_lib(lib: syn::File) -> Self { + assert_eq!(export_status(&lib.attrs), ExportStatus::Export); + let mut res = Self { modules: HashMap::default() }; + res.load_module("".to_owned(), lib.attrs, lib.items); + res + } +} + /// Top-level struct tracking everything which has been defined while walking the crate. pub struct CrateTypes<'a> { /// This may contain structs or enums, but only when either is mapped as @@ -556,14 +604,38 @@ pub struct CrateTypes<'a> { /// exists. /// /// This is used at the end of processing to make C++ wrapper classes - pub templates_defined: HashMap, + pub templates_defined: RefCell>, /// The output file for any created template container types, written to as we find new /// template containers which need to be defined. - pub template_file: &'a mut File, + template_file: RefCell<&'a mut File>, /// Set of containers which are clonable - pub clonable_types: HashSet, + clonable_types: RefCell>, /// Key impls Value pub trait_impls: HashMap>, + /// The full set of modules in the crate(s) + pub lib_ast: &'a FullLibraryAST, +} + +impl<'a> CrateTypes<'a> { + pub fn new(template_file: &'a mut File, libast: &'a FullLibraryAST) -> Self { + CrateTypes { + opaques: HashMap::new(), mirrored_enums: HashMap::new(), traits: HashMap::new(), + type_aliases: HashMap::new(), reverse_alias_map: HashMap::new(), + templates_defined: RefCell::new(HashMap::default()), + clonable_types: RefCell::new(HashSet::new()), trait_impls: HashMap::new(), + template_file: RefCell::new(template_file), lib_ast: &libast, + } + } + pub fn set_clonable(&self, object: String) { + self.clonable_types.borrow_mut().insert(object); + } + pub fn is_clonable(&self, object: &str) -> bool { + self.clonable_types.borrow().contains(object) + } + pub fn write_new_template(&self, mangled_container: String, has_destructor: bool, created_container: &[u8]) { + self.template_file.borrow_mut().write(created_container).unwrap(); + self.templates_defined.borrow_mut().insert(mangled_container, has_destructor); + } } /// A struct which tracks resolving rust types into C-mapped equivalents, exists for one specific @@ -571,7 +643,7 @@ pub struct CrateTypes<'a> { pub struct TypeResolver<'mod_lifetime, 'crate_lft: 'mod_lifetime> { pub orig_crate: &'mod_lifetime str, pub module_path: &'mod_lifetime str, - pub crate_types: &'mod_lifetime mut CrateTypes<'crate_lft>, + pub crate_types: &'mod_lifetime CrateTypes<'crate_lft>, types: ImportResolver<'mod_lifetime, 'crate_lft>, } @@ -601,7 +673,7 @@ enum ContainerPrefixLocation { } impl<'a, 'c: 'a> TypeResolver<'a, 'c> { - pub fn new(orig_crate: &'a str, module_path: &'a str, types: ImportResolver<'a, 'c>, crate_types: &'a mut CrateTypes<'c>) -> Self { + pub fn new(orig_crate: &'a str, module_path: &'a str, types: ImportResolver<'a, 'c>, crate_types: &'a CrateTypes<'c>) -> Self { Self { orig_crate, module_path, types, crate_types } } @@ -636,7 +708,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } } pub fn is_clonable(&self, ty: &str) -> bool { - if self.crate_types.clonable_types.contains(ty) { return true; } + if self.crate_types.is_clonable(ty) { return true; } if self.is_primitive(ty) { return true; } match ty { "()" => true, @@ -1932,7 +2004,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // *** C Container Type Equivalent and alias Printing *** // ****************************************************** - fn write_template_generics<'b, W: std::io::Write>(&mut self, w: &mut W, args: &mut dyn Iterator, generics: Option<&GenericTypes>, is_ref: bool) -> bool { + fn write_template_generics<'b, W: std::io::Write>(&self, w: &mut W, args: &mut dyn Iterator, generics: Option<&GenericTypes>, is_ref: bool) -> bool { for (idx, t) in args.enumerate() { if idx != 0 { write!(w, ", ").unwrap(); @@ -1966,8 +2038,8 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } true } - fn check_create_container(&mut self, mangled_container: String, container_type: &str, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, is_ref: bool) -> bool { - if !self.crate_types.templates_defined.get(&mangled_container).is_some() { + fn check_create_container(&self, mangled_container: String, container_type: &str, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, is_ref: bool) -> bool { + if !self.crate_types.templates_defined.borrow().get(&mangled_container).is_some() { let mut created_container: Vec = Vec::new(); if container_type == "Result" { @@ -1998,7 +2070,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { let is_clonable = self.is_clonable(&ok_str) && self.is_clonable(&err_str); write_result_block(&mut created_container, &mangled_container, &ok_str, &err_str, is_clonable); if is_clonable { - self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container); + self.crate_types.set_clonable(Self::generated_container_path().to_owned() + "::" + &mangled_container); } } else if container_type == "Vec" { let mut a_ty: Vec = Vec::new(); @@ -2007,7 +2079,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { let is_clonable = self.is_clonable(&ty); write_vec_block(&mut created_container, &mangled_container, &ty, is_clonable); if is_clonable { - self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container); + self.crate_types.set_clonable(Self::generated_container_path().to_owned() + "::" + &mangled_container); } } else if container_type.ends_with("Tuple") { let mut tuple_args = Vec::new(); @@ -2023,7 +2095,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } write_tuple_block(&mut created_container, &mangled_container, &tuple_args, is_clonable); if is_clonable { - self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container); + self.crate_types.set_clonable(Self::generated_container_path().to_owned() + "::" + &mangled_container); } } else if container_type == "Option" { let mut a_ty: Vec = Vec::new(); @@ -2032,14 +2104,12 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { let is_clonable = self.is_clonable(&ty); write_option_block(&mut created_container, &mangled_container, &ty, is_clonable); if is_clonable { - self.crate_types.clonable_types.insert(Self::generated_container_path().to_owned() + "::" + &mangled_container); + self.crate_types.set_clonable(Self::generated_container_path().to_owned() + "::" + &mangled_container); } } else { unreachable!(); } - self.crate_types.templates_defined.insert(mangled_container.clone(), true); - - self.crate_types.template_file.write(&created_container).unwrap(); + self.crate_types.write_new_template(mangled_container.clone(), true, &created_container); } true } @@ -2049,7 +2119,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else { unimplemented!(); } } fn write_c_mangled_container_path_intern - (&mut self, w: &mut W, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, ident: &str, is_ref: bool, is_mut: bool, ptr_for_ref: bool, in_type: bool) -> bool { + (&self, w: &mut W, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, ident: &str, is_ref: bool, is_mut: bool, ptr_for_ref: bool, in_type: bool) -> bool { let mut mangled_type: Vec = Vec::new(); if !self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a)) { write!(w, "C{}_", ident).unwrap(); @@ -2161,7 +2231,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // Make sure the type is actually defined: self.check_create_container(String::from_utf8(mangled_type).unwrap(), ident, args, generics, is_ref) } - fn write_c_mangled_container_path(&mut self, w: &mut W, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, ident: &str, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool { + fn write_c_mangled_container_path(&self, w: &mut W, args: Vec<&syn::Type>, generics: Option<&GenericTypes>, ident: &str, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool { if !self.is_transparent_container(ident, is_ref, args.iter().map(|a| *a)) { write!(w, "{}::", Self::generated_container_path()).unwrap(); } @@ -2204,7 +2274,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { false } } - fn write_c_type_intern(&mut self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool { + fn write_c_type_intern(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, is_ref: bool, is_mut: bool, ptr_for_ref: bool) -> bool { match t { syn::Type::Path(p) => { if p.qself.is_some() { @@ -2295,14 +2365,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { _ => false, } } - pub fn write_c_type(&mut self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool) { + pub fn write_c_type(&self, w: &mut W, t: &syn::Type, generics: Option<&GenericTypes>, ptr_for_ref: bool) { assert!(self.write_c_type_intern(w, t, generics, false, false, ptr_for_ref)); } - pub fn understood_c_path(&mut self, p: &syn::Path) -> bool { + pub fn understood_c_path(&self, p: &syn::Path) -> bool { if p.leading_colon.is_some() { return false; } self.write_c_path_intern(&mut std::io::sink(), p, None, false, false, false) } - pub fn understood_c_type(&mut self, t: &syn::Type, generics: Option<&GenericTypes>) -> bool { + pub fn understood_c_type(&self, t: &syn::Type, generics: Option<&GenericTypes>) -> bool { self.write_c_type_intern(&mut std::io::sink(), t, generics, false, false, false) } } diff --git a/lightning-c-bindings/Cargo.toml b/lightning-c-bindings/Cargo.toml index e8e556b..788cff1 100644 --- a/lightning-c-bindings/Cargo.toml +++ b/lightning-c-bindings/Cargo.toml @@ -18,11 +18,11 @@ crate-type = ["staticlib" bitcoin = "0.26" secp256k1 = { version = "0.20.1", features = ["global-context-less-secure"] } # Note that the following line is matched by genbindings to update the path -lightning = { git = "https://git.bitcoin.ninja/rust-lightning", rev = "6fcac8bc65ed6d372e0b8c367e9934c754f99ff3", features = ["allow_wallclock_use"] } +lightning = { git = "https://git.bitcoin.ninja/rust-lightning", rev = "8088e4ba1505c026ac91f8c1489fb7d53d6b656e", features = ["allow_wallclock_use"] } [patch.crates-io] # Rust-Secp256k1 PR 279. Should be dropped once merged. -secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1', rev = '15a0d4195a20355f6b1e8f54c84eba56abc15cbd' } +secp256k1 = { git = 'https://github.com/TheBlueMatt/rust-secp256k1', rev = '50bf9e48ca0f0d267c41e729520a2673ecfaa84f' } # Always force panic=abort, further options are set in the genbindings.sh build script [profile.dev] diff --git a/lightning-c-bindings/demo.cpp b/lightning-c-bindings/demo.cpp index 230e334..222e29e 100644 --- a/lightning-c-bindings/demo.cpp +++ b/lightning-c-bindings/demo.cpp @@ -373,8 +373,8 @@ int main() { // Demo getting a channel key and check that its returning real pubkeys: LDK::Sign chan_signer1 = keys_source1->get_channel_signer(keys_source1->this_arg, false, 42); - chan_signer1->set_pubkeys(&chan_signer1); // Make sure pubkeys is defined - LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->pubkeys); + chan_signer1->BaseSign.set_pubkeys(&chan_signer1->BaseSign); // Make sure pubkeys is defined + LDKPublicKey payment_point = ChannelPublicKeys_get_payment_point(&chan_signer1->BaseSign.pubkeys); assert(memcmp(&payment_point, &null_pk, sizeof(null_pk))); // Instantiate classes for node 2: @@ -437,10 +437,10 @@ int main() { 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_block + 58 + 81, 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, std::move(outp)); + LDKTransaction funding_transaction { .data = const_cast(channel_open_block + 81), .datalen = sizeof(channel_open_block) - 81, .data_is_owned = false }; + + LDK::CResult_NoneAPIErrorZ fund_res = ChannelManager_funding_transaction_generated(&cm1, &events->data[0].funding_generation_ready.temporary_channel_id.data, funding_transaction); + assert(fund_res->result_ok); break; } std::this_thread::yield(); @@ -448,14 +448,9 @@ int main() { // We observe when the funding signed messages have been exchanged by // waiting for two monitors to be registered. + assert(num_txs_broadcasted == 0); 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; - } + while (num_txs_broadcasted != 1) { std::this_thread::yield(); } diff --git a/lightning-c-bindings/include/lightning.h b/lightning-c-bindings/include/lightning.h index bdeb298..168bc7c 100644 --- a/lightning-c-bindings/include/lightning.h +++ b/lightning-c-bindings/include/lightning.h @@ -3201,12 +3201,6 @@ typedef enum LDKEvent_Tag { * counterparty can steal your funds! */ LDKEvent_FundingGenerationReady, - /** - * 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! - */ - LDKEvent_FundingBroadcastSafe, /** * Indicates we've received money! Just gotta dig out that payment preimage and feed it to * ChannelManager::claim_funds to get it.... @@ -3272,18 +3266,6 @@ typedef struct LDKEvent_LDKFundingGenerationReady_Body { uint64_t user_channel_id; } LDKEvent_LDKFundingGenerationReady_Body; -typedef struct LDKEvent_LDKFundingBroadcastSafe_Body { - /** - * The output, which was passed to ChannelManager::funding_transaction_generated, which is - * now safe to broadcast. - */ - struct LDKOutPoint funding_txo; - /** - * The value passed in to ChannelManager::create_channel - */ - uint64_t user_channel_id; -} LDKEvent_LDKFundingBroadcastSafe_Body; - typedef struct LDKEvent_LDKPaymentReceived_Body { /** * The hash for which the preimage should be handed to the ChannelManager. @@ -3352,7 +3334,6 @@ typedef struct MUST_USE_STRUCT LDKEvent { LDKEvent_Tag tag; union { LDKEvent_LDKFundingGenerationReady_Body funding_generation_ready; - LDKEvent_LDKFundingBroadcastSafe_Body funding_broadcast_safe; LDKEvent_LDKPaymentReceived_Body payment_received; LDKEvent_LDKPaymentSent_Body payment_sent; LDKEvent_LDKPaymentFailed_Body payment_failed; @@ -3820,7 +3801,7 @@ typedef struct MUST_USE_STRUCT LDKUnsignedChannelAnnouncement { * to act, as liveness and breach reply correctness are always going to be hard requirements * of LN security model, orthogonal of key management issues. */ -typedef struct LDKSign { +typedef struct LDKBaseSign { /** * An opaque pointer which is passed to your function implementations as an argument. * This has no meaning in the LDK, and can be NULL or any other value. @@ -3852,7 +3833,7 @@ typedef struct LDKSign { * 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. */ - void (*set_pubkeys)(const struct LDKSign*NONNULL_PTR ); + void (*set_pubkeys)(const struct LDKBaseSign*NONNULL_PTR ); /** * Gets an arbitrary identifier describing the set of keys which are provided back to you in * some SpendableOutputDescriptor types. This should be sufficient to identify this @@ -3950,15 +3931,44 @@ typedef struct LDKSign { */ void (*ready_channel)(void *this_arg, const struct LDKChannelTransactionParameters *NONNULL_PTR channel_parameters); /** - * Creates a copy of the object pointed to by this_arg, for a copy of this Sign. - * Note that the ultimate copy of the Sign will have all function pointers the same as the original. - * May be NULL if no action needs to be taken, the this_arg pointer will be copied into the new Sign. + * Frees any resources associated with this object given its this_arg pointer. + * Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed. */ - void *(*clone)(const void *this_arg); + void (*free)(void *this_arg); +} LDKBaseSign; + +/** + * A cloneable signer. + * + * Although we require signers to be cloneable, it may be useful for developers to be able to use + * signers in an un-sized way, for example as `dyn BaseSign`. Therefore we separate the Clone trait, + * which implies Sized, into this derived trait. + */ +typedef struct LDKSign { + /** + * An opaque pointer which is passed to your function implementations as an argument. + * This has no meaning in the LDK, and can be NULL or any other value. + */ + void *this_arg; + /** + * Implementation of BaseSign for this object. + */ + struct LDKBaseSign BaseSign; + /** + * Creates a copy of the BaseSign, for a copy of this Sign. + * Because BaseSign doesn't natively support copying itself, you have to provide a full copy implementation here. + */ + struct LDKBaseSign (*BaseSign_clone)(const struct LDKBaseSign *NONNULL_PTR orig_BaseSign); /** * Serialize the object into a byte array */ struct LDKCVec_u8Z (*write)(const void *this_arg); + /** + * Creates a copy of the object pointed to by this_arg, for a copy of this Sign. + * Note that the ultimate copy of the Sign will have all function pointers the same as the original. + * May be NULL if no action needs to be taken, the this_arg pointer will be copied into the new Sign. + */ + void *(*clone)(const void *this_arg); /** * Frees any resources associated with this object given its this_arg pointer. * Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed. @@ -10531,6 +10541,11 @@ struct LDKCVec_u8Z SpendableOutputDescriptor_write(const struct LDKSpendableOutp */ struct LDKCResult_SpendableOutputDescriptorDecodeErrorZ SpendableOutputDescriptor_read(struct LDKu8slice ser); +/** + * Calls the free function if one is set + */ +void BaseSign_free(struct LDKBaseSign this_ptr); + /** * Creates a copy of a Sign */ @@ -10682,6 +10697,12 @@ MUST_USE_RES struct LDKCResult_CVec_CVec_u8ZZNoneZ InMemorySigner_sign_counterpa */ MUST_USE_RES struct LDKCResult_CVec_CVec_u8ZZNoneZ InMemorySigner_sign_dynamic_p2wsh_input(const struct LDKInMemorySigner *NONNULL_PTR this_arg, struct LDKTransaction spend_tx, uintptr_t input_idx, const struct LDKDelayedPaymentOutputDescriptor *NONNULL_PTR descriptor); +/** + * Constructs a new BaseSign which calls the relevant methods on this_arg. + * This copies the `inner` pointer in this_arg and thus the returned BaseSign must be freed before this_arg is + */ +struct LDKBaseSign InMemorySigner_as_BaseSign(const struct LDKInMemorySigner *NONNULL_PTR this_arg); + /** * Constructs a new Sign which calls the relevant methods on this_arg. * This copies the `inner` pointer in this_arg and thus the returned Sign must be freed before this_arg is @@ -10962,10 +10983,11 @@ MUST_USE_RES struct LDKChannelManager ChannelManager_new(struct LDKFeeEstimator /** * 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. + * user_id will be provided back as user_channel_id in FundingGenerationReady events to allow + * tracking of which events correspond with which create_channel call. Note that the + * user_channel_id defaults to 0 for inbound channels, so you may wish to avoid using 0 for + * user_id here. user_id has no meaning inside of LDK, it is simply copied to events and + * otherwise ignored. * * If successful, will generate a SendOpenChannel message event, so you should probably poll * PeerManager::process_events afterwards. @@ -11057,15 +11079,24 @@ MUST_USE_RES struct LDKCResult_NonePaymentSendFailureZ ChannelManager_send_payme /** * 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! + * Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs + * or if no output was found which matches the parameters in [`Event::FundingGenerationReady`]. * * 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). + * May panic if the output found in the funding transaction is duplicative with some other + * channel (note that this should be trivially prevented by using unique funding transaction + * keys per-channel). + * + * Do NOT broadcast the funding transaction yourself. When we have safely received our + * counterparty's signature the funding transaction will automatically be broadcast via the + * [`BroadcasterInterface`] provided when this `ChannelManager` was constructed. + * + * Note that this includes RBF or similar transaction replacement strategies - lightning does + * not currently support replacing a funding transaction on an existing channel. Instead, + * create a new channel with a conflicting funding transaction. */ -void ChannelManager_funding_transaction_generated(const struct LDKChannelManager *NONNULL_PTR this_arg, const uint8_t (*temporary_channel_id)[32], struct LDKOutPoint funding_txo); +MUST_USE_RES struct LDKCResult_NoneAPIErrorZ ChannelManager_funding_transaction_generated(const struct LDKChannelManager *NONNULL_PTR this_arg, const uint8_t (*temporary_channel_id)[32], struct LDKTransaction funding_transaction); /** * Generates a signed node_announcement from the given arguments and creates a @@ -11179,17 +11210,42 @@ struct LDKEventsProvider ChannelManager_as_EventsProvider(const struct LDKChanne struct LDKListen ChannelManager_as_Listen(const struct LDKChannelManager *NONNULL_PTR this_arg); /** - * Updates channel state based on transactions seen in a connected block. + * Updates channel state to take note of transactions which were confirmed in the given block + * at the given height. + * + * Note that you must still call (or have called) [`update_best_block`] with the block + * information which is included here. + * + * This method may be called before or after [`update_best_block`] for a given block's + * transaction data and may be called multiple times with additional transaction data for a + * given block. + * + * This method may be called for a previous block after an [`update_best_block`] call has + * been made for a later block, however it must *not* be called with transaction data from a + * block which is no longer in the best chain (ie where [`update_best_block`] has already + * been informed about a blockchain reorganization which no longer includes the block which + * corresponds to `header`). + * + * [`update_best_block`]: `Self::update_best_block` */ -void ChannelManager_block_connected(const struct LDKChannelManager *NONNULL_PTR this_arg, const uint8_t (*header)[80], struct LDKCVec_C2Tuple_usizeTransactionZZ txdata, uint32_t height); +void ChannelManager_transactions_confirmed(const struct LDKChannelManager *NONNULL_PTR this_arg, const uint8_t (*header)[80], uint32_t height, struct LDKCVec_C2Tuple_usizeTransactionZZ txdata); /** - * Updates channel state based on a disconnected block. + * Updates channel state with the current best blockchain tip. You should attempt to call this + * quickly after a new block becomes available, however if multiple new blocks become + * available at the same time, only a single `update_best_block()` call needs to be made. + * + * This method should also be called immediately after any block disconnections, once at the + * reorganization fork point, and once with the new chain tip. Calling this method at the + * blockchain reorganization fork point ensures we learn when a funding transaction which was + * previously confirmed is reorganized out of the blockchain, ensuring we do not continue to + * accept payments which cannot be enforced on-chain. * - * If necessary, the channel may be force-closed without letting the counterparty participate - * in the shutdown. + * In both the block-connection and block-disconnection case, this method may be called either + * once per block connected or disconnected, or simply at the fork point and new tip(s), + * skipping any intermediary blocks. */ -void ChannelManager_block_disconnected(const struct LDKChannelManager *NONNULL_PTR this_arg, const uint8_t (*header)[80]); +void ChannelManager_update_best_block(const struct LDKChannelManager *NONNULL_PTR this_arg, const uint8_t (*header)[80], uint32_t height); /** * Blocks until ChannelManager needs to be persisted or a timeout is reached. It returns a bool diff --git a/lightning-c-bindings/include/lightningpp.hpp b/lightning-c-bindings/include/lightningpp.hpp index b73d943..ef43273 100644 --- a/lightning-c-bindings/include/lightningpp.hpp +++ b/lightning-c-bindings/include/lightningpp.hpp @@ -971,6 +971,21 @@ public: const LDKSpendableOutputDescriptor* operator &() const { return &self; } const LDKSpendableOutputDescriptor* operator ->() const { return &self; } }; +class BaseSign { +private: + LDKBaseSign self; +public: + BaseSign(const BaseSign&) = delete; + BaseSign(BaseSign&& o) : self(o.self) { memset(&o, 0, sizeof(BaseSign)); } + BaseSign(LDKBaseSign&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKBaseSign)); } + operator LDKBaseSign() && { LDKBaseSign res = self; memset(&self, 0, sizeof(LDKBaseSign)); return res; } + ~BaseSign() { BaseSign_free(self); } + BaseSign& operator=(BaseSign&& o) { BaseSign_free(self); self = o.self; memset(&o, 0, sizeof(BaseSign)); return *this; } + LDKBaseSign* operator &() { return &self; } + LDKBaseSign* operator ->() { return &self; } + const LDKBaseSign* operator &() const { return &self; } + const LDKBaseSign* operator ->() const { return &self; } +}; class Sign { private: LDKSign self; diff --git a/lightning-c-bindings/include/rust_types.h b/lightning-c-bindings/include/rust_types.h index aecf627..34db4a6 100644 --- a/lightning-c-bindings/include/rust_types.h +++ b/lightning-c-bindings/include/rust_types.h @@ -99,8 +99,8 @@ struct nativeDelayedPaymentOutputDescriptorOpaque; typedef struct nativeDelayedPaymentOutputDescriptorOpaque LDKnativeDelayedPaymentOutputDescriptor; struct nativeStaticPaymentOutputDescriptorOpaque; typedef struct nativeStaticPaymentOutputDescriptorOpaque LDKnativeStaticPaymentOutputDescriptor; -struct LDKSign; -typedef struct LDKSign LDKSign; +struct LDKBaseSign; +typedef struct LDKBaseSign LDKBaseSign; struct nativeInMemorySignerOpaque; typedef struct nativeInMemorySignerOpaque LDKnativeInMemorySigner; struct nativeKeysManagerOpaque; diff --git a/lightning-c-bindings/src/chain/keysinterface.rs b/lightning-c-bindings/src/chain/keysinterface.rs index daa76b7..5c50e53 100644 --- a/lightning-c-bindings/src/chain/keysinterface.rs +++ b/lightning-c-bindings/src/chain/keysinterface.rs @@ -481,7 +481,7 @@ pub extern "C" fn SpendableOutputDescriptor_read(ser: crate::c_types::u8slice) - /// to act, as liveness and breach reply correctness are always going to be hard requirements /// of LN security model, orthogonal of key management issues. #[repr(C)] -pub struct Sign { +pub struct BaseSign { /// An opaque pointer which is passed to your function implementations as an argument. /// This has no meaning in the LDK, and can be NULL or any other value. pub this_arg: *mut c_void, @@ -505,7 +505,7 @@ pub struct Sign { /// 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, + pub set_pubkeys: Option, /// Gets an arbitrary identifier describing the set of keys which are provided back to you in /// some SpendableOutputDescriptor types. This should be sufficient to identify this /// Sign object uniquely and lookup or re-derive its keys. @@ -593,54 +593,15 @@ pub struct Sign { /// /// Will be called before any signatures are applied. pub ready_channel: extern "C" fn (this_arg: *mut c_void, channel_parameters: &crate::ln::chan_utils::ChannelTransactionParameters), - /// Creates a copy of the object pointed to by this_arg, for a copy of this Sign. - /// Note that the ultimate copy of the Sign will have all function pointers the same as the original. - /// May be NULL if no action needs to be taken, the this_arg pointer will be copied into the new Sign. - pub clone: Option *mut c_void>, - /// Serialize the object into a byte array - pub write: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_u8Z, /// Frees any resources associated with this object given its this_arg pointer. /// Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed. pub free: Option, } -unsafe impl Send for Sign {} -#[no_mangle] -/// Creates a copy of a Sign -pub extern "C" fn Sign_clone(orig: &Sign) -> Sign { - Sign { - this_arg: if let Some(f) = orig.clone { (f)(orig.this_arg) } else { orig.this_arg }, - get_per_commitment_point: orig.get_per_commitment_point.clone(), - release_commitment_secret: orig.release_commitment_secret.clone(), - pubkeys: orig.pubkeys.clone(), - set_pubkeys: orig.set_pubkeys.clone(), - channel_keys_id: orig.channel_keys_id.clone(), - sign_counterparty_commitment: orig.sign_counterparty_commitment.clone(), - sign_holder_commitment_and_htlcs: orig.sign_holder_commitment_and_htlcs.clone(), - sign_justice_transaction: orig.sign_justice_transaction.clone(), - sign_counterparty_htlc_transaction: orig.sign_counterparty_htlc_transaction.clone(), - sign_closing_transaction: orig.sign_closing_transaction.clone(), - sign_channel_announcement: orig.sign_channel_announcement.clone(), - ready_channel: orig.ready_channel.clone(), - clone: orig.clone.clone(), - write: orig.write.clone(), - free: orig.free.clone(), - } -} -impl Clone for Sign { - fn clone(&self) -> Self { - Sign_clone(self) - } -} -impl lightning::util::ser::Writeable for Sign { - fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { - let vec = (self.write)(self.this_arg); - w.write_all(vec.as_slice()) - } -} +unsafe impl Send for BaseSign {} -use lightning::chain::keysinterface::Sign as rustSign; -impl rustSign for Sign { - fn get_per_commitment_point(&self, idx: u64, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> bitcoin::secp256k1::key::PublicKey { +use lightning::chain::keysinterface::BaseSign as rustBaseSign; +impl rustBaseSign for BaseSign { + fn get_per_commitment_point(&self, idx: u64, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> bitcoin::secp256k1::key::PublicKey { let mut ret = (self.get_per_commitment_point)(self.this_arg, idx); ret.into_rust() } @@ -650,7 +611,7 @@ impl rustSign for Sign { } fn pubkeys(&self) -> &lightning::ln::chan_utils::ChannelPublicKeys { if let Some(f) = self.set_pubkeys { - (f)(self); + (f)(&self); } unsafe { &*self.pubkeys.inner } } @@ -658,36 +619,36 @@ impl rustSign for Sign { let mut ret = (self.channel_keys_id)(self.this_arg); ret.data } - fn sign_counterparty_commitment(&self, commitment_tx: &lightning::ln::chan_utils::CommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result<(bitcoin::secp256k1::Signature, Vec), ()> { + fn sign_counterparty_commitment(&self, commitment_tx: &lightning::ln::chan_utils::CommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result<(bitcoin::secp256k1::Signature, Vec), ()> { let mut ret = (self.sign_counterparty_commitment)(self.this_arg, &crate::ln::chan_utils::CommitmentTransaction { inner: unsafe { (commitment_tx as *const _) as *mut _ }, is_owned: false }); 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(<*mut _>::take_ptr(&mut ret.contents.result)) }).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(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; local_ret } - fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &lightning::ln::chan_utils::HolderCommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result<(bitcoin::secp256k1::Signature, Vec), ()> { + fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &lightning::ln::chan_utils::HolderCommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result<(bitcoin::secp256k1::Signature, Vec), ()> { let mut ret = (self.sign_holder_commitment_and_htlcs)(self.this_arg, &crate::ln::chan_utils::HolderCommitmentTransaction { inner: unsafe { (commitment_tx as *const _) as *mut _ }, is_owned: false }); 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(<*mut _>::take_ptr(&mut ret.contents.result)) }).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(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; local_ret } - fn sign_justice_transaction(&self, justice_tx: &bitcoin::blockdata::transaction::Transaction, input: usize, amount: u64, per_commitment_key: &bitcoin::secp256k1::key::SecretKey, htlc: &Option, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { + fn sign_justice_transaction(&self, justice_tx: &bitcoin::blockdata::transaction::Transaction, input: usize, amount: u64, per_commitment_key: &bitcoin::secp256k1::key::SecretKey, htlc: &Option, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { 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_vec(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(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; local_ret } - fn sign_counterparty_htlc_transaction(&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) -> Result { + fn sign_counterparty_htlc_transaction(&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) -> Result { let mut local_htlc_tx = ::bitcoin::consensus::encode::serialize(htlc_tx); let mut ret = (self.sign_counterparty_htlc_transaction)(self.this_arg, crate::c_types::Transaction::from_vec(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(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; local_ret } - fn sign_closing_transaction(&self, closing_tx: &bitcoin::blockdata::transaction::Transaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { + fn sign_closing_transaction(&self, closing_tx: &bitcoin::blockdata::transaction::Transaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { 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_vec(local_closing_tx)); let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; local_ret } - fn sign_channel_announcement(&self, msg: &lightning::ln::msgs::UnsignedChannelAnnouncement, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { + fn sign_channel_announcement(&self, msg: &lightning::ln::msgs::UnsignedChannelAnnouncement, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { 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(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; local_ret @@ -697,6 +658,135 @@ impl rustSign for Sign { } } +// 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 BaseSign { + type Target = Self; + fn deref(&self) -> &Self { + self + } +} +/// Calls the free function if one is set +#[no_mangle] +pub extern "C" fn BaseSign_free(this_ptr: BaseSign) { } +impl Drop for BaseSign { + fn drop(&mut self) { + if let Some(f) = self.free { + f(self.this_arg); + } + } +} +/// A cloneable signer. +/// +/// Although we require signers to be cloneable, it may be useful for developers to be able to use +/// signers in an un-sized way, for example as `dyn BaseSign`. Therefore we separate the Clone trait, +/// which implies Sized, into this derived trait. +#[repr(C)] +pub struct Sign { + /// An opaque pointer which is passed to your function implementations as an argument. + /// This has no meaning in the LDK, and can be NULL or any other value. + pub this_arg: *mut c_void, + /// Implementation of BaseSign for this object. + pub BaseSign: crate::chain::keysinterface::BaseSign, + /// Creates a copy of the BaseSign, for a copy of this Sign. + /// Because BaseSign doesn't natively support copying itself, you have to provide a full copy implementation here. + pub BaseSign_clone: extern "C" fn (orig_BaseSign: &BaseSign) -> BaseSign, + /// Serialize the object into a byte array + pub write: extern "C" fn (this_arg: *const c_void) -> crate::c_types::derived::CVec_u8Z, + /// Creates a copy of the object pointed to by this_arg, for a copy of this Sign. + /// Note that the ultimate copy of the Sign will have all function pointers the same as the original. + /// May be NULL if no action needs to be taken, the this_arg pointer will be copied into the new Sign. + pub clone: Option *mut c_void>, + /// Frees any resources associated with this object given its this_arg pointer. + /// Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed. + pub free: Option, +} +impl lightning::chain::keysinterface::BaseSign for Sign { + fn get_per_commitment_point(&self, idx: u64, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> bitcoin::secp256k1::key::PublicKey { + let mut ret = (self.BaseSign.get_per_commitment_point)(self.this_arg, idx); + ret.into_rust() + } + fn release_commitment_secret(&self, idx: u64) -> [u8; 32] { + let mut ret = (self.BaseSign.release_commitment_secret)(self.this_arg, idx); + ret.data + } + fn pubkeys(&self) -> &lightning::ln::chan_utils::ChannelPublicKeys { + if let Some(f) = self.BaseSign.set_pubkeys { + (f)(&self.BaseSign); + } + unsafe { &*self.BaseSign.pubkeys.inner } + } + fn channel_keys_id(&self) -> [u8; 32] { + let mut ret = (self.BaseSign.channel_keys_id)(self.this_arg); + ret.data + } + fn sign_counterparty_commitment(&self, commitment_tx: &lightning::ln::chan_utils::CommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result<(bitcoin::secp256k1::Signature, Vec), ()> { + let mut ret = (self.BaseSign.sign_counterparty_commitment)(self.this_arg, &crate::ln::chan_utils::CommitmentTransaction { inner: unsafe { (commitment_tx as *const _) as *mut _ }, is_owned: false }); + 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(<*mut _>::take_ptr(&mut ret.contents.result)) }).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(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; + local_ret + } + fn sign_holder_commitment_and_htlcs(&self, commitment_tx: &lightning::ln::chan_utils::HolderCommitmentTransaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result<(bitcoin::secp256k1::Signature, Vec), ()> { + let mut ret = (self.BaseSign.sign_holder_commitment_and_htlcs)(self.this_arg, &crate::ln::chan_utils::HolderCommitmentTransaction { inner: unsafe { (commitment_tx as *const _) as *mut _ }, is_owned: false }); + 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(<*mut _>::take_ptr(&mut ret.contents.result)) }).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(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; + local_ret + } + fn sign_justice_transaction(&self, justice_tx: &bitcoin::blockdata::transaction::Transaction, input: usize, amount: u64, per_commitment_key: &bitcoin::secp256k1::key::SecretKey, htlc: &Option, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { + 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.BaseSign.sign_justice_transaction)(self.this_arg, crate::c_types::Transaction::from_vec(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(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; + local_ret + } + fn sign_counterparty_htlc_transaction(&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) -> Result { + let mut local_htlc_tx = ::bitcoin::consensus::encode::serialize(htlc_tx); + let mut ret = (self.BaseSign.sign_counterparty_htlc_transaction)(self.this_arg, crate::c_types::Transaction::from_vec(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(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; + local_ret + } + fn sign_closing_transaction(&self, closing_tx: &bitcoin::blockdata::transaction::Transaction, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { + let mut local_closing_tx = ::bitcoin::consensus::encode::serialize(closing_tx); + let mut ret = (self.BaseSign.sign_closing_transaction)(self.this_arg, crate::c_types::Transaction::from_vec(local_closing_tx)); + let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; + local_ret + } + fn sign_channel_announcement(&self, msg: &lightning::ln::msgs::UnsignedChannelAnnouncement, _secp_ctx: &bitcoin::secp256k1::Secp256k1) -> Result { + let mut ret = (self.BaseSign.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(<*mut _>::take_ptr(&mut ret.contents.result)) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(<*mut _>::take_ptr(&mut ret.contents.err)) })*/ })}; + local_ret + } + fn ready_channel(&mut self, channel_parameters: &lightning::ln::chan_utils::ChannelTransactionParameters) { + (self.BaseSign.ready_channel)(self.this_arg, &crate::ln::chan_utils::ChannelTransactionParameters { inner: unsafe { (channel_parameters as *const _) as *mut _ }, is_owned: false }) + } +} +unsafe impl Send for Sign {} +impl lightning::util::ser::Writeable for Sign { + fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { + let vec = (self.write)(self.this_arg); + w.write_all(vec.as_slice()) + } +} +#[no_mangle] +/// Creates a copy of a Sign +pub extern "C" fn Sign_clone(orig: &Sign) -> Sign { + Sign { + this_arg: if let Some(f) = orig.clone { (f)(orig.this_arg) } else { orig.this_arg }, + BaseSign: (orig.BaseSign_clone)(&orig.BaseSign), + BaseSign_clone: orig.BaseSign_clone, + write: Clone::clone(&orig.write), + clone: Clone::clone(&orig.clone), + free: Clone::clone(&orig.free), + } +} +impl Clone for Sign { + fn clone(&self) -> Self { + Sign_clone(self) + } +} + +use lightning::chain::keysinterface::Sign as rustSign; +impl rustSign for Sign { +} + // 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 Sign { @@ -1044,107 +1134,165 @@ pub extern "C" fn InMemorySigner_sign_dynamic_p2wsh_input(this_arg: &InMemorySig local_ret } -impl From for crate::chain::keysinterface::Sign { +impl From for crate::chain::keysinterface::BaseSign { fn from(obj: nativeInMemorySigner) -> Self { let mut rust_obj = InMemorySigner { inner: Box::into_raw(Box::new(obj)), is_owned: true }; - let mut ret = InMemorySigner_as_Sign(&rust_obj); + let mut ret = InMemorySigner_as_BaseSign(&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(InMemorySigner_free_void); ret } } -/// Constructs a new Sign which calls the relevant methods on this_arg. -/// This copies the `inner` pointer in this_arg and thus the returned Sign must be freed before this_arg is +/// Constructs a new BaseSign which calls the relevant methods on this_arg. +/// This copies the `inner` pointer in this_arg and thus the returned BaseSign must be freed before this_arg is #[no_mangle] -pub extern "C" fn InMemorySigner_as_Sign(this_arg: &InMemorySigner) -> crate::chain::keysinterface::Sign { - crate::chain::keysinterface::Sign { +pub extern "C" fn InMemorySigner_as_BaseSign(this_arg: &InMemorySigner) -> crate::chain::keysinterface::BaseSign { + crate::chain::keysinterface::BaseSign { this_arg: unsafe { (*this_arg).inner as *mut c_void }, free: None, - get_per_commitment_point: InMemorySigner_Sign_get_per_commitment_point, - release_commitment_secret: InMemorySigner_Sign_release_commitment_secret, + get_per_commitment_point: InMemorySigner_BaseSign_get_per_commitment_point, + release_commitment_secret: InMemorySigner_BaseSign_release_commitment_secret, pubkeys: crate::ln::chan_utils::ChannelPublicKeys { inner: std::ptr::null_mut(), is_owned: true }, - set_pubkeys: Some(InMemorySigner_Sign_set_pubkeys), - channel_keys_id: InMemorySigner_Sign_channel_keys_id, - sign_counterparty_commitment: InMemorySigner_Sign_sign_counterparty_commitment, - sign_holder_commitment_and_htlcs: InMemorySigner_Sign_sign_holder_commitment_and_htlcs, - sign_justice_transaction: InMemorySigner_Sign_sign_justice_transaction, - sign_counterparty_htlc_transaction: InMemorySigner_Sign_sign_counterparty_htlc_transaction, - sign_closing_transaction: InMemorySigner_Sign_sign_closing_transaction, - sign_channel_announcement: InMemorySigner_Sign_sign_channel_announcement, - ready_channel: InMemorySigner_Sign_ready_channel, - clone: Some(InMemorySigner_clone_void), - write: InMemorySigner_write_void, + set_pubkeys: Some(InMemorySigner_BaseSign_set_pubkeys), + channel_keys_id: InMemorySigner_BaseSign_channel_keys_id, + sign_counterparty_commitment: InMemorySigner_BaseSign_sign_counterparty_commitment, + sign_holder_commitment_and_htlcs: InMemorySigner_BaseSign_sign_holder_commitment_and_htlcs, + sign_justice_transaction: InMemorySigner_BaseSign_sign_justice_transaction, + sign_counterparty_htlc_transaction: InMemorySigner_BaseSign_sign_counterparty_htlc_transaction, + sign_closing_transaction: InMemorySigner_BaseSign_sign_closing_transaction, + sign_channel_announcement: InMemorySigner_BaseSign_sign_channel_announcement, + ready_channel: InMemorySigner_BaseSign_ready_channel, } } #[must_use] -extern "C" fn InMemorySigner_Sign_get_per_commitment_point(this_arg: *const c_void, mut idx: u64) -> crate::c_types::PublicKey { - let mut ret = >::get_per_commitment_point(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, idx, secp256k1::SECP256K1); +extern "C" fn InMemorySigner_BaseSign_get_per_commitment_point(this_arg: *const c_void, mut idx: u64) -> crate::c_types::PublicKey { + let mut ret = >::get_per_commitment_point(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, idx, secp256k1::SECP256K1); crate::c_types::PublicKey::from_rust(&ret) } #[must_use] -extern "C" fn InMemorySigner_Sign_release_commitment_secret(this_arg: *const c_void, mut idx: u64) -> crate::c_types::ThirtyTwoBytes { - let mut ret = >::release_commitment_secret(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, idx); +extern "C" fn InMemorySigner_BaseSign_release_commitment_secret(this_arg: *const c_void, mut idx: u64) -> crate::c_types::ThirtyTwoBytes { + let mut ret = >::release_commitment_secret(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, idx); crate::c_types::ThirtyTwoBytes { data: ret } } #[must_use] -extern "C" fn InMemorySigner_Sign_pubkeys(this_arg: *const c_void) -> crate::ln::chan_utils::ChannelPublicKeys { - let mut ret = >::pubkeys(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, ); +extern "C" fn InMemorySigner_BaseSign_pubkeys(this_arg: *const c_void) -> crate::ln::chan_utils::ChannelPublicKeys { + let mut ret = >::pubkeys(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, ); crate::ln::chan_utils::ChannelPublicKeys { inner: unsafe { ( (&(*ret) as *const _) as *mut _) }, is_owned: false } } -extern "C" fn InMemorySigner_Sign_set_pubkeys(trait_self_arg: &Sign) { +extern "C" fn InMemorySigner_BaseSign_set_pubkeys(trait_self_arg: &BaseSign) { // 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 Sign as *mut Sign) }.pubkeys = InMemorySigner_Sign_pubkeys(trait_self_arg.this_arg); + unsafe { &mut *(trait_self_arg as *const BaseSign as *mut BaseSign) }.pubkeys = InMemorySigner_BaseSign_pubkeys(trait_self_arg.this_arg); } } #[must_use] -extern "C" fn InMemorySigner_Sign_channel_keys_id(this_arg: *const c_void) -> crate::c_types::ThirtyTwoBytes { - let mut ret = >::channel_keys_id(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, ); +extern "C" fn InMemorySigner_BaseSign_channel_keys_id(this_arg: *const c_void) -> crate::c_types::ThirtyTwoBytes { + let mut ret = >::channel_keys_id(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, ); crate::c_types::ThirtyTwoBytes { data: ret } } #[must_use] -extern "C" fn InMemorySigner_Sign_sign_counterparty_commitment(this_arg: *const c_void, commitment_tx: &crate::ln::chan_utils::CommitmentTransaction) -> crate::c_types::derived::CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ { - let mut ret = >::sign_counterparty_commitment(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*commitment_tx.inner }, secp256k1::SECP256K1); +extern "C" fn InMemorySigner_BaseSign_sign_counterparty_commitment(this_arg: *const c_void, commitment_tx: &crate::ln::chan_utils::CommitmentTransaction) -> crate::c_types::derived::CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ { + let mut ret = >::sign_counterparty_commitment(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*commitment_tx.inner }, secp256k1::SECP256K1); 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 mut 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 }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }).into() }; local_ret } #[must_use] -extern "C" fn InMemorySigner_Sign_sign_holder_commitment_and_htlcs(this_arg: *const c_void, commitment_tx: &crate::ln::chan_utils::HolderCommitmentTransaction) -> crate::c_types::derived::CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ { - let mut ret = >::sign_holder_commitment_and_htlcs(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*commitment_tx.inner }, secp256k1::SECP256K1); +extern "C" fn InMemorySigner_BaseSign_sign_holder_commitment_and_htlcs(this_arg: *const c_void, commitment_tx: &crate::ln::chan_utils::HolderCommitmentTransaction) -> crate::c_types::derived::CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ { + let mut ret = >::sign_holder_commitment_and_htlcs(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*commitment_tx.inner }, secp256k1::SECP256K1); 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 mut 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 }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }).into() }; local_ret } #[must_use] -extern "C" fn InMemorySigner_Sign_sign_justice_transaction(this_arg: *const c_void, mut 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 { +extern "C" fn InMemorySigner_BaseSign_sign_justice_transaction(this_arg: *const c_void, mut 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 = >::sign_justice_transaction(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, &justice_tx.into_bitcoin(), input, amount, &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *per_commitment_key}[..]).unwrap(), &local_htlc, secp256k1::SECP256K1); + let mut ret = >::sign_justice_transaction(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, &justice_tx.into_bitcoin(), input, amount, &::bitcoin::secp256k1::key::SecretKey::from_slice(&unsafe { *per_commitment_key}[..]).unwrap(), &local_htlc, secp256k1::SECP256K1); let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }).into() }; local_ret } #[must_use] -extern "C" fn InMemorySigner_Sign_sign_counterparty_htlc_transaction(this_arg: *const c_void, mut htlc_tx: crate::c_types::Transaction, mut input: usize, mut amount: u64, mut per_commitment_point: crate::c_types::PublicKey, htlc: &crate::ln::chan_utils::HTLCOutputInCommitment) -> crate::c_types::derived::CResult_SignatureNoneZ { - let mut ret = >::sign_counterparty_htlc_transaction(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, &htlc_tx.into_bitcoin(), input, amount, &per_commitment_point.into_rust(), unsafe { &*htlc.inner }, secp256k1::SECP256K1); +extern "C" fn InMemorySigner_BaseSign_sign_counterparty_htlc_transaction(this_arg: *const c_void, mut htlc_tx: crate::c_types::Transaction, mut input: usize, mut amount: u64, mut per_commitment_point: crate::c_types::PublicKey, htlc: &crate::ln::chan_utils::HTLCOutputInCommitment) -> crate::c_types::derived::CResult_SignatureNoneZ { + let mut ret = >::sign_counterparty_htlc_transaction(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, &htlc_tx.into_bitcoin(), input, amount, &per_commitment_point.into_rust(), unsafe { &*htlc.inner }, secp256k1::SECP256K1); let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }).into() }; local_ret } #[must_use] -extern "C" fn InMemorySigner_Sign_sign_closing_transaction(this_arg: *const c_void, mut closing_tx: crate::c_types::Transaction) -> crate::c_types::derived::CResult_SignatureNoneZ { - let mut ret = >::sign_closing_transaction(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, &closing_tx.into_bitcoin(), secp256k1::SECP256K1); +extern "C" fn InMemorySigner_BaseSign_sign_closing_transaction(this_arg: *const c_void, mut closing_tx: crate::c_types::Transaction) -> crate::c_types::derived::CResult_SignatureNoneZ { + let mut ret = >::sign_closing_transaction(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, &closing_tx.into_bitcoin(), secp256k1::SECP256K1); let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }).into() }; local_ret } #[must_use] -extern "C" fn InMemorySigner_Sign_sign_channel_announcement(this_arg: *const c_void, msg: &crate::ln::msgs::UnsignedChannelAnnouncement) -> crate::c_types::derived::CResult_SignatureNoneZ { - let mut ret = >::sign_channel_announcement(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*msg.inner }, secp256k1::SECP256K1); +extern "C" fn InMemorySigner_BaseSign_sign_channel_announcement(this_arg: *const c_void, msg: &crate::ln::msgs::UnsignedChannelAnnouncement) -> crate::c_types::derived::CResult_SignatureNoneZ { + let mut ret = >::sign_channel_announcement(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*msg.inner }, secp256k1::SECP256K1); let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::c_types::Signature::from_rust(&o) }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { 0u8 /*e*/ }).into() }; local_ret } -extern "C" fn InMemorySigner_Sign_ready_channel(this_arg: *mut c_void, channel_parameters: &crate::ln::chan_utils::ChannelTransactionParameters) { - >::ready_channel(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*channel_parameters.inner }) +extern "C" fn InMemorySigner_BaseSign_ready_channel(this_arg: *mut c_void, channel_parameters: &crate::ln::chan_utils::ChannelTransactionParameters) { + >::ready_channel(unsafe { &mut *(this_arg as *mut nativeInMemorySigner) }, unsafe { &*channel_parameters.inner }) +} + +impl From for crate::chain::keysinterface::Sign { + fn from(obj: nativeInMemorySigner) -> Self { + let mut rust_obj = InMemorySigner { inner: Box::into_raw(Box::new(obj)), is_owned: true }; + let mut ret = InMemorySigner_as_Sign(&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(InMemorySigner_free_void); + ret + } +} +/// Constructs a new Sign which calls the relevant methods on this_arg. +/// This copies the `inner` pointer in this_arg and thus the returned Sign must be freed before this_arg is +#[no_mangle] +pub extern "C" fn InMemorySigner_as_Sign(this_arg: &InMemorySigner) -> crate::chain::keysinterface::Sign { + crate::chain::keysinterface::Sign { + this_arg: unsafe { (*this_arg).inner as *mut c_void }, + free: None, + BaseSign: crate::chain::keysinterface::BaseSign { + this_arg: unsafe { (*this_arg).inner as *mut c_void }, + free: None, + get_per_commitment_point: InMemorySigner_BaseSign_get_per_commitment_point, + release_commitment_secret: InMemorySigner_BaseSign_release_commitment_secret, + + pubkeys: crate::ln::chan_utils::ChannelPublicKeys { inner: std::ptr::null_mut(), is_owned: true }, + set_pubkeys: Some(InMemorySigner_BaseSign_set_pubkeys), + channel_keys_id: InMemorySigner_BaseSign_channel_keys_id, + sign_counterparty_commitment: InMemorySigner_BaseSign_sign_counterparty_commitment, + sign_holder_commitment_and_htlcs: InMemorySigner_BaseSign_sign_holder_commitment_and_htlcs, + sign_justice_transaction: InMemorySigner_BaseSign_sign_justice_transaction, + sign_counterparty_htlc_transaction: InMemorySigner_BaseSign_sign_counterparty_htlc_transaction, + sign_closing_transaction: InMemorySigner_BaseSign_sign_closing_transaction, + sign_channel_announcement: InMemorySigner_BaseSign_sign_channel_announcement, + ready_channel: InMemorySigner_BaseSign_ready_channel, + }, + BaseSign_clone: InMemorySigner_BaseSign_clone, + write: InMemorySigner_write_void, + clone: Some(InMemorySigner_clone_void), + } +} + +extern "C" fn InMemorySigner_BaseSign_clone(orig: &crate::chain::keysinterface::BaseSign) -> crate::chain::keysinterface::BaseSign { + crate::chain::keysinterface::BaseSign { + this_arg: orig.this_arg, + free: None, + get_per_commitment_point: InMemorySigner_BaseSign_get_per_commitment_point, + release_commitment_secret: InMemorySigner_BaseSign_release_commitment_secret, + + pubkeys: crate::ln::chan_utils::ChannelPublicKeys { inner: std::ptr::null_mut(), is_owned: true }, + set_pubkeys: Some(InMemorySigner_BaseSign_set_pubkeys), + channel_keys_id: InMemorySigner_BaseSign_channel_keys_id, + sign_counterparty_commitment: InMemorySigner_BaseSign_sign_counterparty_commitment, + sign_holder_commitment_and_htlcs: InMemorySigner_BaseSign_sign_holder_commitment_and_htlcs, + sign_justice_transaction: InMemorySigner_BaseSign_sign_justice_transaction, + sign_counterparty_htlc_transaction: InMemorySigner_BaseSign_sign_counterparty_htlc_transaction, + sign_closing_transaction: InMemorySigner_BaseSign_sign_closing_transaction, + sign_channel_announcement: InMemorySigner_BaseSign_sign_channel_announcement, + ready_channel: InMemorySigner_BaseSign_ready_channel, + } } #[no_mangle] diff --git a/lightning-c-bindings/src/ln/channelmanager.rs b/lightning-c-bindings/src/ln/channelmanager.rs index 89a3b24..cad534b 100644 --- a/lightning-c-bindings/src/ln/channelmanager.rs +++ b/lightning-c-bindings/src/ln/channelmanager.rs @@ -597,10 +597,11 @@ pub extern "C" fn ChannelManager_new(mut fee_est: crate::chain::chaininterface:: /// 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. +/// user_id will be provided back as user_channel_id in FundingGenerationReady events to allow +/// tracking of which events correspond with which create_channel call. Note that the +/// user_channel_id defaults to 0 for inbound channels, so you may wish to avoid using 0 for +/// user_id here. user_id has no meaning inside of LDK, it is simply copied to events and +/// otherwise ignored. /// /// If successful, will generate a SendOpenChannel message event, so you should probably poll /// PeerManager::process_events afterwards. @@ -719,16 +720,28 @@ pub extern "C" fn ChannelManager_send_payment(this_arg: &ChannelManager, route: /// 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! +/// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs +/// or if no output was found which matches the parameters in [`Event::FundingGenerationReady`]. /// /// 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). +/// May panic if the output found in the funding transaction is duplicative with some other +/// channel (note that this should be trivially prevented by using unique funding transaction +/// keys per-channel). +/// +/// Do NOT broadcast the funding transaction yourself. When we have safely received our +/// counterparty's signature the funding transaction will automatically be broadcast via the +/// [`BroadcasterInterface`] provided when this `ChannelManager` was constructed. +/// +/// Note that this includes RBF or similar transaction replacement strategies - lightning does +/// not currently support replacing a funding transaction on an existing channel. Instead, +/// create a new channel with a conflicting funding transaction. +#[must_use] #[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_inner()) }) +pub extern "C" fn ChannelManager_funding_transaction_generated(this_arg: &ChannelManager, temporary_channel_id: *const [u8; 32], mut funding_transaction: crate::c_types::Transaction) -> crate::c_types::derived::CResult_NoneAPIErrorZ { + let mut ret = unsafe { &*this_arg.inner }.funding_transaction_generated(unsafe { &*temporary_channel_id}, funding_transaction.into_bitcoin()); + let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::util::errors::APIError::native_into(e) }).into() }; + local_ret } /// Generates a signed node_announcement from the given arguments and creates a @@ -921,24 +934,49 @@ pub extern "C" fn ChannelManager_as_Listen(this_arg: &ChannelManager) -> crate:: extern "C" fn ChannelManager_Listen_block_connected(this_arg: *const c_void, mut block: crate::c_types::u8slice, mut height: u32) { >::block_connected(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &::bitcoin::consensus::encode::deserialize(block.to_slice()).unwrap(), height) } -extern "C" fn ChannelManager_Listen_block_disconnected(this_arg: *const c_void, header: *const [u8; 80], mut _height: u32) { - >::block_disconnected(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), _height) +extern "C" fn ChannelManager_Listen_block_disconnected(this_arg: *const c_void, header: *const [u8; 80], mut height: u32) { + >::block_disconnected(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height) } -/// Updates channel state based on transactions seen in a connected block. +/// Updates channel state to take note of transactions which were confirmed in the given block +/// at the given height. +/// +/// Note that you must still call (or have called) [`update_best_block`] with the block +/// information which is included here. +/// +/// This method may be called before or after [`update_best_block`] for a given block's +/// transaction data and may be called multiple times with additional transaction data for a +/// given block. +/// +/// This method may be called for a previous block after an [`update_best_block`] call has +/// been made for a later block, however it must *not* be called with transaction data from a +/// block which is no longer in the best chain (ie where [`update_best_block`] has already +/// been informed about a blockchain reorganization which no longer includes the block which +/// corresponds to `header`). +/// +/// [`update_best_block`]: `Self::update_best_block` #[no_mangle] -pub extern "C" fn ChannelManager_block_connected(this_arg: &ChannelManager, header: *const [u8; 80], mut txdata: crate::c_types::derived::CVec_C2Tuple_usizeTransactionZZ, mut height: u32) { +pub extern "C" fn ChannelManager_transactions_confirmed(this_arg: &ChannelManager, header: *const [u8; 80], mut height: u32, mut txdata: crate::c_types::derived::CVec_C2Tuple_usizeTransactionZZ) { let mut local_txdata = Vec::new(); for mut item in txdata.into_rust().drain(..) { local_txdata.push( { let (mut orig_txdata_0_0, mut orig_txdata_0_1) = item.to_rust(); let mut local_txdata_0 = (orig_txdata_0_0, orig_txdata_0_1.into_bitcoin()); local_txdata_0 }); }; - unsafe { &*this_arg.inner }.block_connected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), &local_txdata.iter().map(|(a, b)| (*a, b)).collect::>()[..], height) + unsafe { &*this_arg.inner }.transactions_confirmed(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height, &local_txdata.iter().map(|(a, b)| (*a, b)).collect::>()[..]) } -/// Updates channel state based on a disconnected block. +/// Updates channel state with the current best blockchain tip. You should attempt to call this +/// quickly after a new block becomes available, however if multiple new blocks become +/// available at the same time, only a single `update_best_block()` call needs to be made. +/// +/// This method should also be called immediately after any block disconnections, once at the +/// reorganization fork point, and once with the new chain tip. Calling this method at the +/// blockchain reorganization fork point ensures we learn when a funding transaction which was +/// previously confirmed is reorganized out of the blockchain, ensuring we do not continue to +/// accept payments which cannot be enforced on-chain. /// -/// If necessary, the channel may be force-closed without letting the counterparty participate -/// in the shutdown. +/// In both the block-connection and block-disconnection case, this method may be called either +/// once per block connected or disconnected, or simply at the fork point and new tip(s), +/// skipping any intermediary blocks. #[no_mangle] -pub extern "C" fn ChannelManager_block_disconnected(this_arg: &ChannelManager, header: *const [u8; 80]) { - unsafe { &*this_arg.inner }.block_disconnected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap()) +pub extern "C" fn ChannelManager_update_best_block(this_arg: &ChannelManager, header: *const [u8; 80], mut height: u32) { + unsafe { &*this_arg.inner }.update_best_block(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height) } /// Blocks until ChannelManager needs to be persisted or a timeout is reached. It returns a bool @@ -1001,7 +1039,7 @@ pub extern "C" fn ChannelManager_as_ChannelMessageHandler(this_arg: &ChannelMana 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, + get_and_clear_pending_msg_events: ChannelManager_MessageSendEventsProvider_get_and_clear_pending_msg_events, }, } } @@ -1066,12 +1104,6 @@ extern "C" fn ChannelManager_ChannelMessageHandler_peer_connected(this_arg: *con extern "C" fn ChannelManager_ChannelMessageHandler_handle_error(this_arg: *const c_void, mut counterparty_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ErrorMessage) { >::handle_error(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, &counterparty_node_id.into_rust(), unsafe { &*msg.inner }) } -#[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 = >::get_and_clear_pending_msg_events(unsafe { &mut *(this_arg as *mut nativeChannelManager) }, ); - let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); }; - local_ret.into() -} #[no_mangle] /// Serialize the ChannelManager object into a byte array which can be read by ChannelManager_read diff --git a/lightning-c-bindings/src/ln/msgs.rs b/lightning-c-bindings/src/ln/msgs.rs index 5f32cac..67d2f0b 100644 --- a/lightning-c-bindings/src/ln/msgs.rs +++ b/lightning-c-bindings/src/ln/msgs.rs @@ -4512,7 +4512,7 @@ pub struct ChannelMessageHandler { pub handle_channel_update: extern "C" fn (this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ChannelUpdate), /// Handle an incoming error message from the given peer. pub handle_error: extern "C" fn (this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: &crate::ln::msgs::ErrorMessage), -/// Implementation of MessageSendEventsProvider for this object. + /// Implementation of MessageSendEventsProvider for this object. pub MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider, /// Frees any resources associated with this object given its this_arg pointer. /// Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed. @@ -4520,7 +4520,9 @@ pub struct ChannelMessageHandler { } impl lightning::util::events::MessageSendEventsProvider for ChannelMessageHandler { fn get_and_clear_pending_msg_events(&self) -> Vec { - ::get_and_clear_pending_msg_events(&self.MessageSendEventsProvider) + let mut ret = (self.MessageSendEventsProvider.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 } } unsafe impl Send for ChannelMessageHandler {} @@ -4668,7 +4670,7 @@ pub struct RoutingMessageHandler { /// list of short_channel_ids. #[must_use] pub handle_query_short_channel_ids: extern "C" fn (this_arg: *const c_void, their_node_id: crate::c_types::PublicKey, msg: crate::ln::msgs::QueryShortChannelIds) -> crate::c_types::derived::CResult_NoneLightningErrorZ, -/// Implementation of MessageSendEventsProvider for this object. + /// Implementation of MessageSendEventsProvider for this object. pub MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider, /// Frees any resources associated with this object given its this_arg pointer. /// Does not need to free the outer struct containing function pointers and may be NULL is no resources need to be freed. @@ -4678,7 +4680,9 @@ unsafe impl Send for RoutingMessageHandler {} unsafe impl Sync for RoutingMessageHandler {} impl lightning::util::events::MessageSendEventsProvider for RoutingMessageHandler { fn get_and_clear_pending_msg_events(&self) -> Vec { - ::get_and_clear_pending_msg_events(&self.MessageSendEventsProvider) + let mut ret = (self.MessageSendEventsProvider.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 } } diff --git a/lightning-c-bindings/src/ln/peer_handler.rs b/lightning-c-bindings/src/ln/peer_handler.rs index 9f3f840..07368ae 100644 --- a/lightning-c-bindings/src/ln/peer_handler.rs +++ b/lightning-c-bindings/src/ln/peer_handler.rs @@ -130,7 +130,7 @@ pub extern "C" fn IgnoringMessageHandler_as_RoutingMessageHandler(this_arg: &Ign MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider { this_arg: unsafe { (*this_arg).inner as *mut c_void }, free: None, - get_and_clear_pending_msg_events: IgnoringMessageHandler_RoutingMessageHandler_get_and_clear_pending_msg_events, + get_and_clear_pending_msg_events: IgnoringMessageHandler_MessageSendEventsProvider_get_and_clear_pending_msg_events, }, } } @@ -196,12 +196,6 @@ extern "C" fn IgnoringMessageHandler_RoutingMessageHandler_handle_query_short_ch let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::msgs::LightningError { inner: Box::into_raw(Box::new(e)), is_owned: true } }).into() }; local_ret } -#[must_use] -extern "C" fn IgnoringMessageHandler_RoutingMessageHandler_get_and_clear_pending_msg_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ { - let mut ret = >::get_and_clear_pending_msg_events(unsafe { &mut *(this_arg as *mut nativeIgnoringMessageHandler) }, ); - let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); }; - local_ret.into() -} use lightning::ln::peer_handler::ErroringMessageHandler as nativeErroringMessageHandlerImport; @@ -325,7 +319,7 @@ pub extern "C" fn ErroringMessageHandler_as_ChannelMessageHandler(this_arg: &Err MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider { this_arg: unsafe { (*this_arg).inner as *mut c_void }, free: None, - get_and_clear_pending_msg_events: ErroringMessageHandler_ChannelMessageHandler_get_and_clear_pending_msg_events, + get_and_clear_pending_msg_events: ErroringMessageHandler_MessageSendEventsProvider_get_and_clear_pending_msg_events, }, } } @@ -390,12 +384,6 @@ extern "C" fn ErroringMessageHandler_ChannelMessageHandler_peer_connected(this_a extern "C" fn ErroringMessageHandler_ChannelMessageHandler_handle_error(this_arg: *const c_void, mut _their_node_id: crate::c_types::PublicKey, _msg: &crate::ln::msgs::ErrorMessage) { >::handle_error(unsafe { &mut *(this_arg as *mut nativeErroringMessageHandler) }, &_their_node_id.into_rust(), unsafe { &*_msg.inner }) } -#[must_use] -extern "C" fn ErroringMessageHandler_ChannelMessageHandler_get_and_clear_pending_msg_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ { - let mut ret = >::get_and_clear_pending_msg_events(unsafe { &mut *(this_arg as *mut nativeErroringMessageHandler) }, ); - let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); }; - local_ret.into() -} use lightning::ln::peer_handler::MessageHandler as nativeMessageHandlerImport; @@ -540,12 +528,12 @@ impl std::hash::Hash for SocketDescriptor { pub extern "C" fn SocketDescriptor_clone(orig: &SocketDescriptor) -> SocketDescriptor { SocketDescriptor { this_arg: if let Some(f) = orig.clone { (f)(orig.this_arg) } else { orig.this_arg }, - send_data: orig.send_data.clone(), - disconnect_socket: orig.disconnect_socket.clone(), - eq: orig.eq.clone(), - hash: orig.hash.clone(), - clone: orig.clone.clone(), - free: orig.free.clone(), + send_data: Clone::clone(&orig.send_data), + disconnect_socket: Clone::clone(&orig.disconnect_socket), + eq: Clone::clone(&orig.eq), + hash: Clone::clone(&orig.hash), + clone: Clone::clone(&orig.clone), + free: Clone::clone(&orig.free), } } impl Clone for SocketDescriptor { diff --git a/lightning-c-bindings/src/routing/network_graph.rs b/lightning-c-bindings/src/routing/network_graph.rs index 7947ac6..b1421b8 100644 --- a/lightning-c-bindings/src/routing/network_graph.rs +++ b/lightning-c-bindings/src/routing/network_graph.rs @@ -254,7 +254,7 @@ pub extern "C" fn NetGraphMsgHandler_as_RoutingMessageHandler(this_arg: &NetGrap MessageSendEventsProvider: crate::util::events::MessageSendEventsProvider { this_arg: unsafe { (*this_arg).inner as *mut c_void }, free: None, - get_and_clear_pending_msg_events: NetGraphMsgHandler_RoutingMessageHandler_get_and_clear_pending_msg_events, + get_and_clear_pending_msg_events: NetGraphMsgHandler_MessageSendEventsProvider_get_and_clear_pending_msg_events, }, } } @@ -320,12 +320,6 @@ extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_handle_query_short_channe let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::ln::msgs::LightningError { inner: Box::into_raw(Box::new(e)), is_owned: true } }).into() }; local_ret } -#[must_use] -extern "C" fn NetGraphMsgHandler_RoutingMessageHandler_get_and_clear_pending_msg_events(this_arg: *const c_void) -> crate::c_types::derived::CVec_MessageSendEventZ { - let mut ret = >::get_and_clear_pending_msg_events(unsafe { &mut *(this_arg as *mut nativeNetGraphMsgHandler) }, ); - let mut local_ret = Vec::new(); for mut item in ret.drain(..) { local_ret.push( { crate::util::events::MessageSendEvent::native_into(item) }); }; - local_ret.into() -} impl From for crate::util::events::MessageSendEventsProvider { fn from(obj: nativeNetGraphMsgHandler) -> Self { diff --git a/lightning-c-bindings/src/util/events.rs b/lightning-c-bindings/src/util/events.rs index 72d9de5..295878e 100644 --- a/lightning-c-bindings/src/util/events.rs +++ b/lightning-c-bindings/src/util/events.rs @@ -42,16 +42,6 @@ pub enum Event { /// The value passed in to ChannelManager::create_channel 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 { - /// The output, which was passed to ChannelManager::funding_transaction_generated, which is - /// now safe to broadcast. - funding_txo: crate::chain::transaction::OutPoint, - /// The value passed in to ChannelManager::create_channel - 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 @@ -137,14 +127,6 @@ impl Event { 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_inner()) }, - 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(); @@ -196,12 +178,6 @@ impl Event { 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_inner()) }, - 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 { @@ -249,14 +225,6 @@ impl Event { 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(); @@ -308,12 +276,6 @@ impl Event { 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 {