Drop Deref indirection for KVStore
What changed, and why it matters
This commit is a code cleanup change in the Lightning Dev Kit Rust library. It removes an extra layer of pointer-like wrapping (called Deref indirection) around the key-value store trait (KVStore). The stated goal is to reduce generic type complexity and verbosity. The change does not alter how data is stored or encrypted, and the commit message does not describe it as a security fix. A new blanket implementation is added so that any wrapper type that can be dereferenced to a KVStore still behaves like a KVStore, preserving backward compatibility for callers that pass references or smart pointers.
No immediate security action required. Treat as a normal refactoring commit. Reviewers may want to confirm that the new blanket KVStore implementation does not introduce ambiguity with the existing `KVStoreSyncWrapper` impl or downstream custom wrappers, and that the documentation warning about shared KVStore references is followed in consuming code.
Security signals we found
Refactoring of generic trait bounds only; no logic changes to read/write/remove/list implementations
New blanket implementation delegates KVStore methods via Deref, preserving existing call semantics
Documentation added warning that KVStore should be shared by reference across node components
No mention of vulnerability, CVE, security bug, or exploit in commit message or diff
Evidence from the diff
The patch refactors generic bounds from K: Deref where K::Target: KVStore to K: KVStore across lightning-liquidity, lightning-background-processor, lightning::chain::chainmonitor, lightning::util::persist, and lightning::util::sweep. To keep existing call sites working, a blanket impl<K> KVStore for K where K: Deref, K::Target: KVStore is introduced in lightning/src/util/persist.rs. This delegates read, write, remove, and list through Deref. The KVStoreSyncWrapper loses its own Deref impl because the blanket impl now covers it. Documentation is updated to warn that KVStore instances should generally be shared by reference across components. No behavioral changes to persistence, serialization, or cryptography are visible in the diff.
Changed components
lightning-background-processor/src/lib.rslightning-liquidity/src/events/event_queue.rslightning-liquidity/src/lsps0/client.rslightning-liquidity/src/lsps1/client.rslightning-liquidity/src/lsps1/service.rslightning-liquidity/src/lsps2/client.rslightning-liquidity/src/lsps2/service.rslightning-liquidity/src/lsps5/client.rslightning-liquidity/src/lsps5/service.rslightning-liquidity/src/manager.rslightning-liquidity/src/persist.rslightning/src/chain/chainmonitor.rslightning/src/util/persist.rslightning/src/util/sweep.rsInspect captured patch +110 / −189
diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs
index 79a3b95..a16933f 100644
--- a/lightning-background-processor/src/lib.rs
+++ b/lightning-background-processor/src/lib.rs
@@ -474,7 +474,6 @@ pub const NO_LIQUIDITY_MANAGER: Option<
CM = &DynChannelManager,
Filter = dyn chain::Filter + Send + Sync,
C = &(dyn chain::Filter + Send + Sync),
- KVStore = DummyKVStore,
K = &DummyKVStore,
TimeProvider = dyn lightning_liquidity::utils::time::TimeProvider + Send + Sync,
TP = &(dyn lightning_liquidity::utils::time::TimeProvider + Send + Sync),
@@ -955,7 +954,7 @@ pub async fn process_events_async<
LM: Deref,
D: Deref,
O: Deref,
- K: Deref,
+ K: KVStore,
OS: Deref<Target = OutputSweeper<T, D, F, CF, K, L, O>>,
S: Deref<Target = SC>,
SC: for<'b> WriteableScore<'b>,
@@ -978,7 +977,6 @@ where
LM::Target: ALiquidityManager,
O::Target: OutputSpender,
D::Target: ChangeDestinationSource,
- K::Target: KVStore,
{
let async_event_handler = |event| {
let network_graph = gossip_sync.network_graph();
diff --git a/lightning-liquidity/src/events/event_queue.rs b/lightning-liquidity/src/events/event_queue.rs
index 0d6e3a0..9fb8a25 100644
--- a/lightning-liquidity/src/events/event_queue.rs
+++ b/lightning-liquidity/src/events/event_queue.rs
@@ -12,7 +12,6 @@ use alloc::collections::VecDeque;
use alloc::vec::Vec;
use core::future::Future;
-use core::ops::Deref;
use core::task::{Poll, Waker};
use lightning::ln::msgs::DecodeError;
@@ -25,10 +24,7 @@ use lightning::util::wakers::Notifier;
/// The maximum queue size we allow before starting to drop events.
pub const MAX_EVENT_QUEUE_SIZE: usize = 1000;
-pub(crate) struct EventQueue<K: Deref + Clone>
-where
- K::Target: KVStore,
-{
+pub(crate) struct EventQueue<K: KVStore + Clone> {
state: Mutex<QueueState>,
waker: Mutex<Option<Waker>>,
#[cfg(feature = "std")]
@@ -37,10 +33,7 @@ where
persist_notifier: Arc<Notifier>,
}
-impl<K: Deref + Clone> EventQueue<K>
-where
- K::Target: KVStore,
-{
+impl<K: KVStore + Clone> EventQueue<K> {
pub fn new(
queue: VecDeque<LiquidityEvent>, kv_store: K, persist_notifier: Arc<Notifier>,
) -> Self {
@@ -164,14 +157,9 @@ struct QueueState {
// A guard type that will notify about new events when dropped.
#[must_use]
-pub(crate) struct EventQueueNotifierGuard<'a, K: Deref + Clone>(&'a EventQueue<K>)
-where
- K::Target: KVStore;
-
-impl<'a, K: Deref + Clone> EventQueueNotifierGuard<'a, K>
-where
- K::Target: KVStore,
-{
+pub(crate) struct EventQueueNotifierGuard<'a, K: KVStore + Clone>(&'a EventQueue<K>);
+
+impl<'a, K: KVStore + Clone> EventQueueNotifierGuard<'a, K> {
pub fn enqueue<E: Into<LiquidityEvent>>(&self, event: E) {
let mut state_lock = self.0.state.lock().unwrap();
if state_lock.queue.len() < MAX_EVENT_QUEUE_SIZE {
@@ -183,10 +171,7 @@ where
}
}
-impl<'a, K: Deref + Clone> Drop for EventQueueNotifierGuard<'a, K>
-where
- K::Target: KVStore,
-{
+impl<'a, K: KVStore + Clone> Drop for EventQueueNotifierGuard<'a, K> {
fn drop(&mut self) {
let (should_notify, should_persist_notify) = {
let state_lock = self.0.state.lock().unwrap();
@@ -208,14 +193,9 @@ where
}
}
-struct EventFuture<'a, K: Deref + Clone>(&'a EventQueue<K>)
-where
- K::Target: KVStore;
+struct EventFuture<'a, K: KVStore + Clone>(&'a EventQueue<K>);
-impl<K: Deref + Clone> Future for EventFuture<'_, K>
-where
- K::Target: KVStore,
-{
+impl<K: KVStore + Clone> Future for EventFuture<'_, K> {
type Output = LiquidityEvent;
fn poll(
diff --git a/lightning-liquidity/src/lsps0/client.rs b/lightning-liquidity/src/lsps0/client.rs
index 776e9d3..298cb30 100644
--- a/lightning-liquidity/src/lsps0/client.rs
+++ b/lightning-liquidity/src/lsps0/client.rs
@@ -22,22 +22,14 @@ use lightning::util::persist::KVStore;
use bitcoin::secp256k1::PublicKey;
-use core::ops::Deref;
-
/// A message handler capable of sending and handling bLIP-50 / LSPS0 messages.
-pub struct LSPS0ClientHandler<ES: EntropySource, K: Deref + Clone>
-where
- K::Target: KVStore,
-{
+pub struct LSPS0ClientHandler<ES: EntropySource, K: KVStore + Clone> {
entropy_source: ES,
pending_messages: Arc<MessageQueue>,
pending_events: Arc<EventQueue<K>>,
}
-impl<ES: EntropySource, K: Deref + Clone> LSPS0ClientHandler<ES, K>
-where
- K::Target: KVStore,
-{
+impl<ES: EntropySource, K: KVStore + Clone> LSPS0ClientHandler<ES, K> {
/// Returns a new instance of [`LSPS0ClientHandler`].
pub(crate) fn new(
entropy_source: ES, pending_messages: Arc<MessageQueue>, pending_events: Arc<EventQueue<K>>,
@@ -87,9 +79,8 @@ where
}
}
-impl<ES: EntropySource, K: Deref + Clone> LSPSProtocolMessageHandler for LSPS0ClientHandler<ES, K>
-where
- K::Target: KVStore,
+impl<ES: EntropySource, K: KVStore + Clone> LSPSProtocolMessageHandler
+ for LSPS0ClientHandler<ES, K>
{
type ProtocolMessage = LSPS0Message;
const PROTOCOL_NUMBER: Option<u16> = None;
diff --git a/lightning-liquidity/src/lsps1/client.rs b/lightning-liquidity/src/lsps1/client.rs
index 1e5b2e3..2cbfb04 100644
--- a/lightning-liquidity/src/lsps1/client.rs
+++ b/lightning-liquidity/src/lsps1/client.rs
@@ -30,8 +30,6 @@ use lightning::util::persist::KVStore;
use bitcoin::secp256k1::PublicKey;
use bitcoin::Address;
-use core::ops::Deref;
-
/// Client-side configuration options for bLIP-51 / LSPS1 channel requests.
#[derive(Clone, Debug)]
pub struct LSPS1ClientConfig {
@@ -47,10 +45,7 @@ struct PeerState {
}
/// The main object allowing to send and receive bLIP-51 / LSPS1 messages.
-pub struct LSPS1ClientHandler<ES: EntropySource, K: Deref + Clone>
-where
- K::Target: KVStore,
-{
+pub struct LSPS1ClientHandler<ES: EntropySource, K: KVStore + Clone> {
entropy_source: ES,
pending_messages: Arc<MessageQueue>,
pending_events: Arc<EventQueue<K>>,
@@ -58,10 +53,7 @@ where
config: LSPS1ClientConfig,
}
-impl<ES: EntropySource, K: Deref + Clone> LSPS1ClientHandler<ES, K>
-where
- K::Target: KVStore,
-{
+impl<ES: EntropySource, K: KVStore + Clone> LSPS1ClientHandler<ES, K> {
/// Constructs an `LSPS1ClientHandler`.
pub(crate) fn new(
entropy_source: ES, pending_messages: Arc<MessageQueue>,
@@ -430,9 +422,8 @@ where
}
}
-impl<ES: EntropySource, K: Deref + Clone> LSPSProtocolMessageHandler for LSPS1ClientHandler<ES, K>
-where
- K::Target: KVStore,
+impl<ES: EntropySource, K: KVStore + Clone> LSPSProtocolMessageHandler
+ for LSPS1ClientHandler<ES, K>
{
type ProtocolMessage = LSPS1Message;
const PROTOCOL_NUMBER: Option<u16> = Some(1);
diff --git a/lightning-liquidity/src/lsps1/service.rs b/lightning-liquidity/src/lsps1/service.rs
index 76a9a43..154c6f5 100644
--- a/lightning-liquidity/src/lsps1/service.rs
+++ b/lightning-liquidity/src/lsps1/service.rs
@@ -132,11 +132,10 @@ impl PeerState {
}
/// The main object allowing to send and receive bLIP-51 / LSPS1 messages.
-pub struct LSPS1ServiceHandler<ES: EntropySource, CM: Deref + Clone, C: Deref, K: Deref + Clone>
+pub struct LSPS1ServiceHandler<ES: EntropySource, CM: Deref + Clone, C: Deref, K: KVStore + Clone>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
{
entropy_source: ES,
channel_manager: CM,
@@ -147,12 +146,11 @@ where
config: LSPS1ServiceConfig,
}
-impl<ES: EntropySource, CM: Deref + Clone, C: Deref, K: Deref + Clone>
+impl<ES: EntropySource, CM: Deref + Clone, C: Deref, K: KVStore + Clone>
LSPS1ServiceHandler<ES, CM, C, K>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
{
/// Constructs a `LSPS1ServiceHandler`.
pub(crate) fn new(
@@ -419,12 +417,11 @@ where
}
}
-impl<ES: EntropySource, CM: Deref + Clone, C: Deref, K: Deref + Clone> LSPSProtocolMessageHandler
+impl<ES: EntropySource, CM: Deref + Clone, C: Deref, K: KVStore + Clone> LSPSProtocolMessageHandler
for LSPS1ServiceHandler<ES, CM, C, K>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
{
type ProtocolMessage = LSPS1Message;
const PROTOCOL_NUMBER: Option<u16> = Some(1);
diff --git a/lightning-liquidity/src/lsps2/client.rs b/lightning-liquidity/src/lsps2/client.rs
index 2e9fca2..21b5716 100644
--- a/lightning-liquidity/src/lsps2/client.rs
+++ b/lightning-liquidity/src/lsps2/client.rs
@@ -13,7 +13,6 @@ use alloc::string::{String, ToString};
use lightning::util::persist::KVStore;
use core::default::Default;
-use core::ops::Deref;
use crate::events::EventQueue;
use crate::lsps0::ser::{LSPSProtocolMessageHandler, LSPSRequestId, LSPSResponseError};
@@ -68,10 +67,7 @@ impl PeerState {
/// opened. Please refer to the [`bLIP-52 / LSPS2 specification`] for more information.
///
/// [`bLIP-52 / LSPS2 specification`]: https://github.com/lightning/blips/blob/master/blip-0052.md#trust-models
-pub struct LSPS2ClientHandler<ES: EntropySource, K: Deref + Clone>
-where
- K::Target: KVStore,
-{
+pub struct LSPS2ClientHandler<ES: EntropySource, K: KVStore + Clone> {
entropy_source: ES,
pending_messages: Arc<MessageQueue>,
pending_events: Arc<EventQueue<K>>,
@@ -79,10 +75,7 @@ where
config: LSPS2ClientConfig,
}
-impl<ES: EntropySource, K: Deref + Clone> LSPS2ClientHandler<ES, K>
-where
- K::Target: KVStore,
-{
+impl<ES: EntropySource, K: KVStore + Clone> LSPS2ClientHandler<ES, K> {
/// Constructs an `LSPS2ClientHandler`.
pub(crate) fn new(
entropy_source: ES, pending_messages: Arc<MessageQueue>,
@@ -373,9 +366,8 @@ where
}
}
-impl<ES: EntropySource, K: Deref + Clone> LSPSProtocolMessageHandler for LSPS2ClientHandler<ES, K>
-where
- K::Target: KVStore,
+impl<ES: EntropySource, K: KVStore + Clone> LSPSProtocolMessageHandler
+ for LSPS2ClientHandler<ES, K>
{
type ProtocolMessage = LSPS2Message;
const PROTOCOL_NUMBER: Option<u16> = Some(2);
diff --git a/lightning-liquidity/src/lsps2/service.rs b/lightning-liquidity/src/lsps2/service.rs
index 756e8b3..00f68af 100644
--- a/lightning-liquidity/src/lsps2/service.rs
+++ b/lightning-liquidity/src/lsps2/service.rs
@@ -702,10 +702,9 @@ macro_rules! get_or_insert_peer_state_entry {
}
/// The main object allowing to send and receive bLIP-52 / LSPS2 messages.
-pub struct LSPS2ServiceHandler<CM: Deref, K: Deref + Clone, T: BroadcasterInterface>
+pub struct LSPS2ServiceHandler<CM: Deref, K: KVStore + Clone, T: BroadcasterInterface>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
{
channel_manager: CM,
kv_store: K,
@@ -720,10 +719,9 @@ where
persistence_in_flight: AtomicUsize,
}
-impl<CM: Deref, K: Deref + Clone, T: BroadcasterInterface + Clone> LSPS2ServiceHandler<CM, K, T>
+impl<CM: Deref, K: KVStore + Clone, T: BroadcasterInterface + Clone> LSPS2ServiceHandler<CM, K, T>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
{
/// Constructs a `LSPS2ServiceHandler`.
pub(crate) fn new(
@@ -2042,11 +2040,10 @@ where
}
}
-impl<CM: Deref, K: Deref + Clone, T: BroadcasterInterface + Clone> LSPSProtocolMessageHandler
+impl<CM: Deref, K: KVStore + Clone, T: BroadcasterInterface + Clone> LSPSProtocolMessageHandler
for LSPS2ServiceHandler<CM, K, T>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
{
type ProtocolMessage = LSPS2Message;
const PROTOCOL_NUMBER: Option<u16> = Some(2);
@@ -2116,19 +2113,21 @@ fn calculate_amount_to_forward_per_htlc(
/// A synchroneous wrapper around [`LSPS2ServiceHandler`] to be used in contexts where async is not
/// available.
-pub struct LSPS2ServiceHandlerSync<'a, CM: Deref, K: Deref + Clone, T: BroadcasterInterface + Clone>
-where
+pub struct LSPS2ServiceHandlerSync<
+ 'a,
+ CM: Deref,
+ K: KVStore + Clone,
+ T: BroadcasterInterface + Clone,
+> where
CM::Target: AChannelManager,
- K::Target: KVStore,
{
inner: &'a LSPS2ServiceHandler<CM, K, T>,
}
-impl<'a, CM: Deref, K: Deref + Clone, T: BroadcasterInterface + Clone>
+impl<'a, CM: Deref, K: KVStore + Clone, T: BroadcasterInterface + Clone>
LSPS2ServiceHandlerSync<'a, CM, K, T>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
{
pub(crate) fn from_inner(inner: &'a LSPS2ServiceHandler<CM, K, T>) -> Self {
Self { inner }
diff --git a/lightning-liquidity/src/lsps5/client.rs b/lightning-liquidity/src/lsps5/client.rs
index df10522..26c0b18 100644
--- a/lightning-liquidity/src/lsps5/client.rs
+++ b/lightning-liquidity/src/lsps5/client.rs
@@ -35,8 +35,6 @@ use alloc::collections::VecDeque;
use alloc::string::String;
use lightning::util::persist::KVStore;
-use core::ops::Deref;
-
impl PartialEq<LSPSRequestId> for (LSPSRequestId, (LSPS5AppName, LSPS5WebhookUrl)) {
fn eq(&self, other: &LSPSRequestId) -> bool {
&self.0 == other
@@ -125,10 +123,7 @@ impl PeerState {
/// [`lsps5.list_webhooks`]: super::msgs::LSPS5Request::ListWebhooks
/// [`lsps5.remove_webhook`]: super::msgs::LSPS5Request::RemoveWebhook
/// [`LSPS5Validator`]: super::validator::LSPS5Validator
-pub struct LSPS5ClientHandler<ES: EntropySource, K: Deref + Clone>
-where
- K::Target: KVStore,
-{
+pub struct LSPS5ClientHandler<ES: EntropySource, K: KVStore + Clone> {
pending_messages: Arc<MessageQueue>,
pending_events: Arc<EventQueue<K>>,
entropy_source: ES,
@@ -136,10 +131,7 @@ where
_config: LSPS5ClientConfig,
}
-impl<ES: EntropySource, K: Deref + Clone> LSPS5ClientHandler<ES, K>
-where
- K::Target: KVStore,
-{
+impl<ES: EntropySource, K: KVStore + Clone> LSPS5ClientHandler<ES, K> {
/// Constructs an `LSPS5ClientHandler`.
pub(crate) fn new(
entropy_source: ES, pending_messages: Arc<MessageQueue>,
@@ -424,9 +416,8 @@ where
}
}
-impl<ES: EntropySource, K: Deref + Clone> LSPSProtocolMessageHandler for LSPS5ClientHandler<ES, K>
-where
- K::Target: KVStore,
+impl<ES: EntropySource, K: KVStore + Clone> LSPSProtocolMessageHandler
+ for LSPS5ClientHandler<ES, K>
{
type ProtocolMessage = LSPS5Message;
const PROTOCOL_NUMBER: Option<u16> = Some(5);
diff --git a/lightning-liquidity/src/lsps5/service.rs b/lightning-liquidity/src/lsps5/service.rs
index 489d543..4678d38 100644
--- a/lightning-liquidity/src/lsps5/service.rs
+++ b/lightning-liquidity/src/lsps5/service.rs
@@ -125,10 +125,9 @@ impl Default for LSPS5ServiceConfig {
/// [`LSPS5ServiceEvent::SendWebhookNotification`]: super::event::LSPS5ServiceEvent::SendWebhookNotification
/// [`app_name`]: super::msgs::LSPS5AppName
/// [`lsps5.webhook_registered`]: super::msgs::WebhookNotificationMethod::LSPS5WebhookRegistered
-pub struct LSPS5ServiceHandler<CM: Deref, NS: NodeSigner, K: Deref + Clone, TP: Deref>
+pub struct LSPS5ServiceHandler<CM: Deref, NS: NodeSigner, K: KVStore + Clone, TP: Deref>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
config: LSPS5ServiceConfig,
@@ -143,10 +142,9 @@ where
persistence_in_flight: AtomicUsize,
}
-impl<CM: Deref, NS: NodeSigner, K: Deref + Clone, TP: Deref> LSPS5ServiceHandler<CM, NS, K, TP>
+impl<CM: Deref, NS: NodeSigner, K: KVStore + Clone, TP: Deref> LSPS5ServiceHandler<CM, NS, K, TP>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
/// Constructs a `LSPS5ServiceHandler` using the given time provider.
@@ -692,11 +690,10 @@ where
}
}
-impl<CM: Deref, NS: NodeSigner, K: Deref + Clone, TP: Deref> LSPSProtocolMessageHandler
+impl<CM: Deref, NS: NodeSigner, K: KVStore + Clone, TP: Deref> LSPSProtocolMessageHandler
for LSPS5ServiceHandler<CM, NS, K, TP>
where
CM::Target: AChannelManager,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
type ProtocolMessage = LSPS5Message;
diff --git a/lightning-liquidity/src/manager.rs b/lightning-liquidity/src/manager.rs
index 0e897dd..c3e9fa4 100644
--- a/lightning-liquidity/src/manager.rs
+++ b/lightning-liquidity/src/manager.rs
@@ -116,9 +116,7 @@ pub trait ALiquidityManager {
/// A type that may be dereferenced to [`Self::Filter`].
type C: Deref<Target = Self::Filter> + Clone;
/// A type implementing [`KVStore`].
- type KVStore: KVStore + ?Sized;
- /// A type that may be dereferenced to [`Self::KVStore`].
- type K: Deref<Target = Self::KVStore> + Clone;
+ type K: KVStore + Clone;
/// A type implementing [`TimeProvider`].
type TimeProvider: TimeProvider + ?Sized;
/// A type that may be dereferenced to [`Self::TimeProvider`].
@@ -144,14 +142,13 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> ALiquidityManager for LiquidityManager<ES, NS, CM, C, K, TP, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
type EntropySource = ES;
@@ -160,7 +157,6 @@ where
type CM = CM;
type Filter = C::Target;
type C = C;
- type KVStore = K::Target;
type K = K;
type TimeProvider = TP::Target;
type TP = TP;
@@ -294,13 +290,12 @@ pub struct LiquidityManager<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
pending_messages: Arc<MessageQueue>,
@@ -330,13 +325,12 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
T: BroadcasterInterface + Clone,
> LiquidityManager<ES, NS, CM, C, K, DefaultTimeProvider, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
{
/// Constructor for the [`LiquidityManager`] using the default system clock
///
@@ -368,14 +362,13 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> LiquidityManager<ES, NS, CM, C, K, TP, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
/// Constructor for the [`LiquidityManager`] with a custom time provider.
@@ -792,14 +785,13 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> CustomMessageReader for LiquidityManager<ES, NS, CM, C, K, TP, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
type CustomMessage = RawLSPSMessage;
@@ -821,14 +813,13 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> CustomMessageHandler for LiquidityManager<ES, NS, CM, C, K, TP, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
fn handle_custom_message(
@@ -952,14 +943,13 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> Listen for LiquidityManager<ES, NS, CM, C, K, TP, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
fn filtered_block_connected(
@@ -995,14 +985,13 @@ impl<
NS: NodeSigner + Clone,
CM: Deref + Clone,
C: Deref + Clone,
- K: Deref + Clone,
+ K: KVStore + Clone,
TP: Deref + Clone,
T: BroadcasterInterface + Clone,
> Confirm for LiquidityManager<ES, NS, CM, C, K, TP, T>
where
CM::Target: AChannelManager,
C::Target: Filter,
- K::Target: KVStore,
TP::Target: TimeProvider,
{
fn transactions_confirmed(
diff --git a/lightning-liquidity/src/persist.rs b/lightning-liquidity/src/persist.rs
index ec0d5a6..d019944 100644
--- a/lightning-liquidity/src/persist.rs
+++ b/lightning-liquidity/src/persist.rs
@@ -22,8 +22,6 @@ use lightning::util::ser::Readable;
use bitcoin::secp256k1::PublicKey;
use alloc::collections::VecDeque;
-
-use core::ops::Deref;
use core::str::FromStr;
/// The primary namespace under which the [`LiquidityManager`] will be persisted.
@@ -51,12 +49,9 @@ pub const LSPS2_SERVICE_PERSISTENCE_SECONDARY_NAMESPACE: &str = "lsps2_service";
/// [`LSPS5ServiceHandler`]: crate::lsps5::service::LSPS5ServiceHandler
pub const LSPS5_SERVICE_PERSISTENCE_SECONDARY_NAMESPACE: &str = "lsps5_service";
-pub(crate) async fn read_event_queue<K: Deref>(
+pub(crate) async fn read_event_queue<K: KVStore>(
kv_store: K,
-) -> Result<Option<VecDeque<LiquidityEvent>>, lightning::io::Error>
-where
- K::Target: KVStore,
-{
+) -> Result<Option<VecDeque<LiquidityEvent>>, lightning::io::Error> {
let read_fut = kv_store.read(
LIQUIDITY_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE,
LIQUIDITY_MANAGER_EVENT_QUEUE_PERSISTENCE_SECONDARY_NAMESPACE,
@@ -85,12 +80,9 @@ where
Ok(Some(queue.0))
}
-pub(crate) async fn read_lsps2_service_peer_states<K: Deref>(
+pub(crate) async fn read_lsps2_service_peer_states<K: KVStore>(
kv_store: K,
-) -> Result<HashMap<PublicKey, Mutex<LSPS2ServicePeerState>>, lightning::io::Error>
-where
- K::Target: KVStore,
-{
+) -> Result<HashMap<PublicKey, Mutex<LSPS2ServicePeerState>>, lightning::io::Error> {
let mut res = new_hash_map();
for stored_key in kv_store
@@ -129,12 +121,9 @@ where
Ok(res)
}
-pub(crate) async fn read_lsps5_service_peer_states<K: Deref>(
+pub(crate) async fn read_lsps5_service_peer_states<K: KVStore>(
kv_store: K,
-) -> Result<HashMap<PublicKey, LSPS5ServicePeerState>, lightning::io::Error>
-where
- K::Target: KVStore,
-{
+) -> Result<HashMap<PublicKey, LSPS5ServicePeerState>, lightning::io::Error> {
let mut res = new_hash_map();
for stored_key in kv_store
diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs
index 8835e9c..536a1f9 100644
--- a/lightning/src/chain/chainmonitor.rs
+++ b/lightning/src/chain/chainmonitor.rs
@@ -256,22 +256,20 @@ impl<ChannelSigner: EcdsaChannelSigner> Deref for LockedChannelMonitor<'_, Chann
///
/// This is not exported to bindings users as async is not supported outside of Rust.
pub struct AsyncPersister<
- K: Deref + MaybeSend + MaybeSync + 'static,
+ K: KVStore + MaybeSend + MaybeSync + 'static,
S: FutureSpawner,
L: Logger + MaybeSend + MaybeSync + 'static,
ES: EntropySource + MaybeSend + MaybeSync + 'static,
SP: SignerProvider + MaybeSend + MaybeSync + 'static,
BI: BroadcasterInterface + MaybeSend + MaybeSync + 'static,
FE: FeeEstimator + MaybeSend + MaybeSync + 'static,
-> where
- K::Target: KVStore + MaybeSync,
-{
+> {
persister: MonitorUpdatingPersisterAsync<K, S, L, ES, SP, BI, FE>,
event_notifier: Arc<Notifier>,
}
impl<
- K: Deref + MaybeSend + MaybeSync + 'static,
+ K: KVStore + MaybeSend + MaybeSync + 'static,
S: FutureSpawner,
L: Logger + MaybeSend + MaybeSync + 'static,
ES: EntropySource + MaybeSend + MaybeSync + 'static,
@@ -279,8 +277,6 @@ impl<
BI: BroadcasterInterface + MaybeSend + MaybeSync + 'static,
FE: FeeEstimator + MaybeSend + MaybeSync + 'static,
> Deref for AsyncPersister<K, S, L, ES, SP, BI, FE>
-where
- K::Target: KVStore + MaybeSync,
{
type Target = Self;
fn deref(&self) -> &Self {
@@ -289,7 +285,7 @@ where
}
impl<
- K: Deref + MaybeSend + MaybeSync + 'static,
+ K: KVStore + MaybeSend + MaybeSync + 'static,
S: FutureSpawner,
L: Logger + MaybeSend + MaybeSync + 'static,
ES: EntropySource + MaybeSend + MaybeSync + 'static,
@@ -298,7 +294,6 @@ impl<
FE: FeeEstimator + MaybeSend + MaybeSync + 'static,
> Persist<SP::EcdsaSigner> for AsyncPersister<K, S, L, ES, SP, BI, FE>
where
- K::Target: KVStore + MaybeSync,
SP::EcdsaSigner: MaybeSend + 'static,
{
fn persist_new_channel(
@@ -380,7 +375,7 @@ pub struct ChainMonitor<
}
impl<
- K: Deref + MaybeSend + MaybeSync + 'static,
+ K: KVStore + MaybeSend + MaybeSync + 'static,
S: FutureSpawner,
SP: SignerProvider + MaybeSend + MaybeSync + 'static,
C: Deref,
@@ -390,7 +385,6 @@ impl<
ES: EntropySource + MaybeSend + MaybeSync + 'static,
> ChainMonitor<SP::EcdsaSigner, C, T, F, L, AsyncPersister<K, S, L, ES, SP, T, F>, ES>
where
- K::Target: KVStore + MaybeSync,
C::Target: chain::Filter,
SP::EcdsaSigner: MaybeSend + 'static,
{
diff --git a/lightning/src/util/persist.rs b/lightning/src/util/persist.rs
index 7742abf..440d1d3 100644
--- a/lightning/src/util/persist.rs
+++ b/lightning/src/util/persist.rs
@@ -202,16 +202,6 @@ pub struct KVStoreSyncWrapper<K: Deref>(pub K)
where
K::Target: KVStoreSync;
-impl<K: Deref> Deref for KVStoreSyncWrapper<K>
-where
- K::Target: KVStoreSync,
-{
- type Target = Self;
- fn deref(&self) -> &Self::Target {
- self
- }
-}
-
/// This is not exported to bindings users as async is only supported in Rust.
impl<K: Deref> KVStore for KVStoreSyncWrapper<K>
where
@@ -268,6 +258,10 @@ where
/// namespace, i.e., conflicts between keys and equally named
/// primary namespaces/secondary namespaces must be avoided.
///
+/// Instantiations of this trait should generally be shared by reference across the lightning
+/// node's components. E.g., it would be unsafe to provide a different [`KVStore`] to
+/// [`OutputSweeper`] vs [`MonitorUpdatingPersister`].
+///
/// **Note:** Users migrating custom persistence backends from the pre-v0.0.117 `KVStorePersister`
/// interface can use a concatenation of `[{primary_namespace}/[{secondary_namespace}/]]{key}` to
/// recover a `key` compatible with the data model previously assumed by `KVStorePersister::persist`.
@@ -275,6 +269,9 @@ where
/// For a synchronous version of this trait, see [`KVStoreSync`].
///
/// This is not exported to bindings users as async is only supported in Rust.
+///
+/// [`OutputSweeper`]: crate::util::sweep::OutputSweeper
+/// [`MonitorUpdatingPersister`]: crate::util::persist::MonitorUpdatingPersister
// Note that updates to documentation on this trait should be copied to the synchronous version.
pub trait KVStore {
/// Returns the data stored for the given `primary_namespace`, `secondary_namespace`, and
@@ -347,6 +344,36 @@ pub trait KVStore {
) -> impl Future<Output = Result<Vec<String>, io::Error>> + 'static + MaybeSend;
}
+impl<K> KVStore for K
+where
+ K: Deref,
+ K::Target: KVStore,
+{
+ fn read(
+ &self, primary_namespace: &str, secondary_namespace: &str, key: &str,
+ ) -> impl Future<Output = Result<Vec<u8>, io::Error>> + 'static + MaybeSend {
+ self.deref().read(primary_namespace, secondary_namespace, key)
+ }
+
+ fn write(
+ &self, primary_namespace: &str, secondary_namespace: &str, key: &str, buf: Vec<u8>,
+ ) -> impl Future<Output = Result<(), io::Error>> + 'static + MaybeSend {
+ self.deref().write(primary_namespace, secondary_namespace, key, buf)
+ }
+
+ fn remove(
+ &self, primary_namespace: &str, secondary_namespace: &str, key: &str, lazy: bool,
+ ) -> impl Future<Output = Result<(), io::Error>> + 'static + MaybeSend {
+ self.deref().remove(primary_namespace, secondary_namespace, key, lazy)
+ }
+
+ fn list(
+ &self, primary_namespace: &str, secondary_namespace: &str,
+ ) -> impl Future<Output = Result<Vec<String>, io::Error>> + 'static + MaybeSend {
+ self.deref().list(primary_namespace, secondary_namespace)
+ }
+}
+
/// Provides additional interface methods that are required for [`KVStore`]-to-[`KVStore`]
/// data migration.
pub trait MigratableKVStore: KVStoreSync {
@@ -768,28 +795,24 @@ where
/// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor
/// [`ChainMonitor::new_async_beta`]: crate::chain::chainmonitor::ChainMonitor::new_async_beta
pub struct MonitorUpdatingPersisterAsync<
- K: Deref,
+ K: KVStore,
S: FutureSpawner,
L: Logger,
ES: EntropySource,
SP: SignerProvider,
BI: BroadcasterInterface,
FE: FeeEstimator,
->(Arc<MonitorUpdatingPersisterAsyncInner<K, S, L, ES, SP, BI, FE>>)
-where
- K::Target: KVStore;
+>(Arc<MonitorUpdatingPersisterAsyncInner<K, S, L, ES, SP, BI, FE>>);
struct MonitorUpdatingPersisterAsyncInner<
- K: Deref,
+ K: KVStore,
S: FutureSpawner,
L: Logger,
ES: EntropySource,
SP: SignerProvider,
BI: BroadcasterInterface,
FE: FeeEstimator,
-> where
- K::Target: KVStore,
-{
+> {
kv_store: K,
async_completed_updates: Mutex<Vec<(ChannelId, u64)>>,
future_spawner: S,
@@ -802,7 +825,7 @@ struct MonitorUpdatingPersisterAsyncInner<
}
impl<
- K: Deref,
+ K: KVStore,
S: FutureSpawner,
L: Logger,
ES: EntropySource,
@@ -810,8 +833,6 @@ impl<
BI: BroadcasterInterface,
FE: FeeEstimator,
> MonitorUpdatingPersisterAsync<K, S, L, ES, SP, BI, FE>
-where
- K::Target: KVStore,
{
/// Constructs a new [`MonitorUpdatingPersisterAsync`].
///
@@ -941,7 +962,7 @@ where
}
impl<
- K: Deref + MaybeSend + MaybeSync + 'static,
+ K: KVStore + MaybeSend + MaybeSync + 'static,
S: FutureSpawner,
L: Logger + MaybeSend + MaybeSync + 'static,
ES: EntropySource + MaybeSend + MaybeSync + 'static,
@@ -950,7 +971,6 @@ impl<
FE: FeeEstimator + MaybeSend + MaybeSync + 'static,
> MonitorUpdatingPersisterAsync<K, S, L, ES, SP, BI, FE>
where
- K::Target: KVStore + MaybeSync,
SP::EcdsaSigner: MaybeSend + 'static,
{
pub(crate) fn spawn_async_persist_new_channel(
@@ -1026,7 +1046,7 @@ trait MaybeSendableFuture: Future<Output = Result<(), io::Error>> + MaybeSend {}
impl<F: Future<Output = Result<(), io::Error>> + MaybeSend> MaybeSendableFuture for F {}
impl<
- K: Deref,
+ K: KVStore,
S: FutureSpawner,
L: Logger,
ES: EntropySource,
@@ -1034,8 +1054,6 @@ impl<
BI: BroadcasterInterface,
FE: FeeEstimator,
> MonitorUpdatingPersisterAsyncInner<K, S, L, ES, SP, BI, FE>
-where
- K::Target: KVStore,
{
pub async fn read_channel_monitor_with_updates(
&self, monitor_key: &str,
diff --git a/lightning/src/util/sweep.rs b/lightning/src/util/sweep.rs
index f7cf277..2d22244 100644
--- a/lightning/src/util/sweep.rs
+++ b/lightning/src/util/sweep.rs
@@ -342,13 +342,12 @@ pub struct OutputSweeper<
D: Deref,
E: FeeEstimator,
F: Deref,
- K: Deref,
+ K: KVStore,
L: Logger,
O: Deref,
> where
D::Target: ChangeDestinationSource,
F::Target: Filter,
- K::Target: KVStore,
O::Target: OutputSpender,
{
sweeper_state: Mutex<SweeperState>,
@@ -367,14 +366,13 @@ impl<
D: Deref,
E: FeeEstimator,
F: Deref,
- K: Deref,
+ K: KVStore,
L: Logger,
O: Deref,
> OutputSweeper<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSource,
F::Target: Filter,
- K::Target: KVStore,
O::Target: OutputSpender,
{
/// Constructs a new [`OutputSweeper`].
@@ -723,14 +721,13 @@ impl<
D: Deref,
E: FeeEstimator,
F: Deref,
- K: Deref,
+ K: KVStore,
L: Logger,
O: Deref,
> Listen for OutputSweeper<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSource,
F::Target: Filter + Sync + Send,
- K::Target: KVStore,
O::Target: OutputSpender,
{
fn filtered_block_connected(
@@ -768,14 +765,13 @@ impl<
D: Deref,
E: FeeEstimator,
F: Deref,
- K: Deref,
+ K: KVStore,
L: Logger,
O: Deref,
> Confirm for OutputSweeper<B, D, E, F, K, L, O>
where
D::Target: ChangeDestinationSource,
F::Target: Filter + Sync + Send,
- K::Target: KVStore,
O::Target: OutputSpender,
{
fn transactions_confirmed(
@@ -869,14 +865,13 @@ impl<
D: Deref,
E: FeeEstimator,
F: Deref,
- K: Deref,
+ K: KVStore,
L: Logger,
O: Deref,
> ReadableArgs<(B, E, Option<F>, O, D, K, L)> for (BestBlock, OutputSweeper<B, D, E, F, K, L, O>)
where
D::Target: ChangeDestinationSource,
F::Target: Filter + Sync + Send,
- K::Target: KVStore,
O::Target: OutputSpender,
{
#[inline]
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.