13
13
14
14
use core:: ops:: Deref ;
15
15
use core:: time:: Duration ;
16
+ use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
16
17
17
- use bitcoin:: secp256k1;
18
+ use bitcoin:: block:: Header ;
19
+ use bitcoin:: constants:: ChainHash ;
20
+ use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 } ;
21
+ use bitcoin:: network:: Network ;
18
22
19
23
use crate :: blinded_path:: message:: { AsyncPaymentsContext , BlindedMessagePath , OffersContext } ;
20
24
use crate :: blinded_path:: payment:: { BlindedPaymentPath , PaymentContext } ;
21
25
use crate :: chain;
26
+ use crate :: chain:: transaction:: TransactionData ;
22
27
use crate :: ln:: channelmanager:: PaymentId ;
23
28
use crate :: offers:: invoice:: { Bolt12Invoice , DerivedSigningPubkey , InvoiceBuilder } ;
24
29
use crate :: offers:: invoice_error:: InvoiceError ;
@@ -33,6 +38,9 @@ use crate::onion_message::messenger::{Destination, MessageSendInstructions};
33
38
use crate :: onion_message:: offers:: OffersMessage ;
34
39
use crate :: sign:: NodeSigner ;
35
40
use crate :: types:: payment:: { PaymentHash , PaymentSecret } ;
41
+ use crate :: sign:: EntropySource ;
42
+ use crate :: sync:: Mutex ;
43
+ use crate :: ln:: inbound_payment;
36
44
37
45
#[ cfg( async_payments) ]
38
46
use {
@@ -55,7 +63,7 @@ pub trait Flow: chain::Listen {
55
63
fn verify_async_context ( & self , context : AsyncPaymentsContext ) -> Result < Option < PaymentId > , ( ) > ;
56
64
57
65
fn create_offer_builder < F > (
58
- & self , absolute_expiry : Option < Duration > , paths : F ,
66
+ & self , absolute_expiry : Option < Duration > , nonce : Option < Nonce > , paths : F ,
59
67
) -> Result < OfferBuilder < DerivedMetadata , secp256k1:: All > , Bolt12SemanticError >
60
68
where
61
69
F : Fn ( OffersContext ) -> Result < Vec < BlindedMessagePath > , ( ) > ;
@@ -87,7 +95,7 @@ pub trait Flow: chain::Listen {
87
95
F : Fn ( PaymentContext ) -> Result < Vec < BlindedPaymentPath > , ( ) > ;
88
96
89
97
fn create_invoice_from_invoice_request < NS : Deref , F > (
90
- self , signer : NS , invoice_request : VerifiedInvoiceRequest , payment_hash : PaymentHash , payment_paths : F ,
98
+ & self , signer : & NS , invoice_request : VerifiedInvoiceRequest , payment_hash : PaymentHash , payment_paths : F ,
91
99
) -> Result < Bolt12Invoice , InvoiceError >
92
100
where
93
101
NS :: Target : NodeSigner ,
@@ -124,7 +132,6 @@ pub trait Flow: chain::Listen {
124
132
& self ,
125
133
) -> Vec < ( OffersMessage , MessageSendInstructions ) > ;
126
134
127
- #[ cfg( async_payments) ]
128
135
fn get_and_clear_pending_async_messages (
129
136
& self ,
130
137
) -> Vec < ( AsyncPaymentsMessage , MessageSendInstructions ) > ;
@@ -133,4 +140,97 @@ pub trait Flow: chain::Listen {
133
140
fn get_and_clear_pending_dns_messages (
134
141
& self ,
135
142
) -> Vec < ( DNSResolverMessage , MessageSendInstructions ) > ;
143
+ }
144
+
145
+
146
+ pub struct OffersMessageFlow < ES : Deref >
147
+ where
148
+ ES :: Target : EntropySource ,
149
+ {
150
+ chain_hash : ChainHash ,
151
+
152
+ our_network_pubkey : PublicKey ,
153
+ highest_seen_timestamp : AtomicUsize ,
154
+ inbound_payment_key : inbound_payment:: ExpandedKey ,
155
+
156
+ secp_ctx : Secp256k1 < secp256k1:: All > ,
157
+ entropy_source : ES ,
158
+
159
+ #[ cfg( not( any( test, feature = "_test_utils" ) ) ) ]
160
+ pending_offers_messages : Mutex < Vec < ( OffersMessage , MessageSendInstructions ) > > ,
161
+ #[ cfg( any( test, feature = "_test_utils" ) ) ]
162
+ pub ( crate ) pending_offers_messages : Mutex < Vec < ( OffersMessage , MessageSendInstructions ) > > ,
163
+
164
+ pending_async_payments_messages : Mutex < Vec < ( AsyncPaymentsMessage , MessageSendInstructions ) > > ,
165
+
166
+ #[ cfg( feature = "dnssec" ) ]
167
+ pending_dns_onion_messages : Mutex < Vec < ( DNSResolverMessage , MessageSendInstructions ) > > ,
168
+ }
169
+
170
+ impl < ES : Deref > OffersMessageFlow < ES >
171
+ where
172
+ ES :: Target : EntropySource ,
173
+ {
174
+ /// Creates a new [`OffersMessageFlow`]
175
+ pub fn new (
176
+ network : Network , our_network_pubkey : PublicKey ,
177
+ current_timestamp : u32 , inbound_payment_key : inbound_payment:: ExpandedKey ,
178
+ entropy_source : ES ,
179
+ ) -> Self {
180
+ let mut secp_ctx = Secp256k1 :: new ( ) ;
181
+ secp_ctx. seeded_randomize ( & entropy_source. get_secure_random_bytes ( ) ) ;
182
+
183
+ Self {
184
+ chain_hash : ChainHash :: using_genesis_block ( network) ,
185
+
186
+ our_network_pubkey,
187
+ highest_seen_timestamp : AtomicUsize :: new ( current_timestamp as usize ) ,
188
+ inbound_payment_key,
189
+
190
+ secp_ctx,
191
+ entropy_source,
192
+
193
+ pending_offers_messages : Mutex :: new ( Vec :: new ( ) ) ,
194
+ pending_async_payments_messages : Mutex :: new ( Vec :: new ( ) ) ,
195
+ #[ cfg( feature = "dnssec" ) ]
196
+ pending_dns_onion_messages : Mutex :: new ( Vec :: new ( ) ) ,
197
+ }
198
+ }
199
+
200
+ /// Gets the node_id held by this OffersMessageFlow
201
+ pub fn get_our_node_id ( & self ) -> PublicKey {
202
+ self . our_network_pubkey
203
+ }
204
+
205
+ fn best_block_updated ( & self , header : & Header ) {
206
+ macro_rules! max_time {
207
+ ( $timestamp: expr) => {
208
+ loop {
209
+ // Update $timestamp to be the max of its current value and the block
210
+ // timestamp. This should keep us close to the current time without relying on
211
+ // having an explicit local time source.
212
+ // Just in case we end up in a race, we loop until we either successfully
213
+ // update $timestamp or decide we don't need to.
214
+ let old_serial = $timestamp. load( Ordering :: Acquire ) ;
215
+ if old_serial >= header. time as usize { break ; }
216
+ if $timestamp. compare_exchange( old_serial, header. time as usize , Ordering :: AcqRel , Ordering :: Relaxed ) . is_ok( ) {
217
+ break ;
218
+ }
219
+ }
220
+ }
221
+ }
222
+
223
+ max_time ! ( self . highest_seen_timestamp) ;
224
+ }
225
+ }
226
+
227
+ impl < ES : Deref > chain:: Listen for OffersMessageFlow < ES >
228
+ where
229
+ ES :: Target : EntropySource ,
230
+ {
231
+ fn filtered_block_connected ( & self , header : & Header , _txdata : & TransactionData , _height : u32 ) {
232
+ self . best_block_updated ( header) ;
233
+ }
234
+
235
+ fn block_disconnected ( & self , _header : & Header , _height : u32 ) { }
136
236
}
0 commit comments