Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e3653e2
docs(rs-platform-wallet): shielded spec — full scope + post-merge ver…
lklimek May 22, 2026
3428f14
docs(rs-platform-wallet): shielded spec — adversarial / abuse pass (S…
lklimek May 22, 2026
f1c4f6d
Merge remote-tracking branch 'origin/feat/rs-platform-wallet-e2e' int…
lklimek May 22, 2026
89fd200
test(rs-platform-wallet): Wave H shielded e2e harness (prover, bind, …
lklimek May 22, 2026
f09649c
test(rs-platform-wallet): SH-001..SH-019 functional shielded e2e cases
lklimek May 22, 2026
6bfdf68
Merge remote-tracking branch 'origin/feat/rs-platform-wallet-e2e' int…
lklimek May 22, 2026
093a9f7
test(rs-platform-wallet): SH-020..SH-035 adversarial shielded e2e cases
lklimek May 22, 2026
0477786
feat(rs-platform-wallet): shielded build/broadcast split + test-utils…
lklimek May 22, 2026
67773c4
Merge remote-tracking branch 'origin/feat/rs-platform-wallet-e2e' int…
lklimek May 22, 2026
a5efe37
Merge remote-tracking branch 'origin/feat/rs-platform-wallet-e2e' int…
lklimek May 22, 2026
9a6b7f1
docs(rs-platform-wallet): drop stale porter SPV handshake TODO
lklimek May 25, 2026
d529901
Merge branch 'feat/rs-platform-wallet-e2e' into test/rs-platform-wall…
lklimek May 29, 2026
1651540
fix(rs-platform-wallet): resolve merge conflict markers in Cargo.toml…
lklimek May 29, 2026
60ef7f7
fix(rs-platform-wallet): restore shielded operations.rs imports after…
lklimek May 29, 2026
98db84c
Merge branch 'feat/rs-platform-wallet-e2e' into test/rs-platform-wall…
lklimek Jun 1, 2026
2dd7da8
fix(platform-wallet): update shielded examples to multi-handler Platf…
lklimek Jun 1, 2026
95183f4
Merge branch 'feat/rs-platform-wallet-e2e' into test/rs-platform-wall…
lklimek Jun 2, 2026
86b05a3
test(platform-wallet): fund shielded cases above the ~1e9 shield fee …
lklimek Jun 2, 2026
c2dcf03
docs(platform-wallet): update e2e TEST_SPEC for paloma devnet finding…
lklimek Jun 2, 2026
c00ed02
test(platform-wallet): size adversarial shielded notes above the unsh…
lklimek Jun 2, 2026
c640c2d
docs(platform-wallet): note RUST_LOG=trace log-volume footgun for liv…
lklimek Jun 2, 2026
b3764cb
test(platform-wallet): share one Orchard tree across sh e2e cases to …
lklimek Jun 2, 2026
9522811
test(platform-wallet): bound shared shielded registry on teardown; cl…
lklimek Jun 2, 2026
19b7b51
docs(platform-wallet): document AL-001 concurrent asset-lock IS-lock/…
lklimek Jun 2, 2026
adb302f
test(platform-wallet): port state-delta double-spend verdict to SH-02…
lklimek Jun 3, 2026
a9135b8
fix(platform-wallet): accept Testnet-decoded recipient on Devnet/Regt…
lklimek Jun 3, 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
8 changes: 7 additions & 1 deletion packages/rs-platform-wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,13 @@ shielded = ["dep:grovedb-commitment-tree", "dep:rusqlite", "dep:zip32", "dep:fut
# runs the network-dependent harness. Pulls in `shielded` so an e2e run
# exercises the shielded-pool cases too. Run with:
# `cargo test -p platform-wallet --test e2e --features e2e`.
e2e = ["shielded"]
e2e = ["shielded", "test-utils"]
# Test-only seams that expose internal shielded spend-assembly
# (extract-spends, note reservation, build-against-a-chosen-note, and an
# asset-lock one-time-key derivation helper) for the adversarial e2e
# cases. NOT in `default`; pulled in by `e2e`. Never enable in production
# builds — these bypass the wallet's spend guards by design.
test-utils = ["shielded"]
# Opt-in serde derives on the changeset types. Activates `key-wallet/serde`,
# `key-wallet-manager/serde`, and `dash-sdk/serde`. `dpp` derives serde unconditionally.
serde = [
Expand Down
2 changes: 1 addition & 1 deletion packages/rs-platform-wallet/examples/shielded_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ async fn run_wallet_balance_test(wallet: WalletIndex) {
let manager = Arc::new(PlatformWalletManager::new(
Arc::clone(&sdk),
persister,
event_handler,
vec![event_handler],
));

// --- 3. Configure shielded support (creates the SQLite store) ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ async fn main() {
let manager = Arc::new(PlatformWalletManager::new(
Arc::clone(&sdk),
persister,
event_handler,
vec![event_handler],
));

let shielded_db_dir = std::env::temp_dir().join(format!(
Expand Down
61 changes: 60 additions & 1 deletion packages/rs-platform-wallet/src/wallet/platform_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,17 @@ impl PlatformWallet {
"invalid platform address: {e}"
))
})?;
if addr_network != self.sdk.network {
// Interim unblock: the bech32m decoder lossily maps `tdash` → Testnet,
// so a devnet recipient decodes as Testnet. Accept a Testnet-decoded
// address on a Devnet/Regtest wallet. Superseded by #3781 (a
// network-agnostic decoder + HRP-class guard).
let networks_match = addr_network == self.sdk.network
|| (addr_network == dashcore::Network::Testnet
&& matches!(
self.sdk.network,
dashcore::Network::Devnet | dashcore::Network::Regtest
));
if !networks_match {
return Err(PlatformWalletError::ShieldedBuildError(format!(
"platform address network mismatch: address {addr_network:?}, wallet {:?}",
self.sdk.network
Expand Down Expand Up @@ -844,6 +854,55 @@ impl PlatformWallet {
)
.await
}

/// Shield credits from a Core L1 asset lock into the wallet's
/// shielded pool (Type 18), with the resulting note assigned to
/// `shielded_account`'s default Orchard address.
///
/// `asset_lock_proof` is the single-use proof of the locked L1
/// outpoint and `private_key` the one-time key authorizing it (the
/// caller derives both via the asset-lock builder). `amount` is the
/// shielded value. Uses `broadcast_and_wait` for proven inclusion —
/// important because the proof is single-use, so a false-positive on
/// a later-rejected transition would strand the L1 outpoint.
///
/// Mirrors the other four spend wrappers
/// ([`shielded_shield_from_account`](Self::shielded_shield_from_account),
/// [`shielded_transfer_to`](Self::shielded_transfer_to),
/// [`shielded_unshield_to`](Self::shielded_unshield_to),
/// [`shielded_withdraw_to`](Self::shielded_withdraw_to)) and delegates
/// to `operations::shield_from_asset_lock`. Returns `ShieldedNotBound`
/// if no shielded sub-wallet is bound, or `ShieldedKeyDerivation` if
/// `shielded_account` isn't bound on it.
#[cfg(feature = "shielded")]
pub async fn shielded_shield_from_asset_lock<P: dpp::shielded::builder::OrchardProver>(
&self,
shielded_account: u32,
asset_lock_proof: dpp::prelude::AssetLockProof,
private_key: &[u8],
amount: u64,
prover: P,
) -> Result<(), PlatformWalletError> {
let guard = self.shielded_keys.read().await;
let keys = guard
.as_ref()
.ok_or(PlatformWalletError::ShieldedNotBound)?;
let keyset = keys.get(&shielded_account).ok_or_else(|| {
PlatformWalletError::ShieldedKeyDerivation(format!(
"shielded account {shielded_account} not bound"
))
})?;
super::shielded::operations::shield_from_asset_lock(
&self.sdk,
keyset,
shielded_account,
asset_lock_proof,
private_key,
amount,
&prover,
)
.await
}
}

impl PlatformWallet {
Expand Down
Loading
Loading