//! [`BlindedPath`]: crate::blinded_path::BlindedPath
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
-
#[allow(unused_imports)]
use crate::prelude::*;
use crate::blinded_path::utils;
use crate::io;
use crate::io::Cursor;
+use crate::ln::channelmanager::PaymentId;
+use crate::ln::msgs::DecodeError;
use crate::ln::onion_utils;
use crate::onion_message::packet::ControlTlvs;
use crate::sign::{NodeSigner, Recipient};
use crate::crypto::streams::ChaChaPolyReadAdapter;
-use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
+use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Readable, Writeable, Writer};
use core::mem;
use core::ops::Deref;
/// If `path_id` is `Some`, it is used to identify the blinded path that this onion message is
/// sending to. This is useful for receivers to check that said blinded path is being used in
/// the right context.
- pub(crate) path_id: Option<[u8; 32]>,
+ pub path_id: Option<MessageContext>
}
impl Writeable for ForwardTlvs {
}
}
+impl Readable for ReceiveTlvs {
+ fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+ _init_and_read_tlv_stream!(r, {
+ (6, path_id, option),
+ });
+ Ok(ReceiveTlvs { path_id })
+ }
+}
+
+/// Represents additional data included by the recipient in a [`BlindedPath`].
+///
+/// This data is encrypted and will be included when sending through
+/// [`BlindedPath`]. The recipient can authenticate the message and
+/// utilize it for further processing if needed.
+#[derive(Clone, Debug)]
+pub enum MessageContext {
+ /// Represents the data specific to [`OffersMessage`]
+ ///
+ /// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
+ Offers(OffersContext),
+ /// Represents the data appended with Custom Onion Message.
+ Custom(Vec<u8>),
+}
+
+/// Contains the data specific to [`OffersMessage`]
+///
+/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
+#[derive(Clone, Debug)]
+pub enum OffersContext {
+ /// Represents an unknown context.
+ Unknown {},
+ /// Represents an outbound BOLT12 payment context.
+ OutboundPayment {
+ /// Payment ID of the outbound BOLT12 payment.
+ payment_id: PaymentId
+ },
+
+}
+
+impl_writeable_tlv_based_enum!(MessageContext, ;
+ (0, Offers),
+ (1, Custom),
+);
+
+impl_writeable_tlv_based_enum!(OffersContext,
+ (0, Unknown) => {},
+ (1, OutboundPayment) => {
+ (0, payment_id, required),
+ },
+;);
+
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey,
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
use crate::blinded_path::{BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
-use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs};
+use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs, MessageContext};
use crate::blinded_path::utils;
use crate::events::{Event, EventHandler, EventsProvider};
use crate::sign::{EntropySource, NodeSigner, Recipient};
pub enum PeeledOnion<T: OnionMessageContents> {
/// Forwarded onion, with the next node id and a new onion
Forward(NextMessageHop, OnionMessage),
- /// Received onion message, with decrypted contents, path_id, and reply path
- Receive(ParsedOnionMessageContents<T>, Option<[u8; 32]>, Option<BlindedPath>)
+ /// Received onion message, with decrypted contents, recipient data, and reply path
+ Receive(ParsedOnionMessageContents<T>, Option<MessageContext>, Option<BlindedPath>)
}
(control_tlvs_ss, custom_handler.deref(), logger.deref())
) {
Ok((Payload::Receive::<ParsedOnionMessageContents<<<CMH as Deref>::Target as CustomOnionMessageHandler>::CustomMessage>> {
- message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path,
+ message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: context }), reply_path,
}, None)) => {
- Ok(PeeledOnion::Receive(message, path_id, reply_path))
+ match (&message, &context) {
+ (_, None) => {
+ Ok(PeeledOnion::Receive(message, None, reply_path))
+ }
+ (ParsedOnionMessageContents::Offers(_), Some(MessageContext::Offers(_))) => {
+ Ok(PeeledOnion::Receive(message, context, reply_path))
+ }
+ (ParsedOnionMessageContents::Custom(_), Some(MessageContext::Custom(_))) => {
+ Ok(PeeledOnion::Receive(message, context, reply_path))
+ }
+ _ => {
+ log_trace!(logger, "Received message was sent on a blinded path with the wrong context.");
+ Err(())
+ }
+ }
},
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
next_hop, next_blinding_override
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
let logger = WithContext::from(&self.logger, Some(*peer_node_id), None, None);
match self.peel_onion_message(msg) {
- Ok(PeeledOnion::Receive(message, path_id, reply_path)) => {
+ Ok(PeeledOnion::Receive(message, _recipient_data, reply_path)) => {
log_trace!(
logger,
- "Received an onion message with path_id {:02x?} and {} reply_path: {:?}",
- path_id, if reply_path.is_some() { "a" } else { "no" }, message);
+ "Received an onion message with {} reply_path: {:?}",
+ if reply_path.is_some() { "a" } else { "no" }, message);
let responder = reply_path.map(Responder::new);
match message {
}, prev_control_tlvs_ss.unwrap()));
} else {
payloads.push((Payload::Receive {
- control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, }),
+ control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None }),
reply_path: reply_path.take(),
message,
}, prev_control_tlvs_ss.unwrap()));