@@ -52,6 +52,7 @@ use chain::keysinterface::{Sign, KeysInterface, KeysManager, InMemorySigner, Rec
52
52
use util:: config:: UserConfig ;
53
53
use util:: events:: { EventHandler , EventsProvider , MessageSendEvent , MessageSendEventsProvider , ClosureReason } ;
54
54
use util:: { byte_utils, events} ;
55
+ use util:: scid_utils:: fake_scid;
55
56
use util:: ser:: { BigSize , FixedLengthReader , Readable , ReadableArgs , MaybeReadable , Writeable , Writer } ;
56
57
use util:: logger:: { Level , Logger } ;
57
58
use util:: errors:: APIError ;
@@ -973,6 +974,13 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
973
974
974
975
inbound_payment_key : inbound_payment:: ExpandedKey ,
975
976
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
+
976
984
/// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
977
985
/// value increases strictly since we don't assume access to a time source.
978
986
last_node_announcement_serial : AtomicUsize ,
@@ -1309,6 +1317,19 @@ pub enum PaymentSendFailure {
1309
1317
} ,
1310
1318
}
1311
1319
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
+
1312
1333
macro_rules! handle_error {
1313
1334
( $self: ident, $internal: expr, $counterparty_node_id: expr) => {
1314
1335
match $internal {
@@ -1690,6 +1711,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1690
1711
secp_ctx,
1691
1712
1692
1713
inbound_payment_key : expanded_inbound_key,
1714
+ fake_scid_rand_bytes : keys_manager. get_secure_random_bytes ( ) ,
1693
1715
1694
1716
last_node_announcement_serial : AtomicUsize :: new ( 0 ) ,
1695
1717
highest_seen_timestamp : AtomicUsize :: new ( 0 ) ,
@@ -5089,6 +5111,34 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
5089
5111
inbound_payment:: get_payment_preimage ( payment_hash, payment_secret, & self . inbound_payment_key )
5090
5112
}
5091
5113
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
+
5092
5142
#[ cfg( any( test, feature = "fuzztarget" , feature = "_test_utils" ) ) ]
5093
5143
pub fn get_and_clear_pending_events ( & self ) -> Vec < events:: Event > {
5094
5144
let events = core:: cell:: RefCell :: new ( Vec :: new ( ) ) ;
@@ -5819,6 +5869,12 @@ impl_writeable_tlv_based!(ChannelDetails, {
5819
5869
( 32 , is_public, required) ,
5820
5870
} ) ;
5821
5871
5872
+ impl_writeable_tlv_based ! ( PhantomRouteHints , {
5873
+ ( 2 , channels, vec_type) ,
5874
+ ( 4 , phantom_scid, required) ,
5875
+ ( 6 , real_node_pubkey, required) ,
5876
+ } ) ;
5877
+
5822
5878
impl_writeable_tlv_based_enum ! ( PendingHTLCRouting ,
5823
5879
( 0 , Forward ) => {
5824
5880
( 0 , onion_packet, required) ,
@@ -6220,7 +6276,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
6220
6276
write_tlv_fields ! ( writer, {
6221
6277
( 1 , pending_outbound_payments_no_retry, required) ,
6222
6278
( 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) ,
6224
6281
} ) ;
6225
6282
6226
6283
Ok ( ( ) )
@@ -6516,11 +6573,16 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6516
6573
let mut pending_outbound_payments_no_retry: Option < HashMap < PaymentId , HashSet < [ u8 ; 32 ] > > > = None ;
6517
6574
let mut pending_outbound_payments = None ;
6518
6575
let mut received_network_pubkey: Option < PublicKey > = None ;
6576
+ let mut fake_scid_rand_bytes: Option < [ u8 ; 32 ] > = None ;
6519
6577
read_tlv_fields ! ( reader, {
6520
6578
( 1 , pending_outbound_payments_no_retry, option) ,
6521
6579
( 3 , pending_outbound_payments, option) ,
6522
- ( 5 , received_network_pubkey, option)
6580
+ ( 5 , received_network_pubkey, option) ,
6581
+ ( 7 , fake_scid_rand_bytes, option) ,
6523
6582
} ) ;
6583
+ if fake_scid_rand_bytes. is_none ( ) {
6584
+ fake_scid_rand_bytes = Some ( args. keys_manager . get_secure_random_bytes ( ) ) ;
6585
+ }
6524
6586
6525
6587
if pending_outbound_payments. is_none ( ) && pending_outbound_payments_no_retry. is_none ( ) {
6526
6588
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>
6616
6678
inbound_payment_key : expanded_inbound_key,
6617
6679
pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
6618
6680
pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
6681
+ fake_scid_rand_bytes : fake_scid_rand_bytes. unwrap ( ) ,
6619
6682
6620
6683
our_network_key,
6621
6684
our_network_pubkey,
0 commit comments