diff --git a/src/ffi/types.rs b/src/ffi/types.rs index 7380d75ca..88d48e993 100644 --- a/src/ffi/types.rs +++ b/src/ffi/types.rs @@ -25,7 +25,7 @@ pub use bitcoin::{Address, BlockHash, Network, OutPoint, ScriptBuf, Txid}; pub use lightning::chain::channelmonitor::BalanceSource; use lightning::events::PaidBolt12Invoice as LdkPaidBolt12Invoice; pub use lightning::events::{ClosureReason, PaymentFailureReason}; -use lightning::ln::channel_state::ChannelShutdownState; +use lightning::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo}; use lightning::ln::channelmanager::PaymentId; use lightning::ln::msgs::DecodeError; pub use lightning::ln::types::ChannelId; @@ -44,7 +44,7 @@ pub use lightning_liquidity::lsps0::ser::LSPSDateTime; pub use lightning_liquidity::lsps1::msgs::{ LSPS1ChannelInfo, LSPS1OrderId, LSPS1OrderParams, LSPS1PaymentState, }; -use lightning_types::features::NodeFeatures as LdkNodeFeatures; +use lightning_types::features::{InitFeatures as LdkInitFeatures, NodeFeatures as LdkNodeFeatures}; pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; pub use lightning_types::string::UntrustedString; use vss_client::headers::{ @@ -1815,6 +1815,296 @@ impl From for NodeFeatures { } } +#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)] +pub struct InitFeatures { + pub(crate) inner: LdkInitFeatures, +} + +impl InitFeatures { + /// Constructs init features from big-endian BOLT 9 encoded bytes. + #[uniffi::constructor] + pub fn from_bytes(bytes: &[u8]) -> Self { + Self { inner: LdkInitFeatures::from_be_bytes(bytes.to_vec()).into() } + } + + /// Returns the BOLT 9 big-endian encoded representation of these features. + pub fn to_bytes(&self) -> Vec { + self.inner.encode() + } + + /// Whether the peer's `init` message advertises support for `option_static_remotekey`. + pub fn supports_static_remote_key(&self) -> bool { + self.inner.supports_static_remote_key() + } + + /// Whether the peer's `init` message requires `option_static_remotekey`. + pub fn requires_static_remote_key(&self) -> bool { + self.inner.requires_static_remote_key() + } + + /// Whether the peer's `init` message advertises support for `option_anchors_zero_fee_htlc_tx`. + pub fn supports_anchors_zero_fee_htlc_tx(&self) -> bool { + self.inner.supports_anchors_zero_fee_htlc_tx() + } + + /// Whether the peer's `init` message requires `option_anchors_zero_fee_htlc_tx`. + pub fn requires_anchors_zero_fee_htlc_tx(&self) -> bool { + self.inner.requires_anchors_zero_fee_htlc_tx() + } + + /// Whether the peer's `init` message advertises support for `option_anchors_nonzero_fee_htlc_tx`. + pub fn supports_anchors_nonzero_fee_htlc_tx(&self) -> bool { + self.inner.supports_anchors_nonzero_fee_htlc_tx() + } + + /// Whether the peer's `init` message requires `option_anchors_nonzero_fee_htlc_tx`. + pub fn requires_anchors_nonzero_fee_htlc_tx(&self) -> bool { + self.inner.requires_anchors_nonzero_fee_htlc_tx() + } + + /// Whether the peer's `init` message advertises support for `option_support_large_channel`. + pub fn supports_wumbo(&self) -> bool { + self.inner.supports_wumbo() + } + + /// Whether the peer's `init` message requires `option_support_large_channel`. + pub fn requires_wumbo(&self) -> bool { + self.inner.requires_wumbo() + } + + /// Whether the peer's `init` message advertises support for `option_route_blinding`. + pub fn supports_route_blinding(&self) -> bool { + self.inner.supports_route_blinding() + } + + /// Whether the peer's `init` message requires `option_route_blinding`. + pub fn requires_route_blinding(&self) -> bool { + self.inner.requires_route_blinding() + } + + /// Whether the peer's `init` message advertises support for `option_onion_messages`. + pub fn supports_onion_messages(&self) -> bool { + self.inner.supports_onion_messages() + } + + /// Whether the peer's `init` message requires `option_onion_messages`. + pub fn requires_onion_messages(&self) -> bool { + self.inner.requires_onion_messages() + } + + /// Whether the peer's `init` message advertises support for `option_scid_alias`. + pub fn supports_scid_privacy(&self) -> bool { + self.inner.supports_scid_privacy() + } + + /// Whether the peer's `init` message requires `option_scid_alias`. + pub fn requires_scid_privacy(&self) -> bool { + self.inner.requires_scid_privacy() + } + + /// Whether the peer's `init` message advertises support for `option_zeroconf`. + pub fn supports_zero_conf(&self) -> bool { + self.inner.supports_zero_conf() + } + + /// Whether the peer's `init` message requires `option_zeroconf`. + pub fn requires_zero_conf(&self) -> bool { + self.inner.requires_zero_conf() + } + + /// Whether the peer's `init` message advertises support for `option_dual_fund`. + pub fn supports_dual_fund(&self) -> bool { + self.inner.supports_dual_fund() + } + + /// Whether the peer's `init` message requires `option_dual_fund`. + pub fn requires_dual_fund(&self) -> bool { + self.inner.requires_dual_fund() + } + + /// Whether the peer's `init` message advertises support for `option_quiesce`. + pub fn supports_quiescence(&self) -> bool { + self.inner.supports_quiescence() + } + + /// Whether the peer's `init` message requires `option_quiesce`. + pub fn requires_quiescence(&self) -> bool { + self.inner.requires_quiescence() + } + + /// Whether the peer's `init` message advertises support for `option_data_loss_protect`. + pub fn supports_data_loss_protect(&self) -> bool { + self.inner.supports_data_loss_protect() + } + + /// Whether the peer's `init` message requires `option_data_loss_protect`. + pub fn requires_data_loss_protect(&self) -> bool { + self.inner.requires_data_loss_protect() + } + + /// Whether the peer's `init` message advertises support for `option_upfront_shutdown_script`. + pub fn supports_upfront_shutdown_script(&self) -> bool { + self.inner.supports_upfront_shutdown_script() + } + + /// Whether the peer's `init` message requires `option_upfront_shutdown_script`. + pub fn requires_upfront_shutdown_script(&self) -> bool { + self.inner.requires_upfront_shutdown_script() + } + + /// Whether the peer's `init` message advertises support for `gossip_queries`. + pub fn supports_gossip_queries(&self) -> bool { + self.inner.supports_gossip_queries() + } + + /// Whether the peer's `init` message requires `gossip_queries`. + pub fn requires_gossip_queries(&self) -> bool { + self.inner.requires_gossip_queries() + } + + /// Whether the peer's `init` message advertises support for `var_onion_optin`. + pub fn supports_variable_length_onion(&self) -> bool { + self.inner.supports_variable_length_onion() + } + + /// Whether the peer's `init` message requires `var_onion_optin`. + pub fn requires_variable_length_onion(&self) -> bool { + self.inner.requires_variable_length_onion() + } + + /// Whether the peer's `init` message advertises support for `payment_secret`. + pub fn supports_payment_secret(&self) -> bool { + self.inner.supports_payment_secret() + } + + /// Whether the peer's `init` message requires `payment_secret`. + pub fn requires_payment_secret(&self) -> bool { + self.inner.requires_payment_secret() + } + + /// Whether the peer's `init` message advertises support for `basic_mpp`. + pub fn supports_basic_mpp(&self) -> bool { + self.inner.supports_basic_mpp() + } + + /// Whether the peer's `init` message requires `basic_mpp`. + pub fn requires_basic_mpp(&self) -> bool { + self.inner.requires_basic_mpp() + } + + /// Whether the peer's `init` message advertises support for `opt_shutdown_anysegwit`. + pub fn supports_shutdown_anysegwit(&self) -> bool { + self.inner.supports_shutdown_anysegwit() + } + + /// Whether the peer's `init` message requires `opt_shutdown_anysegwit`. + pub fn requires_shutdown_anysegwit(&self) -> bool { + self.inner.requires_shutdown_anysegwit() + } + + /// Whether the peer's `init` message advertises support for `option_channel_type`. + pub fn supports_channel_type(&self) -> bool { + self.inner.supports_channel_type() + } + + /// Whether the peer's `init` message requires `option_channel_type`. + pub fn requires_channel_type(&self) -> bool { + self.inner.requires_channel_type() + } + + /// Whether the peer's `init` message advertises support for `option_trampoline`. + pub fn supports_trampoline_routing(&self) -> bool { + self.inner.supports_trampoline_routing() + } + + /// Whether the peer's `init` message requires `option_trampoline`. + pub fn requires_trampoline_routing(&self) -> bool { + self.inner.requires_trampoline_routing() + } + + /// Whether the peer's `init` message advertises support for `option_simple_close`. + pub fn supports_simple_close(&self) -> bool { + self.inner.supports_simple_close() + } + + /// Whether the peer's `init` message requires `option_simple_close`. + pub fn requires_simple_close(&self) -> bool { + self.inner.requires_simple_close() + } + + /// Whether the peer's `init` message advertises support for `option_splice`. + pub fn supports_splicing(&self) -> bool { + self.inner.supports_splicing() + } + + /// Whether the peer's `init` message requires `option_splice`. + pub fn requires_splicing(&self) -> bool { + self.inner.requires_splicing() + } + + /// Whether the peer's `init` message advertises support for `option_provide_storage`. + pub fn supports_provide_storage(&self) -> bool { + self.inner.supports_provide_storage() + } + + /// Whether the peer's `init` message requires `option_provide_storage`. + pub fn requires_provide_storage(&self) -> bool { + self.inner.requires_provide_storage() + } + + /// Whether the peer's `init` message set `initial_routing_sync`. + pub fn initial_routing_sync(&self) -> bool { + self.inner.initial_routing_sync() + } + + /// Whether the peer's `init` message advertises support for `option_taproot`. + pub fn supports_taproot(&self) -> bool { + self.inner.supports_taproot() + } + + /// Whether the peer's `init` message requires `option_taproot`. + pub fn requires_taproot(&self) -> bool { + self.inner.requires_taproot() + } + + /// Whether the peer's `init` message advertises support for `option_zero_fee_commitments`. + pub fn supports_anchor_zero_fee_commitments(&self) -> bool { + self.inner.supports_anchor_zero_fee_commitments() + } + + /// Whether the peer's `init` message requires `option_zero_fee_commitments`. + pub fn requires_anchor_zero_fee_commitments(&self) -> bool { + self.inner.requires_anchor_zero_fee_commitments() + } + + /// Whether the peer's `init` message advertises support for HTLC hold. + pub fn supports_htlc_hold(&self) -> bool { + self.inner.supports_htlc_hold() + } + + /// Whether the peer's `init` message requires HTLC hold. + pub fn requires_htlc_hold(&self) -> bool { + self.inner.requires_htlc_hold() + } +} + +impl From for InitFeatures { + fn from(ldk_init: LdkInitFeatures) -> Self { + Self { inner: ldk_init } + } +} +/// Information needed for constructing an invoice route hint for this channel. +#[uniffi::remote(Record)] +pub struct CounterpartyForwardingInfo { + /// Base routing fee in millisatoshis. + pub fee_base_msat: u32, + /// Amount in millionths of a satoshi the channel will charge per transferred satoshi. + pub fee_proportional_millionths: u32, + /// The minimum difference in cltv_expiry between an ingoing HTLC and its outgoing counterpart, + /// such that the outgoing HTLC is forwardable to this counterparty. + pub cltv_expiry_delta: u16, +} + #[cfg(test)] mod tests { use std::num::NonZeroU64; diff --git a/src/lib.rs b/src/lib.rs index 614be098b..ce55a1dad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -180,7 +180,10 @@ use types::{ HRNResolver, KeysManager, OnionMessenger, PaymentStore, PeerManager, Router, Scorer, Sweeper, Wallet, }; -pub use types::{ChannelDetails, CustomTlvRecord, PeerDetails, SyncAndAsyncKVStore, UserChannelId}; +pub use types::{ + ChannelCounterparty, ChannelDetails, CustomTlvRecord, PeerDetails, ReserveType, + SyncAndAsyncKVStore, UserChannelId, +}; pub use vss_client; use crate::scoring::setup_background_pathfinding_scores_sync; @@ -1093,7 +1096,11 @@ impl Node { /// Retrieve a list of known channels. pub fn list_channels(&self) -> Vec { - self.channel_manager.list_channels().into_iter().map(|c| c.into()).collect() + self.channel_manager + .list_channels() + .into_iter() + .map(|c| ChannelDetails::from_ldk(c, self.config.anchor_channels_config.as_ref())) + .collect() } /// Connect to a node on the peer-to-peer network. diff --git a/src/types.rs b/src/types.rs index 06e65fbd0..9b1d1c1d9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -20,7 +20,9 @@ use bitcoin_payment_instructions::hrn_resolution::{ use bitcoin_payment_instructions::onion_message_resolver::LDKOnionMessageDNSSECHrnResolver; use lightning::chain::chainmonitor; use lightning::impl_writeable_tlv_based; -use lightning::ln::channel_state::{ChannelDetails as LdkChannelDetails, ChannelShutdownState}; +use lightning::ln::channel_state::{ + ChannelDetails as LdkChannelDetails, ChannelShutdownState, CounterpartyForwardingInfo, +}; use lightning::ln::msgs::{RoutingMessageHandler, SocketAddress}; use lightning::ln::peer_handler::IgnoringMessageHandler; use lightning::ln::types::ChannelId; @@ -38,14 +40,20 @@ use lightning_net_tokio::SocketDescriptor; use crate::chain::bitcoind::UtxoSourceClient; use crate::chain::ChainSource; -use crate::config::ChannelConfig; +use crate::config::{AnchorChannelsConfig, ChannelConfig}; use crate::data_store::DataStore; use crate::fee_estimator::OnchainFeeEstimator; +use crate::ffi::maybe_wrap; use crate::logger::Logger; use crate::message_handler::NodeCustomMessageHandler; use crate::payment::{PaymentDetails, PendingPaymentDetails}; use crate::runtime::RuntimeSpawner; +#[cfg(not(feature = "uniffi"))] +type InitFeatures = lightning::types::features::InitFeatures; +#[cfg(feature = "uniffi")] +type InitFeatures = Arc; + /// A supertrait that requires that a type implements both [`KVStore`] and [`KVStoreSync`] at the /// same time. pub trait SyncAndAsyncKVStore: KVStore + KVStoreSync {} @@ -415,6 +423,78 @@ impl fmt::Display for UserChannelId { } } +/// Channel parameters which apply to our counterparty. These are split out from [`ChannelDetails`] +/// to better separate parameters. +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +pub struct ChannelCounterparty { + /// The node_id of our counterparty + pub node_id: PublicKey, + /// The Features the channel counterparty provided upon last connection. + /// Useful for routing as it is the most up-to-date copy of the counterparty's features and + /// many routing-relevant features are present in the init context. + pub features: InitFeatures, + /// The value, in satoshis, that must always be held in the channel for our counterparty. This + /// value ensures that if our counterparty broadcasts a revoked state, we can punish them by + /// claiming at least this value on chain. + /// + /// This value is not included in [`inbound_capacity_msat`] as it can never be spent. + /// + /// [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat + pub unspendable_punishment_reserve: u64, + /// Information on the fees and requirements that the counterparty requires when forwarding + /// payments to us through this channel. + pub forwarding_info: Option, + /// The smallest value HTLC (in msat) the remote peer will accept, for this channel. + /// + /// Will be `None` before we have received the `OpenChannel` or `AcceptChannel` message + /// from the remote peer. + pub outbound_htlc_minimum_msat: Option, + /// The largest value HTLC (in msat) the remote peer currently will accept, for this channel. + pub outbound_htlc_maximum_msat: Option, +} + +/// Describes the reserve behavior of a channel based on its type and trust configuration. +/// +/// This captures the combination of the channel's on-chain construction (anchor outputs vs legacy +/// static_remote_key) and whether the counterparty is in our trusted peers list. It tells the +/// user what reserve obligations exist for this channel without exposing internal protocol details. +/// +/// See [`AnchorChannelsConfig`] for how reserve behavior is configured. +/// +/// [`AnchorChannelsConfig`]: crate::config::AnchorChannelsConfig +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +pub enum ReserveType { + /// An anchor outputs channel where we maintain a per-channel on-chain reserve for fee + /// bumping force-close transactions. + /// + /// Anchor channels allow either party to fee-bump commitment transactions via CPFP + /// at broadcast time. Because the pre-signed commitment fee may be insufficient under + /// current fee conditions, the broadcaster must supply additional funds (hence adaptive) + /// through an anchor output spend. The reserve ensures sufficient on-chain funds are + /// available to cover this. + /// + /// This is the default for anchor channels when the counterparty is not in + /// [`trusted_peers_no_reserve`]. + /// + /// [`trusted_peers_no_reserve`]: crate::config::AnchorChannelsConfig::trusted_peers_no_reserve + Adaptive, + /// An anchor outputs channel where we do not maintain any reserve, because the counterparty + /// is in our [`trusted_peers_no_reserve`] list. + /// + /// In this mode, we trust the counterparty to broadcast a valid commitment transaction on + /// our behalf and do not set aside funds for fee bumping. + /// + /// [`trusted_peers_no_reserve`]: crate::config::AnchorChannelsConfig::trusted_peers_no_reserve + TrustedPeersNoReserve, + /// A legacy (pre-anchor) channel using only `option_static_remotekey`. + /// + /// These channels do not use anchor outputs and therefore do not require an on-chain reserve + /// for fee bumping. Commitment transaction fees are pre-committed at channel open time. + Legacy, +} + /// Details of a channel as returned by [`Node::list_channels`]. /// /// When a channel is spliced, most fields continue to refer to the original pre-splice channel @@ -431,8 +511,8 @@ pub struct ChannelDetails { /// Note that this means this value is *not* persistent - it can change once during the /// lifetime of the channel. pub channel_id: ChannelId, - /// The node ID of our the channel's counterparty. - pub counterparty_node_id: PublicKey, + /// Parameters which apply to our counterparty. See individual fields for more information. + pub counterparty: ChannelCounterparty, /// The channel's funding transaction output, if we've negotiated the funding transaction with /// our counterparty already. /// @@ -548,28 +628,6 @@ pub struct ChannelDetails { /// The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over /// the channel. pub cltv_expiry_delta: Option, - /// The value, in satoshis, that must always be held in the channel for our counterparty. This - /// value ensures that if our counterparty broadcasts a revoked state, we can punish them by - /// claiming at least this value on chain. - /// - /// This value is not included in [`inbound_capacity_msat`] as it can never be spent. - /// - /// [`inbound_capacity_msat`]: ChannelDetails::inbound_capacity_msat - pub counterparty_unspendable_punishment_reserve: u64, - /// The smallest value HTLC (in msat) the remote peer will accept, for this channel. - /// - /// This field is only `None` before we have received either the `OpenChannel` or - /// `AcceptChannel` message from the remote peer. - pub counterparty_outbound_htlc_minimum_msat: Option, - /// The largest value HTLC (in msat) the remote peer currently will accept, for this channel. - pub counterparty_outbound_htlc_maximum_msat: Option, - /// Base routing fee in millisatoshis. - pub counterparty_forwarding_info_fee_base_msat: Option, - /// Proportional fee, in millionths of a satoshi the channel will charge per transferred satoshi. - pub counterparty_forwarding_info_fee_proportional_millionths: Option, - /// The minimum difference in CLTV expiry between an ingoing HTLC and its outgoing counterpart, - /// such that the outgoing HTLC is forwardable to this counterparty. - pub counterparty_forwarding_info_cltv_expiry_delta: Option, /// The available outbound capacity for sending a single HTLC to the remote peer. This is /// similar to [`ChannelDetails::outbound_capacity_msat`] but it may be further restricted by /// the current state and per-HTLC limit(s). This is intended for use when routing, allowing us @@ -601,13 +659,49 @@ pub struct ChannelDetails { /// /// Will be `None` for objects serialized with LDK Node v0.1 and earlier. pub channel_shutdown_state: Option, + /// The type of on-chain reserve maintained for this channel. + /// + /// See [`ReserveType`] for details on how reserves differ between anchor and legacy channels. + pub reserve_type: ReserveType, } -impl From for ChannelDetails { - fn from(value: LdkChannelDetails) -> Self { +impl ChannelDetails { + pub(crate) fn from_ldk( + value: LdkChannelDetails, anchor_channels_config: Option<&AnchorChannelsConfig>, + ) -> Self { + let reserve_type = + if value.channel_type.as_ref().is_some_and(|ct| ct.supports_anchors_zero_fee_htlc_tx()) + { + if let Some(config) = anchor_channels_config { + if config.trusted_peers_no_reserve.contains(&value.counterparty.node_id) { + ReserveType::TrustedPeersNoReserve + } else { + ReserveType::Adaptive + } + } else { + // Edge case: if `AnchorChannelsConfig` was previously set and later + // removed, we can no longer distinguish whether this anchor channel's + // reserve was `Adaptive` or `TrustedPeersNoReserve`. We default to + // `Adaptive` here, which may incorrectly override a prior + // `TrustedPeersNoReserve` designation. This is acceptable since + // unsetting `AnchorChannelsConfig` on a node with existing anchor + // channels is not an expected operation. + ReserveType::Adaptive + } + } else { + ReserveType::Legacy + }; + ChannelDetails { channel_id: value.channel_id, - counterparty_node_id: value.counterparty.node_id, + counterparty: ChannelCounterparty { + node_id: value.counterparty.node_id, + features: maybe_wrap(value.counterparty.features), + unspendable_punishment_reserve: value.counterparty.unspendable_punishment_reserve, + forwarding_info: value.counterparty.forwarding_info, + outbound_htlc_minimum_msat: value.counterparty.outbound_htlc_minimum_msat, + outbound_htlc_maximum_msat: value.counterparty.outbound_htlc_maximum_msat, + }, funding_txo: value.funding_txo.map(|o| o.into_bitcoin_outpoint()), funding_redeem_script: value.funding_redeem_script, short_channel_id: value.short_channel_id, @@ -628,26 +722,6 @@ impl From for ChannelDetails { is_usable: value.is_usable, is_announced: value.is_announced, cltv_expiry_delta: value.config.map(|c| c.cltv_expiry_delta), - counterparty_unspendable_punishment_reserve: value - .counterparty - .unspendable_punishment_reserve, - counterparty_outbound_htlc_minimum_msat: value.counterparty.outbound_htlc_minimum_msat, - counterparty_outbound_htlc_maximum_msat: value.counterparty.outbound_htlc_maximum_msat, - counterparty_forwarding_info_fee_base_msat: value - .counterparty - .forwarding_info - .as_ref() - .map(|f| f.fee_base_msat), - counterparty_forwarding_info_fee_proportional_millionths: value - .counterparty - .forwarding_info - .as_ref() - .map(|f| f.fee_proportional_millionths), - counterparty_forwarding_info_cltv_expiry_delta: value - .counterparty - .forwarding_info - .as_ref() - .map(|f| f.cltv_expiry_delta), next_outbound_htlc_limit_msat: value.next_outbound_htlc_limit_msat, next_outbound_htlc_minimum_msat: value.next_outbound_htlc_minimum_msat, force_close_spend_delay: value.force_close_spend_delay, @@ -660,6 +734,7 @@ impl From for ChannelDetails { .map(|c| c.into()) .expect("value is set for objects serialized with LDK v0.0.109+"), channel_shutdown_state: value.channel_shutdown_state, + reserve_type, } } } diff --git a/tests/integration_tests_rust.rs b/tests/integration_tests_rust.rs index 1ea6c4584..1d7f22c81 100644 --- a/tests/integration_tests_rust.rs +++ b/tests/integration_tests_rust.rs @@ -2212,7 +2212,7 @@ async fn lsps2_client_trusts_lsp() { client_node .list_channels() .iter() - .find(|c| c.counterparty_node_id == service_node_id) + .find(|c| c.counterparty.node_id == service_node_id) .unwrap() .confirmations, Some(0) @@ -2221,7 +2221,7 @@ async fn lsps2_client_trusts_lsp() { service_node .list_channels() .iter() - .find(|c| c.counterparty_node_id == client_node_id) + .find(|c| c.counterparty.node_id == client_node_id) .unwrap() .confirmations, Some(0) @@ -2256,7 +2256,7 @@ async fn lsps2_client_trusts_lsp() { client_node .list_channels() .iter() - .find(|c| c.counterparty_node_id == service_node_id) + .find(|c| c.counterparty.node_id == service_node_id) .unwrap() .confirmations, Some(6) @@ -2265,7 +2265,7 @@ async fn lsps2_client_trusts_lsp() { service_node .list_channels() .iter() - .find(|c| c.counterparty_node_id == client_node_id) + .find(|c| c.counterparty.node_id == client_node_id) .unwrap() .confirmations, Some(6) @@ -2385,7 +2385,7 @@ async fn lsps2_lsp_trusts_client_but_client_does_not_claim() { client_node .list_channels() .iter() - .find(|c| c.counterparty_node_id == service_node_id) + .find(|c| c.counterparty.node_id == service_node_id) .unwrap() .confirmations, Some(6) @@ -2394,7 +2394,7 @@ async fn lsps2_lsp_trusts_client_but_client_does_not_claim() { service_node .list_channels() .iter() - .find(|c| c.counterparty_node_id == client_node_id) + .find(|c| c.counterparty.node_id == client_node_id) .unwrap() .confirmations, Some(6) @@ -2880,7 +2880,7 @@ async fn open_channel_with_all_with_anchors() { assert_eq!(channels.len(), 1); let channel = &channels[0]; assert!(channel.channel_value_sats > premine_amount_sat - anchor_reserve_sat - 500); - assert_eq!(channel.counterparty_node_id, node_b.node_id()); + assert_eq!(channel.counterparty.node_id, node_b.node_id()); assert_eq!(channel.funding_txo.unwrap(), funding_txo); node_a.stop().unwrap(); @@ -2931,7 +2931,7 @@ async fn open_channel_with_all_without_anchors() { assert_eq!(channels.len(), 1); let channel = &channels[0]; assert!(channel.channel_value_sats > premine_amount_sat - 500); - assert_eq!(channel.counterparty_node_id, node_b.node_id()); + assert_eq!(channel.counterparty.node_id, node_b.node_id()); assert_eq!(channel.funding_txo.unwrap(), funding_txo); node_a.stop().unwrap();