Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,17 @@ default = []
#lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
#lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }

lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["std"] }
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["std"] }
lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["rest-client", "rpc-client", "tokio"] }
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["esplora-async-https", "electrum-rustls-ring", "time"] }
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0" }
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["std"] }
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["std"] }
lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["rest-client", "rpc-client", "tokio"] }
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["esplora-async-https", "electrum-rustls-ring", "time"] }
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4" }

#lightning = { path = "../rust-lightning/lightning", features = ["std"] }
#lightning-types = { path = "../rust-lightning/lightning-types" }
Expand Down Expand Up @@ -109,7 +109,7 @@ winapi = { version = "0.3", features = ["winbase"] }
[dev-dependencies]
#lightning = { version = "0.1.0", features = ["std", "_test_utils"] }
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["std", "_test_utils"] }
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "84398d9e5b3dc61c0a5c71972aa944f19948aef0", features = ["std", "_test_utils"] }
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "b002e43ec5f9c1cbdcd1ac8588402c5a65ecd2e4", features = ["std", "_test_utils"] }
#lightning = { path = "../rust-lightning/lightning", features = ["std", "_test_utils"] }
proptest = "1.0.0"
regex = "1.5.6"
Expand Down
4 changes: 4 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,10 @@ fn build_with_store_internal(
100;
}

if config.async_payment_services_enabled {
user_config.accept_forwards_to_priv_channels = true;
}

let message_router =
Arc::new(MessageRouter::new(Arc::clone(&network_graph), Arc::clone(&keys_manager)));

Expand Down
26 changes: 20 additions & 6 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1500,13 +1500,19 @@ where

LdkEvent::PersistStaticInvoice {
invoice,
invoice_request_path,
invoice_slot,
recipient_id,
invoice_persisted_path,
} => {
if let Some(store) = self.static_invoice_store.as_ref() {
match store
.handle_persist_static_invoice(invoice, invoice_slot, recipient_id)
.handle_persist_static_invoice(
invoice,
invoice_request_path,
invoice_slot,
recipient_id,
)
.await
{
Ok(_) => {
Expand All @@ -1519,16 +1525,24 @@ where
};
}
},
LdkEvent::StaticInvoiceRequested { recipient_id, invoice_slot, reply_path } => {
LdkEvent::StaticInvoiceRequested {
recipient_id,
invoice_slot,
reply_path,
invoice_request,
} => {
if let Some(store) = self.static_invoice_store.as_ref() {
let invoice =
store.handle_static_invoice_requested(&recipient_id, invoice_slot).await;

match invoice {
Ok(Some(invoice)) => {
if let Err(e) =
self.channel_manager.send_static_invoice(invoice, reply_path)
{
Ok(Some((invoice, invoice_request_path))) => {
if let Err(e) = self.channel_manager.respond_to_static_invoice_request(
invoice,
reply_path,
invoice_request,
invoice_request_path,
) {
log_error!(self.logger, "Failed to send static invoice: {:?}", e);
}
},
Expand Down
50 changes: 38 additions & 12 deletions src/payment/asynchronous/static_invoice_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,23 @@ use crate::types::DynStore;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;

use lightning::{offers::static_invoice::StaticInvoice, util::ser::Writeable};
use lightning::blinded_path::message::BlindedMessagePath;
use lightning::impl_writeable_tlv_based;
use lightning::{offers::static_invoice::StaticInvoice, util::ser::Readable, util::ser::Writeable};

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

struct PersistedStaticInvoice {
invoice: StaticInvoice,
request_path: BlindedMessagePath,
}

impl_writeable_tlv_based!(PersistedStaticInvoice, {
(0, invoice, required),
(2, request_path, required)
});

pub(crate) struct StaticInvoiceStore {
kv_store: Arc<DynStore>,
request_rate_limiter: Mutex<RateLimiter>,
Expand Down Expand Up @@ -60,20 +72,24 @@ impl StaticInvoiceStore {

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

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

self.kv_store
.read(STATIC_INVOICE_STORE_PRIMARY_NAMESPACE, &secondary_namespace, &key)
.and_then(|data| {
data.try_into().map(Some).map_err(|e| {
lightning::io::Error::new(
lightning::io::ErrorKind::InvalidData,
format!("Failed to parse static invoice: {:?}", e),
)
})
PersistedStaticInvoice::read(&mut &*data)
.map(|persisted_invoice| {
Some((persisted_invoice.invoice, persisted_invoice.request_path))
})
.map_err(|e| {
lightning::io::Error::new(
lightning::io::ErrorKind::InvalidData,
format!("Failed to parse static invoice: {:?}", e),
)
})
})
.or_else(
|e| {
Expand All @@ -87,14 +103,18 @@ impl StaticInvoiceStore {
}

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

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

let persisted_invoice =
PersistedStaticInvoice { invoice, request_path: invoice_request_path };

let mut buf = Vec::new();
invoice.write(&mut buf)?;
persisted_invoice.write(&mut buf)?;

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

let static_invoice = invoice();
let recipient_id = vec![1, 1, 1];
let invoice_request_path = blinded_path();
assert!(static_invoice_store
.handle_persist_static_invoice(static_invoice.clone(), 0, recipient_id.clone())
.handle_persist_static_invoice(
static_invoice.clone(),
invoice_request_path.clone(),
0,
recipient_id.clone()
)
.await
.is_ok());

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

assert_eq!(requested_invoice.unwrap(), static_invoice);
assert_eq!(requested_invoice.unwrap(), (static_invoice, invoice_request_path));

assert!(static_invoice_store
.handle_static_invoice_requested(&recipient_id, 1)
Expand Down
11 changes: 9 additions & 2 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,14 +589,21 @@ pub(crate) fn bump_fee_and_broadcast<E: ElectrumApi>(
pub fn open_channel(
node_a: &TestNode, node_b: &TestNode, funding_amount_sat: u64, should_announce: bool,
electrsd: &ElectrsD,
) -> OutPoint {
open_channel_push_amt(node_a, node_b, funding_amount_sat, None, should_announce, electrsd)
}

pub fn open_channel_push_amt(
node_a: &TestNode, node_b: &TestNode, funding_amount_sat: u64, push_amount_msat: Option<u64>,
should_announce: bool, electrsd: &ElectrsD,
) -> OutPoint {
if should_announce {
node_a
.open_announced_channel(
node_b.node_id(),
node_b.listening_addresses().unwrap().first().unwrap().clone(),
funding_amount_sat,
None,
push_amount_msat,
None,
)
.unwrap();
Expand All @@ -606,7 +613,7 @@ pub fn open_channel(
node_b.node_id(),
node_b.listening_addresses().unwrap().first().unwrap().clone(),
funding_amount_sat,
None,
push_amount_msat,
None,
)
.unwrap();
Expand Down
33 changes: 22 additions & 11 deletions tests/integration_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use common::{
generate_blocks_and_wait,
logging::MultiNodeLogger,
logging::{init_log_logger, validate_log_entry, TestLogWriter},
open_channel, premine_and_distribute_funds, premine_blocks, prepare_rbf, random_config,
random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
open_channel, open_channel_push_amt, premine_and_distribute_funds, premine_blocks, prepare_rbf,
random_config, random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder,
setup_node, setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
};

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

let mut config_sender = random_config(true);
config_sender.node_config.listening_addresses = None;
config_sender.node_config.node_alias = None;
config_sender.log_writer =
TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("sender ".to_string())));
let node_sender = setup_node(&chain_source, config_sender, None);

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

let mut config_receiver = random_config(true);
config_receiver.node_config.listening_addresses = None;
config_receiver.node_config.node_alias = None;
config_receiver.log_writer =
TestLogWriter::Custom(Arc::new(MultiNodeLogger::new("receiver ".to_string())));

let node_receiver = setup_node(&chain_source, config_receiver, None);

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

open_channel(&node_sender, &node_sender_lsp, 400_000, true, &electrsd);
open_channel(&node_sender, &node_sender_lsp, 400_000, false, &electrsd);
open_channel(&node_sender_lsp, &node_receiver_lsp, 400_000, true, &electrsd);
open_channel(&node_receiver_lsp, &node_receiver, 400_000, true, &electrsd);
open_channel_push_amt(
&node_receiver,
&node_receiver_lsp,
400_000,
Some(200_000_000),
false,
&electrsd,
);

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

Expand All @@ -1201,14 +1212,14 @@ fn static_invoice_server() {
.filter(|n| {
node.network_graph().node(n).map_or(false, |info| info.announcement_info.is_some())
})
.count() >= 4
.count() >= 2
};

// Wait for everyone to see all channels and node announcements.
while node_sender.network_graph().list_channels().len() < 3
|| node_sender_lsp.network_graph().list_channels().len() < 3
|| node_receiver_lsp.network_graph().list_channels().len() < 3
|| node_receiver.network_graph().list_channels().len() < 3
while node_sender.network_graph().list_channels().len() < 1
|| node_sender_lsp.network_graph().list_channels().len() < 1
|| node_receiver_lsp.network_graph().list_channels().len() < 1
|| node_receiver.network_graph().list_channels().len() < 1
|| !has_node_announcements(&node_sender)
|| !has_node_announcements(&node_sender_lsp)
|| !has_node_announcements(&node_receiver_lsp)
Expand Down
Loading