Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f4703d6
feat(swift-sdk): use SPV-synced quorums for Platform proof verification
QuantumExplorer Mar 31, 2026
ad6904a
refactor(rs-sdk-ffi): move SPV context provider from Swift to Rust
QuantumExplorer Mar 31, 2026
d9e478e
feat(platform-wallet): add pure-Rust SpvContextProvider
QuantumExplorer Mar 31, 2026
8d2bb27
fix: address CodeRabbit review feedback on SPV quorums PR
QuantumExplorer Apr 2, 2026
fa7e531
feat: use pure-Rust SpvContextProvider, bump rust-dashcore
QuantumExplorer Apr 2, 2026
54b6ed0
fix: eliminate race between didSet and handleNetworkSwitch
QuantumExplorer Apr 2, 2026
cfde224
fix: use try_read() instead of blocking_read(), add dep: prefix
QuantumExplorer Apr 2, 2026
6f67870
Merge v4.1-dev into feat/ios-spv-quorums; re-integrate SPV context pr…
shumkov Jul 11, 2026
05fd41d
style(platform-wallet-ffi): apply rustfmt; drop internal re-integrati…
shumkov Jul 11, 2026
3fad6f8
feat(swift-sdk): verify proofs against SPV quorums via attach-after-b…
shumkov Jul 13, 2026
600b440
feat(sdk): share context provider across SDK clones; live Auto/SPV/Tr…
shumkov Jul 13, 2026
9a2289a
test(sdk,rs-sdk-ffi): cover context-provider clone-sharing + install/…
shumkov Jul 13, 2026
584e68c
fix(rs-platform-wallet): reverse quorum hash to internal order for SP…
shumkov Jul 14, 2026
1deb36b
fix(rs-platform-wallet): guard byte-order via production helper + pin…
shumkov Jul 14, 2026
8263be0
fix(rs-sdk-ffi): install SPV quorum provider as a composite over trusted
shumkov Jul 14, 2026
a53b983
fix(swift-sdk): force SPV install in SPV mode instead of gating on ru…
shumkov Jul 14, 2026
a0fa683
fix(rs-platform-wallet): avoid block_in_place panic on a current-thre…
shumkov Jul 15, 2026
6fc782f
fix(rs-platform-wallet): fail closed on current-thread runtime, not a…
shumkov Jul 15, 2026
3a5e96e
refactor(sdk): add adaptive SPV context provider
shumkov Jul 15, 2026
ba2fbef
docs: remove adaptive SPV provider spec
shumkov Jul 15, 2026
d4046ca
refactor(sdk): separate adaptive and SPV providers
shumkov Jul 16, 2026
4961a0e
chore(sdk): remove unused HTTP dependency
shumkov Jul 16, 2026
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
24 changes: 13 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ async fn main() -> Result<()> {
// Build SDK with mock core (context provider will handle everything)
let sdk = SdkBuilder::new(AddressList::from_iter(addresses))
.with_core("127.0.0.1", 1, "mock", "mock") // Mock values, won't be used
.with_context_provider(context_provider)
.build()?;

// Set our trusted context provider
sdk.set_context_provider(context_provider);

// Fetch the identity
println!("Fetching identity with proof verification...");
match Identity::fetch(&sdk, identity_id).await {
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-platform-wallet-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description = "C FFI bindings for platform-wallet"
crate-type = ["staticlib", "cdylib", "rlib"]

[dependencies]
platform-wallet = { path = "../rs-platform-wallet" }
platform-wallet = { path = "../rs-platform-wallet", features = ["spv-context"] }
dpp = { path = "../rs-dpp" }
dash-sdk = { path = "../rs-sdk", features = ["wallet"] }
# Needed for `SignerHandle` + `VTableSigner` so the `*_with_signer`
Expand Down
53 changes: 53 additions & 0 deletions packages/rs-platform-wallet-ffi/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,59 @@ pub unsafe extern "C" fn platform_wallet_manager_create(
PlatformWalletFFIResult::ok()
}

/// Create a manager from an owning SDK handle and populate that SDK's fixed
/// adaptive provider with the manager's SPV source.
///
/// The SDK handle is borrowed only for this synchronous call. The manager
/// retains an `Sdk` clone, never the raw handle.
#[no_mangle]
pub unsafe extern "C" fn platform_wallet_manager_create_with_sdk(
sdk_handle: *mut rs_sdk_ffi::SDKHandle,
persistence: *const PersistenceCallbacks,
event_handler: *const EventHandlerCallbacks,
out_handle: *mut Handle,
) -> PlatformWalletFFIResult {
check_ptr!(sdk_handle);
check_ptr!(persistence);
check_ptr!(event_handler);
check_ptr!(out_handle);

let sdk_ptr = rs_sdk_ffi::dash_sdk_get_inner_sdk_ptr(sdk_handle);
if sdk_ptr.is_null() {
return PlatformWalletFFIResult::err(
PlatformWalletFFIResultCode::ErrorInvalidParameter,
"SDK has no inner SDK".to_string(),
);
}

let sdk = Arc::new((*(sdk_ptr as *const Sdk)).clone());
let persister = Arc::new(FFIPersister::new(std::ptr::read(persistence)));
let handler: Arc<dyn platform_wallet::PlatformEventHandler> =
Arc::new(FFIEventHandler::new(std::ptr::read(event_handler)));

let _runtime_guard = runtime().enter();
let manager = PlatformWalletManager::new(Arc::clone(&sdk), persister, handler);
let spv = manager.spv_arc();
let provider = Arc::new(
platform_wallet::spv_context_provider::SpvContextProvider::new(
Arc::clone(&spv),
sdk.network,
),
);
let readiness = Arc::new(move || spv.is_ready());
if let Err(message) = rs_sdk_ffi::dash_sdk_set_spv_source(sdk_handle, provider, readiness) {
drop(_runtime_guard);
runtime().block_on(manager.shutdown());
return PlatformWalletFFIResult::err(
PlatformWalletFFIResultCode::ErrorInvalidParameter,
message,
);
}

*out_handle = PLATFORM_WALLET_MANAGER_STORAGE.insert(manager);
PlatformWalletFFIResult::ok()
}

/// Map the C `has_x: bool` + `x` companion-pair idiom to a Rust `Option<u32>`.
///
/// `has == true` yields `Some(value)` — including `Some(0)`, kept distinct
Expand Down
10 changes: 10 additions & 0 deletions packages/rs-platform-wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ dash-spv = { workspace = true }
# Core dependencies
dashcore = { workspace = true }

# SPV context provider dependency (optional). `dash-spv` and `tokio` are
# already non-optional dependencies above, so the `spv-context` feature only
# needs to pull in the context-provider trait crate.
dash-context-provider = { path = "../rs-context-provider", optional = true }

# Standard dependencies
thiserror = "1.0"
async-trait = "0.1"
Expand Down Expand Up @@ -112,6 +117,11 @@ rs-sdk-trusted-context-provider = { path = "../rs-sdk-trusted-context-provider"

[features]
default = ["bls", "eddsa"]
# SPV-backed Platform context provider (delegates quorum lookups to the SPV
# runtime). `dash-spv`/`tokio` are already non-optional deps; this pulls in the
# context-provider trait crate plus `rt-multi-thread` (the sync->async bridge
# in `spv_context_provider` uses `tokio::task::block_in_place`).
spv-context = ["dep:dash-context-provider", "tokio/rt-multi-thread"]
bls = ["key-wallet/bls", "key-wallet-manager/bls"]
eddsa = ["key-wallet/eddsa", "key-wallet-manager/eddsa"]
shielded = ["dep:grovedb-commitment-tree", "dep:rusqlite", "dep:zip32", "dep:futures", "dash-sdk/shielded", "dpp/shielded-client"]
Expand Down
3 changes: 3 additions & 0 deletions packages/rs-platform-wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub(crate) mod test_support;
mod util;
pub mod wallet;

#[cfg(feature = "spv-context")]
pub mod spv_context_provider;

pub use error::PlatformWalletError;
pub use events::{PlatformEventHandler, PlatformEventManager};
pub use key_wallet::wallet::managed_wallet_info::asset_lock_builder::AssetLockFundingType;
Expand Down
Loading
Loading