Add a trait for handling BOLT 12 Offers messages to OnionMessenger and a
skeleton implementation of it for ChannelManager. This allows users to
either provide their own custom handling Offers messages or rely on a
version provided by LDK using stateless verification.
use lightning::util::enforcing_trait_impls::EnforcingSigner;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, Writeable, Writer};
use lightning::util::enforcing_trait_impls::EnforcingSigner;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, Writeable, Writer};
-use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OnionMessenger};
+use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, OnionMessenger};
use crate::utils::test_logger;
use crate::utils::test_logger;
node_secret: secret,
counter: AtomicU64::new(0),
};
node_secret: secret,
counter: AtomicU64::new(0),
};
+ let offers_msg_handler = TestOffersMessageHandler {};
let custom_msg_handler = TestCustomMessageHandler {};
let custom_msg_handler = TestCustomMessageHandler {};
- let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, &custom_msg_handler);
+ let onion_messenger = OnionMessenger::new(
+ &keys_manager, &keys_manager, logger, &offers_msg_handler, &custom_msg_handler
+ );
let mut pk = [2; 33]; pk[1] = 0xff;
let peer_node_id_not_used = PublicKey::from_slice(&pk).unwrap();
onion_messenger.handle_onion_message(&peer_node_id_not_used, &msg);
let mut pk = [2; 33]; pk[1] = 0xff;
let peer_node_id_not_used = PublicKey::from_slice(&pk).unwrap();
onion_messenger.handle_onion_message(&peer_node_id_not_used, &msg);
do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, &logger);
}
do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, &logger);
}
+struct TestOffersMessageHandler {}
+
+impl OffersMessageHandler for TestOffersMessageHandler {
+ fn handle_message(&self, _message: OffersMessage) {}
+}
+
struct TestCustomMessage {}
const CUSTOM_MESSAGE_TYPE: u64 = 4242;
struct TestCustomMessage {}
const CUSTOM_MESSAGE_TYPE: u64 = 4242;
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
use crate::ln::wire;
use crate::ln::wire::{Encode, Type};
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
use crate::ln::wire;
use crate::ln::wire::{Encode, Type};
-use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias};
use crate::util::atomic_counter::AtomicCounter;
use crate::util::logger::Logger;
use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias};
use crate::util::atomic_counter::AtomicCounter;
use crate::util::logger::Logger;
InitFeatures::empty()
}
}
InitFeatures::empty()
}
}
+impl OffersMessageHandler for IgnoringMessageHandler {
+ fn handle_message(&self, _msg: OffersMessage) {}
+}
impl CustomOnionMessageHandler for IgnoringMessageHandler {
type CustomMessage = Infallible;
fn handle_custom_message(&self, _msg: Infallible) {
impl CustomOnionMessageHandler for IgnoringMessageHandler {
type CustomMessage = Infallible;
fn handle_custom_message(&self, _msg: Infallible) {
use crate::sign::{NodeSigner, Recipient};
use crate::ln::features::InitFeatures;
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
use crate::sign::{NodeSigner, Recipient};
use crate::ln::features::InitFeatures;
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
-use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError};
+use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessenger, SendError};
use crate::util::ser::{Writeable, Writer};
use crate::util::test_utils;
use crate::util::ser::{Writeable, Writer};
use crate::util::test_utils;
struct MessengerNode {
keys_manager: Arc<test_utils::TestKeysInterface>,
struct MessengerNode {
keys_manager: Arc<test_utils::TestKeysInterface>,
- messenger: OnionMessenger<Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestLogger>, Arc<TestCustomMessageHandler>>,
+ messenger: OnionMessenger<Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestKeysInterface>, Arc<test_utils::TestLogger>, Arc<TestOffersMessageHandler>, Arc<TestCustomMessageHandler>>,
custom_message_handler: Arc<TestCustomMessageHandler>,
logger: Arc<test_utils::TestLogger>,
}
custom_message_handler: Arc<TestCustomMessageHandler>,
logger: Arc<test_utils::TestLogger>,
}
+struct TestOffersMessageHandler {}
+
+impl OffersMessageHandler for TestOffersMessageHandler {
+ fn handle_message(&self, _message: OffersMessage) {
+ todo!()
+ }
+}
+
#[derive(Clone)]
struct TestCustomMessage {}
#[derive(Clone)]
struct TestCustomMessage {}
let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i)));
let seed = [i as u8; 32];
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", i)));
let seed = [i as u8; 32];
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&seed, Network::Testnet));
+ let offers_message_handler = Arc::new(TestOffersMessageHandler {});
let custom_message_handler = Arc::new(TestCustomMessageHandler::new());
nodes.push(MessengerNode {
keys_manager: keys_manager.clone(),
let custom_message_handler = Arc::new(TestCustomMessageHandler::new());
nodes.push(MessengerNode {
keys_manager: keys_manager.clone(),
- messenger: OnionMessenger::new(keys_manager.clone(), keys_manager.clone(), logger.clone(), custom_message_handler.clone()),
+ messenger: OnionMessenger::new(keys_manager.clone(), keys_manager, logger.clone(), offers_message_handler, custom_message_handler.clone()),
custom_message_handler,
logger,
});
custom_message_handler,
logger,
});
use crate::ln::onion_utils;
use crate::ln::peer_handler::IgnoringMessageHandler;
pub use super::packet::{CustomOnionMessageContents, OnionMessageContents};
use crate::ln::onion_utils;
use crate::ln::peer_handler::IgnoringMessageHandler;
pub use super::packet::{CustomOnionMessageContents, OnionMessageContents};
+use super::offers::OffersMessageHandler;
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
use crate::util::logger::Logger;
use crate::util::ser::Writeable;
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
use crate::util::logger::Logger;
use crate::util::ser::Writeable;
/// # let hop_node_id1 = PublicKey::from_secret_key(&secp_ctx, &node_secret);
/// # let (hop_node_id2, hop_node_id3, hop_node_id4) = (hop_node_id1, hop_node_id1, hop_node_id1);
/// # let destination_node_id = hop_node_id1;
/// # let hop_node_id1 = PublicKey::from_secret_key(&secp_ctx, &node_secret);
/// # let (hop_node_id2, hop_node_id3, hop_node_id4) = (hop_node_id1, hop_node_id1, hop_node_id1);
/// # let destination_node_id = hop_node_id1;
-/// # let your_custom_message_handler = IgnoringMessageHandler {};
+/// # let custom_message_handler = IgnoringMessageHandler {};
+/// # let offers_message_handler = IgnoringMessageHandler {};
/// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
/// // ChannelManager.
/// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
/// // ChannelManager.
-/// let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, &your_custom_message_handler);
+/// let onion_messenger = OnionMessenger::new(&keys_manager, &keys_manager, logger, &offers_message_handler, &custom_message_handler);
///
/// # struct YourCustomMessage {}
/// impl Writeable for YourCustomMessage {
///
/// # struct YourCustomMessage {}
/// impl Writeable for YourCustomMessage {
///
/// [offers]: <https://github.com/lightning/bolts/pull/798>
/// [`OnionMessenger`]: crate::onion_message::OnionMessenger
///
/// [offers]: <https://github.com/lightning/bolts/pull/798>
/// [`OnionMessenger`]: crate::onion_message::OnionMessenger
-pub struct OnionMessenger<ES: Deref, NS: Deref, L: Deref, CMH: Deref>
- where ES::Target: EntropySource,
- NS::Target: NodeSigner,
- L::Target: Logger,
- CMH:: Target: CustomOnionMessageHandler,
+pub struct OnionMessenger<ES: Deref, NS: Deref, L: Deref, OMH: Deref, CMH: Deref>
+where
+ ES::Target: EntropySource,
+ NS::Target: NodeSigner,
+ L::Target: Logger,
+ OMH::Target: OffersMessageHandler,
+ CMH:: Target: CustomOnionMessageHandler,
{
entropy_source: ES,
node_signer: NS,
logger: L,
pending_messages: Mutex<HashMap<PublicKey, VecDeque<msgs::OnionMessage>>>,
secp_ctx: Secp256k1<secp256k1::All>,
{
entropy_source: ES,
node_signer: NS,
logger: L,
pending_messages: Mutex<HashMap<PublicKey, VecDeque<msgs::OnionMessage>>>,
secp_ctx: Secp256k1<secp256k1::All>,
- // Coming soon:
- // invoice_handler: InvoiceHandler,
}
/// The destination of an onion message.
}
/// The destination of an onion message.
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError>;
}
fn read_custom_message<R: io::Read>(&self, message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError>;
}
-impl<ES: Deref, NS: Deref, L: Deref, CMH: Deref> OnionMessenger<ES, NS, L, CMH>
- where ES::Target: EntropySource,
- NS::Target: NodeSigner,
- L::Target: Logger,
- CMH::Target: CustomOnionMessageHandler,
+impl<ES: Deref, NS: Deref, L: Deref, OMH: Deref, CMH: Deref> OnionMessenger<ES, NS, L, OMH, CMH>
+where
+ ES::Target: EntropySource,
+ NS::Target: NodeSigner,
+ L::Target: Logger,
+ OMH::Target: OffersMessageHandler,
+ CMH::Target: CustomOnionMessageHandler,
{
/// Constructs a new `OnionMessenger` to send, forward, and delegate received onion messages to
/// their respective handlers.
{
/// Constructs a new `OnionMessenger` to send, forward, and delegate received onion messages to
/// their respective handlers.
- pub fn new(entropy_source: ES, node_signer: NS, logger: L, custom_handler: CMH) -> Self {
+ pub fn new(
+ entropy_source: ES, node_signer: NS, logger: L, offers_handler: OMH, custom_handler: CMH
+ ) -> Self {
let mut secp_ctx = Secp256k1::new();
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
OnionMessenger {
let mut secp_ctx = Secp256k1::new();
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
OnionMessenger {
pending_messages: Mutex::new(HashMap::new()),
secp_ctx,
logger,
pending_messages: Mutex::new(HashMap::new()),
secp_ctx,
logger,
-impl<ES: Deref, NS: Deref, L: Deref, CMH: Deref> OnionMessageHandler for OnionMessenger<ES, NS, L, CMH>
- where ES::Target: EntropySource,
- NS::Target: NodeSigner,
- L::Target: Logger + Sized,
- CMH::Target: CustomOnionMessageHandler + Sized,
+impl<ES: Deref, NS: Deref, L: Deref, OMH: Deref, CMH: Deref> OnionMessageHandler
+for OnionMessenger<ES, NS, L, OMH, CMH>
+where
+ ES::Target: EntropySource,
+ NS::Target: NodeSigner,
+ L::Target: Logger,
+ OMH::Target: OffersMessageHandler,
+ CMH::Target: CustomOnionMessageHandler + Sized,
{
/// Handle an incoming onion message. Currently, if a message was destined for us we will log, but
/// soon we'll delegate the onion message to a handler that can generate invoices or send
{
/// Handle an incoming onion message. Currently, if a message was destined for us we will log, but
/// soon we'll delegate the onion message to a handler that can generate invoices or send
"Received an onion message with path_id {:02x?} and {} reply_path",
path_id, if reply_path.is_some() { "a" } else { "no" });
match message {
"Received an onion message with path_id {:02x?} and {} reply_path",
path_id, if reply_path.is_some() { "a" } else { "no" });
match message {
- OnionMessageContents::Offers(_msg) => todo!(),
+ OnionMessageContents::Offers(msg) => self.offers_handler.handle_message(msg),
OnionMessageContents::Custom(msg) => self.custom_handler.handle_custom_message(msg),
}
},
OnionMessageContents::Custom(msg) => self.custom_handler.handle_custom_message(msg),
}
},
-impl<ES: Deref, NS: Deref, L: Deref, CMH: Deref> OnionMessageProvider for OnionMessenger<ES, NS, L, CMH>
- where ES::Target: EntropySource,
- NS::Target: NodeSigner,
- L::Target: Logger,
- CMH::Target: CustomOnionMessageHandler,
+impl<ES: Deref, NS: Deref, L: Deref, OMH: Deref, CMH: Deref> OnionMessageProvider
+for OnionMessenger<ES, NS, L, OMH, CMH>
+where
+ ES::Target: EntropySource,
+ NS::Target: NodeSigner,
+ L::Target: Logger,
+ OMH::Target: OffersMessageHandler,
+ CMH::Target: CustomOnionMessageHandler,
{
fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage> {
let mut pending_msgs = self.pending_messages.lock().unwrap();
{
fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage> {
let mut pending_msgs = self.pending_messages.lock().unwrap();
///
/// [`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
/// [`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
///
/// [`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
/// [`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
-pub type SimpleArcOnionMessenger<L> = OnionMessenger<Arc<KeysManager>, Arc<KeysManager>, Arc<L>, IgnoringMessageHandler>;
+pub type SimpleArcOnionMessenger<L> = OnionMessenger<
+ Arc<KeysManager>,
+ Arc<KeysManager>,
+ Arc<L>,
+ IgnoringMessageHandler,
+ IgnoringMessageHandler
+>;
+
/// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and
/// [`SimpleRefPeerManager`]. See their docs for more details.
///
/// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and
/// [`SimpleRefPeerManager`]. See their docs for more details.
///
///
/// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
/// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
///
/// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
/// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
-pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<&'a KeysManager, &'a KeysManager, &'b L, IgnoringMessageHandler>;
+pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<
+ &'a KeysManager,
+ &'a KeysManager,
+ &'b L,
+ IgnoringMessageHandler,
+ IgnoringMessageHandler
+>;
/// Construct onion packet payloads and keys for sending an onion message along the given
/// `unblinded_path` to the given `destination`.
/// Construct onion packet payloads and keys for sending an onion message along the given
/// `unblinded_path` to the given `destination`.
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+pub use self::offers::{OffersMessage, OffersMessageHandler};
pub(crate) use self::packet::{ControlTlvs, Packet};
pub(crate) use self::packet::{ControlTlvs, Packet};
const INVOICE_TLV_TYPE: u64 = 66;
const INVOICE_ERROR_TLV_TYPE: u64 = 68;
const INVOICE_TLV_TYPE: u64 = 66;
const INVOICE_ERROR_TLV_TYPE: u64 = 68;
+/// A handler for an [`OnionMessage`] containing a BOLT 12 Offers message as its payload.
+///
+/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
+pub trait OffersMessageHandler {
+ /// Handles the given message by either responding with an [`Invoice`], sending a payment, or
+ /// replying with an error.
+ fn handle_message(&self, message: OffersMessage);
+}
+
/// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`].
///
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
/// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`].
///
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
-impl<L: Logger> ReadableArgs<(u64, &L)> for OffersMessage {
+impl<L: Logger + ?Sized> ReadableArgs<(u64, &L)> for OffersMessage {
fn read<R: Read>(r: &mut R, read_args: (u64, &L)) -> Result<Self, DecodeError> {
let (tlv_type, logger) = read_args;
if tlv_type == INVOICE_ERROR_TLV_TYPE {
fn read<R: Read>(r: &mut R, read_args: (u64, &L)) -> Result<Self, DecodeError> {
let (tlv_type, logger) = read_args;
if tlv_type == INVOICE_ERROR_TLV_TYPE {
}
// Uses the provided secret to simultaneously decode and decrypt the control TLVs and data TLV.
}
// Uses the provided secret to simultaneously decode and decrypt the control TLVs and data TLV.
-impl<H: CustomOnionMessageHandler, L: Logger>
+impl<H: CustomOnionMessageHandler, L: Logger + ?Sized>
ReadableArgs<(SharedSecret, &H, &L)> for Payload<<H as CustomOnionMessageHandler>::CustomMessage> {
fn read<R: Read>(r: &mut R, args: (SharedSecret, &H, &L)) -> Result<Self, DecodeError> {
let (encrypted_tlvs_ss, handler, logger) = args;
ReadableArgs<(SharedSecret, &H, &L)> for Payload<<H as CustomOnionMessageHandler>::CustomMessage> {
fn read<R: Read>(r: &mut R, args: (SharedSecret, &H, &L)) -> Result<Self, DecodeError> {
let (encrypted_tlvs_ss, handler, logger) = args;