@@ -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
@@ -904,6 +904,7 @@ mod fuzzy_internal_msgs {
904
904
#[ derive( Clone ) ]
905
905
pub ( crate ) struct FinalOnionHopData {
906
906
pub ( crate ) payment_secret : PaymentSecret ,
907
+ pub ( crate ) payment_metadata : Option < Vec < u8 > > ,
907
908
/// The total value, in msat, of the payment as received by the ultimate recipient.
908
909
/// Message serialization may panic if this value is more than 21 million Bitcoin.
909
910
pub ( crate ) total_msat : u64 ,
@@ -1274,6 +1275,11 @@ impl_writeable_msg!(UpdateAddHTLC, {
1274
1275
onion_routing_packet
1275
1276
} , { } ) ;
1276
1277
1278
+ // The serialization here is really funky - FinalOnionHopData somewhat serves as two different
1279
+ // things. First, it is *the* object which is written with type 8 in the onion TLV. Second, it is
1280
+ // the data which a node may expect to receive when we are the recipient of an invoice payment.
1281
+ // Thus, its serialization doesn't match its in-memory layout - with the payment_metadata included
1282
+ // in the struct, but serialized separately.
1277
1283
impl Writeable for FinalOnionHopData {
1278
1284
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1279
1285
self . payment_secret . 0 . write ( w) ?;
@@ -1285,7 +1291,7 @@ impl Readable for FinalOnionHopData {
1285
1291
fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1286
1292
let secret: [ u8 ; 32 ] = Readable :: read ( r) ?;
1287
1293
let amt: HighZeroBytesDroppedVarInt < u64 > = Readable :: read ( r) ?;
1288
- Ok ( Self { payment_secret : PaymentSecret ( secret) , total_msat : amt. 0 } )
1294
+ Ok ( Self { payment_secret : PaymentSecret ( secret) , total_msat : amt. 0 , payment_metadata : None , } )
1289
1295
}
1290
1296
}
1291
1297
@@ -1314,10 +1320,15 @@ impl Writeable for OnionHopData {
1314
1320
if let Some ( final_data) = payment_data {
1315
1321
if final_data. total_msat > MAX_VALUE_MSAT { panic ! ( "We should never be sending infinite/overflow onion payments" ) ; }
1316
1322
}
1323
+ let payment_metadata = if let Some ( data) = payment_data {
1324
+ if let Some ( ref metadata) = data. payment_metadata { Some ( VecWriteWrapper ( metadata) )
1325
+ } else { None }
1326
+ } else { None } ;
1317
1327
encode_varint_length_prefixed_tlv ! ( w, {
1318
1328
( 2 , HighZeroBytesDroppedVarInt ( self . amt_to_forward) , required) ,
1319
1329
( 4 , HighZeroBytesDroppedVarInt ( self . outgoing_cltv_value) , required) ,
1320
1330
( 8 , payment_data, option) ,
1331
+ ( 16 , payment_metadata, option) ,
1321
1332
( 5482373484 , keysend_preimage, option)
1322
1333
} ) ;
1323
1334
} ,
@@ -1341,26 +1352,30 @@ impl Readable for OnionHopData {
1341
1352
let mut cltv_value = HighZeroBytesDroppedVarInt ( 0u32 ) ;
1342
1353
let mut short_id: Option < u64 > = None ;
1343
1354
let mut payment_data: Option < FinalOnionHopData > = None ;
1355
+ let mut payment_metadata: Option < VecReadWrapper < u8 > > = None ;
1344
1356
let mut keysend_preimage: Option < PaymentPreimage > = None ;
1345
1357
// The TLV type is chosen to be compatible with lnd and c-lightning.
1346
1358
decode_tlv_stream ! ( & mut rd, {
1347
1359
( 2 , amt, required) ,
1348
1360
( 4 , cltv_value, required) ,
1349
1361
( 6 , short_id, option) ,
1350
1362
( 8 , payment_data, option) ,
1363
+ ( 16 , payment_metadata, option) ,
1351
1364
( 5482373484 , keysend_preimage, option)
1352
1365
} ) ;
1353
1366
rd. eat_remaining ( ) . map_err ( |_| DecodeError :: ShortRead ) ?;
1354
1367
let format = if let Some ( short_channel_id) = short_id {
1355
1368
if payment_data. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1369
+ if payment_metadata. is_some ( ) { return Err ( DecodeError :: InvalidValue ) ; }
1356
1370
OnionHopDataFormat :: NonFinalNode {
1357
1371
short_channel_id,
1358
1372
}
1359
1373
} else {
1360
- if let & Some ( ref data) = & payment_data {
1374
+ if let Some ( ref mut data) = & mut payment_data {
1361
1375
if data. total_msat > MAX_VALUE_MSAT {
1362
1376
return Err ( DecodeError :: InvalidValue ) ;
1363
1377
}
1378
+ data. payment_metadata = payment_metadata. map ( |v| v. 0 ) ;
1364
1379
}
1365
1380
OnionHopDataFormat :: FinalNode {
1366
1381
payment_data,
@@ -2551,6 +2566,7 @@ mod tests {
2551
2566
format : OnionHopDataFormat :: FinalNode {
2552
2567
payment_data : Some ( FinalOnionHopData {
2553
2568
payment_secret : expected_payment_secret,
2569
+ payment_metadata : None ,
2554
2570
total_msat : 0x1badca1f
2555
2571
} ) ,
2556
2572
keysend_preimage : None ,
@@ -2565,6 +2581,7 @@ mod tests {
2565
2581
if let OnionHopDataFormat :: FinalNode {
2566
2582
payment_data : Some ( FinalOnionHopData {
2567
2583
payment_secret,
2584
+ payment_metadata : None ,
2568
2585
total_msat : 0x1badca1f
2569
2586
} ) ,
2570
2587
keysend_preimage : None ,
0 commit comments