@@ -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
@@ -918,6 +918,7 @@ mod fuzzy_internal_msgs {
918
918
#[ derive( Clone ) ]
919
919
pub ( crate ) struct FinalOnionHopData {
920
920
pub ( crate ) payment_secret : PaymentSecret ,
921
+ pub ( crate ) payment_metadata : Option < Vec < u8 > > ,
921
922
/// The total value, in msat, of the payment as received by the ultimate recipient.
922
923
/// Message serialization may panic if this value is more than 21 million Bitcoin.
923
924
pub ( crate ) total_msat : u64 ,
@@ -1301,6 +1302,11 @@ impl_writeable_msg!(UpdateAddHTLC, {
1301
1302
onion_routing_packet
1302
1303
} , { } ) ;
1303
1304
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.
1304
1310
impl Writeable for FinalOnionHopData {
1305
1311
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1306
1312
self . payment_secret . 0 . write ( w) ?;
@@ -1312,7 +1318,7 @@ impl Readable for FinalOnionHopData {
1312
1318
fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1313
1319
let secret: [ u8 ; 32 ] = Readable :: read ( r) ?;
1314
1320
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 , } )
1316
1322
}
1317
1323
}
1318
1324
@@ -1334,10 +1340,15 @@ impl Writeable for OnionHopData {
1334
1340
} ) ;
1335
1341
} ,
1336
1342
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 } ;
1337
1347
encode_varint_length_prefixed_tlv ! ( w, {
1338
1348
( 2 , HighZeroBytesDroppedVarInt ( self . amt_to_forward) , required) ,
1339
1349
( 4 , HighZeroBytesDroppedVarInt ( self . outgoing_cltv_value) , required) ,
1340
1350
( 8 , payment_data, option) ,
1351
+ ( 16 , payment_metadata, option) ,
1341
1352
( 5482373484 , keysend_preimage, option)
1342
1353
} ) ;
1343
1354
} ,
@@ -1361,26 +1372,30 @@ impl Readable for OnionHopData {
1361
1372
let mut cltv_value = HighZeroBytesDroppedVarInt ( 0u32 ) ;
1362
1373
let mut short_id: Option < u64 > = None ;
1363
1374
let mut payment_data: Option < FinalOnionHopData > = None ;
1375
+ let mut payment_metadata: Option < VecReadWrapper < u8 > > = None ;
1364
1376
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1365
1377
// The TLV type is chosen to be compatible with lnd and c-lightning.
1366
1378
decode_tlv_stream ! ( & mut rd, {
1367
1379
( 2 , amt, required) ,
1368
1380
( 4 , cltv_value, required) ,
1369
1381
( 6 , short_id, option) ,
1370
1382
( 8 , payment_data, option) ,
1383
+ ( 16 , payment_metadata, option) ,
1371
1384
( 5482373484 , keysend_preimage, option)
1372
1385
} ) ;
1373
1386
rd. eat_remaining ( ) . map_err ( |_| DecodeError :: ShortRead ) ?;
1374
1387
let format = if let Some ( short_channel_id) = short_id {
1375
1388
if payment_data. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1389
+ if payment_metadata. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1376
1390
OnionHopDataFormat :: NonFinalNode {
1377
1391
short_channel_id,
1378
1392
}
1379
1393
} else {
1380
- if let & Some ( ref data) = & payment_data {
1394
+ if let Some ( ref mut data) = & mut payment_data {
1381
1395
if data. total_msat > MAX_VALUE_MSAT {
1382
1396
return Err ( DecodeError :: InvalidValue ) ;
1383
1397
}
1398
+ data. payment_metadata = payment_metadata. map ( |v| v. 0 ) ;
1384
1399
}
1385
1400
OnionHopDataFormat :: FinalNode {
1386
1401
payment_data,
@@ -2587,6 +2602,7 @@ mod tests {
2587
2602
format : OnionHopDataFormat :: FinalNode {
2588
2603
payment_data : Some ( FinalOnionHopData {
2589
2604
payment_secret : expected_payment_secret,
2605
+ payment_metadata : None ,
2590
2606
total_msat : 0x1badca1f
2591
2607
} ) ,
2592
2608
keysend_preimage : None ,
@@ -2601,6 +2617,7 @@ mod tests {
2601
2617
if let OnionHopDataFormat :: FinalNode {
2602
2618
payment_data : Some ( FinalOnionHopData {
2603
2619
payment_secret,
2620
+ payment_metadata : None ,
2604
2621
total_msat : 0x1badca1f
2605
2622
} ) ,
2606
2623
keysend_preimage : None ,
0 commit comments