Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

zcash_client_backend: Propose multiple transactions when shielding funds from multiple transparent receivers #1201

Open
str4d opened this issue Feb 27, 2024 · 0 comments
Labels
A-wallet Area: light wallet backend.

Comments

@str4d
Copy link
Contributor

str4d commented Feb 27, 2024

zcash_client_backend::data_api::wallet::{propose_shielding, shield_transparent_funds} take a slice of transparent receivers that is used to filter the UTXOs that will be shielded:

let mut transparent_inputs: Vec<WalletTransparentOutput> = source_addrs
.iter()
.map(|taddr| {
wallet_db.get_unspent_transparent_outputs(
taddr,
target_height - min_confirmations,
&[],
)
})

These transparent inputs are then proposed to be spent in a single transaction:

Proposal::single_step(
TransactionRequest::empty(),
BTreeMap::new(),
transparent_inputs,
None,
balance,
(*self.change_strategy.fee_rule()).clone(),
target_height,
true,
)

This creates an address linkability problem: if the transparent receivers are present in distinct diversified UAs for the account, then when this shielding transaction is posted to the chain, it creates an indelible link between those UAs, and consequentially between the shielded receivers. The current way to avoid this is to only specify a single transparent receiver at a time, and require the caller to:

  • notice that this problem can occur (neither of the current APIs document this problem, and the fact that the API takes a slice implies that passing multiple transparent receivers is the normal and safe use case).
  • manually loop over the available transparent receivers and call this API repeatedly to produce individual proposals / transactions.

After the recent changes to Proposal that enable it to propose the creation of multiple transactions, create_proposed_transactions (and thus shield_transparent_funds which uses it) now returns NonEmpty<TxId>. This means that a shielding proposal can now represent multiple transactions, and more importantly the caller is already required to assume that multiple transactions were created (even though they are not currently).

We should take advantage of this change:

  • Remove the slice of transparent addresses to filter with.
  • Generate a Proposal containing a separate transaction for each transparent receiver that contains funds to shield.

Then in the worst case of the caller submitting all transactions to the chain at the same time, the address linking issue is only heuristic, rather than indelible. And the caller has the same opportunity to submit transactions in uncorrelatable ways (e.g. via a mixnet) as they currently do, but with a much clearer and safer API.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-wallet Area: light wallet backend.
Projects
None yet
Development

No branches or pull requests

3 participants