Skip to content

Commit 0f1d66c

Browse files
authored
Merge pull request #635 from joostjager/always-online-fwd-inv-req
Update static invoice store for invoice requests
2 parents e8b2513 + efbef4c commit 0f1d66c

File tree

6 files changed

+105
-43
lines changed

6 files changed

+105
-43
lines changed

Cargo.toml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,17 @@ default = []
5252
#lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
5353
#lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
5454

55-
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["std"] }
56-
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
57-
lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["std"] }
58-
lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
59-
lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
60-
lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
61-
lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
62-
lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["rest-client", "rpc-client", "tokio"] }
63-
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["esplora-async-https", "electrum-rustls-ring", "time"] }
64-
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
65-
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
55+
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["std"] }
56+
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
57+
lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["std"] }
58+
lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
59+
lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
60+
lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
61+
lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
62+
lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["rest-client", "rpc-client", "tokio"] }
63+
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["esplora-async-https", "electrum-rustls-ring", "time"] }
64+
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
65+
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
6666

6767
#lightning = { path = "../rust-lightning/lightning", features = ["std"] }
6868
#lightning-types = { path = "../rust-lightning/lightning-types" }
@@ -109,7 +109,7 @@ winapi = { version = "0.3", features = ["winbase"] }
109109
[dev-dependencies]
110110
#lightning = { version = "0.1.0", features = ["std", "_test_utils"] }
111111
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["std", "_test_utils"] }
112-
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["std", "_test_utils"] }
112+
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["std", "_test_utils"] }
113113
#lightning = { path = "../rust-lightning/lightning", features = ["std", "_test_utils"] }
114114
proptest = "1.0.0"
115115
regex = "1.5.6"

src/builder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,10 @@ fn build_with_store_internal(
13781378
100;
13791379
}
13801380

1381+
if config.async_payment_services_enabled {
1382+
user_config.accept_forwards_to_priv_channels = true;
1383+
}
1384+
13811385
let message_router =
13821386
Arc::new(MessageRouter::new(Arc::clone(&network_graph), Arc::clone(&keys_manager)));
13831387

src/event.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,13 +1500,19 @@ where
15001500

15011501
LdkEvent::PersistStaticInvoice {
15021502
invoice,
1503+
invoice_request_path,
15031504
invoice_slot,
15041505
recipient_id,
15051506
invoice_persisted_path,
15061507
} => {
15071508
if let Some(store) = self.static_invoice_store.as_ref() {
15081509
match store
1509-
.handle_persist_static_invoice(invoice, invoice_slot, recipient_id)
1510+
.handle_persist_static_invoice(
1511+
invoice,
1512+
invoice_request_path,
1513+
invoice_slot,
1514+
recipient_id,
1515+
)
15101516
.await
15111517
{
15121518
Ok(_) => {
@@ -1519,16 +1525,24 @@ where
15191525
};
15201526
}
15211527
},
1522-
LdkEvent::StaticInvoiceRequested { recipient_id, invoice_slot, reply_path } => {
1528+
LdkEvent::StaticInvoiceRequested {
1529+
recipient_id,
1530+
invoice_slot,
1531+
reply_path,
1532+
invoice_request,
1533+
} => {
15231534
if let Some(store) = self.static_invoice_store.as_ref() {
15241535
let invoice =
15251536
store.handle_static_invoice_requested(&recipient_id, invoice_slot).await;
15261537

15271538
match invoice {
1528-
Ok(Some(invoice)) => {
1529-
if let Err(e) =
1530-
self.channel_manager.send_static_invoice(invoice, reply_path)
1531-
{
1539+
Ok(Some((invoice, invoice_request_path))) => {
1540+
if let Err(e) = self.channel_manager.respond_to_static_invoice_request(
1541+
invoice,
1542+
reply_path,
1543+
invoice_request,
1544+
invoice_request_path,
1545+
) {
15321546
log_error!(self.logger, "Failed to send static invoice: {:?}", e);
15331547
}
15341548
},

src/payment/asynchronous/static_invoice_store.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,23 @@ use crate::types::DynStore;
1515
use bitcoin::hashes::sha256::Hash as Sha256;
1616
use bitcoin::hashes::Hash;
1717

18-
use lightning::{offers::static_invoice::StaticInvoice, util::ser::Writeable};
18+
use lightning::blinded_path::message::BlindedMessagePath;
19+
use lightning::impl_writeable_tlv_based;
20+
use lightning::{offers::static_invoice::StaticInvoice, util::ser::Readable, util::ser::Writeable};
1921

2022
use std::sync::{Arc, Mutex};
2123
use std::time::Duration;
2224

25+
struct PersistedStaticInvoice {
26+
invoice: StaticInvoice,
27+
request_path: BlindedMessagePath,
28+
}
29+
30+
impl_writeable_tlv_based!(PersistedStaticInvoice, {
31+
(0, invoice, required),
32+
(2, request_path, required)
33+
});
34+
2335
pub(crate) struct StaticInvoiceStore {
2436
kv_store: Arc<DynStore>,
2537
request_rate_limiter: Mutex<RateLimiter>,
@@ -60,20 +72,24 @@ impl StaticInvoiceStore {
6072

6173
pub(crate) async fn handle_static_invoice_requested(
6274
&self, recipient_id: &[u8], invoice_slot: u16,
63-
) -> Result<Option<StaticInvoice>, lightning::io::Error> {
75+
) -> Result<Option<(StaticInvoice, BlindedMessagePath)>, lightning::io::Error> {
6476
Self::check_rate_limit(&self.request_rate_limiter, &recipient_id)?;
6577

6678
let (secondary_namespace, key) = Self::get_storage_location(invoice_slot, recipient_id);
6779

6880
self.kv_store
6981
.read(STATIC_INVOICE_STORE_PRIMARY_NAMESPACE, &secondary_namespace, &key)
7082
.and_then(|data| {
71-
data.try_into().map(Some).map_err(|e| {
72-
lightning::io::Error::new(
73-
lightning::io::ErrorKind::InvalidData,
74-
format!("Failed to parse static invoice: {:?}", e),
75-
)
76-
})
83+
PersistedStaticInvoice::read(&mut &*data)
84+
.map(|persisted_invoice| {
85+
Some((persisted_invoice.invoice, persisted_invoice.request_path))
86+
})
87+
.map_err(|e| {
88+
lightning::io::Error::new(
89+
lightning::io::ErrorKind::InvalidData,
90+
format!("Failed to parse static invoice: {:?}", e),
91+
)
92+
})
7793
})
7894
.or_else(
7995
|e| {
@@ -87,14 +103,18 @@ impl StaticInvoiceStore {
87103
}
88104

89105
pub(crate) async fn handle_persist_static_invoice(
90-
&self, invoice: StaticInvoice, invoice_slot: u16, recipient_id: Vec<u8>,
106+
&self, invoice: StaticInvoice, invoice_request_path: BlindedMessagePath, invoice_slot: u16,
107+
recipient_id: Vec<u8>,
91108
) -> Result<(), lightning::io::Error> {
92109
Self::check_rate_limit(&self.persist_rate_limiter, &recipient_id)?;
93110

94111
let (secondary_namespace, key) = Self::get_storage_location(invoice_slot, &recipient_id);
95112

113+
let persisted_invoice =
114+
PersistedStaticInvoice { invoice, request_path: invoice_request_path };
115+
96116
let mut buf = Vec::new();
97-
invoice.write(&mut buf)?;
117+
persisted_invoice.write(&mut buf)?;
98118

99119
// Static invoices will be persisted at "static_invoices/<sha256(recipient_id)>/<invoice_slot>".
100120
//
@@ -144,15 +164,21 @@ mod tests {
144164

145165
let static_invoice = invoice();
146166
let recipient_id = vec![1, 1, 1];
167+
let invoice_request_path = blinded_path();
147168
assert!(static_invoice_store
148-
.handle_persist_static_invoice(static_invoice.clone(), 0, recipient_id.clone())
169+
.handle_persist_static_invoice(
170+
static_invoice.clone(),
171+
invoice_request_path.clone(),
172+
0,
173+
recipient_id.clone()
174+
)
149175
.await
150176
.is_ok());
151177

152178
let requested_invoice =
153179
static_invoice_store.handle_static_invoice_requested(&recipient_id, 0).await.unwrap();
154180

155-
assert_eq!(requested_invoice.unwrap(), static_invoice);
181+
assert_eq!(requested_invoice.unwrap(), (static_invoice, invoice_request_path));
156182

157183
assert!(static_invoice_store
158184
.handle_static_invoice_requested(&recipient_id, 1)

tests/common/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,14 +589,21 @@ pub(crate) fn bump_fee_and_broadcast<E: ElectrumApi>(
589589
pub fn open_channel(
590590
node_a: &TestNode, node_b: &TestNode, funding_amount_sat: u64, should_announce: bool,
591591
electrsd: &ElectrsD,
592+
) -> OutPoint {
593+
open_channel_push_amt(node_a, node_b, funding_amount_sat, None, should_announce, electrsd)
594+
}
595+
596+
pub fn open_channel_push_amt(
597+
node_a: &TestNode, node_b: &TestNode, funding_amount_sat: u64, push_amount_msat: Option<u64>,
598+
should_announce: bool, electrsd: &ElectrsD,
592599
) -> OutPoint {
593600
if should_announce {
594601
node_a
595602
.open_announced_channel(
596603
node_b.node_id(),
597604
node_b.listening_addresses().unwrap().first().unwrap().clone(),
598605
funding_amount_sat,
599-
None,
606+
push_amount_msat,
600607
None,
601608
)
602609
.unwrap();
@@ -606,7 +613,7 @@ pub fn open_channel(
606613
node_b.node_id(),
607614
node_b.listening_addresses().unwrap().first().unwrap().clone(),
608615
funding_amount_sat,
609-
None,
616+
push_amount_msat,
610617
None,
611618
)
612619
.unwrap();

tests/integration_tests_rust.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ use common::{
1414
generate_blocks_and_wait,
1515
logging::MultiNodeLogger,
1616
logging::{init_log_logger, validate_log_entry, TestLogWriter},
17-
open_channel, premine_and_distribute_funds, premine_blocks, prepare_rbf, random_config,
18-
random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
19-
setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
17+
open_channel, open_channel_push_amt, premine_and_distribute_funds, premine_blocks, prepare_rbf,
18+
random_config, random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder,
19+
setup_node, setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
2020
};
2121

2222
use ldk_node::config::EsploraSyncConfig;
@@ -1137,11 +1137,14 @@ fn static_invoice_server() {
11371137
let chain_source = TestChainSource::Esplora(&electrsd);
11381138

11391139
let mut config_sender = random_config(true);
1140+
config_sender.node_config.listening_addresses = None;
1141+
config_sender.node_config.node_alias = None;
11401142
config_sender.log_writer =
11411143
TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("sender ".to_string())));
11421144
let node_sender = setup_node(&chain_source, config_sender, None);
11431145

11441146
let mut config_sender_lsp = random_config(true);
1147+
config_sender_lsp.node_config.async_payment_services_enabled = true;
11451148
config_sender_lsp.log_writer =
11461149
TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("sender_lsp ".to_string())));
11471150
let node_sender_lsp = setup_node(&chain_source, config_sender_lsp, None);
@@ -1154,9 +1157,10 @@ fn static_invoice_server() {
11541157
let node_receiver_lsp = setup_node(&chain_source, config_receiver_lsp, None);
11551158

11561159
let mut config_receiver = random_config(true);
1160+
config_receiver.node_config.listening_addresses = None;
1161+
config_receiver.node_config.node_alias = None;
11571162
config_receiver.log_writer =
11581163
TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("receiver ".to_string())));
1159-
11601164
let node_receiver = setup_node(&chain_source, config_receiver, None);
11611165

11621166
let address_sender = node_sender.onchain_payment().new_address().unwrap();
@@ -1176,9 +1180,16 @@ fn static_invoice_server() {
11761180
node_receiver_lsp.sync_wallets().unwrap();
11771181
node_receiver.sync_wallets().unwrap();
11781182

1179-
open_channel(&node_sender, &node_sender_lsp, 400_000, true, &electrsd);
1183+
open_channel(&node_sender, &node_sender_lsp, 400_000, false, &electrsd);
11801184
open_channel(&node_sender_lsp, &node_receiver_lsp, 400_000, true, &electrsd);
1181-
open_channel(&node_receiver_lsp, &node_receiver, 400_000, true, &electrsd);
1185+
open_channel_push_amt(
1186+
&node_receiver,
1187+
&node_receiver_lsp,
1188+
400_000,
1189+
Some(200_000_000),
1190+
false,
1191+
&electrsd,
1192+
);
11821193

11831194
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);
11841195

@@ -1201,14 +1212,14 @@ fn static_invoice_server() {
12011212
.filter(|n| {
12021213
node.network_graph().node(n).map_or(false, |info| info.announcement_info.is_some())
12031214
})
1204-
.count() >= 4
1215+
.count() >= 2
12051216
};
12061217

12071218
// Wait for everyone to see all channels and node announcements.
1208-
while node_sender.network_graph().list_channels().len() < 3
1209-
|| node_sender_lsp.network_graph().list_channels().len() < 3
1210-
|| node_receiver_lsp.network_graph().list_channels().len() < 3
1211-
|| node_receiver.network_graph().list_channels().len() < 3
1219+
while node_sender.network_graph().list_channels().len() < 1
1220+
|| node_sender_lsp.network_graph().list_channels().len() < 1
1221+
|| node_receiver_lsp.network_graph().list_channels().len() < 1
1222+
|| node_receiver.network_graph().list_channels().len() < 1
12121223
|| !has_node_announcements(&node_sender)
12131224
|| !has_node_announcements(&node_sender_lsp)
12141225
|| !has_node_announcements(&node_receiver_lsp)

0 commit comments

Comments
 (0)