@@ -52,6 +52,7 @@ use chain::keysinterface::{Sign, KeysInterface, KeysManager, InMemorySigner, Rec
5252use util:: config:: UserConfig ;
5353use util:: events:: { EventHandler , EventsProvider , MessageSendEvent , MessageSendEventsProvider , ClosureReason } ;
5454use util:: { byte_utils, events} ;
55+ use util:: scid_utils:: fake_scid;
5556use util:: ser:: { BigSize , FixedLengthReader , Readable , ReadableArgs , MaybeReadable , Writeable , Writer } ;
5657use util:: logger:: { Level , Logger } ;
5758use util:: errors:: APIError ;
@@ -973,6 +974,13 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
973974
974975 inbound_payment_key : inbound_payment:: ExpandedKey ,
975976
977+ /// LDK puts the [fake scids] that it generates into namespaces, to identify the type of an
978+ /// incoming payment. To make it harder for a third-party to identify the type of a payment,
979+ /// we encrypt the namespace identifier using these bytes.
980+ ///
981+ /// [fake scids]: crate::util::scid_utils::fake_scid
982+ fake_scid_rand_bytes : [ u8 ; 32 ] ,
983+
976984 /// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
977985 /// value increases strictly since we don't assume access to a time source.
978986 last_node_announcement_serial : AtomicUsize ,
@@ -1309,6 +1317,19 @@ pub enum PaymentSendFailure {
13091317 } ,
13101318}
13111319
1320+ /// Route hints used in constructing invoices for [phantom node payents].
1321+ ///
1322+ /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
1323+ pub struct PhantomRouteHints {
1324+ /// The list of channels to be included in the invoice route hints.
1325+ pub channels : Vec < ChannelDetails > ,
1326+ /// A fake scid used for representing the phantom node's fake channel in generating the invoice
1327+ /// route hints.
1328+ pub phantom_scid : u64 ,
1329+ /// The pubkey of the real backing node that would ultimately receive the payment.
1330+ pub real_node_pubkey : PublicKey ,
1331+ }
1332+
13121333macro_rules! handle_error {
13131334 ( $self: ident, $internal: expr, $counterparty_node_id: expr) => {
13141335 match $internal {
@@ -1690,6 +1711,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16901711 secp_ctx,
16911712
16921713 inbound_payment_key : expanded_inbound_key,
1714+ fake_scid_rand_bytes : keys_manager. get_secure_random_bytes ( ) ,
16931715
16941716 last_node_announcement_serial : AtomicUsize :: new ( 0 ) ,
16951717 highest_seen_timestamp : AtomicUsize :: new ( 0 ) ,
@@ -5089,6 +5111,34 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
50895111 inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
50905112 }
50915113
5114+ /// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids
5115+ /// are used when constructing the phantom invoice's route hints.
5116+ ///
5117+ /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
5118+ pub fn get_phantom_scid ( & self ) -> u64 {
5119+ let mut channel_state = self . channel_state . lock ( ) . unwrap ( ) ;
5120+ let best_block = self . best_block . read ( ) . unwrap ( ) ;
5121+ loop {
5122+ let scid_candidate = fake_scid:: get_phantom_scid ( & self . fake_scid_rand_bytes , best_block. height ( ) , & self . genesis_hash , & self . keys_manager ) ;
5123+ // Ensure the generated scid doesn't conflict with a real channel.
5124+ match channel_state. short_to_id . entry ( scid_candidate) {
5125+ hash_map:: Entry :: Occupied ( _) => continue ,
5126+ hash_map:: Entry :: Vacant ( _) => return scid_candidate
5127+ }
5128+ }
5129+ }
5130+
5131+ /// Gets route hints for use in receiving [phantom node payments].
5132+ ///
5133+ /// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
5134+ pub fn get_phantom_route_hints ( & self ) -> PhantomRouteHints {
5135+ PhantomRouteHints {
5136+ channels : self . list_usable_channels ( ) ,
5137+ phantom_scid : self . get_phantom_scid ( ) ,
5138+ real_node_pubkey : self . get_our_node_id ( ) ,
5139+ }
5140+ }
5141+
50925142 #[ cfg( any( test, feature = "fuzztarget" , feature = "_test_utils" ) ) ]
50935143 pub fn get_and_clear_pending_events ( & self ) -> Vec < events:: Event > {
50945144 let events = core:: cell:: RefCell :: new ( Vec :: new ( ) ) ;
@@ -5819,6 +5869,12 @@ impl_writeable_tlv_based!(ChannelDetails, {
58195869 ( 32 , is_public, required) ,
58205870} ) ;
58215871
5872+ impl_writeable_tlv_based ! ( PhantomRouteHints , {
5873+ ( 2 , channels, vec_type) ,
5874+ ( 4 , phantom_scid, required) ,
5875+ ( 6 , real_node_pubkey, required) ,
5876+ } ) ;
5877+
58225878impl_writeable_tlv_based_enum ! ( PendingHTLCRouting ,
58235879 ( 0 , Forward ) => {
58245880 ( 0 , onion_packet, required) ,
@@ -6220,7 +6276,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
62206276 write_tlv_fields ! ( writer, {
62216277 ( 1 , pending_outbound_payments_no_retry, required) ,
62226278 ( 3 , pending_outbound_payments, required) ,
6223- ( 5 , self . our_network_pubkey, required)
6279+ ( 5 , self . our_network_pubkey, required) ,
6280+ ( 7 , self . fake_scid_rand_bytes, required) ,
62246281 } ) ;
62256282
62266283 Ok ( ( ) )
@@ -6516,11 +6573,16 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
65166573 let mut pending_outbound_payments_no_retry: Option < HashMap < PaymentId , HashSet < [ u8 ; 32 ] > > > = None ;
65176574 let mut pending_outbound_payments = None ;
65186575 let mut received_network_pubkey: Option < PublicKey > = None ;
6576+ let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
65196577 read_tlv_fields ! ( reader, {
65206578 ( 1 , pending_outbound_payments_no_retry, option) ,
65216579 ( 3 , pending_outbound_payments, option) ,
6522- ( 5 , received_network_pubkey, option)
6580+ ( 5 , received_network_pubkey, option) ,
6581+ ( 7 , fake_scid_rand_bytes, option) ,
65236582 } ) ;
6583+ if fake_scid_rand_bytes. is_none ( ) {
6584+ fake_scid_rand_bytes = Some ( args. keys_manager . get_secure_random_bytes ( ) ) ;
6585+ }
65246586
65256587 if pending_outbound_payments. is_none ( ) && pending_outbound_payments_no_retry. is_none ( ) {
65266588 pending_outbound_payments = Some ( pending_outbound_payments_compat) ;
@@ -6616,6 +6678,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
66166678 inbound_payment_key : expanded_inbound_key,
66176679 pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
66186680 pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
6681+ fake_scid_rand_bytes : fake_scid_rand_bytes. unwrap ( ) ,
66196682
66206683 our_network_key,
66216684 our_network_pubkey,
0 commit comments