public create_payment_onion in onion_utils
authorEvan Feenstra <evanfeenstra@gmail.com>
Sat, 28 Oct 2023 22:10:00 +0000 (15:10 -0700)
committerEvan Feenstra <evanfeenstra@gmail.com>
Mon, 6 Nov 2023 18:41:35 +0000 (10:41 -0800)
lightning/src/ln/channelmanager.rs
lightning/src/ln/mod.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_utils.rs

index c4efd895796e67d1f3c1ecc46e5559b277c5cc9b..9f86095d647e522d876628768b7f3b4ac6bd08f1 100644 (file)
@@ -3420,12 +3420,10 @@ where
                let prng_seed = self.entropy_source.get_secure_random_bytes();
                let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted");
 
-               let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv)
-                       .map_err(|_| APIError::InvalidRoute{err: "Pubkey along hop was maliciously selected".to_owned()})?;
-               let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, recipient_onion, cur_height, keysend_preimage)?;
-
-               let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, prng_seed, payment_hash)
-                       .map_err(|_| APIError::InvalidRoute { err: "Route size too large considering onion data".to_owned()})?;
+               let (onion_packet, htlc_msat, htlc_cltv) = onion_utils::create_payment_onion(
+                       &self.secp_ctx, &path, &session_priv, total_value, recipient_onion, cur_height,
+                       payment_hash, keysend_preimage, prng_seed
+               )?;
 
                let err: Result<(), _> = loop {
                        let (counterparty_node_id, id) = match self.short_to_chan_info.read().unwrap().get(&path.hops.first().unwrap().short_channel_id) {
index beefd2d463b3ed2b938c6f82fdabef63757adccd..041c196f637c51ad91d9d46bf86739d468e6c270 100644 (file)
@@ -39,6 +39,7 @@ pub(crate) mod onion_utils;
 mod outbound_payment;
 pub mod wire;
 
+pub use onion_utils::create_payment_onion;
 // Older rustc (which we support) refuses to let us call the get_payment_preimage_hash!() macro
 // without the node parameter being mut. This is incorrect, and thus newer rustcs will complain
 // about an unnecessary mut. Thus, we silence the unused_mut warning in two test modules below.
index 6043bf35b99d4d85ae79a5656cc75b82e7d6c09e..d43ad6d0aebc2fd372c5c7837349a9beac0ebedf 100644 (file)
@@ -1674,17 +1674,21 @@ pub use self::fuzzy_internal_msgs::*;
 #[cfg(not(fuzzing))]
 pub(crate) use self::fuzzy_internal_msgs::*;
 
+/// BOLT 4 onion packet including hop data for the next peer.
 #[derive(Clone)]
-pub(crate) struct OnionPacket {
-       pub(crate) version: u8,
+pub struct OnionPacket {
+       /// BOLT 4 version number.
+       pub version: u8,
        /// In order to ensure we always return an error on onion decode in compliance with [BOLT
        /// #4](https://github.com/lightning/bolts/blob/master/04-onion-routing.md), we have to
        /// deserialize `OnionPacket`s contained in [`UpdateAddHTLC`] messages even if the ephemeral
        /// public key (here) is bogus, so we hold a [`Result`] instead of a [`PublicKey`] as we'd
        /// like.
-       pub(crate) public_key: Result<PublicKey, secp256k1::Error>,
-       pub(crate) hop_data: [u8; 20*65],
-       pub(crate) hmac: [u8; 32],
+       pub public_key: Result<PublicKey, secp256k1::Error>,
+       /// 1300 bytes encrypted payload for the next hop.
+       pub hop_data: [u8; 20*65],
+       /// HMAC to verify the integrity of hop_data.
+       pub hmac: [u8; 32],
 }
 
 impl onion_utils::Packet for OnionPacket {
index 9af3de07ff4e7356ac65fe2069b3ff209761156a..63abdc59b487554c79afdf43c472598271d6ae94 100644 (file)
@@ -935,6 +935,27 @@ pub(crate) fn decode_next_payment_hop<NS: Deref>(
        }
 }
 
+/// Build a payment onion, returning the first hop msat and cltv values as well.
+/// `cur_block_height` should be set to the best known block height + 1.
+pub fn create_payment_onion<T: secp256k1::Signing>(
+       secp_ctx: &Secp256k1<T>, path: &Path, session_priv: &SecretKey, total_msat: u64,
+       recipient_onion: RecipientOnionFields, cur_block_height: u32, payment_hash: &PaymentHash,
+       keysend_preimage: &Option<PaymentPreimage>, prng_seed: [u8; 32]
+) -> Result<(msgs::OnionPacket, u64, u32), APIError> {
+       let onion_keys = construct_onion_keys(&secp_ctx, &path, &session_priv)
+               .map_err(|_| APIError::InvalidRoute{
+                       err: "Pubkey along hop was maliciously selected".to_owned()
+               })?;
+       let (onion_payloads, htlc_msat, htlc_cltv) = build_onion_payloads(
+               &path, total_msat, recipient_onion, cur_block_height, keysend_preimage
+       )?;
+       let onion_packet = construct_onion_packet(onion_payloads, onion_keys, prng_seed, payment_hash)
+               .map_err(|_| APIError::InvalidRoute{
+                       err: "Route size too large considering onion data".to_owned()
+               })?;
+       Ok((onion_packet, htlc_msat, htlc_cltv))
+}
+
 pub(crate) fn decode_next_untagged_hop<T, R: ReadableArgs<T>, N: NextPacketBytes>(shared_secret: [u8; 32], hop_data: &[u8], hmac_bytes: [u8; 32], read_args: T) -> Result<(R, Option<([u8; 32], N)>), OnionDecodeErr> {
        decode_next_hop(shared_secret, hop_data, hmac_bytes, None, read_args)
 }