Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -116,7 +116,13 @@ shielded = ["dep:grovedb-commitment-tree", "dep:zip32", "dash-sdk/shielded", "dp
# 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"]
# Forward to the upstream `key-wallet` / `key-wallet-manager`
# `keep-finalized-transactions` feature. With it OFF (the default),
# chainlocked transactions are evicted from the in-memory
Expand Down
49 changes: 49 additions & 0 deletions packages/rs-platform-wallet/src/wallet/platform_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,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