@@ -31,24 +31,26 @@ use bitcoin::{secp256k1, Witness};
3131use bitcoin:: blockdata:: script:: Script ;
3232use bitcoin:: hash_types:: { Txid , BlockHash } ;
3333
34+ use crate :: blinded_path:: payment:: ReceiveTlvs ;
3435use crate :: ln:: { ChannelId , PaymentPreimage , PaymentHash , PaymentSecret } ;
3536use crate :: ln:: features:: { ChannelFeatures , ChannelTypeFeatures , InitFeatures , NodeFeatures } ;
3637use crate :: ln:: onion_utils;
3738use crate :: onion_message;
38- use crate :: sign:: NodeSigner ;
39+ use crate :: sign:: { NodeSigner , Recipient } ;
3940
4041use crate :: prelude:: * ;
4142use core:: convert:: TryFrom ;
4243use core:: fmt;
4344use core:: fmt:: Debug ;
4445use core:: ops:: Deref ;
4546use core:: str:: FromStr ;
46- use crate :: io:: { self , Read } ;
47+ use crate :: io:: { self , Cursor , Read } ;
4748use crate :: io_extras:: read_to_end;
4849
4950use crate :: events:: { MessageSendEventsProvider , OnionMessageProvider } ;
51+ use crate :: util:: chacha20poly1305rfc:: ChaChaPolyReadAdapter ;
5052use crate :: util:: logger;
51- use crate :: util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited , BigSize } ;
53+ use crate :: util:: ser:: { LengthReadable , LengthReadableArgs , Readable , ReadableArgs , Writeable , Writer , WithoutLength , FixedLengthReader , HighZeroBytesDroppedBigSize , Hostname , TransactionU16LenLimited , BigSize } ;
5254use crate :: util:: base32;
5355
5456use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
@@ -1520,6 +1522,7 @@ pub trait OnionMessageHandler : OnionMessageProvider {
15201522
15211523mod fuzzy_internal_msgs {
15221524 use bitcoin:: secp256k1:: PublicKey ;
1525+ use crate :: blinded_path:: payment:: PaymentConstraints ;
15231526 use crate :: prelude:: * ;
15241527 use crate :: ln:: { PaymentPreimage , PaymentSecret } ;
15251528
@@ -1548,6 +1551,14 @@ mod fuzzy_internal_msgs {
15481551 amt_msat : u64 ,
15491552 outgoing_cltv_value : u32 ,
15501553 } ,
1554+ BlindedReceive {
1555+ amt_msat : u64 ,
1556+ total_msat : u64 ,
1557+ outgoing_cltv_value : u32 ,
1558+ payment_secret : PaymentSecret ,
1559+ payment_constraints : PaymentConstraints ,
1560+ intro_node_blinding_point : PublicKey ,
1561+ }
15511562 }
15521563
15531564 pub ( crate ) enum OutboundOnionPayload {
@@ -2136,22 +2147,28 @@ impl Writeable for OutboundOnionPayload {
21362147
21372148impl < NS : Deref > ReadableArgs < & NS > for InboundOnionPayload where NS :: Target : NodeSigner {
21382149 fn read < R : Read > ( r : & mut R , node_signer : & NS ) -> Result < Self , DecodeError > {
2139- let mut amt = HighZeroBytesDroppedBigSize ( 0u64 ) ;
2140- let mut cltv_value = HighZeroBytesDroppedBigSize ( 0u32 ) ;
2150+ let mut amt = None ;
2151+ let mut cltv_value = None ;
21412152 let mut short_id: Option < u64 > = None ;
21422153 let mut payment_data: Option < FinalOnionHopData > = None ;
2154+ let mut encrypted_tlvs_opt: Option < WithoutLength < Vec < u8 > > > = None ;
2155+ let mut intro_node_blinding_point = None ;
21432156 let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
2157+ let mut total_msat = None ;
21442158 let mut keysend_preimage: Option < PaymentPreimage > = None ;
21452159 let mut custom_tlvs = Vec :: new ( ) ;
21462160
21472161 let tlv_len = BigSize :: read ( r) ?;
21482162 let rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
21492163 decode_tlv_stream_with_custom_tlv_decode ! ( rd, {
2150- ( 2 , amt, required ) ,
2151- ( 4 , cltv_value, required ) ,
2164+ ( 2 , amt, ( option , encoding : ( u64 , HighZeroBytesDroppedBigSize ) ) ) ,
2165+ ( 4 , cltv_value, ( option , encoding : ( u32 , HighZeroBytesDroppedBigSize ) ) ) ,
21522166 ( 6 , short_id, option) ,
21532167 ( 8 , payment_data, option) ,
2168+ ( 10 , encrypted_tlvs_opt, option) ,
2169+ ( 12 , intro_node_blinding_point, option) ,
21542170 ( 16 , payment_metadata, option) ,
2171+ ( 18 , total_msat, ( option, encoding: ( u64 , HighZeroBytesDroppedBigSize ) ) ) ,
21552172 // See https://github.com/lightning/blips/blob/master/blip-0003.md
21562173 ( 5482373484 , keysend_preimage, option)
21572174 } , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
@@ -2162,16 +2179,44 @@ impl<NS: Deref> ReadableArgs<&NS> for InboundOnionPayload where NS::Target: Node
21622179 Ok ( true )
21632180 } ) ;
21642181
2165- if amt. 0 > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
2166- if let Some ( short_channel_id) = short_id {
2167- if payment_data. is_some ( ) { return Err ( DecodeError :: InvalidValue ) }
2168- if payment_metadata. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
2182+ if amt. unwrap_or ( 0 ) > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
2183+
2184+ if let Some ( blinding_point) = intro_node_blinding_point {
2185+ if short_id. is_some ( ) || payment_data. is_some ( ) || payment_metadata. is_some ( ) {
2186+ return Err ( DecodeError :: InvalidValue )
2187+ }
2188+ let enc_tlvs = encrypted_tlvs_opt. ok_or ( DecodeError :: InvalidValue ) ?. 0 ;
2189+ let enc_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & blinding_point, None )
2190+ . map_err ( |_| DecodeError :: InvalidValue ) ?;
2191+ let rho = onion_utils:: gen_rho_from_shared_secret ( & enc_tlvs_ss. secret_bytes ( ) ) ;
2192+ let mut s = Cursor :: new ( & enc_tlvs) ;
2193+ let mut reader = FixedLengthReader :: new ( & mut s, enc_tlvs. len ( ) as u64 ) ;
2194+ match ChaChaPolyReadAdapter :: read ( & mut reader, rho) ? {
2195+ ChaChaPolyReadAdapter { readable : ReceiveTlvs { payment_secret, payment_constraints } } => {
2196+ if total_msat. unwrap_or ( 0 ) > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
2197+ Ok ( Self :: BlindedReceive {
2198+ amt_msat : amt. ok_or ( DecodeError :: InvalidValue ) ?,
2199+ total_msat : total_msat. ok_or ( DecodeError :: InvalidValue ) ?,
2200+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ?,
2201+ payment_secret,
2202+ payment_constraints,
2203+ intro_node_blinding_point : blinding_point,
2204+ } )
2205+ } ,
2206+ }
2207+ } else if let Some ( short_channel_id) = short_id {
2208+ if payment_data. is_some ( ) || payment_metadata. is_some ( ) || encrypted_tlvs_opt. is_some ( ) ||
2209+ total_msat. is_some ( )
2210+ { return Err ( DecodeError :: InvalidValue ) }
21692211 Ok ( Self :: Forward {
21702212 short_channel_id,
2171- amt_to_forward : amt. 0 ,
2172- outgoing_cltv_value : cltv_value. 0 ,
2213+ amt_to_forward : amt. ok_or ( DecodeError :: InvalidValue ) ? ,
2214+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ? ,
21732215 } )
21742216 } else {
2217+ if encrypted_tlvs_opt. is_some ( ) || total_msat. is_some ( ) {
2218+ return Err ( DecodeError :: InvalidValue )
2219+ }
21752220 if let Some ( data) = & payment_data {
21762221 if data. total_msat > MAX_VALUE_MSAT {
21772222 return Err ( DecodeError :: InvalidValue ) ;
@@ -2181,8 +2226,8 @@ impl<NS: Deref> ReadableArgs<&NS> for InboundOnionPayload where NS::Target: Node
21812226 payment_data,
21822227 payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
21832228 keysend_preimage,
2184- amt_msat : amt. 0 ,
2185- outgoing_cltv_value : cltv_value. 0 ,
2229+ amt_msat : amt. ok_or ( DecodeError :: InvalidValue ) ? ,
2230+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ? ,
21862231 custom_tlvs,
21872232 } )
21882233 }
0 commit comments