Skip to explanation

Money

How credit becomes private

Follow public lifetime credit through a private-value proof into ordinary outputs and a recoverable debit checkpoint.

6 minute read
On this page
The answer

A private-value transaction may use address credit, owned notes, or both while exposing the same public proof and effects. The credit-capable relation proves sufficiency and checkpoint continuity without revealing the funding composition.

For youRead this after the issuance article when you want to understand the public-to-private boundary.

Before you startKnow that creditAccrued is an address's public lifetime total and never decreases.

Public credit enters a proof; private outputs come out
  1. Public stateLifetime creditThe proof privately opens the address's credit leaf and user account.
  2. Private proofAuthorize and checkSelected account rule + available credit + current checkpoint.
  3. New outputsOrdinary notes + checkpointUp to four ordinary outputs and one private cumulative-debit checkpoint.
  4. Public resultThe common private-value shapeFour nullifiers and five outputs reveal neither the funding composition nor the transfer value.
The proof privately opens the credit, account policy, and current debit checkpoint. Nodes receive only the fixed public effects required to settle the action.

The protocol cannot issue a private note directly to an arbitrary Ethereum address: the address may never have published a PCASH receive key, and one block could otherwise create hundreds of tiny notes. Credit solves the delivery and fragmentation problem by accumulating publicly first. The owner later contributes any positive portion directly to an ordinary private-value transaction, alone or alongside notes.

Available credit is checked, never published

Lifetime accrual
creditAccrued
Cumulative debit
creditSpent
Available now
accrued − spent
Ordinary outputs
Up to 4 private notes
Generated example accrual
1.175811238024197692 PCASH
Debit after spend one
0.260000000000000000 PCASH
Available after spend two
0.814811238024197692 PCASH

Inside the proof, the wallet opens the address's current credit leaf and user account under one recent PCASH state. It also opens the latest private checkpoint, if one exists, and zero to three ordinary input notes. The proof checks:

note inputs + credit contribution = native outputs + public fee

new creditSpent = prior creditSpent + credit contribution

new creditSpent ≤ creditAccrued

Neither comparison becomes a public transaction field. One selected installed application authorizes the account's complete transaction, whichever private funding sources participated. CHONK folds that application, the credit-capable protocol kernel, the common private-value finalizer, and the common wire into one proof.

View the source behind this explanationcircuits/stacks/private_value/credit_kernel/src/main.nr:329

One private checkpoint carries the running debit

Each spend destroys the previous end of the chain
  1. Before any spendNo checkpointThe first nullifier is derived from the address's private nullifier key.
  2. Spend 1checkpoint 0creditSpent = credit contribution
  3. Spend 2checkpoint 1creditSpent = previous total + credit contribution
  4. Next spendSpend the current checkpointOnly one successor can consume it.
The public credit leaf remains a lifetime gross total. A private checkpoint in the output tree carries the cumulative amount already spent.

On the first spend there is no predecessor. The proof derives a unique first-spend nullifier from the address and its private nullifier key, creates the ordinary outputs, and appends checkpoint 0.

Every later spend proves membership of the current checkpoint, publishes that checkpoint's nullifier, and appends a successor with the next index and higher cumulative debit. Because the global nullifier set accepts the predecessor only once, two competing successors cannot both settle. Whether this is the first spend is itself private.

Every successful private-value transaction appends exactly five output commitments. In a credit-bearing action input slot 3 carries the credit-chain nullifier and output slot 4 carries the new checkpoint; their classes remain private. Input slots 0 through 2 and output slots 0 through 3 retain the ordinary note-or-padding grammar.

View the source behind this explanationcircuits/stacks/private_value/credit_kernel/src/main.nr:166

The public transaction does not identify the funding source

The privacy boundary
FactObserver seesWhy
Funding compositionHiddenNotes, credit, and mixed funding share one wire shape
Fee and fee recipientVisibleNodes must apply the fee credit
Funding addressHiddenOpened only inside the proof
Payment amount and recipientsHiddenCommitted in private note outputs
Spent total and remaining creditHiddenCarried through the checkpoint chain
Selected account ruleHiddenFolded into the same proof
Nodes learn only what consensus needs to verify freshness, prevent replay, append commitments, and pay the relayer.

Note-only, credit-only, and mixed actions share type 0x00, one wire VK, four nullifiers, five output bodies and output-data hashes, one fee, one validity window, and one proof length. The fee amount and recipient remain public because every node must apply that fee as a credit increment, but no field says which private funding sources participated.

The funding address and credit contribution are absent. So are the input notes, recipients, cumulative debit, available credit, first-versus-later branch, selected protocol kernel, and selected authorization application. Nodes verify the proof and apply its opaque commitments without reconstructing any of those facts.

The owner can recover after losing wallet state

Opaque recovery data is useful only with the wallet key
slot-4 recovery capsulepublic ciphertext in ordinary output data
wallet keyderived from creditSpendNk
creditSpentverify by recomputing the checkpoint output
Each checkpoint's proof-bound output data carries a wallet recovery capsule. The owner can open it, validate the checkpoint, and reconstruct the private spending history.

The recovery capsule does not reveal the debit to observers. It is encrypted to a deterministic recovery key derived from the owner's private credit nullifier hierarchy, while its exact bytes are bound by the transaction commitment. The latest valid capsule alone determines cumulative spending and therefore current available credit; earlier capsules are needed only to locate and authenticate that terminal checkpoint when no trusted local position survives. The wallet validates any recovered capsule by recomputing the checkpoint body and indexed output commitment.

This makes the chain recoverable from the owner's keys and canonical history rather than a fragile local counter. Capsule usefulness follows the same wallet boundary as recipient delivery: consensus binds opaque bytes but does not prove that a custom wallet constructed useful recovery material. The reference wallet round-trips the capsule before submission; retaining an authenticated terminal checkpoint is an optimization, not a second balance representation.