@@ -1431,6 +1431,19 @@ pub(crate) enum Hop {
1431
1431
/// Bytes of the onion packet we're forwarding.
1432
1432
new_packet_bytes : [ u8 ; ONION_DATA_LEN ] ,
1433
1433
} ,
1434
+ /// This onion was received via Trampoline, and needs to be forwarded to a subsequent Trampoline
1435
+ /// node.
1436
+ #[ cfg( trampoline) ]
1437
+ TrampolineForward {
1438
+ #[ allow( unused) ]
1439
+ outer_hop_data : msgs:: InboundTrampolineEntrypointPayload ,
1440
+ outer_shared_secret : SharedSecret ,
1441
+ incoming_trampoline_public_key : PublicKey ,
1442
+ trampoline_shared_secret : SharedSecret ,
1443
+ next_trampoline_hop_data : msgs:: InboundTrampolineForwardPayload ,
1444
+ next_trampoline_hop_hmac : [ u8 ; 32 ] ,
1445
+ new_trampoline_packet_bytes : Vec < u8 > ,
1446
+ } ,
1434
1447
/// This onion payload needs to be forwarded to a next-hop.
1435
1448
BlindedForward {
1436
1449
/// Onion payload data used in forwarding the payment.
@@ -1458,6 +1471,16 @@ pub(crate) enum Hop {
1458
1471
/// Shared secret that was used to decrypt hop_data.
1459
1472
shared_secret : SharedSecret ,
1460
1473
} ,
1474
+ /// This onion payload was for us, not for forwarding to a next-hop, and it was sent to us via
1475
+ /// Trampoline. Contains information for verifying the incoming payment.
1476
+ #[ allow( unused) ]
1477
+ #[ cfg( trampoline) ]
1478
+ TrampolineReceive {
1479
+ outer_hop_data : msgs:: InboundTrampolineEntrypointPayload ,
1480
+ outer_shared_secret : SharedSecret ,
1481
+ trampoline_hop_data : msgs:: InboundOnionReceivePayload ,
1482
+ trampoline_shared_secret : SharedSecret ,
1483
+ } ,
1461
1484
}
1462
1485
1463
1486
impl Hop {
@@ -1478,8 +1501,12 @@ impl Hop {
1478
1501
match self {
1479
1502
Hop :: Forward { shared_secret, .. } => shared_secret,
1480
1503
Hop :: BlindedForward { shared_secret, .. } => shared_secret,
1504
+ #[ cfg( trampoline) ]
1505
+ Hop :: TrampolineForward { outer_shared_secret, .. } => outer_shared_secret,
1481
1506
Hop :: Receive { shared_secret, .. } => shared_secret,
1482
1507
Hop :: BlindedReceive { shared_secret, .. } => shared_secret,
1508
+ #[ cfg( trampoline) ]
1509
+ Hop :: TrampolineReceive { outer_shared_secret, .. } => outer_shared_secret,
1483
1510
}
1484
1511
}
1485
1512
}
@@ -1490,7 +1517,15 @@ pub(crate) enum OnionDecodeErr {
1490
1517
/// The HMAC of the onion packet did not match the hop data.
1491
1518
Malformed { err_msg : & ' static str , err_code : u16 } ,
1492
1519
/// We failed to decode the onion payload.
1493
- Relay { err_msg : & ' static str , err_code : u16 , shared_secret : SharedSecret } ,
1520
+ ///
1521
+ /// If the payload we failed to decode belonged to a Trampoline onion, following the successful
1522
+ /// decoding of the outer onion, the trampoline_shared_secret field should be set.
1523
+ Relay {
1524
+ err_msg : & ' static str ,
1525
+ err_code : u16 ,
1526
+ shared_secret : SharedSecret ,
1527
+ trampoline_shared_secret : Option < SharedSecret > ,
1528
+ } ,
1494
1529
}
1495
1530
1496
1531
pub ( crate ) fn decode_next_payment_hop < NS : Deref > (
@@ -1514,7 +1549,7 @@ where
1514
1549
hop_data,
1515
1550
hmac_bytes,
1516
1551
Some ( payment_hash) ,
1517
- ( blinding_point, node_signer) ,
1552
+ ( blinding_point, & ( * node_signer) ) ,
1518
1553
) ;
1519
1554
match decoded_hop {
1520
1555
Ok ( ( next_hop_data, Some ( ( next_hop_hmac, FixedSizeOnionPacket ( new_packet_bytes) ) ) ) ) => {
@@ -1545,6 +1580,7 @@ where
1545
1580
err_msg : "Final Node OnionHopData provided for us as an intermediary node" ,
1546
1581
err_code : 0x4000 | 22 ,
1547
1582
shared_secret,
1583
+ trampoline_shared_secret : None ,
1548
1584
} )
1549
1585
} ,
1550
1586
}
@@ -1556,6 +1592,75 @@ where
1556
1592
msgs:: InboundOnionPayload :: BlindedReceive ( hop_data) => {
1557
1593
Ok ( Hop :: BlindedReceive { shared_secret, hop_data } )
1558
1594
} ,
1595
+ #[ cfg( trampoline) ]
1596
+ msgs:: InboundOnionPayload :: TrampolineEntrypoint ( hop_data) => {
1597
+ let incoming_trampoline_public_key = hop_data. trampoline_packet . public_key ;
1598
+ let trampoline_shared_secret = node_signer
1599
+ . ecdh (
1600
+ recipient,
1601
+ & incoming_trampoline_public_key,
1602
+ blinded_node_id_tweak. as_ref ( ) ,
1603
+ )
1604
+ . unwrap ( )
1605
+ . secret_bytes ( ) ;
1606
+ let decoded_trampoline_hop: Result <
1607
+ ( msgs:: InboundOnionPayload , Option < ( [ u8 ; 32 ] , Vec < u8 > ) > ) ,
1608
+ _ ,
1609
+ > = decode_next_hop (
1610
+ trampoline_shared_secret,
1611
+ & hop_data. trampoline_packet . hop_data ,
1612
+ hop_data. trampoline_packet . hmac ,
1613
+ Some ( payment_hash) ,
1614
+ ( blinding_point, node_signer) ,
1615
+ ) ;
1616
+ match decoded_trampoline_hop {
1617
+ Ok ( (
1618
+ next_trampoline_hop_data,
1619
+ Some ( ( next_trampoline_hop_hmac, new_trampoline_packet_bytes) ) ,
1620
+ ) ) => {
1621
+ match next_trampoline_hop_data {
1622
+ msgs:: InboundOnionPayload :: TrampolineForward ( trampoline_hop_data) => {
1623
+ Ok ( Hop :: TrampolineForward {
1624
+ outer_hop_data : hop_data,
1625
+ outer_shared_secret : shared_secret,
1626
+ incoming_trampoline_public_key,
1627
+ trampoline_shared_secret : SharedSecret :: from_bytes (
1628
+ trampoline_shared_secret,
1629
+ ) ,
1630
+ next_trampoline_hop_data : trampoline_hop_data,
1631
+ next_trampoline_hop_hmac,
1632
+ new_trampoline_packet_bytes,
1633
+ } )
1634
+ } ,
1635
+ _ => Err ( OnionDecodeErr :: Malformed {
1636
+ err_msg : "Non-Trampoline onion data provided to us as inner onion" ,
1637
+ // todo: find more suitable error code
1638
+ err_code : 0x4000 | 22 ,
1639
+ } ) ,
1640
+ }
1641
+ } ,
1642
+ Ok ( ( trampoline_hop_data, None ) ) => {
1643
+ match trampoline_hop_data {
1644
+ msgs:: InboundOnionPayload :: Receive ( trampoline_hop_data) => {
1645
+ Ok ( Hop :: TrampolineReceive {
1646
+ outer_hop_data : hop_data,
1647
+ outer_shared_secret : shared_secret,
1648
+ trampoline_hop_data,
1649
+ trampoline_shared_secret : SharedSecret :: from_bytes (
1650
+ trampoline_shared_secret,
1651
+ ) ,
1652
+ } )
1653
+ } ,
1654
+ _ => Err ( OnionDecodeErr :: Malformed {
1655
+ err_msg : "Non-Trampoline onion data provided to us as inner onion" ,
1656
+ // todo: find more suitable error code
1657
+ err_code : 0x4000 | 22 ,
1658
+ } ) ,
1659
+ }
1660
+ } ,
1661
+ Err ( e) => Err ( e) ,
1662
+ }
1663
+ } ,
1559
1664
_ => {
1560
1665
if blinding_point. is_some ( ) {
1561
1666
return Err ( OnionDecodeErr :: Malformed {
@@ -1567,6 +1672,7 @@ where
1567
1672
err_msg : "Intermediate Node OnionHopData provided for us as a final node" ,
1568
1673
err_code : 0x4000 | 22 ,
1569
1674
shared_secret,
1675
+ trampoline_shared_secret : None ,
1570
1676
} )
1571
1677
} ,
1572
1678
} ,
@@ -1715,6 +1821,7 @@ fn decode_next_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(
1715
1821
err_msg : "Unable to decode our hop data" ,
1716
1822
err_code : error_code,
1717
1823
shared_secret : SharedSecret :: from_bytes ( shared_secret) ,
1824
+ trampoline_shared_secret : None ,
1718
1825
} ) ;
1719
1826
} ,
1720
1827
Ok ( msg) => {
@@ -1724,6 +1831,7 @@ fn decode_next_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(
1724
1831
err_msg : "Unable to decode our hop data" ,
1725
1832
err_code : 0x4000 | 22 ,
1726
1833
shared_secret : SharedSecret :: from_bytes ( shared_secret) ,
1834
+ trampoline_shared_secret : None ,
1727
1835
} ) ;
1728
1836
}
1729
1837
if hmac == [ 0 ; 32 ] {
0 commit comments