@@ -1431,6 +1431,19 @@ pub(crate) enum Hop {
14311431 /// Bytes of the onion packet we're forwarding.
14321432 new_packet_bytes : [ u8 ; ONION_DATA_LEN ] ,
14331433 } ,
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+ } ,
14341447 /// This onion payload needs to be forwarded to a next-hop.
14351448 BlindedForward {
14361449 /// Onion payload data used in forwarding the payment.
@@ -1458,6 +1471,16 @@ pub(crate) enum Hop {
14581471 /// Shared secret that was used to decrypt hop_data.
14591472 shared_secret : SharedSecret ,
14601473 } ,
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+ } ,
14611484}
14621485
14631486impl Hop {
@@ -1478,8 +1501,12 @@ impl Hop {
14781501 match self {
14791502 Hop :: Forward { shared_secret, .. } => shared_secret,
14801503 Hop :: BlindedForward { shared_secret, .. } => shared_secret,
1504+ #[ cfg( trampoline) ]
1505+ Hop :: TrampolineForward { outer_shared_secret, .. } => outer_shared_secret,
14811506 Hop :: Receive { shared_secret, .. } => shared_secret,
14821507 Hop :: BlindedReceive { shared_secret, .. } => shared_secret,
1508+ #[ cfg( trampoline) ]
1509+ Hop :: TrampolineReceive { outer_shared_secret, .. } => outer_shared_secret,
14831510 }
14841511 }
14851512}
@@ -1490,7 +1517,15 @@ pub(crate) enum OnionDecodeErr {
14901517 /// The HMAC of the onion packet did not match the hop data.
14911518 Malformed { err_msg : & ' static str , err_code : u16 } ,
14921519 /// 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+ } ,
14941529}
14951530
14961531pub ( crate ) fn decode_next_payment_hop < NS : Deref > (
@@ -1514,7 +1549,7 @@ where
15141549 hop_data,
15151550 hmac_bytes,
15161551 Some ( payment_hash) ,
1517- ( blinding_point, node_signer) ,
1552+ ( blinding_point, & ( * node_signer) ) ,
15181553 ) ;
15191554 match decoded_hop {
15201555 Ok ( ( next_hop_data, Some ( ( next_hop_hmac, FixedSizeOnionPacket ( new_packet_bytes) ) ) ) ) => {
@@ -1545,6 +1580,7 @@ where
15451580 err_msg : "Final Node OnionHopData provided for us as an intermediary node" ,
15461581 err_code : 0x4000 | 22 ,
15471582 shared_secret,
1583+ trampoline_shared_secret : None ,
15481584 } )
15491585 } ,
15501586 }
@@ -1556,6 +1592,75 @@ where
15561592 msgs:: InboundOnionPayload :: BlindedReceive ( hop_data) => {
15571593 Ok ( Hop :: BlindedReceive { shared_secret, hop_data } )
15581594 } ,
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+ } ,
15591664 _ => {
15601665 if blinding_point. is_some ( ) {
15611666 return Err ( OnionDecodeErr :: Malformed {
@@ -1567,6 +1672,7 @@ where
15671672 err_msg : "Intermediate Node OnionHopData provided for us as a final node" ,
15681673 err_code : 0x4000 | 22 ,
15691674 shared_secret,
1675+ trampoline_shared_secret : None ,
15701676 } )
15711677 } ,
15721678 } ,
@@ -1715,6 +1821,7 @@ fn decode_next_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(
17151821 err_msg : "Unable to decode our hop data" ,
17161822 err_code : error_code,
17171823 shared_secret : SharedSecret :: from_bytes ( shared_secret) ,
1824+ trampoline_shared_secret : None ,
17181825 } ) ;
17191826 } ,
17201827 Ok ( msg) => {
@@ -1724,6 +1831,7 @@ fn decode_next_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(
17241831 err_msg : "Unable to decode our hop data" ,
17251832 err_code : 0x4000 | 22 ,
17261833 shared_secret : SharedSecret :: from_bytes ( shared_secret) ,
1834+ trampoline_shared_secret : None ,
17271835 } ) ;
17281836 }
17291837 if hmac == [ 0 ; 32 ] {
0 commit comments