@@ -17,7 +17,7 @@ use bitcoin::secp256k1::PublicKey;
17
17
use ln:: channelmanager:: ChannelDetails ;
18
18
use ln:: features:: { ChannelFeatures , InvoiceFeatures , NodeFeatures } ;
19
19
use ln:: msgs:: { DecodeError , ErrorAction , LightningError , MAX_VALUE_MSAT } ;
20
- use routing:: scoring:: { ChannelUsage , Score } ;
20
+ use routing:: scoring:: { ChannelUsage , Score , DynamicPenaltyScorer } ;
21
21
use routing:: network_graph:: { DirectedChannelInfoWithUpdate , EffectiveCapacity , NetworkGraph , ReadOnlyNetworkGraph , NodeId , RoutingFees } ;
22
22
use util:: ser:: { Writeable , Readable } ;
23
23
use util:: logger:: { Level , Logger } ;
@@ -151,7 +151,7 @@ impl Readable for Route {
151
151
152
152
/// Parameters needed to find a [`Route`].
153
153
///
154
- /// Passed to [`find_route`] and also provided in [`Event::PaymentPathFailed`] for retrying a failed
154
+ /// Passed to [`find_route`] and [`build_route_from_hops`], but also provided in [`Event::PaymentPathFailed`] for retrying a failed
155
155
/// payment path.
156
156
///
157
157
/// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
@@ -1785,6 +1785,49 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
1785
1785
}
1786
1786
}
1787
1787
1788
+ /// Build a route from us (payer) with the given hops ending at the target node (payee).
1789
+ ///
1790
+ /// Re-uses logic from `find_route`, so the restrictions described there also apply here.
1791
+ pub fn build_route_from_hops < L : Deref > (
1792
+ our_node_pubkey : & PublicKey , hops : & [ PublicKey ] , route_params : & RouteParameters , network : & NetworkGraph ,
1793
+ logger : L , random_seed_bytes : & [ u8 ; 32 ] ) -> Result < Route , LightningError >
1794
+ where L :: Target : Logger {
1795
+ let network_graph = network. read_only ( ) ;
1796
+ match build_route_from_hops_internal (
1797
+ our_node_pubkey, hops, & route_params. payment_params , & network_graph,
1798
+ route_params. final_value_msat , route_params. final_cltv_expiry_delta , logger, random_seed_bytes
1799
+ ) {
1800
+ Ok ( mut route) => {
1801
+ add_random_cltv_offset ( & mut route, & route_params. payment_params , & network_graph, random_seed_bytes) ;
1802
+ Ok ( route)
1803
+ } ,
1804
+ Err ( err) => Err ( err) ,
1805
+ }
1806
+ }
1807
+
1808
+ fn build_route_from_hops_internal < L : Deref > (
1809
+ our_node_pubkey : & PublicKey , hops : & [ PublicKey ] , payment_params : & PaymentParameters ,
1810
+ network_graph : & ReadOnlyNetworkGraph , final_value_msat : u64 , final_cltv_expiry_delta : u32 ,
1811
+ logger : L , random_seed_bytes : & [ u8 ; 32 ] ) -> Result < Route , LightningError > where L :: Target : Logger {
1812
+
1813
+ let node_ids_iter = hops. iter ( ) . map ( |hop_pubkey| NodeId :: from_pubkey ( & hop_pubkey) ) ;
1814
+ let hop_iter = core:: iter:: once ( NodeId :: from_pubkey ( & our_node_pubkey) )
1815
+ . chain ( node_ids_iter. clone ( ) )
1816
+ . zip ( node_ids_iter) ;
1817
+ let filter_channels = |_short_channel_id : u64 , source : & NodeId , target : & NodeId ,
1818
+ _usage : ChannelUsage | {
1819
+ match hop_iter. clone ( ) . find ( |( cur_id, next_id) | { * cur_id == * source && * next_id == * target } ) {
1820
+ Some ( _) => 0 ,
1821
+ None => u64:: max_value ( )
1822
+ }
1823
+ } ;
1824
+
1825
+ let scorer = DynamicPenaltyScorer :: with_penalty_func ( filter_channels) ;
1826
+
1827
+ get_route ( our_node_pubkey, payment_params, network_graph, None , final_value_msat,
1828
+ final_cltv_expiry_delta, logger, & scorer, random_seed_bytes)
1829
+ }
1830
+
1788
1831
#[ cfg( test) ]
1789
1832
mod tests {
1790
1833
use routing:: network_graph:: { NetworkGraph , NetGraphMsgHandler , NodeId } ;
0 commit comments