@@ -338,6 +338,103 @@ mod inbound_payment {
338
338
}
339
339
}
340
340
341
+ mod fake_scid {
342
+ use bitcoin:: blockdata:: constants:: genesis_block;
343
+ use bitcoin:: hash_types:: BlockHash ;
344
+ use bitcoin:: network:: constants:: Network ;
345
+ use chain:: keysinterface:: { Sign , KeysInterface } ;
346
+ use ln:: channelmanager:: DecodeError ;
347
+ use util:: scid_utils;
348
+ use util:: ser:: Readable ;
349
+
350
+ use core:: convert:: TryInto ;
351
+ use core:: ops:: Deref ;
352
+
353
+ const TEST_SEGWIT_ACTIVATION_HEIGHT : u32 = 0 ;
354
+ const MAINNET_SEGWIT_ACTIVATION_HEIGHT : u32 = 481_824 ;
355
+ const MAX_TX_INDEX : u32 = 2_500 ;
356
+ const MAX_VOUT : u16 = 10_000 ;
357
+ const MAX_NAMESPACES : u8 = 8 ;
358
+ const NAMESPACE_TYPE_BITMASK : u8 = 0b111 ;
359
+
360
+ pub ( super ) enum Namespace {
361
+ Phantom ( u8 ) ,
362
+ // Coming soon: a variant for the zero-conf scid namespace
363
+ }
364
+
365
+ impl Namespace {
366
+ pub ( super ) fn get_fake_scid < Signer : Sign , K : Deref > ( & self , highest_seen_blockheight : u32 , genesis_hash : & BlockHash , keys_manager : & K ) -> u64
367
+ where K :: Target : KeysInterface < Signer = Signer > ,
368
+ {
369
+ let scid_namespace = self . as_u8 ( ) ;
370
+ let rand_bytes = keys_manager. get_secure_random_bytes ( ) ;
371
+
372
+ let valid_block_range = highest_seen_blockheight - segwit_activation_height ( genesis_hash) ;
373
+ let rand_value_for_height = u32:: from_be_bytes ( rand_bytes[ ..4 ] . try_into ( ) . unwrap ( ) ) ;
374
+ let fake_scid_height = segwit_activation_height ( genesis_hash) + rand_value_for_height % valid_block_range;
375
+
376
+ let rand_i32 = i32:: from_be_bytes ( rand_bytes[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) . abs ( ) ;
377
+ let rand_tx_index = rand_i32 % ( MAX_TX_INDEX as i32 ) ;
378
+ let offset = ( scid_namespace as i32 - rand_tx_index) % ( MAX_NAMESPACES as i32 ) ;
379
+ let fake_scid_tx_index: u64 = ( rand_tx_index + offset) as u64 ;
380
+
381
+ let rand_value_for_vout = u16:: from_be_bytes ( rand_bytes[ 8 ..10 ] . try_into ( ) . unwrap ( ) ) ;
382
+ let fake_scid_vout_index = rand_value_for_vout % MAX_VOUT ;
383
+ scid_utils:: scid_from_parts ( fake_scid_height as u64 , fake_scid_tx_index, fake_scid_vout_index as u64 ) . unwrap ( )
384
+ }
385
+
386
+ fn as_u8 ( & self ) -> u8 {
387
+ match self {
388
+ Namespace :: Phantom ( namespace) => * namespace,
389
+ }
390
+ }
391
+
392
+ pub ( super ) fn phantom < Signer : Sign , K : Deref > ( keys_manager : & K ) -> Namespace
393
+ where K :: Target : KeysInterface < Signer = Signer > ,
394
+ {
395
+ let phantom_scid_namespace_rand_bytes = keys_manager. get_secure_random_bytes ( ) ;
396
+ let phantom_scid_namespace = phantom_scid_namespace_rand_bytes[ 0 ] & NAMESPACE_TYPE_BITMASK ;
397
+ Namespace :: Phantom ( phantom_scid_namespace)
398
+ }
399
+ }
400
+
401
+ // XXX test
402
+ fn segwit_activation_height ( genesis : & BlockHash ) -> u32 {
403
+ if genesis_block ( Network :: Bitcoin ) . header . block_hash ( ) == * genesis {
404
+ MAINNET_SEGWIT_ACTIVATION_HEIGHT
405
+ } else {
406
+ TEST_SEGWIT_ACTIVATION_HEIGHT
407
+ }
408
+ }
409
+
410
+ // XXX docs, test
411
+ pub ( super ) fn is_valid ( namespace : & Namespace , scid : u64 ) -> bool {
412
+ scid_utils:: tx_index_from_scid ( & scid) % MAX_NAMESPACES as u32 == namespace. as_u8 ( ) as u32
413
+ }
414
+
415
+ impl_writeable_tlv_based_enum ! ( Namespace , ;
416
+ ( 0 , Phantom ) ,
417
+ ) ;
418
+
419
+ #[ cfg( test) ]
420
+ mod tests {
421
+ use bitcoin:: network:: constants:: Network ;
422
+ use ln:: channelmanager:: fake_scid:: { Namespace , NAMESPACE_TYPE_BITMASK } ;
423
+ use util:: test_utils;
424
+ use sync:: Arc ;
425
+
426
+ #[ test]
427
+ fn namespace_is_within_range ( ) {
428
+ let seed = [ 0 as u8 ; 32 ] ;
429
+ let keys_manager = Arc :: new ( test_utils:: TestKeysInterface :: new ( & seed, Network :: Testnet ) ) ;
430
+ let Namespace :: Phantom ( ns) = Namespace :: phantom ( & keys_manager) ;
431
+ assert ! ( ns <= NAMESPACE_TYPE_BITMASK ) ;
432
+ }
433
+ // XXX tests for get_fake_scid
434
+ }
435
+ }
436
+
437
+
341
438
// We hold various information about HTLC relay in the HTLC objects in Channel itself:
342
439
//
343
440
// Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should
@@ -960,6 +1057,8 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
960
1057
961
1058
inbound_payment_key : inbound_payment:: ExpandedKey ,
962
1059
1060
+ phantom_scid_namespace : fake_scid:: Namespace ,
1061
+
963
1062
/// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
964
1063
/// value increases strictly since we don't assume access to a time source.
965
1064
last_node_announcement_serial : AtomicUsize ,
@@ -1655,6 +1754,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1655
1754
secp_ctx. seeded_randomize ( & keys_manager. get_secure_random_bytes ( ) ) ;
1656
1755
let inbound_pmt_key_material = keys_manager. get_inbound_payment_key_material ( ) ;
1657
1756
let expanded_inbound_key = inbound_payment:: ExpandedKey :: new ( & inbound_pmt_key_material) ;
1757
+ let phantom_scid_namespace = fake_scid:: Namespace :: phantom ( & keys_manager) ;
1658
1758
ChannelManager {
1659
1759
default_configuration : config. clone ( ) ,
1660
1760
genesis_hash : genesis_block ( params. network ) . header . block_hash ( ) ,
@@ -1680,6 +1780,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1680
1780
1681
1781
inbound_payment_key : expanded_inbound_key,
1682
1782
1783
+ phantom_scid_namespace,
1784
+
1683
1785
last_node_announcement_serial : AtomicUsize :: new ( 0 ) ,
1684
1786
highest_seen_timestamp : AtomicUsize :: new ( 0 ) ,
1685
1787
@@ -6145,6 +6247,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
6145
6247
write_tlv_fields ! ( writer, {
6146
6248
( 1 , pending_outbound_payments_no_retry, required) ,
6147
6249
( 3 , pending_outbound_payments, required) ,
6250
+ ( 5 , self . phantom_scid_namespace, required) ,
6148
6251
} ) ;
6149
6252
6150
6253
Ok ( ( ) )
@@ -6439,10 +6542,16 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6439
6542
// pending_outbound_payments_no_retry is for compatibility with 0.0.101 clients.
6440
6543
let mut pending_outbound_payments_no_retry: Option < HashMap < PaymentId , HashSet < [ u8 ; 32 ] > > > = None ;
6441
6544
let mut pending_outbound_payments = None ;
6545
+ let mut phantom_scid_namespace: Option < fake_scid:: Namespace > = None ;
6442
6546
read_tlv_fields ! ( reader, {
6443
6547
( 1 , pending_outbound_payments_no_retry, option) ,
6444
6548
( 3 , pending_outbound_payments, option) ,
6549
+ ( 5 , phantom_scid_namespace, option) ,
6445
6550
} ) ;
6551
+ if phantom_scid_namespace. is_none ( ) {
6552
+ phantom_scid_namespace = Some ( fake_scid:: Namespace :: phantom ( & args. keys_manager ) ) ;
6553
+ }
6554
+
6446
6555
if pending_outbound_payments. is_none ( ) && pending_outbound_payments_no_retry. is_none ( ) {
6447
6556
pending_outbound_payments = Some ( pending_outbound_payments_compat) ;
6448
6557
} else if pending_outbound_payments. is_none ( ) {
@@ -6525,6 +6634,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
6525
6634
inbound_payment_key : expanded_inbound_key,
6526
6635
pending_inbound_payments : Mutex :: new ( pending_inbound_payments) ,
6527
6636
pending_outbound_payments : Mutex :: new ( pending_outbound_payments. unwrap ( ) ) ,
6637
+ phantom_scid_namespace : phantom_scid_namespace. unwrap ( ) ,
6528
6638
6529
6639
our_network_key : args. keys_manager . get_node_secret ( ) ,
6530
6640
our_network_pubkey : PublicKey :: from_secret_key ( & secp_ctx, & args. keys_manager . get_node_secret ( ) ) ,
0 commit comments