Introducing Transaction Controls in Zcash

Introducing Transaction Controls in Zcash

ZIP Info

A draft ZIP corresponding to this piece of work is available on this pull request and can be previewed here

In the current version of Zcash, fund transfers occur without explicit recipient consent. While this simplicity offers convenience, it creates significant challenges for users and businesses alike. This proposal introduces transaction user controls - a mechanism allowing recipients to actively participate in the transfer process by approving or rejecting incoming transactions.

This enhancement addresses crucial needs in the Zcash ecosystem, particularly at a time when privacy-preserving assets face increased scrutiny from major exchanges. The proposed controls offer robust safeguarding solutions while maintaining Zcash’s core privacy features


This piece of work comes at a time where privacy-preserving assets are under heavy scrutiny by major crypto exchanges. We believe that user controls can offer a robust safeguarding solution to prevent fund loss during transfer; while offering a promising avenue to keep Zcash listed on exchanges.

NOTE

This post summarizes two longer write-ups:

It also relates to this presentation which video is available here.

Current State of Payment Authorization

Today, network users have one way to control who can send them funds on the blockchain. This is done primarily through address sharing. By controlling who has their payment address, recipients can “authorize” or “not authorize” someone to pay them.


[Caption] Left: Recipients authorize a sender to send them funds by sharing their address. Right: Recipients refuse to receive funds from a sender by refusing to share their address

However, using “address sharing” as a mechanism to control the receipt of funds is fragile and error prone. The main drawbacks of this approach are listed below.

1. It is transitive (which is bad)


[Caption] Charlie can pay Alice while Alice never shared her address with him

As illustrated above, address sharing is a transitive operation. If Alice shares her payment address with Bob and Bob shares Alice’s payment address with Charlie; this is equivalent to the case where Alice shares her payment address with Charlie. So, basically, by sharing Alice’s address with Charlie, Bob can “authorize Charlie to pay Alice” on Alice’s behalf.

This is a problem that becomes worse every time Alice shares her address with a sender. Every time she shares her address, she must trust the sender to never (willingly or unwillingly - e.g. hack) share her address with anyone.

2. It’s loose

Sharing one’s address with other network participants allows them to transfer funds to one’s wallet. However, it does not, in any way restrict the terms of those said transfers.


[Caption] Two users agree on a transfer of 2 ZEC, but the sender unilaterally decides to transfer another amount.

Here again, this lack of restriction over incoming transfers is an issue for the recipient who has no efficient way of refusing the payment.

3. It’s not easily revocable

In a case similar to the one above, once recipients have shared their payment address with senders, they do not have an easy way to revoke the senders’ rights to transfer them funds.

Of course, recipients can generate new payment addresses. But, to revoke senders’ right to pay them, they would need to delete their old keys after sending all their assets to a new wallet. This operation can lead to lost funds, however, especially if legitimate senders continue to send funds to the old address.


[Caption] Once a sender has a recipient’s address, nothing prevents them to send funds to the recipient beyond the initial agreement.

4. It’s error prone

Finally, relying exclusively on the sender to create the transaction using the recipient’s address is error prone.

If the sender makes a typo in the recipient’s address (or if they “fat finger” the amount to be sent), funds may be lost for ever.

Despite the design of user friendly websites & interfaces (with clipeable fields etc) user mistakes will continue to happen. Likewise, UI & clickjacking attacks will always be a threat for crypto users.


[Caption] A sender making a typo in the address of the recipient

Note: Mechanisms like Unified Addresses (zip 316) can make it easier for users to share their addresses. That being said, typos / fat finger mistakes (e.g. on the amount) can always happen.

Note 2: Mistakes during fund transfers are extremely common in the banking sector, too. This led to the introduction of mechanisms like Confirmation of Payee (CoP) that offer account / name checking services to make sure senders send the funds to the right person during bank transfers.

Key Use Cases of User Control

Transaction controls are a set of mechanisms that address the drawbacks aforementioned. Having user-controls allows recipients to play an active role in the transfer of funds which enables several use-cases. We group these use cases in 2 main categories.

1. Loss Prevention / better safeguarding

The types of safeguarding use cases that become possible with user controls mechanisms are:

  • Double opt-in verification of transfers: both sender and recipient must approve the transfer which limits mistakes. The sender still puts the transaction together and the recipient reviews it to approve it, or not.
  • Confirmation that recipients can access funds: By approving the transaction, the recipient also confirms that they can receive the funds (i.e. they still have access to their wallet).

While relevant to every user of zcash, we believe these safeguarding use cases to be particularly relevant to custodians (e.g. CEXs), and businesses - more generally.

2. Enhanced Wallet Management

Allowing recipients to play an active role accepting or rejecting a transaction gives them a fine-grained control over incoming transactions. For instance, they can:

  • Inspect the transaction and decide whether or not it aligns with their expectations (e.g. “does the payment align with the terms of a contract?”)
  • Only accept payments above a certain value
  • Only accept shielded payments with at most X notes (e.g. payment with at most 2 notes, to avoid the total sum due to be split across too many notes, which would make it expensive to consolidate in the future for the recipient)
  • Control the timing of the payment (e.g. “don’t pay me before date X”)

etc.

Design Considerations

In order to be secure and versatile enough, we believe that user-controls protocol designers must bear the following design considerations in mind.

Firstly, recipient confirmation might not always make sense or be necessary. As such, it might be relevant to make user-controls / transaction approvals optional or use-case specific (e.g. for certain ZSAs only).

Secondly, user-control protocols must not undermine the Zcash’s privacy properties nor add significant overhead on the blockchain network. What this means is that any extra communications between sender and recipient must not generate additional privacy leaks on the blockchain. Likewise, any change in the transaction format or any extra transaction validity checks must not undermine the privacy of transacting parties.

Finally, user-control designers should ask themselves a series of question to make sure that the control protocols align with the desired goals. Some of these questions are:

  • What needs to be approved? The full transaction object? An Action? An Action Group (see Asset Swap ZIP228)?
  • Should “lack of approval” mean “rejection”?
  • Does “approval” (resp. “rejection”) need to happen on-chain? If so, who should be responsible for paying the fee between the sender and the recipient?
  • Should all blockchain transactions be subject to “approval”/“rejection”? If not, which transactions should, and which should not?
  • What about malicious recipients? E.g. How to prevent malicious recipients from freezing a transfer by withholding approval?

etc.

Avenues for user controls

Multiple options can co-exist to allow recipients to have better control over incoming funds to their wallet.

Rejection: Ignoring funds

For instance, recipients can reject an incoming transfer by simply ignoring it and never touching the associated funds. This does not require any protocol change but might necessitate some changes in wallet softwares to make it easier (and less error prone) for users to “ignore” rejected notes.

Rejection: Sending funds back

In some scenarios, recipients can also express their rejection of incoming funds by sending them back to the sender. This is possible if the incoming funds originate from a transparent address. To be feasible in all circumstances, this rejection method will require protocol and wallet changes (e.g. see TEX Addresses ZIP320).

Note: As described here, the derivation of payment addresses could be modified to encode specific payment instructions. This would be a step towards programmability and would generalize on the notion of TEX Addresses (which force incoming funds to be unshielded).

Rejection: Burning the funds

Another way in which recipients of funds can reject incoming funds is by simply burning them. However, burning funds when supply is bounded has a tendency to increase the asset price (demand stays constant while supply dimishes) which isn’t a neutral operation.

Approval via countersignature

Transaction approval can be done using a digital signature scheme. In this case, the recipient of the funds signs the transaction object (or a subset of the transaction like a specific Action/Action Group) to approve a specific transfer of funds for which it is the recipient.

This construction assumes that both the sender and the recipient are willing to engage in an interactive protocol to generate the transaction approval. More details about the protocol can be found in Zcash Transaction Confirmation Via Recipient Counter-Signatures.

Automated payment approval or rejection: towards programmable addresses?

As explained in Zcash User Controls: Transaction approvals and rejections, it could be possible to modify the address derivation in the Zcash protocol to let recipients create special address types encoding specific payment authorizations.

As done with TEX Addresses - which constrain payments to be done from transparent addresses - the Zcash protocol could be modified to allow recipients to derive addresses which would constrain the type of funds that can be sent to them.

For instance, it could be possible to modify the address derivation for users to generate:

  • Addresses that can only be paid once per sender
  • Addresses that can only receive payments of (or above) a specific value
  • etc.


[Caption] A sketch showing how a more versatile address derivation mechanism could allow users to “generate payment invoices” on Zcash

Looking Ahead

Transaction user controls open new possibilities for the Zcash ecosystem, such as:

  • Enhanced exchange integration
  • Better compliance tools for businesses
  • Improved user experience for all participants
  • Potential for more sophisticated approval policies and payment flows

The introduction of transaction user controls represents an important step forward in Zcash’s evolution, providing users and businesses with better tools to manage their digital assets while maintaining the network’s core privacy features.

References

12 Likes

This also may be advantageous in a forthcoming scenario where memos can include links to encrypted files and users may want to refuse that type of transaction unless explicitly approved.

In the future, a wallet owner may also wish to deny incoming transactions are without a proof that it is from a “safe” source (a non-sanctioned entity, etc.).

4 Likes

[This comment is partly based on discussion in yesterday’s ZIP sync meeting, although it is my analysis.]

I’m skeptical of some of the rationale for this feature; I don’t think it will actually help much with centralized exchanges, for instance.

I’m also skeptical of the “It is transitive (which is bad)” argument, because Bob can always give Charlie enough information to allow Charlie to act as Bob. This is a general counterargument to attempting to prevent transitive grants of authority in any cryptographic capability system (which is what Zcash is). [*1]

But my long-standing position has been that addresses as currently designed grant too much authority, so I accept that part of the argument — expressed in the points “It’s loose” and “It’s not easily revocable”.

My main comment on the protocol outline at Zcash Transaction Confirmation Via Recipient Counter-Signatures - Google Docs is that it is insufficient for the recipient to prove knowledge of the incoming viewing key. That key is a viewing key, not an authorization key, and it is fully intended that it can be given out to parties that should not be able to act as the recipient.

I suggested, in comments on the Google Doc, a different approach involving additive blinding of \mathsf{ask} (identical to what we already use for hardware wallets) that fixes the problem and allows the transaction to be authorized by knowledge of the spending key. Note that the required RedPallas signature can be produced by a hardware wallet, and so a recipient that holds its spending keys in a hardware wallet can use it to authorize transactions (which would otherwise be a showstopper for authorizing transactions using the spending key).

This approach would require proving the “Spend authority” and “Diversified address integrity” parts of the Action statement for the new note, along with “New note commitment integrity” to ensure that the proof is about the right note. Given that the recipient-authorization signature would also have to be unlinkable in a protocol based on Qedit’s proposal, a blinding step for \mathsf{ivk} with at least similar cost to “Spend authority” [*2] is needed (both solutions in the Google Doc have at least that cost), and that would also need to be done in a zk proof along with “New note commitment integrity”. So the extra cost for my approach relative to Qedit’s (restricting to variants with adequate address privacy properties) is at most one full-width variable-base Pallas scalar multiplication in a zk circuit, while fixing a significant problem that would interfere with the use of viewing keys. My approach is also easier to analyze because it reuses RedDSA’s key rerandomization property rather than inventing a new protocol for blinding.

It is possible to make transactions that make a payment requiring authorization indistinguishable from those that do not. Details omitted here, but note that we can have a proof per transaction that proves linking of the recipient authorization with the required RedPallas signature key if needed and with an arbitrary key if not. This incurs constant additional validation cost for all transactions regardless of the number of actions (with the trade-off that if a payment requires authorization, it must be the only payment in the transaction).


[*1] In fact diversified addresses were almost rerandomizable, which would have allowed Bob to give Charlie a randomized address for Alice that could not be traced to Bob. The design decision to make them non-rerandomizable in Sapling was motivated by fixing a separate decryption oracle attack. That is, we did not make a conscious decision that preventing untraceable forwarding of addresses was a goal; that was a side-effect of the use of \mathsf{DiversifyHash} which was introduced for a different reason.

[*2] Qedit’s “Unlinkability Solution 2” uses multiplicative blinding rather than additive. That costs slightly more (a variable-base scalar multiplication rather than a fixed-base one). I am not sure why they chose multiplicative.

3 Likes

Thank you very much for saying this. We agree completely.

I have mixed feelings on the pros and cons of the transaction controls discussed above (including the allocation of limited development resources to this compared to other priorities) but am happy that engineers such as yourself are fighting to guarantee any tx controls (if implemented) do not lead to degradations of Zcash privacy guarantees.

2 Likes

Hi @daira, thanks a lot for the feedback (and the comments on the Google Doc) - that’s very helpful! :slight_smile: (and really nice to see this thread become alive again :star_struck:)

I wasn’t on the ZIP sync call you mentioned, (so not sure what was discussed exactly) but here’s some follow ups on your comments :slight_smile:

Exchange Use Cases

AFAICT, most centralized exchanges supporting Zcash only accept transparent deposits/withdrawals, so users have to unshield before depositing (and need to withdraw transparent funds). This creates friction and reduces privacy. Exchanges are also nervous about deposits from recently unshielded funds (see the Binance delisting thread).

It feels like having a mechanism by which exchanges can “ask more questions about the funds coming in or out” would be helpful here. Transaction controls could work like enhanced TEX addresses - giving exchanges more control over incoming funds while enabling shielded deposits.

(Note: The double opt-in also prevents fat-finger errors, similar to how banks verify IBAN details before transfers. This could be useful even outside of the CEX use-case.)

Transitivity

This one’s a bit more relevant in the case where addresses are long lived and used across payments. Basically if someone’s address gets leaked in a data breach, malicious actors can send unwanted tokens to create relationships (like teams sending Vitalik meme coins for “endorsement”). This is less of an issue with Zcash’s privacy, but still relevant for long-lived addresses.

Other potential use cases of TX controls

E.g. ZSA UX considerations for AssetId discovery and authentication · Issue #755 · zcash/zips · GitHub seems relevant here. Especially:

“It could be nice if wallets have an opt-in or opt-out to receive funds, especially of a new Asset type. This doesn’t necessarily require protocol support. For example, a wallet could have a “block this txn and all future txns involving this AssetId” button that simply mutes those txns from the history list.”

ivk vs ask

Totally fair point about ivk not being appropriate. My reasoning was:

  1. Reuse existing Orchard keys where possible (avoid adding new keys to the protocol. I saw your comment about considering “to have an intermediate key between the spending key and the full viewing key that could be used to authorize receiving funds”. This definitely was in my mind too, but as you pointed out in the comment, there is no such key in Orchard - as of now - and I decided to stick to the current key structure to limit the scope of the protocol changes).
  2. ivk felt more appropriate than ask because it relates to incoming funds, just like approving transactions. Also, my understanding is that: yes, in theory ivk can literally be given to anyone (it’s a key with “fairly weak privileges”), but in practice, it won’t be given to any random party asking for it, simply because ZEC holders won’t want literally everyone to know when they receive funds. Under this setting, I assumed that the holders of a party P’s ivk were “trusted enough” by P to assume the extra responsibility of approving txs. It’s 100% fair to discuss and dispute this assumption.

Now, in my mind, ask isn’t a great fit either because:

  1. ask is about spending not receiving, now we’d mix both
  2. ask should stay “as cold as possible” - and the frequency of “signing to spend” is quite different from the frequency of “signing to receive” funds (especially for a business / charity)
  3. If we use FROST, we’ll need an MPC to accept incoming funds

TL;DR: I don’t think there’s a silver bullet if we want to use one of the existing Orchard key, be it ask or ivk. The cleanest way would be to introduce a new key to have a clear separation of concerns in the key set, but that comes at the cost of adding another key in the protocol.

RedDSA Reuse

Good point, I agree. I noted (in the draft ZIP) that RedDSA was already in the protocol. This was a kind of a TODO for me to check if it could be plugged in as is.. (but I didn’t do that, and moved on to other tasks…) Reusing it is definitely better and cleaner than re-inventing the wheel! :smiley:

[EDIT] So, using RedDSA seems totally fine here, but there’s a caveat. As discussed above, in this ZIP we try to reuse existing keys for the tx approval (that’s a core assumption we make in this design. It’s fine to introduce another key dedicated to “tx-approval” only - as discussed - but we tried not to here to keep protocol changes as limited as possible). Given that we want to prove knowledge of ivk and that we use the relationship pk_d = [ivk]g_d, to use RedDSA in it’s re-randomized form (see screenshot below), we’d need to be able to pass a generator as input to RedDSA.RandomizePublic(𝛼, vk) so that we can re-randomize w.r.t. g_d instead of w.r.t P_G (as currently done in the specs as show below)

And yes, it’s totally fine to blind the key additively instead of multiplicatively (both are sound, but additive blinding is more efficient).

2 Likes