X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fonion_utils.rs;h=e952bd8e2e125c5d8c16ef6f8419e1c8a2579ba0;hb=0456b0e311a4996b00d715f9211adcabc06b37c7;hp=390826e4f3d2938b32a69855b8b70eab2d476e3e;hpb=6299f7d14f4a6b47e133c6abaa3a05ed50177b0f;p=rust-lightning diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index 390826e4..e952bd8e 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -93,7 +93,7 @@ pub(super) fn gen_pad_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] { } /// Calculates a pubkey for the next hop, such as the next hop's packet pubkey or blinding point. -pub(crate) fn next_hop_pubkey( +pub(crate) fn next_hop_pubkey( secp_ctx: &Secp256k1, curr_pubkey: PublicKey, shared_secret: &[u8] ) -> Result { let blinding_factor = { @@ -935,6 +935,27 @@ pub(crate) fn decode_next_payment_hop( } } +/// 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( + secp_ctx: &Secp256k1, path: &Path, session_priv: &SecretKey, total_msat: u64, + recipient_onion: RecipientOnionFields, cur_block_height: u32, payment_hash: &PaymentHash, + keysend_preimage: &Option, 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, 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) } @@ -1046,27 +1067,27 @@ mod tests { RouteHop { pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(), channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(), - short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops. + short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops. }, RouteHop { pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(), channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(), - short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops. + short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops. }, RouteHop { pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(), channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(), - short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops. + short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops. }, RouteHop { pubkey: PublicKey::from_slice(&hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]).unwrap(), channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(), - short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops. + short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops. }, RouteHop { pubkey: PublicKey::from_slice(&hex::decode("02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145").unwrap()[..]).unwrap(), channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(), - short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops. + short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops. }, ], blinded_tail: None }], route_params: None,