mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 23:08:36 +01:00
Merge pull request #3125 from valentinewallace/2024-06-async-payments-prefactor
Async payments message encoding and prefactor
This commit is contained in:
commit
88e1b56d66
18 changed files with 342 additions and 39 deletions
|
@ -104,6 +104,8 @@ def check_cfg_tag(cfg):
|
||||||
pass
|
pass
|
||||||
elif cfg == "splicing":
|
elif cfg == "splicing":
|
||||||
pass
|
pass
|
||||||
|
elif cfg == "async_payments":
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
print("Bad cfg tag: " + cfg)
|
print("Bad cfg tag: " + cfg)
|
||||||
assert False
|
assert False
|
||||||
|
|
|
@ -179,3 +179,5 @@ RUSTFLAGS="--cfg=async_signing" cargo test --verbose --color always -p lightning
|
||||||
RUSTFLAGS="--cfg=dual_funding" cargo test --verbose --color always -p lightning
|
RUSTFLAGS="--cfg=dual_funding" cargo test --verbose --color always -p lightning
|
||||||
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
|
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
|
||||||
RUSTFLAGS="--cfg=splicing" cargo test --verbose --color always -p lightning
|
RUSTFLAGS="--cfg=splicing" cargo test --verbose --color always -p lightning
|
||||||
|
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
|
||||||
|
RUSTFLAGS="--cfg=async_payments" cargo test --verbose --color always -p lightning
|
||||||
|
|
|
@ -12,6 +12,9 @@ use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
|
||||||
use lightning::ln::script::ShutdownScript;
|
use lightning::ln::script::ShutdownScript;
|
||||||
use lightning::offers::invoice::UnsignedBolt12Invoice;
|
use lightning::offers::invoice::UnsignedBolt12Invoice;
|
||||||
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
|
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
|
||||||
|
use lightning::onion_message::async_payments::{
|
||||||
|
AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc,
|
||||||
|
};
|
||||||
use lightning::onion_message::messenger::{
|
use lightning::onion_message::messenger::{
|
||||||
CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger,
|
CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger,
|
||||||
PendingOnionMessage, Responder, ResponseInstruction,
|
PendingOnionMessage, Responder, ResponseInstruction,
|
||||||
|
@ -39,6 +42,7 @@ pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
|
||||||
let node_id_lookup = EmptyNodeIdLookUp {};
|
let node_id_lookup = EmptyNodeIdLookUp {};
|
||||||
let message_router = TestMessageRouter {};
|
let message_router = TestMessageRouter {};
|
||||||
let offers_msg_handler = TestOffersMessageHandler {};
|
let offers_msg_handler = TestOffersMessageHandler {};
|
||||||
|
let async_payments_msg_handler = TestAsyncPaymentsMessageHandler {};
|
||||||
let custom_msg_handler = TestCustomMessageHandler {};
|
let custom_msg_handler = TestCustomMessageHandler {};
|
||||||
let onion_messenger = OnionMessenger::new(
|
let onion_messenger = OnionMessenger::new(
|
||||||
&keys_manager,
|
&keys_manager,
|
||||||
|
@ -47,6 +51,7 @@ pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
|
||||||
&node_id_lookup,
|
&node_id_lookup,
|
||||||
&message_router,
|
&message_router,
|
||||||
&offers_msg_handler,
|
&offers_msg_handler,
|
||||||
|
&async_payments_msg_handler,
|
||||||
&custom_msg_handler,
|
&custom_msg_handler,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -105,6 +110,17 @@ impl OffersMessageHandler for TestOffersMessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TestAsyncPaymentsMessageHandler {}
|
||||||
|
|
||||||
|
impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler {
|
||||||
|
fn held_htlc_available(
|
||||||
|
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
|
||||||
|
) -> ResponseInstruction<ReleaseHeldHtlc> {
|
||||||
|
ResponseInstruction::NoResponse
|
||||||
|
}
|
||||||
|
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TestCustomMessage {}
|
struct TestCustomMessage {}
|
||||||
|
|
||||||
|
|
|
@ -568,7 +568,7 @@ use core::task;
|
||||||
/// # type NetworkGraph = lightning::routing::gossip::NetworkGraph<Arc<Logger>>;
|
/// # type NetworkGraph = lightning::routing::gossip::NetworkGraph<Arc<Logger>>;
|
||||||
/// # type P2PGossipSync<UL> = lightning::routing::gossip::P2PGossipSync<Arc<NetworkGraph>, Arc<UL>, Arc<Logger>>;
|
/// # type P2PGossipSync<UL> = lightning::routing::gossip::P2PGossipSync<Arc<NetworkGraph>, Arc<UL>, Arc<Logger>>;
|
||||||
/// # type ChannelManager<B, F, FE> = lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor<B, F, FE>, B, FE, Logger>;
|
/// # type ChannelManager<B, F, FE> = lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor<B, F, FE>, B, FE, Logger>;
|
||||||
/// # type OnionMessenger<B, F, FE> = lightning::onion_message::messenger::OnionMessenger<Arc<lightning::sign::KeysManager>, Arc<lightning::sign::KeysManager>, Arc<Logger>, Arc<ChannelManager<B, F, FE>>, Arc<lightning::onion_message::messenger::DefaultMessageRouter<Arc<NetworkGraph>, Arc<Logger>, Arc<lightning::sign::KeysManager>>>, Arc<ChannelManager<B, F, FE>>, lightning::ln::peer_handler::IgnoringMessageHandler>;
|
/// # type OnionMessenger<B, F, FE> = lightning::onion_message::messenger::OnionMessenger<Arc<lightning::sign::KeysManager>, Arc<lightning::sign::KeysManager>, Arc<Logger>, Arc<ChannelManager<B, F, FE>>, Arc<lightning::onion_message::messenger::DefaultMessageRouter<Arc<NetworkGraph>, Arc<Logger>, Arc<lightning::sign::KeysManager>>>, Arc<ChannelManager<B, F, FE>>, lightning::ln::peer_handler::IgnoringMessageHandler, lightning::ln::peer_handler::IgnoringMessageHandler>;
|
||||||
/// # type Scorer = RwLock<lightning::routing::scoring::ProbabilisticScorer<Arc<NetworkGraph>, Arc<Logger>>>;
|
/// # type Scorer = RwLock<lightning::routing::scoring::ProbabilisticScorer<Arc<NetworkGraph>, Arc<Logger>>>;
|
||||||
/// # type PeerManager<B, F, FE, UL> = lightning::ln::peer_handler::SimpleArcPeerManager<SocketDescriptor, ChainMonitor<B, F, FE>, B, FE, Arc<UL>, Logger>;
|
/// # type PeerManager<B, F, FE, UL> = lightning::ln::peer_handler::SimpleArcPeerManager<SocketDescriptor, ChainMonitor<B, F, FE>, B, FE, Arc<UL>, Logger>;
|
||||||
/// #
|
/// #
|
||||||
|
@ -996,7 +996,7 @@ mod tests {
|
||||||
type PGS = Arc<P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>>;
|
type PGS = Arc<P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>>;
|
||||||
type RGS = Arc<RapidGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>>>;
|
type RGS = Arc<RapidGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>>>;
|
||||||
|
|
||||||
type OM = OnionMessenger<Arc<KeysManager>, Arc<KeysManager>, Arc<test_utils::TestLogger>, Arc<ChannelManager>, Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>, Arc<KeysManager>>>, IgnoringMessageHandler, IgnoringMessageHandler>;
|
type OM = OnionMessenger<Arc<KeysManager>, Arc<KeysManager>, Arc<test_utils::TestLogger>, Arc<ChannelManager>, Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestLogger>, Arc<KeysManager>>>, IgnoringMessageHandler, IgnoringMessageHandler, IgnoringMessageHandler>;
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
node: Arc<ChannelManager>,
|
node: Arc<ChannelManager>,
|
||||||
|
@ -1291,7 +1291,7 @@ mod tests {
|
||||||
let best_block = BestBlock::from_network(network);
|
let best_block = BestBlock::from_network(network);
|
||||||
let params = ChainParameters { network, best_block };
|
let params = ChainParameters { network, best_block };
|
||||||
let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster.clone(), router.clone(), logger.clone(), keys_manager.clone(), keys_manager.clone(), keys_manager.clone(), UserConfig::default(), params, genesis_block.header.time));
|
let manager = Arc::new(ChannelManager::new(fee_estimator.clone(), chain_monitor.clone(), tx_broadcaster.clone(), router.clone(), logger.clone(), keys_manager.clone(), keys_manager.clone(), keys_manager.clone(), UserConfig::default(), params, genesis_block.header.time));
|
||||||
let messenger = Arc::new(OnionMessenger::new(keys_manager.clone(), keys_manager.clone(), logger.clone(), manager.clone(), msg_router.clone(), IgnoringMessageHandler {}, IgnoringMessageHandler {}));
|
let messenger = Arc::new(OnionMessenger::new(keys_manager.clone(), keys_manager.clone(), logger.clone(), manager.clone(), msg_router.clone(), IgnoringMessageHandler {}, IgnoringMessageHandler {}, IgnoringMessageHandler {}));
|
||||||
let wallet = Arc::new(TestWallet {});
|
let wallet = Arc::new(TestWallet {});
|
||||||
let sweeper = Arc::new(OutputSweeper::new(best_block, Arc::clone(&tx_broadcaster), Arc::clone(&fee_estimator),
|
let sweeper = Arc::new(OutputSweeper::new(best_block, Arc::clone(&tx_broadcaster), Arc::clone(&fee_estimator),
|
||||||
None::<Arc<dyn Filter + Sync + Send>>, Arc::clone(&keys_manager), wallet, Arc::clone(&kv_store), Arc::clone(&logger)));
|
None::<Arc<dyn Filter + Sync + Send>>, Arc::clone(&keys_manager), wallet, Arc::clone(&kv_store), Arc::clone(&logger)));
|
||||||
|
|
|
@ -10377,6 +10377,17 @@ where
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(_invoice) => {
|
||||||
|
match responder {
|
||||||
|
Some(responder) => {
|
||||||
|
responder.respond(OffersMessage::InvoiceError(
|
||||||
|
InvoiceError::from_string("Static invoices not yet supported".to_string())
|
||||||
|
))
|
||||||
|
},
|
||||||
|
None => return ResponseInstruction::NoResponse,
|
||||||
|
}
|
||||||
|
},
|
||||||
OffersMessage::InvoiceError(invoice_error) => {
|
OffersMessage::InvoiceError(invoice_error) => {
|
||||||
log_trace!(self.logger, "Received invoice_error: {}", invoice_error);
|
log_trace!(self.logger, "Received invoice_error: {}", invoice_error);
|
||||||
ResponseInstruction::NoResponse
|
ResponseInstruction::NoResponse
|
||||||
|
|
|
@ -423,6 +423,7 @@ type TestOnionMessenger<'chan_man, 'node_cfg, 'chan_mon_cfg> = OnionMessenger<
|
||||||
&'node_cfg test_utils::TestMessageRouter<'chan_mon_cfg>,
|
&'node_cfg test_utils::TestMessageRouter<'chan_mon_cfg>,
|
||||||
&'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
|
&'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
|
||||||
IgnoringMessageHandler,
|
IgnoringMessageHandler,
|
||||||
|
IgnoringMessageHandler,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// For use with [`OnionMessenger`] otherwise `test_restored_packages_retry` will fail. This is
|
/// For use with [`OnionMessenger`] otherwise `test_restored_packages_retry` will fail. This is
|
||||||
|
@ -3258,7 +3259,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
|
||||||
let dedicated_entropy = DedicatedEntropy(RandomBytes::new([i as u8; 32]));
|
let dedicated_entropy = DedicatedEntropy(RandomBytes::new([i as u8; 32]));
|
||||||
let onion_messenger = OnionMessenger::new(
|
let onion_messenger = OnionMessenger::new(
|
||||||
dedicated_entropy, cfgs[i].keys_manager, cfgs[i].logger, &chan_mgrs[i],
|
dedicated_entropy, cfgs[i].keys_manager, cfgs[i].logger, &chan_mgrs[i],
|
||||||
&cfgs[i].message_router, &chan_mgrs[i], IgnoringMessageHandler {},
|
&cfgs[i].message_router, &chan_mgrs[i], IgnoringMessageHandler {}, IgnoringMessageHandler {},
|
||||||
);
|
);
|
||||||
let gossip_sync = P2PGossipSync::new(cfgs[i].network_graph.as_ref(), None, cfgs[i].logger);
|
let gossip_sync = P2PGossipSync::new(cfgs[i].network_graph.as_ref(), None, cfgs[i].logger);
|
||||||
let wallet_source = Arc::new(test_utils::TestWalletSource::new(SecretKey::from_slice(&[i as u8 + 1; 32]).unwrap()));
|
let wallet_source = Arc::new(test_utils::TestWalletSource::new(SecretKey::from_slice(&[i as u8 + 1; 32]).unwrap()));
|
||||||
|
|
|
@ -192,8 +192,12 @@ fn extract_invoice_request<'a, 'b, 'c>(
|
||||||
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
|
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
|
||||||
OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path.unwrap()),
|
OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path.unwrap()),
|
||||||
OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
|
OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(invoice) => panic!("Unexpected static invoice: {:?}", invoice),
|
||||||
OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error),
|
OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error),
|
||||||
},
|
},
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
ParsedOnionMessageContents::AsyncPayments(message) => panic!("Unexpected async payments message: {:?}", message),
|
||||||
ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
|
ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
|
||||||
},
|
},
|
||||||
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
|
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
|
||||||
|
@ -207,8 +211,12 @@ fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage)
|
||||||
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
|
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
|
||||||
OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
|
OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
|
||||||
OffersMessage::Invoice(invoice) => invoice,
|
OffersMessage::Invoice(invoice) => invoice,
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(invoice) => panic!("Unexpected static invoice: {:?}", invoice),
|
||||||
OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error),
|
OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error),
|
||||||
},
|
},
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
ParsedOnionMessageContents::AsyncPayments(message) => panic!("Unexpected async payments message: {:?}", message),
|
||||||
ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
|
ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
|
||||||
},
|
},
|
||||||
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
|
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
|
||||||
|
@ -224,8 +232,12 @@ fn extract_invoice_error<'a, 'b, 'c>(
|
||||||
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
|
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
|
||||||
OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
|
OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
|
||||||
OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
|
OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
|
||||||
OffersMessage::InvoiceError(error) => error,
|
OffersMessage::InvoiceError(error) => error,
|
||||||
},
|
},
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
ParsedOnionMessageContents::AsyncPayments(message) => panic!("Unexpected async payments message: {:?}", message),
|
||||||
ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
|
ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
|
||||||
},
|
},
|
||||||
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
|
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
|
||||||
|
|
|
@ -28,6 +28,7 @@ use crate::util::ser::{VecWriter, Writeable, Writer};
|
||||||
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE};
|
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE};
|
||||||
use crate::ln::wire;
|
use crate::ln::wire;
|
||||||
use crate::ln::wire::{Encode, Type};
|
use crate::ln::wire::{Encode, Type};
|
||||||
|
use crate::onion_message::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc};
|
||||||
use crate::onion_message::messenger::{CustomOnionMessageHandler, PendingOnionMessage, Responder, ResponseInstruction};
|
use crate::onion_message::messenger::{CustomOnionMessageHandler, PendingOnionMessage, Responder, ResponseInstruction};
|
||||||
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
|
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
|
||||||
use crate::onion_message::packet::OnionMessageContents;
|
use crate::onion_message::packet::OnionMessageContents;
|
||||||
|
@ -148,6 +149,14 @@ impl OffersMessageHandler for IgnoringMessageHandler {
|
||||||
ResponseInstruction::NoResponse
|
ResponseInstruction::NoResponse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
|
||||||
|
fn held_htlc_available(
|
||||||
|
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
|
||||||
|
) -> ResponseInstruction<ReleaseHeldHtlc> {
|
||||||
|
ResponseInstruction::NoResponse
|
||||||
|
}
|
||||||
|
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
|
||||||
|
}
|
||||||
impl CustomOnionMessageHandler for IgnoringMessageHandler {
|
impl CustomOnionMessageHandler for IgnoringMessageHandler {
|
||||||
type CustomMessage = Infallible;
|
type CustomMessage = Infallible;
|
||||||
fn handle_custom_message(&self, _message: Self::CustomMessage, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
|
fn handle_custom_message(&self, _message: Self::CustomMessage, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub mod parse;
|
||||||
mod payer;
|
mod payer;
|
||||||
pub mod refund;
|
pub mod refund;
|
||||||
pub(crate) mod signer;
|
pub(crate) mod signer;
|
||||||
#[allow(unused)]
|
#[cfg(async_payments)]
|
||||||
pub(crate) mod static_invoice;
|
pub mod static_invoice;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod test_utils;
|
pub(crate) mod test_utils;
|
||||||
|
|
|
@ -665,6 +665,7 @@ impl Offer {
|
||||||
self.contents.expects_quantity()
|
self.contents.expects_quantity()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(async_payments)]
|
||||||
pub(super) fn verify<T: secp256k1::Signing>(
|
pub(super) fn verify<T: secp256k1::Signing>(
|
||||||
&self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
|
&self, key: &ExpandedKey, secp_ctx: &Secp256k1<T>
|
||||||
) -> Result<(OfferId, Option<Keypair>), ()> {
|
) -> Result<(OfferId, Option<Keypair>), ()> {
|
||||||
|
|
|
@ -15,8 +15,8 @@ use crate::ln::features::{Bolt12InvoiceFeatures, OfferFeatures};
|
||||||
use crate::ln::inbound_payment::ExpandedKey;
|
use crate::ln::inbound_payment::ExpandedKey;
|
||||||
use crate::ln::msgs::DecodeError;
|
use crate::ln::msgs::DecodeError;
|
||||||
use crate::offers::invoice::{
|
use crate::offers::invoice::{
|
||||||
check_invoice_signing_pubkey, construct_payment_paths, filter_fallbacks, BlindedPathIter,
|
check_invoice_signing_pubkey, construct_payment_paths, filter_fallbacks, BlindedPayInfo,
|
||||||
BlindedPayInfo, BlindedPayInfoIter, FallbackAddress, InvoiceTlvStream, InvoiceTlvStreamRef,
|
FallbackAddress, InvoiceTlvStream, InvoiceTlvStreamRef,
|
||||||
};
|
};
|
||||||
use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common};
|
use crate::offers::invoice_macros::{invoice_accessors_common, invoice_builder_methods_common};
|
||||||
use crate::offers::merkle::{
|
use crate::offers::merkle::{
|
||||||
|
@ -26,9 +26,7 @@ use crate::offers::offer::{
|
||||||
Amount, Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef, Quantity,
|
Amount, Offer, OfferContents, OfferTlvStream, OfferTlvStreamRef, Quantity,
|
||||||
};
|
};
|
||||||
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
|
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
|
||||||
use crate::util::ser::{
|
use crate::util::ser::{Iterable, SeekReadable, WithoutLength, Writeable, Writer};
|
||||||
HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer,
|
|
||||||
};
|
|
||||||
use crate::util::string::PrintableString;
|
use crate::util::string::PrintableString;
|
||||||
use bitcoin::address::Address;
|
use bitcoin::address::Address;
|
||||||
use bitcoin::blockdata::constants::ChainHash;
|
use bitcoin::blockdata::constants::ChainHash;
|
||||||
|
|
152
lightning/src/onion_message/async_payments.rs
Normal file
152
lightning/src/onion_message/async_payments.rs
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
// This file is Copyright its original authors, visible in version control
|
||||||
|
// history.
|
||||||
|
//
|
||||||
|
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
||||||
|
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
|
||||||
|
// You may not use this file except in accordance with one or both of these
|
||||||
|
// licenses.
|
||||||
|
|
||||||
|
//! Message handling for async payments.
|
||||||
|
|
||||||
|
use crate::io;
|
||||||
|
use crate::ln::msgs::DecodeError;
|
||||||
|
use crate::onion_message::messenger::PendingOnionMessage;
|
||||||
|
use crate::onion_message::messenger::{Responder, ResponseInstruction};
|
||||||
|
use crate::onion_message::packet::OnionMessageContents;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
||||||
|
|
||||||
|
// TLV record types for the `onionmsg_tlv` TLV stream as defined in BOLT 4.
|
||||||
|
const HELD_HTLC_AVAILABLE_TLV_TYPE: u64 = 72;
|
||||||
|
const RELEASE_HELD_HTLC_TLV_TYPE: u64 = 74;
|
||||||
|
|
||||||
|
/// A handler for an [`OnionMessage`] containing an async payments message as its payload.
|
||||||
|
///
|
||||||
|
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
|
||||||
|
pub trait AsyncPaymentsMessageHandler {
|
||||||
|
/// Handle a [`HeldHtlcAvailable`] message. A [`ReleaseHeldHtlc`] should be returned to release
|
||||||
|
/// the held funds.
|
||||||
|
fn held_htlc_available(
|
||||||
|
&self, message: HeldHtlcAvailable, responder: Option<Responder>,
|
||||||
|
) -> ResponseInstruction<ReleaseHeldHtlc>;
|
||||||
|
|
||||||
|
/// Handle a [`ReleaseHeldHtlc`] message. If authentication of the message succeeds, an HTLC
|
||||||
|
/// should be released to the corresponding payee.
|
||||||
|
fn release_held_htlc(&self, message: ReleaseHeldHtlc);
|
||||||
|
|
||||||
|
/// Release any [`AsyncPaymentsMessage`]s that need to be sent.
|
||||||
|
///
|
||||||
|
/// Typically, this is used for messages initiating an async payment flow rather than in response
|
||||||
|
/// to another message.
|
||||||
|
#[cfg(not(c_bindings))]
|
||||||
|
fn release_pending_messages(&self) -> Vec<PendingOnionMessage<AsyncPaymentsMessage>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Release any [`AsyncPaymentsMessage`]s that need to be sent.
|
||||||
|
///
|
||||||
|
/// Typically, this is used for messages initiating a payment flow rather than in response to
|
||||||
|
/// another message.
|
||||||
|
#[cfg(c_bindings)]
|
||||||
|
fn release_pending_messages(
|
||||||
|
&self,
|
||||||
|
) -> Vec<(
|
||||||
|
AsyncPaymentsMessage,
|
||||||
|
crate::onion_message::messenger::Destination,
|
||||||
|
Option<crate::blinded_path::BlindedPath>,
|
||||||
|
)> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possible async payment messages sent and received via an [`OnionMessage`].
|
||||||
|
///
|
||||||
|
/// [`OnionMessage`]: crate::ln::msgs::OnionMessage
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum AsyncPaymentsMessage {
|
||||||
|
/// An HTLC is being held upstream for the often-offline recipient, to be released via
|
||||||
|
/// [`ReleaseHeldHtlc`].
|
||||||
|
HeldHtlcAvailable(HeldHtlcAvailable),
|
||||||
|
|
||||||
|
/// Releases the HTLC corresponding to an inbound [`HeldHtlcAvailable`] message.
|
||||||
|
ReleaseHeldHtlc(ReleaseHeldHtlc),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An HTLC destined for the recipient of this message is being held upstream. The reply path
|
||||||
|
/// accompanying this onion message should be used to send a [`ReleaseHeldHtlc`] response, which
|
||||||
|
/// will cause the upstream HTLC to be released.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct HeldHtlcAvailable {
|
||||||
|
/// The secret that will be used by the recipient of this message to release the held HTLC.
|
||||||
|
pub payment_release_secret: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases the HTLC corresponding to an inbound [`HeldHtlcAvailable`] message.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ReleaseHeldHtlc {
|
||||||
|
/// Used to release the HTLC held upstream if it matches the corresponding
|
||||||
|
/// [`HeldHtlcAvailable::payment_release_secret`].
|
||||||
|
pub payment_release_secret: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OnionMessageContents for ReleaseHeldHtlc {
|
||||||
|
fn tlv_type(&self) -> u64 {
|
||||||
|
RELEASE_HELD_HTLC_TLV_TYPE
|
||||||
|
}
|
||||||
|
fn msg_type(&self) -> &'static str {
|
||||||
|
"Release Held HTLC"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_writeable_tlv_based!(HeldHtlcAvailable, {
|
||||||
|
(0, payment_release_secret, required),
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_writeable_tlv_based!(ReleaseHeldHtlc, {
|
||||||
|
(0, payment_release_secret, required),
|
||||||
|
});
|
||||||
|
|
||||||
|
impl AsyncPaymentsMessage {
|
||||||
|
/// Returns whether `tlv_type` corresponds to a TLV record for async payment messages.
|
||||||
|
pub fn is_known_type(tlv_type: u64) -> bool {
|
||||||
|
match tlv_type {
|
||||||
|
HELD_HTLC_AVAILABLE_TLV_TYPE | RELEASE_HELD_HTLC_TLV_TYPE => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OnionMessageContents for AsyncPaymentsMessage {
|
||||||
|
fn tlv_type(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
Self::HeldHtlcAvailable(_) => HELD_HTLC_AVAILABLE_TLV_TYPE,
|
||||||
|
Self::ReleaseHeldHtlc(msg) => msg.tlv_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn msg_type(&self) -> &'static str {
|
||||||
|
match &self {
|
||||||
|
Self::HeldHtlcAvailable(_) => "Held HTLC Available",
|
||||||
|
Self::ReleaseHeldHtlc(msg) => msg.msg_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writeable for AsyncPaymentsMessage {
|
||||||
|
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||||
|
match self {
|
||||||
|
Self::HeldHtlcAvailable(message) => message.write(w),
|
||||||
|
Self::ReleaseHeldHtlc(message) => message.write(w),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadableArgs<u64> for AsyncPaymentsMessage {
|
||||||
|
fn read<R: io::Read>(r: &mut R, tlv_type: u64) -> Result<Self, DecodeError> {
|
||||||
|
match tlv_type {
|
||||||
|
HELD_HTLC_AVAILABLE_TLV_TYPE => Ok(Self::HeldHtlcAvailable(Readable::read(r)?)),
|
||||||
|
RELEASE_HELD_HTLC_TLV_TYPE => Ok(Self::ReleaseHeldHtlc(Readable::read(r)?)),
|
||||||
|
_ => Err(DecodeError::InvalidValue),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ use crate::routing::test_utils::{add_channel, add_or_update_node};
|
||||||
use crate::sign::{NodeSigner, Recipient};
|
use crate::sign::{NodeSigner, Recipient};
|
||||||
use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
|
use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
|
||||||
use crate::util::test_utils;
|
use crate::util::test_utils;
|
||||||
|
use super::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc};
|
||||||
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess};
|
use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess};
|
||||||
use super::offers::{OffersMessage, OffersMessageHandler};
|
use super::offers::{OffersMessage, OffersMessageHandler};
|
||||||
use super::packet::{OnionMessageContents, Packet};
|
use super::packet::{OnionMessageContents, Packet};
|
||||||
|
@ -50,6 +51,7 @@ struct MessengerNode {
|
||||||
Arc<test_utils::TestKeysInterface>
|
Arc<test_utils::TestKeysInterface>
|
||||||
>>,
|
>>,
|
||||||
Arc<TestOffersMessageHandler>,
|
Arc<TestOffersMessageHandler>,
|
||||||
|
Arc<TestAsyncPaymentsMessageHandler>,
|
||||||
Arc<TestCustomMessageHandler>
|
Arc<TestCustomMessageHandler>
|
||||||
>,
|
>,
|
||||||
custom_message_handler: Arc<TestCustomMessageHandler>,
|
custom_message_handler: Arc<TestCustomMessageHandler>,
|
||||||
|
@ -79,6 +81,17 @@ impl OffersMessageHandler for TestOffersMessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TestAsyncPaymentsMessageHandler {}
|
||||||
|
|
||||||
|
impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler {
|
||||||
|
fn held_htlc_available(
|
||||||
|
&self, _message: HeldHtlcAvailable, _responder: Option<Responder>,
|
||||||
|
) -> ResponseInstruction<ReleaseHeldHtlc> {
|
||||||
|
ResponseInstruction::NoResponse
|
||||||
|
}
|
||||||
|
fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
enum TestCustomMessage {
|
enum TestCustomMessage {
|
||||||
Ping,
|
Ping,
|
||||||
|
@ -249,18 +262,19 @@ fn create_nodes_using_cfgs(cfgs: Vec<MessengerCfg>) -> Vec<MessengerNode> {
|
||||||
DefaultMessageRouter::new(network_graph.clone(), entropy_source.clone())
|
DefaultMessageRouter::new(network_graph.clone(), entropy_source.clone())
|
||||||
);
|
);
|
||||||
let offers_message_handler = Arc::new(TestOffersMessageHandler {});
|
let offers_message_handler = Arc::new(TestOffersMessageHandler {});
|
||||||
|
let async_payments_message_handler = Arc::new(TestAsyncPaymentsMessageHandler {});
|
||||||
let custom_message_handler = Arc::new(TestCustomMessageHandler::new());
|
let custom_message_handler = Arc::new(TestCustomMessageHandler::new());
|
||||||
let messenger = if cfg.intercept_offline_peer_oms {
|
let messenger = if cfg.intercept_offline_peer_oms {
|
||||||
OnionMessenger::new_with_offline_peer_interception(
|
OnionMessenger::new_with_offline_peer_interception(
|
||||||
entropy_source.clone(), node_signer.clone(), logger.clone(),
|
entropy_source.clone(), node_signer.clone(), logger.clone(),
|
||||||
node_id_lookup, message_router, offers_message_handler,
|
node_id_lookup, message_router, offers_message_handler,
|
||||||
custom_message_handler.clone()
|
async_payments_message_handler, custom_message_handler.clone()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
OnionMessenger::new(
|
OnionMessenger::new(
|
||||||
entropy_source.clone(), node_signer.clone(), logger.clone(),
|
entropy_source.clone(), node_signer.clone(), logger.clone(),
|
||||||
node_id_lookup, message_router, offers_message_handler,
|
node_id_lookup, message_router, offers_message_handler,
|
||||||
custom_message_handler.clone()
|
async_payments_message_handler, custom_message_handler.clone()
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
nodes.push(MessengerNode {
|
nodes.push(MessengerNode {
|
||||||
|
|
|
@ -24,6 +24,9 @@ use crate::ln::features::{InitFeatures, NodeFeatures};
|
||||||
use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler, SocketAddress};
|
use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler, SocketAddress};
|
||||||
use crate::ln::onion_utils;
|
use crate::ln::onion_utils;
|
||||||
use crate::routing::gossip::{NetworkGraph, NodeId, ReadOnlyNetworkGraph};
|
use crate::routing::gossip::{NetworkGraph, NodeId, ReadOnlyNetworkGraph};
|
||||||
|
use super::async_payments::AsyncPaymentsMessageHandler;
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
use super::async_payments::AsyncPaymentsMessage;
|
||||||
use super::packet::OnionMessageContents;
|
use super::packet::OnionMessageContents;
|
||||||
use super::packet::ParsedOnionMessageContents;
|
use super::packet::ParsedOnionMessageContents;
|
||||||
use super::offers::OffersMessageHandler;
|
use super::offers::OffersMessageHandler;
|
||||||
|
@ -76,22 +79,27 @@ pub trait AOnionMessenger {
|
||||||
type OffersMessageHandler: OffersMessageHandler + ?Sized;
|
type OffersMessageHandler: OffersMessageHandler + ?Sized;
|
||||||
/// A type that may be dereferenced to [`Self::OffersMessageHandler`]
|
/// A type that may be dereferenced to [`Self::OffersMessageHandler`]
|
||||||
type OMH: Deref<Target = Self::OffersMessageHandler>;
|
type OMH: Deref<Target = Self::OffersMessageHandler>;
|
||||||
|
/// A type implementing [`AsyncPaymentsMessageHandler`]
|
||||||
|
type AsyncPaymentsMessageHandler: AsyncPaymentsMessageHandler + ?Sized;
|
||||||
|
/// A type that may be dereferenced to [`Self::AsyncPaymentsMessageHandler`]
|
||||||
|
type APH: Deref<Target = Self::AsyncPaymentsMessageHandler>;
|
||||||
/// A type implementing [`CustomOnionMessageHandler`]
|
/// A type implementing [`CustomOnionMessageHandler`]
|
||||||
type CustomOnionMessageHandler: CustomOnionMessageHandler + ?Sized;
|
type CustomOnionMessageHandler: CustomOnionMessageHandler + ?Sized;
|
||||||
/// A type that may be dereferenced to [`Self::CustomOnionMessageHandler`]
|
/// A type that may be dereferenced to [`Self::CustomOnionMessageHandler`]
|
||||||
type CMH: Deref<Target = Self::CustomOnionMessageHandler>;
|
type CMH: Deref<Target = Self::CustomOnionMessageHandler>;
|
||||||
/// Returns a reference to the actual [`OnionMessenger`] object.
|
/// Returns a reference to the actual [`OnionMessenger`] object.
|
||||||
fn get_om(&self) -> &OnionMessenger<Self::ES, Self::NS, Self::L, Self::NL, Self::MR, Self::OMH, Self::CMH>;
|
fn get_om(&self) -> &OnionMessenger<Self::ES, Self::NS, Self::L, Self::NL, Self::MR, Self::OMH, Self::APH, Self::CMH>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, CMH: Deref> AOnionMessenger
|
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, APH: Deref, CMH: Deref> AOnionMessenger
|
||||||
for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> where
|
for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
NS::Target: NodeSigner,
|
NS::Target: NodeSigner,
|
||||||
L::Target: Logger,
|
L::Target: Logger,
|
||||||
NL::Target: NodeIdLookUp,
|
NL::Target: NodeIdLookUp,
|
||||||
MR::Target: MessageRouter,
|
MR::Target: MessageRouter,
|
||||||
OMH::Target: OffersMessageHandler,
|
OMH::Target: OffersMessageHandler,
|
||||||
|
APH:: Target: AsyncPaymentsMessageHandler,
|
||||||
CMH::Target: CustomOnionMessageHandler,
|
CMH::Target: CustomOnionMessageHandler,
|
||||||
{
|
{
|
||||||
type EntropySource = ES::Target;
|
type EntropySource = ES::Target;
|
||||||
|
@ -106,9 +114,11 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> where
|
||||||
type MR = MR;
|
type MR = MR;
|
||||||
type OffersMessageHandler = OMH::Target;
|
type OffersMessageHandler = OMH::Target;
|
||||||
type OMH = OMH;
|
type OMH = OMH;
|
||||||
|
type AsyncPaymentsMessageHandler = APH::Target;
|
||||||
|
type APH = APH;
|
||||||
type CustomOnionMessageHandler = CMH::Target;
|
type CustomOnionMessageHandler = CMH::Target;
|
||||||
type CMH = CMH;
|
type CMH = CMH;
|
||||||
fn get_om(&self) -> &OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> { self }
|
fn get_om(&self) -> &OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> { self }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A sender, receiver and forwarder of [`OnionMessage`]s.
|
/// A sender, receiver and forwarder of [`OnionMessage`]s.
|
||||||
|
@ -180,11 +190,12 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> where
|
||||||
/// # let message_router = Arc::new(FakeMessageRouter {});
|
/// # let message_router = Arc::new(FakeMessageRouter {});
|
||||||
/// # let custom_message_handler = IgnoringMessageHandler {};
|
/// # let custom_message_handler = IgnoringMessageHandler {};
|
||||||
/// # let offers_message_handler = IgnoringMessageHandler {};
|
/// # let offers_message_handler = IgnoringMessageHandler {};
|
||||||
|
/// # let async_payments_message_handler = IgnoringMessageHandler {};
|
||||||
/// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
|
/// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
|
||||||
/// // ChannelManager.
|
/// // ChannelManager.
|
||||||
/// let onion_messenger = OnionMessenger::new(
|
/// let onion_messenger = OnionMessenger::new(
|
||||||
/// &keys_manager, &keys_manager, logger, &node_id_lookup, message_router,
|
/// &keys_manager, &keys_manager, logger, &node_id_lookup, message_router,
|
||||||
/// &offers_message_handler, &custom_message_handler
|
/// &offers_message_handler, &async_payments_message_handler, &custom_message_handler
|
||||||
/// );
|
/// );
|
||||||
|
|
||||||
/// # #[derive(Debug)]
|
/// # #[derive(Debug)]
|
||||||
|
@ -225,14 +236,16 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> where
|
||||||
///
|
///
|
||||||
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
|
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
|
||||||
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
|
||||||
pub struct OnionMessenger<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, CMH: Deref>
|
pub struct OnionMessenger<
|
||||||
where
|
ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, APH: Deref, CMH: Deref
|
||||||
|
> where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
NS::Target: NodeSigner,
|
NS::Target: NodeSigner,
|
||||||
L::Target: Logger,
|
L::Target: Logger,
|
||||||
NL::Target: NodeIdLookUp,
|
NL::Target: NodeIdLookUp,
|
||||||
MR::Target: MessageRouter,
|
MR::Target: MessageRouter,
|
||||||
OMH::Target: OffersMessageHandler,
|
OMH::Target: OffersMessageHandler,
|
||||||
|
APH::Target: AsyncPaymentsMessageHandler,
|
||||||
CMH::Target: CustomOnionMessageHandler,
|
CMH::Target: CustomOnionMessageHandler,
|
||||||
{
|
{
|
||||||
entropy_source: ES,
|
entropy_source: ES,
|
||||||
|
@ -243,6 +256,8 @@ where
|
||||||
node_id_lookup: NL,
|
node_id_lookup: NL,
|
||||||
message_router: MR,
|
message_router: MR,
|
||||||
offers_handler: OMH,
|
offers_handler: OMH,
|
||||||
|
#[allow(unused)]
|
||||||
|
async_payments_handler: APH,
|
||||||
custom_handler: CMH,
|
custom_handler: CMH,
|
||||||
intercept_messages_for_offline_peers: bool,
|
intercept_messages_for_offline_peers: bool,
|
||||||
pending_events: Mutex<PendingEvents>,
|
pending_events: Mutex<PendingEvents>,
|
||||||
|
@ -993,8 +1008,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, CMH: Deref>
|
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, APH: Deref, CMH: Deref>
|
||||||
OnionMessenger<ES, NS, L, NL, MR, OMH, CMH>
|
OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH>
|
||||||
where
|
where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
NS::Target: NodeSigner,
|
NS::Target: NodeSigner,
|
||||||
|
@ -1002,17 +1017,18 @@ where
|
||||||
NL::Target: NodeIdLookUp,
|
NL::Target: NodeIdLookUp,
|
||||||
MR::Target: MessageRouter,
|
MR::Target: MessageRouter,
|
||||||
OMH::Target: OffersMessageHandler,
|
OMH::Target: OffersMessageHandler,
|
||||||
|
APH::Target: AsyncPaymentsMessageHandler,
|
||||||
CMH::Target: CustomOnionMessageHandler,
|
CMH::Target: CustomOnionMessageHandler,
|
||||||
{
|
{
|
||||||
/// Constructs a new `OnionMessenger` to send, forward, and delegate received onion messages to
|
/// Constructs a new `OnionMessenger` to send, forward, and delegate received onion messages to
|
||||||
/// their respective handlers.
|
/// their respective handlers.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL, message_router: MR,
|
entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL, message_router: MR,
|
||||||
offers_handler: OMH, custom_handler: CMH
|
offers_handler: OMH, async_payments_handler: APH, custom_handler: CMH
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
entropy_source, node_signer, logger, node_id_lookup, message_router,
|
entropy_source, node_signer, logger, node_id_lookup, message_router,
|
||||||
offers_handler, custom_handler, false
|
offers_handler, async_payments_handler, custom_handler, false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,17 +1055,17 @@ where
|
||||||
/// peers.
|
/// peers.
|
||||||
pub fn new_with_offline_peer_interception(
|
pub fn new_with_offline_peer_interception(
|
||||||
entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL,
|
entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL,
|
||||||
message_router: MR, offers_handler: OMH, custom_handler: CMH
|
message_router: MR, offers_handler: OMH, async_payments_handler: APH, custom_handler: CMH
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
entropy_source, node_signer, logger, node_id_lookup, message_router,
|
entropy_source, node_signer, logger, node_id_lookup, message_router,
|
||||||
offers_handler, custom_handler, true
|
offers_handler, async_payments_handler, custom_handler, true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_inner(
|
fn new_inner(
|
||||||
entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL,
|
entropy_source: ES, node_signer: NS, logger: L, node_id_lookup: NL,
|
||||||
message_router: MR, offers_handler: OMH, custom_handler: CMH,
|
message_router: MR, offers_handler: OMH, async_payments_handler: APH, custom_handler: CMH,
|
||||||
intercept_messages_for_offline_peers: bool
|
intercept_messages_for_offline_peers: bool
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut secp_ctx = Secp256k1::new();
|
let mut secp_ctx = Secp256k1::new();
|
||||||
|
@ -1063,6 +1079,7 @@ where
|
||||||
node_id_lookup,
|
node_id_lookup,
|
||||||
message_router,
|
message_router,
|
||||||
offers_handler,
|
offers_handler,
|
||||||
|
async_payments_handler,
|
||||||
custom_handler,
|
custom_handler,
|
||||||
intercept_messages_for_offline_peers,
|
intercept_messages_for_offline_peers,
|
||||||
pending_events: Mutex::new(PendingEvents {
|
pending_events: Mutex::new(PendingEvents {
|
||||||
|
@ -1367,8 +1384,8 @@ fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap<PublicKey, On
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, CMH: Deref> EventsProvider
|
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, APH: Deref, CMH: Deref> EventsProvider
|
||||||
for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH>
|
for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH>
|
||||||
where
|
where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
NS::Target: NodeSigner,
|
NS::Target: NodeSigner,
|
||||||
|
@ -1376,6 +1393,7 @@ where
|
||||||
NL::Target: NodeIdLookUp,
|
NL::Target: NodeIdLookUp,
|
||||||
MR::Target: MessageRouter,
|
MR::Target: MessageRouter,
|
||||||
OMH::Target: OffersMessageHandler,
|
OMH::Target: OffersMessageHandler,
|
||||||
|
APH::Target: AsyncPaymentsMessageHandler,
|
||||||
CMH::Target: CustomOnionMessageHandler,
|
CMH::Target: CustomOnionMessageHandler,
|
||||||
{
|
{
|
||||||
fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler {
|
fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler {
|
||||||
|
@ -1407,8 +1425,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, CMH: Deref> OnionMessageHandler
|
impl<ES: Deref, NS: Deref, L: Deref, NL: Deref, MR: Deref, OMH: Deref, APH: Deref, CMH: Deref> OnionMessageHandler
|
||||||
for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH>
|
for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH>
|
||||||
where
|
where
|
||||||
ES::Target: EntropySource,
|
ES::Target: EntropySource,
|
||||||
NS::Target: NodeSigner,
|
NS::Target: NodeSigner,
|
||||||
|
@ -1416,6 +1434,7 @@ where
|
||||||
NL::Target: NodeIdLookUp,
|
NL::Target: NodeIdLookUp,
|
||||||
MR::Target: MessageRouter,
|
MR::Target: MessageRouter,
|
||||||
OMH::Target: OffersMessageHandler,
|
OMH::Target: OffersMessageHandler,
|
||||||
|
APH::Target: AsyncPaymentsMessageHandler,
|
||||||
CMH::Target: CustomOnionMessageHandler,
|
CMH::Target: CustomOnionMessageHandler,
|
||||||
{
|
{
|
||||||
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
|
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
|
||||||
|
@ -1427,18 +1446,26 @@ where
|
||||||
"Received an onion message with path_id {:02x?} and {} reply_path: {:?}",
|
"Received an onion message with path_id {:02x?} and {} reply_path: {:?}",
|
||||||
path_id, if reply_path.is_some() { "a" } else { "no" }, message);
|
path_id, if reply_path.is_some() { "a" } else { "no" }, message);
|
||||||
|
|
||||||
|
let responder = reply_path.map(
|
||||||
|
|reply_path| Responder::new(reply_path, path_id)
|
||||||
|
);
|
||||||
match message {
|
match message {
|
||||||
ParsedOnionMessageContents::Offers(msg) => {
|
ParsedOnionMessageContents::Offers(msg) => {
|
||||||
let responder = reply_path.map(
|
|
||||||
|reply_path| Responder::new(reply_path, path_id)
|
|
||||||
);
|
|
||||||
let response_instructions = self.offers_handler.handle_message(msg, responder);
|
let response_instructions = self.offers_handler.handle_message(msg, responder);
|
||||||
let _ = self.handle_onion_message_response(response_instructions);
|
let _ = self.handle_onion_message_response(response_instructions);
|
||||||
},
|
},
|
||||||
ParsedOnionMessageContents::Custom(msg) => {
|
#[cfg(async_payments)]
|
||||||
let responder = reply_path.map(
|
ParsedOnionMessageContents::AsyncPayments(AsyncPaymentsMessage::HeldHtlcAvailable(msg)) => {
|
||||||
|reply_path| Responder::new(reply_path, path_id)
|
let response_instructions = self.async_payments_handler.held_htlc_available(
|
||||||
|
msg, responder
|
||||||
);
|
);
|
||||||
|
let _ = self.handle_onion_message_response(response_instructions);
|
||||||
|
},
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
ParsedOnionMessageContents::AsyncPayments(AsyncPaymentsMessage::ReleaseHeldHtlc(msg)) => {
|
||||||
|
self.async_payments_handler.release_held_htlc(msg);
|
||||||
|
},
|
||||||
|
ParsedOnionMessageContents::Custom(msg) => {
|
||||||
let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
|
let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
|
||||||
let _ = self.handle_onion_message_response(response_instructions);
|
let _ = self.handle_onion_message_response(response_instructions);
|
||||||
},
|
},
|
||||||
|
@ -1606,6 +1633,7 @@ pub type SimpleArcOnionMessenger<M, T, F, L> = OnionMessenger<
|
||||||
Arc<SimpleArcChannelManager<M, T, F, L>>,
|
Arc<SimpleArcChannelManager<M, T, F, L>>,
|
||||||
Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<L>>>, Arc<L>, Arc<KeysManager>>>,
|
Arc<DefaultMessageRouter<Arc<NetworkGraph<Arc<L>>>, Arc<L>, Arc<KeysManager>>>,
|
||||||
Arc<SimpleArcChannelManager<M, T, F, L>>,
|
Arc<SimpleArcChannelManager<M, T, F, L>>,
|
||||||
|
IgnoringMessageHandler,
|
||||||
IgnoringMessageHandler
|
IgnoringMessageHandler
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
@ -1626,6 +1654,7 @@ pub type SimpleRefOnionMessenger<
|
||||||
&'i SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>,
|
&'i SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>,
|
||||||
&'j DefaultMessageRouter<&'g NetworkGraph<&'b L>, &'b L, &'a KeysManager>,
|
&'j DefaultMessageRouter<&'g NetworkGraph<&'b L>, &'b L, &'a KeysManager>,
|
||||||
&'i SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>,
|
&'i SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>,
|
||||||
|
IgnoringMessageHandler,
|
||||||
IgnoringMessageHandler
|
IgnoringMessageHandler
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
//! [blinded paths]: crate::blinded_path::BlindedPath
|
//! [blinded paths]: crate::blinded_path::BlindedPath
|
||||||
//! [`OnionMessenger`]: self::messenger::OnionMessenger
|
//! [`OnionMessenger`]: self::messenger::OnionMessenger
|
||||||
|
|
||||||
|
pub mod async_payments;
|
||||||
pub mod messenger;
|
pub mod messenger;
|
||||||
pub mod offers;
|
pub mod offers;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
|
|
|
@ -16,6 +16,8 @@ use crate::offers::invoice_error::InvoiceError;
|
||||||
use crate::offers::invoice_request::InvoiceRequest;
|
use crate::offers::invoice_request::InvoiceRequest;
|
||||||
use crate::offers::invoice::Bolt12Invoice;
|
use crate::offers::invoice::Bolt12Invoice;
|
||||||
use crate::offers::parse::Bolt12ParseError;
|
use crate::offers::parse::Bolt12ParseError;
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
use crate::offers::static_invoice::StaticInvoice;
|
||||||
use crate::onion_message::packet::OnionMessageContents;
|
use crate::onion_message::packet::OnionMessageContents;
|
||||||
use crate::util::logger::Logger;
|
use crate::util::logger::Logger;
|
||||||
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
||||||
|
@ -29,6 +31,8 @@ use crate::prelude::*;
|
||||||
const INVOICE_REQUEST_TLV_TYPE: u64 = 64;
|
const INVOICE_REQUEST_TLV_TYPE: u64 = 64;
|
||||||
const INVOICE_TLV_TYPE: u64 = 66;
|
const INVOICE_TLV_TYPE: u64 = 66;
|
||||||
const INVOICE_ERROR_TLV_TYPE: u64 = 68;
|
const INVOICE_ERROR_TLV_TYPE: u64 = 68;
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
const STATIC_INVOICE_TLV_TYPE: u64 = 70;
|
||||||
|
|
||||||
/// A handler for an [`OnionMessage`] containing a BOLT 12 Offers message as its payload.
|
/// A handler for an [`OnionMessage`] containing a BOLT 12 Offers message as its payload.
|
||||||
///
|
///
|
||||||
|
@ -72,6 +76,10 @@ pub enum OffersMessage {
|
||||||
/// [`Refund`]: crate::offers::refund::Refund
|
/// [`Refund`]: crate::offers::refund::Refund
|
||||||
Invoice(Bolt12Invoice),
|
Invoice(Bolt12Invoice),
|
||||||
|
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
/// A [`StaticInvoice`] sent in response to an [`InvoiceRequest`].
|
||||||
|
StaticInvoice(StaticInvoice),
|
||||||
|
|
||||||
/// An error from handling an [`OffersMessage`].
|
/// An error from handling an [`OffersMessage`].
|
||||||
InvoiceError(InvoiceError),
|
InvoiceError(InvoiceError),
|
||||||
}
|
}
|
||||||
|
@ -80,7 +88,11 @@ impl OffersMessage {
|
||||||
/// Returns whether `tlv_type` corresponds to a TLV record for Offers.
|
/// Returns whether `tlv_type` corresponds to a TLV record for Offers.
|
||||||
pub fn is_known_type(tlv_type: u64) -> bool {
|
pub fn is_known_type(tlv_type: u64) -> bool {
|
||||||
match tlv_type {
|
match tlv_type {
|
||||||
INVOICE_REQUEST_TLV_TYPE | INVOICE_TLV_TYPE | INVOICE_ERROR_TLV_TYPE => true,
|
INVOICE_REQUEST_TLV_TYPE
|
||||||
|
| INVOICE_TLV_TYPE
|
||||||
|
| INVOICE_ERROR_TLV_TYPE => true,
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
STATIC_INVOICE_TLV_TYPE => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,6 +101,8 @@ impl OffersMessage {
|
||||||
match tlv_type {
|
match tlv_type {
|
||||||
INVOICE_REQUEST_TLV_TYPE => Ok(Self::InvoiceRequest(InvoiceRequest::try_from(bytes)?)),
|
INVOICE_REQUEST_TLV_TYPE => Ok(Self::InvoiceRequest(InvoiceRequest::try_from(bytes)?)),
|
||||||
INVOICE_TLV_TYPE => Ok(Self::Invoice(Bolt12Invoice::try_from(bytes)?)),
|
INVOICE_TLV_TYPE => Ok(Self::Invoice(Bolt12Invoice::try_from(bytes)?)),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
STATIC_INVOICE_TLV_TYPE => Ok(Self::StaticInvoice(StaticInvoice::try_from(bytes)?)),
|
||||||
_ => Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)),
|
_ => Err(Bolt12ParseError::Decode(DecodeError::InvalidValue)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +117,10 @@ impl fmt::Debug for OffersMessage {
|
||||||
OffersMessage::Invoice(message) => {
|
OffersMessage::Invoice(message) => {
|
||||||
write!(f, "{:?}", message.as_tlv_stream())
|
write!(f, "{:?}", message.as_tlv_stream())
|
||||||
}
|
}
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(message) => {
|
||||||
|
write!(f, "{:?}", message)
|
||||||
|
}
|
||||||
OffersMessage::InvoiceError(message) => {
|
OffersMessage::InvoiceError(message) => {
|
||||||
write!(f, "{:?}", message)
|
write!(f, "{:?}", message)
|
||||||
}
|
}
|
||||||
|
@ -115,6 +133,8 @@ impl OnionMessageContents for OffersMessage {
|
||||||
match self {
|
match self {
|
||||||
OffersMessage::InvoiceRequest(_) => INVOICE_REQUEST_TLV_TYPE,
|
OffersMessage::InvoiceRequest(_) => INVOICE_REQUEST_TLV_TYPE,
|
||||||
OffersMessage::Invoice(_) => INVOICE_TLV_TYPE,
|
OffersMessage::Invoice(_) => INVOICE_TLV_TYPE,
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(_) => STATIC_INVOICE_TLV_TYPE,
|
||||||
OffersMessage::InvoiceError(_) => INVOICE_ERROR_TLV_TYPE,
|
OffersMessage::InvoiceError(_) => INVOICE_ERROR_TLV_TYPE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +142,8 @@ impl OnionMessageContents for OffersMessage {
|
||||||
match &self {
|
match &self {
|
||||||
OffersMessage::InvoiceRequest(_) => "Invoice Request",
|
OffersMessage::InvoiceRequest(_) => "Invoice Request",
|
||||||
OffersMessage::Invoice(_) => "Invoice",
|
OffersMessage::Invoice(_) => "Invoice",
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(_) => "Static Invoice",
|
||||||
OffersMessage::InvoiceError(_) => "Invoice Error",
|
OffersMessage::InvoiceError(_) => "Invoice Error",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,6 +154,8 @@ impl Writeable for OffersMessage {
|
||||||
match self {
|
match self {
|
||||||
OffersMessage::InvoiceRequest(message) => message.write(w),
|
OffersMessage::InvoiceRequest(message) => message.write(w),
|
||||||
OffersMessage::Invoice(message) => message.write(w),
|
OffersMessage::Invoice(message) => message.write(w),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
OffersMessage::StaticInvoice(message) => message.write(w),
|
||||||
OffersMessage::InvoiceError(message) => message.write(w),
|
OffersMessage::InvoiceError(message) => message.write(w),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ use crate::blinded_path::message::{ForwardTlvs, ReceiveTlvs};
|
||||||
use crate::blinded_path::utils::Padding;
|
use crate::blinded_path::utils::Padding;
|
||||||
use crate::ln::msgs::DecodeError;
|
use crate::ln::msgs::DecodeError;
|
||||||
use crate::ln::onion_utils;
|
use crate::ln::onion_utils;
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
use super::async_payments::AsyncPaymentsMessage;
|
||||||
use super::messenger::CustomOnionMessageHandler;
|
use super::messenger::CustomOnionMessageHandler;
|
||||||
use super::offers::OffersMessage;
|
use super::offers::OffersMessage;
|
||||||
use crate::crypto::streams::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
|
use crate::crypto::streams::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
|
||||||
|
@ -128,6 +130,9 @@ pub(super) enum Payload<T: OnionMessageContents> {
|
||||||
pub enum ParsedOnionMessageContents<T: OnionMessageContents> {
|
pub enum ParsedOnionMessageContents<T: OnionMessageContents> {
|
||||||
/// A message related to BOLT 12 Offers.
|
/// A message related to BOLT 12 Offers.
|
||||||
Offers(OffersMessage),
|
Offers(OffersMessage),
|
||||||
|
/// A message related to async payments.
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
AsyncPayments(AsyncPaymentsMessage),
|
||||||
/// A custom onion message specified by the user.
|
/// A custom onion message specified by the user.
|
||||||
Custom(T),
|
Custom(T),
|
||||||
}
|
}
|
||||||
|
@ -139,12 +144,16 @@ impl<T: OnionMessageContents> OnionMessageContents for ParsedOnionMessageContent
|
||||||
fn tlv_type(&self) -> u64 {
|
fn tlv_type(&self) -> u64 {
|
||||||
match self {
|
match self {
|
||||||
&ParsedOnionMessageContents::Offers(ref msg) => msg.tlv_type(),
|
&ParsedOnionMessageContents::Offers(ref msg) => msg.tlv_type(),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
&ParsedOnionMessageContents::AsyncPayments(ref msg) => msg.tlv_type(),
|
||||||
&ParsedOnionMessageContents::Custom(ref msg) => msg.tlv_type(),
|
&ParsedOnionMessageContents::Custom(ref msg) => msg.tlv_type(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn msg_type(&self) -> &'static str {
|
fn msg_type(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
ParsedOnionMessageContents::Offers(ref msg) => msg.msg_type(),
|
ParsedOnionMessageContents::Offers(ref msg) => msg.msg_type(),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
ParsedOnionMessageContents::AsyncPayments(ref msg) => msg.msg_type(),
|
||||||
ParsedOnionMessageContents::Custom(ref msg) => msg.msg_type(),
|
ParsedOnionMessageContents::Custom(ref msg) => msg.msg_type(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +163,8 @@ impl<T: OnionMessageContents> Writeable for ParsedOnionMessageContents<T> {
|
||||||
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
|
||||||
match self {
|
match self {
|
||||||
ParsedOnionMessageContents::Offers(msg) => Ok(msg.write(w)?),
|
ParsedOnionMessageContents::Offers(msg) => Ok(msg.write(w)?),
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
ParsedOnionMessageContents::AsyncPayments(msg) => Ok(msg.write(w)?),
|
||||||
ParsedOnionMessageContents::Custom(msg) => Ok(msg.write(w)?),
|
ParsedOnionMessageContents::Custom(msg) => Ok(msg.write(w)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,6 +266,12 @@ for Payload<ParsedOnionMessageContents<<H as CustomOnionMessageHandler>::CustomM
|
||||||
message = Some(ParsedOnionMessageContents::Offers(msg));
|
message = Some(ParsedOnionMessageContents::Offers(msg));
|
||||||
Ok(true)
|
Ok(true)
|
||||||
},
|
},
|
||||||
|
#[cfg(async_payments)]
|
||||||
|
tlv_type if AsyncPaymentsMessage::is_known_type(tlv_type) => {
|
||||||
|
let msg = AsyncPaymentsMessage::read(msg_reader, tlv_type)?;
|
||||||
|
message = Some(ParsedOnionMessageContents::AsyncPayments(msg));
|
||||||
|
Ok(true)
|
||||||
|
},
|
||||||
_ => match handler.read_custom_message(msg_type, msg_reader)? {
|
_ => match handler.read_custom_message(msg_type, msg_reader)? {
|
||||||
Some(msg) => {
|
Some(msg) => {
|
||||||
message = Some(ParsedOnionMessageContents::Custom(msg));
|
message = Some(ParsedOnionMessageContents::Custom(msg));
|
||||||
|
|
|
@ -633,7 +633,7 @@ macro_rules! impl_writeable_msg {
|
||||||
$($crate::_init_tlv_field_var!($tlvfield, $fieldty);)*
|
$($crate::_init_tlv_field_var!($tlvfield, $fieldty);)*
|
||||||
$crate::decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*});
|
$crate::decode_tlv_stream!(r, {$(($type, $tlvfield, $fieldty)),*});
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
$($field),*,
|
$($field,)*
|
||||||
$($tlvfield),*
|
$($tlvfield),*
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1531,4 +1531,18 @@ mod tests {
|
||||||
fn simple_test_tlv_write() {
|
fn simple_test_tlv_write() {
|
||||||
do_simple_test_tlv_write().unwrap();
|
do_simple_test_tlv_write().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
|
struct EmptyMsg {}
|
||||||
|
impl_writeable_msg!(EmptyMsg, {}, {});
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn impl_writeable_msg_empty() {
|
||||||
|
let msg = EmptyMsg {};
|
||||||
|
let mut encoded_msg = msg.encode();
|
||||||
|
assert!(encoded_msg.is_empty());
|
||||||
|
let mut encoded_msg_stream = Cursor::new(&mut encoded_msg);
|
||||||
|
let decoded_msg: EmptyMsg = Readable::read(&mut encoded_msg_stream).unwrap();
|
||||||
|
assert_eq!(msg, decoded_msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue