@@ -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
@@ -1438,6 +1438,8 @@ mod fuzzy_internal_msgs {
1438
1438
payment_data : Option < FinalOnionHopData > ,
1439
1439
payment_metadata : Option < Vec < u8 > > ,
1440
1440
keysend_preimage : Option < PaymentPreimage > ,
1441
+ /// Serialization will fail if this is not a valid TLV stream
1442
+ custom_tlvs : Vec < ( u64 , Vec < u8 > ) > ,
1441
1443
} ,
1442
1444
}
1443
1445
@@ -1965,14 +1967,22 @@ impl Writeable for OnionHopData {
1965
1967
( 6 , short_channel_id, required)
1966
1968
} ) ;
1967
1969
} ,
1968
- OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
1970
+ OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage, ref custom_tlvs } => {
1971
+ // We need to update [`ln::outbound_payment::RecipientOnionFields::with_custom_tlvs`]
1972
+ // to reject any reserved types in the experimental range if new ones are ever
1973
+ // standardized.
1974
+ let preimage = if let Some ( ref preimage) = keysend_preimage {
1975
+ Some ( ( 5482373484 , preimage. encode ( ) ) )
1976
+ } else { None } ;
1977
+ let mut custom_tlvs: Vec < & ( u64 , Vec < u8 > ) > = custom_tlvs. iter ( ) . chain ( preimage. iter ( ) ) . collect ( ) ;
1978
+ custom_tlvs. sort_unstable_by_key ( |( typ, _) | * typ) ;
1979
+
1969
1980
_encode_varint_length_prefixed_tlv ! ( w, {
1970
1981
( 2 , HighZeroBytesDroppedBigSize ( self . amt_to_forward) , required) ,
1971
1982
( 4 , HighZeroBytesDroppedBigSize ( self . outgoing_cltv_value) , required) ,
1972
1983
( 8 , payment_data, option) ,
1973
- ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option) ,
1974
- ( 5482373484 , keysend_preimage, option)
1975
- } ) ;
1984
+ ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option)
1985
+ } , custom_tlvs. iter( ) ) ;
1976
1986
} ,
1977
1987
}
1978
1988
Ok ( ( ) )
@@ -1987,14 +1997,24 @@ impl Readable for OnionHopData {
1987
1997
let mut payment_data: Option < FinalOnionHopData > = None ;
1988
1998
let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
1989
1999
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1990
- read_tlv_fields ! ( r, {
2000
+ let mut custom_tlvs = Vec :: new ( ) ;
2001
+
2002
+ let tlv_len = BigSize :: read ( r) ?;
2003
+ let rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
2004
+ decode_tlv_stream_with_custom_tlv_decode ! ( rd, {
1991
2005
( 2 , amt, required) ,
1992
2006
( 4 , cltv_value, required) ,
1993
2007
( 6 , short_id, option) ,
1994
2008
( 8 , payment_data, option) ,
1995
2009
( 16 , payment_metadata, option) ,
1996
2010
// See https://github.com/lightning/blips/blob/master/blip-0003.md
1997
2011
( 5482373484 , keysend_preimage, option)
2012
+ } , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
2013
+ if msg_type < 1 << 16 { return Ok ( false ) }
2014
+ let mut value = Vec :: new( ) ;
2015
+ msg_reader. read_to_end( & mut value) ?;
2016
+ custom_tlvs. push( ( msg_type, value) ) ;
2017
+ Ok ( true )
1998
2018
} ) ;
1999
2019
2000
2020
let format = if let Some ( short_channel_id) = short_id {
@@ -2013,6 +2033,7 @@ impl Readable for OnionHopData {
2013
2033
payment_data,
2014
2034
payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
2015
2035
keysend_preimage,
2036
+ custom_tlvs,
2016
2037
}
2017
2038
} ;
2018
2039
@@ -3555,6 +3576,7 @@ mod tests {
3555
3576
payment_data : None ,
3556
3577
payment_metadata : None ,
3557
3578
keysend_preimage : None ,
3579
+ custom_tlvs : vec ! [ ] ,
3558
3580
} ,
3559
3581
amt_to_forward : 0x0badf00d01020304 ,
3560
3582
outgoing_cltv_value : 0xffffffff ,
@@ -3579,6 +3601,7 @@ mod tests {
3579
3601
} ) ,
3580
3602
payment_metadata : None ,
3581
3603
keysend_preimage : None ,
3604
+ custom_tlvs : vec ! [ ] ,
3582
3605
} ,
3583
3606
amt_to_forward : 0x0badf00d01020304 ,
3584
3607
outgoing_cltv_value : 0xffffffff ,
@@ -3594,13 +3617,81 @@ mod tests {
3594
3617
} ) ,
3595
3618
payment_metadata : None ,
3596
3619
keysend_preimage : None ,
3620
+ custom_tlvs : _,
3597
3621
} = msg. format {
3598
3622
assert_eq ! ( payment_secret, expected_payment_secret) ;
3599
3623
} else { panic ! ( ) ; }
3600
3624
assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3601
3625
assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3602
3626
}
3603
3627
3628
+ #[ test]
3629
+ fn encoding_final_onion_hop_data_with_bad_custom_tlvs ( ) {
3630
+ // If custom TLVs have type number within the range reserved for protocol, treat them as if
3631
+ // they're unknown
3632
+ let bad_type_range_tlvs = vec ! [
3633
+ ( ( 1 << 16 ) - 4 , vec![ 42 ] ) ,
3634
+ ( ( 1 << 16 ) - 2 , vec![ 42 ; 32 ] ) ,
3635
+ ] ;
3636
+ let mut msg = msgs:: OnionHopData {
3637
+ format : OnionHopDataFormat :: FinalNode {
3638
+ payment_data : None ,
3639
+ payment_metadata : None ,
3640
+ keysend_preimage : None ,
3641
+ custom_tlvs : bad_type_range_tlvs,
3642
+ } ,
3643
+ amt_to_forward : 0x0badf00d01020304 ,
3644
+ outgoing_cltv_value : 0xffffffff ,
3645
+ } ;
3646
+ let encoded_value = msg. encode ( ) ;
3647
+ assert ! ( msgs:: OnionHopData :: read( & mut Cursor :: new( & encoded_value[ ..] ) ) . is_err( ) ) ;
3648
+ let good_type_range_tlvs = vec ! [
3649
+ ( ( 1 << 16 ) - 3 , vec![ 42 ] ) ,
3650
+ ( ( 1 << 16 ) - 1 , vec![ 42 ; 32 ] ) ,
3651
+ ] ;
3652
+ if let OnionHopDataFormat :: FinalNode { ref mut custom_tlvs, .. } = msg. format {
3653
+ * custom_tlvs = good_type_range_tlvs. clone ( ) ;
3654
+ }
3655
+ let encoded_value = msg. encode ( ) ;
3656
+ msg = Readable :: read ( & mut Cursor :: new ( & encoded_value[ ..] ) ) . unwrap ( ) ;
3657
+ match msg. format {
3658
+ OnionHopDataFormat :: FinalNode { custom_tlvs, .. } => assert ! ( custom_tlvs. is_empty( ) ) ,
3659
+ _ => panic ! ( ) ,
3660
+ }
3661
+ }
3662
+
3663
+ #[ test]
3664
+ fn encoding_final_onion_hop_data_with_custom_tlvs ( ) {
3665
+ let expected_custom_tlvs = vec ! [
3666
+ ( 5482373483 , vec![ 0x12 , 0x34 ] ) ,
3667
+ ( 5482373487 , vec![ 0x42u8 ; 8 ] ) ,
3668
+ ] ;
3669
+ let mut msg = msgs:: OnionHopData {
3670
+ format : OnionHopDataFormat :: FinalNode {
3671
+ payment_data : None ,
3672
+ payment_metadata : None ,
3673
+ keysend_preimage : None ,
3674
+ custom_tlvs : expected_custom_tlvs. clone ( ) ,
3675
+ } ,
3676
+ amt_to_forward : 0x0badf00d01020304 ,
3677
+ outgoing_cltv_value : 0xffffffff ,
3678
+ } ;
3679
+ let encoded_value = msg. encode ( ) ;
3680
+ let target_value = hex:: decode ( "2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242" ) . unwrap ( ) ;
3681
+ assert_eq ! ( encoded_value, target_value) ;
3682
+ msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3683
+ if let OnionHopDataFormat :: FinalNode {
3684
+ payment_data : None ,
3685
+ payment_metadata : None ,
3686
+ keysend_preimage : None ,
3687
+ custom_tlvs,
3688
+ } = msg. format {
3689
+ assert_eq ! ( custom_tlvs, expected_custom_tlvs) ;
3690
+ } else { panic ! ( ) ; }
3691
+ assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3692
+ assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3693
+ }
3694
+
3604
3695
#[ test]
3605
3696
fn query_channel_range_end_blocknum ( ) {
3606
3697
let tests: Vec < ( u32 , u32 , u32 ) > = vec ! [
0 commit comments