Skip to content

Commit e7029bf

Browse files
committed
use lightning::util::anchor_channel_reserves for improved anchor reserve estimation
Replaced flat fee-based reserve logic with estimation using `get_reserve_per_channel`, following changes introduced in lightningdevkit/rust-lightning#3487.
1 parent dd51908 commit e7029bf

File tree

7 files changed

+39
-45
lines changed

7 files changed

+39
-45
lines changed

bindings/ldk_node.udl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ dictionary Config {
1717

1818
dictionary AnchorChannelsConfig {
1919
sequence<PublicKey> trusted_peers_no_reserve;
20-
u64 per_channel_reserve_sats;
2120
};
2221

2322
dictionary BackgroundSyncConfig {

src/config.rs

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 80;
2727
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 30;
2828
const DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS: u64 = 60 * 10;
2929
const DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER: u64 = 3;
30-
const DEFAULT_ANCHOR_PER_CHANNEL_RESERVE_SATS: u64 = 25_000;
3130

3231
/// The default log level.
3332
pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Debug;
@@ -219,7 +218,6 @@ impl Default for Config {
219218
/// | Parameter | Value |
220219
/// |----------------------------|--------|
221220
/// | `trusted_peers_no_reserve` | [] |
222-
/// | `per_channel_reserve_sats` | 25000 |
223221
///
224222
///
225223
/// [BOLT 3]: https://github.com/lightning/bolts/blob/master/03-transactions.md#htlc-timeout-and-htlc-success-transactions
@@ -235,33 +233,11 @@ pub struct AnchorChannelsConfig {
235233
/// required Anchor spending transactions confirmed on-chain is potentially insecure
236234
/// as the channel may not be closed if they refuse to do so.
237235
pub trusted_peers_no_reserve: Vec<PublicKey>,
238-
/// The amount of satoshis per anchors-negotiated channel with an untrusted peer that we keep
239-
/// as an emergency reserve in our on-chain wallet.
240-
///
241-
/// This allows for having the required Anchor output spending and HTLC transactions confirmed
242-
/// when the channel is closed.
243-
///
244-
/// If the channel peer is not marked as trusted via
245-
/// [`AnchorChannelsConfig::trusted_peers_no_reserve`], we will always try to spend the Anchor
246-
/// outputs with *any* on-chain funds available, i.e., the total reserve value as well as any
247-
/// spendable funds available in the on-chain wallet. Therefore, this per-channel multiplier is
248-
/// really a emergency reserve that we maintain at all time to reduce reduce the risk of
249-
/// insufficient funds at time of a channel closure. To this end, we will refuse to open
250-
/// outbound or accept inbound channels if we don't have sufficient on-chain funds available to
251-
/// cover the additional reserve requirement.
252-
///
253-
/// **Note:** Depending on the fee market at the time of closure, this reserve amount might or
254-
/// might not suffice to successfully spend the Anchor output and have the HTLC transactions
255-
/// confirmed on-chain, i.e., you may want to adjust this value accordingly.
256-
pub per_channel_reserve_sats: u64,
257236
}
258237

259238
impl Default for AnchorChannelsConfig {
260239
fn default() -> Self {
261-
Self {
262-
trusted_peers_no_reserve: Vec::new(),
263-
per_channel_reserve_sats: DEFAULT_ANCHOR_PER_CHANNEL_RESERVE_SATS,
264-
}
240+
Self { trusted_peers_no_reserve: Vec::new() }
265241
}
266242
}
267243

src/event.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ use lightning::impl_writeable_tlv_based_enum;
2222
use lightning::ln::channelmanager::PaymentId;
2323
use lightning::ln::types::ChannelId;
2424
use lightning::routing::gossip::NodeId;
25+
use lightning::util::anchor_channel_reserves::{
26+
get_reserve_per_channel, AnchorChannelReserveContext,
27+
};
2528
use lightning::util::config::{
2629
ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate,
2730
};
@@ -1108,7 +1111,8 @@ where
11081111
{
11091112
0
11101113
} else {
1111-
anchor_channels_config.per_channel_reserve_sats
1114+
get_reserve_per_channel(&AnchorChannelReserveContext::default())
1115+
.to_sat()
11121116
};
11131117

11141118
if spendable_amount_sats < required_amount_sats {

src/lib.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ use lightning::ln::channel_state::ChannelShutdownState;
136136
use lightning::ln::channelmanager::PaymentId;
137137
use lightning::ln::msgs::SocketAddress;
138138
use lightning::routing::gossip::NodeAlias;
139+
use lightning::util::anchor_channel_reserves::{
140+
get_reserve_per_channel, AnchorChannelReserveContext,
141+
};
139142
use lightning::util::persist::KVStoreSync;
140143
use lightning_background_processor::process_events_async;
141144
use liquidity::{LSPS1Liquidity, LiquiditySource};
@@ -1069,7 +1072,7 @@ impl Node {
10691072
if init_features.requires_anchors_zero_fee_htlc_tx()
10701073
&& !c.trusted_peers_no_reserve.contains(&node_id)
10711074
{
1072-
c.per_channel_reserve_sats
1075+
get_reserve_per_channel(&AnchorChannelReserveContext::default()).to_sat()
10731076
} else {
10741077
0
10751078
}
@@ -1132,13 +1135,11 @@ impl Node {
11321135
/// channel counterparty on channel open. This can be useful to start out with the balance not
11331136
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
11341137
///
1135-
/// If Anchor channels are enabled, this will ensure the configured
1136-
/// [`AnchorChannelsConfig::per_channel_reserve_sats`] is available and will be retained before
1137-
/// opening the channel.
1138+
/// If Anchor channels are enabled, this will ensure the reserved amount per
1139+
/// channel is available and will be retained before opening the channel.
11381140
///
11391141
/// Returns a [`UserChannelId`] allowing to locally keep track of the channel.
11401142
///
1141-
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
11421143
pub fn open_channel(
11431144
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
11441145
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
@@ -1167,13 +1168,11 @@ impl Node {
11671168
/// channel counterparty on channel open. This can be useful to start out with the balance not
11681169
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
11691170
///
1170-
/// If Anchor channels are enabled, this will ensure the configured
1171-
/// [`AnchorChannelsConfig::per_channel_reserve_sats`] is available and will be retained before
1172-
/// opening the channel.
1171+
/// If Anchor channels are enabled, this will ensure the reserved amount per
1172+
/// channel is available and will be retained before opening the channel.
11731173
///
11741174
/// Returns a [`UserChannelId`] allowing to locally keep track of the channel.
11751175
///
1176-
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
11771176
pub fn open_announced_channel(
11781177
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
11791178
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
@@ -1580,6 +1579,8 @@ impl_writeable_tlv_based!(NodeMetrics, {
15801579
pub(crate) fn total_anchor_channels_reserve_sats(
15811580
channel_manager: &ChannelManager, config: &Config,
15821581
) -> u64 {
1582+
let reserve_sat_per_channel = get_anchor_reserve_per_channel();
1583+
15831584
config.anchor_channels_config.as_ref().map_or(0, |anchor_channels_config| {
15841585
channel_manager
15851586
.list_channels()
@@ -1593,6 +1594,12 @@ pub(crate) fn total_anchor_channels_reserve_sats(
15931594
.map_or(false, |t| t.requires_anchors_zero_fee_htlc_tx())
15941595
})
15951596
.count() as u64
1596-
* anchor_channels_config.per_channel_reserve_sats
1597+
* reserve_sat_per_channel
15971598
})
15981599
}
1600+
1601+
/// Returns the configured anchor channel reserve per channel in satoshis.
1602+
pub fn get_anchor_reserve_per_channel() -> u64 {
1603+
let context = AnchorChannelReserveContext::default();
1604+
get_reserve_per_channel(&context).to_sat()
1605+
}

src/liquidity.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
2020
use lightning::ln::msgs::SocketAddress;
2121
use lightning::ln::types::ChannelId;
2222
use lightning::routing::router::{RouteHint, RouteHintHop};
23+
use lightning::util::anchor_channel_reserves::{
24+
get_reserve_per_channel, AnchorChannelReserveContext,
25+
};
2326
use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, InvoiceBuilder, RoutingFees};
2427
use lightning_liquidity::events::LiquidityEvent;
2528
use lightning_liquidity::lsps0::ser::{LSPSDateTime, LSPSRequestId};
@@ -672,7 +675,8 @@ where
672675
if init_features.requires_anchors_zero_fee_htlc_tx()
673676
&& !c.trusted_peers_no_reserve.contains(&their_network_key)
674677
{
675-
c.per_channel_reserve_sats
678+
get_reserve_per_channel(&AnchorChannelReserveContext::default())
679+
.to_sat()
676680
} else {
677681
0
678682
}

tests/common/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use electrsd::corepc_node::{Client as BitcoindClient, Node as BitcoinD};
2929
use electrsd::{corepc_node, ElectrsD};
3030
use electrum_client::ElectrumApi;
3131
use ldk_node::config::{AsyncPaymentsRole, Config, ElectrumSyncConfig, EsploraSyncConfig};
32+
use ldk_node::get_anchor_reserve_per_channel;
3233
use ldk_node::io::sqlite_store::SqliteStore;
3334
use ldk_node::payment::{PaymentDirection, PaymentKind, PaymentStatus};
3435
use ldk_node::{
@@ -640,8 +641,9 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
640641
let addr_a = node_a.onchain_payment().new_address().unwrap();
641642
let addr_b = node_b.onchain_payment().new_address().unwrap();
642643

643-
let premine_amount_sat = if expect_anchor_channel { 2_125_000 } else { 2_100_000 };
644+
let anchor_reserve = if expect_anchor_channel { get_anchor_reserve_per_channel() } else { 0 };
644645

646+
let premine_amount_sat = 2_100_000 + anchor_reserve;
645647
premine_and_distribute_funds(
646648
&bitcoind,
647649
electrsd,
@@ -725,7 +727,8 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
725727
);
726728

727729
let onchain_fee_buffer_sat = 5000;
728-
let node_a_anchor_reserve_sat = if expect_anchor_channel { 25_000 } else { 0 };
730+
let node_a_anchor_reserve_sat =
731+
if expect_anchor_channel { get_anchor_reserve_per_channel() } else { 0 };
729732
let node_a_upper_bound_sat =
730733
premine_amount_sat - node_a_anchor_reserve_sat - funding_amount_sat;
731734
let node_a_lower_bound_sat = premine_amount_sat
@@ -746,7 +749,7 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
746749
{
747750
0
748751
} else {
749-
25_000
752+
get_anchor_reserve_per_channel()
750753
};
751754
assert_eq!(
752755
node_b.list_balances().spendable_onchain_balance_sats,

tests/integration_tests_rust.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use common::{
2626
setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
2727
};
2828
use ldk_node::config::{AsyncPaymentsRole, EsploraSyncConfig};
29+
use ldk_node::get_anchor_reserve_per_channel;
2930
use ldk_node::liquidity::LSPS2ServiceConfig;
3031
use ldk_node::payment::{
3132
ConfirmationStatus, PaymentDetails, PaymentDirection, PaymentKind, PaymentStatus,
@@ -317,7 +318,7 @@ fn onchain_send_receive() {
317318
let unchecked_address = Address::<NetworkUnchecked>::from_str(static_address).unwrap();
318319
let addr_c = unchecked_address.assume_checked();
319320

320-
let premine_amount_sat = 1_100_000;
321+
let premine_amount_sat = 2_100_000;
321322
premine_and_distribute_funds(
322323
&bitcoind.client,
323324
&electrsd.client,
@@ -349,7 +350,7 @@ fn onchain_send_receive() {
349350
}
350351

351352
let channel_amount_sat = 1_000_000;
352-
let reserve_amount_sat = 25_000;
353+
let reserve_amount_sat = get_anchor_reserve_per_channel();
353354
open_channel(&node_b, &node_a, channel_amount_sat, true, &electrsd);
354355
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);
355356

@@ -514,8 +515,8 @@ fn onchain_send_all_retains_reserve() {
514515
let addr_a = node_a.onchain_payment().new_address().unwrap();
515516
let addr_b = node_b.onchain_payment().new_address().unwrap();
516517

517-
let premine_amount_sat = 1_000_000;
518-
let reserve_amount_sat = 25_000;
518+
let premine_amount_sat = 2_000_000;
519+
let reserve_amount_sat = get_anchor_reserve_per_channel();
519520
let onchain_fee_buffer_sat = 1000;
520521
premine_and_distribute_funds(
521522
&bitcoind.client,

0 commit comments

Comments
 (0)