Skip to content

Commit 4ba5131

Browse files
committed
f: config via builder enum setter
1 parent 8271a22 commit 4ba5131

File tree

7 files changed

+119
-69
lines changed

7 files changed

+119
-69
lines changed

bindings/ldk_node.udl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ dictionary Config {
1313
u64 probing_liquidity_limit_multiplier;
1414
AnchorChannelsConfig? anchor_channels_config;
1515
RouteParametersConfig? route_parameters;
16-
boolean async_payment_services_enabled;
17-
boolean hold_outbound_htlcs_at_next_hop;
1816
};
1917

2018
dictionary AnchorChannelsConfig {
@@ -96,6 +94,7 @@ interface Builder {
9694
void set_announcement_addresses(sequence<SocketAddress> announcement_addresses);
9795
[Throws=BuildError]
9896
void set_node_alias(string node_alias);
97+
void set_async_payments_role(AsyncPaymentsRole? role);
9998
[Throws=BuildError]
10099
Node build();
101100
[Throws=BuildError]
@@ -721,6 +720,11 @@ enum Currency {
721720
"Signet",
722721
};
723722

723+
enum AsyncPaymentsRole {
724+
"Client",
725+
"Server",
726+
};
727+
724728
dictionary RouteHintHop {
725729
PublicKey src_node_id;
726730
u64 short_channel_id;

src/builder.rs

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
use crate::chain::ChainSource;
99
use crate::config::{
10-
default_user_config, may_announce_channel, AnnounceError, BitcoindRestClientConfig, Config,
11-
ElectrumSyncConfig, EsploraSyncConfig, DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME,
12-
DEFAULT_LOG_LEVEL, WALLET_KEYS_SEED_LEN,
10+
default_user_config, may_announce_channel, AnnounceError, AsyncPaymentsRole,
11+
BitcoindRestClientConfig, Config, ElectrumSyncConfig, EsploraSyncConfig,
12+
DEFAULT_ESPLORA_SERVER_URL, DEFAULT_LOG_FILENAME, DEFAULT_LOG_LEVEL, WALLET_KEYS_SEED_LEN,
1313
};
1414

1515
use crate::connection::ConnectionManager;
@@ -242,6 +242,7 @@ pub struct NodeBuilder {
242242
liquidity_source_config: Option<LiquiditySourceConfig>,
243243
log_writer_config: Option<LogWriterConfig>,
244244
runtime_handle: Option<tokio::runtime::Handle>,
245+
async_payments_role: Option<AsyncPaymentsRole>,
245246
}
246247

247248
impl NodeBuilder {
@@ -267,6 +268,7 @@ impl NodeBuilder {
267268
liquidity_source_config,
268269
log_writer_config,
269270
runtime_handle,
271+
async_payments_role: None,
270272
}
271273
}
272274

@@ -545,6 +547,12 @@ impl NodeBuilder {
545547
Ok(self)
546548
}
547549

550+
/// Sets the role of the node in an asynchronous payments context.
551+
pub fn set_async_payments_role(&mut self, role: Option<AsyncPaymentsRole>) -> &mut Self {
552+
self.async_payments_role = role;
553+
self
554+
}
555+
548556
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
549557
/// previously configured.
550558
pub fn build(&self) -> Result<Node, BuildError> {
@@ -705,6 +713,7 @@ impl NodeBuilder {
705713
runtime,
706714
logger,
707715
Arc::new(vss_store),
716+
self.async_payments_role,
708717
)
709718
}
710719

@@ -737,6 +746,7 @@ impl NodeBuilder {
737746
runtime,
738747
logger,
739748
kv_store,
749+
self.async_payments_role,
740750
)
741751
}
742752
}
@@ -990,6 +1000,11 @@ impl ArcedNodeBuilder {
9901000
self.inner.write().unwrap().set_node_alias(node_alias).map(|_| ())
9911001
}
9921002

1003+
/// Sets the role of the node in an asynchronous payments context.
1004+
pub fn set_async_payments_role(&self, role: Option<AsyncPaymentsRole>) {
1005+
_ = self.inner.write().unwrap().set_async_payments_role(role)
1006+
}
1007+
9931008
/// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options
9941009
/// previously configured.
9951010
pub fn build(&self) -> Result<Arc<Node>, BuildError> {
@@ -1085,6 +1100,7 @@ fn build_with_store_internal(
10851100
gossip_source_config: Option<&GossipSourceConfig>,
10861101
liquidity_source_config: Option<&LiquiditySourceConfig>, seed_bytes: [u8; 64],
10871102
runtime: Arc<Runtime>, logger: Arc<Logger>, kv_store: Arc<DynStore>,
1103+
async_payments_role: Option<AsyncPaymentsRole>,
10881104
) -> Result<Node, BuildError> {
10891105
optionally_install_rustls_cryptoprovider();
10901106

@@ -1379,8 +1395,14 @@ fn build_with_store_internal(
13791395
100;
13801396
}
13811397

1382-
if config.async_payment_services_enabled {
1383-
user_config.accept_forwards_to_priv_channels = true;
1398+
if let Some(role) = async_payments_role {
1399+
match role {
1400+
AsyncPaymentsRole::Server => {
1401+
user_config.accept_forwards_to_priv_channels = true;
1402+
user_config.enable_htlc_hold = true;
1403+
},
1404+
AsyncPaymentsRole::Client => user_config.hold_outbound_htlcs_at_next_hop = true,
1405+
}
13841406
}
13851407

13861408
let message_router =
@@ -1453,31 +1475,32 @@ fn build_with_store_internal(
14531475
}
14541476

14551477
// Initialize the PeerManager
1456-
let onion_messenger: Arc<OnionMessenger> = if config.async_payment_services_enabled {
1457-
Arc::new(OnionMessenger::new_with_offline_peer_interception(
1458-
Arc::clone(&keys_manager),
1459-
Arc::clone(&keys_manager),
1460-
Arc::clone(&logger),
1461-
Arc::clone(&channel_manager),
1462-
message_router,
1463-
Arc::clone(&channel_manager),
1464-
Arc::clone(&channel_manager),
1465-
IgnoringMessageHandler {},
1466-
IgnoringMessageHandler {},
1467-
))
1468-
} else {
1469-
Arc::new(OnionMessenger::new(
1470-
Arc::clone(&keys_manager),
1471-
Arc::clone(&keys_manager),
1472-
Arc::clone(&logger),
1473-
Arc::clone(&channel_manager),
1474-
message_router,
1475-
Arc::clone(&channel_manager),
1476-
Arc::clone(&channel_manager),
1477-
IgnoringMessageHandler {},
1478-
IgnoringMessageHandler {},
1479-
))
1480-
};
1478+
let onion_messenger: Arc<OnionMessenger> =
1479+
if let Some(AsyncPaymentsRole::Server) = async_payments_role {
1480+
Arc::new(OnionMessenger::new_with_offline_peer_interception(
1481+
Arc::clone(&keys_manager),
1482+
Arc::clone(&keys_manager),
1483+
Arc::clone(&logger),
1484+
Arc::clone(&channel_manager),
1485+
message_router,
1486+
Arc::clone(&channel_manager),
1487+
Arc::clone(&channel_manager),
1488+
IgnoringMessageHandler {},
1489+
IgnoringMessageHandler {},
1490+
))
1491+
} else {
1492+
Arc::new(OnionMessenger::new(
1493+
Arc::clone(&keys_manager),
1494+
Arc::clone(&keys_manager),
1495+
Arc::clone(&logger),
1496+
Arc::clone(&channel_manager),
1497+
message_router,
1498+
Arc::clone(&channel_manager),
1499+
Arc::clone(&channel_manager),
1500+
IgnoringMessageHandler {},
1501+
IgnoringMessageHandler {},
1502+
))
1503+
};
14811504
let ephemeral_bytes: [u8; 32] = keys_manager.get_secure_random_bytes();
14821505

14831506
// Initialize the GossipSource
@@ -1664,7 +1687,7 @@ fn build_with_store_internal(
16641687
},
16651688
};
16661689

1667-
let om_mailbox = if config.async_payment_services_enabled {
1690+
let om_mailbox = if let Some(AsyncPaymentsRole::Server) = async_payments_role {
16681691
Some(Arc::new(OnionMessageMailbox::new()))
16691692
} else {
16701693
None
@@ -1703,6 +1726,7 @@ fn build_with_store_internal(
17031726
is_listening,
17041727
node_metrics,
17051728
om_mailbox,
1729+
async_payments_role,
17061730
})
17071731
}
17081732

src/config.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,6 @@ pub struct Config {
179179
/// **Note:** If unset, default parameters will be used, and you will be able to override the
180180
/// parameters on a per-payment basis in the corresponding method calls.
181181
pub route_parameters: Option<RouteParametersConfig>,
182-
/// Whether to enable the static invoice service to support async payment reception for clients.
183-
pub async_payment_services_enabled: bool,
184-
/// If this is set to true, then if we as an often-offline payer receive a [`StaticInvoice`] to
185-
/// pay, we will attempt to hold the corresponding outbound HTLCs with our next-hop channel
186-
/// counterparty(s) that support the `htlc_hold` feature. This allows our node to go offline once
187-
/// the HTLCs are locked in even though the recipient may not yet be online to receive them.
188-
///
189-
/// [`StaticInvoice`]: lightning::offers::static_invoice::StaticInvoice
190-
pub hold_outbound_htlcs_at_next_hop: bool,
191182
}
192183

193184
impl Default for Config {
@@ -202,8 +193,6 @@ impl Default for Config {
202193
anchor_channels_config: Some(AnchorChannelsConfig::default()),
203194
route_parameters: None,
204195
node_alias: None,
205-
async_payment_services_enabled: false,
206-
hold_outbound_htlcs_at_next_hop: false,
207196
}
208197
}
209198
}
@@ -338,13 +327,6 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
338327
user_config.channel_handshake_limits.force_announced_channel_preference = true;
339328
}
340329

341-
if config.async_payment_services_enabled {
342-
user_config.enable_htlc_hold = true;
343-
}
344-
if config.hold_outbound_htlcs_at_next_hop {
345-
user_config.hold_outbound_htlcs_at_next_hop = true;
346-
}
347-
348330
user_config
349331
}
350332

@@ -552,6 +534,17 @@ impl From<MaxDustHTLCExposure> for LdkMaxDustHTLCExposure {
552534
}
553535
}
554536

537+
#[derive(Debug, Clone, Copy)]
538+
/// The role of the node in an asynchronous payments context.
539+
pub enum AsyncPaymentsRole {
540+
/// Node acts a client in an async payments context. This means that if possible, it will instruct its peers to hold
541+
/// htlcs for it, so that it can go offline.
542+
Client,
543+
/// Node acts as a server in an async payments context. This means that it will hold async payments htlcs and onion
544+
/// messages for its peers.
545+
Server,
546+
}
547+
555548
#[cfg(test)]
556549
mod tests {
557550
use std::str::FromStr;

src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ pub use builder::BuildError;
126126
pub use builder::NodeBuilder as Builder;
127127

128128
use chain::ChainSource;
129+
use config::AsyncPaymentsRole;
129130
use config::{
130131
default_user_config, may_announce_channel, ChannelConfig, Config, NODE_ANN_BCAST_INTERVAL,
131132
PEER_RECONNECTION_INTERVAL, RGS_SYNC_INTERVAL,
@@ -207,6 +208,7 @@ pub struct Node {
207208
is_listening: Arc<AtomicBool>,
208209
node_metrics: Arc<RwLock<NodeMetrics>>,
209210
om_mailbox: Option<Arc<OnionMessageMailbox>>,
211+
async_payments_role: Option<AsyncPaymentsRole>,
210212
}
211213

212214
impl Node {
@@ -501,7 +503,8 @@ impl Node {
501503
Arc::clone(&self.logger),
502504
));
503505

504-
let static_invoice_store = if self.config.async_payment_services_enabled {
506+
let static_invoice_store = if let Some(AsyncPaymentsRole::Server) = self.async_payments_role
507+
{
505508
Some(StaticInvoiceStore::new(Arc::clone(&self.kv_store)))
506509
} else {
507510
None
@@ -830,9 +833,9 @@ impl Node {
830833
Bolt12Payment::new(
831834
Arc::clone(&self.channel_manager),
832835
Arc::clone(&self.payment_store),
833-
Arc::clone(&self.config),
834836
Arc::clone(&self.is_running),
835837
Arc::clone(&self.logger),
838+
self.async_payments_role,
836839
)
837840
}
838841

@@ -844,9 +847,9 @@ impl Node {
844847
Arc::new(Bolt12Payment::new(
845848
Arc::clone(&self.channel_manager),
846849
Arc::clone(&self.payment_store),
847-
Arc::clone(&self.config),
848850
Arc::clone(&self.is_running),
849851
Arc::clone(&self.logger),
852+
self.async_payments_role,
850853
))
851854
}
852855

src/payment/bolt12.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//!
1010
//! [BOLT 12]: https://github.com/lightning/bolts/blob/master/12-offer-encoding.md
1111
12-
use crate::config::{Config, LDK_PAYMENT_RETRY_TIMEOUT};
12+
use crate::config::{AsyncPaymentsRole, LDK_PAYMENT_RETRY_TIMEOUT};
1313
use crate::error::Error;
1414
use crate::ffi::{maybe_deref, maybe_wrap};
1515
use crate::logger::{log_error, log_info, LdkLogger, Logger};
@@ -57,16 +57,17 @@ pub struct Bolt12Payment {
5757
channel_manager: Arc<ChannelManager>,
5858
payment_store: Arc<PaymentStore>,
5959
is_running: Arc<RwLock<bool>>,
60-
config: Arc<Config>,
6160
logger: Arc<Logger>,
61+
async_payments_role: Option<AsyncPaymentsRole>,
6262
}
6363

6464
impl Bolt12Payment {
6565
pub(crate) fn new(
6666
channel_manager: Arc<ChannelManager>, payment_store: Arc<PaymentStore>,
67-
config: Arc<Config>, is_running: Arc<RwLock<bool>>, logger: Arc<Logger>,
67+
is_running: Arc<RwLock<bool>>, logger: Arc<Logger>,
68+
async_payments_role: Option<AsyncPaymentsRole>,
6869
) -> Self {
69-
Self { channel_manager, payment_store, config, is_running, logger }
70+
Self { channel_manager, payment_store, is_running, logger, async_payments_role }
7071
}
7172

7273
/// Send a payment given an offer.
@@ -554,8 +555,11 @@ impl Bolt12Payment {
554555
fn blinded_paths_for_async_recipient_internal(
555556
&self, recipient_id: Vec<u8>,
556557
) -> Result<Vec<BlindedMessagePath>, Error> {
557-
if !self.config.async_payment_services_enabled {
558-
return Err(Error::AsyncPaymentServicesDisabled);
558+
match self.async_payments_role {
559+
Some(AsyncPaymentsRole::Server) => {},
560+
_ => {
561+
return Err(Error::AsyncPaymentServicesDisabled);
562+
},
559563
}
560564

561565
self.channel_manager

tests/common/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub(crate) mod logging;
1212

1313
use logging::TestLogWriter;
1414

15-
use ldk_node::config::{Config, ElectrumSyncConfig, EsploraSyncConfig};
15+
use ldk_node::config::{AsyncPaymentsRole, Config, ElectrumSyncConfig, EsploraSyncConfig};
1616
use ldk_node::io::sqlite_store::SqliteStore;
1717
use ldk_node::payment::{PaymentDirection, PaymentKind, PaymentStatus};
1818
use ldk_node::{
@@ -310,6 +310,13 @@ pub(crate) fn setup_two_nodes(
310310

311311
pub(crate) fn setup_node(
312312
chain_source: &TestChainSource, config: TestConfig, seed_bytes: Option<Vec<u8>>,
313+
) -> TestNode {
314+
setup_node_for_async_payments(chain_source, config, seed_bytes, None)
315+
}
316+
317+
pub(crate) fn setup_node_for_async_payments(
318+
chain_source: &TestChainSource, config: TestConfig, seed_bytes: Option<Vec<u8>>,
319+
async_payments_role: Option<AsyncPaymentsRole>,
313320
) -> TestNode {
314321
setup_builder!(builder, config.node_config);
315322
match chain_source {
@@ -375,6 +382,8 @@ pub(crate) fn setup_node(
375382
}
376383
}
377384

385+
builder.set_async_payments_role(async_payments_role);
386+
378387
let test_sync_store = Arc::new(TestSyncStore::new(config.node_config.storage_dir_path.into()));
379388
let node = builder.build_with_store(test_sync_store).unwrap();
380389
node.start().unwrap();

0 commit comments

Comments
 (0)