@@ -13,7 +13,7 @@ use crate::ln::msgs;
13
13
use crate :: ln:: wire:: Encode ;
14
14
use crate :: routing:: gossip:: NetworkUpdate ;
15
15
use crate :: routing:: router:: { BlindedTail , Path , RouteHop } ;
16
- use crate :: sign:: NodeSigner ;
16
+ use crate :: sign:: { NodeSigner , Recipient } ;
17
17
use crate :: util:: chacha20:: { ChaCha20 , ChaChaReader } ;
18
18
use crate :: util:: errors:: { self , APIError } ;
19
19
use crate :: util:: ser:: { Readable , ReadableArgs , Writeable , Writer , LengthCalculatingWriter } ;
@@ -1044,12 +1044,20 @@ pub enum PeeledPayment {
1044
1044
/// Unwrap one layer of an incoming HTLC, returning either or a received payment, or a another
1045
1045
/// onion to forward.
1046
1046
pub fn peel_payment_onion < NS : Deref > (
1047
- shared_secret : [ u8 ; 32 ] , onion : & msgs:: OnionPacket , payment_hash : PaymentHash ,
1048
- node_signer : & NS , secp_ctx : & Secp256k1 < secp256k1:: All >
1047
+ onion : & msgs:: OnionPacket , payment_hash : PaymentHash , node_signer : & NS ,
1048
+ secp_ctx : & Secp256k1 < secp256k1:: All >
1049
1049
) -> Result < PeeledPayment , ( ) >
1050
1050
where
1051
1051
NS :: Target : NodeSigner ,
1052
1052
{
1053
+ if onion. public_key . is_err ( ) {
1054
+ return Err ( ( ) ) ;
1055
+ }
1056
+ let shared_secret = node_signer
1057
+ . ecdh ( Recipient :: Node , & onion. public_key . unwrap ( ) , None )
1058
+ . unwrap ( )
1059
+ . secret_bytes ( ) ;
1060
+
1053
1061
let hop = decode_next_payment_hop ( shared_secret, & onion. hop_data [ ..] , onion. hmac , payment_hash, node_signer) . map_err ( |_| ( ) ) ?;
1054
1062
let peeled = match hop {
1055
1063
Hop :: Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
@@ -1381,4 +1389,103 @@ mod tests {
1381
1389
writer. write_all ( & self . data [ ..] )
1382
1390
}
1383
1391
}
1392
+
1393
+ #[ test]
1394
+ fn create_and_peel_payment_onion ( ) {
1395
+ use crate :: ln:: channelmanager:: RecipientOnionFields ;
1396
+ use crate :: ln:: PaymentPreimage ;
1397
+ use std:: convert:: TryInto ;
1398
+ use super :: { create_payment_onion, peel_payment_onion} ;
1399
+ use super :: { Sha256 , Hash , PeeledPayment , ReceivedPayment } ;
1400
+
1401
+ let secp_ctx = Secp256k1 :: new ( ) ;
1402
+ let recipient_onion = RecipientOnionFields :: spontaneous_empty ( ) ;
1403
+ let session_priv_bytes = [ 42 ; 32 ] ;
1404
+ let session_priv = SecretKey :: from_slice ( & session_priv_bytes) . unwrap ( ) ;
1405
+ let amt_msat = 1000 ;
1406
+ let cur_height = 1000 ;
1407
+ let preimage_bytes = [ 43 ; 32 ] ;
1408
+ let preimage = PaymentPreimage ( preimage_bytes) ;
1409
+ let rhash = Sha256 :: hash ( & preimage_bytes) . to_vec ( ) ;
1410
+ let rhash_bytes: [ u8 ; 32 ] = rhash. try_into ( ) . unwrap ( ) ;
1411
+ let payment_hash = PaymentHash ( rhash_bytes) ;
1412
+ let prng_seed = [ 44 ; 32 ] ;
1413
+
1414
+ // let alice = make_keys_manager(&[1; 32]);
1415
+ let bob = make_keys_manager ( & [ 2 ; 32 ] ) ;
1416
+ let bob_pk = PublicKey :: from_secret_key ( & secp_ctx, & bob. get_node_secret_key ( ) ) ;
1417
+ let charlie = make_keys_manager ( & [ 3 ; 32 ] ) ;
1418
+ let charlie_pk = PublicKey :: from_secret_key ( & secp_ctx, & charlie. get_node_secret_key ( ) ) ;
1419
+
1420
+ // make a route alice -> bob -> charlie
1421
+ let bob_fee = 1 ;
1422
+ let recipient_amount = 999 ;
1423
+ let hops = vec ! [
1424
+ RouteHop {
1425
+ pubkey: bob_pk,
1426
+ fee_msat: bob_fee,
1427
+ cltv_expiry_delta: 0 ,
1428
+ short_channel_id: 1 ,
1429
+ node_features: NodeFeatures :: empty( ) ,
1430
+ channel_features: ChannelFeatures :: empty( ) ,
1431
+ maybe_announced_channel: false ,
1432
+ } ,
1433
+ RouteHop {
1434
+ pubkey: charlie_pk,
1435
+ fee_msat: recipient_amount,
1436
+ cltv_expiry_delta: 0 ,
1437
+ short_channel_id: 2 ,
1438
+ node_features: NodeFeatures :: empty( ) ,
1439
+ channel_features: ChannelFeatures :: empty( ) ,
1440
+ maybe_announced_channel: false ,
1441
+ }
1442
+ ] ;
1443
+ let path = Path {
1444
+ hops : hops,
1445
+ blinded_tail : None ,
1446
+ } ;
1447
+
1448
+ let ( _htlc_msat, _htlc_cltv, onion) = create_payment_onion (
1449
+ & secp_ctx, & path, & session_priv, amt_msat, recipient_onion, cur_height, payment_hash,
1450
+ Some ( preimage) , prng_seed
1451
+ ) . unwrap ( ) ;
1452
+
1453
+ // bob peels to find another onion
1454
+ let next_onion = match peel_payment_onion ( & onion, payment_hash, & & bob, & secp_ctx) . unwrap ( ) {
1455
+ PeeledPayment :: Receive ( _) => {
1456
+ panic ! ( "should not be a receive" ) ;
1457
+ } ,
1458
+ PeeledPayment :: Forward ( forwarded) => {
1459
+ forwarded. onion_packet
1460
+ } ,
1461
+ } ;
1462
+
1463
+ // charlie peels to find a received payment
1464
+ match peel_payment_onion ( & next_onion, payment_hash, & & charlie, & secp_ctx) . unwrap ( ) {
1465
+ PeeledPayment :: Receive ( received) => match received {
1466
+ ReceivedPayment :: Regular { amt_msat, keysend_preimage, ..} => {
1467
+ assert_eq ! ( amt_msat, recipient_amount, "wrong received amount" ) ;
1468
+ assert_eq ! ( Some ( preimage_bytes) , keysend_preimage, "wrong received preimage" ) ;
1469
+ } ,
1470
+ ReceivedPayment :: Blinded { ..} => {
1471
+ panic ! ( "should not be blinded" ) ;
1472
+ }
1473
+ } ,
1474
+ PeeledPayment :: Forward ( _) => {
1475
+ panic ! ( "should not be a receive" ) ;
1476
+ } ,
1477
+ } ;
1478
+
1479
+ }
1480
+
1481
+ fn make_keys_manager ( seed : & [ u8 ; 32 ] ) -> crate :: sign:: KeysManager {
1482
+ use crate :: sign:: KeysManager ;
1483
+ use std:: time:: { SystemTime , UNIX_EPOCH } ;
1484
+ let start = SystemTime :: now ( ) ;
1485
+ let now = start
1486
+ . duration_since ( UNIX_EPOCH )
1487
+ . expect ( "Time went backwards" ) ;
1488
+ KeysManager :: new ( seed, now. as_secs ( ) , now. subsec_nanos ( ) )
1489
+ }
1490
+
1384
1491
}
0 commit comments