@@ -32,6 +32,7 @@ use bitcoin::hash_types::{Txid, BlockHash};
32
32
33
33
use crate :: ln:: features:: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , NodeFeatures } ;
34
34
use crate :: ln:: onion_utils;
35
+ use crate :: offers:: { TlvStream , TlvRecord } ;
35
36
use crate :: onion_message;
36
37
37
38
use crate :: prelude:: * ;
@@ -42,7 +43,7 @@ use crate::io_extras::read_to_end;
42
43
43
44
use crate :: events:: { MessageSendEventsProvider , OnionMessageProvider } ;
44
45
use crate :: util:: logger;
45
- 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 } ;
46
47
47
48
use crate :: ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
48
49
@@ -1413,6 +1414,8 @@ mod fuzzy_internal_msgs {
1413
1414
payment_data : Option < FinalOnionHopData > ,
1414
1415
payment_metadata : Option < Vec < u8 > > ,
1415
1416
keysend_preimage : Option < PaymentPreimage > ,
1417
+ /// Serialization will fail if this is not a valid TLV stream
1418
+ custom_tlvs : Option < Vec < u8 > > ,
1416
1419
} ,
1417
1420
}
1418
1421
@@ -1934,20 +1937,36 @@ impl Writeable for OnionHopData {
1934
1937
( 6 , short_channel_id, required)
1935
1938
} ) ;
1936
1939
} ,
1937
- OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
1940
+ OnionHopDataFormat :: FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage, ref custom_tlvs } => {
1941
+ let mut custom_tlv_stream = custom_tlvs. clone ( ) . unwrap_or ( Vec :: new ( ) ) ;
1942
+ encode_tlv_stream ! ( & mut custom_tlv_stream, {
1943
+ ( 5482373484 , keysend_preimage, option)
1944
+ } ) ;
1945
+ let sorted_custom_tlvs = sorted_tlv_stream ( & custom_tlv_stream) ?;
1938
1946
_encode_varint_length_prefixed_tlv ! ( w, {
1939
1947
( 2 , HighZeroBytesDroppedBigSize ( self . amt_to_forward) , required) ,
1940
1948
( 4 , HighZeroBytesDroppedBigSize ( self . outgoing_cltv_value) , required) ,
1941
1949
( 8 , payment_data, option) ,
1942
- ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option) ,
1943
- ( 5482373484 , keysend_preimage, option)
1944
- } ) ;
1950
+ ( 16 , payment_metadata. as_ref( ) . map( |m| WithoutLength ( m) ) , option)
1951
+ } , & sorted_custom_tlvs) ;
1945
1952
} ,
1946
1953
}
1947
1954
Ok ( ( ) )
1948
1955
}
1949
1956
}
1950
1957
1958
+ fn sorted_tlv_stream ( bytes : & [ u8 ] ) -> Result < Vec < u8 > , io:: Error > {
1959
+ let mut tlv_stream = TlvStream :: try_new ( bytes)
1960
+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "Could not serialize custom TLV stream" ) ) ?
1961
+ . collect :: < Vec < TlvRecord > > ( ) ;
1962
+ tlv_stream. sort_by_key ( |tlv| tlv. get_type ( ) ) ;
1963
+ let mut sorted_bytes = Vec :: with_capacity ( bytes. len ( ) ) ;
1964
+ for tlv in tlv_stream {
1965
+ tlv. write ( & mut sorted_bytes) ?;
1966
+ }
1967
+ Ok ( sorted_bytes)
1968
+ }
1969
+
1951
1970
impl Readable for OnionHopData {
1952
1971
fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1953
1972
let mut amt = HighZeroBytesDroppedBigSize ( 0u64 ) ;
@@ -1956,14 +1975,27 @@ impl Readable for OnionHopData {
1956
1975
let mut payment_data: Option < FinalOnionHopData > = None ;
1957
1976
let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
1958
1977
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1959
- read_tlv_fields ! ( r, {
1978
+ let mut custom_tlvs = Vec :: new ( ) ;
1979
+
1980
+ let tlv_len = BigSize :: read ( r) ?;
1981
+ let rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
1982
+ decode_tlv_stream_with_custom_tlv_decode ! ( rd, {
1960
1983
( 2 , amt, required) ,
1961
1984
( 4 , cltv_value, required) ,
1962
1985
( 6 , short_id, option) ,
1963
1986
( 8 , payment_data, option) ,
1964
1987
( 16 , payment_metadata, option) ,
1965
1988
// See https://github.com/lightning/blips/blob/master/blip-0003.md
1966
1989
( 5482373484 , keysend_preimage, option)
1990
+ } , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
1991
+ if msg_type < 1 << 16 { return Ok ( false ) }
1992
+ // Re-serialize into TLV record
1993
+ let mut buffer = Vec :: new( ) ;
1994
+ msg_reader. read_to_end( & mut buffer) ?;
1995
+ BigSize ( msg_type) . write( & mut custom_tlvs) ?;
1996
+ BigSize ( buffer. len( ) as u64 ) . write( & mut custom_tlvs) ?;
1997
+ custom_tlvs. append( & mut buffer) ;
1998
+ Ok ( true )
1967
1999
} ) ;
1968
2000
1969
2001
let format = if let Some ( short_channel_id) = short_id {
@@ -1982,6 +2014,7 @@ impl Readable for OnionHopData {
1982
2014
payment_data,
1983
2015
payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
1984
2016
keysend_preimage,
2017
+ custom_tlvs : if custom_tlvs. is_empty ( ) { None } else { Some ( custom_tlvs) } ,
1985
2018
}
1986
2019
} ;
1987
2020
@@ -2417,7 +2450,7 @@ mod tests {
2417
2450
use crate :: ln:: features:: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , NodeFeatures } ;
2418
2451
use crate :: ln:: msgs:: { self , FinalOnionHopData , OnionErrorPacket , OnionHopDataFormat } ;
2419
2452
use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
2420
- use crate :: util:: ser:: { Writeable , Readable , Hostname , TransactionU16LenLimited } ;
2453
+ use crate :: util:: ser:: { Writeable , Writer , Readable , Hostname , TransactionU16LenLimited } ;
2421
2454
2422
2455
use bitcoin:: hashes:: hex:: FromHex ;
2423
2456
use bitcoin:: util:: address:: Address ;
@@ -3513,6 +3546,7 @@ mod tests {
3513
3546
payment_data : None ,
3514
3547
payment_metadata : None ,
3515
3548
keysend_preimage : None ,
3549
+ custom_tlvs : None ,
3516
3550
} ,
3517
3551
amt_to_forward : 0x0badf00d01020304 ,
3518
3552
outgoing_cltv_value : 0xffffffff ,
@@ -3537,6 +3571,7 @@ mod tests {
3537
3571
} ) ,
3538
3572
payment_metadata : None ,
3539
3573
keysend_preimage : None ,
3574
+ custom_tlvs : None ,
3540
3575
} ,
3541
3576
amt_to_forward : 0x0badf00d01020304 ,
3542
3577
outgoing_cltv_value : 0xffffffff ,
@@ -3552,13 +3587,87 @@ mod tests {
3552
3587
} ) ,
3553
3588
payment_metadata : None ,
3554
3589
keysend_preimage : None ,
3590
+ custom_tlvs : None ,
3555
3591
} = msg. format {
3556
3592
assert_eq ! ( payment_secret, expected_payment_secret) ;
3557
3593
} else { panic ! ( ) ; }
3558
3594
assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3559
3595
assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3560
3596
}
3561
3597
3598
+ #[ test]
3599
+ fn encoding_final_onion_hop_data_with_bad_custom_tlvs ( ) {
3600
+ let bad_tlvs = vec ! [ 42 ; 32 ] ;
3601
+ let mut msg = msgs:: OnionHopData {
3602
+ format : OnionHopDataFormat :: FinalNode {
3603
+ payment_data : None ,
3604
+ payment_metadata : None ,
3605
+ keysend_preimage : None ,
3606
+ custom_tlvs : Some ( bad_tlvs) ,
3607
+ } ,
3608
+ amt_to_forward : 0x0badf00d01020304 ,
3609
+ outgoing_cltv_value : 0xffffffff ,
3610
+ } ;
3611
+ assert ! ( msg. write( & mut Vec :: new( ) ) . is_err( ) ) ;
3612
+
3613
+ // If custom TLVs have type number within the range reserved for protocol, treat them as if
3614
+ // they're unknown
3615
+ let bad_type_range_tlvs = _get_encoded_tlv_stream ! ( {
3616
+ ( ( 1 << 16 ) - 4 , 42 , required) ,
3617
+ ( ( 1 << 16 ) - 2 , Some ( vec![ 42 ; 32 ] ) , option) ,
3618
+ } ) ;
3619
+ if let OnionHopDataFormat :: FinalNode { ref mut custom_tlvs, .. } = msg. format {
3620
+ * custom_tlvs = Some ( bad_type_range_tlvs. clone ( ) ) ;
3621
+ }
3622
+ let encoded_value = msg. encode ( ) ;
3623
+ assert ! ( msgs:: OnionHopData :: read( & mut Cursor :: new( & encoded_value[ ..] ) ) . is_err( ) ) ;
3624
+ let good_type_range_tlvs = _get_encoded_tlv_stream ! ( {
3625
+ ( ( 1 << 16 ) - 3 , 42 , required) ,
3626
+ ( ( 1 << 16 ) - 1 , Some ( vec![ 42 ; 32 ] ) , option) ,
3627
+ } ) ;
3628
+ if let OnionHopDataFormat :: FinalNode { ref mut custom_tlvs, .. } = msg. format {
3629
+ * custom_tlvs = Some ( good_type_range_tlvs. clone ( ) ) ;
3630
+ }
3631
+ let encoded_value = msg. encode ( ) ;
3632
+ msg = Readable :: read ( & mut Cursor :: new ( & encoded_value[ ..] ) ) . unwrap ( ) ;
3633
+ match msg. format {
3634
+ OnionHopDataFormat :: FinalNode { custom_tlvs, .. } => assert ! ( custom_tlvs. is_none( ) ) ,
3635
+ _ => panic ! ( ) ,
3636
+ }
3637
+ }
3638
+
3639
+ #[ test]
3640
+ fn encoding_final_onion_hop_data_with_custom_tlvs ( ) {
3641
+ let expected_custom_tlvs = _get_encoded_tlv_stream ! ( {
3642
+ ( 5482373483 , 0x1234 , required) ,
3643
+ ( 5482373487 , Some ( vec![ 0x42u8 ; 8 ] ) , option) ,
3644
+ } ) ;
3645
+ let mut msg = msgs:: OnionHopData {
3646
+ format : OnionHopDataFormat :: FinalNode {
3647
+ payment_data : None ,
3648
+ payment_metadata : None ,
3649
+ keysend_preimage : None ,
3650
+ custom_tlvs : Some ( expected_custom_tlvs. clone ( ) ) ,
3651
+ } ,
3652
+ amt_to_forward : 0x0badf00d01020304 ,
3653
+ outgoing_cltv_value : 0xffffffff ,
3654
+ } ;
3655
+ let encoded_value = msg. encode ( ) ;
3656
+ let target_value = hex:: decode ( "3202080badf00d010203040404ffffffffff0000000146c6616b0400001234ff0000000146c6616f0a00084242424242424242" ) . unwrap ( ) ;
3657
+ assert_eq ! ( encoded_value, target_value) ;
3658
+ msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3659
+ if let OnionHopDataFormat :: FinalNode {
3660
+ payment_data : None ,
3661
+ payment_metadata : None ,
3662
+ keysend_preimage : None ,
3663
+ custom_tlvs,
3664
+ } = msg. format {
3665
+ assert_eq ! ( custom_tlvs. unwrap( ) , expected_custom_tlvs) ;
3666
+ } else { panic ! ( ) ; }
3667
+ assert_eq ! ( msg. amt_to_forward, 0x0badf00d01020304 ) ;
3668
+ assert_eq ! ( msg. outgoing_cltv_value, 0xffffffff ) ;
3669
+ }
3670
+
3562
3671
#[ test]
3563
3672
fn query_channel_range_end_blocknum ( ) {
3564
3673
let tests: Vec < ( u32 , u32 , u32 ) > = vec ! [
0 commit comments