Skip to content

Commit aff986a

Browse files
amackillopFernando Ledesma
authored andcommitted
make minimum channel reserve configurable (#1)
Add configurable min_their_channel_reserve_satoshis field to ChannelHandshakeConfig, allowing users to set the minimum channel reserve value. Special case: When set to 0, the dust limit check is bypassed. This enables LSP use cases where clients are able to fully withdraw their funds from the channel without closing it. For non-zero values below the dust limit, validation still enforces the dust limit. Replaces hardcoded MIN_THEIR_CHAN_RESERVE_SATOSHIS constant with configurable value while maintaining backward compatibility. Default remains 1000 sats to preserve existing behavior.
1 parent 1c1755f commit aff986a

File tree

7 files changed

+331
-121
lines changed

7 files changed

+331
-121
lines changed

lightning-liquidity/src/lsps4/htlc_store.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use lightning::util::ser::{Readable, Writeable};
99
use lightning::{impl_writeable_tlv_based, log_error};
1010
use lightning::ln::channelmanager::InterceptId;
1111
use lightning::util::logger::Logger;
12-
use lightning::util::persist::KVStore;
12+
use lightning::util::persist::KVStoreSync;
1313
use lightning_types::payment::PaymentHash;
1414

1515
use bitcoin::secp256k1::PublicKey;
@@ -97,30 +97,30 @@ impl_writeable_tlv_based!(InterceptedHtlc, {
9797
});
9898

9999
pub struct HTLCStore<L: Deref, KV: Deref + Clone>
100-
where L::Target: Logger, KV::Target: KVStore {
100+
where L::Target: Logger, KV::Target: KVStoreSync {
101101
htlcs: Mutex<HashMap<InterceptId, InterceptedHtlc>>,
102102
kv_store: KV,
103103
logger: L
104104
}
105105

106106
impl<L: Deref, KV: Deref + Clone> HTLCStore<L, KV>
107-
where L::Target: Logger, KV::Target: KVStore {
108-
pub(crate) async fn new(
107+
where L::Target: Logger, KV::Target: KVStoreSync {
108+
pub(crate) fn new(
109109
kv_store: KV, logger: L,
110110
) -> Result<Self, io::Error> {
111111
let mut htlcs = Vec::new();
112112

113113
let stored_keys = kv_store.list(
114114
INTERCEPTED_HTLC_STORE_PERSISTENCE_PRIMARY_NAMESPACE,
115115
INTERCEPTED_HTLC_STORE_PERSISTENCE_SECONDARY_NAMESPACE,
116-
).await?;
116+
)?;
117117

118118
for stored_key in stored_keys {
119119
let data = kv_store.read(
120120
INTERCEPTED_HTLC_STORE_PERSISTENCE_PRIMARY_NAMESPACE,
121121
INTERCEPTED_HTLC_STORE_PERSISTENCE_SECONDARY_NAMESPACE,
122122
&stored_key,
123-
).await?;
123+
)?;
124124
let mut reader = Cursor::new(data);
125125
let htlc = InterceptedHtlc::read(&mut reader).map_err(|e| {
126126
log_error!(logger, "Failed to deserialize InterceptedHtlc: {}", e);
@@ -138,7 +138,7 @@ where L::Target: Logger, KV::Target: KVStore {
138138
Ok(Self { htlcs, kv_store, logger })
139139
}
140140

141-
pub(crate) async fn insert(&self, htlc: InterceptedHtlc) -> Result<bool, io::Error> {
141+
pub(crate) fn insert(&self, htlc: InterceptedHtlc) -> Result<bool, io::Error> {
142142
// Check if already exists
143143
{
144144
let locked_htlcs = self.htlcs.lock().unwrap();
@@ -147,22 +147,21 @@ where L::Target: Logger, KV::Target: KVStore {
147147
}
148148
}
149149

150-
// Persist first (outside the lock to avoid holding across await)
151-
self.persist(&htlc).await?;
150+
// Persist first (outside the lock)
151+
self.persist(&htlc)?;
152152

153153
// Then insert into the map
154154
let mut locked_htlcs = self.htlcs.lock().unwrap();
155155
let updated = locked_htlcs.insert(htlc.id(), htlc).is_some();
156156
Ok(updated)
157157
}
158158

159-
pub(crate) async fn remove(&self, id: &InterceptId) -> Result<(), io::Error> {
159+
pub(crate) fn remove(&self, id: &InterceptId) -> Result<(), io::Error> {
160160
let removed = self.htlcs.lock().unwrap().remove(id).is_some();
161161
if removed {
162162
let store_key = utils::to_string(&id.0);
163163
self.kv_store
164164
.remove(INTERCEPTED_HTLC_STORE_PERSISTENCE_PRIMARY_NAMESPACE, INTERCEPTED_HTLC_STORE_PERSISTENCE_SECONDARY_NAMESPACE, &store_key, false)
165-
.await
166165
.map_err(|e| {
167166
log_error!(
168167
self.logger,
@@ -199,12 +198,11 @@ where L::Target: Logger, KV::Target: KVStore {
199198
})
200199
}
201200

202-
async fn persist(&self, htlc: &InterceptedHtlc) -> Result<(), io::Error> {
201+
fn persist(&self, htlc: &InterceptedHtlc) -> Result<(), io::Error> {
203202
let store_key = utils::to_string(&htlc.id().0);
204203
let data = htlc.encode();
205204
self.kv_store
206205
.write(INTERCEPTED_HTLC_STORE_PERSISTENCE_PRIMARY_NAMESPACE, INTERCEPTED_HTLC_STORE_PERSISTENCE_SECONDARY_NAMESPACE, &store_key, data)
207-
.await
208206
.map_err(|e| {
209207
log_error!(
210208
self.logger,
@@ -217,7 +215,7 @@ where L::Target: Logger, KV::Target: KVStore {
217215
Ok(())
218216
}
219217

220-
pub async fn add_intercepted_htlc(
218+
pub fn add_intercepted_htlc(
221219
&self, intercept_id: InterceptId, requested_next_hop_scid: u64,
222220
expected_outbound_amount_msat: u64, payment_hash: PaymentHash, next_node_id: PublicKey,
223221
) -> Result<bool, io::Error> {
@@ -228,6 +226,6 @@ where L::Target: Logger, KV::Target: KVStore {
228226
payment_hash,
229227
next_node_id,
230228
);
231-
self.insert(htlc).await
229+
self.insert(htlc)
232230
}
233231
}

lightning-liquidity/src/lsps4/scid_store.rs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use lightning::util::ser::{Readable, Writeable};
99
use lightning::{impl_writeable_tlv_based, log_error};
1010
use lightning::util::logger::Logger;
11-
use lightning::util::persist::KVStore;
11+
use lightning::util::persist::KVStoreSync;
1212

1313
use bitcoin::secp256k1::PublicKey;
1414

@@ -62,31 +62,31 @@ impl_writeable_tlv_based!(ScidWithPeer, {
6262
});
6363

6464
pub struct ScidStore<L: Deref, KV: Deref + Clone>
65-
where L::Target: Logger, KV::Target: KVStore {
65+
where L::Target: Logger, KV::Target: KVStoreSync {
6666
peer_by_scid: RwLock<HashMap<u64, PublicKey>>,
6767
scid_by_peer: RwLock<HashMap<PublicKey, u64>>,
6868
kv_store: KV,
6969
logger: L
7070
}
7171

7272
impl<L: Deref, KV: Deref + Clone> ScidStore<L, KV>
73-
where L::Target: Logger, KV::Target: KVStore {
74-
pub(crate) async fn new(
73+
where L::Target: Logger, KV::Target: KVStoreSync {
74+
pub(crate) fn new(
7575
kv_store: KV, logger: L,
7676
) -> Result<Self, io::Error> {
7777
let mut scids = Vec::new();
7878

7979
let stored_keys = kv_store.list(
8080
INTERCEPT_SCID_STORE_PERSISTENCE_PRIMARY_NAMESPACE,
8181
INTERCEPT_SCID_STORE_PERSISTENCE_SECONDARY_NAMESPACE,
82-
).await?;
82+
)?;
8383

8484
for stored_key in stored_keys {
8585
let data = kv_store.read(
8686
INTERCEPT_SCID_STORE_PERSISTENCE_PRIMARY_NAMESPACE,
8787
INTERCEPT_SCID_STORE_PERSISTENCE_SECONDARY_NAMESPACE,
8888
&stored_key,
89-
).await?;
89+
)?;
9090
let mut reader = Cursor::new(data);
9191
let scid = ScidWithPeer::read(&mut reader).map_err(|e| {
9292
log_error!(logger, "Failed to deserialize InterceptScid: {}", e);
@@ -107,19 +107,31 @@ where L::Target: Logger, KV::Target: KVStore {
107107
Ok(Self { peer_by_scid, scid_by_peer, kv_store, logger })
108108
}
109109

110-
pub(crate) async fn insert(&self, scid: ScidWithPeer) -> Result<bool, io::Error> {
111-
// Persist first (outside the lock to avoid holding across await)
112-
self.persist(&scid).await?;
110+
pub(crate) fn insert(&self, scid: ScidWithPeer) -> Result<bool, io::Error> {
111+
use lightning::log_info;
112+
log_info!(self.logger, "[LSPS4 ScidStore] Inserting SCID {} for peer {}", scid.scid(), scid.peer_id());
113+
114+
// Persist first
115+
self.persist(&scid)?;
113116

114117
// Then insert into the maps
115118
let mut locked_peer_by_scid = self.peer_by_scid.write().unwrap();
116119
let mut locked_scid_by_peer = self.scid_by_peer.write().unwrap();
117120
let updated = locked_peer_by_scid.insert(scid.scid(), scid.peer_id().clone()).is_some();
118121
locked_scid_by_peer.insert(scid.peer_id().clone(), scid.scid());
122+
123+
log_info!(
124+
self.logger,
125+
"[LSPS4 ScidStore] Successfully inserted SCID {} for peer {} (was_update: {})",
126+
scid.scid(),
127+
scid.peer_id(),
128+
updated
129+
);
130+
119131
Ok(updated)
120132
}
121133

122-
pub(crate) async fn remove(&self, scid: u64) -> Result<(), io::Error> {
134+
pub(crate) fn remove(&self, scid: u64) -> Result<(), io::Error> {
123135
let mut locked_peer_by_scid = self.peer_by_scid.write().unwrap();
124136
let mut locked_scid_by_peer = self.scid_by_peer.write().unwrap();
125137

@@ -129,7 +141,6 @@ where L::Target: Logger, KV::Target: KVStore {
129141
let store_key = utils::to_string(&scid.to_be_bytes());
130142
self.kv_store
131143
.remove(INTERCEPT_SCID_STORE_PERSISTENCE_PRIMARY_NAMESPACE, INTERCEPT_SCID_STORE_PERSISTENCE_SECONDARY_NAMESPACE, &store_key, false)
132-
.await
133144
.map_err(|e| {
134145
log_error!(
135146
self.logger,
@@ -143,12 +154,11 @@ where L::Target: Logger, KV::Target: KVStore {
143154
Ok(())
144155
}
145156

146-
async fn persist(&self, scid: &ScidWithPeer) -> Result<(), io::Error> {
157+
fn persist(&self, scid: &ScidWithPeer) -> Result<(), io::Error> {
147158
let store_key = scid.store_key();
148159
let data = scid.encode();
149160
self.kv_store
150161
.write(INTERCEPT_SCID_STORE_PERSISTENCE_PRIMARY_NAMESPACE, INTERCEPT_SCID_STORE_PERSISTENCE_SECONDARY_NAMESPACE, &store_key, data)
151-
.await
152162
.map_err(|e| {
153163
log_error!(
154164
self.logger,
@@ -161,21 +171,37 @@ where L::Target: Logger, KV::Target: KVStore {
161171
Ok(())
162172
}
163173

164-
pub async fn add_intercepted_scid(
174+
pub fn add_intercepted_scid(
165175
&self, scid: u64, peer_id: PublicKey,
166176
) -> Result<bool, io::Error> {
167177
let scid = ScidWithPeer::new(
168178
scid,
169179
peer_id,
170180
);
171-
self.insert(scid).await
181+
self.insert(scid)
172182
}
173183

174184
pub fn get_peer(&self, scid: u64) -> Option<PublicKey> {
175-
self.peer_by_scid.read().unwrap().get(&scid).cloned()
185+
use lightning::log_debug;
186+
let result = self.peer_by_scid.read().unwrap().get(&scid).cloned();
187+
log_debug!(
188+
self.logger,
189+
"[LSPS4 ScidStore] get_peer({}) = {:?}",
190+
scid,
191+
result
192+
);
193+
result
176194
}
177195

178196
pub fn get_scid(&self, peer_id: &PublicKey) -> Option<u64> {
179-
self.scid_by_peer.read().unwrap().get(peer_id).cloned()
197+
use lightning::log_debug;
198+
let result = self.scid_by_peer.read().unwrap().get(peer_id).cloned();
199+
log_debug!(
200+
self.logger,
201+
"[LSPS4 ScidStore] get_scid({}) = {:?}",
202+
peer_id,
203+
result
204+
);
205+
result
180206
}
181207
}

0 commit comments

Comments
 (0)