@@ -43,7 +43,7 @@ use crate::io_extras::read_to_end;
43
43
44
44
use crate :: events:: { MessageSendEventsProvider , OnionMessageProvider } ;
45
45
use crate :: util:: logger;
46
- use crate :: util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited } ;
46
+ use crate :: util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited , BigSize } ;
47
47
48
48
use crate :: ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
49
49
@@ -1429,6 +1429,8 @@ mod fuzzy_internal_msgs {
1429
1429
payment_data : Option < FinalOnionHopData > ,
1430
1430
payment_metadata : Option < Vec < u8 > > ,
1431
1431
keysend_preimage : Option < PaymentPreimage > ,
1432
+ /// Serialization will fail if this is not a valid TLV stream
1433
+ custom_tlvs : Option < Vec < ( u64 , Vec < u8 > ) > > ,
1432
1434
} ,
1433
1435
}
1434
1436
@@ -1954,14 +1956,19 @@ impl Writeable for OnionHopData {
1954
1956
( 6 , short_channel_id, required)
1955
1957
} ) ;
1956
1958
} ,
1957
- OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
1959
+ OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage, ref custom_tlvs } => {
1960
+ let preimage = if let Some ( ref preimage) = keysend_preimage {
1961
+ Some ( ( 5482373484 , preimage. encode ( ) ) )
1962
+ } else { None } ;
1963
+ let mut custom_tlvs: Vec < & ( u64 , Vec < u8 > ) > = custom_tlvs. iter ( ) . flatten ( ) . chain ( preimage. iter ( ) ) . collect ( ) ;
1964
+ custom_tlvs. sort_by_key ( |( typ, _) | * typ) ;
1965
+
1958
1966
_encode_varint_length_prefixed_tlv ! ( w, {
1959
1967
( 2 , HighZeroBytesDroppedBigSize ( self . amt_to_forward) , required) ,
1960
1968
( 4 , HighZeroBytesDroppedBigSize ( self . outgoing_cltv_value) , required) ,
1961
1969
( 8 , payment_data, option) ,
1962
- ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option) ,
1963
- ( 5482373484 , keysend_preimage, option)
1964
- } ) ;
1970
+ ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option)
1971
+ } , custom_tlvs. iter( ) ) ;
1965
1972
} ,
1966
1973
}
1967
1974
Ok ( ( ) )
@@ -1976,14 +1983,24 @@ impl Readable for OnionHopData {
1976
1983
let mut payment_data: Option < FinalOnionHopData > = None ;
1977
1984
let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
1978
1985
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1979
- read_tlv_fields ! ( r, {
1986
+ let mut custom_tlvs = Vec :: new ( ) ;
1987
+
1988
+ let tlv_len = BigSize :: read ( r) ?;
1989
+ let rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
1990
+ decode_tlv_stream_with_custom_tlv_decode ! ( rd, {
1980
1991
( 2 , amt, required) ,
1981
1992
( 4 , cltv_value, required) ,
1982
1993
( 6 , short_id, option) ,
1983
1994
( 8 , payment_data, option) ,
1984
1995
( 16 , payment_metadata, option) ,
1985
1996
// See https://github.com/lightning/blips/blob/master/blip-0003.md
1986
1997
( 5482373484 , keysend_preimage, option)
1998
+ } , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
1999
+ if msg_type < 1 << 16 { return Ok ( false ) }
2000
+ let mut value = Vec :: new( ) ;
2001
+ msg_reader. read_to_end( & mut value) ?;
2002
+ custom_tlvs. push( ( msg_type, value) ) ;
2003
+ Ok ( true )
1987
2004
} ) ;
1988
2005
1989
2006
let format = if let Some ( short_channel_id) = short_id {
@@ -2002,6 +2019,7 @@ impl Readable for OnionHopData {
2002
2019
payment_data,
2003
2020
payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
2004
2021
keysend_preimage,
2022
+ custom_tlvs : if custom_tlvs. is_empty ( ) { None } else { Some ( custom_tlvs) } ,
2005
2023
}
2006
2024
} ;
2007
2025
@@ -3543,6 +3561,7 @@ mod tests {
3543
3561
payment_data : None ,
3544
3562
payment_metadata : None ,
3545
3563
keysend_preimage : None ,
3564
+ custom_tlvs : None ,
3546
3565
} ,
3547
3566
amt_to_forward : 0x0badf00d01020304 ,
3548
3567
outgoing_cltv_value : 0xffffffff ,
@@ -3567,6 +3586,7 @@ mod tests {
3567
3586
} ) ,
3568
3587
payment_metadata : None ,
3569
3588
keysend_preimage : None ,
3589
+ custom_tlvs : None ,
3570
3590
} ,
3571
3591
amt_to_forward : 0x0badf00d01020304 ,
3572
3592
outgoing_cltv_value : 0xffffffff ,
@@ -3582,13 +3602,81 @@ mod tests {
3582
3602
} ) ,
3583
3603
payment_metadata : None ,
3584
3604
keysend_preimage : None ,
3605
+ custom_tlvs : None ,
3585
3606
} = msg. format {
3586
3607
assert_eq ! ( payment_secret, expected_payment_secret) ;
3587
3608
} else { panic ! ( ) ; }
3588
3609
assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3589
3610
assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3590
3611
}
3591
3612
3613
+ #[ test]
3614
+ fn encoding_final_onion_hop_data_with_bad_custom_tlvs ( ) {
3615
+ // If custom TLVs have type number within the range reserved for protocol, treat them as if
3616
+ // they're unknown
3617
+ let bad_type_range_tlvs = vec ! [
3618
+ ( ( 1 << 16 ) - 4 , vec![ 42 ] ) ,
3619
+ ( ( 1 << 16 ) - 2 , vec![ 42 ; 32 ] ) ,
3620
+ ] ;
3621
+ let mut msg = msgs:: OnionHopData {
3622
+ format : OnionHopDataFormat :: FinalNode {
3623
+ payment_data : None ,
3624
+ payment_metadata : None ,
3625
+ keysend_preimage : None ,
3626
+ custom_tlvs : Some ( bad_type_range_tlvs) ,
3627
+ } ,
3628
+ amt_to_forward : 0x0badf00d01020304 ,
3629
+ outgoing_cltv_value : 0xffffffff ,
3630
+ } ;
3631
+ let encoded_value = msg. encode ( ) ;
3632
+ assert ! ( msgs:: OnionHopData :: read( & mut Cursor :: new( & encoded_value[ ..] ) ) . is_err( ) ) ;
3633
+ let good_type_range_tlvs = vec ! [
3634
+ ( ( 1 << 16 ) - 3 , vec![ 42 ] ) ,
3635
+ ( ( 1 << 16 ) - 1 , vec![ 42 ; 32 ] ) ,
3636
+ ] ;
3637
+ if let OnionHopDataFormat :: FinalNode { ref mut custom_tlvs, .. } = msg. format {
3638
+ * custom_tlvs = Some ( good_type_range_tlvs. clone ( ) ) ;
3639
+ }
3640
+ let encoded_value = msg. encode ( ) ;
3641
+ msg = Readable :: read ( & mut Cursor :: new ( & encoded_value[ ..] ) ) . unwrap ( ) ;
3642
+ match msg. format {
3643
+ OnionHopDataFormat :: FinalNode { custom_tlvs, .. } => assert ! ( custom_tlvs. is_none( ) ) ,
3644
+ _ => panic ! ( ) ,
3645
+ }
3646
+ }
3647
+
3648
+ #[ test]
3649
+ fn encoding_final_onion_hop_data_with_custom_tlvs ( ) {
3650
+ let expected_custom_tlvs = vec ! [
3651
+ ( 5482373483 , vec![ 0x12 , 0x34 ] ) ,
3652
+ ( 5482373487 , vec![ 0x42u8 ; 8 ] ) ,
3653
+ ] ;
3654
+ let mut msg = msgs:: OnionHopData {
3655
+ format : OnionHopDataFormat :: FinalNode {
3656
+ payment_data : None ,
3657
+ payment_metadata : None ,
3658
+ keysend_preimage : None ,
3659
+ custom_tlvs : Some ( expected_custom_tlvs. clone ( ) ) ,
3660
+ } ,
3661
+ amt_to_forward : 0x0badf00d01020304 ,
3662
+ outgoing_cltv_value : 0xffffffff ,
3663
+ } ;
3664
+ let encoded_value = msg. encode ( ) ;
3665
+ let target_value = hex:: decode ( "2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242" ) . unwrap ( ) ;
3666
+ assert_eq ! ( encoded_value, target_value) ;
3667
+ msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3668
+ if let OnionHopDataFormat :: FinalNode {
3669
+ payment_data : None ,
3670
+ payment_metadata : None ,
3671
+ keysend_preimage : None ,
3672
+ custom_tlvs,
3673
+ } = msg. format {
3674
+ assert_eq ! ( custom_tlvs. unwrap( ) , expected_custom_tlvs) ;
3675
+ } else { panic ! ( ) ; }
3676
+ assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3677
+ assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3678
+ }
3679
+
3592
3680
#[ test]
3593
3681
fn query_channel_range_end_blocknum ( ) {
3594
3682
let tests: Vec < ( u32 , u32 , u32 ) > = vec ! [
0 commit comments