Pulse

Private Accounting

Pulse tracks private balances with shielded account entries designed for DEX workflows on Midnight.

Why Pulse uses its own model

Pulse originally tried to build directly on Midnight shielded notes. That approach worked for simple private transfers, but it placed tight limits on what could be done in one transaction.

The DEX needs account entries that can carry more than one asset at a time and attach action data, so that chains of instructions can be submitted for swaps, liquidity management, withdrawals, or other processing by the batcher. Native shielded notes did not provide enough room for those workflows.

Instead, Pulse implements its own shielded accounting inside the Pulse contract. Users can think of this as shielded accounts for Pulse assets, similar to ERC-20 balances on Ethereum. The important difference is that the account standard and wallet integrations are still being worked out, so these accounts can currently only be accessed through the Pulse DApp.

Shielded accounts

A shielded account entry is a private object owned by an owner commitment. The public contract sees only the hash of that object, while the private data needed to spend it is kept off-chain. Only the owner can spend an entry by proving knowledge of the secret that was committed to.

Although this is easiest to understand as an account balance, each entry is closer to a UTxO than to an Ethereum contract account. It has its own id, owner commitment, asset ids, amounts, and optional action payload. Spending the entry consumes that object and creates one or more new committed entries for the next state.

Pulse entries can hold up to two asset slots. This lets one private object represent a two-sided liquidity deposit.

Nullifiers

Nullifiers prevent double spending. Spending an account entry derives a nullifier from the entry id and owner commitment. When a shielded entry is spent, the transaction proves that the entry commitment exists in the contract's commitment tree and that the nullifier doesn't already exist.

The contract stores every revealed nullifier in a public set. If a later transaction tries to spend the same entry again, it derives the same nullifier, finds that it has already been used, and fails.

This gives Pulse UTxO-like spend semantics while preserving privacy: observers can see that some committed entry was spent, but they do not learn anything about the entry it is related to, nor are able to link it to the new entries created as change or output.