@@ -40,7 +40,7 @@ use io_extras::read_to_end;
40
40
41
41
use util:: events:: MessageSendEventsProvider ;
42
42
use util:: logger;
43
- use util:: ser:: { Readable , Writeable , Writer , FixedLengthReader , HighZeroBytesDroppedVarInt } ;
43
+ use util:: ser:: { Readable , Writeable , Writer , VecWriteWrapper , VecReadWrapper , FixedLengthReader , HighZeroBytesDroppedVarInt } ;
44
44
45
45
use ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
46
46
@@ -878,6 +878,7 @@ mod fuzzy_internal_msgs {
878
878
#[ derive( Clone ) ]
879
879
pub ( crate ) struct FinalOnionHopData {
880
880
pub ( crate ) payment_secret : PaymentSecret ,
881
+ pub ( crate ) payment_metadata : Option < Vec < u8 > > ,
881
882
/// The total value, in msat, of the payment as received by the ultimate recipient.
882
883
/// Message serialization may panic if this value is more than 21 million Bitcoin.
883
884
pub ( crate ) total_msat : u64 ,
@@ -1248,6 +1249,11 @@ impl_writeable_msg!(UpdateAddHTLC, {
1248
1249
onion_routing_packet
1249
1250
} , { } ) ;
1250
1251
1252
+ // The serialization here is really funky - FinalOnionHopData somewhat serves as two different
1253
+ // things. First, it is *the* object which is written with type 8 in the onion TLV. Second, it is
1254
+ // the data which a node may expect to receive when we are the recipient of an invoice payment.
1255
+ // Thus, its serialization doesn't match its in-memory layout - with the payment_metadata included
1256
+ // in the struct, but serialized separately.
1251
1257
impl Writeable for FinalOnionHopData {
1252
1258
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1253
1259
self . payment_secret . 0 . write ( w) ?;
@@ -1259,7 +1265,7 @@ impl Readable for FinalOnionHopData {
1259
1265
fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1260
1266
let secret: [ u8 ; 32 ] = Readable :: read ( r) ?;
1261
1267
let amt: HighZeroBytesDroppedVarInt < u64 > = Readable :: read ( r) ?;
1262
- Ok ( Self { payment_secret : PaymentSecret ( secret) , total_msat : amt. 0 } )
1268
+ Ok ( Self { payment_secret : PaymentSecret ( secret) , total_msat : amt. 0 , payment_metadata : None , } )
1263
1269
}
1264
1270
}
1265
1271
@@ -1288,10 +1294,15 @@ impl Writeable for OnionHopData {
1288
1294
if let Some ( final_data) = payment_data {
1289
1295
if final_data. total_msat > MAX_VALUE_MSAT { panic ! ( "We should never be sending infinite/overflow onion payments" ) ; }
1290
1296
}
1297
+ let payment_metadata = if let Some ( data) = payment_data {
1298
+ if let Some ( ref metadata) = data. payment_metadata { Some ( VecWriteWrapper ( metadata) )
1299
+ } else { None }
1300
+ } else { None } ;
1291
1301
encode_varint_length_prefixed_tlv ! ( w, {
1292
1302
( 2 , HighZeroBytesDroppedVarInt ( self . amt_to_forward) , required) ,
1293
1303
( 4 , HighZeroBytesDroppedVarInt ( self . outgoing_cltv_value) , required) ,
1294
1304
( 8 , payment_data, option) ,
1305
+ ( 16 , payment_metadata, option) ,
1295
1306
( 5482373484 , keysend_preimage, option)
1296
1307
} ) ;
1297
1308
} ,
@@ -1315,26 +1326,30 @@ impl Readable for OnionHopData {
1315
1326
let mut cltv_value = HighZeroBytesDroppedVarInt ( 0u32 ) ;
1316
1327
let mut short_id: Option < u64 > = None ;
1317
1328
let mut payment_data: Option < FinalOnionHopData > = None ;
1329
+ let mut payment_metadata: Option < VecReadWrapper < u8 > > = None ;
1318
1330
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1319
1331
// The TLV type is chosen to be compatible with lnd and c-lightning.
1320
1332
decode_tlv_stream ! ( & mut rd, {
1321
1333
( 2 , amt, required) ,
1322
1334
( 4 , cltv_value, required) ,
1323
1335
( 6 , short_id, option) ,
1324
1336
( 8 , payment_data, option) ,
1337
+ ( 16 , payment_metadata, option) ,
1325
1338
( 5482373484 , keysend_preimage, option)
1326
1339
} ) ;
1327
1340
rd. eat_remaining ( ) . map_err ( |_| DecodeError :: ShortRead ) ?;
1328
1341
let format = if let Some ( short_channel_id) = short_id {
1329
1342
if payment_data. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1343
+ if payment_metadata. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1330
1344
OnionHopDataFormat :: NonFinalNode {
1331
1345
short_channel_id,
1332
1346
}
1333
1347
} else {
1334
- if let & Some ( ref data) = & payment_data {
1348
+ if let Some ( ref mut data) = & mut payment_data {
1335
1349
if data. total_msat > MAX_VALUE_MSAT {
1336
1350
return Err ( DecodeError :: InvalidValue ) ;
1337
1351
}
1352
+ data. payment_metadata = payment_metadata. map ( |v| v. 0 ) ;
1338
1353
}
1339
1354
OnionHopDataFormat :: FinalNode {
1340
1355
payment_data,
@@ -2486,6 +2501,7 @@ mod tests {
2486
2501
format : OnionHopDataFormat :: FinalNode {
2487
2502
payment_data : Some ( FinalOnionHopData {
2488
2503
payment_secret : expected_payment_secret,
2504
+ payment_metadata : None ,
2489
2505
total_msat : 0x1badca1f
2490
2506
} ) ,
2491
2507
keysend_preimage : None ,
@@ -2500,6 +2516,7 @@ mod tests {
2500
2516
if let OnionHopDataFormat :: FinalNode {
2501
2517
payment_data : Some ( FinalOnionHopData {
2502
2518
payment_secret,
2519
+ payment_metadata : None ,
2503
2520
total_msat : 0x1badca1f
2504
2521
} ) ,
2505
2522
keysend_preimage : None ,
0 commit comments