@@ -40,7 +40,7 @@ use io_extras::read_to_end;
4040
4141use util:: events:: MessageSendEventsProvider ;
4242use util:: logger;
43- use util:: ser:: { Readable , Writeable , Writer , FixedLengthReader , HighZeroBytesDroppedVarInt } ;
43+ use util:: ser:: { Readable , Writeable , Writer , VecWriteWrapper , VecReadWrapper , FixedLengthReader , HighZeroBytesDroppedVarInt } ;
4444
4545use ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
4646
@@ -918,6 +918,7 @@ mod fuzzy_internal_msgs {
918918 #[ derive( Clone ) ]
919919 pub ( crate ) struct FinalOnionHopData {
920920 pub ( crate ) payment_secret : PaymentSecret ,
921+ pub ( crate ) payment_metadata : Option < Vec < u8 > > ,
921922 /// The total value, in msat, of the payment as received by the ultimate recipient.
922923 /// Message serialization may panic if this value is more than 21 million Bitcoin.
923924 pub ( crate ) total_msat : u64 ,
@@ -1301,6 +1302,11 @@ impl_writeable_msg!(UpdateAddHTLC, {
13011302 onion_routing_packet
13021303} , { } ) ;
13031304
1305+ // The serialization here is really funky - FinalOnionHopData somewhat serves as two different
1306+ // things. First, it is *the* object which is written with type 8 in the onion TLV. Second, it is
1307+ // the data which a node may expect to receive when we are the recipient of an invoice payment.
1308+ // Thus, its serialization doesn't match its in-memory layout - with the payment_metadata included
1309+ // in the struct, but serialized separately.
13041310impl Writeable for FinalOnionHopData {
13051311 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
13061312 self . payment_secret . 0 . write ( w) ?;
@@ -1312,7 +1318,7 @@ impl Readable for FinalOnionHopData {
13121318 fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
13131319 let secret: [ u8 ; 32 ] = Readable :: read ( r) ?;
13141320 let amt: HighZeroBytesDroppedVarInt < u64 > = Readable :: read ( r) ?;
1315- Ok ( Self { payment_secret : PaymentSecret ( secret) , total_msat : amt. 0 } )
1321+ Ok ( Self { payment_secret : PaymentSecret ( secret) , total_msat : amt. 0 , payment_metadata : None , } )
13161322 }
13171323}
13181324
@@ -1334,10 +1340,15 @@ impl Writeable for OnionHopData {
13341340 } ) ;
13351341 } ,
13361342 OnionHopDataFormat :: FinalNode { ref payment_data, ref keysend_preimage } => {
1343+ let payment_metadata = if let Some ( data) = payment_data {
1344+ if let Some ( ref metadata) = data. payment_metadata { Some ( VecWriteWrapper ( metadata) )
1345+ } else { None }
1346+ } else { None } ;
13371347 encode_varint_length_prefixed_tlv ! ( w, {
13381348 ( 2 , HighZeroBytesDroppedVarInt ( self . amt_to_forward) , required) ,
13391349 ( 4 , HighZeroBytesDroppedVarInt ( self . outgoing_cltv_value) , required) ,
13401350 ( 8 , payment_data, option) ,
1351+ ( 16 , payment_metadata, option) ,
13411352 ( 5482373484 , keysend_preimage, option)
13421353 } ) ;
13431354 } ,
@@ -1361,26 +1372,30 @@ impl Readable for OnionHopData {
13611372 let mut cltv_value = HighZeroBytesDroppedVarInt ( 0u32 ) ;
13621373 let mut short_id: Option < u64 > = None ;
13631374 let mut payment_data: Option < FinalOnionHopData > = None ;
1375+ let mut payment_metadata: Option < VecReadWrapper < u8 > > = None ;
13641376 let mut keysend_preimage: Option < PaymentPreimage > = None ;
13651377 // The TLV type is chosen to be compatible with lnd and c-lightning.
13661378 decode_tlv_stream ! ( & mut rd, {
13671379 ( 2 , amt, required) ,
13681380 ( 4 , cltv_value, required) ,
13691381 ( 6 , short_id, option) ,
13701382 ( 8 , payment_data, option) ,
1383+ ( 16 , payment_metadata, option) ,
13711384 ( 5482373484 , keysend_preimage, option)
13721385 } ) ;
13731386 rd. eat_remaining ( ) . map_err ( |_| DecodeError :: ShortRead ) ?;
13741387 let format = if let Some ( short_channel_id) = short_id {
13751388 if payment_data. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1389+ if payment_metadata. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
13761390 OnionHopDataFormat :: NonFinalNode {
13771391 short_channel_id,
13781392 }
13791393 } else {
1380- if let & Some ( ref data) = & payment_data {
1394+ if let Some ( ref mut data) = & mut payment_data {
13811395 if data. total_msat > MAX_VALUE_MSAT {
13821396 return Err ( DecodeError :: InvalidValue ) ;
13831397 }
1398+ data. payment_metadata = payment_metadata. map ( |v| v. 0 ) ;
13841399 }
13851400 OnionHopDataFormat :: FinalNode {
13861401 payment_data,
@@ -2587,6 +2602,7 @@ mod tests {
25872602 format : OnionHopDataFormat :: FinalNode {
25882603 payment_data : Some ( FinalOnionHopData {
25892604 payment_secret : expected_payment_secret,
2605+ payment_metadata : None ,
25902606 total_msat : 0x1badca1f
25912607 } ) ,
25922608 keysend_preimage : None ,
@@ -2601,6 +2617,7 @@ mod tests {
26012617 if let OnionHopDataFormat :: FinalNode {
26022618 payment_data : Some ( FinalOnionHopData {
26032619 payment_secret,
2620+ payment_metadata : None ,
26042621 total_msat : 0x1badca1f
26052622 } ) ,
26062623 keysend_preimage : None ,
0 commit comments