@@ -31,20 +31,24 @@ use bitcoin::{secp256k1, Witness};
31
31
use bitcoin:: blockdata:: script:: Script ;
32
32
use bitcoin:: hash_types:: { Txid , BlockHash } ;
33
33
34
+ use crate :: blinded_path:: payment:: { BlindedPaymentTlvs , ForwardTlvs , ReceiveTlvs } ;
34
35
use crate :: ln:: { ChannelId , PaymentPreimage , PaymentHash , PaymentSecret } ;
35
36
use crate :: ln:: features:: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , NodeFeatures } ;
36
37
use crate :: ln:: onion_utils;
37
38
use crate :: onion_message;
39
+ use crate :: sign:: { NodeSigner , Recipient } ;
38
40
39
41
use crate :: prelude:: * ;
40
42
use core:: fmt;
41
43
use core:: fmt:: Debug ;
42
- use crate :: io:: { self , Read } ;
44
+ use core:: ops:: Deref ;
45
+ use crate :: io:: { self , Cursor , Read } ;
43
46
use crate :: io_extras:: read_to_end;
44
47
45
48
use crate :: events:: { MessageSendEventsProvider , OnionMessageProvider } ;
49
+ use crate :: util:: chacha20poly1305rfc:: ChaChaPolyReadAdapter ;
46
50
use crate :: util:: logger;
47
- use crate :: util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited , BigSize } ;
51
+ use crate :: util:: ser:: { LengthReadable , LengthReadableArgs , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited , BigSize } ;
48
52
49
53
use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
50
54
@@ -1420,8 +1424,10 @@ pub trait OnionMessageHandler : OnionMessageProvider {
1420
1424
1421
1425
mod fuzzy_internal_msgs {
1422
1426
use bitcoin:: secp256k1:: PublicKey ;
1427
+ use crate :: blinded_path:: payment:: { PaymentConstraints , PaymentRelay } ;
1423
1428
use crate :: prelude:: * ;
1424
1429
use crate :: ln:: { PaymentPreimage , PaymentSecret } ;
1430
+ use crate :: ln:: features:: BlindedHopFeatures ;
1425
1431
1426
1432
// These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize
1427
1433
// them from untrusted input):
@@ -1448,6 +1454,21 @@ mod fuzzy_internal_msgs {
1448
1454
amt_msat : u64 ,
1449
1455
outgoing_cltv_value : u32 ,
1450
1456
} ,
1457
+ BlindedForward {
1458
+ short_channel_id : u64 ,
1459
+ payment_relay : PaymentRelay ,
1460
+ payment_constraints : PaymentConstraints ,
1461
+ features : BlindedHopFeatures ,
1462
+ intro_node_blinding_point : Option < PublicKey > ,
1463
+ } ,
1464
+ BlindedReceive {
1465
+ amt_msat : u64 ,
1466
+ total_msat : u64 ,
1467
+ outgoing_cltv_value : u32 ,
1468
+ payment_secret : PaymentSecret ,
1469
+ payment_constraints : PaymentConstraints ,
1470
+ intro_node_blinding_point : Option < PublicKey > ,
1471
+ }
1451
1472
}
1452
1473
1453
1474
pub ( crate ) enum OutboundOnionPayload {
@@ -2035,24 +2056,33 @@ impl Writeable for OutboundOnionPayload {
2035
2056
}
2036
2057
}
2037
2058
2038
- impl Readable for InboundOnionPayload {
2039
- fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
2040
- let mut amt = HighZeroBytesDroppedBigSize ( 0u64 ) ;
2041
- let mut cltv_value = HighZeroBytesDroppedBigSize ( 0u32 ) ;
2059
+ impl < NS : Deref > ReadableArgs < ( Option < PublicKey > , & NS ) > for InboundOnionPayload where NS :: Target : NodeSigner {
2060
+ fn read < R : Read > ( r : & mut R , args : ( Option < PublicKey > , & NS ) ) -> Result < Self , DecodeError > {
2061
+ // TODO if we are the intro node and hit an error here, we won't correctly return the malformed
2062
+ // error atm
2063
+ let ( update_add_blinding_point, node_signer) = args;
2064
+ let mut amt = None ;
2065
+ let mut cltv_value = None ;
2042
2066
let mut short_id: Option < u64 > = None ;
2043
2067
let mut payment_data: Option < FinalOnionHopData > = None ;
2068
+ let mut encrypted_tlvs_opt: Option < WithoutLength < Vec < u8 > > > = None ;
2069
+ let mut intro_node_blinding_point = None ;
2044
2070
let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
2071
+ let mut total_msat = None ;
2045
2072
let mut keysend_preimage: Option < PaymentPreimage > = None ;
2046
2073
let mut custom_tlvs = Vec :: new ( ) ;
2047
2074
2048
2075
let tlv_len = BigSize :: read ( r) ?;
2049
2076
let rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
2050
2077
decode_tlv_stream_with_custom_tlv_decode ! ( rd, {
2051
- ( 2 , amt, required ) ,
2052
- ( 4 , cltv_value, required ) ,
2078
+ ( 2 , amt, ( option , encoding : ( u64 , HighZeroBytesDroppedBigSize ) ) ) ,
2079
+ ( 4 , cltv_value, ( option , encoding : ( u32 , HighZeroBytesDroppedBigSize ) ) ) ,
2053
2080
( 6 , short_id, option) ,
2054
2081
( 8 , payment_data, option) ,
2082
+ ( 10 , encrypted_tlvs_opt, option) ,
2083
+ ( 12 , intro_node_blinding_point, option) ,
2055
2084
( 16 , payment_metadata, option) ,
2085
+ ( 18 , total_msat, ( option, encoding: ( u64 , HighZeroBytesDroppedBigSize ) ) ) ,
2056
2086
// See https://github.com/lightning/blips/blob/master/blip-0003.md
2057
2087
( 5482373484 , keysend_preimage, option)
2058
2088
} , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
@@ -2063,41 +2093,82 @@ impl Readable for InboundOnionPayload {
2063
2093
Ok ( true )
2064
2094
} ) ;
2065
2095
2066
- if amt. 0 > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
2067
- if let Some ( short_channel_id) = short_id {
2068
- if payment_data. is_some ( ) { return Err ( DecodeError :: InvalidValue ) }
2069
- if payment_metadata. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
2096
+ if update_add_blinding_point. is_some ( ) && intro_node_blinding_point. is_some ( ) {
2097
+ return Err ( DecodeError :: InvalidValue )
2098
+ }
2099
+ if amt. unwrap_or ( 0 ) > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
2100
+
2101
+ if let Some ( blinding_point) = update_add_blinding_point. or ( intro_node_blinding_point) {
2102
+ if short_id. is_some ( ) || payment_data. is_some ( ) || payment_metadata. is_some ( ) {
2103
+ return Err ( DecodeError :: InvalidValue )
2104
+ }
2105
+ let enc_tlvs = encrypted_tlvs_opt. ok_or ( DecodeError :: InvalidValue ) ?. 0 ;
2106
+ let enc_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & blinding_point, None )
2107
+ . map_err ( |_| DecodeError :: InvalidValue ) ?;
2108
+ let rho = onion_utils:: gen_rho_from_shared_secret ( & enc_tlvs_ss. secret_bytes ( ) ) ;
2109
+ let mut s = Cursor :: new ( & enc_tlvs) ;
2110
+ let mut reader = FixedLengthReader :: new ( & mut s, enc_tlvs. len ( ) as u64 ) ;
2111
+ match ChaChaPolyReadAdapter :: read ( & mut reader, rho) ? {
2112
+ ChaChaPolyReadAdapter { readable : BlindedPaymentTlvs :: Forward ( ForwardTlvs {
2113
+ short_channel_id, payment_relay, payment_constraints, features
2114
+ } ) } => {
2115
+ if amt. is_some ( ) || cltv_value. is_some ( ) || total_msat. is_some ( ) {
2116
+ return Err ( DecodeError :: InvalidValue )
2117
+ }
2118
+ Ok ( Self :: BlindedForward {
2119
+ short_channel_id,
2120
+ payment_relay,
2121
+ payment_constraints,
2122
+ features,
2123
+ intro_node_blinding_point,
2124
+ } )
2125
+ } ,
2126
+ ChaChaPolyReadAdapter { readable : BlindedPaymentTlvs :: Receive ( ReceiveTlvs {
2127
+ payment_secret, payment_constraints
2128
+ } ) } => {
2129
+ if total_msat. unwrap_or ( 0 ) > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
2130
+ Ok ( Self :: BlindedReceive {
2131
+ amt_msat : amt. ok_or ( DecodeError :: InvalidValue ) ?,
2132
+ total_msat : total_msat. ok_or ( DecodeError :: InvalidValue ) ?,
2133
+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ?,
2134
+ payment_secret,
2135
+ payment_constraints,
2136
+ intro_node_blinding_point,
2137
+ } )
2138
+ } ,
2139
+ }
2140
+ } else if let Some ( short_channel_id) = short_id {
2141
+ if payment_data. is_some ( ) || payment_metadata. is_some ( ) || encrypted_tlvs_opt. is_some ( ) ||
2142
+ total_msat. is_some ( )
2143
+ {
2144
+ return Err ( DecodeError :: InvalidValue )
2145
+ }
2070
2146
Ok ( Self :: Forward {
2071
2147
short_channel_id,
2072
- amt_to_forward : amt. 0 ,
2073
- outgoing_cltv_value : cltv_value. 0 ,
2148
+ amt_to_forward : amt. ok_or ( DecodeError :: InvalidValue ) ? ,
2149
+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ? ,
2074
2150
} )
2075
2151
} else {
2152
+ if encrypted_tlvs_opt. is_some ( ) || total_msat. is_some ( ) {
2153
+ return Err ( DecodeError :: InvalidValue )
2154
+ }
2076
2155
if let Some ( data) = & payment_data {
2077
2156
if data. total_msat > MAX_VALUE_MSAT {
2078
- return Err ( DecodeError :: InvalidValue ) ;
2157
+ return Err ( DecodeError :: InvalidValue )
2079
2158
}
2080
2159
}
2081
2160
Ok ( Self :: Receive {
2082
2161
payment_data,
2083
2162
payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
2084
2163
keysend_preimage,
2085
- amt_msat : amt. 0 ,
2086
- outgoing_cltv_value : cltv_value. 0 ,
2164
+ amt_msat : amt. ok_or ( DecodeError :: InvalidValue ) ? ,
2165
+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ? ,
2087
2166
custom_tlvs,
2088
2167
} )
2089
2168
}
2090
2169
}
2091
2170
}
2092
2171
2093
- // ReadableArgs because we need onion_utils::decode_next_hop to accommodate payment packets and
2094
- // onion message packets.
2095
- impl ReadableArgs < ( ) > for InboundOnionPayload {
2096
- fn read < R : Read > ( r : & mut R , _arg : ( ) ) -> Result < Self , DecodeError > {
2097
- <Self as Readable >:: read ( r)
2098
- }
2099
- }
2100
-
2101
2172
impl Writeable for Ping {
2102
2173
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
2103
2174
self . ponglen . write ( w) ?;
@@ -2513,7 +2584,8 @@ mod tests {
2513
2584
use crate :: ln:: features:: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , NodeFeatures } ;
2514
2585
use crate :: ln:: msgs:: { self , FinalOnionHopData , OnionErrorPacket } ;
2515
2586
use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
2516
- use crate :: util:: ser:: { Writeable , Readable , Hostname , TransactionU16LenLimited } ;
2587
+ use crate :: util:: ser:: { Writeable , Readable , ReadableArgs , Hostname , TransactionU16LenLimited } ;
2588
+ use crate :: util:: test_utils;
2517
2589
2518
2590
use bitcoin:: hashes:: hex:: FromHex ;
2519
2591
use bitcoin:: util:: address:: Address ;
@@ -3604,8 +3676,11 @@ mod tests {
3604
3676
let target_value = hex:: decode ( "1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea" ) . unwrap ( ) ;
3605
3677
assert_eq ! ( encoded_value, target_value) ;
3606
3678
3607
- let inbound_msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3608
- if let msgs:: InboundOnionPayload :: Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = inbound_msg {
3679
+ let node_signer = test_utils:: TestKeysInterface :: new ( & [ 42 ; 32 ] , Network :: Testnet ) ;
3680
+ let inbound_msg = ReadableArgs :: read ( & mut Cursor :: new ( & target_value[ ..] ) , ( None , & & node_signer) ) . unwrap ( ) ;
3681
+ if let msgs:: InboundOnionPayload :: Forward {
3682
+ short_channel_id, amt_to_forward, outgoing_cltv_value
3683
+ } = inbound_msg {
3609
3684
assert_eq ! ( short_channel_id, 0xdeadbeef1bad1dea ) ;
3610
3685
assert_eq ! ( amt_to_forward, 0x0badf00d01020304 ) ;
3611
3686
assert_eq ! ( outgoing_cltv_value, 0xffffffff ) ;
@@ -3626,8 +3701,11 @@ mod tests {
3626
3701
let target_value = hex:: decode ( "1002080badf00d010203040404ffffffff" ) . unwrap ( ) ;
3627
3702
assert_eq ! ( encoded_value, target_value) ;
3628
3703
3629
- let inbound_msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3630
- if let msgs:: InboundOnionPayload :: Receive { payment_data : None , amt_msat, outgoing_cltv_value, .. } = inbound_msg {
3704
+ let node_signer = test_utils:: TestKeysInterface :: new ( & [ 42 ; 32 ] , Network :: Testnet ) ;
3705
+ let inbound_msg = ReadableArgs :: read ( & mut Cursor :: new ( & target_value[ ..] ) , ( None , & & node_signer) ) . unwrap ( ) ;
3706
+ if let msgs:: InboundOnionPayload :: Receive {
3707
+ payment_data : None , amt_msat, outgoing_cltv_value, ..
3708
+ } = inbound_msg {
3631
3709
assert_eq ! ( amt_msat, 0x0badf00d01020304 ) ;
3632
3710
assert_eq ! ( outgoing_cltv_value, 0xffffffff ) ;
3633
3711
} else { panic ! ( ) ; }
@@ -3651,7 +3729,8 @@ mod tests {
3651
3729
let target_value = hex:: decode ( "3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f" ) . unwrap ( ) ;
3652
3730
assert_eq ! ( encoded_value, target_value) ;
3653
3731
3654
- let inbound_msg = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3732
+ let node_signer = test_utils:: TestKeysInterface :: new ( & [ 42 ; 32 ] , Network :: Testnet ) ;
3733
+ let inbound_msg = ReadableArgs :: read ( & mut Cursor :: new ( & target_value[ ..] ) , ( None , & & node_signer) ) . unwrap ( ) ;
3655
3734
if let msgs:: InboundOnionPayload :: Receive {
3656
3735
payment_data : Some ( FinalOnionHopData {
3657
3736
payment_secret,
@@ -3686,7 +3765,8 @@ mod tests {
3686
3765
outgoing_cltv_value : 0xffffffff ,
3687
3766
} ;
3688
3767
let encoded_value = msg. encode ( ) ;
3689
- assert ! ( msgs:: InboundOnionPayload :: read( & mut Cursor :: new( & encoded_value[ ..] ) ) . is_err( ) ) ;
3768
+ let node_signer = test_utils:: TestKeysInterface :: new ( & [ 42 ; 32 ] , Network :: Testnet ) ;
3769
+ assert ! ( msgs:: InboundOnionPayload :: read( & mut Cursor :: new( & encoded_value[ ..] ) , ( None , &&node_signer) ) . is_err( ) ) ;
3690
3770
let good_type_range_tlvs = vec ! [
3691
3771
( ( 1 << 16 ) - 3 , vec![ 42 ] ) ,
3692
3772
( ( 1 << 16 ) - 1 , vec![ 42 ; 32 ] ) ,
@@ -3695,7 +3775,7 @@ mod tests {
3695
3775
* custom_tlvs = good_type_range_tlvs. clone ( ) ;
3696
3776
}
3697
3777
let encoded_value = msg. encode ( ) ;
3698
- let inbound_msg = Readable :: read ( & mut Cursor :: new ( & encoded_value[ ..] ) ) . unwrap ( ) ;
3778
+ let inbound_msg = ReadableArgs :: read ( & mut Cursor :: new ( & encoded_value[ ..] ) , ( None , & & node_signer ) ) . unwrap ( ) ;
3699
3779
match inbound_msg {
3700
3780
msgs:: InboundOnionPayload :: Receive { custom_tlvs, .. } => assert ! ( custom_tlvs. is_empty( ) ) ,
3701
3781
_ => panic ! ( ) ,
@@ -3719,7 +3799,8 @@ mod tests {
3719
3799
let encoded_value = msg. encode ( ) ;
3720
3800
let target_value = hex:: decode ( "2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242" ) . unwrap ( ) ;
3721
3801
assert_eq ! ( encoded_value, target_value) ;
3722
- let inbound_msg: msgs:: InboundOnionPayload = Readable :: read ( & mut Cursor :: new ( & target_value[ ..] ) ) . unwrap ( ) ;
3802
+ let node_signer = test_utils:: TestKeysInterface :: new ( & [ 42 ; 32 ] , Network :: Testnet ) ;
3803
+ let inbound_msg: msgs:: InboundOnionPayload = ReadableArgs :: read ( & mut Cursor :: new ( & target_value[ ..] ) , ( None , & & node_signer) ) . unwrap ( ) ;
3723
3804
if let msgs:: InboundOnionPayload :: Receive {
3724
3805
payment_data : None ,
3725
3806
payment_metadata : None ,
@@ -3882,7 +3963,10 @@ mod tests {
3882
3963
// payload length to be encoded over multiple bytes rather than a single u8.
3883
3964
let big_payload = encode_big_payload ( ) . unwrap ( ) ;
3884
3965
let mut rd = Cursor :: new ( & big_payload[ ..] ) ;
3885
- <msgs:: InboundOnionPayload as Readable >:: read ( & mut rd) . unwrap ( ) ;
3966
+
3967
+ let node_signer = test_utils:: TestKeysInterface :: new ( & [ 42 ; 32 ] , Network :: Testnet ) ;
3968
+ <msgs:: InboundOnionPayload as ReadableArgs < ( Option < PublicKey > , & & test_utils:: TestKeysInterface ) > >
3969
+ :: read ( & mut rd, ( None , & & node_signer) ) . unwrap ( ) ;
3886
3970
}
3887
3971
// see above test, needs to be a separate method for use of the serialization macros.
3888
3972
fn encode_big_payload ( ) -> Result < Vec < u8 > , io:: Error > {
0 commit comments