Right now, a lot of projects I’ve seen that approach the identification of addresses use an ENS-like approach, where a central registry identifies everyone. While this works for a transparent system like Ethereum or perhaps Zcash Transparent, it is fundamentally not suited for shielded addresses, where address rotation is practically a given, and anonymity/unlinkability matters the most.
Further, most of them require you to contact a light indexer using your IP, which reveals your IP and that you are requesting a specific identity to the server, especially when there is no PIR. We do not claim that we can solve this, but our solution intends to lessen the attack surface from “a general indexer which logs every request” to “only the intended server does”
So, the obvious go-to solution is: federated identity servers, similar to emails. Hence, we thought up a simple, SMTP-like protocol: Zcash Simple Money Transfer Protocol (ZSMTP)
As proposed, the protocol is very simple:
- Servers expose a service (either on a standard port or via SRV) that uses a CEI (Commit-Effect-Interact)-like protocol to reveal addresses.
- Initially, both servers authenticate themselves to be true to their DNS via domainkeys (similar to DKIM)
- Then, the servers perform an Elliptic Curve Diffie Hellman key exchange to establish a secure, deniable session.
- Then the sender requests a (optionally signed) attestation of an address for a given queried user, which the server can generate on-demand using keypairs to protect privacy; for public identities (ENS-like), this can optionally include an attestation against a static public key or against an entry in the Zcash ledger
- The sender sends a sealed invoice encrypted using K.
- The transaction has K as a memo attached, that the
receiving server uses a Incoming Viewing Key to decrypt.receiving party uses their IVK to decrypt. The server can either just be a dumb mailbox for the encrypted blob, which the user can decrypt using their IVK, or the server can be relegated the authority by letting it generate its own IVK. - The exchange completes seamlessly.
Private Information Retrieval can also be implemented to enhance security of this setup.
The main, and most exciting thing will be that if this were to become a ZIP, we can propose and design many more features that can be added as “plugins” to these servers natively, such as:
- A proof-of-activity or proof-of-funds circuit where a sender can prove that they currently own a specific UTXO or combination of UTXOs that equal to or exceed a given transaction value X ZEC, without revealing which UTXO or what their address is, using Merkle membership proofs with a range proof. Services can use this to establish anti-fraud measures as well as for invoicing or “free trials”.
- Loyalty proofs using a shared session key:
- Essentially, say a company wants to give you an airdrop, or check your loyalty without actually logging all your transactions.
- You agree on a shared session secret, and then the company server generates a tree of all of their addresses, and gives the tree and root to you.
- The circuit can privately compute that your address(es) that you have spending keys to have spent a total of more or less than X ZEC across all addresses in the tree, from any number of your own addresses (that you own spending rights to), without revealing either which address were paid from or which addresses were paid into, and what amounts or at what time.
- And many more, suggestions welcome!
Although we did some initial work, we wanted input as to whether this was something Zcash users would really appreciate, and whether this would be good as a standalone grant, a ZIP first (and subsequent grant), or something that should be incorporated in a later network upgrade instead (this one is kind of overblown but putting it there because why not)
Also, if you want to see if a specific thing can be circuit-ised, just reply to this post and our engineers will see if it is possible for that idea to exist as a future plugin ![]()
To be clear, these will run as a Layer-2 over Zcash, privately between two entities over ZSMTP rather than something being broadcasted over the network.
EDIT: Crucial clarification:
I failed to write it clearly, possibly because I am sleep deprived. Just like a real email server, the server doesn’t necessarily have to have the IVK, just like the sending server doesn’t necessarily need to have the spending keys to broadcast the transactions. This task can be delegated to the server or passed back down to the actual user who is receiving or sending the things.
We made it this way so:
- If the server owns the IVK, it can decrypt the memo as normal, there is literally no hassle to the server.
- If the server does NOT own the IVK, then the person who does own the IVK can fetch the encrypted memo from the server mailbox (we envision an IMAP-like approach), and decrypt it locally via their own transaction history. Crucially, encrypting the memo using K that can be later retrieved exclusively by the owner of the IVK prevents the server from learning about the invoice even if it did not own the IVK, while still not requiring the user to be online to receive the invoice themselves, and still allowing proof-of-integrity (user cannot claim they didn’t know what the payment is for, since the server signed for the (encrypted) invoice)
