From: Matt Corallo <649246+TheBlueMatt@users.noreply.github.com> Date: Tue, 24 Nov 2020 16:36:14 +0000 (-0800) Subject: Merge pull request #748 from TheBlueMatt/2020-11-router-fuzzer X-Git-Tag: v0.0.12~2 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=fc7df54f8dc3baf710371e2ad2beb862946d5b1c;hp=b56b4add6ae0625271a66a8a1a48058c7f542352;p=rust-lightning Merge pull request #748 from TheBlueMatt/2020-11-router-fuzzer Make router_target a bit easier for fuzzers to explore and fix two found bugs --- diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index ecbd947b..4193f6d3 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -148,6 +148,9 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty } writeln_docs(w, &t.attrs, ""); + let mut gen_types = GenericTypes::new(); + assert!(gen_types.learn_generics(&t.generics, types)); + writeln!(w, "#[repr(C)]\npub struct {} {{", trait_name).unwrap(); writeln!(w, "\tpub this_arg: *mut c_void,").unwrap(); let associated_types = learn_associated_types(t); @@ -158,15 +161,17 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty match export_status(&m.attrs) { ExportStatus::NoExport => { // NoExport in this context means we'll hit an unimplemented!() at runtime, - // so add a comment noting that this needs to change in the output. - writeln!(w, "\t//XXX: Need to export {}", m.sig.ident).unwrap(); - continue; + // so bail out. + unimplemented!(); }, ExportStatus::Export => {}, ExportStatus::TestOnly => continue, } if m.default.is_some() { unimplemented!(); } + gen_types.push_ctx(); + assert!(gen_types.learn_generics(&m.sig.generics, types)); + writeln_docs(w, &m.attrs, "\t"); if let syn::ReturnType::Type(_, rtype) = &m.sig.output { @@ -183,7 +188,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty // 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, None, false); + types.write_c_type(w, &*r.elem, Some(&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(); @@ -195,6 +200,7 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty // 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 @@ -204,8 +210,10 @@ 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, &associated_types, "c_void", types, None, true, false); + write_method_params(w, &m.sig, &associated_types, "c_void", types, Some(&gen_types), true, false); writeln!(w, ",").unwrap(); + + gen_types.pop_ctx(); }, &syn::TraitItem::Type(_) => {}, _ => unimplemented!(), @@ -218,7 +226,8 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty generated_fields.push("clone".to_owned()); }, ("std::cmp::Eq", _) => { - writeln!(w, "\tpub eq: extern \"C\" fn (this_arg: *const c_void, other_arg: *const c_void) -> bool,").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()); }, ("std::hash::Hash", _) => { @@ -243,21 +252,25 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty ("std::cmp::Eq", _) => { writeln!(w, "impl std::cmp::Eq for {} {{}}", trait_name).unwrap(); writeln!(w, "impl std::cmp::PartialEq for {} {{", trait_name).unwrap(); - writeln!(w, "\tfn eq(&self, o: &Self) -> bool {{ (self.eq)(self.this_arg, o.this_arg) }}\n}}").unwrap(); + writeln!(w, "\tfn eq(&self, o: &Self) -> bool {{ (self.eq)(self.this_arg, o) }}\n}}").unwrap(); }, ("std::hash::Hash", _) => { writeln!(w, "impl std::hash::Hash for {} {{", trait_name).unwrap(); writeln!(w, "\tfn hash(&self, hasher: &mut H) {{ hasher.write_u64((self.hash)(self.this_arg)) }}\n}}").unwrap(); }, ("Clone", _) => { - writeln!(w, "impl Clone for {} {{", trait_name).unwrap(); - writeln!(w, "\tfn clone(&self) -> Self {{").unwrap(); - writeln!(w, "\t\tSelf {{").unwrap(); - writeln!(w, "\t\tthis_arg: if let Some(f) = self.clone {{ (f)(self.this_arg) }} else {{ self.this_arg }},").unwrap(); + writeln!(w, "#[no_mangle]").unwrap(); + 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\t{}: self.{}.clone(),", field, field).unwrap(); + writeln!(w, "\t\t{}: orig.{}.clone(),", field, field).unwrap(); } - writeln!(w, "\t\t}}\n\t}}\n}}").unwrap(); + writeln!(w, "\t}}\n}}").unwrap(); + writeln!(w, "impl Clone for {} {{", trait_name).unwrap(); + writeln!(w, "\tfn clone(&self) -> Self {{").unwrap(); + writeln!(w, "\t\t{}_clone(self)", trait_name).unwrap(); + writeln!(w, "\t}}\n}}").unwrap(); }, (s, i) => { if s != "util::events::MessageSendEventsProvider" { unimplemented!(); } @@ -284,8 +297,10 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty 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, m.sig.generics.params.iter()); + 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 { @@ -309,11 +324,11 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty ident.mutability.is_some() || ident.subpat.is_some() { unimplemented!(); } - write!(w, ", {}{}: ", if types.skip_arg(&*arg.ty, None) { "_" } else { "" }, ident.ident).unwrap(); + write!(w, ", {}{}: ", if types.skip_arg(&*arg.ty, Some(&gen_types)) { "_" } else { "" }, ident.ident).unwrap(); } _ => unimplemented!(), } - types.write_rust_type(w, &*arg.ty); + types.write_rust_type(w, Some(&gen_types), &*arg.ty); } } } @@ -321,15 +336,14 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty match &m.sig.output { syn::ReturnType::Type(_, rtype) => { write!(w, " -> ").unwrap(); - types.write_rust_type(w, &*rtype) + types.write_rust_type(w, Some(&gen_types), &*rtype) }, _ => {}, } write!(w, " {{\n\t\t").unwrap(); match export_status(&m.attrs) { ExportStatus::NoExport => { - writeln!(w, "unimplemented!();\n\t}}").unwrap(); - continue; + unimplemented!(); }, _ => {}, } @@ -339,25 +353,27 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty 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, None); + 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, None); + 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, None, true); + 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, &associated_types, "\t", types, None, "", true); + write_method_call_params(w, &m.sig, &associated_types, "\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, None)).unwrap(); + writeln!(w, "\ttype {} = crate::{};", t.ident, types.resolve_path(&tr.path, Some(&gen_types))).unwrap(); }, _ => unimplemented!(), } @@ -439,6 +455,10 @@ fn writeln_opaque(w: &mut W, ident: &syn::Ident, struct_name: writeln!(w, "pub(crate) extern \"C\" fn {}_clone_void(this_ptr: *const c_void) -> *mut c_void {{", struct_name).unwrap(); writeln!(w, "\tBox::into_raw(Box::new(unsafe {{ (*(this_ptr as *mut native{})).clone() }})) as *mut c_void", struct_name).unwrap(); writeln!(w, "}}").unwrap(); + writeln!(w, "#[no_mangle]").unwrap(); + writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", struct_name, struct_name, struct_name).unwrap(); + writeln!(w, "\t{} {{ inner: Box::into_raw(Box::new(unsafe {{ &*orig.inner }}.clone())), is_owned: true }}", struct_name).unwrap(); + writeln!(w, "}}").unwrap(); break 'attr_loop; } } @@ -980,6 +1000,10 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type if needs_free { writeln!(w, "#[no_mangle]\npub extern \"C\" fn {}_free(this_ptr: {}) {{ }}", e.ident, e.ident).unwrap(); } + writeln!(w, "#[no_mangle]").unwrap(); + writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", e.ident, e.ident, e.ident).unwrap(); + writeln!(w, "\torig.clone()").unwrap(); + writeln!(w, "}}").unwrap(); write_cpp_wrapper(cpp_headers, &format!("{}", e.ident), needs_free); } diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 3fc35e8b..483c1d9b 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -932,19 +932,34 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { // *** Original Rust Type Printing *** // *********************************** - fn write_rust_path(&self, w: &mut W, path: &syn::Path) { - if let Some(resolved) = self.maybe_resolve_path(&path, None) { + fn in_rust_prelude(resolved_path: &str) -> bool { + match resolved_path { + "Vec" => true, + "Result" => true, + "Option" => true, + _ => false, + } + } + + fn write_rust_path(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, path: &syn::Path) { + if let Some(resolved) = self.maybe_resolve_path(&path, generics_resolver) { if self.is_primitive(&resolved) { write!(w, "{}", path.get_ident().unwrap()).unwrap(); } else { - if resolved.starts_with("ln::") || resolved.starts_with("chain::") || resolved.starts_with("util::") { - write!(w, "lightning::{}", resolved).unwrap(); + // TODO: We should have a generic "is from a dependency" check here instead of + // checking for "bitcoin" explicitly. + if resolved.starts_with("bitcoin::") || Self::in_rust_prelude(&resolved) { + write!(w, "{}", resolved).unwrap(); + // If we're printing a generic argument, it needs to reference the crate, otherwise + // the original crate: + } else if self.maybe_resolve_path(&path, None).as_ref() == Some(&resolved) { + write!(w, "{}::{}", self.orig_crate, resolved).unwrap(); } else { - write!(w, "{}", resolved).unwrap(); // XXX: Probably doens't work, get_ident().unwrap() + write!(w, "crate::{}", resolved).unwrap(); } } if let syn::PathArguments::AngleBracketed(args) = &path.segments.iter().last().unwrap().arguments { - self.write_rust_generic_arg(w, args.args.iter()); + self.write_rust_generic_arg(w, generics_resolver, args.args.iter()); } } else { if path.leading_colon.is_some() { @@ -954,12 +969,12 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if idx != 0 { write!(w, "::").unwrap(); } write!(w, "{}", seg.ident).unwrap(); if let syn::PathArguments::AngleBracketed(args) = &seg.arguments { - self.write_rust_generic_arg(w, args.args.iter()); + self.write_rust_generic_arg(w, generics_resolver, args.args.iter()); } } } } - pub fn write_rust_generic_param<'b, W: std::io::Write>(&self, w: &mut W, generics: impl Iterator) { + pub fn write_rust_generic_param<'b, W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, generics: impl Iterator) { let mut had_params = false; for (idx, arg) in generics.enumerate() { if idx != 0 { write!(w, ", ").unwrap(); } else { write!(w, "<").unwrap(); } @@ -974,7 +989,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { match bound { syn::TypeParamBound::Trait(tb) => { if tb.paren_token.is_some() || tb.lifetimes.is_some() { unimplemented!(); } - self.write_rust_path(w, &tb.path); + self.write_rust_path(w, generics_resolver, &tb.path); }, _ => unimplemented!(), } @@ -987,24 +1002,24 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if had_params { write!(w, ">").unwrap(); } } - pub fn write_rust_generic_arg<'b, W: std::io::Write>(&self, w: &mut W, generics: impl Iterator) { + pub fn write_rust_generic_arg<'b, W: std::io::Write>(&self, w: &mut W, generics_resolver: Option<&GenericTypes>, generics: impl Iterator) { write!(w, "<").unwrap(); for (idx, arg) in generics.enumerate() { if idx != 0 { write!(w, ", ").unwrap(); } match arg { - syn::GenericArgument::Type(t) => self.write_rust_type(w, t), + syn::GenericArgument::Type(t) => self.write_rust_type(w, generics_resolver, t), _ => unimplemented!(), } } write!(w, ">").unwrap(); } - pub fn write_rust_type(&self, w: &mut W, t: &syn::Type) { + pub fn write_rust_type(&self, w: &mut W, generics: Option<&GenericTypes>, t: &syn::Type) { match t { syn::Type::Path(p) => { if p.qself.is_some() || p.path.leading_colon.is_some() { unimplemented!(); } - self.write_rust_path(w, &p.path); + self.write_rust_path(w, generics, &p.path); }, syn::Type::Reference(r) => { write!(w, "&").unwrap(); @@ -1014,11 +1029,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if r.mutability.is_some() { write!(w, "mut ").unwrap(); } - self.write_rust_type(w, &*r.elem); + self.write_rust_type(w, generics, &*r.elem); }, syn::Type::Array(a) => { write!(w, "[").unwrap(); - self.write_rust_type(w, &a.elem); + self.write_rust_type(w, generics, &a.elem); if let syn::Expr::Lit(l) = &a.len { if let syn::Lit::Int(i) = &l.lit { write!(w, "; {}]", i).unwrap(); @@ -1027,14 +1042,14 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } syn::Type::Slice(s) => { write!(w, "[").unwrap(); - self.write_rust_type(w, &s.elem); + self.write_rust_type(w, generics, &s.elem); write!(w, "]").unwrap(); }, syn::Type::Tuple(s) => { write!(w, "(").unwrap(); for (idx, t) in s.elems.iter().enumerate() { if idx != 0 { write!(w, ", ").unwrap(); } - self.write_rust_type(w, &t); + self.write_rust_type(w, generics, &t); } write!(w, ")").unwrap(); }, @@ -1743,7 +1758,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { } else if in_crate { write!(w, "{}", c_type).unwrap(); } else { - self.write_rust_type(w, &t); + self.write_rust_type(w, None, &t); } } else { // If we just write out resolved_generic, it may mostly work, however for diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index d88cc71f..377ac8d7 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -35,10 +35,11 @@ use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, use lightning::chain::transaction::OutPoint; use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator}; use lightning::chain::keysinterface::{KeysInterface, InMemoryChannelKeys}; -use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, ChannelManagerReadArgs}; +use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret, PaymentSendFailure, ChannelManagerReadArgs}; use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC, Init}; use lightning::util::enforcing_trait_impls::EnforcingChannelKeys; +use lightning::util::errors::APIError; use lightning::util::events; use lightning::util::logger::Logger; use lightning::util::config::UserConfig; @@ -128,7 +129,7 @@ impl chain::Watch for TestChainMonitor { }; let mut deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>:: read(&mut Cursor::new(&map_entry.get().1)).unwrap().1; - deserialized_monitor.update_monitor(&update, &&TestBroadcaster {}, &self.logger).unwrap(); + deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &&FuzzEstimator{}, &self.logger).unwrap(); let mut ser = VecWriter(Vec::new()); deserialized_monitor.serialize_for_disk(&mut ser).unwrap(); map_entry.insert((update.update_id, ser.0)); @@ -185,6 +186,93 @@ impl KeysInterface for KeyProvider { } } +#[inline] +fn check_api_err(api_err: APIError) { + match api_err { + APIError::APIMisuseError { .. } => panic!("We can't misuse the API"), + APIError::FeeRateTooHigh { .. } => panic!("We can't send too much fee?"), + APIError::RouteError { .. } => panic!("Our routes should work"), + APIError::ChannelUnavailable { err } => { + // Test the error against a list of errors we can hit, and reject + // all others. If you hit this panic, the list of acceptable errors + // is probably just stale and you should add new messages here. + match err.as_str() { + "Peer for first hop currently disconnected/pending monitor update!" => {}, + _ if err.starts_with("Cannot push more than their max accepted HTLCs ") => {}, + _ if err.starts_with("Cannot send value that would put us over the max HTLC value in flight our peer will accept ") => {}, + _ if err.starts_with("Cannot send value that would put our balance under counterparty-announced channel reserve value") => {}, + _ if err.starts_with("Cannot send value that would overdraw remaining funds.") => {}, + _ if err.starts_with("Cannot send value that would not leave enough to pay for fees.") => {}, + _ => panic!(err), + } + }, + APIError::MonitorUpdateFailed => { + // We can (obviously) temp-fail a monitor update + }, + } +} +#[inline] +fn check_payment_err(send_err: PaymentSendFailure) { + match send_err { + PaymentSendFailure::ParameterError(api_err) => check_api_err(api_err), + PaymentSendFailure::PathParameterError(per_path_results) => { + for res in per_path_results { if let Err(api_err) = res { check_api_err(api_err); } } + }, + PaymentSendFailure::AllFailedRetrySafe(per_path_results) => { + for api_err in per_path_results { check_api_err(api_err); } + }, + PaymentSendFailure::PartialFailure(per_path_results) => { + for res in per_path_results { if let Err(api_err) = res { check_api_err(api_err); } } + }, + } +} + +type ChanMan = ChannelManager, Arc, Arc, Arc, Arc>; + +#[inline] +fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, payment_id: &mut u8) -> bool { + let payment_hash = Sha256::hash(&[*payment_id; 1]); + *payment_id = payment_id.wrapping_add(1); + if let Err(err) = source.send_payment(&Route { + paths: vec![vec![RouteHop { + pubkey: dest.get_our_node_id(), + node_features: NodeFeatures::empty(), + short_channel_id: dest_chan_id, + channel_features: ChannelFeatures::empty(), + fee_msat: amt, + cltv_expiry_delta: 200, + }]], + }, PaymentHash(payment_hash.into_inner()), &None) { + check_payment_err(err); + false + } else { true } +} +#[inline] +fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, dest: &ChanMan, dest_chan_id: u64, amt: u64, payment_id: &mut u8) -> bool { + let payment_hash = Sha256::hash(&[*payment_id; 1]); + *payment_id = payment_id.wrapping_add(1); + if let Err(err) = source.send_payment(&Route { + paths: vec![vec![RouteHop { + pubkey: middle.get_our_node_id(), + node_features: NodeFeatures::empty(), + short_channel_id: middle_chan_id, + channel_features: ChannelFeatures::empty(), + fee_msat: 50000, + cltv_expiry_delta: 100, + },RouteHop { + pubkey: dest.get_our_node_id(), + node_features: NodeFeatures::empty(), + short_channel_id: dest_chan_id, + channel_features: ChannelFeatures::empty(), + fee_msat: amt, + cltv_expiry_delta: 200, + }]], + }, PaymentHash(payment_hash.into_inner()), &None) { + check_payment_err(err); + false + } else { true } +} + #[inline] pub fn do_test(data: &[u8], out: Out) { let fee_est = Arc::new(FuzzEstimator{}); @@ -200,7 +288,7 @@ pub fn do_test(data: &[u8], out: Out) { config.channel_options.fee_proportional_millionths = 0; config.channel_options.announced_channel = true; config.peer_channel_config_limits.min_dust_limit_satoshis = 0; - (Arc::new(ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0)), + (ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config, 0), monitor) } } } @@ -237,14 +325,14 @@ pub fn do_test(data: &[u8], out: Out) { channel_monitors: monitor_refs, }; - (<(BlockHash, ChannelManager, Arc, Arc, Arc, Arc>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, chain_monitor) + (<(BlockHash, ChanMan)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, chain_monitor) } } } let mut channel_txn = Vec::new(); macro_rules! make_channel { ($source: expr, $dest: expr, $chan_id: expr) => { { - $source.create_channel($dest.get_our_node_id(), 10000000, 42, 0, None).unwrap(); + $source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None).unwrap(); let open_channel = { let events = $source.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -347,9 +435,9 @@ pub fn do_test(data: &[u8], out: Out) { // 3 nodes is enough to hit all the possible cases, notably unknown-source-unknown-dest // forwarding. - let (mut node_a, mut monitor_a) = make_node!(0); - let (mut node_b, mut monitor_b) = make_node!(1); - let (mut node_c, mut monitor_c) = make_node!(2); + let (node_a, mut monitor_a) = make_node!(0); + let (node_b, mut monitor_b) = make_node!(1); + let (node_c, mut monitor_c) = make_node!(2); let mut nodes = [node_a, node_b, node_c]; @@ -365,7 +453,7 @@ pub fn do_test(data: &[u8], out: Out) { let chan_a = nodes[0].list_usable_channels()[0].short_channel_id.unwrap(); let chan_b = nodes[2].list_usable_channels()[0].short_channel_id.unwrap(); - let mut payment_id = 0; + let mut payment_id: u8 = 0; let mut chan_a_disconnected = false; let mut chan_b_disconnected = false; @@ -403,88 +491,44 @@ pub fn do_test(data: &[u8], out: Out) { } loop { - macro_rules! send_payment { - ($source: expr, $dest: expr, $amt: expr) => { { - let payment_hash = Sha256::hash(&[payment_id; 1]); - payment_id = payment_id.wrapping_add(1); - if let Err(_) = $source.send_payment(&Route { - paths: vec![vec![RouteHop { - pubkey: $dest.0.get_our_node_id(), - node_features: NodeFeatures::empty(), - short_channel_id: $dest.1, - channel_features: ChannelFeatures::empty(), - fee_msat: $amt, - cltv_expiry_delta: 200, - }]], - }, PaymentHash(payment_hash.into_inner()), &None) { - // Probably ran out of funds - test_return!(); - } - } }; - ($source: expr, $middle: expr, $dest: expr, $amt: expr) => { { - let payment_hash = Sha256::hash(&[payment_id; 1]); - payment_id = payment_id.wrapping_add(1); - if let Err(_) = $source.send_payment(&Route { - paths: vec![vec![RouteHop { - pubkey: $middle.0.get_our_node_id(), - node_features: NodeFeatures::empty(), - short_channel_id: $middle.1, - channel_features: ChannelFeatures::empty(), - fee_msat: 50000, - cltv_expiry_delta: 100, - },RouteHop { - pubkey: $dest.0.get_our_node_id(), - node_features: NodeFeatures::empty(), - short_channel_id: $dest.1, - channel_features: ChannelFeatures::empty(), - fee_msat: $amt, - cltv_expiry_delta: 200, - }]], - }, PaymentHash(payment_hash.into_inner()), &None) { - // Probably ran out of funds - test_return!(); - } - } } - } macro_rules! send_payment_with_secret { ($source: expr, $middle: expr, $dest: expr) => { { let payment_hash = Sha256::hash(&[payment_id; 1]); payment_id = payment_id.wrapping_add(1); let payment_secret = Sha256::hash(&[payment_id; 1]); payment_id = payment_id.wrapping_add(1); - if let Err(_) = $source.send_payment(&Route { + if let Err(err) = $source.send_payment(&Route { paths: vec![vec![RouteHop { pubkey: $middle.0.get_our_node_id(), node_features: NodeFeatures::empty(), short_channel_id: $middle.1, channel_features: ChannelFeatures::empty(), - fee_msat: 50000, + fee_msat: 50_000, cltv_expiry_delta: 100, },RouteHop { pubkey: $dest.0.get_our_node_id(), node_features: NodeFeatures::empty(), short_channel_id: $dest.1, channel_features: ChannelFeatures::empty(), - fee_msat: 5000000, + fee_msat: 10_000_000, cltv_expiry_delta: 200, }],vec![RouteHop { pubkey: $middle.0.get_our_node_id(), node_features: NodeFeatures::empty(), short_channel_id: $middle.1, channel_features: ChannelFeatures::empty(), - fee_msat: 50000, + fee_msat: 50_000, cltv_expiry_delta: 100, },RouteHop { pubkey: $dest.0.get_our_node_id(), node_features: NodeFeatures::empty(), short_channel_id: $dest.1, channel_features: ChannelFeatures::empty(), - fee_msat: 5000000, + fee_msat: 10_000_000, cltv_expiry_delta: 200, }]], }, PaymentHash(payment_hash.into_inner()), &Some(PaymentSecret(payment_secret.into_inner()))) { - // Probably ran out of funds - test_return!(); + check_payment_err(err); } } } } @@ -498,7 +542,9 @@ pub fn do_test(data: &[u8], out: Out) { bc_events.clear(); new_events } else { Vec::new() }; + let mut had_events = false; for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) { + had_events = true; match event { events::MessageSendEvent::UpdateHTLCs { ref node_id, updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => { for dest in nodes.iter() { @@ -552,13 +598,10 @@ pub fn do_test(data: &[u8], out: Out) { // Can be generated due to a payment forward being rejected due to a // channel having previously failed a monitor update }, - events::MessageSendEvent::HandleError { action: ErrorAction::IgnoreError, .. } => { - // Can be generated at any processing step to send back an error, disconnect - // peer or just ignore - }, _ => panic!("Unhandled message event"), } } + had_events } } } @@ -638,6 +681,7 @@ pub fn do_test(data: &[u8], out: Out) { } else { Ordering::Equal } } else { Ordering::Equal } }); + let had_events = !events.is_empty(); for event in events.drain(..) { match event { events::Event::PaymentReceived { payment_hash, payment_secret, amt } => { @@ -657,43 +701,44 @@ pub fn do_test(data: &[u8], out: Out) { _ => panic!("Unhandled event"), } } + had_events } } } match get_slice!(1)[0] { + // In general, we keep related message groups close together in binary form, allowing + // bit-twiddling mutations to have similar effects. This is probably overkill, but no + // harm in doing so. + 0x00 => *monitor_a.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), 0x01 => *monitor_b.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), 0x02 => *monitor_c.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure), - 0x03 => *monitor_a.update_ret.lock().unwrap() = Ok(()), - 0x04 => *monitor_b.update_ret.lock().unwrap() = Ok(()), - 0x05 => *monitor_c.update_ret.lock().unwrap() = Ok(()), - 0x06 => { + 0x04 => *monitor_a.update_ret.lock().unwrap() = Ok(()), + 0x05 => *monitor_b.update_ret.lock().unwrap() = Ok(()), + 0x06 => *monitor_c.update_ret.lock().unwrap() = Ok(()), + + 0x08 => { if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) { nodes[0].channel_monitor_updated(&chan_1_funding, *id); } }, - 0x07 => { + 0x09 => { if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_1_funding) { nodes[1].channel_monitor_updated(&chan_1_funding, *id); } }, - 0x24 => { + 0x0a => { if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_2_funding) { nodes[1].channel_monitor_updated(&chan_2_funding, *id); } }, - 0x08 => { + 0x0b => { if let Some((id, _)) = monitor_c.latest_monitors.lock().unwrap().get(&chan_2_funding) { nodes[2].channel_monitor_updated(&chan_2_funding, *id); } }, - 0x09 => send_payment!(nodes[0], (&nodes[1], chan_a), 5_000_000), - 0x0a => send_payment!(nodes[1], (&nodes[0], chan_a), 5_000_000), - 0x0b => send_payment!(nodes[1], (&nodes[2], chan_b), 5_000_000), - 0x0c => send_payment!(nodes[2], (&nodes[1], chan_b), 5_000_000), - 0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 5_000_000), - 0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 5_000_000), - 0x0f => { + + 0x0c => { if !chan_a_disconnected { nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false); nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false); @@ -701,7 +746,7 @@ pub fn do_test(data: &[u8], out: Out) { drain_msg_events_on_disconnect!(0); } }, - 0x10 => { + 0x0d => { if !chan_b_disconnected { nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false); nodes[2].peer_disconnected(&nodes[1].get_our_node_id(), false); @@ -709,44 +754,45 @@ pub fn do_test(data: &[u8], out: Out) { drain_msg_events_on_disconnect!(2); } }, - 0x11 => { + 0x0e => { if chan_a_disconnected { nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() }); nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() }); chan_a_disconnected = false; } }, - 0x12 => { + 0x0f => { if chan_b_disconnected { nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() }); nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() }); chan_b_disconnected = false; } }, - 0x13 => process_msg_events!(0, true), - 0x14 => process_msg_events!(0, false), - 0x15 => process_events!(0, true), - 0x16 => process_events!(0, false), - 0x17 => process_msg_events!(1, true), - 0x18 => process_msg_events!(1, false), - 0x19 => process_events!(1, true), - 0x1a => process_events!(1, false), - 0x1b => process_msg_events!(2, true), - 0x1c => process_msg_events!(2, false), - 0x1d => process_events!(2, true), - 0x1e => process_events!(2, false), - 0x1f => { + + 0x10 => { process_msg_events!(0, true); }, + 0x11 => { process_msg_events!(0, false); }, + 0x12 => { process_events!(0, true); }, + 0x13 => { process_events!(0, false); }, + 0x14 => { process_msg_events!(1, true); }, + 0x15 => { process_msg_events!(1, false); }, + 0x16 => { process_events!(1, true); }, + 0x17 => { process_events!(1, false); }, + 0x18 => { process_msg_events!(2, true); }, + 0x19 => { process_msg_events!(2, false); }, + 0x1a => { process_events!(2, true); }, + 0x1b => { process_events!(2, false); }, + + 0x1c => { if !chan_a_disconnected { nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false); chan_a_disconnected = true; drain_msg_events_on_disconnect!(0); } let (new_node_a, new_monitor_a) = reload_node!(node_a_ser, 0, monitor_a); - node_a = Arc::new(new_node_a); - nodes[0] = node_a.clone(); + nodes[0] = new_node_a; monitor_a = new_monitor_a; }, - 0x20 => { + 0x1d => { if !chan_a_disconnected { nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false); chan_a_disconnected = true; @@ -760,42 +806,136 @@ pub fn do_test(data: &[u8], out: Out) { bc_events.clear(); } let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b); - node_b = Arc::new(new_node_b); - nodes[1] = node_b.clone(); + nodes[1] = new_node_b; monitor_b = new_monitor_b; }, - 0x21 => { + 0x1e => { if !chan_b_disconnected { nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false); chan_b_disconnected = true; drain_msg_events_on_disconnect!(2); } let (new_node_c, new_monitor_c) = reload_node!(node_c_ser, 2, monitor_c); - node_c = Arc::new(new_node_c); - nodes[2] = node_c.clone(); + nodes[2] = new_node_c; monitor_c = new_monitor_c; }, - 0x22 => send_payment_with_secret!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)), - 0x23 => send_payment_with_secret!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)), - 0x25 => send_payment!(nodes[0], (&nodes[1], chan_a), 10), - 0x26 => send_payment!(nodes[1], (&nodes[0], chan_a), 10), - 0x27 => send_payment!(nodes[1], (&nodes[2], chan_b), 10), - 0x28 => send_payment!(nodes[2], (&nodes[1], chan_b), 10), - 0x29 => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 10), - 0x2a => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 10), - 0x2b => send_payment!(nodes[0], (&nodes[1], chan_a), 1_000), - 0x2c => send_payment!(nodes[1], (&nodes[0], chan_a), 1_000), - 0x2d => send_payment!(nodes[1], (&nodes[2], chan_b), 1_000), - 0x2e => send_payment!(nodes[2], (&nodes[1], chan_b), 1_000), - 0x2f => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 1_000), - 0x30 => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 1_000), - 0x31 => send_payment!(nodes[0], (&nodes[1], chan_a), 100_000), - 0x32 => send_payment!(nodes[1], (&nodes[0], chan_a), 100_000), - 0x33 => send_payment!(nodes[1], (&nodes[2], chan_b), 100_000), - 0x34 => send_payment!(nodes[2], (&nodes[1], chan_b), 100_000), - 0x35 => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 100_000), - 0x36 => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 100_000), - // 0x24 defined above + + // 1/10th the channel size: + 0x20 => { send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id); }, + 0x21 => { send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id); }, + 0x22 => { send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id); }, + 0x23 => { send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id); }, + 0x24 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000_000, &mut payment_id); }, + 0x25 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000_000, &mut payment_id); }, + + 0x26 => { send_payment_with_secret!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)); }, + 0x27 => { send_payment_with_secret!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)); }, + + 0x28 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000_000, &mut payment_id); }, + 0x29 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000_000, &mut payment_id); }, + 0x2a => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000_000, &mut payment_id); }, + 0x2b => { send_payment(&nodes[2], &nodes[1], chan_b, 1_000_000, &mut payment_id); }, + 0x2c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1_000_000, &mut payment_id); }, + 0x2d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1_000_000, &mut payment_id); }, + + 0x30 => { send_payment(&nodes[0], &nodes[1], chan_a, 100_000, &mut payment_id); }, + 0x31 => { send_payment(&nodes[1], &nodes[0], chan_a, 100_000, &mut payment_id); }, + 0x32 => { send_payment(&nodes[1], &nodes[2], chan_b, 100_000, &mut payment_id); }, + 0x33 => { send_payment(&nodes[2], &nodes[1], chan_b, 100_000, &mut payment_id); }, + 0x34 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 100_000, &mut payment_id); }, + 0x35 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 100_000, &mut payment_id); }, + + 0x38 => { send_payment(&nodes[0], &nodes[1], chan_a, 10_000, &mut payment_id); }, + 0x39 => { send_payment(&nodes[1], &nodes[0], chan_a, 10_000, &mut payment_id); }, + 0x3a => { send_payment(&nodes[1], &nodes[2], chan_b, 10_000, &mut payment_id); }, + 0x3b => { send_payment(&nodes[2], &nodes[1], chan_b, 10_000, &mut payment_id); }, + 0x3c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000, &mut payment_id); }, + 0x3d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000, &mut payment_id); }, + + 0x40 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000, &mut payment_id); }, + 0x41 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000, &mut payment_id); }, + 0x42 => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000, &mut payment_id); }, + 0x43 => { send_payment(&nodes[2], &nodes[1], chan_b, 1_000, &mut payment_id); }, + 0x44 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1_000, &mut payment_id); }, + 0x45 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1_000, &mut payment_id); }, + + 0x48 => { send_payment(&nodes[0], &nodes[1], chan_a, 100, &mut payment_id); }, + 0x49 => { send_payment(&nodes[1], &nodes[0], chan_a, 100, &mut payment_id); }, + 0x4a => { send_payment(&nodes[1], &nodes[2], chan_b, 100, &mut payment_id); }, + 0x4b => { send_payment(&nodes[2], &nodes[1], chan_b, 100, &mut payment_id); }, + 0x4c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 100, &mut payment_id); }, + 0x4d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 100, &mut payment_id); }, + + 0x50 => { send_payment(&nodes[0], &nodes[1], chan_a, 10, &mut payment_id); }, + 0x51 => { send_payment(&nodes[1], &nodes[0], chan_a, 10, &mut payment_id); }, + 0x52 => { send_payment(&nodes[1], &nodes[2], chan_b, 10, &mut payment_id); }, + 0x53 => { send_payment(&nodes[2], &nodes[1], chan_b, 10, &mut payment_id); }, + 0x54 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10, &mut payment_id); }, + 0x55 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10, &mut payment_id); }, + + 0x58 => { send_payment(&nodes[0], &nodes[1], chan_a, 1, &mut payment_id); }, + 0x59 => { send_payment(&nodes[1], &nodes[0], chan_a, 1, &mut payment_id); }, + 0x5a => { send_payment(&nodes[1], &nodes[2], chan_b, 1, &mut payment_id); }, + 0x5b => { send_payment(&nodes[2], &nodes[1], chan_b, 1, &mut payment_id); }, + 0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); }, + 0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); }, + + 0xff => { + // Test that no channel is in a stuck state where neither party can send funds even + // after we resolve all pending events. + // First make sure there are no pending monitor updates, resetting the error state + // and calling channel_monitor_updated for each monitor. + *monitor_a.update_ret.lock().unwrap() = Ok(()); + *monitor_b.update_ret.lock().unwrap() = Ok(()); + *monitor_c.update_ret.lock().unwrap() = Ok(()); + + if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) { + nodes[0].channel_monitor_updated(&chan_1_funding, *id); + } + if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_1_funding) { + nodes[1].channel_monitor_updated(&chan_1_funding, *id); + } + if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_2_funding) { + nodes[1].channel_monitor_updated(&chan_2_funding, *id); + } + if let Some((id, _)) = monitor_c.latest_monitors.lock().unwrap().get(&chan_2_funding) { + nodes[2].channel_monitor_updated(&chan_2_funding, *id); + } + + // Next, make sure peers are all connected to each other + if chan_a_disconnected { + nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() }); + nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() }); + chan_a_disconnected = false; + } + if chan_b_disconnected { + nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() }); + nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() }); + chan_b_disconnected = false; + } + + for i in 0..std::usize::MAX { + if i == 100 { panic!("It may take may iterations to settle the state, but it should not take forever"); } + // Then, make sure any current forwards make their way to their destination + if process_msg_events!(0, false) { continue; } + if process_msg_events!(1, false) { continue; } + if process_msg_events!(2, false) { continue; } + // ...making sure any pending PendingHTLCsForwardable events are handled and + // payments claimed. + if process_events!(0, false) { continue; } + if process_events!(1, false) { continue; } + if process_events!(2, false) { continue; } + break; + } + + // Finally, make sure that at least one end of each channel can make a substantial payment. + assert!( + send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id) || + send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id)); + assert!( + send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id) || + send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id)); + }, _ => test_return!(), } diff --git a/genbindings.sh b/genbindings.sh index 01029658..ae2a2357 100755 --- a/genbindings.sh +++ b/genbindings.sh @@ -167,7 +167,7 @@ else fi # Now build with LTO on on both C++ and rust, but without cross-language LTO: -cargo rustc -v --release -- -C lto +CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C lto clang++ -std=c++11 -Wall -flto -O2 -pthread demo.cpp target/release/libldk.a -ldl echo "C++ Bin size and runtime with only RL (LTO) optimized:" ls -lha a.out @@ -179,7 +179,7 @@ if [ "$HOST_PLATFORM" != "host: x86_64-apple-darwin" -a "$CLANGPP" != "" ]; then # or Ubuntu packages). This should work fine on Distros which do more involved # packaging than simply shipping the rustup binaries (eg Debian should Just Work # here). - cargo rustc -v --release -- -C linker-plugin-lto -C lto -C link-arg=-fuse-ld=lld + CARGO_PROFILE_RELEASE_LTO=true cargo rustc -v --release -- -C linker-plugin-lto -C lto -C link-arg=-fuse-ld=lld $CLANGPP -Wall -std=c++11 -flto -fuse-ld=lld -O2 -pthread demo.cpp target/release/libldk.a -ldl echo "C++ Bin size and runtime with cross-language LTO:" ls -lha a.out diff --git a/lightning-c-bindings/demo.cpp b/lightning-c-bindings/demo.cpp index ee1cedf1..531d7e67 100644 --- a/lightning-c-bindings/demo.cpp +++ b/lightning-c-bindings/demo.cpp @@ -110,6 +110,12 @@ uint32_t get_fee(const void *this_arg, LDKConfirmationTarget target) { } // Note that we don't call _free() on target, but that's OK, its unitary } +// We use the same fee estimator globally: +const LDKFeeEstimator fee_est { + .this_arg = NULL, + .get_est_sat_per_1000_weight = get_fee, + .free = NULL, +}; static int num_txs_broadcasted = 0; // Technically a race, but ints are atomic on x86 void broadcast_tx(const void *this_arg, LDKTransaction tx) { @@ -126,7 +132,7 @@ struct NodeMonitors { void ConnectBlock(const uint8_t (*header)[80], uint32_t height, LDKCVec_C2Tuple_usizeTransactionZZ tx_data, LDKBroadcasterInterface broadcast, LDKFeeEstimator fee_est) { std::unique_lock l(mut); for (auto& mon : mons) { - LDK::CVec_C2Tuple_TxidCVec_TxOutZZZ res = ChannelMonitor_block_connected(&mon.second, &header_2, tx_data, height, broadcast, fee_est, *logger); + LDK::CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ res = ChannelMonitor_block_connected(&mon.second, &header_2, tx_data, height, broadcast, fee_est, *logger); } } }; @@ -159,7 +165,7 @@ LDKCResult_NoneChannelMonitorUpdateErrZ update_channel_monitor(const void *this_ LDKBroadcasterInterface broadcaster = { .broadcast_transaction = broadcast_tx, }; - LDK::CResult_NoneMonitorUpdateErrorZ res = ChannelMonitor_update_monitor(&mon.second, update, &broadcaster, arg->logger); + LDK::CResult_NoneMonitorUpdateErrorZ res = ChannelMonitor_update_monitor(&mon.second, &update, &broadcaster, &fee_est, arg->logger); assert(res->result_ok); } } @@ -191,8 +197,8 @@ uintptr_t sock_send_data(void *this_arg, LDKu8slice data, bool resume_read) { void sock_disconnect_socket(void *this_arg) { close((int)((long)this_arg)); } -bool sock_eq(const void *this_arg, const void *other_arg) { - return this_arg == other_arg; +bool sock_eq(const void *this_arg, const LDKSocketDescriptor *other_arg) { + return this_arg == other_arg->this_arg; } uint64_t sock_hash(const void *this_arg) { return (uint64_t)this_arg; @@ -224,12 +230,6 @@ int main() { LDKNetwork network = LDKNetwork_Testnet; // Trait implementations: - LDKFeeEstimator fee_est { - .this_arg = NULL, - .get_est_sat_per_1000_weight = get_fee, - .free = NULL, - }; - LDKBroadcasterInterface broadcast { .this_arg = NULL, .broadcast_transaction = broadcast_tx, @@ -420,19 +420,19 @@ int main() { } LDKCVec_C2Tuple_usizeTransactionZZ txdata { .data = (LDKC2TupleTempl_usize__Transaction*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 }; - *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); + *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); ChannelManager_block_connected(&cm1, &channel_open_header, txdata, 1); txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2TupleTempl_usize__Transaction*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 }; - *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); + *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); ChannelManager_block_connected(&cm2, &channel_open_header, txdata, 1); txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2TupleTempl_usize__Transaction*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 }; - *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); + *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); mons1.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est); txdata = LDKCVec_C2Tuple_usizeTransactionZZ { .data = (LDKC2TupleTempl_usize__Transaction*)malloc(sizeof(LDKC2Tuple_usizeTransactionZ)), .datalen = 1 }; - *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); + *txdata.data = C2Tuple_usizeTransactionZ_new(0, LDKTransaction { .data = (uint8_t*)channel_open_tx, .datalen = sizeof(channel_open_tx), .data_is_owned = false }); mons2.ConnectBlock(&channel_open_header, 1, txdata, broadcast, fee_est); ChannelManager_block_connected(&cm1, &header_1, LDKCVec_C2Tuple_usizeTransactionZZ { .data = NULL, .datalen = 0 }, 2); diff --git a/lightning-c-bindings/include/lightning.h b/lightning-c-bindings/include/lightning.h index cd246f92..45e4fa3a 100644 --- a/lightning-c-bindings/include/lightning.h +++ b/lightning-c-bindings/include/lightning.h @@ -198,7 +198,10 @@ typedef enum LDKSecp256k1Error { * `data_is_owned` either set or unset at your discretion. */ typedef struct LDKTransaction { - const uint8_t *data; + /** + * This is non-const for your convenience, an object passed to Rust is never written to. + */ + uint8_t *data; uintptr_t datalen; bool data_is_owned; } LDKTransaction; @@ -245,7 +248,7 @@ typedef LDKCResultTempl_u8__ChannelMonitorUpdateErr LDKCResult_NoneChannelMonito * inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::update_monitor this * means you tried to update a monitor for a different channel or the ChannelMonitorUpdate was * corrupted. - * Contains a human-readable error message. + * Contains a developer-readable error message. */ typedef struct MUST_USE_STRUCT LDKMonitorUpdateError { /** @@ -292,6 +295,13 @@ typedef struct LDKC2TupleTempl_OutPoint__CVec_u8Z { typedef LDKC2TupleTempl_OutPoint__CVec_u8Z LDKC2Tuple_OutPointScriptZ; +typedef struct LDKC2TupleTempl_u32__TxOut { + uint32_t a; + LDKTxOut b; +} LDKC2TupleTempl_u32__TxOut; + +typedef LDKC2TupleTempl_u32__TxOut LDKC2Tuple_u32TxOutZ; + /** * Arbitrary 32 bytes, which could represent one of a few different things. You probably want to * look up the corresponding function in rust-lightning's docs. @@ -300,19 +310,19 @@ typedef struct LDKThirtyTwoBytes { uint8_t data[32]; } LDKThirtyTwoBytes; -typedef struct LDKCVecTempl_TxOut { - LDKTxOut *data; +typedef struct LDKCVecTempl_C2TupleTempl_u32__TxOut { + LDKC2TupleTempl_u32__TxOut *data; uintptr_t datalen; -} LDKCVecTempl_TxOut; +} LDKCVecTempl_C2TupleTempl_u32__TxOut; -typedef struct LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut { +typedef struct LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut { LDKThirtyTwoBytes a; - LDKCVecTempl_TxOut b; -} LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut; + LDKCVecTempl_C2TupleTempl_u32__TxOut b; +} LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut; -typedef LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut LDKC2Tuple_TxidCVec_TxOutZZ; +typedef LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ; -typedef LDKCVecTempl_TxOut LDKCVec_TxOutZ; +typedef LDKCVecTempl_C2TupleTempl_u32__TxOut LDKCVec_C2Tuple_u32TxOutZZ; typedef struct LDKC2TupleTempl_u64__u64 { uint64_t a; @@ -1820,6 +1830,68 @@ typedef struct LDKFeeEstimator { void (*free)(void *this_arg); } LDKFeeEstimator; +/** + * `Persist` defines behavior for persisting channel monitors: this could mean + * writing once to disk, and/or uploading to one or more backup services. + * + * Note that for every new monitor, you **must** persist the new `ChannelMonitor` + * to disk/backups. And, on every update, you **must** persist either the + * `ChannelMonitorUpdate` or the updated monitor itself. Otherwise, there is risk + * of situations such as revoking a transaction, then crashing before this + * revocation can be persisted, then unintentionally broadcasting a revoked + * transaction and losing money. This is a risk because previous channel states + * are toxic, so it's important that whatever channel state is persisted is + * kept up-to-date. + */ +typedef struct LDKPersist { + void *this_arg; + /** + * Persist a new channel's data. The data can be stored any way you want, but + * the identifier provided by Rust-Lightning is the channel's outpoint (and + * it is up to you to maintain a correct mapping between the outpoint and the + * stored channel data). Note that you **must** persist every new monitor to + * disk. See the `Persist` trait documentation for more details. + * + * See [`ChannelMonitor::serialize_for_disk`] for writing out a `ChannelMonitor`, + * and [`ChannelMonitorUpdateErr`] for requirements when returning errors. + * + * [`ChannelMonitor::serialize_for_disk`]: struct.ChannelMonitor.html#method.serialize_for_disk + * [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html + */ + LDKCResult_NoneChannelMonitorUpdateErrZ (*persist_new_channel)(const void *this_arg, LDKOutPoint id, const LDKChannelMonitor *data); + /** + * Update one channel's data. The provided `ChannelMonitor` has already + * applied the given update. + * + * Note that on every update, you **must** persist either the + * `ChannelMonitorUpdate` or the updated monitor itself to disk/backups. See + * the `Persist` trait documentation for more details. + * + * If an implementer chooses to persist the updates only, they need to make + * sure that all the updates are applied to the `ChannelMonitors` *before* + * the set of channel monitors is given to the `ChannelManager` + * deserialization routine. See [`ChannelMonitor::update_monitor`] for + * applying a monitor update to a monitor. If full `ChannelMonitors` are + * persisted, then there is no need to persist individual updates. + * + * Note that there could be a performance tradeoff between persisting complete + * channel monitors on every update vs. persisting only updates and applying + * them in batches. The size of each monitor grows `O(number of state updates)` + * whereas updates are small and `O(1)`. + * + * See [`ChannelMonitor::serialize_for_disk`] for writing out a `ChannelMonitor`, + * [`ChannelMonitorUpdate::write`] for writing out an update, and + * [`ChannelMonitorUpdateErr`] for requirements when returning errors. + * + * [`ChannelMonitor::update_monitor`]: struct.ChannelMonitor.html#impl-1 + * [`ChannelMonitor::serialize_for_disk`]: struct.ChannelMonitor.html#method.serialize_for_disk + * [`ChannelMonitorUpdate::write`]: struct.ChannelMonitorUpdate.html#method.write + * [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html + */ + LDKCResult_NoneChannelMonitorUpdateErrZ (*update_persisted_channel)(const void *this_arg, LDKOutPoint id, const LDKChannelMonitorUpdate *update, const LDKChannelMonitor *data); + void (*free)(void *this_arg); +} LDKPersist; + /** @@ -1875,12 +1947,12 @@ typedef struct LDKCVecTempl_Transaction { typedef LDKCVecTempl_Transaction LDKCVec_TransactionZ; -typedef struct LDKCVecTempl_C2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut { - LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut *data; +typedef struct LDKCVecTempl_C2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut { + LDKC2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut *data; uintptr_t datalen; -} LDKCVecTempl_C2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut; +} LDKCVecTempl_C2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut; -typedef LDKCVecTempl_C2TupleTempl_ThirtyTwoBytes__CVecTempl_TxOut LDKCVec_C2Tuple_TxidCVec_TxOutZZZ; +typedef LDKCVecTempl_C2TupleTempl_ThirtyTwoBytes__CVecTempl_C2TupleTempl_u32__TxOut LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ; typedef struct LDKSecretKey { uint8_t bytes[32]; @@ -2735,7 +2807,7 @@ typedef struct LDKSocketDescriptor { * socket_disconnected but prior to socket_disconnected returning. */ void (*disconnect_socket)(void *this_arg); - bool (*eq)(const void *this_arg, const void *other_arg); + bool (*eq)(const void *this_arg, const LDKSocketDescriptor *other_arg); uint64_t (*hash)(const void *this_arg); void *(*clone)(const void *this_arg); void (*free)(void *this_arg); @@ -3047,7 +3119,9 @@ extern const void (*C2Tuple_OutPointScriptZ_free)(LDKC2Tuple_OutPointScriptZ); extern const void (*C2Tuple_SignatureCVec_SignatureZZ_free)(LDKC2Tuple_SignatureCVec_SignatureZZ); -extern const void (*C2Tuple_TxidCVec_TxOutZZ_free)(LDKC2Tuple_TxidCVec_TxOutZZ); +extern const void (*C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ_free)(LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ); + +extern const void (*C2Tuple_u32TxOutZ_free)(LDKC2Tuple_u32TxOutZ); extern const void (*C2Tuple_u64u64Z_free)(LDKC2Tuple_u64u64Z); @@ -3055,6 +3129,8 @@ extern const void (*C2Tuple_usizeTransactionZ_free)(LDKC2Tuple_usizeTransactionZ extern const void (*C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ_free)(LDKC3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZ); +extern const uint64_t CLOSED_CHANNEL_UPDATE_ID; + extern const void (*CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ_free)(LDKCResult_C2Tuple_SignatureCVec_SignatureZZNoneZ); extern const LDKCResult_C2Tuple_SignatureCVec_SignatureZZNoneZ (*CResult_C2Tuple_SignatureCVec_SignatureZZNoneZ_ok)(LDKC2Tuple_SignatureCVec_SignatureZZ); @@ -3137,7 +3213,9 @@ extern const LDKCResult_boolPeerHandleErrorZ (*CResult_boolPeerHandleErrorZ_ok)( extern const void (*CVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ_free)(LDKCVec_C2Tuple_HTLCOutputInCommitmentSignatureZZ); -extern const void (*CVec_C2Tuple_TxidCVec_TxOutZZZ_free)(LDKCVec_C2Tuple_TxidCVec_TxOutZZZ); +extern const void (*CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ_free)(LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ); + +extern const void (*CVec_C2Tuple_u32TxOutZZ_free)(LDKCVec_C2Tuple_u32TxOutZZ); extern const void (*CVec_C2Tuple_usizeTransactionZZ_free)(LDKCVec_C2Tuple_usizeTransactionZZ); @@ -3173,8 +3251,6 @@ extern const void (*CVec_SpendableOutputDescriptorZ_free)(LDKCVec_SpendableOutpu extern const void (*CVec_TransactionZ_free)(LDKCVec_TransactionZ); -extern const void (*CVec_TxOutZ_free)(LDKCVec_TxOutZ); - extern const void (*CVec_UpdateAddHTLCZ_free)(LDKCVec_UpdateAddHTLCZ); extern const void (*CVec_UpdateFailHTLCZ_free)(LDKCVec_UpdateFailHTLCZ); @@ -3201,7 +3277,9 @@ LDKCResult_NoneMonitorUpdateErrorZ CResult_NoneMonitorUpdateErrorZ_ok(void); LDKC2Tuple_OutPointScriptZ C2Tuple_OutPointScriptZ_new(LDKOutPoint a, LDKCVec_u8Z b); -LDKC2Tuple_TxidCVec_TxOutZZ C2Tuple_TxidCVec_TxOutZZ_new(LDKThirtyTwoBytes a, LDKCVec_TxOutZ b); +LDKC2Tuple_u32TxOutZ C2Tuple_u32TxOutZ_new(uint32_t a, LDKTxOut b); + +LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ_new(LDKThirtyTwoBytes a, LDKCVec_C2Tuple_u32TxOutZZ b); LDKC2Tuple_u64u64Z C2Tuple_u64u64Z_new(uint64_t a, uint64_t b); @@ -3225,8 +3303,12 @@ LDKC2Tuple_HTLCOutputInCommitmentSignatureZ C2Tuple_HTLCOutputInCommitmentSignat void Event_free(LDKEvent this_ptr); +LDKEvent Event_clone(const LDKEvent *orig); + void MessageSendEvent_free(LDKMessageSendEvent this_ptr); +LDKMessageSendEvent MessageSendEvent_clone(const LDKMessageSendEvent *orig); + /** * Calls the free function if one is set */ @@ -3239,6 +3321,10 @@ void EventsProvider_free(LDKEventsProvider this_ptr); void APIError_free(LDKAPIError this_ptr); +LDKAPIError APIError_clone(const LDKAPIError *orig); + +LDKLevel Level_clone(const LDKLevel *orig); + /** * Returns the most verbose logging level. */ @@ -3251,6 +3337,8 @@ void Logger_free(LDKLogger this_ptr); void ChannelHandshakeConfig_free(LDKChannelHandshakeConfig this_ptr); +LDKChannelHandshakeConfig ChannelHandshakeConfig_clone(const LDKChannelHandshakeConfig *orig); + /** * Confirmations we will wait for before considering the channel locked in. * Applied only for inbound channels (see ChannelHandshakeLimits::max_minimum_depth for the @@ -3329,6 +3417,8 @@ MUST_USE_RES LDKChannelHandshakeConfig ChannelHandshakeConfig_default(void); void ChannelHandshakeLimits_free(LDKChannelHandshakeLimits this_ptr); +LDKChannelHandshakeLimits ChannelHandshakeLimits_clone(const LDKChannelHandshakeLimits *orig); + /** * Minimum allowed satoshis when a channel is funded, this is supplied by the sender and so * only applies to inbound channels. @@ -3521,6 +3611,8 @@ MUST_USE_RES LDKChannelHandshakeLimits ChannelHandshakeLimits_default(void); void ChannelConfig_free(LDKChannelConfig this_ptr); +LDKChannelConfig ChannelConfig_clone(const LDKChannelConfig *orig); + /** * Amount (in millionths of a satoshi) the channel will charge per transferred satoshi. * This may be allowed to change at runtime in a later update, however doing so must result in @@ -3609,6 +3701,8 @@ LDKChannelConfig ChannelConfig_read(LDKu8slice ser); void UserConfig_free(LDKUserConfig this_ptr); +LDKUserConfig UserConfig_clone(const LDKUserConfig *orig); + /** * Channel config that we propose to our counterparty. */ @@ -3643,6 +3737,8 @@ MUST_USE_RES LDKUserConfig UserConfig_new(LDKChannelHandshakeConfig own_channel_ MUST_USE_RES LDKUserConfig UserConfig_default(void); +LDKAccessError AccessError_clone(const LDKAccessError *orig); + /** * Calls the free function if one is set */ @@ -3663,6 +3759,8 @@ void Filter_free(LDKFilter this_ptr); */ void BroadcasterInterface_free(LDKBroadcasterInterface this_ptr); +LDKConfirmationTarget ConfirmationTarget_clone(const LDKConfirmationTarget *orig); + /** * Calls the free function if one is set */ @@ -3707,7 +3805,7 @@ void ChainMonitor_block_disconnected(const LDKChainMonitor *this_arg, const uint * * [`chain::Filter`]: ../trait.Filter.html */ -MUST_USE_RES LDKChainMonitor ChainMonitor_new(LDKFilter *chain_source, LDKBroadcasterInterface broadcaster, LDKLogger logger, LDKFeeEstimator feeest); +MUST_USE_RES LDKChainMonitor ChainMonitor_new(LDKFilter *chain_source, LDKBroadcasterInterface broadcaster, LDKLogger logger, LDKFeeEstimator feeest, LDKPersist persister); LDKWatch ChainMonitor_as_Watch(const LDKChainMonitor *this_arg); @@ -3715,25 +3813,39 @@ LDKEventsProvider ChainMonitor_as_EventsProvider(const LDKChainMonitor *this_arg void ChannelMonitorUpdate_free(LDKChannelMonitorUpdate this_ptr); +LDKChannelMonitorUpdate ChannelMonitorUpdate_clone(const LDKChannelMonitorUpdate *orig); + /** * The sequence number of this update. Updates *must* be replayed in-order according to this * sequence number (and updates may panic if they are not). The update_id values are strictly - * increasing and increase by one for each new update. + * increasing and increase by one for each new update, with one exception specified below. * * This sequence number is also used to track up to which points updates which returned * ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given * ChannelMonitor when ChannelManager::channel_monitor_updated is called. + * + * The only instance where update_id values are not strictly increasing is the case where we + * allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See + * its docs for more details. + * + * [`CLOSED_CHANNEL_UPDATE_ID`]: constant.CLOSED_CHANNEL_UPDATE_ID.html */ uint64_t ChannelMonitorUpdate_get_update_id(const LDKChannelMonitorUpdate *this_ptr); /** * The sequence number of this update. Updates *must* be replayed in-order according to this * sequence number (and updates may panic if they are not). The update_id values are strictly - * increasing and increase by one for each new update. + * increasing and increase by one for each new update, with one exception specified below. * * This sequence number is also used to track up to which points updates which returned * ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given * ChannelMonitor when ChannelManager::channel_monitor_updated is called. + * + * The only instance where update_id values are not strictly increasing is the case where we + * allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See + * its docs for more details. + * + * [`CLOSED_CHANNEL_UPDATE_ID`]: constant.CLOSED_CHANNEL_UPDATE_ID.html */ void ChannelMonitorUpdate_set_update_id(LDKChannelMonitorUpdate *this_ptr, uint64_t val); @@ -3741,12 +3853,18 @@ LDKCVec_u8Z ChannelMonitorUpdate_write(const LDKChannelMonitorUpdate *obj); LDKChannelMonitorUpdate ChannelMonitorUpdate_read(LDKu8slice ser); +LDKChannelMonitorUpdateErr ChannelMonitorUpdateErr_clone(const LDKChannelMonitorUpdateErr *orig); + void MonitorUpdateError_free(LDKMonitorUpdateError this_ptr); void MonitorEvent_free(LDKMonitorEvent this_ptr); +LDKMonitorEvent MonitorEvent_clone(const LDKMonitorEvent *orig); + void HTLCUpdate_free(LDKHTLCUpdate this_ptr); +LDKHTLCUpdate HTLCUpdate_clone(const LDKHTLCUpdate *orig); + LDKCVec_u8Z HTLCUpdate_write(const LDKHTLCUpdate *obj); LDKHTLCUpdate HTLCUpdate_read(LDKu8slice ser); @@ -3759,7 +3877,7 @@ void ChannelMonitor_free(LDKChannelMonitor this_ptr); * * panics if the given update is not the next update by update_id. */ -MUST_USE_RES LDKCResult_NoneMonitorUpdateErrorZ ChannelMonitor_update_monitor(LDKChannelMonitor *this_arg, LDKChannelMonitorUpdate updates, const LDKBroadcasterInterface *broadcaster, const LDKLogger *logger); +MUST_USE_RES LDKCResult_NoneMonitorUpdateErrorZ ChannelMonitor_update_monitor(LDKChannelMonitor *this_arg, const LDKChannelMonitorUpdate *updates, const LDKBroadcasterInterface *broadcaster, const LDKFeeEstimator *fee_estimator, const LDKLogger *logger); /** * Gets the update_id from the latest ChannelMonitorUpdate which was applied to this @@ -3816,7 +3934,7 @@ MUST_USE_RES LDKCVec_TransactionZ ChannelMonitor_get_latest_holder_commitment_tx * * [`get_outputs_to_watch`]: #method.get_outputs_to_watch */ -MUST_USE_RES LDKCVec_C2Tuple_TxidCVec_TxOutZZZ ChannelMonitor_block_connected(LDKChannelMonitor *this_arg, const uint8_t (*header)[80], LDKCVec_C2Tuple_usizeTransactionZZ txdata, uint32_t height, LDKBroadcasterInterface broadcaster, LDKFeeEstimator fee_estimator, LDKLogger logger); +MUST_USE_RES LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ ChannelMonitor_block_connected(LDKChannelMonitor *this_arg, const uint8_t (*header)[80], LDKCVec_C2Tuple_usizeTransactionZZ txdata, uint32_t height, LDKBroadcasterInterface broadcaster, LDKFeeEstimator fee_estimator, LDKLogger logger); /** * Determines if the disconnected block contained any transactions of interest and updates @@ -3824,8 +3942,15 @@ MUST_USE_RES LDKCVec_C2Tuple_TxidCVec_TxOutZZZ ChannelMonitor_block_connected(LD */ void ChannelMonitor_block_disconnected(LDKChannelMonitor *this_arg, const uint8_t (*header)[80], uint32_t height, LDKBroadcasterInterface broadcaster, LDKFeeEstimator fee_estimator, LDKLogger logger); +/** + * Calls the free function if one is set + */ +void Persist_free(LDKPersist this_ptr); + void OutPoint_free(LDKOutPoint this_ptr); +LDKOutPoint OutPoint_clone(const LDKOutPoint *orig); + /** * The referenced transaction's txid. */ @@ -3859,6 +3984,10 @@ LDKOutPoint OutPoint_read(LDKu8slice ser); void SpendableOutputDescriptor_free(LDKSpendableOutputDescriptor this_ptr); +LDKSpendableOutputDescriptor SpendableOutputDescriptor_clone(const LDKSpendableOutputDescriptor *orig); + +LDKChannelKeys ChannelKeys_clone(const LDKChannelKeys *orig); + /** * Calls the free function if one is set */ @@ -3871,6 +4000,8 @@ void KeysInterface_free(LDKKeysInterface this_ptr); void InMemoryChannelKeys_free(LDKInMemoryChannelKeys this_ptr); +LDKInMemoryChannelKeys InMemoryChannelKeys_clone(const LDKInMemoryChannelKeys *orig); + /** * Private key of anchor tx */ @@ -4005,6 +4136,8 @@ void ChannelManager_free(LDKChannelManager this_ptr); void ChannelDetails_free(LDKChannelDetails this_ptr); +LDKChannelDetails ChannelDetails_clone(const LDKChannelDetails *orig); + /** * The channel's ID (prior to funding transaction generation, this is a random 32 bytes, * thereafter this is the txid of the funding transaction xor the funding transaction output). @@ -4444,8 +4577,12 @@ void DecodeError_free(LDKDecodeError this_ptr); void Init_free(LDKInit this_ptr); +LDKInit Init_clone(const LDKInit *orig); + void ErrorMessage_free(LDKErrorMessage this_ptr); +LDKErrorMessage ErrorMessage_clone(const LDKErrorMessage *orig); + /** * The channel ID involved in the error */ @@ -4476,6 +4613,8 @@ MUST_USE_RES LDKErrorMessage ErrorMessage_new(LDKThirtyTwoBytes channel_id_arg, void Ping_free(LDKPing this_ptr); +LDKPing Ping_clone(const LDKPing *orig); + /** * The desired response length */ @@ -4502,6 +4641,8 @@ MUST_USE_RES LDKPing Ping_new(uint16_t ponglen_arg, uint16_t byteslen_arg); void Pong_free(LDKPong this_ptr); +LDKPong Pong_clone(const LDKPong *orig); + /** * The pong packet size. * This field is not sent on the wire. byteslen zeros are sent. @@ -4518,6 +4659,8 @@ MUST_USE_RES LDKPong Pong_new(uint16_t byteslen_arg); void OpenChannel_free(LDKOpenChannel this_ptr); +LDKOpenChannel OpenChannel_clone(const LDKOpenChannel *orig); + /** * The genesis hash of the blockchain where the channel is to be opened */ @@ -4700,6 +4843,8 @@ void OpenChannel_set_channel_flags(LDKOpenChannel *this_ptr, uint8_t val); void AcceptChannel_free(LDKAcceptChannel this_ptr); +LDKAcceptChannel AcceptChannel_clone(const LDKAcceptChannel *orig); + /** * A temporary channel ID, until the funding outpoint is announced */ @@ -4842,6 +4987,8 @@ void AcceptChannel_set_first_per_commitment_point(LDKAcceptChannel *this_ptr, LD void FundingCreated_free(LDKFundingCreated this_ptr); +LDKFundingCreated FundingCreated_clone(const LDKFundingCreated *orig); + /** * A temporary channel ID, until the funding is established */ @@ -4886,6 +5033,8 @@ MUST_USE_RES LDKFundingCreated FundingCreated_new(LDKThirtyTwoBytes temporary_ch void FundingSigned_free(LDKFundingSigned this_ptr); +LDKFundingSigned FundingSigned_clone(const LDKFundingSigned *orig); + /** * The channel ID */ @@ -4910,6 +5059,8 @@ MUST_USE_RES LDKFundingSigned FundingSigned_new(LDKThirtyTwoBytes channel_id_arg void FundingLocked_free(LDKFundingLocked this_ptr); +LDKFundingLocked FundingLocked_clone(const LDKFundingLocked *orig); + /** * The channel ID */ @@ -4934,6 +5085,8 @@ MUST_USE_RES LDKFundingLocked FundingLocked_new(LDKThirtyTwoBytes channel_id_arg void Shutdown_free(LDKShutdown this_ptr); +LDKShutdown Shutdown_clone(const LDKShutdown *orig); + /** * The channel ID */ @@ -4960,6 +5113,8 @@ MUST_USE_RES LDKShutdown Shutdown_new(LDKThirtyTwoBytes channel_id_arg, LDKCVec_ void ClosingSigned_free(LDKClosingSigned this_ptr); +LDKClosingSigned ClosingSigned_clone(const LDKClosingSigned *orig); + /** * The channel ID */ @@ -4994,6 +5149,8 @@ MUST_USE_RES LDKClosingSigned ClosingSigned_new(LDKThirtyTwoBytes channel_id_arg void UpdateAddHTLC_free(LDKUpdateAddHTLC this_ptr); +LDKUpdateAddHTLC UpdateAddHTLC_clone(const LDKUpdateAddHTLC *orig); + /** * The channel ID */ @@ -5046,6 +5203,8 @@ void UpdateAddHTLC_set_cltv_expiry(LDKUpdateAddHTLC *this_ptr, uint32_t val); void UpdateFulfillHTLC_free(LDKUpdateFulfillHTLC this_ptr); +LDKUpdateFulfillHTLC UpdateFulfillHTLC_clone(const LDKUpdateFulfillHTLC *orig); + /** * The channel ID */ @@ -5080,6 +5239,8 @@ MUST_USE_RES LDKUpdateFulfillHTLC UpdateFulfillHTLC_new(LDKThirtyTwoBytes channe void UpdateFailHTLC_free(LDKUpdateFailHTLC this_ptr); +LDKUpdateFailHTLC UpdateFailHTLC_clone(const LDKUpdateFailHTLC *orig); + /** * The channel ID */ @@ -5102,6 +5263,8 @@ void UpdateFailHTLC_set_htlc_id(LDKUpdateFailHTLC *this_ptr, uint64_t val); void UpdateFailMalformedHTLC_free(LDKUpdateFailMalformedHTLC this_ptr); +LDKUpdateFailMalformedHTLC UpdateFailMalformedHTLC_clone(const LDKUpdateFailMalformedHTLC *orig); + /** * The channel ID */ @@ -5134,6 +5297,8 @@ void UpdateFailMalformedHTLC_set_failure_code(LDKUpdateFailMalformedHTLC *this_p void CommitmentSigned_free(LDKCommitmentSigned this_ptr); +LDKCommitmentSigned CommitmentSigned_clone(const LDKCommitmentSigned *orig); + /** * The channel ID */ @@ -5163,6 +5328,8 @@ MUST_USE_RES LDKCommitmentSigned CommitmentSigned_new(LDKThirtyTwoBytes channel_ void RevokeAndACK_free(LDKRevokeAndACK this_ptr); +LDKRevokeAndACK RevokeAndACK_clone(const LDKRevokeAndACK *orig); + /** * The channel ID */ @@ -5197,6 +5364,8 @@ MUST_USE_RES LDKRevokeAndACK RevokeAndACK_new(LDKThirtyTwoBytes channel_id_arg, void UpdateFee_free(LDKUpdateFee this_ptr); +LDKUpdateFee UpdateFee_clone(const LDKUpdateFee *orig); + /** * The channel ID */ @@ -5221,6 +5390,8 @@ MUST_USE_RES LDKUpdateFee UpdateFee_new(LDKThirtyTwoBytes channel_id_arg, uint32 void DataLossProtect_free(LDKDataLossProtect this_ptr); +LDKDataLossProtect DataLossProtect_clone(const LDKDataLossProtect *orig); + /** * Proof that the sender knows the per-commitment secret of a specific commitment transaction * belonging to the recipient @@ -5247,6 +5418,8 @@ MUST_USE_RES LDKDataLossProtect DataLossProtect_new(LDKThirtyTwoBytes your_last_ void ChannelReestablish_free(LDKChannelReestablish this_ptr); +LDKChannelReestablish ChannelReestablish_clone(const LDKChannelReestablish *orig); + /** * The channel ID */ @@ -5279,6 +5452,8 @@ void ChannelReestablish_set_next_remote_commitment_number(LDKChannelReestablish void AnnouncementSignatures_free(LDKAnnouncementSignatures this_ptr); +LDKAnnouncementSignatures AnnouncementSignatures_clone(const LDKAnnouncementSignatures *orig); + /** * The channel ID */ @@ -5323,8 +5498,12 @@ MUST_USE_RES LDKAnnouncementSignatures AnnouncementSignatures_new(LDKThirtyTwoBy void NetAddress_free(LDKNetAddress this_ptr); +LDKNetAddress NetAddress_clone(const LDKNetAddress *orig); + void UnsignedNodeAnnouncement_free(LDKUnsignedNodeAnnouncement this_ptr); +LDKUnsignedNodeAnnouncement UnsignedNodeAnnouncement_clone(const LDKUnsignedNodeAnnouncement *orig); + /** * The advertised features */ @@ -5386,6 +5565,8 @@ void UnsignedNodeAnnouncement_set_addresses(LDKUnsignedNodeAnnouncement *this_pt void NodeAnnouncement_free(LDKNodeAnnouncement this_ptr); +LDKNodeAnnouncement NodeAnnouncement_clone(const LDKNodeAnnouncement *orig); + /** * The signature by the node key */ @@ -5410,6 +5591,8 @@ MUST_USE_RES LDKNodeAnnouncement NodeAnnouncement_new(LDKSignature signature_arg void UnsignedChannelAnnouncement_free(LDKUnsignedChannelAnnouncement this_ptr); +LDKUnsignedChannelAnnouncement UnsignedChannelAnnouncement_clone(const LDKUnsignedChannelAnnouncement *orig); + /** * The advertised channel features */ @@ -5482,6 +5665,8 @@ void UnsignedChannelAnnouncement_set_bitcoin_key_2(LDKUnsignedChannelAnnouncemen void ChannelAnnouncement_free(LDKChannelAnnouncement this_ptr); +LDKChannelAnnouncement ChannelAnnouncement_clone(const LDKChannelAnnouncement *orig); + /** * Authentication of the announcement by the first public node */ @@ -5536,6 +5721,8 @@ MUST_USE_RES LDKChannelAnnouncement ChannelAnnouncement_new(LDKSignature node_si void UnsignedChannelUpdate_free(LDKUnsignedChannelUpdate this_ptr); +LDKUnsignedChannelUpdate UnsignedChannelUpdate_clone(const LDKUnsignedChannelUpdate *orig); + /** * The genesis hash of the blockchain where the channel is to be opened */ @@ -5618,6 +5805,8 @@ void UnsignedChannelUpdate_set_fee_proportional_millionths(LDKUnsignedChannelUpd void ChannelUpdate_free(LDKChannelUpdate this_ptr); +LDKChannelUpdate ChannelUpdate_clone(const LDKChannelUpdate *orig); + /** * A signature of the channel update */ @@ -5642,6 +5831,8 @@ MUST_USE_RES LDKChannelUpdate ChannelUpdate_new(LDKSignature signature_arg, LDKU void QueryChannelRange_free(LDKQueryChannelRange this_ptr); +LDKQueryChannelRange QueryChannelRange_clone(const LDKQueryChannelRange *orig); + /** * The genesis hash of the blockchain being queried */ @@ -5676,6 +5867,8 @@ MUST_USE_RES LDKQueryChannelRange QueryChannelRange_new(LDKThirtyTwoBytes chain_ void ReplyChannelRange_free(LDKReplyChannelRange this_ptr); +LDKReplyChannelRange ReplyChannelRange_clone(const LDKReplyChannelRange *orig); + /** * The genesis hash of the blockchain being queried */ @@ -5727,6 +5920,8 @@ MUST_USE_RES LDKReplyChannelRange ReplyChannelRange_new(LDKThirtyTwoBytes chain_ void QueryShortChannelIds_free(LDKQueryShortChannelIds this_ptr); +LDKQueryShortChannelIds QueryShortChannelIds_clone(const LDKQueryShortChannelIds *orig); + /** * The genesis hash of the blockchain being queried */ @@ -5746,6 +5941,8 @@ MUST_USE_RES LDKQueryShortChannelIds QueryShortChannelIds_new(LDKThirtyTwoBytes void ReplyShortChannelIdsEnd_free(LDKReplyShortChannelIdsEnd this_ptr); +LDKReplyShortChannelIdsEnd ReplyShortChannelIdsEnd_clone(const LDKReplyShortChannelIdsEnd *orig); + /** * The genesis hash of the blockchain that was queried */ @@ -5772,6 +5969,8 @@ MUST_USE_RES LDKReplyShortChannelIdsEnd ReplyShortChannelIdsEnd_new(LDKThirtyTwo void GossipTimestampFilter_free(LDKGossipTimestampFilter this_ptr); +LDKGossipTimestampFilter GossipTimestampFilter_clone(const LDKGossipTimestampFilter *orig); + /** * The genesis hash of the blockchain for channel and node information */ @@ -5806,6 +6005,8 @@ MUST_USE_RES LDKGossipTimestampFilter GossipTimestampFilter_new(LDKThirtyTwoByte void ErrorAction_free(LDKErrorAction this_ptr); +LDKErrorAction ErrorAction_clone(const LDKErrorAction *orig); + void LightningError_free(LDKLightningError this_ptr); /** @@ -5832,6 +6033,8 @@ MUST_USE_RES LDKLightningError LightningError_new(LDKCVec_u8Z err_arg, LDKErrorA void CommitmentUpdate_free(LDKCommitmentUpdate this_ptr); +LDKCommitmentUpdate CommitmentUpdate_clone(const LDKCommitmentUpdate *orig); + /** * update_add_htlc messages which should be sent */ @@ -5876,6 +6079,8 @@ MUST_USE_RES LDKCommitmentUpdate CommitmentUpdate_new(LDKCVec_UpdateAddHTLCZ upd void HTLCFailChannelUpdate_free(LDKHTLCFailChannelUpdate this_ptr); +LDKHTLCFailChannelUpdate HTLCFailChannelUpdate_clone(const LDKHTLCFailChannelUpdate *orig); + /** * Calls the free function if one is set */ @@ -6038,6 +6243,8 @@ void MessageHandler_set_route_handler(LDKMessageHandler *this_ptr, LDKRoutingMes MUST_USE_RES LDKMessageHandler MessageHandler_new(LDKChannelMessageHandler chan_handler_arg, LDKRoutingMessageHandler route_handler_arg); +LDKSocketDescriptor SocketDescriptor_clone(const LDKSocketDescriptor *orig); + /** * Calls the free function if one is set */ @@ -6212,6 +6419,8 @@ LDKCResult_PublicKeySecpErrorZ derive_public_revocation_key(LDKPublicKey per_com void TxCreationKeys_free(LDKTxCreationKeys this_ptr); +LDKTxCreationKeys TxCreationKeys_clone(const LDKTxCreationKeys *orig); + /** * The broadcaster's per-commitment public key which was used to derive the other keys. */ @@ -6274,6 +6483,8 @@ LDKTxCreationKeys TxCreationKeys_read(LDKu8slice ser); void PreCalculatedTxCreationKeys_free(LDKPreCalculatedTxCreationKeys this_ptr); +LDKPreCalculatedTxCreationKeys PreCalculatedTxCreationKeys_clone(const LDKPreCalculatedTxCreationKeys *orig); + /** * Create a new PreCalculatedTxCreationKeys from TxCreationKeys */ @@ -6292,6 +6503,8 @@ MUST_USE_RES LDKPublicKey PreCalculatedTxCreationKeys_per_commitment_point(const void ChannelPublicKeys_free(LDKChannelPublicKeys this_ptr); +LDKChannelPublicKeys ChannelPublicKeys_clone(const LDKChannelPublicKeys *orig); + /** * The public key which is used to sign all commitment transactions, as it appears in the * on-chain channel lock-in 2-of-2 multisig output. @@ -6380,6 +6593,8 @@ LDKCVec_u8Z get_revokeable_redeemscript(LDKPublicKey revocation_key, uint16_t co void HTLCOutputInCommitment_free(LDKHTLCOutputInCommitment this_ptr); +LDKHTLCOutputInCommitment HTLCOutputInCommitment_clone(const LDKHTLCOutputInCommitment *orig); + /** * Whether the HTLC was \"offered\" (ie outbound in relation to this commitment transaction). * Note that this is not the same as whether it is ountbound *from us*. To determine that you @@ -6451,6 +6666,8 @@ LDKTransaction build_htlc_transaction(const uint8_t (*prev_hash)[32], uint32_t f void HolderCommitmentTransaction_free(LDKHolderCommitmentTransaction this_ptr); +LDKHolderCommitmentTransaction HolderCommitmentTransaction_clone(const LDKHolderCommitmentTransaction *orig); + /** * The commitment transaction itself, in unsigned form. */ @@ -6550,6 +6767,8 @@ void ChannelFeatures_free(LDKChannelFeatures this_ptr); void RouteHop_free(LDKRouteHop this_ptr); +LDKRouteHop RouteHop_clone(const LDKRouteHop *orig); + /** * The node_id of the node at this hop. */ @@ -6620,6 +6839,8 @@ MUST_USE_RES LDKRouteHop RouteHop_new(LDKPublicKey pubkey_arg, LDKNodeFeatures n void Route_free(LDKRoute this_ptr); +LDKRoute Route_clone(const LDKRoute *orig); + /** * The list of routes taken for a single (potentially-)multi-part payment. The pubkey of the * last RouteHop in each path must be the same. @@ -6638,6 +6859,8 @@ LDKRoute Route_read(LDKu8slice ser); void RouteHint_free(LDKRouteHint this_ptr); +LDKRouteHint RouteHint_clone(const LDKRouteHint *orig); + /** * The node_id of the non-target end of the route */ @@ -6884,6 +7107,8 @@ LDKChannelInfo ChannelInfo_read(LDKu8slice ser); void RoutingFees_free(LDKRoutingFees this_ptr); +LDKRoutingFees RoutingFees_clone(const LDKRoutingFees *orig); + /** * Flat routing fee in satoshis */ diff --git a/lightning-c-bindings/include/lightningpp.hpp b/lightning-c-bindings/include/lightningpp.hpp index 77b587fd..49e78e38 100644 --- a/lightning-c-bindings/include/lightningpp.hpp +++ b/lightning-c-bindings/include/lightningpp.hpp @@ -291,6 +291,20 @@ public: const LDKChannelMonitor* operator &() const { return &self; } const LDKChannelMonitor* operator ->() const { return &self; } }; +class Persist { +private: + LDKPersist self; +public: + Persist(const Persist&) = delete; + ~Persist() { Persist_free(self); } + Persist(Persist&& o) : self(o.self) { memset(&o, 0, sizeof(Persist)); } + Persist(LDKPersist&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKPersist)); } + operator LDKPersist() { LDKPersist res = self; memset(&self, 0, sizeof(LDKPersist)); return res; } + LDKPersist* operator &() { return &self; } + LDKPersist* operator ->() { return &self; } + const LDKPersist* operator &() const { return &self; } + const LDKPersist* operator ->() const { return &self; } +}; class OutPoint { private: LDKOutPoint self; @@ -1396,6 +1410,20 @@ public: const LDKCResult_C2Tuple_SignatureCVec_SignatureZZNoneZ* operator &() const { return &self; } const LDKCResult_C2Tuple_SignatureCVec_SignatureZZNoneZ* operator ->() const { return &self; } }; +class C2Tuple_u32TxOutZ { +private: + LDKC2Tuple_u32TxOutZ self; +public: + C2Tuple_u32TxOutZ(const C2Tuple_u32TxOutZ&) = delete; + ~C2Tuple_u32TxOutZ() { C2Tuple_u32TxOutZ_free(self); } + C2Tuple_u32TxOutZ(C2Tuple_u32TxOutZ&& o) : self(o.self) { memset(&o, 0, sizeof(C2Tuple_u32TxOutZ)); } + C2Tuple_u32TxOutZ(LDKC2Tuple_u32TxOutZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKC2Tuple_u32TxOutZ)); } + operator LDKC2Tuple_u32TxOutZ() { LDKC2Tuple_u32TxOutZ res = self; memset(&self, 0, sizeof(LDKC2Tuple_u32TxOutZ)); return res; } + LDKC2Tuple_u32TxOutZ* operator &() { return &self; } + LDKC2Tuple_u32TxOutZ* operator ->() { return &self; } + const LDKC2Tuple_u32TxOutZ* operator &() const { return &self; } + const LDKC2Tuple_u32TxOutZ* operator ->() const { return &self; } +}; class CResult_NoneMonitorUpdateErrorZ { private: LDKCResult_NoneMonitorUpdateErrorZ self; @@ -1410,20 +1438,6 @@ public: const LDKCResult_NoneMonitorUpdateErrorZ* operator &() const { return &self; } const LDKCResult_NoneMonitorUpdateErrorZ* operator ->() const { return &self; } }; -class CVec_UpdateFailHTLCZ { -private: - LDKCVec_UpdateFailHTLCZ self; -public: - CVec_UpdateFailHTLCZ(const CVec_UpdateFailHTLCZ&) = delete; - ~CVec_UpdateFailHTLCZ() { CVec_UpdateFailHTLCZ_free(self); } - CVec_UpdateFailHTLCZ(CVec_UpdateFailHTLCZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_UpdateFailHTLCZ)); } - CVec_UpdateFailHTLCZ(LDKCVec_UpdateFailHTLCZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_UpdateFailHTLCZ)); } - operator LDKCVec_UpdateFailHTLCZ() { LDKCVec_UpdateFailHTLCZ res = self; memset(&self, 0, sizeof(LDKCVec_UpdateFailHTLCZ)); return res; } - LDKCVec_UpdateFailHTLCZ* operator &() { return &self; } - LDKCVec_UpdateFailHTLCZ* operator ->() { return &self; } - const LDKCVec_UpdateFailHTLCZ* operator &() const { return &self; } - const LDKCVec_UpdateFailHTLCZ* operator ->() const { return &self; } -}; class CVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ { private: LDKCVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ self; @@ -1438,19 +1452,19 @@ public: const LDKCVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ* operator &() const { return &self; } const LDKCVec_C3Tuple_ChannelAnnouncementChannelUpdateChannelUpdateZZ* operator ->() const { return &self; } }; -class CVec_NodeAnnouncementZ { +class CVec_PublicKeyZ { private: - LDKCVec_NodeAnnouncementZ self; + LDKCVec_PublicKeyZ self; public: - CVec_NodeAnnouncementZ(const CVec_NodeAnnouncementZ&) = delete; - ~CVec_NodeAnnouncementZ() { CVec_NodeAnnouncementZ_free(self); } - CVec_NodeAnnouncementZ(CVec_NodeAnnouncementZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_NodeAnnouncementZ)); } - CVec_NodeAnnouncementZ(LDKCVec_NodeAnnouncementZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_NodeAnnouncementZ)); } - operator LDKCVec_NodeAnnouncementZ() { LDKCVec_NodeAnnouncementZ res = self; memset(&self, 0, sizeof(LDKCVec_NodeAnnouncementZ)); return res; } - LDKCVec_NodeAnnouncementZ* operator &() { return &self; } - LDKCVec_NodeAnnouncementZ* operator ->() { return &self; } - const LDKCVec_NodeAnnouncementZ* operator &() const { return &self; } - const LDKCVec_NodeAnnouncementZ* operator ->() const { return &self; } + CVec_PublicKeyZ(const CVec_PublicKeyZ&) = delete; + ~CVec_PublicKeyZ() { CVec_PublicKeyZ_free(self); } + CVec_PublicKeyZ(CVec_PublicKeyZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_PublicKeyZ)); } + CVec_PublicKeyZ(LDKCVec_PublicKeyZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_PublicKeyZ)); } + operator LDKCVec_PublicKeyZ() { LDKCVec_PublicKeyZ res = self; memset(&self, 0, sizeof(LDKCVec_PublicKeyZ)); return res; } + LDKCVec_PublicKeyZ* operator &() { return &self; } + LDKCVec_PublicKeyZ* operator ->() { return &self; } + const LDKCVec_PublicKeyZ* operator &() const { return &self; } + const LDKCVec_PublicKeyZ* operator ->() const { return &self; } }; class CResult_boolLightningErrorZ { private: @@ -1466,33 +1480,19 @@ public: const LDKCResult_boolLightningErrorZ* operator &() const { return &self; } const LDKCResult_boolLightningErrorZ* operator ->() const { return &self; } }; -class CVec_PublicKeyZ { +class CVec_C2Tuple_u32TxOutZZ { private: - LDKCVec_PublicKeyZ self; + LDKCVec_C2Tuple_u32TxOutZZ self; public: - CVec_PublicKeyZ(const CVec_PublicKeyZ&) = delete; - ~CVec_PublicKeyZ() { CVec_PublicKeyZ_free(self); } - CVec_PublicKeyZ(CVec_PublicKeyZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_PublicKeyZ)); } - CVec_PublicKeyZ(LDKCVec_PublicKeyZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_PublicKeyZ)); } - operator LDKCVec_PublicKeyZ() { LDKCVec_PublicKeyZ res = self; memset(&self, 0, sizeof(LDKCVec_PublicKeyZ)); return res; } - LDKCVec_PublicKeyZ* operator &() { return &self; } - LDKCVec_PublicKeyZ* operator ->() { return &self; } - const LDKCVec_PublicKeyZ* operator &() const { return &self; } - const LDKCVec_PublicKeyZ* operator ->() const { return &self; } -}; -class CResult_SecretKeySecpErrorZ { -private: - LDKCResult_SecretKeySecpErrorZ self; -public: - CResult_SecretKeySecpErrorZ(const CResult_SecretKeySecpErrorZ&) = delete; - ~CResult_SecretKeySecpErrorZ() { CResult_SecretKeySecpErrorZ_free(self); } - CResult_SecretKeySecpErrorZ(CResult_SecretKeySecpErrorZ&& o) : self(o.self) { memset(&o, 0, sizeof(CResult_SecretKeySecpErrorZ)); } - CResult_SecretKeySecpErrorZ(LDKCResult_SecretKeySecpErrorZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCResult_SecretKeySecpErrorZ)); } - operator LDKCResult_SecretKeySecpErrorZ() { LDKCResult_SecretKeySecpErrorZ res = self; memset(&self, 0, sizeof(LDKCResult_SecretKeySecpErrorZ)); return res; } - LDKCResult_SecretKeySecpErrorZ* operator &() { return &self; } - LDKCResult_SecretKeySecpErrorZ* operator ->() { return &self; } - const LDKCResult_SecretKeySecpErrorZ* operator &() const { return &self; } - const LDKCResult_SecretKeySecpErrorZ* operator ->() const { return &self; } + CVec_C2Tuple_u32TxOutZZ(const CVec_C2Tuple_u32TxOutZZ&) = delete; + ~CVec_C2Tuple_u32TxOutZZ() { CVec_C2Tuple_u32TxOutZZ_free(self); } + CVec_C2Tuple_u32TxOutZZ(CVec_C2Tuple_u32TxOutZZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_C2Tuple_u32TxOutZZ)); } + CVec_C2Tuple_u32TxOutZZ(LDKCVec_C2Tuple_u32TxOutZZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_C2Tuple_u32TxOutZZ)); } + operator LDKCVec_C2Tuple_u32TxOutZZ() { LDKCVec_C2Tuple_u32TxOutZZ res = self; memset(&self, 0, sizeof(LDKCVec_C2Tuple_u32TxOutZZ)); return res; } + LDKCVec_C2Tuple_u32TxOutZZ* operator &() { return &self; } + LDKCVec_C2Tuple_u32TxOutZZ* operator ->() { return &self; } + const LDKCVec_C2Tuple_u32TxOutZZ* operator &() const { return &self; } + const LDKCVec_C2Tuple_u32TxOutZZ* operator ->() const { return &self; } }; class CVec_SignatureZ { private: @@ -1550,6 +1550,20 @@ public: const LDKCVec_UpdateFailMalformedHTLCZ* operator &() const { return &self; } const LDKCVec_UpdateFailMalformedHTLCZ* operator ->() const { return &self; } }; +class CResult_SecretKeySecpErrorZ { +private: + LDKCResult_SecretKeySecpErrorZ self; +public: + CResult_SecretKeySecpErrorZ(const CResult_SecretKeySecpErrorZ&) = delete; + ~CResult_SecretKeySecpErrorZ() { CResult_SecretKeySecpErrorZ_free(self); } + CResult_SecretKeySecpErrorZ(CResult_SecretKeySecpErrorZ&& o) : self(o.self) { memset(&o, 0, sizeof(CResult_SecretKeySecpErrorZ)); } + CResult_SecretKeySecpErrorZ(LDKCResult_SecretKeySecpErrorZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCResult_SecretKeySecpErrorZ)); } + operator LDKCResult_SecretKeySecpErrorZ() { LDKCResult_SecretKeySecpErrorZ res = self; memset(&self, 0, sizeof(LDKCResult_SecretKeySecpErrorZ)); return res; } + LDKCResult_SecretKeySecpErrorZ* operator &() { return &self; } + LDKCResult_SecretKeySecpErrorZ* operator ->() { return &self; } + const LDKCResult_SecretKeySecpErrorZ* operator &() const { return &self; } + const LDKCResult_SecretKeySecpErrorZ* operator ->() const { return &self; } +}; class C2Tuple_HTLCOutputInCommitmentSignatureZ { private: LDKC2Tuple_HTLCOutputInCommitmentSignatureZ self; @@ -1858,19 +1872,19 @@ public: const LDKCResult_SignatureNoneZ* operator &() const { return &self; } const LDKCResult_SignatureNoneZ* operator ->() const { return &self; } }; -class C2Tuple_TxidCVec_TxOutZZ { +class C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ { private: - LDKC2Tuple_TxidCVec_TxOutZZ self; + LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ self; public: - C2Tuple_TxidCVec_TxOutZZ(const C2Tuple_TxidCVec_TxOutZZ&) = delete; - ~C2Tuple_TxidCVec_TxOutZZ() { C2Tuple_TxidCVec_TxOutZZ_free(self); } - C2Tuple_TxidCVec_TxOutZZ(C2Tuple_TxidCVec_TxOutZZ&& o) : self(o.self) { memset(&o, 0, sizeof(C2Tuple_TxidCVec_TxOutZZ)); } - C2Tuple_TxidCVec_TxOutZZ(LDKC2Tuple_TxidCVec_TxOutZZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKC2Tuple_TxidCVec_TxOutZZ)); } - operator LDKC2Tuple_TxidCVec_TxOutZZ() { LDKC2Tuple_TxidCVec_TxOutZZ res = self; memset(&self, 0, sizeof(LDKC2Tuple_TxidCVec_TxOutZZ)); return res; } - LDKC2Tuple_TxidCVec_TxOutZZ* operator &() { return &self; } - LDKC2Tuple_TxidCVec_TxOutZZ* operator ->() { return &self; } - const LDKC2Tuple_TxidCVec_TxOutZZ* operator &() const { return &self; } - const LDKC2Tuple_TxidCVec_TxOutZZ* operator ->() const { return &self; } + C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ(const C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ&) = delete; + ~C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ() { C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ_free(self); } + C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ(C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ&& o) : self(o.self) { memset(&o, 0, sizeof(C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ)); } + C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ(LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ)); } + operator LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ() { LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ res = self; memset(&self, 0, sizeof(LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ)); return res; } + LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ* operator &() { return &self; } + LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ* operator ->() { return &self; } + const LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ* operator &() const { return &self; } + const LDKC2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ* operator ->() const { return &self; } }; class CVec_ChannelDetailsZ { private: @@ -1900,6 +1914,20 @@ public: const LDKCVec_MessageSendEventZ* operator &() const { return &self; } const LDKCVec_MessageSendEventZ* operator ->() const { return &self; } }; +class CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ { +private: + LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ self; +public: + CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ(const CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ&) = delete; + ~CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ() { CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ_free(self); } + CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ(CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ)); } + CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ(LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ)); } + operator LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ() { LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ res = self; memset(&self, 0, sizeof(LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ)); return res; } + LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ* operator &() { return &self; } + LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ* operator ->() { return &self; } + const LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ* operator &() const { return &self; } + const LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ* operator ->() const { return &self; } +}; class CResult_NoneAPIErrorZ { private: LDKCResult_NoneAPIErrorZ self; @@ -1942,20 +1970,6 @@ public: const LDKCVec_NetAddressZ* operator &() const { return &self; } const LDKCVec_NetAddressZ* operator ->() const { return &self; } }; -class CVec_TxOutZ { -private: - LDKCVec_TxOutZ self; -public: - CVec_TxOutZ(const CVec_TxOutZ&) = delete; - ~CVec_TxOutZ() { CVec_TxOutZ_free(self); } - CVec_TxOutZ(CVec_TxOutZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_TxOutZ)); } - CVec_TxOutZ(LDKCVec_TxOutZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_TxOutZ)); } - operator LDKCVec_TxOutZ() { LDKCVec_TxOutZ res = self; memset(&self, 0, sizeof(LDKCVec_TxOutZ)); return res; } - LDKCVec_TxOutZ* operator &() { return &self; } - LDKCVec_TxOutZ* operator ->() { return &self; } - const LDKCVec_TxOutZ* operator &() const { return &self; } - const LDKCVec_TxOutZ* operator ->() const { return &self; } -}; class C2Tuple_usizeTransactionZ { private: LDKC2Tuple_usizeTransactionZ self; @@ -1984,6 +1998,20 @@ public: const LDKCVec_C2Tuple_usizeTransactionZZ* operator &() const { return &self; } const LDKCVec_C2Tuple_usizeTransactionZZ* operator ->() const { return &self; } }; +class CVec_TransactionZ { +private: + LDKCVec_TransactionZ self; +public: + CVec_TransactionZ(const CVec_TransactionZ&) = delete; + ~CVec_TransactionZ() { CVec_TransactionZ_free(self); } + CVec_TransactionZ(CVec_TransactionZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_TransactionZ)); } + CVec_TransactionZ(LDKCVec_TransactionZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_TransactionZ)); } + operator LDKCVec_TransactionZ() { LDKCVec_TransactionZ res = self; memset(&self, 0, sizeof(LDKCVec_TransactionZ)); return res; } + LDKCVec_TransactionZ* operator &() { return &self; } + LDKCVec_TransactionZ* operator ->() { return &self; } + const LDKCVec_TransactionZ* operator &() const { return &self; } + const LDKCVec_TransactionZ* operator ->() const { return &self; } +}; class CVec_ChannelMonitorZ { private: LDKCVec_ChannelMonitorZ self; @@ -1998,33 +2026,33 @@ public: const LDKCVec_ChannelMonitorZ* operator &() const { return &self; } const LDKCVec_ChannelMonitorZ* operator ->() const { return &self; } }; -class CVec_TransactionZ { +class CVec_UpdateFailHTLCZ { private: - LDKCVec_TransactionZ self; + LDKCVec_UpdateFailHTLCZ self; public: - CVec_TransactionZ(const CVec_TransactionZ&) = delete; - ~CVec_TransactionZ() { CVec_TransactionZ_free(self); } - CVec_TransactionZ(CVec_TransactionZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_TransactionZ)); } - CVec_TransactionZ(LDKCVec_TransactionZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_TransactionZ)); } - operator LDKCVec_TransactionZ() { LDKCVec_TransactionZ res = self; memset(&self, 0, sizeof(LDKCVec_TransactionZ)); return res; } - LDKCVec_TransactionZ* operator &() { return &self; } - LDKCVec_TransactionZ* operator ->() { return &self; } - const LDKCVec_TransactionZ* operator &() const { return &self; } - const LDKCVec_TransactionZ* operator ->() const { return &self; } + CVec_UpdateFailHTLCZ(const CVec_UpdateFailHTLCZ&) = delete; + ~CVec_UpdateFailHTLCZ() { CVec_UpdateFailHTLCZ_free(self); } + CVec_UpdateFailHTLCZ(CVec_UpdateFailHTLCZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_UpdateFailHTLCZ)); } + CVec_UpdateFailHTLCZ(LDKCVec_UpdateFailHTLCZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_UpdateFailHTLCZ)); } + operator LDKCVec_UpdateFailHTLCZ() { LDKCVec_UpdateFailHTLCZ res = self; memset(&self, 0, sizeof(LDKCVec_UpdateFailHTLCZ)); return res; } + LDKCVec_UpdateFailHTLCZ* operator &() { return &self; } + LDKCVec_UpdateFailHTLCZ* operator ->() { return &self; } + const LDKCVec_UpdateFailHTLCZ* operator &() const { return &self; } + const LDKCVec_UpdateFailHTLCZ* operator ->() const { return &self; } }; -class CVec_C2Tuple_TxidCVec_TxOutZZZ { +class CVec_NodeAnnouncementZ { private: - LDKCVec_C2Tuple_TxidCVec_TxOutZZZ self; + LDKCVec_NodeAnnouncementZ self; public: - CVec_C2Tuple_TxidCVec_TxOutZZZ(const CVec_C2Tuple_TxidCVec_TxOutZZZ&) = delete; - ~CVec_C2Tuple_TxidCVec_TxOutZZZ() { CVec_C2Tuple_TxidCVec_TxOutZZZ_free(self); } - CVec_C2Tuple_TxidCVec_TxOutZZZ(CVec_C2Tuple_TxidCVec_TxOutZZZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_C2Tuple_TxidCVec_TxOutZZZ)); } - CVec_C2Tuple_TxidCVec_TxOutZZZ(LDKCVec_C2Tuple_TxidCVec_TxOutZZZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_C2Tuple_TxidCVec_TxOutZZZ)); } - operator LDKCVec_C2Tuple_TxidCVec_TxOutZZZ() { LDKCVec_C2Tuple_TxidCVec_TxOutZZZ res = self; memset(&self, 0, sizeof(LDKCVec_C2Tuple_TxidCVec_TxOutZZZ)); return res; } - LDKCVec_C2Tuple_TxidCVec_TxOutZZZ* operator &() { return &self; } - LDKCVec_C2Tuple_TxidCVec_TxOutZZZ* operator ->() { return &self; } - const LDKCVec_C2Tuple_TxidCVec_TxOutZZZ* operator &() const { return &self; } - const LDKCVec_C2Tuple_TxidCVec_TxOutZZZ* operator ->() const { return &self; } + CVec_NodeAnnouncementZ(const CVec_NodeAnnouncementZ&) = delete; + ~CVec_NodeAnnouncementZ() { CVec_NodeAnnouncementZ_free(self); } + CVec_NodeAnnouncementZ(CVec_NodeAnnouncementZ&& o) : self(o.self) { memset(&o, 0, sizeof(CVec_NodeAnnouncementZ)); } + CVec_NodeAnnouncementZ(LDKCVec_NodeAnnouncementZ&& m_self) : self(m_self) { memset(&m_self, 0, sizeof(LDKCVec_NodeAnnouncementZ)); } + operator LDKCVec_NodeAnnouncementZ() { LDKCVec_NodeAnnouncementZ res = self; memset(&self, 0, sizeof(LDKCVec_NodeAnnouncementZ)); return res; } + LDKCVec_NodeAnnouncementZ* operator &() { return &self; } + LDKCVec_NodeAnnouncementZ* operator ->() { return &self; } + const LDKCVec_NodeAnnouncementZ* operator &() const { return &self; } + const LDKCVec_NodeAnnouncementZ* operator ->() const { return &self; } }; class C2Tuple_u64u64Z { private: diff --git a/lightning-c-bindings/include/rust_types.h b/lightning-c-bindings/include/rust_types.h index ca6cdc69..2e15b2a2 100644 --- a/lightning-c-bindings/include/rust_types.h +++ b/lightning-c-bindings/include/rust_types.h @@ -116,6 +116,7 @@ struct nativeCommitmentUpdateOpaque; typedef struct nativeCommitmentUpdateOpaque LDKnativeCommitmentUpdate; struct nativeMessageHandlerOpaque; typedef struct nativeMessageHandlerOpaque LDKnativeMessageHandler; +typedef struct LDKSocketDescriptor LDKSocketDescriptor; struct nativePeerHandleErrorOpaque; typedef struct nativePeerHandleErrorOpaque LDKnativePeerHandleError; struct nativePeerManagerOpaque; diff --git a/lightning-c-bindings/src/c_types/derived.rs b/lightning-c-bindings/src/c_types/derived.rs index d084a156..fd77e0d4 100644 --- a/lightning-c-bindings/src/c_types/derived.rs +++ b/lightning-c-bindings/src/c_types/derived.rs @@ -73,23 +73,32 @@ pub type CVec_TransactionZ = crate::c_types::CVecTempl; #[no_mangle] -pub type CVec_TxOutZ = crate::c_types::CVecTempl; +pub type C2Tuple_u32TxOutZ = crate::c_types::C2TupleTempl; #[no_mangle] -pub static CVec_TxOutZ_free: extern "C" fn(CVec_TxOutZ) = crate::c_types::CVecTempl_free::; +pub static C2Tuple_u32TxOutZ_free: extern "C" fn(C2Tuple_u32TxOutZ) = crate::c_types::C2TupleTempl_free::; +#[no_mangle] +pub extern "C" fn C2Tuple_u32TxOutZ_new(a: u32, b: crate::c_types::TxOut) -> C2Tuple_u32TxOutZ { + C2Tuple_u32TxOutZ { a, b, } +} + +#[no_mangle] +pub type CVec_C2Tuple_u32TxOutZZ = crate::c_types::CVecTempl>; +#[no_mangle] +pub static CVec_C2Tuple_u32TxOutZZ_free: extern "C" fn(CVec_C2Tuple_u32TxOutZZ) = crate::c_types::CVecTempl_free::>; #[no_mangle] -pub type C2Tuple_TxidCVec_TxOutZZ = crate::c_types::C2TupleTempl>; +pub type C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ = crate::c_types::C2TupleTempl>>; #[no_mangle] -pub static C2Tuple_TxidCVec_TxOutZZ_free: extern "C" fn(C2Tuple_TxidCVec_TxOutZZ) = crate::c_types::C2TupleTempl_free::>; +pub static C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ_free: extern "C" fn(C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ) = crate::c_types::C2TupleTempl_free::>>; #[no_mangle] -pub extern "C" fn C2Tuple_TxidCVec_TxOutZZ_new(a: crate::c_types::ThirtyTwoBytes, b: crate::c_types::derived::CVec_TxOutZ) -> C2Tuple_TxidCVec_TxOutZZ { - C2Tuple_TxidCVec_TxOutZZ { a, b, } +pub extern "C" fn C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ_new(a: crate::c_types::ThirtyTwoBytes, b: crate::c_types::derived::CVec_C2Tuple_u32TxOutZZ) -> C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ { + C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZ { a, b, } } #[no_mangle] -pub type CVec_C2Tuple_TxidCVec_TxOutZZZ = crate::c_types::CVecTempl>>; +pub type CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ = crate::c_types::CVecTempl>>>; #[no_mangle] -pub static CVec_C2Tuple_TxidCVec_TxOutZZZ_free: extern "C" fn(CVec_C2Tuple_TxidCVec_TxOutZZZ) = crate::c_types::CVecTempl_free::>>; +pub static CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ_free: extern "C" fn(CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ) = crate::c_types::CVecTempl_free::>>>; #[no_mangle] pub type C2Tuple_u64u64Z = crate::c_types::C2TupleTempl; diff --git a/lightning-c-bindings/src/c_types/mod.rs b/lightning-c-bindings/src/c_types/mod.rs index d14fe6fc..19192779 100644 --- a/lightning-c-bindings/src/c_types/mod.rs +++ b/lightning-c-bindings/src/c_types/mod.rs @@ -100,7 +100,8 @@ impl Secp256k1Error { /// set. Similarly, while it may change in the future, all `Transaction`s you pass to Rust may have /// `data_is_owned` either set or unset at your discretion. pub struct Transaction { - pub data: *const u8, + /// This is non-const for your convenience, an object passed to Rust is never written to. + pub data: *mut u8, pub datalen: usize, pub data_is_owned: bool, } @@ -319,7 +320,7 @@ impl Clone for CVecTempl { fn clone(&self) -> Self { let mut res = Vec::new(); if self.datalen == 0 { return Self::from(res); } - res.clone_from_slice(unsafe { std::slice::from_raw_parts_mut(self.data, self.datalen) }); + res.extend_from_slice(unsafe { std::slice::from_raw_parts_mut(self.data, self.datalen) }); Self::from(res) } } diff --git a/lightning-c-bindings/src/chain/chaininterface.rs b/lightning-c-bindings/src/chain/chaininterface.rs index ef524b56..b5f51032 100644 --- a/lightning-c-bindings/src/chain/chaininterface.rs +++ b/lightning-c-bindings/src/chain/chaininterface.rs @@ -93,6 +93,10 @@ impl ConfirmationTarget { } } } +#[no_mangle] +pub extern "C" fn ConfirmationTarget_clone(orig: &ConfirmationTarget) -> ConfirmationTarget { + orig.clone() +} /// A trait which should be implemented to provide feerate information on a number of time /// horizons. /// diff --git a/lightning-c-bindings/src/chain/chainmonitor.rs b/lightning-c-bindings/src/chain/chainmonitor.rs index 539b8450..35eb1bed 100644 --- a/lightning-c-bindings/src/chain/chainmonitor.rs +++ b/lightning-c-bindings/src/chain/chainmonitor.rs @@ -26,7 +26,7 @@ use crate::c_types::*; use lightning::chain::chainmonitor::ChainMonitor as nativeChainMonitorImport; -type nativeChainMonitor = nativeChainMonitorImport; +type nativeChainMonitor = nativeChainMonitorImport; /// An implementation of [`chain::Watch`] for monitoring channels. /// @@ -111,9 +111,9 @@ pub extern "C" fn ChainMonitor_block_disconnected(this_arg: &ChainMonitor, heade /// [`chain::Filter`]: ../trait.Filter.html #[must_use] #[no_mangle] -pub extern "C" fn ChainMonitor_new(chain_source: *mut crate::chain::Filter, mut broadcaster: crate::chain::chaininterface::BroadcasterInterface, mut logger: crate::util::logger::Logger, mut feeest: crate::chain::chaininterface::FeeEstimator) -> ChainMonitor { +pub extern "C" fn ChainMonitor_new(chain_source: *mut crate::chain::Filter, mut broadcaster: crate::chain::chaininterface::BroadcasterInterface, mut logger: crate::util::logger::Logger, mut feeest: crate::chain::chaininterface::FeeEstimator, mut persister: crate::chain::channelmonitor::Persist) -> ChainMonitor { let mut local_chain_source = if chain_source == std::ptr::null_mut() { None } else { Some( { unsafe { *Box::from_raw(chain_source) } }) }; - let mut ret = lightning::chain::chainmonitor::ChainMonitor::new(local_chain_source, broadcaster, logger, feeest); + let mut ret = lightning::chain::chainmonitor::ChainMonitor::new(local_chain_source, broadcaster, logger, feeest, persister); ChainMonitor { inner: Box::into_raw(Box::new(ret)), is_owned: true } } @@ -129,8 +129,8 @@ pub extern "C" fn ChainMonitor_as_Watch(this_arg: *const ChainMonitor) -> crate: } use lightning::chain::Watch as WatchTraitImport; #[must_use] -extern "C" fn ChainMonitor_Watch_watch_channel(this_arg: *const c_void, mut funding_txo: crate::chain::transaction::OutPoint, mut monitor: crate::chain::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ { - let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.watch_channel(*unsafe { Box::from_raw(funding_txo.take_ptr()) }, *unsafe { Box::from_raw(monitor.take_ptr()) }); +extern "C" fn ChainMonitor_Watch_watch_channel(this_arg: *const c_void, mut funding_outpoint: crate::chain::transaction::OutPoint, mut monitor: crate::chain::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ { + let mut ret = unsafe { &mut *(this_arg as *mut nativeChainMonitor) }.watch_channel(*unsafe { Box::from_raw(funding_outpoint.take_ptr()) }, *unsafe { Box::from_raw(monitor.take_ptr()) }); let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::chain::channelmonitor::ChannelMonitorUpdateErr::native_into(e) }) }; local_ret } diff --git a/lightning-c-bindings/src/chain/channelmonitor.rs b/lightning-c-bindings/src/chain/channelmonitor.rs index 79c84d53..c6446702 100644 --- a/lightning-c-bindings/src/chain/channelmonitor.rs +++ b/lightning-c-bindings/src/chain/channelmonitor.rs @@ -69,13 +69,23 @@ impl Clone for ChannelMonitorUpdate { pub(crate) extern "C" fn ChannelMonitorUpdate_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelMonitorUpdate)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelMonitorUpdate_clone(orig: &ChannelMonitorUpdate) -> ChannelMonitorUpdate { + ChannelMonitorUpdate { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The sequence number of this update. Updates *must* be replayed in-order according to this /// sequence number (and updates may panic if they are not). The update_id values are strictly -/// increasing and increase by one for each new update. +/// increasing and increase by one for each new update, with one exception specified below. /// /// This sequence number is also used to track up to which points updates which returned /// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given /// ChannelMonitor when ChannelManager::channel_monitor_updated is called. +/// +/// The only instance where update_id values are not strictly increasing is the case where we +/// allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See +/// its docs for more details. +/// +/// [`CLOSED_CHANNEL_UPDATE_ID`]: constant.CLOSED_CHANNEL_UPDATE_ID.html #[no_mangle] pub extern "C" fn ChannelMonitorUpdate_get_update_id(this_ptr: &ChannelMonitorUpdate) -> u64 { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.update_id; @@ -83,15 +93,24 @@ pub extern "C" fn ChannelMonitorUpdate_get_update_id(this_ptr: &ChannelMonitorUp } /// The sequence number of this update. Updates *must* be replayed in-order according to this /// sequence number (and updates may panic if they are not). The update_id values are strictly -/// increasing and increase by one for each new update. +/// increasing and increase by one for each new update, with one exception specified below. /// /// This sequence number is also used to track up to which points updates which returned /// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given /// ChannelMonitor when ChannelManager::channel_monitor_updated is called. +/// +/// The only instance where update_id values are not strictly increasing is the case where we +/// allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See +/// its docs for more details. +/// +/// [`CLOSED_CHANNEL_UPDATE_ID`]: constant.CLOSED_CHANNEL_UPDATE_ID.html #[no_mangle] pub extern "C" fn ChannelMonitorUpdate_set_update_id(this_ptr: &mut ChannelMonitorUpdate, mut val: u64) { unsafe { &mut *this_ptr.inner }.update_id = val; } + +#[no_mangle] +pub static CLOSED_CHANNEL_UPDATE_ID: u64 = lightning::chain::channelmonitor::CLOSED_CHANNEL_UPDATE_ID; #[no_mangle] pub extern "C" fn ChannelMonitorUpdate_write(obj: *const ChannelMonitorUpdate) -> crate::c_types::derived::CVec_u8Z { crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) }) @@ -197,6 +216,10 @@ impl ChannelMonitorUpdateErr { } } } +#[no_mangle] +pub extern "C" fn ChannelMonitorUpdateErr_clone(orig: &ChannelMonitorUpdateErr) -> ChannelMonitorUpdateErr { + orig.clone() +} use lightning::chain::channelmonitor::MonitorUpdateError as nativeMonitorUpdateErrorImport; type nativeMonitorUpdateError = nativeMonitorUpdateErrorImport; @@ -205,7 +228,7 @@ type nativeMonitorUpdateError = nativeMonitorUpdateErrorImport; /// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::update_monitor this /// means you tried to update a monitor for a different channel or the ChannelMonitorUpdate was /// corrupted. -/// Contains a human-readable error message. +/// Contains a developer-readable error message. #[must_use] #[repr(C)] pub struct MonitorUpdateError { @@ -277,6 +300,23 @@ impl MonitorEvent { ret } } +impl Clone for MonitorEvent { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn MonitorEvent_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeMonitorEvent)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn MonitorEvent_clone(orig: &MonitorEvent) -> MonitorEvent { + MonitorEvent { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} use lightning::chain::channelmonitor::HTLCUpdate as nativeHTLCUpdateImport; type nativeHTLCUpdate = nativeHTLCUpdateImport; @@ -333,6 +373,10 @@ pub(crate) extern "C" fn HTLCUpdate_clone_void(this_ptr: *const c_void) -> *mut Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeHTLCUpdate)).clone() })) as *mut c_void } #[no_mangle] +pub extern "C" fn HTLCUpdate_clone(orig: &HTLCUpdate) -> HTLCUpdate { + HTLCUpdate { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} +#[no_mangle] pub extern "C" fn HTLCUpdate_write(obj: *const HTLCUpdate) -> crate::c_types::derived::CVec_u8Z { crate::c_types::serialize_obj(unsafe { &(*(*obj).inner) }) } @@ -397,8 +441,8 @@ impl ChannelMonitor { /// panics if the given update is not the next update by update_id. #[must_use] #[no_mangle] -pub extern "C" fn ChannelMonitor_update_monitor(this_arg: &mut ChannelMonitor, mut updates: crate::chain::channelmonitor::ChannelMonitorUpdate, broadcaster: &crate::chain::chaininterface::BroadcasterInterface, logger: &crate::util::logger::Logger) -> crate::c_types::derived::CResult_NoneMonitorUpdateErrorZ { - let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.update_monitor(*unsafe { Box::from_raw(updates.take_ptr()) }, broadcaster, logger); +pub extern "C" fn ChannelMonitor_update_monitor(this_arg: &mut ChannelMonitor, updates: &crate::chain::channelmonitor::ChannelMonitorUpdate, broadcaster: &crate::chain::chaininterface::BroadcasterInterface, fee_estimator: &crate::chain::chaininterface::FeeEstimator, logger: &crate::util::logger::Logger) -> crate::c_types::derived::CResult_NoneMonitorUpdateErrorZ { + let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.update_monitor(unsafe { &*updates.inner }, broadcaster, fee_estimator, logger); let mut local_ret = match ret { Ok(mut o) => crate::c_types::CResultTempl::ok( { 0u8 /*o*/ }), Err(mut e) => crate::c_types::CResultTempl::err( { crate::chain::channelmonitor::MonitorUpdateError { inner: Box::into_raw(Box::new(e)), is_owned: true } }) }; local_ret } @@ -477,10 +521,10 @@ pub extern "C" fn ChannelMonitor_get_latest_holder_commitment_txn(this_arg: &mut /// [`get_outputs_to_watch`]: #method.get_outputs_to_watch #[must_use] #[no_mangle] -pub extern "C" fn ChannelMonitor_block_connected(this_arg: &mut ChannelMonitor, header: *const [u8; 80], mut txdata: crate::c_types::derived::CVec_C2Tuple_usizeTransactionZZ, mut height: u32, mut broadcaster: crate::chain::chaininterface::BroadcasterInterface, mut fee_estimator: crate::chain::chaininterface::FeeEstimator, mut logger: crate::util::logger::Logger) -> crate::c_types::derived::CVec_C2Tuple_TxidCVec_TxOutZZZ { +pub extern "C" fn ChannelMonitor_block_connected(this_arg: &mut ChannelMonitor, header: *const [u8; 80], mut txdata: crate::c_types::derived::CVec_C2Tuple_usizeTransactionZZ, mut height: u32, mut broadcaster: crate::chain::chaininterface::BroadcasterInterface, mut fee_estimator: crate::chain::chaininterface::FeeEstimator, mut logger: crate::util::logger::Logger) -> crate::c_types::derived::CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ { 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 }); }; let mut ret = unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.block_connected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), &local_txdata.iter().map(|(a, b)| (*a, b)).collect::>()[..], height, broadcaster, fee_estimator, logger); - let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { let (mut orig_ret_0_0, mut orig_ret_0_1) = item; let mut local_orig_ret_0_1 = Vec::new(); for item in orig_ret_0_1.drain(..) { local_orig_ret_0_1.push( { crate::c_types::TxOut::from_rust(item) }); }; let mut local_ret_0 = (crate::c_types::ThirtyTwoBytes { data: orig_ret_0_0.into_inner() }, local_orig_ret_0_1.into()).into(); local_ret_0 }); }; + let mut local_ret = Vec::new(); for item in ret.drain(..) { local_ret.push( { let (mut orig_ret_0_0, mut orig_ret_0_1) = item; let mut local_orig_ret_0_1 = Vec::new(); for item in orig_ret_0_1.drain(..) { local_orig_ret_0_1.push( { let (mut orig_orig_ret_0_1_0_0, mut orig_orig_ret_0_1_0_1) = item; let mut local_orig_ret_0_1_0 = (orig_orig_ret_0_1_0_0, crate::c_types::TxOut::from_rust(orig_orig_ret_0_1_0_1)).into(); local_orig_ret_0_1_0 }); }; let mut local_ret_0 = (crate::c_types::ThirtyTwoBytes { data: orig_ret_0_0.into_inner() }, local_orig_ret_0_1.into()).into(); local_ret_0 }); }; local_ret.into() } @@ -491,3 +535,96 @@ pub extern "C" fn ChannelMonitor_block_disconnected(this_arg: &mut ChannelMonito unsafe { &mut (*(this_arg.inner as *mut nativeChannelMonitor)) }.block_disconnected(&::bitcoin::consensus::encode::deserialize(unsafe { &*header }).unwrap(), height, broadcaster, fee_estimator, logger) } +/// `Persist` defines behavior for persisting channel monitors: this could mean +/// writing once to disk, and/or uploading to one or more backup services. +/// +/// Note that for every new monitor, you **must** persist the new `ChannelMonitor` +/// to disk/backups. And, on every update, you **must** persist either the +/// `ChannelMonitorUpdate` or the updated monitor itself. Otherwise, there is risk +/// of situations such as revoking a transaction, then crashing before this +/// revocation can be persisted, then unintentionally broadcasting a revoked +/// transaction and losing money. This is a risk because previous channel states +/// are toxic, so it's important that whatever channel state is persisted is +/// kept up-to-date. +#[repr(C)] +pub struct Persist { + pub this_arg: *mut c_void, + /// Persist a new channel's data. The data can be stored any way you want, but + /// the identifier provided by Rust-Lightning is the channel's outpoint (and + /// it is up to you to maintain a correct mapping between the outpoint and the + /// stored channel data). Note that you **must** persist every new monitor to + /// disk. See the `Persist` trait documentation for more details. + /// + /// See [`ChannelMonitor::serialize_for_disk`] for writing out a `ChannelMonitor`, + /// and [`ChannelMonitorUpdateErr`] for requirements when returning errors. + /// + /// [`ChannelMonitor::serialize_for_disk`]: struct.ChannelMonitor.html#method.serialize_for_disk + /// [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html + #[must_use] + pub persist_new_channel: extern "C" fn (this_arg: *const c_void, id: crate::chain::transaction::OutPoint, data: &crate::chain::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ, + /// Update one channel's data. The provided `ChannelMonitor` has already + /// applied the given update. + /// + /// Note that on every update, you **must** persist either the + /// `ChannelMonitorUpdate` or the updated monitor itself to disk/backups. See + /// the `Persist` trait documentation for more details. + /// + /// If an implementer chooses to persist the updates only, they need to make + /// sure that all the updates are applied to the `ChannelMonitors` *before* + /// the set of channel monitors is given to the `ChannelManager` + /// deserialization routine. See [`ChannelMonitor::update_monitor`] for + /// applying a monitor update to a monitor. If full `ChannelMonitors` are + /// persisted, then there is no need to persist individual updates. + /// + /// Note that there could be a performance tradeoff between persisting complete + /// channel monitors on every update vs. persisting only updates and applying + /// them in batches. The size of each monitor grows `O(number of state updates)` + /// whereas updates are small and `O(1)`. + /// + /// See [`ChannelMonitor::serialize_for_disk`] for writing out a `ChannelMonitor`, + /// [`ChannelMonitorUpdate::write`] for writing out an update, and + /// [`ChannelMonitorUpdateErr`] for requirements when returning errors. + /// + /// [`ChannelMonitor::update_monitor`]: struct.ChannelMonitor.html#impl-1 + /// [`ChannelMonitor::serialize_for_disk`]: struct.ChannelMonitor.html#method.serialize_for_disk + /// [`ChannelMonitorUpdate::write`]: struct.ChannelMonitorUpdate.html#method.write + /// [`ChannelMonitorUpdateErr`]: enum.ChannelMonitorUpdateErr.html + #[must_use] + pub update_persisted_channel: extern "C" fn (this_arg: *const c_void, id: crate::chain::transaction::OutPoint, update: &crate::chain::channelmonitor::ChannelMonitorUpdate, data: &crate::chain::channelmonitor::ChannelMonitor) -> crate::c_types::derived::CResult_NoneChannelMonitorUpdateErrZ, + pub free: Option, +} +unsafe impl Send for Persist {} +unsafe impl Sync for Persist {} + +use lightning::chain::channelmonitor::Persist as rustPersist; +impl rustPersist for Persist { + fn persist_new_channel(&self, id: lightning::chain::transaction::OutPoint, data: &lightning::chain::channelmonitor::ChannelMonitor) -> Result<(), lightning::chain::channelmonitor::ChannelMonitorUpdateErr> { + let mut ret = (self.persist_new_channel)(self.this_arg, crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(id)), is_owned: true }, &crate::chain::channelmonitor::ChannelMonitor { inner: unsafe { (data as *const _) as *mut _ }, is_owned: false }); + let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(ret.contents.result.take_ptr()) })*/ }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })}; + local_ret + } + fn update_persisted_channel(&self, id: lightning::chain::transaction::OutPoint, update: &lightning::chain::channelmonitor::ChannelMonitorUpdate, data: &lightning::chain::channelmonitor::ChannelMonitor) -> Result<(), lightning::chain::channelmonitor::ChannelMonitorUpdateErr> { + let mut ret = (self.update_persisted_channel)(self.this_arg, crate::chain::transaction::OutPoint { inner: Box::into_raw(Box::new(id)), is_owned: true }, &crate::chain::channelmonitor::ChannelMonitorUpdate { inner: unsafe { (update as *const _) as *mut _ }, is_owned: false }, &crate::chain::channelmonitor::ChannelMonitor { inner: unsafe { (data as *const _) as *mut _ }, is_owned: false }); + let mut local_ret = match ret.result_ok { true => Ok( { () /*(*unsafe { Box::from_raw(ret.contents.result.take_ptr()) })*/ }), false => Err( { (*unsafe { Box::from_raw(ret.contents.err.take_ptr()) }).into_native() })}; + local_ret + } +} + +// We're essentially a pointer already, or at least a set of pointers, so allow us to be used +// directly as a Deref trait in higher-level structs: +impl std::ops::Deref for Persist { + type Target = Self; + fn deref(&self) -> &Self { + self + } +} +/// Calls the free function if one is set +#[no_mangle] +pub extern "C" fn Persist_free(this_ptr: Persist) { } +impl Drop for Persist { + fn drop(&mut self) { + if let Some(f) = self.free { + f(self.this_arg); + } + } +} diff --git a/lightning-c-bindings/src/chain/keysinterface.rs b/lightning-c-bindings/src/chain/keysinterface.rs index 8d8a0acd..afa982bc 100644 --- a/lightning-c-bindings/src/chain/keysinterface.rs +++ b/lightning-c-bindings/src/chain/keysinterface.rs @@ -220,6 +220,10 @@ impl SpendableOutputDescriptor { } #[no_mangle] pub extern "C" fn SpendableOutputDescriptor_free(this_ptr: SpendableOutputDescriptor) { } +#[no_mangle] +pub extern "C" fn SpendableOutputDescriptor_clone(orig: &SpendableOutputDescriptor) -> SpendableOutputDescriptor { + orig.clone() +} /// Set of lightning keys needed to operate a channel as described in BOLT 3. /// /// Signing services could be implemented on a hardware wallet. In this case, @@ -362,26 +366,30 @@ pub struct ChannelKeys { pub free: Option, } unsafe impl Send for ChannelKeys {} +#[no_mangle] +pub extern "C" fn ChannelKeys_clone(orig: &ChannelKeys) -> ChannelKeys { + ChannelKeys { + 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(), + key_derivation_params: orig.key_derivation_params.clone(), + sign_counterparty_commitment: orig.sign_counterparty_commitment.clone(), + sign_holder_commitment: orig.sign_holder_commitment.clone(), + sign_holder_commitment_htlc_transactions: orig.sign_holder_commitment_htlc_transactions.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(), + on_accept: orig.on_accept.clone(), + clone: orig.clone.clone(), + free: orig.free.clone(), + } +} impl Clone for ChannelKeys { fn clone(&self) -> Self { - Self { - this_arg: if let Some(f) = self.clone { (f)(self.this_arg) } else { self.this_arg }, - get_per_commitment_point: self.get_per_commitment_point.clone(), - release_commitment_secret: self.release_commitment_secret.clone(), - pubkeys: self.pubkeys.clone(), - set_pubkeys: self.set_pubkeys.clone(), - key_derivation_params: self.key_derivation_params.clone(), - sign_counterparty_commitment: self.sign_counterparty_commitment.clone(), - sign_holder_commitment: self.sign_holder_commitment.clone(), - sign_holder_commitment_htlc_transactions: self.sign_holder_commitment_htlc_transactions.clone(), - sign_justice_transaction: self.sign_justice_transaction.clone(), - sign_counterparty_htlc_transaction: self.sign_counterparty_htlc_transaction.clone(), - sign_closing_transaction: self.sign_closing_transaction.clone(), - sign_channel_announcement: self.sign_channel_announcement.clone(), - on_accept: self.on_accept.clone(), - clone: self.clone.clone(), - free: self.free.clone(), - } + ChannelKeys_clone(self) } } @@ -591,6 +599,10 @@ impl Clone for InMemoryChannelKeys { pub(crate) extern "C" fn InMemoryChannelKeys_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeInMemoryChannelKeys)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn InMemoryChannelKeys_clone(orig: &InMemoryChannelKeys) -> InMemoryChannelKeys { + InMemoryChannelKeys { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Private key of anchor tx #[no_mangle] pub extern "C" fn InMemoryChannelKeys_get_funding_key(this_ptr: &InMemoryChannelKeys) -> *const [u8; 32] { diff --git a/lightning-c-bindings/src/chain/mod.rs b/lightning-c-bindings/src/chain/mod.rs index cbfa6074..6ea4d99d 100644 --- a/lightning-c-bindings/src/chain/mod.rs +++ b/lightning-c-bindings/src/chain/mod.rs @@ -52,6 +52,10 @@ impl AccessError { } } } +#[no_mangle] +pub extern "C" fn AccessError_clone(orig: &AccessError) -> AccessError { + orig.clone() +} /// The `Access` trait defines behavior for accessing chain data and state, such as blocks and /// UTXOs. #[repr(C)] diff --git a/lightning-c-bindings/src/chain/transaction.rs b/lightning-c-bindings/src/chain/transaction.rs index 9d099cb6..3a35c472 100644 --- a/lightning-c-bindings/src/chain/transaction.rs +++ b/lightning-c-bindings/src/chain/transaction.rs @@ -58,6 +58,10 @@ impl Clone for OutPoint { pub(crate) extern "C" fn OutPoint_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeOutPoint)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn OutPoint_clone(orig: &OutPoint) -> OutPoint { + OutPoint { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The referenced transaction's txid. #[no_mangle] pub extern "C" fn OutPoint_get_txid(this_ptr: &OutPoint) -> *const [u8; 32] { diff --git a/lightning-c-bindings/src/ln/chan_utils.rs b/lightning-c-bindings/src/ln/chan_utils.rs index 038ad71c..f9e6c407 100644 --- a/lightning-c-bindings/src/ln/chan_utils.rs +++ b/lightning-c-bindings/src/ln/chan_utils.rs @@ -133,6 +133,10 @@ impl Clone for TxCreationKeys { pub(crate) extern "C" fn TxCreationKeys_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeTxCreationKeys)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn TxCreationKeys_clone(orig: &TxCreationKeys) -> TxCreationKeys { + TxCreationKeys { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The broadcaster's per-commitment public key which was used to derive the other keys. #[no_mangle] pub extern "C" fn TxCreationKeys_get_per_commitment_point(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { @@ -256,6 +260,23 @@ impl PreCalculatedTxCreationKeys { ret } } +impl Clone for PreCalculatedTxCreationKeys { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn PreCalculatedTxCreationKeys_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativePreCalculatedTxCreationKeys)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn PreCalculatedTxCreationKeys_clone(orig: &PreCalculatedTxCreationKeys) -> PreCalculatedTxCreationKeys { + PreCalculatedTxCreationKeys { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Create a new PreCalculatedTxCreationKeys from TxCreationKeys #[must_use] #[no_mangle] @@ -332,6 +353,10 @@ impl Clone for ChannelPublicKeys { pub(crate) extern "C" fn ChannelPublicKeys_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelPublicKeys)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelPublicKeys_clone(orig: &ChannelPublicKeys) -> ChannelPublicKeys { + ChannelPublicKeys { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The public key which is used to sign all commitment transactions, as it appears in the /// on-chain channel lock-in 2-of-2 multisig output. #[no_mangle] @@ -497,6 +522,10 @@ impl Clone for HTLCOutputInCommitment { pub(crate) extern "C" fn HTLCOutputInCommitment_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeHTLCOutputInCommitment)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn HTLCOutputInCommitment_clone(orig: &HTLCOutputInCommitment) -> HTLCOutputInCommitment { + HTLCOutputInCommitment { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Whether the HTLC was \"offered\" (ie outbound in relation to this commitment transaction). /// Note that this is not the same as whether it is ountbound *from us*. To determine that you /// need to compare this value to whether the commitment transaction in question is that of @@ -638,6 +667,10 @@ impl Clone for HolderCommitmentTransaction { pub(crate) extern "C" fn HolderCommitmentTransaction_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeHolderCommitmentTransaction)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn HolderCommitmentTransaction_clone(orig: &HolderCommitmentTransaction) -> HolderCommitmentTransaction { + HolderCommitmentTransaction { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The commitment transaction itself, in unsigned form. #[no_mangle] pub extern "C" fn HolderCommitmentTransaction_get_unsigned_tx(this_ptr: &HolderCommitmentTransaction) -> crate::c_types::Transaction { diff --git a/lightning-c-bindings/src/ln/channelmanager.rs b/lightning-c-bindings/src/ln/channelmanager.rs index 7d9028a5..c21f26e9 100644 --- a/lightning-c-bindings/src/ln/channelmanager.rs +++ b/lightning-c-bindings/src/ln/channelmanager.rs @@ -124,6 +124,23 @@ impl ChannelDetails { ret } } +impl Clone for ChannelDetails { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn ChannelDetails_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelDetails)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn ChannelDetails_clone(orig: &ChannelDetails) -> ChannelDetails { + ChannelDetails { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel's ID (prior to funding transaction generation, this is a random 32 bytes, /// thereafter this is the txid of the funding transaction xor the funding transaction output). /// Note that this means this value is *not* persistent - it can change once during the diff --git a/lightning-c-bindings/src/ln/msgs.rs b/lightning-c-bindings/src/ln/msgs.rs index 6925139d..401da377 100644 --- a/lightning-c-bindings/src/ln/msgs.rs +++ b/lightning-c-bindings/src/ln/msgs.rs @@ -95,6 +95,23 @@ impl Init { ret } } +impl Clone for Init { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn Init_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeInit)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn Init_clone(orig: &Init) -> Init { + Init { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} use lightning::ln::msgs::ErrorMessage as nativeErrorMessageImport; type nativeErrorMessage = nativeErrorMessageImport; @@ -146,6 +163,10 @@ impl Clone for ErrorMessage { pub(crate) extern "C" fn ErrorMessage_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeErrorMessage)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ErrorMessage_clone(orig: &ErrorMessage) -> ErrorMessage { + ErrorMessage { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID involved in the error #[no_mangle] pub extern "C" fn ErrorMessage_get_channel_id(this_ptr: &ErrorMessage) -> *const [u8; 32] { @@ -220,6 +241,23 @@ impl Ping { ret } } +impl Clone for Ping { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn Ping_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativePing)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn Ping_clone(orig: &Ping) -> Ping { + Ping { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The desired response length #[no_mangle] pub extern "C" fn Ping_get_ponglen(this_ptr: &Ping) -> u16 { @@ -290,6 +328,23 @@ impl Pong { ret } } +impl Clone for Pong { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn Pong_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativePong)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn Pong_clone(orig: &Pong) -> Pong { + Pong { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The pong packet size. /// This field is not sent on the wire. byteslen zeros are sent. #[no_mangle] @@ -361,6 +416,10 @@ impl Clone for OpenChannel { pub(crate) extern "C" fn OpenChannel_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeOpenChannel)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn OpenChannel_clone(orig: &OpenChannel) -> OpenChannel { + OpenChannel { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain where the channel is to be opened #[no_mangle] pub extern "C" fn OpenChannel_get_chain_hash(this_ptr: &OpenChannel) -> *const [u8; 32] { @@ -610,6 +669,10 @@ impl Clone for AcceptChannel { pub(crate) extern "C" fn AcceptChannel_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeAcceptChannel)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn AcceptChannel_clone(orig: &AcceptChannel) -> AcceptChannel { + AcceptChannel { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// A temporary channel ID, until the funding outpoint is announced #[no_mangle] pub extern "C" fn AcceptChannel_get_temporary_channel_id(this_ptr: &AcceptChannel) -> *const [u8; 32] { @@ -815,6 +878,10 @@ impl Clone for FundingCreated { pub(crate) extern "C" fn FundingCreated_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeFundingCreated)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn FundingCreated_clone(orig: &FundingCreated) -> FundingCreated { + FundingCreated { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// A temporary channel ID, until the funding is established #[no_mangle] pub extern "C" fn FundingCreated_get_temporary_channel_id(this_ptr: &FundingCreated) -> *const [u8; 32] { @@ -920,6 +987,10 @@ impl Clone for FundingSigned { pub(crate) extern "C" fn FundingSigned_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeFundingSigned)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn FundingSigned_clone(orig: &FundingSigned) -> FundingSigned { + FundingSigned { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn FundingSigned_get_channel_id(this_ptr: &FundingSigned) -> *const [u8; 32] { @@ -1001,6 +1072,10 @@ impl Clone for FundingLocked { pub(crate) extern "C" fn FundingLocked_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeFundingLocked)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn FundingLocked_clone(orig: &FundingLocked) -> FundingLocked { + FundingLocked { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn FundingLocked_get_channel_id(this_ptr: &FundingLocked) -> *const [u8; 32] { @@ -1082,6 +1157,10 @@ impl Clone for Shutdown { pub(crate) extern "C" fn Shutdown_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeShutdown)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn Shutdown_clone(orig: &Shutdown) -> Shutdown { + Shutdown { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn Shutdown_get_channel_id(this_ptr: &Shutdown) -> *const [u8; 32] { @@ -1165,6 +1244,10 @@ impl Clone for ClosingSigned { pub(crate) extern "C" fn ClosingSigned_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeClosingSigned)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ClosingSigned_clone(orig: &ClosingSigned) -> ClosingSigned { + ClosingSigned { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn ClosingSigned_get_channel_id(this_ptr: &ClosingSigned) -> *const [u8; 32] { @@ -1258,6 +1341,10 @@ impl Clone for UpdateAddHTLC { pub(crate) extern "C" fn UpdateAddHTLC_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUpdateAddHTLC)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UpdateAddHTLC_clone(orig: &UpdateAddHTLC) -> UpdateAddHTLC { + UpdateAddHTLC { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn UpdateAddHTLC_get_channel_id(this_ptr: &UpdateAddHTLC) -> *const [u8; 32] { @@ -1364,6 +1451,10 @@ impl Clone for UpdateFulfillHTLC { pub(crate) extern "C" fn UpdateFulfillHTLC_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUpdateFulfillHTLC)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UpdateFulfillHTLC_clone(orig: &UpdateFulfillHTLC) -> UpdateFulfillHTLC { + UpdateFulfillHTLC { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn UpdateFulfillHTLC_get_channel_id(this_ptr: &UpdateFulfillHTLC) -> *const [u8; 32] { @@ -1457,6 +1548,10 @@ impl Clone for UpdateFailHTLC { pub(crate) extern "C" fn UpdateFailHTLC_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUpdateFailHTLC)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UpdateFailHTLC_clone(orig: &UpdateFailHTLC) -> UpdateFailHTLC { + UpdateFailHTLC { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn UpdateFailHTLC_get_channel_id(this_ptr: &UpdateFailHTLC) -> *const [u8; 32] { @@ -1530,6 +1625,10 @@ impl Clone for UpdateFailMalformedHTLC { pub(crate) extern "C" fn UpdateFailMalformedHTLC_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUpdateFailMalformedHTLC)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UpdateFailMalformedHTLC_clone(orig: &UpdateFailMalformedHTLC) -> UpdateFailMalformedHTLC { + UpdateFailMalformedHTLC { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn UpdateFailMalformedHTLC_get_channel_id(this_ptr: &UpdateFailMalformedHTLC) -> *const [u8; 32] { @@ -1614,6 +1713,10 @@ impl Clone for CommitmentSigned { pub(crate) extern "C" fn CommitmentSigned_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeCommitmentSigned)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn CommitmentSigned_clone(orig: &CommitmentSigned) -> CommitmentSigned { + CommitmentSigned { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn CommitmentSigned_get_channel_id(this_ptr: &CommitmentSigned) -> *const [u8; 32] { @@ -1703,6 +1806,10 @@ impl Clone for RevokeAndACK { pub(crate) extern "C" fn RevokeAndACK_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRevokeAndACK)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn RevokeAndACK_clone(orig: &RevokeAndACK) -> RevokeAndACK { + RevokeAndACK { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn RevokeAndACK_get_channel_id(this_ptr: &RevokeAndACK) -> *const [u8; 32] { @@ -1796,6 +1903,10 @@ impl Clone for UpdateFee { pub(crate) extern "C" fn UpdateFee_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUpdateFee)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UpdateFee_clone(orig: &UpdateFee) -> UpdateFee { + UpdateFee { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn UpdateFee_get_channel_id(this_ptr: &UpdateFee) -> *const [u8; 32] { @@ -1880,6 +1991,10 @@ impl Clone for DataLossProtect { pub(crate) extern "C" fn DataLossProtect_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeDataLossProtect)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn DataLossProtect_clone(orig: &DataLossProtect) -> DataLossProtect { + DataLossProtect { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Proof that the sender knows the per-commitment secret of a specific commitment transaction /// belonging to the recipient #[no_mangle] @@ -1963,6 +2078,10 @@ impl Clone for ChannelReestablish { pub(crate) extern "C" fn ChannelReestablish_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelReestablish)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelReestablish_clone(orig: &ChannelReestablish) -> ChannelReestablish { + ChannelReestablish { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn ChannelReestablish_get_channel_id(this_ptr: &ChannelReestablish) -> *const [u8; 32] { @@ -2047,6 +2166,10 @@ impl Clone for AnnouncementSignatures { pub(crate) extern "C" fn AnnouncementSignatures_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeAnnouncementSignatures)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn AnnouncementSignatures_clone(orig: &AnnouncementSignatures) -> AnnouncementSignatures { + AnnouncementSignatures { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The channel ID #[no_mangle] pub extern "C" fn AnnouncementSignatures_get_channel_id(this_ptr: &AnnouncementSignatures) -> *const [u8; 32] { @@ -2280,6 +2403,10 @@ impl NetAddress { } #[no_mangle] pub extern "C" fn NetAddress_free(this_ptr: NetAddress) { } +#[no_mangle] +pub extern "C" fn NetAddress_clone(orig: &NetAddress) -> NetAddress { + orig.clone() +} use lightning::ln::msgs::UnsignedNodeAnnouncement as nativeUnsignedNodeAnnouncementImport; type nativeUnsignedNodeAnnouncement = nativeUnsignedNodeAnnouncementImport; @@ -2331,6 +2458,10 @@ impl Clone for UnsignedNodeAnnouncement { pub(crate) extern "C" fn UnsignedNodeAnnouncement_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUnsignedNodeAnnouncement)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UnsignedNodeAnnouncement_clone(orig: &UnsignedNodeAnnouncement) -> UnsignedNodeAnnouncement { + UnsignedNodeAnnouncement { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The advertised features #[no_mangle] pub extern "C" fn UnsignedNodeAnnouncement_get_features(this_ptr: &UnsignedNodeAnnouncement) -> crate::ln::features::NodeFeatures { @@ -2447,6 +2578,10 @@ impl Clone for NodeAnnouncement { pub(crate) extern "C" fn NodeAnnouncement_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeNodeAnnouncement)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn NodeAnnouncement_clone(orig: &NodeAnnouncement) -> NodeAnnouncement { + NodeAnnouncement { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The signature by the node key #[no_mangle] pub extern "C" fn NodeAnnouncement_get_signature(this_ptr: &NodeAnnouncement) -> crate::c_types::Signature { @@ -2528,6 +2663,10 @@ impl Clone for UnsignedChannelAnnouncement { pub(crate) extern "C" fn UnsignedChannelAnnouncement_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUnsignedChannelAnnouncement)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UnsignedChannelAnnouncement_clone(orig: &UnsignedChannelAnnouncement) -> UnsignedChannelAnnouncement { + UnsignedChannelAnnouncement { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The advertised channel features #[no_mangle] pub extern "C" fn UnsignedChannelAnnouncement_get_features(this_ptr: &UnsignedChannelAnnouncement) -> crate::ln::features::ChannelFeatures { @@ -2656,6 +2795,10 @@ impl Clone for ChannelAnnouncement { pub(crate) extern "C" fn ChannelAnnouncement_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelAnnouncement)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelAnnouncement_clone(orig: &ChannelAnnouncement) -> ChannelAnnouncement { + ChannelAnnouncement { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Authentication of the announcement by the first public node #[no_mangle] pub extern "C" fn ChannelAnnouncement_get_node_signature_1(this_ptr: &ChannelAnnouncement) -> crate::c_types::Signature { @@ -2773,6 +2916,10 @@ impl Clone for UnsignedChannelUpdate { pub(crate) extern "C" fn UnsignedChannelUpdate_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUnsignedChannelUpdate)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UnsignedChannelUpdate_clone(orig: &UnsignedChannelUpdate) -> UnsignedChannelUpdate { + UnsignedChannelUpdate { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain where the channel is to be opened #[no_mangle] pub extern "C" fn UnsignedChannelUpdate_get_chain_hash(this_ptr: &UnsignedChannelUpdate) -> *const [u8; 32] { @@ -2912,6 +3059,10 @@ impl Clone for ChannelUpdate { pub(crate) extern "C" fn ChannelUpdate_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelUpdate)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelUpdate_clone(orig: &ChannelUpdate) -> ChannelUpdate { + ChannelUpdate { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// A signature of the channel update #[no_mangle] pub extern "C" fn ChannelUpdate_get_signature(this_ptr: &ChannelUpdate) -> crate::c_types::Signature { @@ -2996,6 +3147,10 @@ impl Clone for QueryChannelRange { pub(crate) extern "C" fn QueryChannelRange_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeQueryChannelRange)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn QueryChannelRange_clone(orig: &QueryChannelRange) -> QueryChannelRange { + QueryChannelRange { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain being queried #[no_mangle] pub extern "C" fn QueryChannelRange_get_chain_hash(this_ptr: &QueryChannelRange) -> *const [u8; 32] { @@ -3095,6 +3250,10 @@ impl Clone for ReplyChannelRange { pub(crate) extern "C" fn ReplyChannelRange_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeReplyChannelRange)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ReplyChannelRange_clone(orig: &ReplyChannelRange) -> ReplyChannelRange { + ReplyChannelRange { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain being queried #[no_mangle] pub extern "C" fn ReplyChannelRange_get_chain_hash(this_ptr: &ReplyChannelRange) -> *const [u8; 32] { @@ -3217,6 +3376,10 @@ impl Clone for QueryShortChannelIds { pub(crate) extern "C" fn QueryShortChannelIds_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeQueryShortChannelIds)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn QueryShortChannelIds_clone(orig: &QueryShortChannelIds) -> QueryShortChannelIds { + QueryShortChannelIds { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain being queried #[no_mangle] pub extern "C" fn QueryShortChannelIds_get_chain_hash(this_ptr: &QueryShortChannelIds) -> *const [u8; 32] { @@ -3297,6 +3460,10 @@ impl Clone for ReplyShortChannelIdsEnd { pub(crate) extern "C" fn ReplyShortChannelIdsEnd_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeReplyShortChannelIdsEnd)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ReplyShortChannelIdsEnd_clone(orig: &ReplyShortChannelIdsEnd) -> ReplyShortChannelIdsEnd { + ReplyShortChannelIdsEnd { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain that was queried #[no_mangle] pub extern "C" fn ReplyShortChannelIdsEnd_get_chain_hash(this_ptr: &ReplyShortChannelIdsEnd) -> *const [u8; 32] { @@ -3382,6 +3549,10 @@ impl Clone for GossipTimestampFilter { pub(crate) extern "C" fn GossipTimestampFilter_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeGossipTimestampFilter)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn GossipTimestampFilter_clone(orig: &GossipTimestampFilter) -> GossipTimestampFilter { + GossipTimestampFilter { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The genesis hash of the blockchain for channel and node information #[no_mangle] pub extern "C" fn GossipTimestampFilter_get_chain_hash(this_ptr: &GossipTimestampFilter) -> *const [u8; 32] { @@ -3517,6 +3688,10 @@ impl ErrorAction { } #[no_mangle] pub extern "C" fn ErrorAction_free(this_ptr: ErrorAction) { } +#[no_mangle] +pub extern "C" fn ErrorAction_clone(orig: &ErrorAction) -> ErrorAction { + orig.clone() +} use lightning::ln::msgs::LightningError as nativeLightningErrorImport; type nativeLightningError = nativeLightningErrorImport; @@ -3637,6 +3812,10 @@ impl Clone for CommitmentUpdate { pub(crate) extern "C" fn CommitmentUpdate_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeCommitmentUpdate)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn CommitmentUpdate_clone(orig: &CommitmentUpdate) -> CommitmentUpdate { + CommitmentUpdate { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// update_add_htlc messages which should be sent #[no_mangle] pub extern "C" fn CommitmentUpdate_set_update_add_htlcs(this_ptr: &mut CommitmentUpdate, mut val: crate::c_types::derived::CVec_UpdateAddHTLCZ) { @@ -3827,6 +4006,10 @@ impl HTLCFailChannelUpdate { } #[no_mangle] pub extern "C" fn HTLCFailChannelUpdate_free(this_ptr: HTLCFailChannelUpdate) { } +#[no_mangle] +pub extern "C" fn HTLCFailChannelUpdate_clone(orig: &HTLCFailChannelUpdate) -> HTLCFailChannelUpdate { + orig.clone() +} /// A trait to describe an object which can receive channel messages. /// /// Messages MAY be called in parallel when they originate from different their_node_ids, however diff --git a/lightning-c-bindings/src/ln/peer_handler.rs b/lightning-c-bindings/src/ln/peer_handler.rs index e4c8b59b..50e1c369 100644 --- a/lightning-c-bindings/src/ln/peer_handler.rs +++ b/lightning-c-bindings/src/ln/peer_handler.rs @@ -118,29 +118,33 @@ pub struct SocketDescriptor { /// though races may occur whereby disconnect_socket is called after a call to /// socket_disconnected but prior to socket_disconnected returning. pub disconnect_socket: extern "C" fn (this_arg: *mut c_void), - pub eq: extern "C" fn (this_arg: *const c_void, other_arg: *const c_void) -> bool, + pub eq: extern "C" fn (this_arg: *const c_void, other_arg: &SocketDescriptor) -> bool, pub hash: extern "C" fn (this_arg: *const c_void) -> u64, pub clone: Option *mut c_void>, pub free: Option, } impl std::cmp::Eq for SocketDescriptor {} impl std::cmp::PartialEq for SocketDescriptor { - fn eq(&self, o: &Self) -> bool { (self.eq)(self.this_arg, o.this_arg) } + fn eq(&self, o: &Self) -> bool { (self.eq)(self.this_arg, o) } } impl std::hash::Hash for SocketDescriptor { fn hash(&self, hasher: &mut H) { hasher.write_u64((self.hash)(self.this_arg)) } } +#[no_mangle] +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(), + } +} impl Clone for SocketDescriptor { fn clone(&self) -> Self { - Self { - this_arg: if let Some(f) = self.clone { (f)(self.this_arg) } else { self.this_arg }, - send_data: self.send_data.clone(), - disconnect_socket: self.disconnect_socket.clone(), - eq: self.eq.clone(), - hash: self.hash.clone(), - clone: self.clone.clone(), - free: self.free.clone(), - } + SocketDescriptor_clone(self) } } diff --git a/lightning-c-bindings/src/routing/network_graph.rs b/lightning-c-bindings/src/routing/network_graph.rs index c2930f0f..11eb92a3 100644 --- a/lightning-c-bindings/src/routing/network_graph.rs +++ b/lightning-c-bindings/src/routing/network_graph.rs @@ -517,6 +517,10 @@ impl Clone for RoutingFees { pub(crate) extern "C" fn RoutingFees_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRoutingFees)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn RoutingFees_clone(orig: &RoutingFees) -> RoutingFees { + RoutingFees { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Flat routing fee in satoshis #[no_mangle] pub extern "C" fn RoutingFees_get_base_msat(this_ptr: &RoutingFees) -> u32 { diff --git a/lightning-c-bindings/src/routing/router.rs b/lightning-c-bindings/src/routing/router.rs index 2195fe47..8be95283 100644 --- a/lightning-c-bindings/src/routing/router.rs +++ b/lightning-c-bindings/src/routing/router.rs @@ -58,6 +58,10 @@ impl Clone for RouteHop { pub(crate) extern "C" fn RouteHop_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRouteHop)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn RouteHop_clone(orig: &RouteHop) -> RouteHop { + RouteHop { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The node_id of the node at this hop. #[no_mangle] pub extern "C" fn RouteHop_get_pubkey(this_ptr: &RouteHop) -> crate::c_types::PublicKey { @@ -194,6 +198,10 @@ impl Clone for Route { pub(crate) extern "C" fn Route_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRoute)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn Route_clone(orig: &Route) -> Route { + Route { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The list of routes taken for a single (potentially-)multi-part payment. The pubkey of the /// last RouteHop in each path must be the same. /// Each entry represents a list of hops, NOT INCLUDING our own, where the last hop is the @@ -263,6 +271,23 @@ impl RouteHint { ret } } +impl Clone for RouteHint { + fn clone(&self) -> Self { + Self { + inner: Box::into_raw(Box::new(unsafe { &*self.inner }.clone())), + is_owned: true, + } + } +} +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +pub(crate) extern "C" fn RouteHint_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRouteHint)).clone() })) as *mut c_void +} +#[no_mangle] +pub extern "C" fn RouteHint_clone(orig: &RouteHint) -> RouteHint { + RouteHint { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// The node_id of the non-target end of the route #[no_mangle] pub extern "C" fn RouteHint_get_src_node_id(this_ptr: &RouteHint) -> crate::c_types::PublicKey { diff --git a/lightning-c-bindings/src/util/config.rs b/lightning-c-bindings/src/util/config.rs index 30a42708..346ddc34 100644 --- a/lightning-c-bindings/src/util/config.rs +++ b/lightning-c-bindings/src/util/config.rs @@ -58,6 +58,10 @@ impl Clone for ChannelHandshakeConfig { pub(crate) extern "C" fn ChannelHandshakeConfig_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelHandshakeConfig)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelHandshakeConfig_clone(orig: &ChannelHandshakeConfig) -> ChannelHandshakeConfig { + ChannelHandshakeConfig { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Confirmations we will wait for before considering the channel locked in. /// Applied only for inbound channels (see ChannelHandshakeLimits::max_minimum_depth for the /// equivalent limit applied to outbound channels). @@ -208,6 +212,10 @@ impl Clone for ChannelHandshakeLimits { pub(crate) extern "C" fn ChannelHandshakeLimits_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelHandshakeLimits)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelHandshakeLimits_clone(orig: &ChannelHandshakeLimits) -> ChannelHandshakeLimits { + ChannelHandshakeLimits { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Minimum allowed satoshis when a channel is funded, this is supplied by the sender and so /// only applies to inbound channels. /// @@ -477,6 +485,10 @@ impl Clone for ChannelConfig { pub(crate) extern "C" fn ChannelConfig_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeChannelConfig)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn ChannelConfig_clone(orig: &ChannelConfig) -> ChannelConfig { + ChannelConfig { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi. /// This may be allowed to change at runtime in a later update, however doing so must result in /// update messages sent to notify all nodes of our updated relay fee. @@ -638,6 +650,10 @@ impl Clone for UserConfig { pub(crate) extern "C" fn UserConfig_clone_void(this_ptr: *const c_void) -> *mut c_void { Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeUserConfig)).clone() })) as *mut c_void } +#[no_mangle] +pub extern "C" fn UserConfig_clone(orig: &UserConfig) -> UserConfig { + UserConfig { inner: Box::into_raw(Box::new(unsafe { &*orig.inner }.clone())), is_owned: true } +} /// Channel config that we propose to our counterparty. #[no_mangle] pub extern "C" fn UserConfig_get_own_channel_config(this_ptr: &UserConfig) -> crate::util::config::ChannelHandshakeConfig { diff --git a/lightning-c-bindings/src/util/errors.rs b/lightning-c-bindings/src/util/errors.rs index 06cb4a7f..9b0e757d 100644 --- a/lightning-c-bindings/src/util/errors.rs +++ b/lightning-c-bindings/src/util/errors.rs @@ -160,3 +160,7 @@ impl APIError { } #[no_mangle] pub extern "C" fn APIError_free(this_ptr: APIError) { } +#[no_mangle] +pub extern "C" fn APIError_clone(orig: &APIError) -> APIError { + orig.clone() +} diff --git a/lightning-c-bindings/src/util/events.rs b/lightning-c-bindings/src/util/events.rs index db8ac33f..e596774b 100644 --- a/lightning-c-bindings/src/util/events.rs +++ b/lightning-c-bindings/src/util/events.rs @@ -308,6 +308,10 @@ impl Event { } #[no_mangle] pub extern "C" fn Event_free(this_ptr: Event) { } +#[no_mangle] +pub extern "C" fn Event_clone(orig: &Event) -> Event { + orig.clone() +} /// An event generated by ChannelManager which indicates a message should be sent to a peer (or /// broadcast to most peers). /// These events are handled by PeerManager::process_events if you are using a PeerManager. @@ -859,6 +863,10 @@ impl MessageSendEvent { } #[no_mangle] pub extern "C" fn MessageSendEvent_free(this_ptr: MessageSendEvent) { } +#[no_mangle] +pub extern "C" fn MessageSendEvent_clone(orig: &MessageSendEvent) -> MessageSendEvent { + orig.clone() +} /// A trait indicating an object may generate message send events #[repr(C)] pub struct MessageSendEventsProvider { diff --git a/lightning-c-bindings/src/util/logger.rs b/lightning-c-bindings/src/util/logger.rs index ae20abbb..8a1fbb15 100644 --- a/lightning-c-bindings/src/util/logger.rs +++ b/lightning-c-bindings/src/util/logger.rs @@ -74,6 +74,10 @@ impl Level { } } } +#[no_mangle] +pub extern "C" fn Level_clone(orig: &Level) -> Level { + orig.clone() +} /// Returns the most verbose logging level. #[must_use] #[no_mangle] diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 469837f0..13a0a883 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -194,11 +194,18 @@ where C::Target: chain::Filter, match monitors.get_mut(&funding_txo) { None => { log_error!(self.logger, "Failed to update channel monitor: no such monitor registered"); + + // We should never ever trigger this from within ChannelManager. Technically a + // user could use this object with some proxying in between which makes this + // possible, but in tests and fuzzing, this should be a panic. + #[cfg(any(test, feature = "fuzztarget"))] + panic!("ChannelManager generated a channel update for a channel that was not yet registered!"); + #[cfg(not(any(test, feature = "fuzztarget")))] Err(ChannelMonitorUpdateErr::PermanentFailure) }, Some(orig_monitor) => { log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor)); - let update_res = orig_monitor.update_monitor(&update, &self.broadcaster, &self.logger); + let update_res = orig_monitor.update_monitor(&update, &self.broadcaster, &self.fee_estimator, &self.logger); if let Err(e) = &update_res { log_error!(self.logger, "Failed to update channel monitor: {:?}", e); } diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 889dfa21..c3382caa 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -64,14 +64,29 @@ pub struct ChannelMonitorUpdate { pub(crate) updates: Vec, /// The sequence number of this update. Updates *must* be replayed in-order according to this /// sequence number (and updates may panic if they are not). The update_id values are strictly - /// increasing and increase by one for each new update. + /// increasing and increase by one for each new update, with one exception specified below. /// /// This sequence number is also used to track up to which points updates which returned /// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given /// ChannelMonitor when ChannelManager::channel_monitor_updated is called. + /// + /// The only instance where update_id values are not strictly increasing is the case where we + /// allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See + /// its docs for more details. + /// + /// [`CLOSED_CHANNEL_UPDATE_ID`]: constant.CLOSED_CHANNEL_UPDATE_ID.html pub update_id: u64, } +/// If: +/// (1) a channel has been force closed and +/// (2) we receive a preimage from a forward link that allows us to spend an HTLC output on +/// this channel's (the backward link's) broadcasted commitment transaction +/// then we allow the `ChannelManager` to send a `ChannelMonitorUpdate` with this update ID, +/// with the update providing said payment preimage. No other update types are allowed after +/// force-close. +pub const CLOSED_CHANNEL_UPDATE_ID: u64 = std::u64::MAX; + impl Writeable for ChannelMonitorUpdate { fn write(&self, w: &mut W) -> Result<(), ::std::io::Error> { self.update_id.write(w)?; @@ -164,7 +179,7 @@ pub enum ChannelMonitorUpdateErr { pub struct MonitorUpdateError(pub &'static str); /// An event to be processed by the ChannelManager. -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum MonitorEvent { /// A monitor event containing an HTLCUpdate. HTLCEvent(HTLCUpdate), @@ -1144,8 +1159,47 @@ impl ChannelMonitor { /// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all /// commitment_tx_infos which contain the payment hash have been revoked. - pub(crate) fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage) { + pub(crate) fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L) + where B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone()); + + // If the channel is force closed, try to claim the output from this preimage. + // First check if a counterparty commitment transaction has been broadcasted: + macro_rules! claim_htlcs { + ($commitment_number: expr, $txid: expr) => { + let htlc_claim_reqs = self.get_counterparty_htlc_output_claim_reqs($commitment_number, $txid, None); + self.onchain_tx_handler.update_claims_view(&Vec::new(), htlc_claim_reqs, None, broadcaster, fee_estimator, logger); + } + } + if let Some(txid) = self.current_counterparty_commitment_txid { + if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { + claim_htlcs!(*commitment_number, txid); + return; + } + } + if let Some(txid) = self.prev_counterparty_commitment_txid { + if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { + claim_htlcs!(*commitment_number, txid); + return; + } + } + + // Then if a holder commitment transaction has been seen on-chain, broadcast transactions + // claiming the HTLC output from each of the holder commitment transactions. + // Note that we can't just use `self.holder_tx_signed`, because that only covers the case where + // *we* sign a holder commitment transaction, not when e.g. a watchtower broadcasts one of our + // holder commitment transactions. + if self.broadcasted_holder_revokable_script.is_some() { + let (claim_reqs, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx); + self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, None, broadcaster, fee_estimator, logger); + if let Some(ref tx) = self.prev_holder_signed_commitment_tx { + let (claim_reqs, _) = self.get_broadcasted_holder_claims(&tx); + self.onchain_tx_handler.update_claims_view(&Vec::new(), claim_reqs, None, broadcaster, fee_estimator, logger); + } + } } pub(crate) fn broadcast_latest_holder_commitment_txn(&mut self, broadcaster: &B, logger: &L) @@ -1162,26 +1216,45 @@ impl ChannelMonitor { /// itself. /// /// panics if the given update is not the next update by update_id. - pub fn update_monitor(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, logger: &L) -> Result<(), MonitorUpdateError> - where B::Target: BroadcasterInterface, - L::Target: Logger, + pub fn update_monitor(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), MonitorUpdateError> + where B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, { - if self.latest_update_id + 1 != updates.update_id { + // ChannelMonitor updates may be applied after force close if we receive a + // preimage for a broadcasted commitment transaction HTLC output that we'd + // like to claim on-chain. If this is the case, we no longer have guaranteed + // access to the monitor's update ID, so we use a sentinel value instead. + if updates.update_id == CLOSED_CHANNEL_UPDATE_ID { + match updates.updates[0] { + ChannelMonitorUpdateStep::PaymentPreimage { .. } => {}, + _ => panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage"), + } + assert_eq!(updates.updates.len(), 1); + } else if self.latest_update_id + 1 != updates.update_id { panic!("Attempted to apply ChannelMonitorUpdates out of order, check the update_id before passing an update to update_monitor!"); } for update in updates.updates.iter() { match update { ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs } => { + log_trace!(logger, "Updating ChannelMonitor with latest holder commitment transaction info"); if self.lockdown_from_offchain { panic!(); } self.provide_latest_holder_commitment_tx_info(commitment_tx.clone(), htlc_outputs.clone())? }, - ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } => - self.provide_latest_counterparty_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs.clone(), *commitment_number, *their_revocation_point, logger), - ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => - self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage), - ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => - self.provide_secret(*idx, *secret)?, + ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } => { + log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info"); + self.provide_latest_counterparty_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs.clone(), *commitment_number, *their_revocation_point, logger) + }, + ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => { + log_trace!(logger, "Updating ChannelMonitor with payment preimage"); + self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, fee_estimator, logger) + }, + ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => { + log_trace!(logger, "Updating ChannelMonitor with commitment secret"); + self.provide_secret(*idx, *secret)? + }, ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } => { + log_trace!(logger, "Updating ChannelMonitor: channel force closed, should broadcast: {}", should_broadcast); self.lockdown_from_offchain = true; if *should_broadcast { self.broadcast_latest_holder_commitment_txn(broadcaster, logger); @@ -1425,39 +1498,55 @@ impl ChannelMonitor { check_htlc_fails!(txid, "previous", 'prev_loop); } + let htlc_claim_reqs = self.get_counterparty_htlc_output_claim_reqs(commitment_number, commitment_txid, Some(tx)); + for req in htlc_claim_reqs { + claimable_outpoints.push(req); + } + + } + (claimable_outpoints, (commitment_txid, watch_outputs)) + } + + fn get_counterparty_htlc_output_claim_reqs(&self, commitment_number: u64, commitment_txid: Txid, tx: Option<&Transaction>) -> Vec { + let mut claims = Vec::new(); + if let Some(htlc_outputs) = self.counterparty_claimable_outpoints.get(&commitment_txid) { if let Some(revocation_points) = self.their_cur_revocation_points { let revocation_point_option = + // If the counterparty commitment tx is the latest valid state, use their latest + // per-commitment point if revocation_points.0 == commitment_number { Some(&revocation_points.1) } else if let Some(point) = revocation_points.2.as_ref() { + // If counterparty commitment tx is the state previous to the latest valid state, use + // their previous per-commitment point (non-atomicity of revocation means it's valid for + // them to temporarily have two valid commitment txns from our viewpoint) if revocation_points.0 == commitment_number + 1 { Some(point) } else { None } } else { None }; if let Some(revocation_point) = revocation_point_option { - self.counterparty_payment_script = { - // Note that the Network here is ignored as we immediately drop the address for the - // script_pubkey version - let payment_hash160 = WPubkeyHash::hash(&self.keys.pubkeys().payment_point.serialize()); - Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script() - }; - - // Then, try to find htlc outputs - for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() { + for (_, &(ref htlc, _)) in htlc_outputs.iter().enumerate() { if let Some(transaction_output_index) = htlc.transaction_output_index { - if transaction_output_index as usize >= tx.output.len() || - tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 { - return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user + if let Some(transaction) = tx { + if transaction_output_index as usize >= transaction.output.len() || + transaction.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 { + return claims; // Corrupted per_commitment_data, fuck this user + } } - let preimage = if htlc.offered { if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { Some(*p) } else { None } } else { None }; + let preimage = + if htlc.offered { + if let Some(p) = self.payment_preimages.get(&htlc.payment_hash) { + Some(*p) + } else { None } + } else { None }; let aggregable = if !htlc.offered { false } else { true }; if preimage.is_some() || !htlc.offered { let witness_data = InputMaterial::CounterpartyHTLC { per_commitment_point: *revocation_point, counterparty_delayed_payment_base_key: self.counterparty_tx_cache.counterparty_delayed_payment_base_key, counterparty_htlc_base_key: self.counterparty_tx_cache.counterparty_htlc_base_key, preimage, htlc: htlc.clone() }; - claimable_outpoints.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data }); + claims.push(ClaimRequest { absolute_timelock: htlc.cltv_expiry, aggregable, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: transaction_output_index }, witness_data }); } } } } } } - (claimable_outpoints, (commitment_txid, watch_outputs)) + claims } /// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key @@ -1487,9 +1576,11 @@ impl ChannelMonitor { (claimable_outpoints, Some((htlc_txid, outputs))) } - fn broadcast_by_holder_state(&self, commitment_tx: &Transaction, holder_tx: &HolderSignedTx) -> (Vec, Vec<(u32, TxOut)>, Option<(Script, PublicKey, PublicKey)>) { + // Returns (1) `ClaimRequest`s that can be given to the OnChainTxHandler, so that the handler can + // broadcast transactions claiming holder HTLC commitment outputs and (2) a holder revokable + // script so we can detect whether a holder transaction has been seen on-chain. + fn get_broadcasted_holder_claims(&self, holder_tx: &HolderSignedTx) -> (Vec, Option<(Script, PublicKey, PublicKey)>) { let mut claim_requests = Vec::with_capacity(holder_tx.htlc_outputs.len()); - let mut watch_outputs = Vec::with_capacity(holder_tx.htlc_outputs.len()); let redeemscript = chan_utils::get_revokeable_redeemscript(&holder_tx.revocation_key, self.on_holder_tx_csv, &holder_tx.delayed_payment_key); let broadcasted_holder_revokable_script = Some((redeemscript.to_v0_p2wsh(), holder_tx.per_commitment_point.clone(), holder_tx.revocation_key.clone())); @@ -1508,11 +1599,21 @@ impl ChannelMonitor { } else { None }, amount: htlc.amount_msat, }}); - watch_outputs.push((transaction_output_index, commitment_tx.output[transaction_output_index as usize].clone())); } } - (claim_requests, watch_outputs, broadcasted_holder_revokable_script) + (claim_requests, broadcasted_holder_revokable_script) + } + + // Returns holder HTLC outputs to watch and react to in case of spending. + fn get_broadcasted_holder_watch_outputs(&self, holder_tx: &HolderSignedTx, commitment_tx: &Transaction) -> Vec<(u32, TxOut)> { + let mut watch_outputs = Vec::with_capacity(holder_tx.htlc_outputs.len()); + for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() { + if let Some(transaction_output_index) = htlc.transaction_output_index { + watch_outputs.push((transaction_output_index, commitment_tx.output[transaction_output_index as usize].clone())); + } + } + watch_outputs } /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet) @@ -1547,10 +1648,10 @@ impl ChannelMonitor { } macro_rules! append_onchain_update { - ($updates: expr) => { + ($updates: expr, $to_watch: expr) => { claim_requests = $updates.0; - watch_outputs.append(&mut $updates.1); - self.broadcasted_holder_revokable_script = $updates.2; + self.broadcasted_holder_revokable_script = $updates.1; + watch_outputs.append(&mut $to_watch); } } @@ -1560,14 +1661,16 @@ impl ChannelMonitor { if self.current_holder_commitment_tx.txid == commitment_txid { is_holder_tx = true; log_trace!(logger, "Got latest holder commitment tx broadcast, searching for available HTLCs to claim"); - let mut res = self.broadcast_by_holder_state(tx, &self.current_holder_commitment_tx); - append_onchain_update!(res); + let res = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx); + let mut to_watch = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, tx); + append_onchain_update!(res, to_watch); } else if let &Some(ref holder_tx) = &self.prev_holder_signed_commitment_tx { if holder_tx.txid == commitment_txid { is_holder_tx = true; log_trace!(logger, "Got previous holder commitment tx broadcast, searching for available HTLCs to claim"); - let mut res = self.broadcast_by_holder_state(tx, holder_tx); - append_onchain_update!(res); + let res = self.get_broadcasted_holder_claims(holder_tx); + let mut to_watch = self.get_broadcasted_holder_watch_outputs(holder_tx, tx); + append_onchain_update!(res, to_watch); } } @@ -1735,7 +1838,8 @@ impl ChannelMonitor { self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0)); if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript) { self.holder_tx_signed = true; - let (mut new_outpoints, new_outputs, _) = self.broadcast_by_holder_state(&commitment_tx, &self.current_holder_commitment_tx); + let (mut new_outpoints, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx); + let new_outputs = self.get_broadcasted_holder_watch_outputs(&self.current_holder_commitment_tx, &commitment_tx); if !new_outputs.is_empty() { watch_outputs.push((self.current_holder_commitment_tx.txid.clone(), new_outputs)); } @@ -1763,7 +1867,7 @@ impl ChannelMonitor { } } - self.onchain_tx_handler.block_connected(&txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger); + self.onchain_tx_handler.update_claims_view(&txn_matched, claimable_outpoints, Some(height), &&*broadcaster, &&*fee_estimator, &&*logger); self.last_block_hash = block_hash; // Determine new outputs to watch by comparing against previously known outputs to watch, @@ -2486,16 +2590,18 @@ mod tests { use ln::onchaintx::{OnchainTxHandler, InputDescriptors}; use ln::chan_utils; use ln::chan_utils::{HTLCOutputInCommitment, HolderCommitmentTransaction}; - use util::test_utils::TestLogger; + use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator}; use bitcoin::secp256k1::key::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; - use std::sync::Arc; + use std::sync::{Arc, Mutex}; use chain::keysinterface::InMemoryChannelKeys; #[test] fn test_prune_preimages() { let secp_ctx = Secp256k1::new(); let logger = Arc::new(TestLogger::new()); + let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}); + let fee_estimator = Arc::new(TestFeeEstimator { sat_per_kw: 253 }); let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() }; @@ -2571,7 +2677,7 @@ mod tests { monitor.provide_latest_counterparty_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger); monitor.provide_latest_counterparty_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger); for &(ref preimage, ref hash) in preimages.iter() { - monitor.provide_payment_preimage(hash, preimage); + monitor.provide_payment_preimage(hash, preimage, &broadcaster, &fee_estimator, &logger); } // Now provide a secret, pruning preimages 10-15 diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 540155a3..7b7d511d 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -318,6 +318,7 @@ impl_writeable!(TxCreationKeys, 33*6, /// in the signer. /// The pre-calculated keys are an optimization, because ChannelKeys has enough /// information to re-derive them. +#[derive(PartialEq, Clone)] pub struct PreCalculatedTxCreationKeys(TxCreationKeys); impl PreCalculatedTxCreationKeys { diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index c34fc6a3..abf2834c 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -4016,11 +4016,23 @@ impl Channel { _ => {} } } + let funding_txo = if let Some(funding_txo) = self.funding_txo { + // If we haven't yet exchanged funding signatures (ie channel_state < FundingSent), + // returning a channel monitor update here would imply a channel monitor update before + // we even registered the channel monitor to begin with, which is invalid. + // Thus, if we aren't actually at a point where we could conceivably broadcast the + // funding transaction, don't return a funding txo (which prevents providing the + // monitor update to the user, even if we return one). + // See test_duplicate_chan_id and test_pre_lockin_no_chan_closed_update for more. + if self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::ChannelFunded as u32 | ChannelState::ShutdownComplete as u32) != 0 { + Some(funding_txo.clone()) + } else { None } + } else { None }; self.channel_state = ChannelState::ShutdownComplete as u32; self.update_time_counter += 1; self.latest_monitor_update_id += 1; - (self.funding_txo.clone(), ChannelMonitorUpdate { + (funding_txo, ChannelMonitorUpdate { update_id: self.latest_monitor_update_id, updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast }], }, dropped_outbound_htlcs) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index b43c98c8..0f5e7f8a 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -37,7 +37,7 @@ use bitcoin::secp256k1; use chain; use chain::Watch; use chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent}; +use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, ChannelMonitorUpdateErr, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID}; use chain::transaction::{OutPoint, TransactionData}; use ln::channel::{Channel, ChannelError}; use ln::features::{InitFeatures, NodeFeatures}; @@ -118,9 +118,15 @@ pub(super) enum PendingHTLCStatus { pub(super) enum HTLCForwardInfo { AddHTLC { + forward_info: PendingHTLCInfo, + + // These fields are produced in `forward_htlcs()` and consumed in + // `process_pending_htlc_forwards()` for constructing the + // `HTLCSource::PreviousHopData` for failed and forwarded + // HTLCs. prev_short_channel_id: u64, prev_htlc_id: u64, - forward_info: PendingHTLCInfo, + prev_funding_outpoint: OutPoint, }, FailHTLC { htlc_id: u64, @@ -134,6 +140,10 @@ pub(crate) struct HTLCPreviousHopData { short_channel_id: u64, htlc_id: u64, incoming_packet_shared_secret: [u8; 32], + + // This field is consumed by `claim_funds_from_hop()` when updating a force-closed backwards + // channel with a preimage provided by the forward channel. + outpoint: OutPoint, } struct ClaimableHTLC { @@ -465,6 +475,7 @@ const CHECK_CLTV_EXPIRY_SANITY: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_P const CHECK_CLTV_EXPIRY_SANITY_2: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER; /// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels +#[derive(Clone)] pub struct ChannelDetails { /// The channel's ID (prior to funding transaction generation, this is a random 32 bytes, /// thereafter this is the txid of the funding transaction xor the funding transaction output). @@ -1554,9 +1565,11 @@ impl failed_forwards.reserve(pending_forwards.len()); for forward_info in pending_forwards.drain(..) { match forward_info { - HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info } => { + HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info, + prev_funding_outpoint } => { let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: prev_short_channel_id, + outpoint: prev_funding_outpoint, htlc_id: prev_htlc_id, incoming_packet_shared_secret: forward_info.incoming_shared_secret, }); @@ -1583,10 +1596,12 @@ impl HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info: PendingHTLCInfo { routing: PendingHTLCRouting::Forward { onion_packet, .. - }, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value }, } => { + }, incoming_shared_secret, payment_hash, amt_to_forward, outgoing_cltv_value }, + prev_funding_outpoint } => { log_trace!(self.logger, "Adding HTLC from short id {} with payment_hash {} to channel with short id {} after delay", log_bytes!(payment_hash.0), prev_short_channel_id, short_chan_id); let htlc_source = HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: prev_short_channel_id, + outpoint: prev_funding_outpoint, htlc_id: prev_htlc_id, incoming_packet_shared_secret: incoming_shared_secret, }); @@ -1701,9 +1716,11 @@ impl match forward_info { HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info: PendingHTLCInfo { routing: PendingHTLCRouting::Receive { payment_data, incoming_cltv_expiry }, - incoming_shared_secret, payment_hash, amt_to_forward, .. }, } => { + incoming_shared_secret, payment_hash, amt_to_forward, .. }, + prev_funding_outpoint } => { let prev_hop = HTLCPreviousHopData { short_channel_id: prev_short_channel_id, + outpoint: prev_funding_outpoint, htlc_id: prev_htlc_id, incoming_packet_shared_secret: incoming_shared_secret, }; @@ -1738,6 +1755,7 @@ impl ); failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: htlc.prev_hop.short_channel_id, + outpoint: prev_funding_outpoint, htlc_id: htlc.prev_hop.htlc_id, incoming_packet_shared_secret: htlc.prev_hop.incoming_packet_shared_secret, }), payment_hash, @@ -1940,7 +1958,7 @@ impl } } }, - HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret }) => { + HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id, htlc_id, incoming_packet_shared_secret, .. }) => { let err_packet = match onion_error { HTLCFailReason::Reason { failure_code, data } => { log_trace!(self.logger, "Failing HTLC with payment_hash {} backwards from us with code {}", log_bytes!(payment_hash.0), failure_code); @@ -2135,12 +2153,23 @@ impl }); }, HTLCSource::PreviousHopData(hop_data) => { + let prev_outpoint = hop_data.outpoint; if let Err((counterparty_node_id, err)) = match self.claim_funds_from_hop(&mut channel_state_lock, hop_data, payment_preimage) { Ok(()) => Ok(()), Err(None) => { - // TODO: There is probably a channel monitor somewhere that needs to - // learn the preimage as the channel already hit the chain and that's - // why it's missing. + let preimage_update = ChannelMonitorUpdate { + update_id: CLOSED_CHANNEL_UPDATE_ID, + updates: vec![ChannelMonitorUpdateStep::PaymentPreimage { + payment_preimage: payment_preimage.clone(), + }], + }; + // We update the ChannelMonitor on the backward link, after + // receiving an offchain preimage event from the forward link (the + // event being update_fulfill_htlc). + if let Err(e) = self.chain_monitor.update_channel(prev_outpoint, preimage_update) { + log_error!(self.logger, "Critical error: failed to update channel monitor with preimage {:?}: {:?}", + payment_preimage, e); + } Ok(()) }, Err(Some(res)) => Err(res), @@ -2201,7 +2230,7 @@ impl let (raa, commitment_update, order, pending_forwards, mut pending_failures, needs_broadcast_safe, funding_locked) = channel.monitor_updating_restored(&self.logger); if !pending_forwards.is_empty() { - htlc_forwards.push((channel.get_short_channel_id().expect("We can't have pending forwards before funding confirmation"), pending_forwards)); + htlc_forwards.push((channel.get_short_channel_id().expect("We can't have pending forwards before funding confirmation"), funding_txo.clone(), pending_forwards)); } htlc_failures.append(&mut pending_failures); @@ -2334,7 +2363,12 @@ impl // channel, not the temporary_channel_id. This is compatible with ourselves, but the // spec is somewhat ambiguous here. Not a huge deal since we'll send error messages for // any messages referencing a previously-closed channel anyway. - return Err(MsgHandleErrInternal::from_finish_shutdown("ChannelMonitor storage failure".to_owned(), funding_msg.channel_id, chan.force_shutdown(true), None)); + // We do not do a force-close here as that would generate a monitor update for + // a monitor that we didn't manage to store (and that we don't care about - we + // don't respond with the funding_signed so the channel can never go on chain). + let (_funding_txo_option, _monitor_update, failed_htlcs) = chan.force_shutdown(true); + assert!(failed_htlcs.is_empty()); + return Err(MsgHandleErrInternal::send_err_msg_no_close("ChannelMonitor storage failure".to_owned(), funding_msg.channel_id)); }, ChannelMonitorUpdateErr::TemporaryFailure => { // There's no problem signing a counterparty's funding transaction if our monitor @@ -2685,8 +2719,8 @@ impl } #[inline] - fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, Vec<(PendingHTLCInfo, u64)>)]) { - for &mut (prev_short_channel_id, ref mut pending_forwards) in per_source_pending_forwards { + fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, Vec<(PendingHTLCInfo, u64)>)]) { + for &mut (prev_short_channel_id, prev_funding_outpoint, ref mut pending_forwards) in per_source_pending_forwards { let mut forward_event = None; if !pending_forwards.is_empty() { let mut channel_state = self.channel_state.lock().unwrap(); @@ -2699,10 +2733,12 @@ impl PendingHTLCRouting::Receive { .. } => 0, }) { hash_map::Entry::Occupied(mut entry) => { - entry.get_mut().push(HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info }); + entry.get_mut().push(HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_funding_outpoint, + prev_htlc_id, forward_info }); }, hash_map::Entry::Vacant(entry) => { - entry.insert(vec!(HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_htlc_id, forward_info })); + entry.insert(vec!(HTLCForwardInfo::AddHTLC { prev_short_channel_id, prev_funding_outpoint, + prev_htlc_id, forward_info })); } } } @@ -2755,18 +2791,18 @@ impl msg, }); } - break Ok((pending_forwards, pending_failures, chan.get().get_short_channel_id().expect("RAA should only work on a short-id-available channel"))) + break Ok((pending_forwards, pending_failures, chan.get().get_short_channel_id().expect("RAA should only work on a short-id-available channel"), chan.get().get_funding_txo().unwrap())) }, hash_map::Entry::Vacant(_) => break Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id)) } }; self.fail_holding_cell_htlcs(htlcs_to_fail, msg.channel_id); match res { - Ok((pending_forwards, mut pending_failures, short_channel_id)) => { + Ok((pending_forwards, mut pending_failures, short_channel_id, channel_outpoint)) => { for failure in pending_failures.drain(..) { self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), failure.0, &failure.1, failure.2); } - self.forward_htlcs(&mut [(short_channel_id, pending_forwards)]); + self.forward_htlcs(&mut [(short_channel_id, channel_outpoint, pending_forwards)]); Ok(()) }, Err(e) => Err(e) @@ -3543,6 +3579,7 @@ impl Readable for PendingHTLCStatus { impl_writeable!(HTLCPreviousHopData, 0, { short_channel_id, + outpoint, htlc_id, incoming_packet_shared_secret }); @@ -3619,9 +3656,10 @@ impl Readable for HTLCFailReason { impl Writeable for HTLCForwardInfo { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { match self { - &HTLCForwardInfo::AddHTLC { ref prev_short_channel_id, ref prev_htlc_id, ref forward_info } => { + &HTLCForwardInfo::AddHTLC { ref prev_short_channel_id, ref prev_funding_outpoint, ref prev_htlc_id, ref forward_info } => { 0u8.write(writer)?; prev_short_channel_id.write(writer)?; + prev_funding_outpoint.write(writer)?; prev_htlc_id.write(writer)?; forward_info.write(writer)?; }, @@ -3640,6 +3678,7 @@ impl Readable for HTLCForwardInfo { match ::read(reader)? { 0 => Ok(HTLCForwardInfo::AddHTLC { prev_short_channel_id: Readable::read(reader)?, + prev_funding_outpoint: Readable::read(reader)?, prev_htlc_id: Readable::read(reader)?, forward_info: Readable::read(reader)?, }), diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index bc8351e4..8ff3d4ea 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -487,7 +487,11 @@ pub fn create_announced_chan_between_nodes<'a, 'b, 'c, 'd>(nodes: &'a Vec(nodes: &'a Vec>, a: usize, b: usize, channel_value: u64, push_msat: u64, a_flags: InitFeatures, b_flags: InitFeatures) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) { let chan_announcement = create_chan_between_nodes_with_value(&nodes[a], &nodes[b], channel_value, push_msat, a_flags, b_flags); + update_nodes_with_chan_announce(nodes, a, b, &chan_announcement.0, &chan_announcement.1, &chan_announcement.2); + (chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4) +} +pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) { nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new()); let a_events = nodes[a].node.get_and_clear_pending_msg_events(); assert_eq!(a_events.len(), 1); @@ -509,13 +513,12 @@ pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a }; for node in nodes { - assert!(node.net_graph_msg_handler.handle_channel_announcement(&chan_announcement.0).unwrap()); - node.net_graph_msg_handler.handle_channel_update(&chan_announcement.1).unwrap(); - node.net_graph_msg_handler.handle_channel_update(&chan_announcement.2).unwrap(); + assert!(node.net_graph_msg_handler.handle_channel_announcement(ann).unwrap()); + node.net_graph_msg_handler.handle_channel_update(upd_1).unwrap(); + node.net_graph_msg_handler.handle_channel_update(upd_2).unwrap(); node.net_graph_msg_handler.handle_node_announcement(&a_node_announcement).unwrap(); node.net_graph_msg_handler.handle_node_announcement(&b_node_announcement).unwrap(); } - (chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4) } macro_rules! check_spends { diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index a2e12504..85dae769 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -3523,7 +3523,7 @@ fn test_force_close_fail_back() { { let mut monitors = nodes[2].chain_monitor.chain_monitor.monitors.lock().unwrap(); monitors.get_mut(&OutPoint{ txid: Txid::from_slice(&payment_event.commitment_msg.channel_id[..]).unwrap(), index: 0 }).unwrap() - .provide_payment_preimage(&our_payment_hash, &our_payment_preimage); + .provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &node_cfgs[2].fee_estimator, &&logger); } connect_block(&nodes[2], &block, 1); let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap(); @@ -8457,6 +8457,43 @@ fn test_concurrent_monitor_claim() { } } +#[test] +fn test_pre_lockin_no_chan_closed_update() { + // Test that if a peer closes a channel in response to a funding_created message we don't + // generate a channel update (as the channel cannot appear on chain without a funding_signed + // message). + // + // Doing so would imply a channel monitor update before the initial channel monitor + // registration, violating our API guarantees. + // + // Previously, full_stack_target managed to hit this case by opening then closing a channel, + // then opening a second channel with the same funding output as the first (which is not + // rejected because the first channel does not exist in the ChannelManager) and closing it + // before receiving funding_signed. + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + // Create an initial channel + nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap(); + let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg); + let accept_chan_msg = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); + nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_chan_msg); + + // Move the first channel through the funding flow... + let (temporary_channel_id, _tx, funding_output) = create_funding_transaction(&nodes[0], 100000, 42); + + nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output); + check_added_monitors!(nodes[0], 0); + + let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let channel_id = ::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id(); + nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id, data: "Hi".to_owned() }); + assert!(nodes[0].chain_monitor.added_monitors.lock().unwrap().is_empty()); +} + #[test] fn test_htlc_no_detection() { // This test is a mutation to underscore the detection logic bug we had @@ -8503,3 +8540,327 @@ fn test_htlc_no_detection() { connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1, 201, true, header_201.block_hash()); expect_payment_failed!(nodes[0], our_payment_hash, true); } + +fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain_before_fulfill: bool) { + // If we route an HTLC, then learn the HTLC's preimage after the upstream channel has been + // force-closed, we must claim that HTLC on-chain. (Given an HTLC forwarded from Alice --> Bob --> + // Carol, Alice would be the upstream node, and Carol the downstream.) + // + // Steps of the test: + // 1) Alice sends a HTLC to Carol through Bob. + // 2) Carol doesn't settle the HTLC. + // 3) If broadcast_alice is true, Alice force-closes her channel with Bob. Else Bob force closes. + // Steps 4 and 5 may be reordered depending on go_onchain_before_fulfill. + // 4) Bob sees the Alice's commitment on his chain or vice versa. An offered output is present + // but can't be claimed as Bob doesn't have yet knowledge of the preimage. + // 5) Carol release the preimage to Bob off-chain. + // 6) Bob claims the offered output on the broadcasted commitment. + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + // Create some initial channels + let chan_ab = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known()); + create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known()); + + // Steps (1) and (2): + // Send an HTLC Alice --> Bob --> Carol, but Carol doesn't settle the HTLC back. + let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3_000_000); + + // Check that Alice's commitment transaction now contains an output for this HTLC. + let alice_txn = get_local_commitment_txn!(nodes[0], chan_ab.2); + check_spends!(alice_txn[0], chan_ab.3); + assert_eq!(alice_txn[0].output.len(), 2); + check_spends!(alice_txn[1], alice_txn[0]); // 2nd transaction is a non-final HTLC-timeout + assert_eq!(alice_txn[1].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + assert_eq!(alice_txn.len(), 2); + + // Steps (3) and (4): + // If `go_onchain_before_fufill`, broadcast the relevant commitment transaction and check that Bob + // responds by (1) broadcasting a channel update and (2) adding a new ChannelMonitor. + let mut force_closing_node = 0; // Alice force-closes + if !broadcast_alice { force_closing_node = 1; } // Bob force-closes + nodes[force_closing_node].node.force_close_channel(&chan_ab.2); + check_closed_broadcast!(nodes[force_closing_node], false); + check_added_monitors!(nodes[force_closing_node], 1); + if go_onchain_before_fulfill { + let txn_to_broadcast = match broadcast_alice { + true => alice_txn.clone(), + false => get_local_commitment_txn!(nodes[1], chan_ab.2) + }; + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42}; + connect_block(&nodes[1], &Block { header, txdata: vec![txn_to_broadcast[0].clone()]}, 1); + let mut bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + if broadcast_alice { + check_closed_broadcast!(nodes[1], false); + check_added_monitors!(nodes[1], 1); + } + assert_eq!(bob_txn.len(), 1); + check_spends!(bob_txn[0], chan_ab.3); + } + + // Step (5): + // Carol then claims the funds and sends an update_fulfill message to Bob, and they go through the + // process of removing the HTLC from their commitment transactions. + assert!(nodes[2].node.claim_funds(payment_preimage, &None, 3_000_000)); + check_added_monitors!(nodes[2], 1); + let carol_updates = get_htlc_update_msgs!(nodes[2], nodes[1].node.get_our_node_id()); + assert!(carol_updates.update_add_htlcs.is_empty()); + assert!(carol_updates.update_fail_htlcs.is_empty()); + assert!(carol_updates.update_fail_malformed_htlcs.is_empty()); + assert!(carol_updates.update_fee.is_none()); + assert_eq!(carol_updates.update_fulfill_htlcs.len(), 1); + + nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &carol_updates.update_fulfill_htlcs[0]); + // If Alice broadcasted but Bob doesn't know yet, here he prepares to tell her about the preimage. + if !go_onchain_before_fulfill && broadcast_alice { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::UpdateHTLCs { ref node_id, .. } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + }; + } + nodes[1].node.handle_commitment_signed(&nodes[2].node.get_our_node_id(), &carol_updates.commitment_signed); + // One monitor update for the preimage to update the Bob<->Alice channel, one monitor update + // Carol<->Bob's updated commitment transaction info. + check_added_monitors!(nodes[1], 2); + + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 2); + let bob_revocation = match events[0] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[2].node.get_our_node_id()); + (*msg).clone() + }, + _ => panic!("Unexpected event"), + }; + let bob_updates = match events[1] { + MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => { + assert_eq!(*node_id, nodes[2].node.get_our_node_id()); + (*updates).clone() + }, + _ => panic!("Unexpected event"), + }; + + nodes[2].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bob_revocation); + check_added_monitors!(nodes[2], 1); + nodes[2].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), &bob_updates.commitment_signed); + check_added_monitors!(nodes[2], 1); + + let events = nodes[2].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + let carol_revocation = match events[0] { + MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + (*msg).clone() + }, + _ => panic!("Unexpected event"), + }; + nodes[1].node.handle_revoke_and_ack(&nodes[2].node.get_our_node_id(), &carol_revocation); + check_added_monitors!(nodes[1], 1); + + // If this test requires the force-closed channel to not be on-chain until after the fulfill, + // here's where we put said channel's commitment tx on-chain. + let mut txn_to_broadcast = alice_txn.clone(); + if !broadcast_alice { txn_to_broadcast = get_local_commitment_txn!(nodes[1], chan_ab.2); } + if !go_onchain_before_fulfill { + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42}; + connect_block(&nodes[1], &Block { header, txdata: vec![txn_to_broadcast[0].clone()]}, 1); + // If Bob was the one to force-close, he will have already passed these checks earlier. + if broadcast_alice { + check_closed_broadcast!(nodes[1], false); + check_added_monitors!(nodes[1], 1); + } + let mut bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); + if broadcast_alice { + // In `connect_block()`, the ChainMonitor and ChannelManager are separately notified about a + // new block being connected. The ChannelManager being notified triggers a monitor update, + // which triggers broadcasting our commitment tx and an HTLC-claiming tx. The ChainMonitor + // being notified triggers the HTLC-claiming tx redundantly, resulting in 3 total txs being + // broadcasted. + assert_eq!(bob_txn.len(), 3); + check_spends!(bob_txn[1], chan_ab.3); + } else { + assert_eq!(bob_txn.len(), 2); + check_spends!(bob_txn[0], chan_ab.3); + } + } + + // Step (6): + // Finally, check that Bob broadcasted a preimage-claiming transaction for the HTLC output on the + // broadcasted commitment transaction. + { + let bob_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); + if go_onchain_before_fulfill { + // Bob should now have an extra broadcasted tx, for the preimage-claiming transaction. + assert_eq!(bob_txn.len(), 2); + } + let script_weight = match broadcast_alice { + true => OFFERED_HTLC_SCRIPT_WEIGHT, + false => ACCEPTED_HTLC_SCRIPT_WEIGHT + }; + // If Alice force-closed and Bob didn't receive her commitment transaction until after he + // received Carol's fulfill, he broadcasts the HTLC-output-claiming transaction first. Else if + // Bob force closed or if he found out about Alice's commitment tx before receiving Carol's + // fulfill, then he broadcasts the HTLC-output-claiming transaction second. + if broadcast_alice && !go_onchain_before_fulfill { + check_spends!(bob_txn[0], txn_to_broadcast[0]); + assert_eq!(bob_txn[0].input[0].witness.last().unwrap().len(), script_weight); + } else { + check_spends!(bob_txn[1], txn_to_broadcast[0]); + assert_eq!(bob_txn[1].input[0].witness.last().unwrap().len(), script_weight); + } + } +} + +#[test] +fn test_onchain_htlc_settlement_after_close() { + do_test_onchain_htlc_settlement_after_close(true, true); + do_test_onchain_htlc_settlement_after_close(false, true); // Technically redundant, but may as well + do_test_onchain_htlc_settlement_after_close(true, false); + do_test_onchain_htlc_settlement_after_close(false, false); +} + +#[test] +fn test_duplicate_chan_id() { + // Test that if a given peer tries to open a channel with the same channel_id as one that is + // already open we reject it and keep the old channel. + // + // Previously, full_stack_target managed to figure out that if you tried to open two channels + // with the same funding output (ie post-funding channel_id), we'd create a monitor update for + // the existing channel when we detect the duplicate new channel, screwing up our monitor + // updating logic for the existing channel. + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + // Create an initial channel + nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap(); + let mut open_chan_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg); + nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + + // Try to create a second channel with the same temporary_channel_id as the first and check + // that it is rejected. + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg); + { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + // Technically, at this point, nodes[1] would be justified in thinking both the + // first (valid) and second (invalid) channels are closed, given they both have + // the same non-temporary channel_id. However, currently we do not, so we just + // move forward with it. + assert_eq!(msg.channel_id, open_chan_msg.temporary_channel_id); + assert_eq!(node_id, nodes[0].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + } + } + + // Move the first channel through the funding flow... + let (temporary_channel_id, tx, funding_output) = create_funding_transaction(&nodes[0], 100000, 42); + + nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output); + check_added_monitors!(nodes[0], 0); + + let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg); + { + let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + assert_eq!(added_monitors[0].0, funding_output); + added_monitors.clear(); + } + let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); + + let funding_outpoint = ::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }; + let channel_id = funding_outpoint.to_channel_id(); + + // Now we have the first channel past funding_created (ie it has a txid-based channel_id, not a + // temporary one). + + // First try to open a second channel with a temporary channel id equal to the txid-based one. + // Technically this is allowed by the spec, but we don't support it and there's little reason + // to. Still, it shouldn't cause any other issues. + open_chan_msg.temporary_channel_id = channel_id; + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_msg); + { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + // Technically, at this point, nodes[1] would be justified in thinking both + // channels are closed, but currently we do not, so we just move forward with it. + assert_eq!(msg.channel_id, open_chan_msg.temporary_channel_id); + assert_eq!(node_id, nodes[0].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + } + } + + // Now try to create a second channel which has a duplicate funding output. + nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap(); + let open_chan_2_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_chan_2_msg); + nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id())); + create_funding_transaction(&nodes[0], 100000, 42); // Get and check the FundingGenerationReady event + + let funding_created = { + let mut a_channel_lock = nodes[0].node.channel_state.lock().unwrap(); + let mut as_chan = a_channel_lock.by_id.get_mut(&open_chan_2_msg.temporary_channel_id).unwrap(); + let logger = test_utils::TestLogger::new(); + as_chan.get_outbound_funding_created(funding_outpoint, &&logger).unwrap() + }; + check_added_monitors!(nodes[0], 0); + nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created); + // At this point we'll try to add a duplicate channel monitor, which will be rejected, but + // still needs to be cleared here. + check_added_monitors!(nodes[1], 1); + + // ...still, nodes[1] will reject the duplicate channel. + { + let events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => { + // Technically, at this point, nodes[1] would be justified in thinking both + // channels are closed, but currently we do not, so we just move forward with it. + assert_eq!(msg.channel_id, channel_id); + assert_eq!(node_id, nodes[0].node.get_our_node_id()); + }, + _ => panic!("Unexpected event"), + } + } + + // finally, finish creating the original channel and send a payment over it to make sure + // everything is functional. + nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg); + { + let mut added_monitors = nodes[0].chain_monitor.added_monitors.lock().unwrap(); + assert_eq!(added_monitors.len(), 1); + assert_eq!(added_monitors[0].0, funding_output); + added_monitors.clear(); + } + + let events_4 = nodes[0].node.get_and_clear_pending_events(); + assert_eq!(events_4.len(), 1); + match events_4[0] { + Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => { + assert_eq!(user_channel_id, 42); + assert_eq!(*funding_txo, funding_output); + }, + _ => panic!("Unexpected event"), + }; + + let (funding_locked, _) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); + let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &funding_locked); + update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update); + send_payment(&nodes[0], &[&nodes[1]], 8000000, 8_000_000); +} diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 16ba0862..f57cf0fd 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -64,6 +64,7 @@ pub enum DecodeError { } /// An init message to be sent or received from a peer +#[derive(Clone)] pub struct Init { #[cfg(not(feature = "fuzztarget"))] pub(crate) features: InitFeatures, @@ -84,6 +85,7 @@ pub struct ErrorMessage { } /// A ping message to be sent or received from a peer +#[derive(Clone)] pub struct Ping { /// The desired response length pub ponglen: u16, @@ -93,6 +95,7 @@ pub struct Ping { } /// A pong message to be sent or received from a peer +#[derive(Clone)] pub struct Pong { /// The pong packet size. /// This field is not sent on the wire. byteslen zeros are sent. diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index 2f156563..3484d898 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -282,6 +282,8 @@ pub struct OnchainTxHandler { onchain_events_waiting_threshold_conf: HashMap>, + latest_height: u32, + secp_ctx: Secp256k1, } @@ -328,6 +330,7 @@ impl OnchainTxHandler { } } } + self.latest_height.write(writer)?; Ok(()) } } @@ -387,6 +390,7 @@ impl Readable for OnchainTxHandler Readable for OnchainTxHandler OnchainTxHandler { pending_claim_requests: HashMap::new(), claimable_outpoints: HashMap::new(), onchain_events_waiting_threshold_conf: HashMap::new(), + latest_height: 0, secp_ctx: Secp256k1::new(), } @@ -471,7 +477,7 @@ impl OnchainTxHandler { /// Lightning security model (i.e being able to redeem/timeout HTLC or penalize coutnerparty onchain) lays on the assumption of claim transactions getting confirmed before timelock expiration /// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent. - fn generate_claim_tx(&mut self, height: u32, cached_claim_datas: &ClaimTxBumpMaterial, fee_estimator: F, logger: L) -> Option<(Option, u32, Transaction)> + fn generate_claim_tx(&mut self, height: u32, cached_claim_datas: &ClaimTxBumpMaterial, fee_estimator: &F, logger: &L) -> Option<(Option, u32, Transaction)> where F::Target: FeeEstimator, L::Target: Logger, { @@ -657,12 +663,20 @@ impl OnchainTxHandler { None } - pub(crate) fn block_connected(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec, height: u32, broadcaster: B, fee_estimator: F, logger: L) + /// Upon channelmonitor.block_connected(..) or upon provision of a preimage on the forward link + /// for this channel, provide new relevant on-chain transactions and/or new claim requests. + /// Formerly this was named `block_connected`, but it is now also used for claiming an HTLC output + /// if we receive a preimage after force-close. + pub(crate) fn update_claims_view(&mut self, txn_matched: &[&Transaction], claimable_outpoints: Vec, latest_height: Option, broadcaster: &B, fee_estimator: &F, logger: &L) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, { - log_trace!(logger, "Block at height {} connected with {} claim requests", height, claimable_outpoints.len()); + let height = match latest_height { + Some(h) => h, + None => self.latest_height, + }; + log_trace!(logger, "Updating claims view at height {} with {} matched transactions and {} claim requests", height, txn_matched.len(), claimable_outpoints.len()); let mut new_claims = Vec::new(); let mut aggregated_claim = HashMap::new(); let mut aggregated_soonest = ::std::u32::MAX; @@ -855,7 +869,7 @@ impl OnchainTxHandler { } } for (_, claim_material) in bump_candidates.iter_mut() { - if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator, &*logger) { + if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &&*fee_estimator, &&*logger) { claim_material.height_timer = new_timer; claim_material.feerate_previous = new_feerate; broadcaster.broadcast_transaction(&bump_tx); diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 526d26b5..490b6b40 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -113,6 +113,7 @@ impl Readable for Route { } /// A channel descriptor which provides a last-hop route to get_route +#[derive(Clone)] pub struct RouteHint { /// The node_id of the non-target end of the route pub src_node_id: PublicKey, diff --git a/lightning/src/util/events.rs b/lightning/src/util/events.rs index 60191b88..3eeacdc7 100644 --- a/lightning/src/util/events.rs +++ b/lightning/src/util/events.rs @@ -31,7 +31,7 @@ use std::time::Duration; /// Note that while Writeable and Readable are implemented for Event, you probably shouldn't use /// them directly as they don't round-trip exactly (for example FundingGenerationReady is never /// written as it makes no sense to respond to it after reconnecting to peers). -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum Event { /// Used to indicate that the client should generate a funding transaction with the given /// parameters and then call ChannelManager::funding_transaction_generated.