Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ impl PlatformAddressWallet {
/// material — callers supply a seed-backed, hardware, or
/// FFI-trampoline signer per their environment (iOS routes through
/// `KeychainSigner` via `VTableSigner`).
///
/// # Local-ledger ownership invariant (V27-007 / QA-010)
///
/// The SDK returns post-transition states for **all** addresses touched by
/// the transition, including foreign output addresses the caller does not
/// own. Only addresses that belong to this wallet's account are written into
/// the local ledger; foreign addresses are silently skipped. The recipient
/// wallet's syncer is responsible for observing inbound credits on its own
/// addresses. Violating this invariant causes the source wallet's
/// `total_credits()` to absorb the recipient's balance, which corrupts
/// dust-gate checks and sweep address selection in teardown.
pub async fn transfer<S: Signer<PlatformAddress> + Send + Sync>(
&self,
account_index: u32,
Expand Down Expand Up @@ -105,6 +116,15 @@ impl PlatformAddressWallet {
continue;
};
let p2pkh = PlatformP2PKHAddress::new(*hash);
// V27-007 / QA-010: skip foreign output addresses.
// The SDK returns post-transition state for every address in
// the transition (inputs + outputs). Output addresses may
// belong to a different wallet; writing their balances here
// would pollute this wallet's local ledger and corrupt
// `total_credits()`. See the method-level doc comment.
if !account.contains_platform_address(&p2pkh) {
continue;
}
Comment thread
lklimek marked this conversation as resolved.
Comment thread
lklimek marked this conversation as resolved.
let funds = match maybe_info {
Some(ai) => dash_sdk::platform::address_sync::AddressFunds {
balance: ai.balance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ impl PlatformAddressWallet {
continue;
};
let p2pkh = PlatformP2PKHAddress::new(*hash);
// Defense-in-depth (V27-007 / QA-010): only update owned
// addresses. Withdrawals send no platform output addresses,
// so this guard is never expected to fire, but keeps the
// local-ledger ownership invariant consistent with `transfer`.
if !account.contains_platform_address(&p2pkh) {
continue;
}
let funds = match maybe_info {
Some(ai) => dash_sdk::platform::address_sync::AddressFunds {
balance: ai.balance,
Expand Down
Loading