Skip to content

Introduce Flow utilities and OffersMessageFlow implementation #3639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions lightning-background-processor/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1081,11 +1081,14 @@ mod tests {
IgnoringMessageHandler, MessageHandler, PeerManager, SocketDescriptor,
};
use lightning::ln::types::ChannelId;
use lightning::offers::flow::OffersMessageFlow;
use lightning::onion_message::messenger::{DefaultMessageRouter, OnionMessenger};
use lightning::routing::gossip::{NetworkGraph, P2PGossipSync};
use lightning::routing::router::{CandidateRouteHop, DefaultRouter, Path, RouteHop};
use lightning::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp, ScoreUpdate};
use lightning::sign::{ChangeDestinationSource, InMemorySigner, KeysManager};
use lightning::sign::{
ChangeDestinationSource, InMemorySigner, KeysManager, NodeSigner, Recipient,
};
use lightning::types::features::{ChannelFeatures, NodeFeatures};
use lightning::types::payment::PaymentHash;
use lightning::util::config::UserConfig;
@@ -1557,6 +1560,21 @@ mod tests {
network_graph.clone(),
Arc::clone(&keys_manager),
));
let best_block = BestBlock::from_network(network);
let params = ChainParameters { network, best_block };
let chain_hash = ChainHash::using_genesis_block(params.network);

let flow = OffersMessageFlow::new(
chain_hash,
params.best_block,
keys_manager.get_node_id(Recipient::Node).unwrap(),
genesis_block.header.time,
keys_manager.get_inbound_payment_key(),
keys_manager.clone(),
msg_router.clone(),
router.clone(),
);

let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Bitcoin));
let kv_store =
Arc::new(FilesystemStore::new(format!("{}_persister_{}", &persist_dir, i).into()));
@@ -1569,14 +1587,14 @@ mod tests {
fee_estimator.clone(),
kv_store.clone(),
));
let best_block = BestBlock::from_network(network);
let params = ChainParameters { network, best_block };

let manager = Arc::new(ChannelManager::new(
fee_estimator.clone(),
chain_monitor.clone(),
tx_broadcaster.clone(),
router.clone(),
msg_router.clone(),
flow,
logger.clone(),
keys_manager.clone(),
keys_manager.clone(),
22 changes: 19 additions & 3 deletions lightning-liquidity/tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,8 @@
#![allow(unused_macros)]

use lightning::chain::Filter;
use lightning::sign::EntropySource;
use lightning::offers::flow::OffersMessageFlow;
use lightning::sign::{EntropySource, NodeSigner, Recipient};

use bitcoin::blockdata::constants::{genesis_block, ChainHash};
use bitcoin::blockdata::transaction::Transaction;
@@ -421,6 +422,22 @@ pub(crate) fn create_liquidity_node(
));
let msg_router =
Arc::new(DefaultMessageRouter::new(Arc::clone(&network_graph), Arc::clone(&keys_manager)));

let best_block = BestBlock::from_network(network);
let chain_params = ChainParameters { network, best_block };
let chain_hash = ChainHash::using_genesis_block(chain_params.network);

let flow = OffersMessageFlow::new(
chain_hash,
chain_params.best_block,
keys_manager.get_node_id(Recipient::Node).unwrap(),
genesis_block.header.time,
keys_manager.get_inbound_payment_key(),
keys_manager.clone(),
msg_router.clone(),
router.clone(),
);

let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Bitcoin));
let kv_store =
Arc::new(FilesystemStore::new(format!("{}_persister_{}", &persist_dir, i).into()));
@@ -431,14 +448,13 @@ pub(crate) fn create_liquidity_node(
fee_estimator.clone(),
kv_store.clone(),
));
let best_block = BestBlock::from_network(network);
let chain_params = ChainParameters { network, best_block };
let channel_manager = Arc::new(ChannelManager::new(
fee_estimator.clone(),
chain_monitor.clone(),
tx_broadcaster.clone(),
router.clone(),
msg_router.clone(),
flow,
logger.clone(),
keys_manager.clone(),
keys_manager.clone(),
524 changes: 80 additions & 444 deletions lightning/src/ln/channelmanager.rs

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions lightning/src/ln/functional_test_utils.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ use crate::chain::transaction::OutPoint;
use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, PaidBolt12Invoice, PathFailure, PaymentFailureReason, PaymentPurpose};
use crate::events::bump_transaction::{BumpTransactionEvent, BumpTransactionEventHandler, Wallet, WalletSource};
use crate::ln::types::ChannelId;
use crate::offers::flow::OffersMessageFlow;
use crate::types::payment::{PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::channelmanager::{AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA};
use crate::types::features::InitFeatures;
@@ -27,7 +28,7 @@ use crate::onion_message::messenger::OnionMessenger;
use crate::ln::onion_utils::LocalHTLCFailureReason;
use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate};
use crate::routing::router::{self, PaymentParameters, Route, RouteParameters};
use crate::sign::{EntropySource, RandomBytes};
use crate::sign::{EntropySource, NodeSigner, RandomBytes, Recipient};
use crate::util::config::{MaxDustHTLCExposure, UserConfig};
use crate::util::logger::Logger;
use crate::util::scid_utils;
@@ -37,6 +38,7 @@ use crate::util::test_utils;
use crate::util::test_utils::{TestChainMonitor, TestScorer, TestKeysInterface};
use crate::util::ser::{ReadableArgs, Writeable};

use bitcoin::constants::ChainHash;
use bitcoin::{Weight, WPubkeyHash};
use bitcoin::amount::Amount;
use bitcoin::block::{Block, Header, Version as BlockVersion};
@@ -3383,7 +3385,17 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>
network,
best_block: BestBlock::from_network(network),
};
let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, &cfgs[i].router, &cfgs[i].message_router, cfgs[i].logger, cfgs[i].keys_manager,
let chain_hash = ChainHash::using_genesis_block(params.network);
let our_network_pubkey = cfgs[i].keys_manager.get_node_id(Recipient::Node).unwrap();
let expanded_inbound_key = cfgs[i].keys_manager.get_inbound_payment_key();

let flow = OffersMessageFlow::new(
chain_hash, params.best_block, our_network_pubkey,
genesis_block.header.time, expanded_inbound_key,
cfgs[i].keys_manager, &cfgs[i].message_router, &cfgs[i].router
);

let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, &cfgs[i].router, &cfgs[i].message_router, flow, cfgs[i].logger, cfgs[i].keys_manager,
cfgs[i].keys_manager, cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { test_default_channel_config() }, params, genesis_block.header.time);
chanmgrs.push(node);
}
4 changes: 2 additions & 2 deletions lightning/src/ln/inbound_payment.rs
Original file line number Diff line number Diff line change
@@ -194,7 +194,7 @@ pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment
}

#[cfg(async_payments)]
pub(super) fn create_for_spontaneous_payment(
pub(crate) fn create_for_spontaneous_payment(
keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32,
current_time: u64, min_final_cltv_expiry_delta: Option<u16>
) -> Result<PaymentSecret, ()> {
@@ -213,7 +213,7 @@ pub(super) fn create_for_spontaneous_payment(
Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
}

pub(super) fn calculate_absolute_expiry(highest_seen_timestamp: u64, invoice_expiry_delta_secs: u32) -> u64 {
pub(crate) fn calculate_absolute_expiry(highest_seen_timestamp: u64, invoice_expiry_delta_secs: u32) -> u64 {
// We assume that highest_seen_timestamp is pretty close to the current time - it's updated when
// we receive a new block with the maximum time we've seen in a header. It should never be more
// than two hours in the future. Thus, we add two hours here as a buffer to ensure we
14 changes: 7 additions & 7 deletions lightning/src/ln/offers_tests.rs
Original file line number Diff line number Diff line change
@@ -1400,7 +1400,7 @@ fn fails_authentication_when_handling_invoice_request() {
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);

connect_peers(david, alice);
match &mut david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
match &mut david.node.flow.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::Node(alice_id),
_ => panic!(),
@@ -1425,7 +1425,7 @@ fn fails_authentication_when_handling_invoice_request() {
.unwrap();
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);

match &mut david.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
match &mut david.node.flow.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::BlindedPath(invalid_path),
_ => panic!(),
@@ -1505,7 +1505,7 @@ fn fails_authentication_when_handling_invoice_for_offer() {

// Don't send the invoice request, but grab its reply path to use with a different request.
let invalid_reply_path = {
let mut pending_offers_messages = david.node.pending_offers_messages.lock().unwrap();
let mut pending_offers_messages = david.node.flow.pending_offers_messages.lock().unwrap();
let pending_invoice_request = pending_offers_messages.pop().unwrap();
pending_offers_messages.clear();
match pending_invoice_request.1 {
@@ -1522,7 +1522,7 @@ fn fails_authentication_when_handling_invoice_for_offer() {
// Swap out the reply path to force authentication to fail when handling the invoice since it
// will be sent over the wrong blinded path.
{
let mut pending_offers_messages = david.node.pending_offers_messages.lock().unwrap();
let mut pending_offers_messages = david.node.flow.pending_offers_messages.lock().unwrap();
let mut pending_invoice_request = pending_offers_messages.first_mut().unwrap();
match &mut pending_invoice_request.1 {
MessageSendInstructions::WithSpecifiedReplyPath { reply_path, .. } =>
@@ -1609,7 +1609,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {
let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();

connect_peers(david, alice);
match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
match &mut alice.node.flow.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::Node(david_id),
_ => panic!(),
@@ -1640,7 +1640,7 @@ fn fails_authentication_when_handling_invoice_for_refund() {

let expected_invoice = alice.node.request_refund_payment(&refund).unwrap();

match &mut alice.node.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
match &mut alice.node.flow.pending_offers_messages.lock().unwrap().first_mut().unwrap().1 {
MessageSendInstructions::WithSpecifiedReplyPath { destination, .. } =>
*destination = Destination::BlindedPath(invalid_path),
_ => panic!(),
@@ -2231,7 +2231,7 @@ fn fails_paying_invoice_with_unknown_required_features() {
destination: Destination::BlindedPath(reply_path),
};
let message = OffersMessage::Invoice(invoice);
alice.node.pending_offers_messages.lock().unwrap().push((message, instructions));
alice.node.flow.pending_offers_messages.lock().unwrap().push((message, instructions));

let onion_message = alice.onion_messenger.next_onion_message_for_peer(charlie_id).unwrap();
charlie.onion_messenger.handle_onion_message(alice_id, &onion_message);
1,018 changes: 1,018 additions & 0 deletions lightning/src/offers/flow.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lightning/src/offers/mod.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
#[macro_use]
pub mod offer;
pub mod flow;

pub mod invoice;
pub mod invoice_error;