From bedc2c64fcfe5fa5f85ded630e9ed2eb3c3651eb Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Thu, 7 Dec 2023 15:53:15 -0600 Subject: [PATCH] Require any Router also implements MessageRouter ChannelManager is parameterized by a Router in order to find routes when sending and retrying payments. For the offers flow, it needs to be able to construct blinded paths (e.g., in the offer and in reply paths). Instead of adding yet another parameter to ChannelManager, require that any Router also implements MessageRouter. Implement this for DefaultRouter by delegating to a DefaultMessageRouter. --- fuzz/src/chanmon_consistency.rs | 21 +++++++++++++++++- fuzz/src/full_stack.rs | 21 +++++++++++++++++- lightning/src/routing/router.rs | 38 ++++++++++++++++++++++++++------ lightning/src/util/test_utils.rs | 21 +++++++++++++++++- 4 files changed, 91 insertions(+), 10 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index f6549087..2c4552d4 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -30,6 +30,7 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{BlockHash, WPubkeyHash}; +use lightning::blinded_path::BlindedPath; use lightning::chain; use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, chainmonitor, channelmonitor, Confirm, Watch}; use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent}; @@ -46,6 +47,7 @@ use lightning::ln::script::ShutdownScript; use lightning::ln::functional_test_utils::*; use lightning::offers::invoice::UnsignedBolt12Invoice; use lightning::offers::invoice_request::UnsignedInvoiceRequest; +use lightning::onion_message::{Destination, MessageRouter, OnionMessagePath}; use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState}; use lightning::util::errors::APIError; use lightning::util::logger::Logger; @@ -56,7 +58,7 @@ use lightning::routing::router::{InFlightHtlcs, Path, Route, RouteHop, RoutePara use crate::utils::test_logger::{self, Output}; use crate::utils::test_persister::TestPersister; -use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1}; +use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1, self}; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::schnorr; @@ -101,6 +103,23 @@ impl Router for FuzzRouter { } } +impl MessageRouter for FuzzRouter { + fn find_path( + &self, _sender: PublicKey, _peers: Vec, _destination: Destination + ) -> Result { + unreachable!() + } + + fn create_blinded_paths< + ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + >( + &self, _recipient: PublicKey, _peers: Vec, _entropy_source: &ES, + _secp_ctx: &Secp256k1 + ) -> Result, ()> { + unreachable!() + } +} + pub struct TestBroadcaster {} impl BroadcasterInterface for TestBroadcaster { fn broadcast_transactions(&self, _txs: &[&Transaction]) { } diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 725f83af..9eb39b11 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -28,6 +28,7 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash}; +use lightning::blinded_path::BlindedPath; use lightning::chain; use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen}; use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator}; @@ -43,6 +44,7 @@ use lightning::ln::script::ShutdownScript; use lightning::ln::functional_test_utils::*; use lightning::offers::invoice::UnsignedBolt12Invoice; use lightning::offers::invoice_request::UnsignedInvoiceRequest; +use lightning::onion_message::{Destination, MessageRouter, OnionMessagePath}; use lightning::routing::gossip::{P2PGossipSync, NetworkGraph}; use lightning::routing::utxo::UtxoLookup; use lightning::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router}; @@ -55,7 +57,7 @@ use lightning::util::ser::{ReadableArgs, Writeable}; use crate::utils::test_logger; use crate::utils::test_persister::TestPersister; -use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1}; +use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1, self}; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::schnorr; @@ -144,6 +146,23 @@ impl Router for FuzzRouter { } } +impl MessageRouter for FuzzRouter { + fn find_path( + &self, _sender: PublicKey, _peers: Vec, _destination: Destination + ) -> Result { + unreachable!() + } + + fn create_blinded_paths< + ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + >( + &self, _recipient: PublicKey, _peers: Vec, _entropy_source: &ES, + _secp_ctx: &Secp256k1 + ) -> Result, ()> { + unreachable!() + } +} + struct TestBroadcaster { txn_broadcasted: Mutex>, } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 7bd1cebc..42eeb6cb 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -9,7 +9,7 @@ //! The router finds paths within a [`NetworkGraph`] for a payment. -use bitcoin::secp256k1::PublicKey; +use bitcoin::secp256k1::{PublicKey, Secp256k1, self}; use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; @@ -19,8 +19,10 @@ use crate::ln::channelmanager::{ChannelDetails, PaymentId}; use crate::ln::features::{Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures}; use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT}; use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice}; +use crate::onion_message::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees}; use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; +use crate::sign::EntropySource; use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; use crate::util::logger::{Level, Logger}; use crate::util::chacha20::ChaCha20; @@ -33,7 +35,7 @@ use core::{cmp, fmt}; use core::ops::Deref; /// A [`Router`] implemented using [`find_route`]. -pub struct DefaultRouter>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where +pub struct DefaultRouter> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, { @@ -41,21 +43,23 @@ pub struct DefaultRouter>, L: Deref, S: Deref, logger: L, random_seed_bytes: Mutex<[u8; 32]>, scorer: S, - score_params: SP + score_params: SP, + message_router: DefaultMessageRouter, } -impl>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where +impl> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> DefaultRouter where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, { /// Creates a new router. pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S, score_params: SP) -> Self { let random_seed_bytes = Mutex::new(random_seed_bytes); - Self { network_graph, logger, random_seed_bytes, scorer, score_params } + let message_router = DefaultMessageRouter::new(network_graph.clone()); + Self { network_graph, logger, random_seed_bytes, scorer, score_params, message_router } } } -impl< G: Deref>, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where +impl> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> Router for DefaultRouter where L::Target: Logger, S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, { @@ -80,8 +84,28 @@ impl< G: Deref>, L: Deref, S: Deref, SP: Sized, Sc: Sco } } +impl< G: Deref> + Clone, L: Deref, S: Deref, SP: Sized, Sc: ScoreLookUp> MessageRouter for DefaultRouter where + L::Target: Logger, + S::Target: for <'a> LockableScore<'a, ScoreLookUp = Sc>, +{ + fn find_path( + &self, sender: PublicKey, peers: Vec, destination: Destination + ) -> Result { + self.message_router.find_path(sender, peers, destination) + } + + fn create_blinded_paths< + ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + >( + &self, recipient: PublicKey, peers: Vec, entropy_source: &ES, + secp_ctx: &Secp256k1 + ) -> Result, ()> { + self.message_router.create_blinded_paths(recipient, peers, entropy_source, secp_ctx) + } +} + /// A trait defining behavior for routing a payment. -pub trait Router { +pub trait Router: MessageRouter { /// Finds a [`Route`] for a payment between the given `payer` and a payee. /// /// The `payee` and the payment's value are given in [`RouteParameters::payment_params`] diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 805806dc..3954088f 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -7,6 +7,7 @@ // You may not use this file except in accordance with one or both of these // licenses. +use crate::blinded_path::BlindedPath; use crate::chain; use crate::chain::WatchedOutput; use crate::chain::chaininterface; @@ -30,6 +31,7 @@ use crate::ln::msgs::LightningError; use crate::ln::script::ShutdownScript; use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::invoice_request::UnsignedInvoiceRequest; +use crate::onion_message::{Destination, MessageRouter, OnionMessagePath}; use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees}; use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult}; use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParameters, RouteHintHop, Router, ScorerAccountingForInFlightHtlcs}; @@ -51,7 +53,7 @@ use bitcoin::network::constants::Network; use bitcoin::hash_types::{BlockHash, Txid}; use bitcoin::sighash::{SighashCache, EcdsaSighashType}; -use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey}; +use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, self}; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::schnorr; @@ -191,6 +193,23 @@ impl<'a> Router for TestRouter<'a> { } } +impl<'a> MessageRouter for TestRouter<'a> { + fn find_path( + &self, _sender: PublicKey, _peers: Vec, _destination: Destination + ) -> Result { + unreachable!() + } + + fn create_blinded_paths< + ES: EntropySource + ?Sized, T: secp256k1::Signing + secp256k1::Verification + >( + &self, _recipient: PublicKey, _peers: Vec, _entropy_source: &ES, + _secp_ctx: &Secp256k1 + ) -> Result, ()> { + unreachable!() + } +} + impl<'a> Drop for TestRouter<'a> { fn drop(&mut self) { #[cfg(feature = "std")] { -- 2.30.2