@@ -49,7 +49,9 @@ pub fn vout_from_scid(short_channel_id: u64) -> u16 {
4949
5050/// Constructs a `short_channel_id` using the components pieces. Results in an error
5151/// if the block height, tx index, or vout index overflow the maximum sizes.
52- pub fn scid_from_parts ( block : u64 , tx_index : u64 , vout_index : u64 ) -> Result < u64 , ShortChannelIdError > {
52+ pub fn scid_from_parts (
53+ block : u64 , tx_index : u64 , vout_index : u64 ,
54+ ) -> Result < u64 , ShortChannelIdError > {
5355 if block > MAX_SCID_BLOCK {
5456 return Err ( ShortChannelIdError :: BlockOverflow ) ;
5557 }
@@ -71,12 +73,12 @@ pub fn scid_from_parts(block: u64, tx_index: u64, vout_index: u64) -> Result<u64
7173/// 3) payments intended to be intercepted will route using a fake scid (this is typically used so
7274/// the forwarding node can open a JIT channel to the next hop)
7375pub ( crate ) mod fake_scid {
74- use bitcoin:: constants:: ChainHash ;
75- use bitcoin:: Network ;
76- use crate :: sign:: EntropySource ;
7776 use crate :: crypto:: chacha20:: ChaCha20 ;
78- use crate :: util:: scid_utils;
7977 use crate :: prelude:: * ;
78+ use crate :: sign:: EntropySource ;
79+ use crate :: util:: scid_utils;
80+ use bitcoin:: constants:: ChainHash ;
81+ use bitcoin:: Network ;
8082
8183 use core:: ops:: Deref ;
8284
@@ -89,7 +91,6 @@ pub(crate) mod fake_scid {
8991 const BLOCKS_PER_MONTH : u32 = 144 /* blocks per day */ * 30 /* days per month */ ;
9092 pub ( crate ) const MAX_SCID_BLOCKS_FROM_NOW : u32 = BLOCKS_PER_MONTH ;
9193
92-
9394 /// Fake scids are divided into namespaces, with each namespace having its own identifier between
9495 /// [0..7]. This allows us to identify what namespace a fake scid corresponds to upon HTLC
9596 /// receipt, and handle the HTLC accordingly. The namespace identifier is encrypted when encoded
@@ -101,44 +102,59 @@ pub(crate) mod fake_scid {
101102 /// SCID aliases for outbound private channels
102103 OutboundAlias ,
103104 /// Payment interception namespace
104- Intercept
105+ Intercept ,
105106 }
106107
107108 impl Namespace {
108109 /// We generate "realistic-looking" random scids here, meaning the scid's block height is
109110 /// between segwit activation and the current best known height, and the tx index and output
110111 /// index are also selected from a "reasonable" range. We add this logic because it makes it
111112 /// non-obvious at a glance that the scid is fake, e.g. if it appears in invoice route hints.
112- pub ( crate ) fn get_fake_scid < ES : Deref > ( & self , highest_seen_blockheight : u32 , chain_hash : & ChainHash , fake_scid_rand_bytes : & [ u8 ; 32 ] , entropy_source : & ES ) -> u64
113- where ES :: Target : EntropySource ,
113+ pub ( crate ) fn get_fake_scid < ES : Deref > (
114+ & self , highest_seen_blockheight : u32 , chain_hash : & ChainHash ,
115+ fake_scid_rand_bytes : & [ u8 ; 32 ] , entropy_source : & ES ,
116+ ) -> u64
117+ where
118+ ES :: Target : EntropySource ,
114119 {
115120 // Ensure we haven't created a namespace that doesn't fit into the 3 bits we've allocated for
116121 // namespaces.
117122 assert ! ( ( * self as u8 ) < MAX_NAMESPACES ) ;
118123 let rand_bytes = entropy_source. get_secure_random_bytes ( ) ;
119124
120125 let segwit_activation_height = segwit_activation_height ( chain_hash) ;
121- let mut blocks_since_segwit_activation = highest_seen_blockheight. saturating_sub ( segwit_activation_height) ;
126+ let mut blocks_since_segwit_activation =
127+ highest_seen_blockheight. saturating_sub ( segwit_activation_height) ;
122128
123129 // We want to ensure that this fake channel won't conflict with any transactions we haven't
124130 // seen yet, in case `highest_seen_blockheight` is updated before we get full information
125131 // about transactions confirmed in the given block.
126- blocks_since_segwit_activation = blocks_since_segwit_activation. saturating_sub ( MAX_SCID_BLOCKS_FROM_NOW ) ;
132+ blocks_since_segwit_activation =
133+ blocks_since_segwit_activation. saturating_sub ( MAX_SCID_BLOCKS_FROM_NOW ) ;
127134
128135 let rand_for_height = u32:: from_be_bytes ( rand_bytes[ ..4 ] . try_into ( ) . unwrap ( ) ) ;
129- let fake_scid_height = segwit_activation_height + rand_for_height % ( blocks_since_segwit_activation + 1 ) ;
136+ let fake_scid_height =
137+ segwit_activation_height + rand_for_height % ( blocks_since_segwit_activation + 1 ) ;
130138
131139 let rand_for_tx_index = u32:: from_be_bytes ( rand_bytes[ 4 ..8 ] . try_into ( ) . unwrap ( ) ) ;
132140 let fake_scid_tx_index = rand_for_tx_index % MAX_TX_INDEX ;
133141
134142 // Put the scid in the given namespace.
135- let fake_scid_vout = self . get_encrypted_vout ( fake_scid_height, fake_scid_tx_index, fake_scid_rand_bytes) ;
136- scid_utils:: scid_from_parts ( fake_scid_height as u64 , fake_scid_tx_index as u64 , fake_scid_vout as u64 ) . unwrap ( )
143+ let fake_scid_vout =
144+ self . get_encrypted_vout ( fake_scid_height, fake_scid_tx_index, fake_scid_rand_bytes) ;
145+ scid_utils:: scid_from_parts (
146+ fake_scid_height as u64 ,
147+ fake_scid_tx_index as u64 ,
148+ fake_scid_vout as u64 ,
149+ )
150+ . unwrap ( )
137151 }
138152
139153 /// We want to ensure that a 3rd party can't identify a payment as belong to a given
140154 /// `Namespace`. Therefore, we encrypt it using a random bytes provided by `ChannelManager`.
141- fn get_encrypted_vout ( & self , block_height : u32 , tx_index : u32 , fake_scid_rand_bytes : & [ u8 ; 32 ] ) -> u8 {
155+ fn get_encrypted_vout (
156+ & self , block_height : u32 , tx_index : u32 , fake_scid_rand_bytes : & [ u8 ; 32 ] ,
157+ ) -> u8 {
142158 let mut salt = [ 0 as u8 ; 8 ] ;
143159 let block_height_bytes = block_height. to_be_bytes ( ) ;
144160 salt[ 0 ..4 ] . copy_from_slice ( & block_height_bytes) ;
@@ -161,7 +177,9 @@ pub(crate) mod fake_scid {
161177 }
162178
163179 /// Returns whether the given fake scid falls into the phantom namespace.
164- pub fn is_valid_phantom ( fake_scid_rand_bytes : & [ u8 ; 32 ] , scid : u64 , chain_hash : & ChainHash ) -> bool {
180+ pub fn is_valid_phantom (
181+ fake_scid_rand_bytes : & [ u8 ; 32 ] , scid : u64 , chain_hash : & ChainHash ,
182+ ) -> bool {
165183 let block_height = scid_utils:: block_from_scid ( scid) ;
166184 let tx_index = scid_utils:: tx_index_from_scid ( scid) ;
167185 let namespace = Namespace :: Phantom ;
@@ -171,7 +189,9 @@ pub(crate) mod fake_scid {
171189 }
172190
173191 /// Returns whether the given fake scid falls into the intercept namespace.
174- pub fn is_valid_intercept ( fake_scid_rand_bytes : & [ u8 ; 32 ] , scid : u64 , chain_hash : & ChainHash ) -> bool {
192+ pub fn is_valid_intercept (
193+ fake_scid_rand_bytes : & [ u8 ; 32 ] , scid : u64 , chain_hash : & ChainHash ,
194+ ) -> bool {
175195 let block_height = scid_utils:: block_from_scid ( scid) ;
176196 let tx_index = scid_utils:: tx_index_from_scid ( scid) ;
177197 let namespace = Namespace :: Intercept ;
@@ -182,12 +202,16 @@ pub(crate) mod fake_scid {
182202
183203 #[ cfg( test) ]
184204 mod tests {
185- use bitcoin:: constants:: ChainHash ;
186- use bitcoin:: network:: Network ;
187- use crate :: util:: scid_utils:: fake_scid:: { is_valid_intercept, is_valid_phantom, MAINNET_SEGWIT_ACTIVATION_HEIGHT , MAX_TX_INDEX , MAX_NAMESPACES , Namespace , NAMESPACE_ID_BITMASK , segwit_activation_height, TEST_SEGWIT_ACTIVATION_HEIGHT } ;
205+ use crate :: sync:: Arc ;
188206 use crate :: util:: scid_utils;
207+ use crate :: util:: scid_utils:: fake_scid:: {
208+ is_valid_intercept, is_valid_phantom, segwit_activation_height, Namespace ,
209+ MAINNET_SEGWIT_ACTIVATION_HEIGHT , MAX_NAMESPACES , MAX_TX_INDEX , NAMESPACE_ID_BITMASK ,
210+ TEST_SEGWIT_ACTIVATION_HEIGHT ,
211+ } ;
189212 use crate :: util:: test_utils;
190- use crate :: sync:: Arc ;
213+ use bitcoin:: constants:: ChainHash ;
214+ use bitcoin:: network:: Network ;
191215
192216 #[ test]
193217 fn namespace_identifier_is_within_range ( ) {
@@ -203,7 +227,10 @@ pub(crate) mod fake_scid {
203227 #[ test]
204228 fn test_segwit_activation_height ( ) {
205229 let mainnet_genesis = ChainHash :: using_genesis_block ( Network :: Bitcoin ) ;
206- assert_eq ! ( segwit_activation_height( & mainnet_genesis) , MAINNET_SEGWIT_ACTIVATION_HEIGHT ) ;
230+ assert_eq ! (
231+ segwit_activation_height( & mainnet_genesis) ,
232+ MAINNET_SEGWIT_ACTIVATION_HEIGHT
233+ ) ;
207234
208235 let testnet_genesis = ChainHash :: using_genesis_block ( Network :: Testnet ) ;
209236 assert_eq ! ( segwit_activation_height( & testnet_genesis) , TEST_SEGWIT_ACTIVATION_HEIGHT ) ;
@@ -221,7 +248,8 @@ pub(crate) mod fake_scid {
221248 let fake_scid_rand_bytes = [ 0 ; 32 ] ;
222249 let testnet_genesis = ChainHash :: using_genesis_block ( Network :: Testnet ) ;
223250 let valid_encrypted_vout = namespace. get_encrypted_vout ( 0 , 0 , & fake_scid_rand_bytes) ;
224- let valid_fake_scid = scid_utils:: scid_from_parts ( 1 , 0 , valid_encrypted_vout as u64 ) . unwrap ( ) ;
251+ let valid_fake_scid =
252+ scid_utils:: scid_from_parts ( 1 , 0 , valid_encrypted_vout as u64 ) . unwrap ( ) ;
225253 assert ! ( is_valid_phantom( & fake_scid_rand_bytes, valid_fake_scid, & testnet_genesis) ) ;
226254 let invalid_fake_scid = scid_utils:: scid_from_parts ( 1 , 0 , 12 ) . unwrap ( ) ;
227255 assert ! ( !is_valid_phantom( & fake_scid_rand_bytes, invalid_fake_scid, & testnet_genesis) ) ;
@@ -233,20 +261,31 @@ pub(crate) mod fake_scid {
233261 let fake_scid_rand_bytes = [ 0 ; 32 ] ;
234262 let testnet_genesis = ChainHash :: using_genesis_block ( Network :: Testnet ) ;
235263 let valid_encrypted_vout = namespace. get_encrypted_vout ( 0 , 0 , & fake_scid_rand_bytes) ;
236- let valid_fake_scid = scid_utils:: scid_from_parts ( 1 , 0 , valid_encrypted_vout as u64 ) . unwrap ( ) ;
264+ let valid_fake_scid =
265+ scid_utils:: scid_from_parts ( 1 , 0 , valid_encrypted_vout as u64 ) . unwrap ( ) ;
237266 assert ! ( is_valid_intercept( & fake_scid_rand_bytes, valid_fake_scid, & testnet_genesis) ) ;
238267 let invalid_fake_scid = scid_utils:: scid_from_parts ( 1 , 0 , 12 ) . unwrap ( ) ;
239- assert ! ( !is_valid_intercept( & fake_scid_rand_bytes, invalid_fake_scid, & testnet_genesis) ) ;
268+ assert ! ( !is_valid_intercept(
269+ & fake_scid_rand_bytes,
270+ invalid_fake_scid,
271+ & testnet_genesis
272+ ) ) ;
240273 }
241274
242275 #[ test]
243276 fn test_get_fake_scid ( ) {
244277 let mainnet_genesis = ChainHash :: using_genesis_block ( Network :: Bitcoin ) ;
245278 let seed = [ 0 ; 32 ] ;
246279 let fake_scid_rand_bytes = [ 1 ; 32 ] ;
247- let keys_manager = Arc :: new ( test_utils:: TestKeysInterface :: new ( & seed, Network :: Testnet ) ) ;
280+ let keys_manager =
281+ Arc :: new ( test_utils:: TestKeysInterface :: new ( & seed, Network :: Testnet ) ) ;
248282 let namespace = Namespace :: Phantom ;
249- let fake_scid = namespace. get_fake_scid ( 500_000 , & mainnet_genesis, & fake_scid_rand_bytes, & keys_manager) ;
283+ let fake_scid = namespace. get_fake_scid (
284+ 500_000 ,
285+ & mainnet_genesis,
286+ & fake_scid_rand_bytes,
287+ & keys_manager,
288+ ) ;
250289
251290 let fake_height = scid_utils:: block_from_scid ( fake_scid) ;
252291 assert ! ( fake_height >= MAINNET_SEGWIT_ACTIVATION_HEIGHT ) ;
@@ -298,8 +337,17 @@ mod tests {
298337 assert_eq ! ( scid_from_parts( 0x00000001 , 0x00000002 , 0x0003 ) . unwrap( ) , 0x000001_000002_0003 ) ;
299338 assert_eq ! ( scid_from_parts( 0x00111111 , 0x00222222 , 0x3333 ) . unwrap( ) , 0x111111_222222_3333 ) ;
300339 assert_eq ! ( scid_from_parts( 0x00ffffff , 0x00ffffff , 0xffff ) . unwrap( ) , 0xffffff_ffffff_ffff ) ;
301- assert_eq ! ( scid_from_parts( 0x01ffffff , 0x00000000 , 0x0000 ) . err( ) . unwrap( ) , ShortChannelIdError :: BlockOverflow ) ;
302- assert_eq ! ( scid_from_parts( 0x00000000 , 0x01ffffff , 0x0000 ) . err( ) . unwrap( ) , ShortChannelIdError :: TxIndexOverflow ) ;
303- assert_eq ! ( scid_from_parts( 0x00000000 , 0x00000000 , 0x010000 ) . err( ) . unwrap( ) , ShortChannelIdError :: VoutIndexOverflow ) ;
340+ assert_eq ! (
341+ scid_from_parts( 0x01ffffff , 0x00000000 , 0x0000 ) . err( ) . unwrap( ) ,
342+ ShortChannelIdError :: BlockOverflow
343+ ) ;
344+ assert_eq ! (
345+ scid_from_parts( 0x00000000 , 0x01ffffff , 0x0000 ) . err( ) . unwrap( ) ,
346+ ShortChannelIdError :: TxIndexOverflow
347+ ) ;
348+ assert_eq ! (
349+ scid_from_parts( 0x00000000 , 0x00000000 , 0x010000 ) . err( ) . unwrap( ) ,
350+ ShortChannelIdError :: VoutIndexOverflow
351+ ) ;
304352 }
305353}
0 commit comments