UX: Private Transactions

Proof Generation and Relayers are crucial pieces of the private transaction process. These steps each require complex interactions, and the user experience (UX) design is critical to ensure that private transactions are simplified for users.

Order of Operations

There is a typical order of operations to every private transaction. The first two actions (#1 gas estimate and #2 relayer fee calculation) occur automatically. They should refresh any time a transaction's parameters change.

#3 Generate Proof should occur after some action by the user, typically through a button. It's recommended to show a loading indicator through the proof generation process, as it can take up to 30 seconds depending on the device and the complexity of the transaction.

#4 Populate and #5 Submit should occur on user submission.

It is recommended as a two-part process with user interaction needed to begin #3 and #4 because of the time proof generation takes.

Please note that each step can throw errors, so it's best practice to wrap calls in a try/catch in order to report the error message to the user.

1. Gas Estimation

First, we estimate the gas for a transaction.

Gas Estimates must be re-estimated when any of the gas-estimate parameters change. Each parameter can impact the number of UTXO inputs and outputs, thereby changing the amount of gas to execute the transaction.

2. Relayer Fee Calculation

Next, the gas estimate is used to calculate the fee that is paid to a Relayer. Relayers typically charge small premiums on top of gas, and they accept a variety of ERC-20 tokens as payment.

See Relayers for connecting to the Relayer network and calculating the Relayer fee.

3. Generate Proof for Transaction

This uses the Groth16 Prover to build a zero-knowledge proof of a user's private transaction. Automatically downloads circuit assets if necessary.

The challenge here is for the user experience — a Relayer Fee expires after a certain period (usually around 3 minutes). Each Relayer broadcasts its current fees and expirations. If the fee expires, the transaction will need to be proved again to be valid.

4. Populate Proved Transaction

This is where we generate the actual encrypted transaction.

The "populate" method for each private transaction will validate the last generated proof and wrap it into a transaction. It then generates an encrypted PopulatedTransaction that is serialized for easy submission through a Relayer.

5. Submit Transaction

Finally, submit the transaction through a Relayer.

Self-Signing Transactions

It is possible to use an owned public wallet to self-sign a transaction, rather than using a Relayer. While the contents of the transaction will be encrypted, the transaction itself will be associated with the self-signing public wallet on the blockchain.

In the self-signing flow, we can skip the #2 Relayer Fee calculation entirely, and sign/send the serialized transaction to the blockchain like any other public transaction without submitting to a Relayer.

In order to retain anonymity, users can seed a new public wallet with gas using a Base Token Unshield, so that none of their previous public transactions are associated with the new wallet. As long as the public wallet is only used to sign private transactions, this same level of anonymoty is achieved as when using a Relayer.

Last updated