Skip to content

Commit b5b4a08

Browse files
committed
Add inital implementation of persisted payment store
1 parent 6aa4a86 commit b5b4a08

File tree

6 files changed

+331
-190
lines changed

6 files changed

+331
-190
lines changed

src/event.rs

+69-56
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
hex_utils, ChannelManager, Config, Error, KeysManager, NetworkGraph, PaymentInfo,
3-
PaymentInfoStorage, PaymentStatus, Wallet,
2+
hex_utils, ChannelManager, Config, Error, KeysManager, NetworkGraph, PaymentDirection,
3+
PaymentInfo, PaymentInfoStorage, PaymentStatus, Wallet,
44
};
55

66
use crate::logger::{log_error, log_info, Logger};
@@ -18,7 +18,7 @@ use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer};
1818

1919
use bitcoin::secp256k1::Secp256k1;
2020
use rand::{thread_rng, Rng};
21-
use std::collections::{hash_map, VecDeque};
21+
use std::collections::VecDeque;
2222
use std::ops::Deref;
2323
use std::sync::{Arc, Condvar, Mutex};
2424
use std::time::Duration;
@@ -191,8 +191,7 @@ where
191191
channel_manager: Arc<ChannelManager>,
192192
network_graph: Arc<NetworkGraph>,
193193
keys_manager: Arc<KeysManager>,
194-
inbound_payments: Arc<PaymentInfoStorage>,
195-
outbound_payments: Arc<PaymentInfoStorage>,
194+
payment_store: Arc<PaymentInfoStorage<K>>,
196195
tokio_runtime: Arc<tokio::runtime::Runtime>,
197196
logger: L,
198197
_config: Arc<Config>,
@@ -206,18 +205,16 @@ where
206205
pub fn new(
207206
wallet: Arc<Wallet<bdk::database::SqliteDatabase>>, event_queue: Arc<EventQueue<K>>,
208207
channel_manager: Arc<ChannelManager>, network_graph: Arc<NetworkGraph>,
209-
keys_manager: Arc<KeysManager>, inbound_payments: Arc<PaymentInfoStorage>,
210-
outbound_payments: Arc<PaymentInfoStorage>, tokio_runtime: Arc<tokio::runtime::Runtime>,
211-
logger: L, _config: Arc<Config>,
208+
keys_manager: Arc<KeysManager>, payment_store: Arc<PaymentInfoStorage<K>>,
209+
tokio_runtime: Arc<tokio::runtime::Runtime>, logger: L, _config: Arc<Config>,
212210
) -> Self {
213211
Self {
214212
event_queue,
215213
wallet,
216214
channel_manager,
217215
network_graph,
218216
keys_manager,
219-
inbound_payments,
220-
outbound_payments,
217+
payment_store,
221218
logger,
222219
tokio_runtime,
223220
_config,
@@ -298,9 +295,25 @@ where
298295
via_channel_id: _,
299296
via_user_channel_id: _,
300297
} => {
298+
if let Some(info) = self.payment_store.get(&payment_hash) {
299+
if info.status == PaymentStatus::Succeeded {
300+
log_info!(
301+
self.logger,
302+
"Refused duplicate inbound payment from payment hash {} of {}msat",
303+
hex_utils::to_string(&payment_hash.0),
304+
amount_msat,
305+
);
306+
self.channel_manager.fail_htlc_backwards(&payment_hash);
307+
self.payment_store
308+
.set_status(&payment_hash, PaymentStatus::Failed)
309+
.expect("Failed to access payment store");
310+
return;
311+
}
312+
}
313+
301314
log_info!(
302315
self.logger,
303-
"Received payment from payment hash {} of {} msats",
316+
"Received payment from payment hash {} of {}msat",
304317
hex_utils::to_string(&payment_hash.0),
305318
amount_msat,
306319
);
@@ -326,7 +339,9 @@ where
326339
hex_utils::to_string(&payment_hash.0),
327340
);
328341
self.channel_manager.fail_htlc_backwards(&payment_hash);
329-
self.inbound_payments.lock().unwrap().remove(&payment_hash);
342+
self.payment_store
343+
.set_status(&payment_hash, PaymentStatus::Failed)
344+
.expect("Failed to access payment store");
330345
}
331346
}
332347
LdkEvent::PaymentClaimed {
@@ -337,7 +352,7 @@ where
337352
} => {
338353
log_info!(
339354
self.logger,
340-
"Claimed payment from payment hash {} of {} msats.",
355+
"Claimed payment from payment hash {} of {}msat.",
341356
hex_utils::to_string(&payment_hash.0),
342357
amount_msat,
343358
);
@@ -347,49 +362,50 @@ where
347362
}
348363
PaymentPurpose::SpontaneousPayment(preimage) => (Some(preimage), None),
349364
};
350-
let mut payments = self.inbound_payments.lock().unwrap();
351-
match payments.entry(payment_hash) {
352-
hash_map::Entry::Occupied(mut e) => {
353-
let payment = e.get_mut();
354-
payment.status = PaymentStatus::Succeeded;
355-
payment.preimage = payment_preimage;
356-
payment.secret = payment_secret;
357-
payment.amount_msat = Some(amount_msat);
358-
}
359-
hash_map::Entry::Vacant(e) => {
360-
e.insert(PaymentInfo {
365+
366+
let payment_info =
367+
if let Some(mut payment_info) = self.payment_store.get(&payment_hash) {
368+
payment_info.status = PaymentStatus::Succeeded;
369+
payment_info.preimage = payment_preimage;
370+
payment_info.secret = payment_secret;
371+
payment_info.amount_msat = Some(amount_msat);
372+
payment_info
373+
} else {
374+
PaymentInfo {
361375
preimage: payment_preimage,
376+
payment_hash,
362377
secret: payment_secret,
363-
status: PaymentStatus::Succeeded,
364378
amount_msat: Some(amount_msat),
365-
});
366-
}
367-
}
379+
direction: PaymentDirection::Inbound,
380+
status: PaymentStatus::Succeeded,
381+
}
382+
};
383+
384+
self.payment_store.insert(payment_info).expect("Failed to access payment store");
368385
self.event_queue
369386
.add_event(Event::PaymentReceived { payment_hash, amount_msat })
370387
.expect("Failed to push to event queue");
371388
}
372389
LdkEvent::PaymentSent { payment_preimage, payment_hash, fee_paid_msat, .. } => {
373-
let mut payments = self.outbound_payments.lock().unwrap();
374-
for (hash, payment) in payments.iter_mut() {
375-
if *hash == payment_hash {
376-
payment.preimage = Some(payment_preimage);
377-
payment.status = PaymentStatus::Succeeded;
378-
log_info!(
379-
self.logger,
380-
"Successfully sent payment of {} msats{} from \
381-
payment hash {:?} with preimage {:?}",
382-
payment.amount_msat.unwrap(),
383-
if let Some(fee) = fee_paid_msat {
384-
format!(" (fee {} msats)", fee)
385-
} else {
386-
"".to_string()
387-
},
388-
hex_utils::to_string(&payment_hash.0),
389-
hex_utils::to_string(&payment_preimage.0)
390-
);
391-
break;
392-
}
390+
if let Some(mut payment_info) = self.payment_store.get(&payment_hash) {
391+
payment_info.preimage = Some(payment_preimage);
392+
payment_info.status = PaymentStatus::Succeeded;
393+
self.payment_store
394+
.insert(payment_info.clone())
395+
.expect("Failed to access payment store");
396+
log_info!(
397+
self.logger,
398+
"Successfully sent payment of {}msat{} from \
399+
payment hash {:?} with preimage {:?}",
400+
payment_info.amount_msat.unwrap(),
401+
if let Some(fee) = fee_paid_msat {
402+
format!(" (fee {} msat)", fee)
403+
} else {
404+
"".to_string()
405+
},
406+
hex_utils::to_string(&payment_hash.0),
407+
hex_utils::to_string(&payment_preimage.0)
408+
);
393409
}
394410
self.event_queue
395411
.add_event(Event::PaymentSuccessful { payment_hash })
@@ -402,12 +418,9 @@ where
402418
hex_utils::to_string(&payment_hash.0)
403419
);
404420

405-
let mut payments = self.outbound_payments.lock().unwrap();
406-
if payments.contains_key(&payment_hash) {
407-
let payment = payments.get_mut(&payment_hash).unwrap();
408-
assert_eq!(payment.status, PaymentStatus::Pending);
409-
payment.status = PaymentStatus::Failed;
410-
}
421+
self.payment_store
422+
.set_status(&payment_hash, PaymentStatus::Failed)
423+
.expect("Failed to access payment store");
411424
self.event_queue
412425
.add_event(Event::PaymentFailed { payment_hash })
413426
.expect("Failed to push to event queue");
@@ -493,15 +506,15 @@ where
493506
if claim_from_onchain_tx {
494507
log_info!(
495508
self.logger,
496-
"Forwarded payment{}{}, earning {} msats in fees from claiming onchain.",
509+
"Forwarded payment{}{}, earning {}msat in fees from claiming onchain.",
497510
from_prev_str,
498511
to_next_str,
499512
fee_earned,
500513
);
501514
} else {
502515
log_info!(
503516
self.logger,
504-
"Forwarded payment{}{}, earning {} msats in fees.",
517+
"Forwarded payment{}{}, earning {}msat in fees.",
505518
from_prev_str,
506519
to_next_str,
507520
fee_earned,

src/io_utils.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use crate::payment_store::{PaymentInfo, PAYMENT_INFO_PERSISTENCE_PREFIX};
12
use crate::{Config, FilesystemLogger, NetworkGraph, Scorer, WALLET_KEYS_SEED_LEN};
23

34
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters};
4-
use lightning::util::ser::ReadableArgs;
5+
use lightning::util::ser::{Readable, ReadableArgs};
56

67
use rand::{thread_rng, RngCore};
78

@@ -60,3 +61,25 @@ pub(crate) fn read_scorer(
6061
}
6162
ProbabilisticScorer::new(params, network_graph, logger)
6263
}
64+
65+
pub(crate) fn read_payment_info(config: &Config) -> Vec<PaymentInfo> {
66+
let ldk_data_dir = format!("{}/ldk", config.storage_dir_path);
67+
let payment_store_path = format!("{}/{}", ldk_data_dir, PAYMENT_INFO_PERSISTENCE_PREFIX);
68+
let mut payments = Vec::new();
69+
70+
if let Ok(res) = fs::read_dir(payment_store_path) {
71+
for entry in res {
72+
if let Ok(entry) = entry {
73+
if entry.path().is_file() {
74+
if let Ok(mut f) = fs::File::open(entry.path()) {
75+
if let Ok(payment_info) = PaymentInfo::read(&mut f) {
76+
payments.push(payment_info);
77+
}
78+
}
79+
}
80+
}
81+
}
82+
}
83+
84+
payments
85+
}

0 commit comments

Comments
 (0)