@@ -649,6 +649,48 @@ pub struct ChannelInfo {
649649 announcement_received_time : u64 ,
650650}
651651
652+ impl ChannelInfo {
653+ /// Returns a [`DirectedChannelInfo`] for the channel from `source` to `target`.
654+ ///
655+ /// # Panics
656+ ///
657+ /// Panics if `source` and `target` are not the channel's counterparties.
658+ pub fn as_directed ( & self , source : & NodeId , target : & NodeId ) -> DirectedChannelInfo {
659+ let ( direction, source, target) = {
660+ if source == & self . node_one && target == & self . node_two {
661+ ( self . one_to_two . as_ref ( ) , & self . node_one , & self . node_two )
662+ } else if source == & self . node_two && target == & self . node_one {
663+ ( self . two_to_one . as_ref ( ) , & self . node_two , & self . node_one )
664+ } else if source != & self . node_one && source != & self . node_two {
665+ panic ! ( "Unknown source node: {:?}" , source)
666+ } else if target != & self . node_one && target != & self . node_two {
667+ panic ! ( "Unknown target node: {:?}" , target)
668+ } else {
669+ unreachable ! ( )
670+ }
671+ } ;
672+ DirectedChannelInfo { channel : self , direction, source, target }
673+ }
674+
675+ /// Returns a [`DirectedChannelInfo`] for the channel directed to the given `target`.
676+ ///
677+ /// # Panics
678+ ///
679+ /// Panics if `target` is not one of the channel's counterparties.
680+ pub fn directed_to ( & self , target : & NodeId ) -> DirectedChannelInfo {
681+ let ( direction, source, target) = {
682+ if target == & self . node_one {
683+ ( self . two_to_one . as_ref ( ) , & self . node_two , & self . node_one )
684+ } else if target == & self . node_two {
685+ ( self . one_to_two . as_ref ( ) , & self . node_one , & self . node_two )
686+ } else {
687+ panic ! ( "Unknown target node: {:?}" , target)
688+ }
689+ } ;
690+ DirectedChannelInfo { channel : self , direction, source, target }
691+ }
692+ }
693+
652694impl fmt:: Display for ChannelInfo {
653695 fn fmt ( & self , f : & mut fmt:: Formatter ) -> Result < ( ) , fmt:: Error > {
654696 write ! ( f, "features: {}, node_one: {}, one_to_two: {:?}, node_two: {}, two_to_one: {:?}" ,
@@ -668,6 +710,105 @@ impl_writeable_tlv_based!(ChannelInfo, {
668710 ( 12 , announcement_message, required) ,
669711} ) ;
670712
713+ /// A wrapper around [`ChannelInfo`] representing information about the channel as directed from a
714+ /// source node to a target node.
715+ pub struct DirectedChannelInfo < ' a : ' b , ' b > {
716+ channel : & ' a ChannelInfo ,
717+ direction : Option < & ' b DirectionalChannelInfo > ,
718+ source : & ' b NodeId ,
719+ target : & ' b NodeId ,
720+ }
721+
722+ impl < ' a : ' b , ' b > DirectedChannelInfo < ' a , ' b > {
723+ /// Returns the node id for the source.
724+ pub fn source ( & self ) -> & ' b NodeId { self . source }
725+
726+ /// Returns the node id for the target.
727+ pub fn target ( & self ) -> & ' b NodeId { self . target }
728+
729+ /// Consumes the [`DirectedChannelInfo`], returning the wrapped parts.
730+ pub fn into_parts ( self ) -> ( & ' a ChannelInfo , Option < & ' b DirectionalChannelInfo > ) {
731+ ( self . channel , self . direction )
732+ }
733+
734+ /// Returns the [`EffectiveCapacity`] of the channel in a specific direction.
735+ ///
736+ /// This is either the total capacity from the funding transaction, if known, or the
737+ /// `htlc_maximum_msat` for the direction as advertised by the gossip network, if known,
738+ /// whichever is smaller.
739+ pub fn effective_capacity ( & self ) -> EffectiveCapacity {
740+ Self :: effective_capacity_from_parts ( self . channel , self . direction )
741+ }
742+
743+ /// Returns the [`EffectiveCapacity`] of the channel in the given direction.
744+ ///
745+ /// See [`Self::effective_capacity`] for details.
746+ pub fn effective_capacity_from_parts (
747+ channel : & ChannelInfo , direction : Option < & DirectionalChannelInfo >
748+ ) -> EffectiveCapacity {
749+ let capacity_msat = channel. capacity_sats . map ( |capacity_sats| capacity_sats * 1000 ) ;
750+ direction
751+ . and_then ( |direction| direction. htlc_maximum_msat )
752+ . map ( |max_htlc_msat| {
753+ let capacity_msat = capacity_msat. unwrap_or ( u64:: max_value ( ) ) ;
754+ if max_htlc_msat < capacity_msat {
755+ EffectiveCapacity :: MaximumHTLC { amount_msat : max_htlc_msat }
756+ } else {
757+ EffectiveCapacity :: Total { capacity_msat }
758+ }
759+ } )
760+ . or_else ( || capacity_msat. map ( |capacity_msat|
761+ EffectiveCapacity :: Total { capacity_msat } ) )
762+ . unwrap_or ( EffectiveCapacity :: Unknown )
763+ }
764+ }
765+
766+ /// The effective capacity of a channel for routing purposes.
767+ ///
768+ /// While this may be smaller than the actual channel capacity, amounts greater than
769+ /// [`Self::as_msat`] should not be routed through the channel.
770+ pub enum EffectiveCapacity {
771+ /// The available liquidity in the channel known from being a channel counterparty, and thus a
772+ /// direct hop.
773+ ExactLiquidity {
774+ /// Either the inbound or outbound liquidity depending on the direction, denominated in
775+ /// millisatoshi.
776+ liquidity_msast : u64 ,
777+ } ,
778+ /// The maximum HTLC amount in one direction as advertised on the gossip network.
779+ MaximumHTLC {
780+ /// The maximum HTLC amount denominated in millisatoshi.
781+ amount_msat : u64 ,
782+ } ,
783+ /// The total capacity of the channel as determined by the funding transaction.
784+ Total {
785+ /// The funding amount denominated in millisatoshi.
786+ capacity_msat : u64 ,
787+ } ,
788+ /// A capacity sufficient to route any payment, typically used for private channels provided by
789+ /// an invoice, though may not be the case for zero-amount invoices.
790+ Infinite ,
791+ /// A capacity that is unknown possibly because either the chain state is unavailable to know
792+ /// the total capacity or the `htlc_maximum_msat` was not advertised on the gossip network.
793+ Unknown ,
794+ }
795+
796+ /// The presumed channel capacity denominated in millisatoshi for [`EffectiveCapacity::Unknown`] to
797+ /// use when making routing decisions.
798+ pub const UNKNOWN_CHANNEL_CAPACITY_MSAT : u64 = 250_000 * 1000 ;
799+
800+ impl EffectiveCapacity {
801+ /// Returns the effective capacity denominated in millisatoshi.
802+ pub fn as_msat ( & self ) -> u64 {
803+ match self {
804+ EffectiveCapacity :: ExactLiquidity { liquidity_msast } => * liquidity_msast,
805+ EffectiveCapacity :: MaximumHTLC { amount_msat } => * amount_msat,
806+ EffectiveCapacity :: Total { capacity_msat } => * capacity_msat,
807+ EffectiveCapacity :: Infinite => u64:: max_value ( ) ,
808+ EffectiveCapacity :: Unknown => UNKNOWN_CHANNEL_CAPACITY_MSAT ,
809+ }
810+ }
811+ }
671812
672813/// Fees for routing via a given channel or a node
673814#[ derive( Eq , PartialEq , Copy , Clone , Debug , Hash ) ]
0 commit comments