Merge pull request #912 from TheBlueMatt/2021-05-more-chan-info

Add flags for if a channel is pub and funding txo in ChannelDetails
This commit is contained in:
Matt Corallo 2021-05-07 15:19:44 +00:00 committed by GitHub
commit 7297e13871
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 14 deletions

View file

@ -12,6 +12,7 @@ use bitcoin::blockdata::transaction::TxOut;
use bitcoin::hash_types::BlockHash; use bitcoin::hash_types::BlockHash;
use lightning::chain; use lightning::chain;
use lightning::chain::transaction::OutPoint;
use lightning::ln::channelmanager::ChannelDetails; use lightning::ln::channelmanager::ChannelDetails;
use lightning::ln::features::InitFeatures; use lightning::ln::features::InitFeatures;
use lightning::ln::msgs; use lightning::ln::msgs;
@ -20,6 +21,7 @@ use lightning::util::logger::Logger;
use lightning::util::ser::Readable; use lightning::util::ser::Readable;
use lightning::routing::network_graph::{NetworkGraph, RoutingFees}; use lightning::routing::network_graph::{NetworkGraph, RoutingFees};
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::key::PublicKey; use bitcoin::secp256k1::key::PublicKey;
use bitcoin::network::constants::Network; use bitcoin::network::constants::Network;
use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::constants::genesis_block;
@ -204,13 +206,17 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
let rnid = node_pks.iter().skip(slice_to_be16(get_slice!(2))as usize % node_pks.len()).next().unwrap(); let rnid = node_pks.iter().skip(slice_to_be16(get_slice!(2))as usize % node_pks.len()).next().unwrap();
first_hops_vec.push(ChannelDetails { first_hops_vec.push(ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(scid), short_channel_id: Some(scid),
remote_network_id: *rnid, remote_network_id: *rnid,
counterparty_features: InitFeatures::known(), counterparty_features: InitFeatures::known(),
channel_value_satoshis: slice_to_be64(get_slice!(8)), channel_value_satoshis: slice_to_be64(get_slice!(8)),
user_id: 0, user_id: 0,
inbound_capacity_msat: 0, inbound_capacity_msat: 0,
is_live: true, is_outbound: true,
is_funding_locked: true,
is_usable: true,
is_public: true,
outbound_capacity_msat: 0, outbound_capacity_msat: 0,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}); });

View file

@ -607,6 +607,12 @@ pub struct ChannelDetails {
/// Note that this means this value is *not* persistent - it can change once during the /// Note that this means this value is *not* persistent - it can change once during the
/// lifetime of the channel. /// lifetime of the channel.
pub channel_id: [u8; 32], pub channel_id: [u8; 32],
/// The Channel's funding transaction output, if we've negotiated the funding transaction with
/// our counterparty already.
///
/// Note that, if this has been set, `channel_id` will be equivalent to
/// `funding_txo.unwrap().to_channel_id()`.
pub funding_txo: Option<OutPoint>,
/// The position of the funding transaction in the chain. None if the funding transaction has /// The position of the funding transaction in the chain. None if the funding transaction has
/// not yet been confirmed and the channel fully opened. /// not yet been confirmed and the channel fully opened.
pub short_channel_id: Option<u64>, pub short_channel_id: Option<u64>,
@ -631,10 +637,21 @@ pub struct ChannelDetails {
/// Note that there are some corner cases not fully handled here, so the actual available /// Note that there are some corner cases not fully handled here, so the actual available
/// inbound capacity may be slightly higher than this. /// inbound capacity may be slightly higher than this.
pub inbound_capacity_msat: u64, pub inbound_capacity_msat: u64,
/// True if the channel was initiated (and thus funded) by us.
pub is_outbound: bool,
/// True if the channel is confirmed, funding_locked messages have been exchanged, and the
/// channel is not currently being shut down. `funding_locked` message exchange implies the
/// required confirmation count has been reached (and we were connected to the peer at some
/// point after the funding transaction received enough confirmations).
pub is_funding_locked: bool,
/// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b) /// True if the channel is (a) confirmed and funding_locked messages have been exchanged, (b)
/// the peer is connected, and (c) no monitor update failure is pending resolution. /// the peer is connected, (c) no monitor update failure is pending resolution, and (d) the
pub is_live: bool, /// channel is not currently negotiating a shutdown.
///
/// This is a strict superset of `is_funding_locked`.
pub is_usable: bool,
/// True if this channel is (or will be) publicly-announced.
pub is_public: bool,
/// Information on the fees and requirements that the counterparty requires when forwarding /// Information on the fees and requirements that the counterparty requires when forwarding
/// payments to us through this channel. /// payments to us through this channel.
pub counterparty_forwarding_info: Option<CounterpartyForwardingInfo>, pub counterparty_forwarding_info: Option<CounterpartyForwardingInfo>,
@ -957,6 +974,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat(); let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat();
res.push(ChannelDetails { res.push(ChannelDetails {
channel_id: (*channel_id).clone(), channel_id: (*channel_id).clone(),
funding_txo: channel.get_funding_txo(),
short_channel_id: channel.get_short_channel_id(), short_channel_id: channel.get_short_channel_id(),
remote_network_id: channel.get_counterparty_node_id(), remote_network_id: channel.get_counterparty_node_id(),
counterparty_features: InitFeatures::empty(), counterparty_features: InitFeatures::empty(),
@ -964,7 +982,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
inbound_capacity_msat, inbound_capacity_msat,
outbound_capacity_msat, outbound_capacity_msat,
user_id: channel.get_user_id(), user_id: channel.get_user_id(),
is_live: channel.is_live(), is_outbound: channel.is_outbound(),
is_funding_locked: channel.is_usable(),
is_usable: channel.is_live(),
is_public: channel.should_announce(),
counterparty_forwarding_info: channel.counterparty_forwarding_info(), counterparty_forwarding_info: channel.counterparty_forwarding_info(),
}); });
} }
@ -987,8 +1008,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
/// Gets the list of usable channels, in random order. Useful as an argument to /// Gets the list of usable channels, in random order. Useful as an argument to
/// get_route to ensure non-announced channels are used. /// get_route to ensure non-announced channels are used.
/// ///
/// These are guaranteed to have their is_live value set to true, see the documentation for /// These are guaranteed to have their [`ChannelDetails::is_usable`] value set to true, see the
/// ChannelDetails::is_live for more info on exactly what the criteria are. /// documentation for [`ChannelDetails::is_usable`] for more info on exactly what the criteria
/// are.
pub fn list_usable_channels(&self) -> Vec<ChannelDetails> { pub fn list_usable_channels(&self) -> Vec<ChannelDetails> {
// Note we use is_live here instead of usable which leads to somewhat confused // Note we use is_live here instead of usable which leads to somewhat confused
// internal/external nomenclature, but that's ok cause that's probably what the user // internal/external nomenclature, but that's ok cause that's probably what the user

View file

@ -1165,6 +1165,7 @@ pub fn get_route<L: Deref>(our_node_id: &PublicKey, network: &NetworkGraph, paye
mod tests { mod tests {
use routing::router::{get_route, RouteHintHop, RoutingFees}; use routing::router::{get_route, RouteHintHop, RoutingFees};
use routing::network_graph::{NetworkGraph, NetGraphMsgHandler}; use routing::network_graph::{NetworkGraph, NetGraphMsgHandler};
use chain::transaction::OutPoint;
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures}; use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler, use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate}; NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
@ -1625,6 +1626,7 @@ mod tests {
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(2), short_channel_id: Some(2),
remote_network_id: our_id, remote_network_id: our_id,
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -1632,7 +1634,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 100000, outbound_capacity_msat: 100000,
inbound_capacity_msat: 100000, inbound_capacity_msat: 100000,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];
@ -1943,6 +1946,7 @@ mod tests {
// If we specify a channel to node7, that overrides our local channel view and that gets used // If we specify a channel to node7, that overrides our local channel view and that gets used
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(42), short_channel_id: Some(42),
remote_network_id: nodes[7].clone(), remote_network_id: nodes[7].clone(),
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -1950,7 +1954,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 250_000_000, outbound_capacity_msat: 250_000_000,
inbound_capacity_msat: 0, inbound_capacity_msat: 0,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];
let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 100, 42, Arc::clone(&logger)).unwrap(); let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 100, 42, Arc::clone(&logger)).unwrap();
@ -1991,6 +1996,7 @@ mod tests {
// If we specify a channel to node7, that overrides our local channel view and that gets used // If we specify a channel to node7, that overrides our local channel view and that gets used
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(42), short_channel_id: Some(42),
remote_network_id: nodes[7].clone(), remote_network_id: nodes[7].clone(),
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -1998,7 +2004,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 250_000_000, outbound_capacity_msat: 250_000_000,
inbound_capacity_msat: 0, inbound_capacity_msat: 0,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];
let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 100, 42, Arc::clone(&logger)).unwrap(); let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 100, 42, Arc::clone(&logger)).unwrap();
@ -2056,6 +2063,7 @@ mod tests {
// If we specify a channel to node7, that overrides our local channel view and that gets used // If we specify a channel to node7, that overrides our local channel view and that gets used
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(42), short_channel_id: Some(42),
remote_network_id: nodes[7].clone(), remote_network_id: nodes[7].clone(),
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -2063,7 +2071,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 250_000_000, outbound_capacity_msat: 250_000_000,
inbound_capacity_msat: 0, inbound_capacity_msat: 0,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];
let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 100, 42, Arc::clone(&logger)).unwrap(); let route = get_route(&our_id, &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[2], None, Some(&our_chans.iter().collect::<Vec<_>>()), &Vec::new(), 100, 42, Arc::clone(&logger)).unwrap();
@ -2193,6 +2202,7 @@ mod tests {
// Simple test with outbound channel to 4 to test that last_hops and first_hops connect // Simple test with outbound channel to 4 to test that last_hops and first_hops connect
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(42), short_channel_id: Some(42),
remote_network_id: nodes[3].clone(), remote_network_id: nodes[3].clone(),
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -2200,7 +2210,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 250_000_000, outbound_capacity_msat: 250_000_000,
inbound_capacity_msat: 0, inbound_capacity_msat: 0,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];
let mut last_hops = last_hops(&nodes); let mut last_hops = last_hops(&nodes);
@ -2322,6 +2333,7 @@ mod tests {
}]; }];
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(42), short_channel_id: Some(42),
remote_network_id: middle_node_id, remote_network_id: middle_node_id,
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -2329,7 +2341,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 100000, outbound_capacity_msat: 100000,
inbound_capacity_msat: 100000, inbound_capacity_msat: 100000,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];
let route = get_route(&source_node_id, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()), &target_node_id, None, Some(&our_chans.iter().collect::<Vec<_>>()), &last_hops.iter().collect::<Vec<_>>(), 100, 42, Arc::new(test_utils::TestLogger::new())).unwrap(); let route = get_route(&source_node_id, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()), &target_node_id, None, Some(&our_chans.iter().collect::<Vec<_>>()), &last_hops.iter().collect::<Vec<_>>(), 100, 42, Arc::new(test_utils::TestLogger::new())).unwrap();
@ -2454,6 +2467,7 @@ mod tests {
// Now, limit the first_hop by the outbound_capacity_msat of 200_000 sats. // Now, limit the first_hop by the outbound_capacity_msat of 200_000 sats.
let our_chans = vec![channelmanager::ChannelDetails { let our_chans = vec![channelmanager::ChannelDetails {
channel_id: [0; 32], channel_id: [0; 32],
funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
short_channel_id: Some(42), short_channel_id: Some(42),
remote_network_id: nodes[0].clone(), remote_network_id: nodes[0].clone(),
counterparty_features: InitFeatures::from_le_bytes(vec![0b11]), counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
@ -2461,7 +2475,8 @@ mod tests {
user_id: 0, user_id: 0,
outbound_capacity_msat: 200_000_000, outbound_capacity_msat: 200_000_000,
inbound_capacity_msat: 0, inbound_capacity_msat: 0,
is_live: true, is_outbound: true, is_funding_locked: true,
is_usable: true, is_public: true,
counterparty_forwarding_info: None, counterparty_forwarding_info: None,
}]; }];