Applied Zcash

Pattern

Polite actions

Each shielded wallet must try to decrypt each action on the chain. Each action that an app adds increases the scan work of all wallets. Thus, an app must keep its number of actions small.

Problem

An app that keeps state on the chain often uses one note for each user. When a user changes, the app spends the old note and makes a new note. That is one action for each changed user. A busy app makes thousands of actions each day.

The app pays only the fee for these actions. All other wallets pay with scan time and bandwidth. The cost increases with each user of the app.

Mechanism

A light wallet downloads compact blocks. A compact block keeps about 148 bytes of each Orchard-protocol action:

nullifier            32 bytes
cmx                  32 bytes
ephemeral key        32 bytes
ciphertext prefix    52 bytes
                    ─────────
                    148 bytes

The wallet tries to decrypt each action with each key that it holds. This is trial decryption. The compact block drops the memo. Thus, in the compact-block scan:

To read a memo, a wallet gets the full transaction. Only the wallets that read the record pay for its memo bytes.

The action count is the lever. An app that uses fewer actions makes the chain faster to scan for all wallets.

Techniques

  1. Put user state in leaves. Put the state of each user in a leaf of a Merkle tree. Bind the root in one bound note. A change to a user changes a leaf, and the root note changes one time for each epoch. Each user gets a leaf proof from the app and compares the leaf with the bound root.
  2. Put records in the memo. A memo holds 512 bytes, and the compact-block scan skips it. Put the public record of the epoch in the memo of the root note. When the record is too long, add chunk notes to the same transaction. Bind a hash of the full record in the root note. Thus, the binding covers each chunk.
  3. Use the free action. An Orchard-protocol bundle has two actions or more. The builder adds a padding action to a bundle with one action. The root note (spend and output) fills one action. A fee from a shielded note and its change fill the second action. With a transparent fee, the second action is padding. Thus, a record that fits in one memo costs two actions, and each chunk adds one action.
  4. Use epochs. Collect the changes of a period in one transaction. A longer epoch makes fewer transactions each day.

Cost

Spec

This pattern is a design rule. It uses the protocol of today: bound notes for the root, and the ZIP 302 memo format for the record.

Demo: the cost of a scoreboard

A toy app keeps a scoreboard for a game. The scores of some players change in each transaction. The calculator compares two designs:

The calculator pays the fee from a shielded note. With a transparent fee, the per-player design uses one action fewer. The mainnet target block time is 75 seconds. Thus, the chain makes about 1,152 blocks each day.

Design Actions each transaction Actions each day Download each day, per wallet Download each year, per wallet

Example results

Each row has 20 changed players in each transaction, and no chunk notes.

Design and cadence Actions each day Download each day
One note per player, each block25,3443.75 MB
One note per epoch, each block2,304341 kB
One note per epoch, each 10 minutes28842.6 kB