Skip to content
Open
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
1 change: 0 additions & 1 deletion bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ dictionary Config {

dictionary AnchorChannelsConfig {
sequence<PublicKey> trusted_peers_no_reserve;
u64 per_channel_reserve_sats;
};

dictionary BackgroundSyncConfig {
Expand Down
26 changes: 1 addition & 25 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const DEFAULT_BDK_WALLET_SYNC_INTERVAL_SECS: u64 = 80;
const DEFAULT_LDK_WALLET_SYNC_INTERVAL_SECS: u64 = 30;
const DEFAULT_FEE_RATE_CACHE_UPDATE_INTERVAL_SECS: u64 = 60 * 10;
const DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER: u64 = 3;
const DEFAULT_ANCHOR_PER_CHANNEL_RESERVE_SATS: u64 = 25_000;

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

impl Default for AnchorChannelsConfig {
fn default() -> Self {
Self {
trusted_peers_no_reserve: Vec::new(),
per_channel_reserve_sats: DEFAULT_ANCHOR_PER_CHANNEL_RESERVE_SATS,
}
Self { trusted_peers_no_reserve: Vec::new() }
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ use lightning::impl_writeable_tlv_based_enum;
use lightning::ln::channelmanager::PaymentId;
use lightning::ln::types::ChannelId;
use lightning::routing::gossip::NodeId;
use lightning::util::anchor_channel_reserves::{
get_reserve_per_channel, AnchorChannelReserveContext,
};
use lightning::util::config::{
ChannelConfigOverrides, ChannelConfigUpdate, ChannelHandshakeConfigUpdate,
};
Expand Down Expand Up @@ -1108,7 +1111,8 @@ where
{
0
} else {
anchor_channels_config.per_channel_reserve_sats
get_reserve_per_channel(&AnchorChannelReserveContext::default())
.to_sat()
};

if spendable_amount_sats < required_amount_sats {
Expand Down
27 changes: 17 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ use lightning::ln::channel_state::ChannelShutdownState;
use lightning::ln::channelmanager::PaymentId;
use lightning::ln::msgs::SocketAddress;
use lightning::routing::gossip::NodeAlias;
use lightning::util::anchor_channel_reserves::{
get_reserve_per_channel, AnchorChannelReserveContext,
};
use lightning::util::persist::KVStoreSync;
use lightning_background_processor::process_events_async;
use liquidity::{LSPS1Liquidity, LiquiditySource};
Expand Down Expand Up @@ -1069,7 +1072,7 @@ impl Node {
if init_features.requires_anchors_zero_fee_htlc_tx()
&& !c.trusted_peers_no_reserve.contains(&node_id)
{
c.per_channel_reserve_sats
get_reserve_per_channel(&AnchorChannelReserveContext::default()).to_sat()
} else {
0
}
Expand Down Expand Up @@ -1132,13 +1135,11 @@ impl Node {
/// channel counterparty on channel open. This can be useful to start out with the balance not
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
///
/// If Anchor channels are enabled, this will ensure the configured
/// [`AnchorChannelsConfig::per_channel_reserve_sats`] is available and will be retained before
/// opening the channel.
/// If Anchor channels are enabled, this will ensure the reserved amount per
/// channel is available and will be retained before opening the channel.
///
/// Returns a [`UserChannelId`] allowing to locally keep track of the channel.
///
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
pub fn open_channel(
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
Expand Down Expand Up @@ -1167,13 +1168,11 @@ impl Node {
/// channel counterparty on channel open. This can be useful to start out with the balance not
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
///
/// If Anchor channels are enabled, this will ensure the configured
/// [`AnchorChannelsConfig::per_channel_reserve_sats`] is available and will be retained before
/// opening the channel.
/// If Anchor channels are enabled, this will ensure the reserved amount per
/// channel is available and will be retained before opening the channel.
///
/// Returns a [`UserChannelId`] allowing to locally keep track of the channel.
///
/// [`AnchorChannelsConfig::per_channel_reserve_sats`]: crate::config::AnchorChannelsConfig::per_channel_reserve_sats
pub fn open_announced_channel(
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
push_to_counterparty_msat: Option<u64>, channel_config: Option<ChannelConfig>,
Expand Down Expand Up @@ -1580,6 +1579,8 @@ impl_writeable_tlv_based!(NodeMetrics, {
pub(crate) fn total_anchor_channels_reserve_sats(
channel_manager: &ChannelManager, config: &Config,
) -> u64 {
let reserve_sat_per_channel = get_anchor_reserve_per_channel();

config.anchor_channels_config.as_ref().map_or(0, |anchor_channels_config| {
channel_manager
.list_channels()
Expand All @@ -1593,6 +1594,12 @@ pub(crate) fn total_anchor_channels_reserve_sats(
.map_or(false, |t| t.requires_anchors_zero_fee_htlc_tx())
})
.count() as u64
* anchor_channels_config.per_channel_reserve_sats
* reserve_sat_per_channel
})
}

/// Returns the configured anchor channel reserve per channel in satoshis.
pub fn get_anchor_reserve_per_channel() -> u64 {
let context = AnchorChannelReserveContext::default();
get_reserve_per_channel(&context).to_sat()
}
6 changes: 5 additions & 1 deletion src/liquidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ use lightning::ln::channelmanager::{InterceptId, MIN_FINAL_CLTV_EXPIRY_DELTA};
use lightning::ln::msgs::SocketAddress;
use lightning::ln::types::ChannelId;
use lightning::routing::router::{RouteHint, RouteHintHop};
use lightning::util::anchor_channel_reserves::{
get_reserve_per_channel, AnchorChannelReserveContext,
};
use lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, InvoiceBuilder, RoutingFees};
use lightning_liquidity::events::LiquidityEvent;
use lightning_liquidity::lsps0::ser::{LSPSDateTime, LSPSRequestId};
Expand Down Expand Up @@ -672,7 +675,8 @@ where
if init_features.requires_anchors_zero_fee_htlc_tx()
&& !c.trusted_peers_no_reserve.contains(&their_network_key)
{
c.per_channel_reserve_sats
get_reserve_per_channel(&AnchorChannelReserveContext::default())
.to_sat()
} else {
0
}
Expand Down
9 changes: 6 additions & 3 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use electrsd::corepc_node::{Client as BitcoindClient, Node as BitcoinD};
use electrsd::{corepc_node, ElectrsD};
use electrum_client::ElectrumApi;
use ldk_node::config::{AsyncPaymentsRole, Config, ElectrumSyncConfig, EsploraSyncConfig};
use ldk_node::get_anchor_reserve_per_channel;
use ldk_node::io::sqlite_store::SqliteStore;
use ldk_node::payment::{PaymentDirection, PaymentKind, PaymentStatus};
use ldk_node::{
Expand Down Expand Up @@ -640,8 +641,9 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
let addr_a = node_a.onchain_payment().new_address().unwrap();
let addr_b = node_b.onchain_payment().new_address().unwrap();

let premine_amount_sat = if expect_anchor_channel { 2_125_000 } else { 2_100_000 };
let anchor_reserve = if expect_anchor_channel { get_anchor_reserve_per_channel() } else { 0 };

let premine_amount_sat = 2_100_000 + anchor_reserve;
premine_and_distribute_funds(
&bitcoind,
electrsd,
Expand Down Expand Up @@ -725,7 +727,8 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
);

let onchain_fee_buffer_sat = 5000;
let node_a_anchor_reserve_sat = if expect_anchor_channel { 25_000 } else { 0 };
let node_a_anchor_reserve_sat =
if expect_anchor_channel { get_anchor_reserve_per_channel() } else { 0 };
let node_a_upper_bound_sat =
premine_amount_sat - node_a_anchor_reserve_sat - funding_amount_sat;
let node_a_lower_bound_sat = premine_amount_sat
Expand All @@ -746,7 +749,7 @@ pub(crate) fn do_channel_full_cycle<E: ElectrumApi>(
{
0
} else {
25_000
get_anchor_reserve_per_channel()
};
assert_eq!(
node_b.list_balances().spendable_onchain_balance_sats,
Expand Down
9 changes: 5 additions & 4 deletions tests/integration_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use common::{
setup_two_nodes, wait_for_tx, TestChainSource, TestSyncStore,
};
use ldk_node::config::{AsyncPaymentsRole, EsploraSyncConfig};
use ldk_node::get_anchor_reserve_per_channel;
use ldk_node::liquidity::LSPS2ServiceConfig;
use ldk_node::payment::{
ConfirmationStatus, PaymentDetails, PaymentDirection, PaymentKind, PaymentStatus,
Expand Down Expand Up @@ -317,7 +318,7 @@ fn onchain_send_receive() {
let unchecked_address = Address::<NetworkUnchecked>::from_str(static_address).unwrap();
let addr_c = unchecked_address.assume_checked();

let premine_amount_sat = 1_100_000;
let premine_amount_sat = 2_100_000;
premine_and_distribute_funds(
&bitcoind.client,
&electrsd.client,
Expand Down Expand Up @@ -349,7 +350,7 @@ fn onchain_send_receive() {
}

let channel_amount_sat = 1_000_000;
let reserve_amount_sat = 25_000;
let reserve_amount_sat = get_anchor_reserve_per_channel();
open_channel(&node_b, &node_a, channel_amount_sat, true, &electrsd);
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);

Expand Down Expand Up @@ -514,8 +515,8 @@ fn onchain_send_all_retains_reserve() {
let addr_a = node_a.onchain_payment().new_address().unwrap();
let addr_b = node_b.onchain_payment().new_address().unwrap();

let premine_amount_sat = 1_000_000;
let reserve_amount_sat = 25_000;
let premine_amount_sat = 2_000_000;
let reserve_amount_sat = get_anchor_reserve_per_channel();
let onchain_fee_buffer_sat = 1000;
premine_and_distribute_funds(
&bitcoind.client,
Expand Down
Loading