mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-23 14:50:45 +01:00
Include HMAC and Nonce in payment::ReceiveTlvs
In order to authenticate a PaymentContext, an HMAC and Nonce must be included along with it in payment::ReceiveTlvs. Compute the HMAC when constructing a BlindedPaymentPath and include it in the recipient's BlindedPaymentTlvs. Authentication will be added in an upcoming commit.
This commit is contained in:
parent
a29153025f
commit
55c02fdee1
9 changed files with 128 additions and 37 deletions
|
@ -12,11 +12,13 @@ use bitcoin::secp256k1::{self, Keypair, Parity, PublicKey, Secp256k1, SecretKey}
|
|||
use core::convert::TryFrom;
|
||||
use lightning::blinded_path::payment::{
|
||||
BlindedPaymentPath, Bolt12OfferContext, ForwardTlvs, PaymentConstraints, PaymentContext,
|
||||
PaymentForwardNode, PaymentRelay, ReceiveTlvs,
|
||||
PaymentForwardNode, PaymentRelay, UnauthenticatedReceiveTlvs,
|
||||
};
|
||||
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
|
||||
use lightning::ln::inbound_payment::ExpandedKey;
|
||||
use lightning::offers::invoice::UnsignedBolt12Invoice;
|
||||
use lightning::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields};
|
||||
use lightning::offers::nonce::Nonce;
|
||||
use lightning::offers::offer::OfferId;
|
||||
use lightning::offers::parse::Bolt12SemanticError;
|
||||
use lightning::sign::EntropySource;
|
||||
|
@ -80,7 +82,9 @@ fn privkey(byte: u8) -> SecretKey {
|
|||
fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
||||
invoice_request: &InvoiceRequest, secp_ctx: &Secp256k1<T>,
|
||||
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
|
||||
let expanded_key = ExpandedKey::new([42; 32]);
|
||||
let entropy_source = Randomness {};
|
||||
let nonce = Nonce::from_entropy_source(&entropy_source);
|
||||
let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext {
|
||||
offer_id: OfferId([42; 32]),
|
||||
invoice_request: InvoiceRequestFields {
|
||||
|
@ -92,7 +96,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
|||
human_readable_name: None,
|
||||
},
|
||||
});
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([42; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 1_000_000,
|
||||
|
@ -100,6 +104,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
|||
},
|
||||
payment_context,
|
||||
};
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
let intermediate_nodes = [PaymentForwardNode {
|
||||
tlvs: ForwardTlvs {
|
||||
short_channel_id: 43,
|
||||
|
@ -109,7 +114,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
|||
fee_base_msat: 1,
|
||||
},
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: payee_tlvs.payment_constraints.max_cltv_expiry + 40,
|
||||
max_cltv_expiry: payee_tlvs.tlvs().payment_constraints.max_cltv_expiry + 40,
|
||||
htlc_minimum_msat: 100,
|
||||
},
|
||||
features: BlindedHopFeatures::empty(),
|
||||
|
|
|
@ -12,10 +12,12 @@ use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey};
|
|||
use core::convert::TryFrom;
|
||||
use lightning::blinded_path::payment::{
|
||||
BlindedPaymentPath, Bolt12RefundContext, ForwardTlvs, PaymentConstraints, PaymentContext,
|
||||
PaymentForwardNode, PaymentRelay, ReceiveTlvs,
|
||||
PaymentForwardNode, PaymentRelay, UnauthenticatedReceiveTlvs,
|
||||
};
|
||||
use lightning::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
|
||||
use lightning::ln::inbound_payment::ExpandedKey;
|
||||
use lightning::offers::invoice::UnsignedBolt12Invoice;
|
||||
use lightning::offers::nonce::Nonce;
|
||||
use lightning::offers::parse::Bolt12SemanticError;
|
||||
use lightning::offers::refund::Refund;
|
||||
use lightning::sign::EntropySource;
|
||||
|
@ -67,9 +69,11 @@ fn privkey(byte: u8) -> SecretKey {
|
|||
fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
||||
refund: &Refund, signing_pubkey: PublicKey, secp_ctx: &Secp256k1<T>,
|
||||
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
|
||||
let expanded_key = ExpandedKey::new([42; 32]);
|
||||
let entropy_source = Randomness {};
|
||||
let nonce = Nonce::from_entropy_source(&entropy_source);
|
||||
let payment_context = PaymentContext::Bolt12Refund(Bolt12RefundContext {});
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([42; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 1_000_000,
|
||||
|
@ -77,6 +81,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
|||
},
|
||||
payment_context,
|
||||
};
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
let intermediate_nodes = [PaymentForwardNode {
|
||||
tlvs: ForwardTlvs {
|
||||
short_channel_id: 43,
|
||||
|
@ -86,7 +91,7 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
|
|||
fee_base_msat: 1,
|
||||
},
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: payee_tlvs.payment_constraints.max_cltv_expiry + 40,
|
||||
max_cltv_expiry: payee_tlvs.tlvs().payment_constraints.max_cltv_expiry + 40,
|
||||
htlc_minimum_msat: 100,
|
||||
},
|
||||
features: BlindedHopFeatures::empty(),
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
//! Data structures and methods for constructing [`BlindedPaymentPath`]s to send a payment over.
|
||||
|
||||
use bitcoin::hashes::hmac::Hmac;
|
||||
use bitcoin::hashes::sha256::Hash as Sha256;
|
||||
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
|
||||
|
||||
use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NodeIdLookUp};
|
||||
|
@ -18,10 +20,13 @@ use crate::io;
|
|||
use crate::io::Cursor;
|
||||
use crate::types::payment::PaymentSecret;
|
||||
use crate::ln::channel_state::CounterpartyForwardingInfo;
|
||||
use crate::ln::channelmanager::Verification;
|
||||
use crate::types::features::BlindedHopFeatures;
|
||||
use crate::ln::inbound_payment::ExpandedKey;
|
||||
use crate::ln::msgs::DecodeError;
|
||||
use crate::ln::onion_utils;
|
||||
use crate::offers::invoice_request::InvoiceRequestFields;
|
||||
use crate::offers::nonce::Nonce;
|
||||
use crate::offers::offer::OfferId;
|
||||
use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
|
||||
use crate::sign::{EntropySource, NodeSigner, Recipient};
|
||||
|
@ -114,7 +119,7 @@ impl BlindedPaymentPath {
|
|||
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
|
||||
|
||||
let blinded_payinfo = compute_payinfo(
|
||||
intermediate_nodes, &payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta
|
||||
intermediate_nodes, &payee_tlvs.tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta
|
||||
)?;
|
||||
Ok(Self {
|
||||
inner_path: BlindedPath {
|
||||
|
@ -252,8 +257,26 @@ pub struct ForwardTlvs {
|
|||
|
||||
/// Data to construct a [`BlindedHop`] for receiving a payment. This payload is custom to LDK and
|
||||
/// may not be valid if received by another lightning implementation.
|
||||
///
|
||||
/// Can only be constructed by calling [`UnauthenticatedReceiveTlvs::authenticate`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ReceiveTlvs {
|
||||
/// The TLVs for which the HMAC in `authentication` is derived.
|
||||
pub(crate) tlvs: UnauthenticatedReceiveTlvs,
|
||||
/// An HMAC of `tlvs` along with a nonce used to construct it.
|
||||
pub(crate) authentication: (Hmac<Sha256>, Nonce),
|
||||
}
|
||||
|
||||
impl ReceiveTlvs {
|
||||
/// Returns the underlying TLVs.
|
||||
pub fn tlvs(&self) -> &UnauthenticatedReceiveTlvs {
|
||||
&self.tlvs
|
||||
}
|
||||
}
|
||||
|
||||
/// An unauthenticated [`ReceiveTlvs`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UnauthenticatedReceiveTlvs {
|
||||
/// Used to authenticate the sender of a payment to the receiver and tie MPP HTLCs together.
|
||||
pub payment_secret: PaymentSecret,
|
||||
/// Constraints for the receiver of this payment.
|
||||
|
@ -262,6 +285,17 @@ pub struct ReceiveTlvs {
|
|||
pub payment_context: PaymentContext,
|
||||
}
|
||||
|
||||
impl UnauthenticatedReceiveTlvs {
|
||||
/// Creates an authenticated [`ReceiveTlvs`], which includes an HMAC and the provide [`Nonce`]
|
||||
/// that can be use later to verify it authenticity.
|
||||
pub fn authenticate(self, nonce: Nonce, expanded_key: &ExpandedKey) -> ReceiveTlvs {
|
||||
ReceiveTlvs {
|
||||
authentication: (self.hmac_for_offer_payment(nonce, expanded_key), nonce),
|
||||
tlvs: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data to construct a [`BlindedHop`] for sending a payment over.
|
||||
///
|
||||
/// [`BlindedHop`]: crate::blinded_path::BlindedHop
|
||||
|
@ -400,11 +434,23 @@ impl Writeable for ForwardTlvs {
|
|||
}
|
||||
|
||||
impl Writeable for ReceiveTlvs {
|
||||
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||
encode_tlv_stream!(w, {
|
||||
(12, self.tlvs.payment_constraints, required),
|
||||
(65536, self.tlvs.payment_secret, required),
|
||||
(65537, self.tlvs.payment_context, required),
|
||||
(65539, self.authentication, required),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Writeable for UnauthenticatedReceiveTlvs {
|
||||
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||
encode_tlv_stream!(w, {
|
||||
(12, self.payment_constraints, required),
|
||||
(65536, self.payment_secret, required),
|
||||
(65537, self.payment_context, required)
|
||||
(65537, self.payment_context, required),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
@ -432,6 +478,7 @@ impl Readable for BlindedPaymentTlvs {
|
|||
(14, features, (option, encoding: (BlindedHopFeatures, WithoutLength))),
|
||||
(65536, payment_secret, option),
|
||||
(65537, payment_context, (default_value, PaymentContext::unknown())),
|
||||
(65539, authentication, option),
|
||||
});
|
||||
let _padding: Option<utils::Padding> = _padding;
|
||||
|
||||
|
@ -449,9 +496,12 @@ impl Readable for BlindedPaymentTlvs {
|
|||
} else {
|
||||
if payment_relay.is_some() || features.is_some() { return Err(DecodeError::InvalidValue) }
|
||||
Ok(BlindedPaymentTlvs::Receive(ReceiveTlvs {
|
||||
payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
|
||||
payment_constraints: payment_constraints.0.unwrap(),
|
||||
payment_context: payment_context.0.unwrap(),
|
||||
tlvs: UnauthenticatedReceiveTlvs {
|
||||
payment_secret: payment_secret.ok_or(DecodeError::InvalidValue)?,
|
||||
payment_constraints: payment_constraints.0.unwrap(),
|
||||
payment_context: payment_context.0.unwrap(),
|
||||
},
|
||||
authentication: authentication.ok_or(DecodeError::InvalidValue)?,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -494,7 +544,7 @@ pub(crate) fn amt_to_forward_msat(inbound_amt_msat: u64, payment_relay: &Payment
|
|||
}
|
||||
|
||||
pub(super) fn compute_payinfo(
|
||||
intermediate_nodes: &[PaymentForwardNode], payee_tlvs: &ReceiveTlvs,
|
||||
intermediate_nodes: &[PaymentForwardNode], payee_tlvs: &UnauthenticatedReceiveTlvs,
|
||||
payee_htlc_maximum_msat: u64, min_final_cltv_expiry_delta: u16,
|
||||
) -> Result<BlindedPayInfo, ()> {
|
||||
let mut curr_base_fee: u64 = 0;
|
||||
|
@ -631,7 +681,7 @@ impl_writeable_tlv_based!(Bolt12RefundContext, {});
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bitcoin::secp256k1::PublicKey;
|
||||
use crate::blinded_path::payment::{PaymentForwardNode, ForwardTlvs, ReceiveTlvs, PaymentConstraints, PaymentContext, PaymentRelay};
|
||||
use crate::blinded_path::payment::{PaymentForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentRelay, UnauthenticatedReceiveTlvs};
|
||||
use crate::types::payment::PaymentSecret;
|
||||
use crate::types::features::BlindedHopFeatures;
|
||||
use crate::ln::functional_test_utils::TEST_FINAL_CLTV;
|
||||
|
@ -676,7 +726,7 @@ mod tests {
|
|||
},
|
||||
htlc_maximum_msat: u64::max_value(),
|
||||
}];
|
||||
let recv_tlvs = ReceiveTlvs {
|
||||
let recv_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([0; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 0,
|
||||
|
@ -695,7 +745,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn compute_payinfo_1_hop() {
|
||||
let recv_tlvs = ReceiveTlvs {
|
||||
let recv_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([0; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 0,
|
||||
|
@ -751,7 +801,7 @@ mod tests {
|
|||
},
|
||||
htlc_maximum_msat: u64::max_value()
|
||||
}];
|
||||
let recv_tlvs = ReceiveTlvs {
|
||||
let recv_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([0; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 0,
|
||||
|
@ -804,7 +854,7 @@ mod tests {
|
|||
},
|
||||
htlc_maximum_msat: u64::max_value()
|
||||
}];
|
||||
let recv_tlvs = ReceiveTlvs {
|
||||
let recv_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([0; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 0,
|
||||
|
@ -861,7 +911,7 @@ mod tests {
|
|||
},
|
||||
htlc_maximum_msat: 10_000
|
||||
}];
|
||||
let recv_tlvs = ReceiveTlvs {
|
||||
let recv_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret: PaymentSecret([0; 32]),
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: 0,
|
||||
|
|
|
@ -12,7 +12,7 @@ use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, schnorr};
|
|||
use bitcoin::secp256k1::ecdh::SharedSecret;
|
||||
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
|
||||
use crate::blinded_path;
|
||||
use crate::blinded_path::payment::{BlindedPaymentPath, PaymentForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentRelay, ReceiveTlvs};
|
||||
use crate::blinded_path::payment::{BlindedPaymentPath, PaymentForwardNode, ForwardTlvs, PaymentConstraints, PaymentContext, PaymentRelay, UnauthenticatedReceiveTlvs};
|
||||
use crate::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentFailureReason};
|
||||
use crate::ln::types::ChannelId;
|
||||
use crate::types::payment::{PaymentHash, PaymentSecret};
|
||||
|
@ -28,6 +28,7 @@ use crate::ln::onion_utils;
|
|||
use crate::ln::onion_utils::INVALID_ONION_BLINDING;
|
||||
use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS};
|
||||
use crate::offers::invoice::UnsignedBolt12Invoice;
|
||||
use crate::offers::nonce::Nonce;
|
||||
use crate::prelude::*;
|
||||
use crate::routing::router::{BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters};
|
||||
use crate::sign::{NodeSigner, Recipient};
|
||||
|
@ -70,7 +71,8 @@ fn blinded_payment_path(
|
|||
.unwrap_or_else(|| channel_upds[idx - 1].htlc_maximum_msat),
|
||||
});
|
||||
}
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret,
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: u32::max_value(),
|
||||
|
@ -79,6 +81,11 @@ fn blinded_payment_path(
|
|||
},
|
||||
payment_context: PaymentContext::unknown(),
|
||||
};
|
||||
|
||||
let nonce = Nonce([42u8; 16]);
|
||||
let expanded_key = keys_manager.get_inbound_payment_key();
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
|
||||
let mut secp_ctx = Secp256k1::new();
|
||||
BlindedPaymentPath::new(
|
||||
&intermediate_nodes[..], *node_ids.last().unwrap(), payee_tlvs,
|
||||
|
@ -117,7 +124,7 @@ fn do_one_hop_blinded_path(success: bool) {
|
|||
|
||||
let amt_msat = 5000;
|
||||
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None);
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret,
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: u32::max_value(),
|
||||
|
@ -125,6 +132,10 @@ fn do_one_hop_blinded_path(success: bool) {
|
|||
},
|
||||
payment_context: PaymentContext::unknown(),
|
||||
};
|
||||
let nonce = Nonce([42u8; 16]);
|
||||
let expanded_key = chanmon_cfgs[1].keys_manager.get_inbound_payment_key();
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
|
||||
let mut secp_ctx = Secp256k1::new();
|
||||
let blinded_path = BlindedPaymentPath::new(
|
||||
&[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16,
|
||||
|
@ -161,7 +172,7 @@ fn mpp_to_one_hop_blinded_path() {
|
|||
|
||||
let amt_msat = 15_000_000;
|
||||
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret,
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: u32::max_value(),
|
||||
|
@ -169,6 +180,9 @@ fn mpp_to_one_hop_blinded_path() {
|
|||
},
|
||||
payment_context: PaymentContext::unknown(),
|
||||
};
|
||||
let nonce = Nonce([42u8; 16]);
|
||||
let expanded_key = chanmon_cfgs[3].keys_manager.get_inbound_payment_key();
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
let blinded_path = BlindedPaymentPath::new(
|
||||
&[], nodes[3].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16,
|
||||
&chanmon_cfgs[3].keys_manager, &secp_ctx
|
||||
|
@ -303,7 +317,7 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
|
|||
let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret, 1, 1_0000_0000,
|
||||
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(),
|
||||
&[&chan_upd_1_2, &chan_upd_2_3], &chanmon_cfgs[3].keys_manager);
|
||||
route_params.payment_params.max_path_length = 18;
|
||||
route_params.payment_params.max_path_length = 17;
|
||||
|
||||
let route = get_route(&nodes[0], &route_params).unwrap();
|
||||
node_cfgs[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
|
||||
|
@ -1366,7 +1380,7 @@ fn custom_tlvs_to_blinded_path() {
|
|||
|
||||
let amt_msat = 5000;
|
||||
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None);
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret,
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: u32::max_value(),
|
||||
|
@ -1374,6 +1388,9 @@ fn custom_tlvs_to_blinded_path() {
|
|||
},
|
||||
payment_context: PaymentContext::unknown(),
|
||||
};
|
||||
let nonce = Nonce([42u8; 16]);
|
||||
let expanded_key = chanmon_cfgs[1].keys_manager.get_inbound_payment_key();
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
let mut secp_ctx = Secp256k1::new();
|
||||
let blinded_path = BlindedPaymentPath::new(
|
||||
&[], nodes[1].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16,
|
||||
|
|
|
@ -36,7 +36,7 @@ use crate::events::FundingInfo;
|
|||
use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, OffersContext};
|
||||
use crate::blinded_path::NodeIdLookUp;
|
||||
use crate::blinded_path::message::{BlindedMessagePath, MessageForwardNode};
|
||||
use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
|
||||
use crate::blinded_path::payment::{BlindedPaymentPath, Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs};
|
||||
use crate::chain;
|
||||
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
|
||||
use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator};
|
||||
|
@ -480,7 +480,7 @@ impl Verification for PaymentHash {
|
|||
}
|
||||
}
|
||||
|
||||
impl Verification for ReceiveTlvs {
|
||||
impl Verification for UnauthenticatedReceiveTlvs {
|
||||
fn hmac_for_offer_payment(
|
||||
&self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
|
||||
) -> Hmac<Sha256> {
|
||||
|
@ -10490,13 +10490,16 @@ where
|
|||
fn create_blinded_payment_paths(
|
||||
&self, amount_msats: u64, payment_secret: PaymentSecret, payment_context: PaymentContext
|
||||
) -> Result<Vec<BlindedPaymentPath>, ()> {
|
||||
let expanded_key = &self.inbound_payment_key;
|
||||
let entropy = &*self.entropy_source;
|
||||
let secp_ctx = &self.secp_ctx;
|
||||
|
||||
let first_hops = self.list_usable_channels();
|
||||
let payee_node_id = self.get_our_node_id();
|
||||
let max_cltv_expiry = self.best_block.read().unwrap().height + CLTV_FAR_FAR_AWAY
|
||||
+ LATENCY_GRACE_PERIOD_BLOCKS;
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret,
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry,
|
||||
|
@ -10504,6 +10507,9 @@ where
|
|||
},
|
||||
payment_context,
|
||||
};
|
||||
let nonce = Nonce::from_entropy_source(entropy);
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, expanded_key);
|
||||
|
||||
self.router.create_blinded_payment_paths(
|
||||
payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx
|
||||
)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use bitcoin::secp256k1::{Secp256k1, PublicKey};
|
||||
use crate::blinded_path::BlindedHop;
|
||||
use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath, PaymentConstraints, PaymentContext, ReceiveTlvs};
|
||||
use crate::blinded_path::payment::{BlindedPayInfo, BlindedPaymentPath, PaymentConstraints, PaymentContext, UnauthenticatedReceiveTlvs};
|
||||
use crate::events::{Event, MessageSendEventsProvider};
|
||||
use crate::types::payment::PaymentSecret;
|
||||
use crate::ln::blinded_payment_tests::get_blinded_route_parameters;
|
||||
|
@ -24,8 +24,10 @@ use crate::ln::msgs::OnionMessageHandler;
|
|||
use crate::ln::onion_utils;
|
||||
use crate::ln::onion_utils::MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY;
|
||||
use crate::ln::outbound_payment::{RecipientOnionFields, Retry, RetryableSendFailure};
|
||||
use crate::offers::nonce::Nonce;
|
||||
use crate::prelude::*;
|
||||
use crate::routing::router::{DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, PaymentParameters, RouteParameters};
|
||||
use crate::sign::NodeSigner;
|
||||
use crate::util::errors::APIError;
|
||||
use crate::util::ser::Writeable;
|
||||
use crate::util::test_utils;
|
||||
|
@ -157,7 +159,7 @@ fn one_hop_blinded_path_with_custom_tlv() {
|
|||
// Construct the route parameters for sending to nodes[2]'s 1-hop blinded path.
|
||||
let amt_msat = 100_000;
|
||||
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), None);
|
||||
let payee_tlvs = ReceiveTlvs {
|
||||
let payee_tlvs = UnauthenticatedReceiveTlvs {
|
||||
payment_secret,
|
||||
payment_constraints: PaymentConstraints {
|
||||
max_cltv_expiry: u32::max_value(),
|
||||
|
@ -165,6 +167,9 @@ fn one_hop_blinded_path_with_custom_tlv() {
|
|||
},
|
||||
payment_context: PaymentContext::unknown(),
|
||||
};
|
||||
let nonce = Nonce([42u8; 16]);
|
||||
let expanded_key = chanmon_cfgs[2].keys_manager.get_inbound_payment_key();
|
||||
let payee_tlvs = payee_tlvs.authenticate(nonce, &expanded_key);
|
||||
let mut secp_ctx = Secp256k1::new();
|
||||
let blinded_path = BlindedPaymentPath::new(
|
||||
&[], nodes[2].node.get_our_node_id(), payee_tlvs, u64::MAX, TEST_FINAL_CLTV as u16,
|
||||
|
|
|
@ -31,7 +31,7 @@ use bitcoin::{secp256k1, Witness};
|
|||
use bitcoin::script::ScriptBuf;
|
||||
use bitcoin::hash_types::Txid;
|
||||
|
||||
use crate::blinded_path::payment::{BlindedPaymentTlvs, ForwardTlvs, ReceiveTlvs};
|
||||
use crate::blinded_path::payment::{BlindedPaymentTlvs, ForwardTlvs, ReceiveTlvs, UnauthenticatedReceiveTlvs};
|
||||
use crate::ln::types::ChannelId;
|
||||
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
|
||||
use crate::types::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
|
||||
|
@ -2907,9 +2907,11 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
|
|||
next_blinding_override,
|
||||
})
|
||||
},
|
||||
ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs {
|
||||
payment_secret, payment_constraints, payment_context
|
||||
})} => {
|
||||
ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(receive_tlvs) } => {
|
||||
let ReceiveTlvs { tlvs, authentication: _ } = receive_tlvs;
|
||||
let UnauthenticatedReceiveTlvs {
|
||||
payment_secret, payment_constraints, payment_context,
|
||||
} = tlvs;
|
||||
if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
|
||||
Ok(Self::BlindedReceive {
|
||||
sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
|
||||
|
|
|
@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
|
|||
use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey, self};
|
||||
use types::payment::PaymentHash;
|
||||
use core::fmt;
|
||||
use crate::blinded_path::payment::ReceiveTlvs;
|
||||
use crate::blinded_path::payment::UnauthenticatedReceiveTlvs;
|
||||
use crate::ln::channelmanager::PaymentId;
|
||||
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN};
|
||||
use crate::offers::merkle::TlvRecord;
|
||||
|
@ -465,7 +465,7 @@ fn hmac_for_payment_id(
|
|||
}
|
||||
|
||||
pub(crate) fn hmac_for_payment_tlvs(
|
||||
receive_tlvs: &ReceiveTlvs, nonce: Nonce, expanded_key: &ExpandedKey,
|
||||
receive_tlvs: &UnauthenticatedReceiveTlvs, nonce: Nonce, expanded_key: &ExpandedKey,
|
||||
) -> Hmac<Sha256> {
|
||||
const IV_BYTES: &[u8; IV_LEN] = b"LDK Payment TLVs";
|
||||
let mut hmac = expanded_key.hmac_for_offer();
|
||||
|
@ -478,7 +478,8 @@ pub(crate) fn hmac_for_payment_tlvs(
|
|||
}
|
||||
|
||||
pub(crate) fn verify_payment_tlvs(
|
||||
receive_tlvs: &ReceiveTlvs, hmac: Hmac<Sha256>, nonce: Nonce, expanded_key: &ExpandedKey,
|
||||
receive_tlvs: &UnauthenticatedReceiveTlvs, hmac: Hmac<Sha256>, nonce: Nonce,
|
||||
expanded_key: &ExpandedKey,
|
||||
) -> Result<(), ()> {
|
||||
if hmac_for_payment_tlvs(receive_tlvs, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) }
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, ES: Deref, S: Deref, SP: Size
|
|||
|
||||
let cltv_expiry_delta = payment_relay.cltv_expiry_delta as u32;
|
||||
let payment_constraints = PaymentConstraints {
|
||||
max_cltv_expiry: tlvs.payment_constraints.max_cltv_expiry + cltv_expiry_delta,
|
||||
max_cltv_expiry: tlvs.tlvs().payment_constraints.max_cltv_expiry + cltv_expiry_delta,
|
||||
htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0),
|
||||
};
|
||||
Some(PaymentForwardNode {
|
||||
|
|
Loading…
Add table
Reference in a new issue