use bitcoin::hashes::Hash as TraitImport;
use bitcoin::WPubkeyHash;
+use lightning::blinded_path::message::MessageContext;
use lightning::blinded_path::payment::ReceiveTlvs;
use lightning::blinded_path::BlindedPath;
use lightning::chain;
}
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
- &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
+ &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
+ _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
unreachable!()
}
use bitcoin::hashes::Hash as _;
use bitcoin::WPubkeyHash;
+use lightning::blinded_path::message::MessageContext;
use lightning::blinded_path::payment::ReceiveTlvs;
use lightning::blinded_path::BlindedPath;
use lightning::chain;
}
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
- &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
+ &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
+ _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
unreachable!()
}
use crate::utils::test_logger;
use bitcoin::secp256k1::{self, Keypair, Parity, PublicKey, Secp256k1, SecretKey};
use core::convert::TryFrom;
-use lightning::blinded_path::message::ForwardNode;
+use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
use lightning::blinded_path::BlindedPath;
use lightning::ln::features::BlindedHopFeatures;
use lightning::ln::PaymentHash;
],
];
let paths = vec![
- BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
- .unwrap(),
- BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
- .unwrap(),
+ BlindedPath::new_for_message(
+ &intermediate_nodes[0],
+ pubkey(42),
+ MessageContext::Offers(OffersContext::Unknown {}),
+ &entropy_source,
+ secp_ctx,
+ )
+ .unwrap(),
+ BlindedPath::new_for_message(
+ &intermediate_nodes[1],
+ pubkey(42),
+ MessageContext::Offers(OffersContext::Unknown {}),
+ &entropy_source,
+ secp_ctx,
+ )
+ .unwrap(),
];
let payinfo = vec![
}
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
- &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
+ &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
+ _secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
unreachable!()
}
use crate::utils::test_logger;
use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey};
use core::convert::TryFrom;
-use lightning::blinded_path::message::ForwardNode;
+use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
use lightning::blinded_path::BlindedPath;
use lightning::ln::features::BlindedHopFeatures;
use lightning::ln::PaymentHash;
],
];
let paths = vec![
- BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
- .unwrap(),
- BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
- .unwrap(),
+ BlindedPath::new_for_message(
+ &intermediate_nodes[0],
+ pubkey(42),
+ MessageContext::Offers(OffersContext::Unknown {}),
+ &entropy_source,
+ secp_ctx,
+ )
+ .unwrap(),
+ BlindedPath::new_for_message(
+ &intermediate_nodes[1],
+ pubkey(42),
+ MessageContext::Offers(OffersContext::Unknown {}),
+ &entropy_source,
+ secp_ctx,
+ )
+ .unwrap(),
];
let payinfo = vec![
//! [`BlindedPath`]: crate::blinded_path::BlindedPath
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
+
#[allow(unused_imports)]
use crate::prelude::*;
/// 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,
- session_priv: &SecretKey
+ context: MessageContext, session_priv: &SecretKey
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
let pks = intermediate_nodes.iter().map(|node| &node.node_id)
.chain(core::iter::once(&recipient_node_id));
None => NextMessageHop::NodeId(*pubkey),
})
.map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None }))
- .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { context: None })));
+ .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context: Some(context) })));
utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv)
}
pub(crate) mod utils;
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
+use message::MessageContext;
use core::ops::Deref;
use crate::ln::msgs::DecodeError;
impl BlindedPath {
/// Create a one-hop blinded path for a message.
pub fn one_hop_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
- recipient_node_id: PublicKey, entropy_source: ES, secp_ctx: &Secp256k1<T>
+ recipient_node_id: PublicKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
) -> Result<Self, ()> where ES::Target: EntropySource {
- Self::new_for_message(&[], recipient_node_id, entropy_source, secp_ctx)
+ Self::new_for_message(&[], recipient_node_id, context, entropy_source, secp_ctx)
}
/// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node
// TODO: make all payloads the same size with padding + add dummy hops
pub fn new_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
intermediate_nodes: &[message::ForwardNode], recipient_node_id: PublicKey,
- entropy_source: ES, secp_ctx: &Secp256k1<T>
+ context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
) -> Result<Self, ()> where ES::Target: EntropySource {
let introduction_node = IntroductionNode::NodeId(
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id)
introduction_node,
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
blinded_hops: message::blinded_hops(
- secp_ctx, intermediate_nodes, recipient_node_id, &blinding_secret,
+ secp_ctx, intermediate_nodes, recipient_node_id,
+ context, &blinding_secret,
).map_err(|_| ())?,
})
}
use bitcoin::secp256k1::Secp256k1;
use bitcoin::{secp256k1, Sequence};
-use crate::blinded_path::message::OffersContext;
+use crate::blinded_path::message::{MessageContext, OffersContext};
use crate::blinded_path::{BlindedPath, NodeIdLookUp};
use crate::blinded_path::message::ForwardNode;
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
let entropy = &*$self.entropy_source;
let secp_ctx = &$self.secp_ctx;
- let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry)
+ let path = $self.create_blinded_path_using_absolute_expiry(OffersContext::Unknown {}, absolute_expiry)
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
let builder = OfferBuilder::deriving_signing_pubkey(
node_id, expanded_key, entropy, secp_ctx
let entropy = &*$self.entropy_source;
let secp_ctx = &$self.secp_ctx;
- let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry))
+ let context = OffersContext::OutboundPayment { payment_id };
+ let path = $self.create_blinded_path_using_absolute_expiry(context, Some(absolute_expiry))
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
let builder = RefundBuilder::deriving_payer_id(
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
Some(payer_note) => builder.payer_note(payer_note),
};
let invoice_request = builder.build_and_sign()?;
- let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
+
+ let context = OffersContext::OutboundPayment { payment_id };
+ let reply_path = self.create_blinded_path(context).map_err(|_| Bolt12SemanticError::MissingPaths)?;
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
)?;
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
- let reply_path = self.create_blinded_path()
+ let reply_path = self.create_blinded_path(OffersContext::Unknown {})
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
/// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
/// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
fn create_blinded_path_using_absolute_expiry(
- &self, absolute_expiry: Option<Duration>
+ &self, context: OffersContext, absolute_expiry: Option<Duration>,
) -> Result<BlindedPath, ()> {
let now = self.duration_since_epoch();
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
- self.create_compact_blinded_path()
+ self.create_compact_blinded_path(context)
} else {
- self.create_blinded_path()
+ self.create_blinded_path(context)
}
}
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
///
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
- fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
+ fn create_blinded_path(&self, context: OffersContext) -> Result<BlindedPath, ()> {
let recipient = self.get_our_node_id();
let secp_ctx = &self.secp_ctx;
.collect::<Vec<_>>();
self.router
- .create_blinded_paths(recipient, peers, secp_ctx)
+ .create_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
.and_then(|paths| paths.into_iter().next().ok_or(()))
}
/// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
///
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
- fn create_compact_blinded_path(&self) -> Result<BlindedPath, ()> {
+ fn create_compact_blinded_path(&self, context: OffersContext) -> Result<BlindedPath, ()> {
let recipient = self.get_our_node_id();
let secp_ctx = &self.secp_ctx;
.collect::<Vec<_>>();
self.router
- .create_compact_blinded_paths(recipient, peers, secp_ctx)
+ .create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
.and_then(|paths| paths.into_iter().next().ok_or(()))
}
use bitcoin::secp256k1::{Secp256k1, PublicKey};
use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode};
use crate::blinded_path::payment::{PaymentConstraints, PaymentContext, ReceiveTlvs};
-use crate::events::MessageSendEventsProvider;
+use crate::events::{Event, MessageSendEventsProvider};
use crate::ln::PaymentSecret;
use crate::ln::blinded_payment_tests::get_blinded_route_parameters;
use crate::ln::channelmanager::PaymentId;
nodes[0].onion_messenger.handle_onion_message(&nodes[1].node.get_our_node_id(), &invoice_om);
// TODO: assert on the invoice error once we support replying to invoice OMs with failure info
nodes[0].logger.assert_log_contains("lightning::ln::channelmanager", "Failed paying invoice: OnionPacketSizeExceeded", 1);
+
+ let events = nodes[0].node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ match events[0] {
+ Event::PaymentFailed { payment_id: id, .. } => {
+ assert_eq!(id, payment_id)
+ },
+ _ => panic!("Unexpected event"),
+ }
}
let invoice_error = extract_invoice_error(david, &onion_message);
assert_eq!(invoice_error, InvoiceError::from(Bolt12SemanticError::MissingPaths));
+
+ // Confirm that david drops this failed payment from his pending outbound payments.
+ match get_event!(david, Event::InvoiceRequestFailed) {
+ Event::InvoiceRequestFailed { payment_id: pay_id } => {
+ assert_eq!(pay_id, payment_id)
+ },
+ _ => panic!("No Event::InvoiceRequestFailed"),
+ }
}
#[test]
//! Onion message testing and test utilities live here.
use crate::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
-use crate::blinded_path::message::{ForwardNode, OffersContext};
+use crate::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
use crate::events::{Event, EventsProvider};
use crate::ln::features::{ChannelFeatures, InitFeatures};
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
impl CustomOnionMessageHandler for TestCustomMessageHandler {
type CustomMessage = TestCustomMessage;
- fn handle_custom_message(&self, msg: Self::CustomMessage, _context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
+ fn handle_custom_message(&self, msg: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
let expectation = self.get_next_expectation();
assert_eq!(msg, expectation.expect);
match responder {
Some(responder) if expectation.include_reply_path => {
- responder.respond_with_reply_path(response)
+ responder.respond_with_reply_path(response, MessageContext::Custom(context.unwrap_or_else(Vec::new)))
},
Some(responder) => responder.respond(response),
None => ResponseInstruction::NoResponse,
let test_msg = TestCustomMessage::Pong;
let secp_ctx = Secp256k1::new();
- let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
let secp_ctx = Secp256k1::new();
let intermediate_nodes = [ForwardNode { node_id: nodes[3].node_id, short_channel_id: None }];
- let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[4].node_id, &*nodes[4].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[4].node_id, context, &*nodes[4].entropy_source, &secp_ctx).unwrap();
let path = OnionMessagePath {
intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id],
destination: Destination::BlindedPath(blinded_path),
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
];
- let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, &*nodes[3].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
// 3. Simulate the creation of a Blinded Reply path provided by Bob.
let secp_ctx = Secp256k1::new();
- let reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
// 4. Create a responder using the reply path for Alice.
let responder = Some(Responder::new(reply_path));
// Alice receives a message from Bob with an added reply_path for responding back.
let message = TestCustomMessage::Ping;
- let reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let reply_path = BlindedPath::new_for_message(&[], bob.node_id, context, &*bob.entropy_source, &secp_ctx).unwrap();
// Alice asynchronously responds to Bob, expecting a response back from him.
let responder = Responder::new(reply_path);
// Alice receives a message from Bob with an added reply_path for responding back.
let message = TestCustomMessage::Ping;
- let reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let reply_path = BlindedPath::new_for_message(&[], bob.node_id, context, &*bob.entropy_source, &secp_ctx).unwrap();
// Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced and
// disconnected. Thus, a reply path could no be created for the response.
ForwardNode { node_id: nodes[0].node_id, short_channel_id: None },
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
];
- let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
nodes[0].messenger.send_onion_message(test_msg.clone(), destination, None).unwrap();
// Try with a two-hop blinded path where we are the introduction node.
let intermediate_nodes = [ForwardNode { node_id: nodes[0].node_id, short_channel_id: None }];
- let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
let secp_ctx = Secp256k1::new();
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
- let mut blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let mut blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap();
blinded_path.blinded_hops.clear();
let destination = Destination::BlindedPath(blinded_path);
let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
];
- let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, context, &*nodes[0].entropy_source, &secp_ctx).unwrap();
nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap();
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
pass_along_path(&nodes);
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
];
- let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, &*nodes[3].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let intermediate_nodes = [
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
];
- let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
+ let context = MessageContext::Custom(Vec::new());
+ let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, context, &*nodes[0].entropy_source, &secp_ctx).unwrap();
nodes[0].messenger.send_onion_message(test_msg, destination, Some(reply_path)).unwrap();
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
+ let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedPath::new_for_message(
- &intermediate_nodes, nodes[2].node_id, &*nodes[0].entropy_source, &secp_ctx
+ &intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx
).unwrap();
let destination = Destination::BlindedPath(blinded_path);
add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
+ let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedPath::new_for_message(
- &intermediate_nodes, nodes[2].node_id, &*nodes[0].entropy_source, &secp_ctx
+ &intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx
).unwrap();
let destination = Destination::BlindedPath(blinded_path);
let message = TestCustomMessage::Pong;
let secp_ctx = Secp256k1::new();
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
+ let context = MessageContext::Custom(Vec::new());
let blinded_path = BlindedPath::new_for_message(
- &intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx
+ &intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx
).unwrap();
let destination = Destination::BlindedPath(blinded_path);
/// # use bitcoin::hashes::hex::FromHex;
/// # use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey, self};
/// # use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
-/// # use lightning::blinded_path::message::ForwardNode;
+/// # use lightning::blinded_path::message::{ForwardNode, MessageContext};
/// # use lightning::sign::{EntropySource, KeysManager};
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
/// # use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath, OnionMessenger};
/// # })
/// # }
/// # fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-/// # &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>
+/// # &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>
/// # ) -> Result<Vec<BlindedPath>, ()> {
/// # unreachable!()
/// # }
/// ForwardNode { node_id: hop_node_id3, short_channel_id: None },
/// ForwardNode { node_id: hop_node_id4, short_channel_id: None },
/// ];
-/// let blinded_path = BlindedPath::new_for_message(&hops, your_node_id, &keys_manager, &secp_ctx).unwrap();
+/// let context = MessageContext::Custom(Vec::new());
+/// let blinded_path = BlindedPath::new_for_message(&hops, your_node_id, context, &keys_manager, &secp_ctx).unwrap();
///
/// // Send a custom onion message to a blinded path.
/// let destination = Destination::BlindedPath(blinded_path);
/// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
///
/// Use when the recipient needs to send back a reply to us.
- pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
+ pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T, context: MessageContext) -> ResponseInstruction<T> {
ResponseInstruction::WithReplyPath(OnionMessageResponse {
message: response,
reply_path: self.reply_path,
- })
+ }, context)
}
}
pub enum ResponseInstruction<T: OnionMessageContents> {
/// Indicates that a response should be sent including a reply path for
/// the recipient to respond back.
- WithReplyPath(OnionMessageResponse<T>),
+ WithReplyPath(OnionMessageResponse<T>, MessageContext),
/// Indicates that a response should be sent without including a reply path
/// for the recipient to respond back.
WithoutReplyPath(OnionMessageResponse<T>),
fn create_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()>;
/// Creates compact [`BlindedPath`]s to the `recipient` node. The nodes in `peers` are assumed
fn create_compact_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
let peers = peers
.into_iter()
.map(|ForwardNode { node_id, short_channel_id: _ }| node_id)
.collect();
- self.create_blinded_paths(recipient, peers, secp_ctx)
+ self.create_blinded_paths(recipient, context, peers, secp_ctx)
}
}
I: ExactSizeIterator<Item = ForwardNode>,
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: I, secp_ctx: &Secp256k1<T>, compact_paths: bool
+ &self, recipient: PublicKey, context: MessageContext, peers: I,
+ secp_ctx: &Secp256k1<T>, compact_paths: bool
) -> Result<Vec<BlindedPath>, ()> {
// Limit the number of blinded paths that are computed.
const MAX_PATHS: usize = 3;
let paths = peer_info.into_iter()
.map(|(peer, _, _)| {
- BlindedPath::new_for_message(&[peer], recipient, &*self.entropy_source, secp_ctx)
+ BlindedPath::new_for_message(&[peer], recipient, context.clone(), &*self.entropy_source, secp_ctx)
})
.take(MAX_PATHS)
.collect::<Result<Vec<_>, _>>();
Ok(paths) if !paths.is_empty() => Ok(paths),
_ => {
if is_recipient_announced {
- BlindedPath::one_hop_for_message(recipient, &*self.entropy_source, secp_ctx)
+ BlindedPath::one_hop_for_message(recipient, context, &*self.entropy_source, secp_ctx)
.map(|path| vec![path])
} else {
Err(())
fn create_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
let peers = peers
.into_iter()
.map(|node_id| ForwardNode { node_id, short_channel_id: None });
- self.create_blinded_paths_from_iter(recipient, peers, secp_ctx, false)
+ self.create_blinded_paths_from_iter(recipient, context, peers, secp_ctx, false)
}
fn create_compact_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.create_blinded_paths_from_iter(recipient, peers.into_iter(), secp_ctx, true)
+ self.create_blinded_paths_from_iter(recipient, context, peers.into_iter(), secp_ctx, true)
}
}
.map_err(|_| SendError::PathNotFound)
}
- fn create_blinded_path(&self) -> Result<BlindedPath, SendError> {
+ fn create_blinded_path(&self, context: MessageContext) -> Result<BlindedPath, SendError> {
let recipient = self.node_signer
.get_node_id(Recipient::Node)
.map_err(|_| SendError::GetNodeIdFailed)?;
.collect::<Vec<_>>();
self.message_router
- .create_blinded_paths(recipient, peers, secp_ctx)
+ .create_blinded_paths(recipient, context, peers, secp_ctx)
.and_then(|paths| paths.into_iter().next().ok_or(()))
.map_err(|_| SendError::PathNotFound)
}
pub fn handle_onion_message_response<T: OnionMessageContents>(
&self, response: ResponseInstruction<T>
) -> Result<Option<SendSuccess>, SendError> {
- let (response, create_reply_path) = match response {
- ResponseInstruction::WithReplyPath(response) => (response, true),
- ResponseInstruction::WithoutReplyPath(response) => (response, false),
+ let (response, context) = match response {
+ ResponseInstruction::WithReplyPath(response, context) => (response, Some(context)),
+ ResponseInstruction::WithoutReplyPath(response) => (response, None),
ResponseInstruction::NoResponse => return Ok(None),
};
let message_type = response.message.msg_type();
- let reply_path = if create_reply_path {
- match self.create_blinded_path() {
+ let reply_path = if let Some(context) = context {
+ match self.create_blinded_path(context) {
Ok(reply_path) => Some(reply_path),
Err(err) => {
log_trace!(
use bitcoin::secp256k1::{PublicKey, Secp256k1, self};
use crate::blinded_path::{BlindedHop, BlindedPath, Direction, IntroductionNode};
-use crate::blinded_path::message;
+use crate::blinded_path::message::{self, MessageContext};
use crate::blinded_path::payment::{ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs, self};
use crate::ln::{PaymentHash, PaymentPreimage};
use crate::ln::channel_state::ChannelDetails;
fn create_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
> (
- &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.message_router.create_blinded_paths(recipient, peers, secp_ctx)
+ self.message_router.create_blinded_paths(recipient, context, peers, secp_ctx)
}
fn create_compact_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
> (
- &self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.message_router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+ self.message_router.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
}
}
// You may not use this file except in accordance with one or both of these
// licenses.
+use crate::blinded_path::message::MessageContext;
use crate::blinded_path::BlindedPath;
use crate::blinded_path::message::ForwardNode;
use crate::blinded_path::payment::ReceiveTlvs;
fn create_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.router.create_blinded_paths(recipient, peers, secp_ctx)
+ self.router.create_blinded_paths(recipient, context, peers, secp_ctx)
}
fn create_compact_blinded_paths<
T: secp256k1::Signing + secp256k1::Verification
>(
- &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+ self.router.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
}
}
}
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
- &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.inner.create_blinded_paths(recipient, peers, secp_ctx)
+ self.inner.create_blinded_paths(recipient, context, peers, secp_ctx)
}
fn create_compact_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
- &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+ &self, recipient: PublicKey, context: MessageContext,
+ peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
) -> Result<Vec<BlindedPath>, ()> {
- self.inner.create_compact_blinded_paths(recipient, peers, secp_ctx)
+ self.inner.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
}
}