@@ -42,7 +42,7 @@ use crate::io_extras::read_to_end;
42
42
43
43
use crate :: events:: { MessageSendEventsProvider , OnionMessageProvider } ;
44
44
use crate :: util:: logger;
45
- use crate :: util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited } ;
45
+ use crate :: util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited , BigSize } ;
46
46
47
47
use crate :: ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
48
48
@@ -1413,6 +1413,8 @@ mod fuzzy_internal_msgs {
1413
1413
payment_data : Option < FinalOnionHopData > ,
1414
1414
payment_metadata : Option < Vec < u8 > > ,
1415
1415
keysend_preimage : Option < PaymentPreimage > ,
1416
+ /// Serialization will fail if this is not a valid TLV stream
1417
+ custom_tlvs : Option < Vec < ( u64 , Vec < u8 > ) > > ,
1416
1418
} ,
1417
1419
}
1418
1420
@@ -1934,14 +1936,27 @@ impl Writeable for OnionHopData {
1934
1936
( 6 , short_channel_id, required)
1935
1937
} ) ;
1936
1938
} ,
1937
- OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
1939
+ OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage, ref custom_tlvs } => {
1940
+ let mut custom_tlvs = custom_tlvs. clone ( ) . unwrap_or ( Vec :: new ( ) ) ;
1941
+ if let & Some ( preimage) = keysend_preimage {
1942
+ let mut preimage_bytes = Vec :: new ( ) ;
1943
+ preimage. write ( & mut preimage_bytes) ?;
1944
+ custom_tlvs. push ( ( 5482373484 , preimage_bytes) ) ;
1945
+ }
1946
+ custom_tlvs. sort_by_key ( |( typ, _) | * typ) ;
1947
+ let mut custom_tlv_stream = Vec :: new ( ) ;
1948
+ for ( typ, value) in custom_tlvs {
1949
+ BigSize ( typ) . write ( & mut custom_tlv_stream) ?;
1950
+ BigSize ( value. len ( ) as u64 ) . write ( & mut custom_tlv_stream) ?;
1951
+ custom_tlv_stream. write_all ( & value) ?;
1952
+ }
1953
+
1938
1954
_encode_varint_length_prefixed_tlv ! ( w, {
1939
1955
( 2 , HighZeroBytesDroppedBigSize ( self . amt_to_forward) , required) ,
1940
1956
( 4 , HighZeroBytesDroppedBigSize ( self . outgoing_cltv_value) , required) ,
1941
1957
( 8 , payment_data, option) ,
1942
- ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option) ,
1943
- ( 5482373484 , keysend_preimage, option)
1944
- } ) ;
1958
+ ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option)
1959
+ } , & custom_tlv_stream) ;
1945
1960
} ,
1946
1961
}
1947
1962
Ok ( ( ) )
@@ -1956,14 +1971,24 @@ impl Readable for OnionHopData {
1956
1971
let mut payment_data: Option < FinalOnionHopData > = None ;
1957
1972
let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
1958
1973
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1959
- read_tlv_fields ! ( r, {
1974
+ let mut custom_tlvs = Vec :: new ( ) ;
1975
+
1976
+ let tlv_len = BigSize :: read ( r) ?;
1977
+ let rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
1978
+ decode_tlv_stream_with_custom_tlv_decode ! ( rd, {
1960
1979
( 2 , amt, required) ,
1961
1980
( 4 , cltv_value, required) ,
1962
1981
( 6 , short_id, option) ,
1963
1982
( 8 , payment_data, option) ,
1964
1983
( 16 , payment_metadata, option) ,
1965
1984
// See https://github.com/lightning/blips/blob/master/blip-0003.md
1966
1985
( 5482373484 , keysend_preimage, option)
1986
+ } , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
1987
+ if msg_type < 1 << 16 { return Ok ( false ) }
1988
+ let mut value = Vec :: new( ) ;
1989
+ msg_reader. read_to_end( & mut value) ?;
1990
+ custom_tlvs. push( ( msg_type, value) ) ;
1991
+ Ok ( true )
1967
1992
} ) ;
1968
1993
1969
1994
let format = if let Some ( short_channel_id) = short_id {
@@ -1982,6 +2007,7 @@ impl Readable for OnionHopData {
1982
2007
payment_data,
1983
2008
payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
1984
2009
keysend_preimage,
2010
+ custom_tlvs : if custom_tlvs. is_empty ( ) { None } else { Some ( custom_tlvs) } ,
1985
2011
}
1986
2012
} ;
1987
2013
@@ -2417,7 +2443,7 @@ mod tests {
2417
2443
use crate :: ln:: features:: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , NodeFeatures } ;
2418
2444
use crate :: ln:: msgs:: { self , FinalOnionHopData , OnionErrorPacket , OnionHopDataFormat } ;
2419
2445
use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
2420
- use crate :: util:: ser:: { Writeable , Readable , Hostname , TransactionU16LenLimited } ;
2446
+ use crate :: util:: ser:: { Writeable , Writer , Readable , Hostname , TransactionU16LenLimited } ;
2421
2447
2422
2448
use bitcoin:: hashes:: hex:: FromHex ;
2423
2449
use bitcoin:: util:: address:: Address ;
@@ -3513,6 +3539,7 @@ mod tests {
3513
3539
payment_data : None ,
3514
3540
payment_metadata : None ,
3515
3541
keysend_preimage : None ,
3542
+ custom_tlvs : None ,
3516
3543
} ,
3517
3544
amt_to_forward : 0x0badf00d01020304 ,
3518
3545
outgoing_cltv_value : 0xffffffff ,
@@ -3537,6 +3564,7 @@ mod tests {
3537
3564
} ) ,
3538
3565
payment_metadata : None ,
3539
3566
keysend_preimage : None ,
3567
+ custom_tlvs : None ,
3540
3568
} ,
3541
3569
amt_to_forward : 0x0badf00d01020304 ,
3542
3570
outgoing_cltv_value : 0xffffffff ,
@@ -3552,13 +3580,81 @@ mod tests {
3552
3580
} ) ,
3553
3581
payment_metadata : None ,
3554
3582
keysend_preimage : None ,
3583
+ custom_tlvs : None ,
3555
3584
} = msg. format {
3556
3585
assert_eq ! ( payment_secret, expected_payment_secret) ;
3557
3586
} else { panic ! ( ) ; }
3558
3587
assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3559
3588
assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3560
3589
}
3561
3590
3591
+ #[ test]
3592
+ fn encoding_final_onion_hop_data_with_bad_custom_tlvs ( ) {
3593
+ // If custom TLVs have type number within the range reserved for protocol, treat them as if
3594
+ // they're unknown
3595
+ let bad_type_range_tlvs = vec ! [
3596
+ ( ( 1 << 16 ) - 4 , vec![ 42 ] ) ,
3597
+ ( ( 1 << 16 ) - 2 , vec![ 42 ; 32 ] ) ,
3598
+ ] ;
3599
+ let mut msg = msgs:: OnionHopData {
3600
+ format : OnionHopDataFormat :: FinalNode {
3601
+ payment_data : None ,
3602
+ payment_metadata : None ,
3603
+ keysend_preimage : None ,
3604
+ custom_tlvs : Some ( bad_type_range_tlvs) ,
3605
+ } ,
3606
+ amt_to_forward : 0x0badf00d01020304 ,
3607
+ outgoing_cltv_value : 0xffffffff ,
3608
+ } ;
3609
+ let encoded_value = msg. encode ( ) ;
3610
+ assert ! ( msgs:: OnionHopData :: read( & mut Cursor :: new( & encoded_value[ ..] ) ) . is_err( ) ) ;
3611
+ let good_type_range_tlvs = vec ! [
3612
+ ( ( 1 << 16 ) - 3 , vec![ 42 ] ) ,
3613
+ ( ( 1 << 16 ) - 1 , vec![ 42 ; 32 ] ) ,
3614
+ ] ;
3615
+ if let OnionHopDataFormat :: FinalNode { ref mut custom_tlvs, .. } = msg. format {
3616
+ * custom_tlvs = Some ( good_type_range_tlvs. clone ( ) ) ;
3617
+ }
3618
+ let encoded_value = msg. encode ( ) ;
3619
+ msg = Readable :: read ( & mut Cursor :: new ( & encoded_value[ ..] ) ) . unwrap ( ) ;
3620
+ match msg. format {
3621
+ OnionHopDataFormat :: FinalNode { custom_tlvs, .. } => assert ! ( custom_tlvs. is_none( ) ) ,
3622
+ _ => panic ! ( ) ,
3623
+ }
3624
+ }
3625
+
3626
+ #[ test]
3627
+ fn encoding_final_onion_hop_data_with_custom_tlvs ( ) {
3628
+ let expected_custom_tlvs = vec ! [
3629
+ ( 5482373483 , vec![ 0x12 , 0x34 ] ) ,
3630
+ ( 5482373487 , vec![ 0x42u8 ; 8 ] ) ,
3631
+ ] ;
3632
+ let mut msg = msgs:: OnionHopData {
3633
+ format : OnionHopDataFormat :: FinalNode {
3634
+ payment_data : None ,
3635
+ payment_metadata : None ,
3636
+ keysend_preimage : None ,
3637
+ custom_tlvs : Some ( expected_custom_tlvs. clone ( ) ) ,
3638
+ } ,
3639
+ amt_to_forward : 0x0badf00d01020304 ,
3640
+ outgoing_cltv_value : 0xffffffff ,
3641
+ } ;
3642
+ let encoded_value = msg. encode ( ) ;
3643
+ let target_value = hex:: decode ( "2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242" ) . unwrap ( ) ;
3644
+ assert_eq ! ( encoded_value, target_value) ;
3645
+ msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3646
+ if let OnionHopDataFormat :: FinalNode {
3647
+ payment_data : None ,
3648
+ payment_metadata : None ,
3649
+ keysend_preimage : None ,
3650
+ custom_tlvs,
3651
+ } = msg. format {
3652
+ assert_eq ! ( custom_tlvs. unwrap( ) , expected_custom_tlvs) ;
3653
+ } else { panic ! ( ) ; }
3654
+ assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3655
+ assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3656
+ }
3657
+
3562
3658
#[ test]
3563
3659
fn query_channel_range_end_blocknum ( ) {
3564
3660
let tests: Vec < ( u32 , u32 , u32 ) > = vec ! [
0 commit comments