Skip to content

Commit e69aaaa

Browse files
committed
Introduce OffersMessageFlow
1 parent abfcc5b commit e69aaaa

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

lightning/src/offers/flow.rs

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// This file is Copyright its original authors, visible in version control
2+
// history.
3+
//
4+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7+
// You may not use this file except in accordance with one or both of these
8+
// licenses.
9+
10+
//! Provides data structures and functions for creating and managing Offers messages,
11+
//! facilitating communication, and handling Bolt12 messages and payments.
12+
13+
use core::ops::Deref;
14+
use core::sync::atomic::{AtomicUsize, Ordering};
15+
use core::time::Duration;
16+
17+
use bitcoin::block::Header;
18+
use bitcoin::constants::ChainHash;
19+
use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
20+
21+
#[allow(unused_imports)]
22+
use crate::prelude::*;
23+
24+
use crate::chain::BestBlock;
25+
use crate::ln::inbound_payment;
26+
use crate::onion_message::async_payments::AsyncPaymentsMessage;
27+
use crate::onion_message::messenger::{MessageRouter, MessageSendInstructions};
28+
use crate::onion_message::offers::OffersMessage;
29+
use crate::sync::{Mutex, RwLock};
30+
31+
#[cfg(feature = "dnssec")]
32+
use crate::onion_message::dns_resolution::DNSResolverMessage;
33+
34+
/// A Bolt12 Offers code and flow utility provider, which facilitates utilities for
35+
/// Bolt12 builder generation, and Onion message handling.
36+
///
37+
/// [`OffersMessageFlow`] is parameterized by following components to achieve this.
38+
///
39+
/// - [`MessageRouter`] for finding message paths when initiating and retrying onion messages
40+
pub struct OffersMessageFlow<MR: Deref>
41+
where
42+
MR::Target: MessageRouter,
43+
{
44+
chain_hash: ChainHash,
45+
best_block: RwLock<BestBlock>,
46+
47+
our_network_pubkey: PublicKey,
48+
highest_seen_timestamp: AtomicUsize,
49+
inbound_payment_key: inbound_payment::ExpandedKey,
50+
51+
secp_ctx: Secp256k1<secp256k1::All>,
52+
message_router: MR,
53+
54+
#[cfg(not(any(test, feature = "_test_utils")))]
55+
pending_offers_messages: Mutex<Vec<(OffersMessage, MessageSendInstructions)>>,
56+
#[cfg(any(test, feature = "_test_utils"))]
57+
pub(crate) pending_offers_messages: Mutex<Vec<(OffersMessage, MessageSendInstructions)>>,
58+
59+
pending_async_payments_messages: Mutex<Vec<(AsyncPaymentsMessage, MessageSendInstructions)>>,
60+
61+
#[cfg(feature = "dnssec")]
62+
pending_dns_onion_messages: Mutex<Vec<(DNSResolverMessage, MessageSendInstructions)>>,
63+
}
64+
65+
impl<MR: Deref> OffersMessageFlow<MR>
66+
where
67+
MR::Target: MessageRouter,
68+
{
69+
/// Creates a new [`OffersMessageFlow`]
70+
pub fn new(
71+
chain_hash: ChainHash, best_block: BestBlock, our_network_pubkey: PublicKey,
72+
current_timestamp: u32, inbound_payment_key: inbound_payment::ExpandedKey,
73+
secp_ctx: Secp256k1<secp256k1::All>, message_router: MR,
74+
) -> Self {
75+
Self {
76+
chain_hash,
77+
best_block: RwLock::new(best_block),
78+
79+
our_network_pubkey,
80+
highest_seen_timestamp: AtomicUsize::new(current_timestamp as usize),
81+
inbound_payment_key,
82+
83+
secp_ctx,
84+
message_router,
85+
86+
pending_offers_messages: Mutex::new(Vec::new()),
87+
pending_async_payments_messages: Mutex::new(Vec::new()),
88+
#[cfg(feature = "dnssec")]
89+
pending_dns_onion_messages: Mutex::new(Vec::new()),
90+
}
91+
}
92+
93+
/// Gets the node_id held by this [`OffersMessageFlow`]`
94+
pub fn get_our_node_id(&self) -> PublicKey {
95+
self.our_network_pubkey
96+
}
97+
98+
fn duration_since_epoch(&self) -> Duration {
99+
#[cfg(not(feature = "std"))]
100+
let now = Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64);
101+
#[cfg(feature = "std")]
102+
let now = std::time::SystemTime::now()
103+
.duration_since(std::time::SystemTime::UNIX_EPOCH)
104+
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
105+
now
106+
}
107+
108+
pub(crate) fn best_block_updated(&self, header: &Header) {
109+
macro_rules! max_time {
110+
($timestamp: expr) => {
111+
loop {
112+
// Update $timestamp to be the max of its current value and the block
113+
// timestamp. This should keep us close to the current time without relying on
114+
// having an explicit local time source.
115+
// Just in case we end up in a race, we loop until we either successfully
116+
// update $timestamp or decide we don't need to.
117+
let old_serial = $timestamp.load(Ordering::Acquire);
118+
if old_serial >= header.time as usize {
119+
break;
120+
}
121+
if $timestamp
122+
.compare_exchange(
123+
old_serial,
124+
header.time as usize,
125+
Ordering::AcqRel,
126+
Ordering::Relaxed,
127+
)
128+
.is_ok()
129+
{
130+
break;
131+
}
132+
}
133+
};
134+
}
135+
136+
max_time!(self.highest_seen_timestamp);
137+
}
138+
}

lightning/src/offers/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
1515
#[macro_use]
1616
pub mod offer;
17+
pub mod flow;
1718

1819
pub mod invoice;
1920
pub mod invoice_error;

0 commit comments

Comments
 (0)