Skip to content

Commit 1cd58c0

Browse files
committed
Replace public FfiDynStore wrapper with dyn FfiDynStoreTrait
Accept foreign store trait objects directly in the UniFFI builder API and adapt them internally to DynStoreTrait via the existing Rust-side adapter. This removes FfiDynStore from the public surface, keeps DynStoreTrait as the internal store abstraction, and updates Rust tests to bridge native stores via DynStoreWrapper instead of the old public wrapper. [Refactor(uniffi)]
1 parent 7155c40 commit 1cd58c0

File tree

6 files changed

+61
-34
lines changed

6 files changed

+61
-34
lines changed

bindings/ldk_node.udl

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,27 @@ interface LogWriter {
3232
void log(LogRecord record);
3333
};
3434

35-
typedef interface FfiDynStore;
35+
[Trait, WithForeign]
36+
interface FfiDynStoreTrait {
37+
[Throws=IOError, Async]
38+
bytes read_async(string primary_namespace, string secondary_namespace, string key);
39+
[Throws=IOError, Async]
40+
void write_async(string primary_namespace, string secondary_namespace, string key, bytes buf);
41+
[Throws=IOError, Async]
42+
void remove_async(string primary_namespace, string secondary_namespace, string key, boolean lazy);
43+
[Throws=IOError, Async]
44+
sequence<string> list_async(string primary_namespace, string secondary_namespace);
45+
46+
[Throws=IOError]
47+
bytes read(string primary_namespace, string secondary_namespace, string key);
48+
[Throws=IOError]
49+
void write(string primary_namespace, string secondary_namespace, string key, bytes buf);
50+
[Throws=IOError]
51+
void remove(string primary_namespace, string secondary_namespace, string key, boolean lazy);
52+
[Throws=IOError]
53+
sequence<string> list(string primary_namespace, string secondary_namespace);
54+
};
55+
3656

3757
interface Builder {
3858
constructor();
@@ -60,8 +80,8 @@ interface Builder {
6080
void set_tor_config(TorConfig tor_config);
6181
[Throws=BuildError]
6282
void set_node_alias(string node_alias);
63-
void set_backup_store(FfiDynStore backup_store);
64-
void set_ephemeral_store(FfiDynStore ephemeral_store);
83+
void set_backup_store(FfiDynStoreTrait backup_store);
84+
void set_ephemeral_store(FfiDynStoreTrait ephemeral_store);
6585
[Throws=BuildError]
6686
void set_async_payments_role(AsyncPaymentsRole? role);
6787
void set_wallet_recovery_mode();
@@ -78,7 +98,7 @@ interface Builder {
7898
[Throws=BuildError]
7999
Node build_with_vss_store_and_header_provider(NodeEntropy node_entropy, string vss_url, string store_id, VssHeaderProvider header_provider);
80100
[Throws=BuildError]
81-
Node build_with_store(NodeEntropy node_entropy, FfiDynStore store);
101+
Node build_with_store(NodeEntropy node_entropy, FfiDynStoreTrait store);
82102
};
83103

84104
interface Node {
@@ -233,6 +253,8 @@ enum NodeError {
233253
"InvalidLnurl",
234254
};
235255

256+
typedef enum IOError;
257+
236258
typedef dictionary NodeStatus;
237259

238260
[Remote]

src/builder.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use crate::entropy::NodeEntropy;
5353
use crate::event::EventQueue;
5454
use crate::fee_estimator::OnchainFeeEstimator;
5555
#[cfg(feature = "uniffi")]
56-
use crate::ffi::FfiDynStore;
56+
use crate::ffi::{FfiDynStore, FfiDynStoreTrait};
5757
use crate::gossip::GossipSource;
5858
use crate::io::sqlite_store::SqliteStore;
5959
use crate::io::tier_store::TierStore;
@@ -1155,8 +1155,8 @@ impl ArcedNodeBuilder {
11551155
/// of all critical data written to the primary store.
11561156
///
11571157
/// Backup writes are non-blocking and do not affect primary store operation performance.
1158-
pub fn set_backup_store(&self, backup_store: Arc<FfiDynStore>) {
1159-
let store: Arc<DynStore> = Arc::new((*backup_store).clone());
1158+
pub fn set_backup_store(&self, backup_store: Arc<dyn FfiDynStoreTrait>) {
1159+
let store: Arc<DynStore> = Arc::new(FfiDynStore::from_store(backup_store));
11601160
self.inner.write().unwrap().set_backup_store(store);
11611161
}
11621162

@@ -1167,8 +1167,8 @@ impl ArcedNodeBuilder {
11671167
/// can be rebuilt if lost.
11681168
///
11691169
/// If not set, non-critical data will be stored in the primary store.
1170-
pub fn set_ephemeral_store(&self, ephemeral_store: Arc<FfiDynStore>) {
1171-
let store: Arc<DynStore> = Arc::new((*ephemeral_store).clone());
1170+
pub fn set_ephemeral_store(&self, ephemeral_store: Arc<dyn FfiDynStoreTrait>) {
1171+
let store: Arc<DynStore> = Arc::new(FfiDynStore::from_store(ephemeral_store));
11721172
self.inner.write().unwrap().set_ephemeral_store(store);
11731173
}
11741174

@@ -1309,9 +1309,9 @@ impl ArcedNodeBuilder {
13091309
/// [`set_ephemeral_store`]: Self::set_ephemeral_store
13101310
/// [`set_backup_store`]: Self::set_backup_store
13111311
pub fn build_with_store(
1312-
&self, node_entropy: Arc<NodeEntropy>, kv_store: Arc<FfiDynStore>,
1312+
&self, node_entropy: Arc<NodeEntropy>, kv_store: Arc<dyn FfiDynStoreTrait>,
13131313
) -> Result<Arc<Node>, BuildError> {
1314-
let store = kv_store as Arc<DynStore>;
1314+
let store: Arc<DynStore> = Arc::new(FfiDynStore::from_store(kv_store));
13151315
self.inner.read().unwrap().build_with_dynstore(*node_entropy, store).map(Arc::new)
13161316
}
13171317
}

src/ffi/io.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ impl std::fmt::Display for IOError {
132132
/// through the async interface.
133133
///
134134
/// [`DynStoreTrait`]: crate::types::DynStoreTrait
135-
#[uniffi::export(with_foreign)]
136135
#[async_trait::async_trait]
137136
pub trait FfiDynStoreTrait: Send + Sync {
138137
async fn read_async(
@@ -173,7 +172,7 @@ pub trait FfiDynStoreTrait: Send + Sync {
173172
/// the corresponding async operation on an internal runtime, which preserves the
174173
/// same ordering guarantees for both sync and async callers.
175174
#[derive(Clone, uniffi::Object)]
176-
pub struct FfiDynStore {
175+
pub(crate) struct FfiDynStore {
177176
inner: Arc<FfiDynStoreInner>,
178177
next_write_version: Arc<AtomicU64>,
179178
}
@@ -607,12 +606,6 @@ impl<T: SyncAndAsyncKVStore + Send + Sync + 'static> FfiDynStoreTrait for DynSto
607606
}
608607
}
609608

610-
impl<T: SyncAndAsyncKVStore + Send + Sync + 'static> From<T> for FfiDynStore {
611-
fn from(store: T) -> Self {
612-
Self::from_store(Arc::new(DynStoreWrapper(store)))
613-
}
614-
}
615-
616609
/// Returns the process-wide runtime used to bridge Rust-side synchronous
617610
/// `FfiDynStore` calls through the canonical async store path.
618611
fn ffi_dynstore_runtime() -> &'static tokio::runtime::Runtime {

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ use fee_estimator::{ConfirmationTarget, FeeEstimator, OnchainFeeEstimator};
142142
#[cfg(feature = "uniffi")]
143143
use ffi::*;
144144
#[cfg(feature = "uniffi")]
145-
pub use ffi::{FfiDynStore, FfiDynStoreTrait, IOError};
145+
pub use ffi::{FfiDynStoreTrait, IOError};
146146
use gossip::GossipSource;
147147
use graph::NetworkGraph;
148148
use io::utils::write_node_metrics;

tests/common/mod.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,10 @@ pub(crate) enum TestChainSource<'a> {
327327
}
328328

329329
#[cfg(feature = "uniffi")]
330-
use ldk_node::FfiDynStore;
330+
use ldk_node::FfiDynStoreTrait;
331331

332332
#[cfg(feature = "uniffi")]
333-
type TestDynStore = Arc<FfiDynStore>;
333+
type TestDynStore = Arc<dyn FfiDynStoreTrait>;
334334
#[cfg(not(feature = "uniffi"))]
335335
type TestDynStore = TestSyncStore;
336336

@@ -400,10 +400,12 @@ pub(crate) fn create_tier_stores(base_path: PathBuf) -> (TestDynStore, TestDynSt
400400

401401
#[cfg(feature = "uniffi")]
402402
{
403+
use ldk_node::DynStoreWrapper;
404+
403405
(
404-
Arc::new(FfiDynStore::from(primary)),
405-
Arc::new(FfiDynStore::from(backup)),
406-
Arc::new(FfiDynStore::from(ephemeral)),
406+
Arc::new(DynStoreWrapper(primary)) as Arc<dyn FfiDynStoreTrait>,
407+
Arc::new(DynStoreWrapper(backup)) as Arc<dyn FfiDynStoreTrait>,
408+
Arc::new(DynStoreWrapper(ephemeral)) as Arc<dyn FfiDynStoreTrait>,
407409
)
408410
}
409411
#[cfg(not(feature = "uniffi"))]
@@ -519,7 +521,9 @@ pub(crate) fn setup_node(chain_source: &TestChainSource, config: TestConfig) ->
519521
let kv_store = TestSyncStore::new(config.node_config.storage_dir_path.into());
520522
#[cfg(feature = "uniffi")]
521523
{
522-
let kv_store = Arc::new(FfiDynStore::from(kv_store));
524+
use ldk_node::DynStoreWrapper;
525+
let kv_store: Arc<dyn FfiDynStoreTrait> = Arc::new(DynStoreWrapper(kv_store));
526+
523527
builder.build_with_store(config.node_entropy.into(), kv_store).unwrap()
524528
}
525529
#[cfg(not(feature = "uniffi"))]
@@ -1770,8 +1774,13 @@ pub fn test_kv_read(
17701774
) -> Result<Vec<u8>, bitcoin::io::Error> {
17711775
#[cfg(feature = "uniffi")]
17721776
{
1773-
use ldk_node::DynStoreTrait;
1774-
DynStoreTrait::read(&**store, primary_ns, secondary_ns, key)
1777+
ldk_node::FfiDynStoreTrait::read(
1778+
&**store,
1779+
primary_ns.to_string(),
1780+
secondary_ns.to_string(),
1781+
key.to_string(),
1782+
)
1783+
.map_err(Into::into)
17751784
}
17761785
#[cfg(not(feature = "uniffi"))]
17771786
{
@@ -1784,8 +1793,8 @@ pub fn test_kv_list(
17841793
) -> Result<Vec<String>, bitcoin::io::Error> {
17851794
#[cfg(feature = "uniffi")]
17861795
{
1787-
use ldk_node::DynStoreTrait;
1788-
DynStoreTrait::list(&**store, primary_ns, secondary_ns)
1796+
ldk_node::FfiDynStoreTrait::list(&**store, primary_ns.to_string(), secondary_ns.to_string())
1797+
.map_err(Into::into)
17891798
}
17901799
#[cfg(not(feature = "uniffi"))]
17911800
{

tests/integration_tests_rust.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,11 @@ async fn start_stop_reinit() {
347347
let node;
348348
#[cfg(feature = "uniffi")]
349349
{
350-
use ldk_node::FfiDynStore;
350+
use ldk_node::{DynStoreWrapper, FfiDynStoreTrait};
351+
352+
let test_sync_store: Arc<dyn FfiDynStoreTrait> =
353+
Arc::new(DynStoreWrapper(test_sync_store.clone()));
351354

352-
let test_sync_store = Arc::new(FfiDynStore::from(test_sync_store.clone()));
353355
node = builder.build_with_store(config.node_entropy.into(), test_sync_store).unwrap();
354356
}
355357
#[cfg(not(feature = "uniffi"))]
@@ -396,9 +398,10 @@ async fn start_stop_reinit() {
396398
let reinitialized_node;
397399
#[cfg(feature = "uniffi")]
398400
{
399-
use ldk_node::FfiDynStore;
401+
use ldk_node::{DynStoreWrapper, FfiDynStoreTrait};
402+
403+
let test_sync_store: Arc<dyn FfiDynStoreTrait> = Arc::new(DynStoreWrapper(test_sync_store));
400404

401-
let test_sync_store = Arc::new(FfiDynStore::from(test_sync_store.clone()));
402405
reinitialized_node =
403406
builder.build_with_store(config.node_entropy.into(), test_sync_store).unwrap();
404407
}

0 commit comments

Comments
 (0)