Skip to content

Commit e5c3a5c

Browse files
committed
kvstore static invoices
1 parent 98c2551 commit e5c3a5c

File tree

3 files changed

+59
-21
lines changed

3 files changed

+59
-21
lines changed

src/event.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,9 +1505,16 @@ where
15051505
recipient_id,
15061506
invoice_persisted_path,
15071507
} => {
1508-
self.static_invoice_store
1508+
match self
1509+
.static_invoice_store
15091510
.handle_persist_static_invoice(invoice, invoice_slot, recipient_id)
1510-
.await;
1511+
.await
1512+
{
1513+
Ok(_) => {},
1514+
Err(e) => {
1515+
log_error!(self.logger, "Failed to persist static invoice: {}", e);
1516+
},
1517+
};
15111518

15121519
self.channel_manager.static_invoice_persisted(invoice_persisted_path);
15131520
},
@@ -1517,13 +1524,18 @@ where
15171524
.handle_static_invoice_requested(recipient_id, invoice_slot)
15181525
.await;
15191526

1520-
if let Some(invoice) = invoice {
1521-
match self.channel_manager.send_static_invoice(invoice, reply_path) {
1522-
Ok(()) => {},
1523-
Err(_) => {
1527+
match invoice {
1528+
Ok(Some(invoice)) => {
1529+
if let Err(_) =
1530+
self.channel_manager.send_static_invoice(invoice, reply_path)
1531+
{
15241532
log_error!(self.logger, "Failed to send static invoice");
1525-
},
1526-
}
1533+
}
1534+
},
1535+
Ok(None) => {},
1536+
Err(e) => {
1537+
log_error!(self.logger, "Failed to retrieve static invoice: {}", e);
1538+
},
15271539
}
15281540
},
15291541
LdkEvent::FundingTransactionReadyForSigning { .. } => {

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ impl Node {
501501
Arc::clone(&self.logger),
502502
));
503503

504-
let static_invoice_store = StaticInvoiceStore::new();
504+
let static_invoice_store = StaticInvoiceStore::new(Arc::clone(&self.kv_store));
505505

506506
let event_handler = Arc::new(EventHandler::new(
507507
Arc::clone(&self.event_queue),

src/static_invoice_store.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,54 @@
1-
use std::{collections::HashMap, sync::Mutex};
2-
3-
use lightning::offers::static_invoice::StaticInvoice;
1+
use crate::{hex_utils, types::DynStore};
2+
use bitcoin::hashes::{sha256, Hash};
3+
use lightning::{offers::static_invoice::StaticInvoice, util::ser::Writeable};
4+
use std::sync::Arc;
45

56
pub(crate) struct StaticInvoiceStore {
6-
pub static_invoices: Mutex<HashMap<(Vec<u8>, u16), StaticInvoice>>,
7+
kv_store: Arc<DynStore>,
78
}
89

910
impl StaticInvoiceStore {
10-
pub(crate) fn new() -> Self {
11-
Self { static_invoices: Mutex::new(HashMap::new()) }
11+
// Static invoices are stored at "static_invoices/<sha256(recipient_id)>/<invoice_slot>".
12+
//
13+
// Example:
14+
// static_invoices/039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81/0000
15+
const PRIMARY_NAMESPACE: &str = "static_invoices";
16+
17+
pub(crate) fn new(kv_store: Arc<DynStore>) -> Self {
18+
Self { kv_store }
1219
}
1320

1421
pub(crate) async fn handle_static_invoice_requested(
1522
&self, recipient_id: Vec<u8>, invoice_slot: u16,
16-
) -> Option<StaticInvoice> {
17-
let map = self.static_invoices.lock().unwrap();
23+
) -> Result<Option<StaticInvoice>, lightning::io::Error> {
24+
let (secondary_namespace, key) = Self::get_storage_location(invoice_slot, recipient_id);
1825

19-
map.get(&(recipient_id.clone(), invoice_slot)).cloned()
26+
self.kv_store.read(Self::PRIMARY_NAMESPACE, &secondary_namespace, &key).and_then(|data| {
27+
data.try_into().map(Some).map_err(|e| {
28+
lightning::io::Error::new(
29+
lightning::io::ErrorKind::InvalidData,
30+
format!("Failed to parse static invoice: {:?}", e),
31+
)
32+
})
33+
})
2034
}
2135

2236
pub(crate) async fn handle_persist_static_invoice(
2337
&self, invoice: StaticInvoice, invoice_slot: u16, recipient_id: Vec<u8>,
24-
) {
25-
let mut map = self.static_invoices.lock().unwrap();
26-
map.insert((recipient_id, invoice_slot), invoice);
38+
) -> Result<(), lightning::io::Error> {
39+
let (secondary_namespace, key) = Self::get_storage_location(invoice_slot, recipient_id);
40+
41+
let mut buf = Vec::new();
42+
invoice.write(&mut buf)?;
43+
44+
self.kv_store.write(Self::PRIMARY_NAMESPACE, &secondary_namespace, &key, buf)
45+
}
46+
47+
fn get_storage_location(invoice_slot: u16, recipient_id: Vec<u8>) -> (String, String) {
48+
let hash = sha256::Hash::hash(&recipient_id).to_byte_array();
49+
let secondary_namespace = hex_utils::to_string(&hash);
50+
51+
let key = hex_utils::to_string(&invoice_slot.to_be_bytes());
52+
(secondary_namespace, key)
2753
}
2854
}

0 commit comments

Comments
 (0)