X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=ldk-c-bindings;a=blobdiff_plain;f=lightning-c-bindings%2Fsrc%2Flightning%2Frouting%2Frouter.rs;h=7022f5033802ab34eb06a9067bba740b0691df37;hp=211b44ff488ea96e70e07505fc06e50908f8b1db;hb=e419524cf19c36857bf1f3c79d4b9dd47c7544c8;hpb=d9866e870bbe080412dc70b1421e28a756e4407e diff --git a/lightning-c-bindings/src/lightning/routing/router.rs b/lightning-c-bindings/src/lightning/routing/router.rs index 211b44f..7022f50 100644 --- a/lightning-c-bindings/src/lightning/routing/router.rs +++ b/lightning-c-bindings/src/lightning/routing/router.rs @@ -11,6 +11,7 @@ //! You probably want to create a NetGraphMsgHandler and use that as your RoutingMessageHandler and then //! interrogate it to get routes for your own payments. +use std::str::FromStr; use std::ffi::c_void; use bitcoin::hashes::Hash; use crate::c_types::*; @@ -64,7 +65,7 @@ impl RouteHop { #[no_mangle] pub extern "C" fn RouteHop_get_pubkey(this_ptr: &RouteHop) -> crate::c_types::PublicKey { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.pubkey; - crate::c_types::PublicKey::from_rust(&(*inner_val)) + crate::c_types::PublicKey::from_rust(&inner_val) } /// The node_id of the node at this hop. #[no_mangle] @@ -76,7 +77,7 @@ pub extern "C" fn RouteHop_set_pubkey(this_ptr: &mut RouteHop, mut val: crate::c #[no_mangle] pub extern "C" fn RouteHop_get_node_features(this_ptr: &RouteHop) -> crate::lightning::ln::features::NodeFeatures { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.node_features; - crate::lightning::ln::features::NodeFeatures { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false } + crate::lightning::ln::features::NodeFeatures { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false } } /// The node_announcement features of the node at this hop. For the last hop, these may be /// amended to match the features present in the invoice this node generated. @@ -88,7 +89,7 @@ pub extern "C" fn RouteHop_set_node_features(this_ptr: &mut RouteHop, mut val: c #[no_mangle] pub extern "C" fn RouteHop_get_short_channel_id(this_ptr: &RouteHop) -> u64 { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.short_channel_id; - (*inner_val) + *inner_val } /// The channel that should be used from the previous hop to reach this node. #[no_mangle] @@ -100,7 +101,7 @@ pub extern "C" fn RouteHop_set_short_channel_id(this_ptr: &mut RouteHop, mut val #[no_mangle] pub extern "C" fn RouteHop_get_channel_features(this_ptr: &RouteHop) -> crate::lightning::ln::features::ChannelFeatures { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.channel_features; - crate::lightning::ln::features::ChannelFeatures { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false } + crate::lightning::ln::features::ChannelFeatures { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false } } /// The channel_announcement features of the channel that should be used from the previous hop /// to reach this node. @@ -114,7 +115,7 @@ pub extern "C" fn RouteHop_set_channel_features(this_ptr: &mut RouteHop, mut val #[no_mangle] pub extern "C" fn RouteHop_get_fee_msat(this_ptr: &RouteHop) -> u64 { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fee_msat; - (*inner_val) + *inner_val } /// The fee taken on this hop (for paying for the use of the *next* channel in the path). /// For the last hop, this should be the full value of the payment (might be more than @@ -128,7 +129,7 @@ pub extern "C" fn RouteHop_set_fee_msat(this_ptr: &mut RouteHop, mut val: u64) { #[no_mangle] pub extern "C" fn RouteHop_get_cltv_expiry_delta(this_ptr: &RouteHop) -> u32 { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.cltv_expiry_delta; - (*inner_val) + *inner_val } /// The CLTV delta added for this hop. For the last hop, this should be the full CLTV value /// expected at the destination, in excess of the current block height. @@ -168,6 +169,22 @@ pub(crate) extern "C" fn RouteHop_clone_void(this_ptr: *const c_void) -> *mut c_ pub extern "C" fn RouteHop_clone(orig: &RouteHop) -> RouteHop { orig.clone() } +#[no_mangle] +/// Serialize the RouteHop object into a byte array which can be read by RouteHop_read +pub extern "C" fn RouteHop_write(obj: &RouteHop) -> crate::c_types::derived::CVec_u8Z { + crate::c_types::serialize_obj(unsafe { &*unsafe { &*obj }.inner }) +} +#[no_mangle] +pub(crate) extern "C" fn RouteHop_write_void(obj: *const c_void) -> crate::c_types::derived::CVec_u8Z { + crate::c_types::serialize_obj(unsafe { &*(obj as *const nativeRouteHop) }) +} +#[no_mangle] +/// Read a RouteHop from a byte array, created by RouteHop_write +pub extern "C" fn RouteHop_read(ser: crate::c_types::u8slice) -> crate::c_types::derived::CResult_RouteHopDecodeErrorZ { + let res = crate::c_types::deserialize_obj(ser); + let mut local_res = match res { Ok(mut o) => crate::c_types::CResultTempl::ok( { crate::lightning::routing::router::RouteHop { inner: Box::into_raw(Box::new(o)), is_owned: true } }).into(), Err(mut e) => crate::c_types::CResultTempl::err( { crate::lightning::ln::msgs::DecodeError { inner: Box::into_raw(Box::new(e)), is_owned: true } }).into() }; + local_res +} use lightning::routing::router::Route as nativeRouteImport; type nativeRoute = nativeRouteImport; @@ -273,7 +290,7 @@ pub extern "C" fn Route_read(ser: crate::c_types::u8slice) -> crate::c_types::de use lightning::routing::router::RouteHint as nativeRouteHintImport; type nativeRouteHint = nativeRouteHintImport; -/// A channel descriptor which provides a last-hop route to get_route +/// A list of hops along a payment path terminating with a channel to the recipient. #[must_use] #[repr(C)] pub struct RouteHint { @@ -314,83 +331,156 @@ impl RouteHint { ret } } +/// Checks if two RouteHints contain equal inner contents. +/// This ignores pointers and is_owned flags and looks at the values in fields. +/// Two objects with NULL inner values will be considered "equal" here. +#[no_mangle] +pub extern "C" fn RouteHint_eq(a: &RouteHint, b: &RouteHint) -> bool { + if a.inner == b.inner { return true; } + if a.inner.is_null() || b.inner.is_null() { return false; } + if unsafe { &*a.inner } == unsafe { &*b.inner } { true } else { false } +} +impl Clone for RouteHint { + fn clone(&self) -> Self { + Self { + inner: if <*mut nativeRouteHint>::is_null(self.inner) { std::ptr::null_mut() } else { + 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] +/// Creates a copy of the RouteHint +pub extern "C" fn RouteHint_clone(orig: &RouteHint) -> RouteHint { + orig.clone() +} + +use lightning::routing::router::RouteHintHop as nativeRouteHintHopImport; +type nativeRouteHintHop = nativeRouteHintHopImport; + +/// A channel descriptor for a hop along a payment path. +#[must_use] +#[repr(C)] +pub struct RouteHintHop { + /// A pointer to the opaque Rust object. + + /// Nearly everywhere, inner must be non-null, however in places where + /// the Rust equivalent takes an Option, it may be set to null to indicate None. + pub inner: *mut nativeRouteHintHop, + /// Indicates that this is the only struct which contains the same pointer. + + /// Rust functions which take ownership of an object provided via an argument require + /// this to be true and invalidate the object pointed to by inner. + pub is_owned: bool, +} + +impl Drop for RouteHintHop { + fn drop(&mut self) { + if self.is_owned && !<*mut nativeRouteHintHop>::is_null(self.inner) { + let _ = unsafe { Box::from_raw(self.inner) }; + } + } +} +/// Frees any resources used by the RouteHintHop, if is_owned is set and inner is non-NULL. +#[no_mangle] +pub extern "C" fn RouteHintHop_free(this_obj: RouteHintHop) { } +#[allow(unused)] +/// Used only if an object of this type is returned as a trait impl by a method +extern "C" fn RouteHintHop_free_void(this_ptr: *mut c_void) { + unsafe { let _ = Box::from_raw(this_ptr as *mut nativeRouteHintHop); } +} +#[allow(unused)] +/// When moving out of the pointer, we have to ensure we aren't a reference, this makes that easy +impl RouteHintHop { + pub(crate) fn take_inner(mut self) -> *mut nativeRouteHintHop { + assert!(self.is_owned); + let ret = self.inner; + self.inner = std::ptr::null_mut(); + ret + } +} /// The node_id of the non-target end of the route #[no_mangle] -pub extern "C" fn RouteHint_get_src_node_id(this_ptr: &RouteHint) -> crate::c_types::PublicKey { +pub extern "C" fn RouteHintHop_get_src_node_id(this_ptr: &RouteHintHop) -> crate::c_types::PublicKey { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.src_node_id; - crate::c_types::PublicKey::from_rust(&(*inner_val)) + crate::c_types::PublicKey::from_rust(&inner_val) } /// The node_id of the non-target end of the route #[no_mangle] -pub extern "C" fn RouteHint_set_src_node_id(this_ptr: &mut RouteHint, mut val: crate::c_types::PublicKey) { +pub extern "C" fn RouteHintHop_set_src_node_id(this_ptr: &mut RouteHintHop, mut val: crate::c_types::PublicKey) { unsafe { &mut *this_ptr.inner }.src_node_id = val.into_rust(); } /// The short_channel_id of this channel #[no_mangle] -pub extern "C" fn RouteHint_get_short_channel_id(this_ptr: &RouteHint) -> u64 { +pub extern "C" fn RouteHintHop_get_short_channel_id(this_ptr: &RouteHintHop) -> u64 { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.short_channel_id; - (*inner_val) + *inner_val } /// The short_channel_id of this channel #[no_mangle] -pub extern "C" fn RouteHint_set_short_channel_id(this_ptr: &mut RouteHint, mut val: u64) { +pub extern "C" fn RouteHintHop_set_short_channel_id(this_ptr: &mut RouteHintHop, mut val: u64) { unsafe { &mut *this_ptr.inner }.short_channel_id = val; } /// The fees which must be paid to use this channel #[no_mangle] -pub extern "C" fn RouteHint_get_fees(this_ptr: &RouteHint) -> crate::lightning::routing::network_graph::RoutingFees { +pub extern "C" fn RouteHintHop_get_fees(this_ptr: &RouteHintHop) -> crate::lightning::routing::network_graph::RoutingFees { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.fees; - crate::lightning::routing::network_graph::RoutingFees { inner: unsafe { ( (&((*inner_val)) as *const _) as *mut _) }, is_owned: false } + crate::lightning::routing::network_graph::RoutingFees { inner: unsafe { ( (&(*inner_val) as *const _) as *mut _) }, is_owned: false } } /// The fees which must be paid to use this channel #[no_mangle] -pub extern "C" fn RouteHint_set_fees(this_ptr: &mut RouteHint, mut val: crate::lightning::routing::network_graph::RoutingFees) { +pub extern "C" fn RouteHintHop_set_fees(this_ptr: &mut RouteHintHop, mut val: crate::lightning::routing::network_graph::RoutingFees) { unsafe { &mut *this_ptr.inner }.fees = *unsafe { Box::from_raw(val.take_inner()) }; } /// The difference in CLTV values between this node and the next node. #[no_mangle] -pub extern "C" fn RouteHint_get_cltv_expiry_delta(this_ptr: &RouteHint) -> u16 { +pub extern "C" fn RouteHintHop_get_cltv_expiry_delta(this_ptr: &RouteHintHop) -> u16 { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.cltv_expiry_delta; - (*inner_val) + *inner_val } /// The difference in CLTV values between this node and the next node. #[no_mangle] -pub extern "C" fn RouteHint_set_cltv_expiry_delta(this_ptr: &mut RouteHint, mut val: u16) { +pub extern "C" fn RouteHintHop_set_cltv_expiry_delta(this_ptr: &mut RouteHintHop, mut val: u16) { unsafe { &mut *this_ptr.inner }.cltv_expiry_delta = val; } /// The minimum value, in msat, which must be relayed to the next hop. #[no_mangle] -pub extern "C" fn RouteHint_get_htlc_minimum_msat(this_ptr: &RouteHint) -> crate::c_types::derived::COption_u64Z { +pub extern "C" fn RouteHintHop_get_htlc_minimum_msat(this_ptr: &RouteHintHop) -> crate::c_types::derived::COption_u64Z { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.htlc_minimum_msat; let mut local_inner_val = if inner_val.is_none() { crate::c_types::derived::COption_u64Z::None } else { { crate::c_types::derived::COption_u64Z::Some(inner_val.unwrap()) } }; local_inner_val } /// The minimum value, in msat, which must be relayed to the next hop. #[no_mangle] -pub extern "C" fn RouteHint_set_htlc_minimum_msat(this_ptr: &mut RouteHint, mut val: crate::c_types::derived::COption_u64Z) { +pub extern "C" fn RouteHintHop_set_htlc_minimum_msat(this_ptr: &mut RouteHintHop, mut val: crate::c_types::derived::COption_u64Z) { let mut local_val = if val.is_some() { Some( { val.take() }) } else { None }; unsafe { &mut *this_ptr.inner }.htlc_minimum_msat = local_val; } /// The maximum value in msat available for routing with a single HTLC. #[no_mangle] -pub extern "C" fn RouteHint_get_htlc_maximum_msat(this_ptr: &RouteHint) -> crate::c_types::derived::COption_u64Z { +pub extern "C" fn RouteHintHop_get_htlc_maximum_msat(this_ptr: &RouteHintHop) -> crate::c_types::derived::COption_u64Z { let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.htlc_maximum_msat; let mut local_inner_val = if inner_val.is_none() { crate::c_types::derived::COption_u64Z::None } else { { crate::c_types::derived::COption_u64Z::Some(inner_val.unwrap()) } }; local_inner_val } /// The maximum value in msat available for routing with a single HTLC. #[no_mangle] -pub extern "C" fn RouteHint_set_htlc_maximum_msat(this_ptr: &mut RouteHint, mut val: crate::c_types::derived::COption_u64Z) { +pub extern "C" fn RouteHintHop_set_htlc_maximum_msat(this_ptr: &mut RouteHintHop, mut val: crate::c_types::derived::COption_u64Z) { let mut local_val = if val.is_some() { Some( { val.take() }) } else { None }; unsafe { &mut *this_ptr.inner }.htlc_maximum_msat = local_val; } -/// Constructs a new RouteHint given each field +/// Constructs a new RouteHintHop given each field #[must_use] #[no_mangle] -pub extern "C" fn RouteHint_new(mut src_node_id_arg: crate::c_types::PublicKey, mut short_channel_id_arg: u64, mut fees_arg: crate::lightning::routing::network_graph::RoutingFees, mut cltv_expiry_delta_arg: u16, mut htlc_minimum_msat_arg: crate::c_types::derived::COption_u64Z, mut htlc_maximum_msat_arg: crate::c_types::derived::COption_u64Z) -> RouteHint { +pub extern "C" fn RouteHintHop_new(mut src_node_id_arg: crate::c_types::PublicKey, mut short_channel_id_arg: u64, mut fees_arg: crate::lightning::routing::network_graph::RoutingFees, mut cltv_expiry_delta_arg: u16, mut htlc_minimum_msat_arg: crate::c_types::derived::COption_u64Z, mut htlc_maximum_msat_arg: crate::c_types::derived::COption_u64Z) -> RouteHintHop { let mut local_htlc_minimum_msat_arg = if htlc_minimum_msat_arg.is_some() { Some( { htlc_minimum_msat_arg.take() }) } else { None }; let mut local_htlc_maximum_msat_arg = if htlc_maximum_msat_arg.is_some() { Some( { htlc_maximum_msat_arg.take() }) } else { None }; - RouteHint { inner: Box::into_raw(Box::new(nativeRouteHint { + RouteHintHop { inner: Box::into_raw(Box::new(nativeRouteHintHop { src_node_id: src_node_id_arg.into_rust(), short_channel_id: short_channel_id_arg, fees: *unsafe { Box::from_raw(fees_arg.take_inner()) }, @@ -399,10 +489,19 @@ pub extern "C" fn RouteHint_new(mut src_node_id_arg: crate::c_types::PublicKey, htlc_maximum_msat: local_htlc_maximum_msat_arg, })), is_owned: true } } -impl Clone for RouteHint { +/// Checks if two RouteHintHops contain equal inner contents. +/// This ignores pointers and is_owned flags and looks at the values in fields. +/// Two objects with NULL inner values will be considered "equal" here. +#[no_mangle] +pub extern "C" fn RouteHintHop_eq(a: &RouteHintHop, b: &RouteHintHop) -> bool { + if a.inner == b.inner { return true; } + if a.inner.is_null() || b.inner.is_null() { return false; } + if unsafe { &*a.inner } == unsafe { &*b.inner } { true } else { false } +} +impl Clone for RouteHintHop { fn clone(&self) -> Self { Self { - inner: if <*mut nativeRouteHint>::is_null(self.inner) { std::ptr::null_mut() } else { + inner: if <*mut nativeRouteHintHop>::is_null(self.inner) { std::ptr::null_mut() } else { Box::into_raw(Box::new(unsafe { &*self.inner }.clone())) }, is_owned: true, } @@ -410,12 +509,12 @@ impl Clone for RouteHint { } #[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 +pub(crate) extern "C" fn RouteHintHop_clone_void(this_ptr: *const c_void) -> *mut c_void { + Box::into_raw(Box::new(unsafe { (*(this_ptr as *mut nativeRouteHintHop)).clone() })) as *mut c_void } #[no_mangle] -/// Creates a copy of the RouteHint -pub extern "C" fn RouteHint_clone(orig: &RouteHint) -> RouteHint { +/// Creates a copy of the RouteHintHop +pub extern "C" fn RouteHintHop_clone(orig: &RouteHintHop) -> RouteHintHop { orig.clone() } /// Gets a route from us (payer) to the given target node (payee). @@ -423,8 +522,8 @@ pub extern "C" fn RouteHint_clone(orig: &RouteHint) -> RouteHint { /// If the payee provided features in their invoice, they should be provided via payee_features. /// Without this, MPP will only be used if the payee's features are available in the network graph. /// -/// Extra routing hops between known nodes and the target will be used if they are included in -/// last_hops. +/// Private routing paths between a public node and the target may be included in `last_hops`. +/// Currently, only the last hop in each path is considered. /// /// If some channels aren't announced, it may be useful to fill in a first_hops with the /// results from a local ChannelManager::list_usable_channels() call. If it is filled in, our