EconomySpend Checks
Authoritative Spend
A receipt is authoritative only when an Allow decision, a reconciled budget hold, a signed execution nonce, and the recorded nonce all agree.
A receipt can say that money moved. That is a different claim from proving it. The difference is a machine-checkable predicate, is_authoritative_spend_receipt in chio-core-types, which every consumer of a spend receipt runs before believing one: the settlement gate, the comptroller surface projection, and the reconciliation ledger all agree on what the word means because they call the same function.
The frozen contract shape the predicate pins is the receipt profile chio.mediated_spend.v1. The nonce it demands is chio.execution_nonce.v1. The strength a store declares for the hold behind the receipt is BudgetGuaranteeLevel. Reconciliation holds the ledger view of the same contract and reuses these ids.
What a receipt must prove
A TrustLevel::Mediated value on a receipt is a stamp written at persistence time. On its own it is not evidence that budget was held or that guards ran, and a receipt emitted beside the kernel rather than through it can carry that stamp while nothing was enforced. The predicate exists so that difference is visible to a program rather than only to a reader.
The rule is a conjunction over one receipt, one presented nonce, and a set of admitted kernel keys. Nothing is weighed and nothing defaults to true. A missing element is a refusal, and the refusal names which element was missing.
The checks
The predicate runs the checks in a fixed order and returns at the first one that fails.
- The receipt signature verifies. The nonce signature covers only the nonce, so without this a holder of a valid nonce could forge the receipt fields around it and still present an admitted key. A verification error and a false result are both refusals.
- The signer is an admitted kernel key. The receipt's
kernel_keymust appear in the caller's admitted set. - The decision is a mediated Allow. Four receipt fields in sequence: receipt kind
MediatedDecision, boundary classPrevent, noobservation_outcome, trust levelMediated, and the decision is Allow. - A hold that reconciled and moved. The receipt must project a
BudgetAuthorityReceiptRefwith a non-empty hold id, its budget-authority block must pin the frozen profile exactly, its terminal mutation must be a reconcile rather than a reverse or a release, and its exposed units must be above zero. - The receipt names the nonce. The budget-authority block carries an execution nonce id and it must equal the presented nonce's id. When the presented nonce also names a reserved hold, that hold must be the one this receipt settled. A nonce naming no reserved hold is bound through the id alone, which is the single-shot and strict-retry path.
- The nonce binds this exact call. Four equalities against the receipt:
capability_id,tool_server,tool_name, andparameter_hash. The refusal names the field that differed. - The nonce is signed by the same key. The nonce signature must verify under the receipt's own kernel key, not merely under some admitted key.
Every way it refuses
The return type is Result<(), NotAuthoritativeReason>, not a boolean, so a consumer that rejects a receipt can say which clause it failed. Each conjunction fragment maps to at least one variant, which is what lets a conformance matrix flip them one at a time.
/// Distinct rejection reasons; each of the (a)-(f) conjunction fragments maps to
/// at least one variant so a conformance matrix can flip them independently.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NotAuthoritativeReason {
ReceiptSignatureInvalid,
SignerNotAdmitted,
NotMediatedDecision,
NotPreventBoundary,
ObservationOutcomePresent,
NotMediatedTrustLevel,
NotAllowDecision,
MissingBudgetAuthority,
HoldNotReconciled,
ExposureNotCommitted,
NonceLinkMissing,
NonceLinkMismatch,
/// The presented nonce cryptographically names a reserved budget hold that
/// differs from the receipt's committed `budget_authority.hold_id`. The
/// nonce id links the two artifacts, but the hold the nonce reserved is not
/// the hold this receipt settled, so the receipt is not authoritative for
/// the presented nonce. Fail-closed on this cross-binding inconsistency.
ReservedHoldMismatch,
NonceBindingMismatch {
field: &'static str,
},
NonceSignatureInvalid,
/// The receipt's budget-authority block does not pin the frozen
/// `MEDIATED_SPEND_PROFILE`, so its contract shape is unversioned or a
/// different version than the consumer requires.
MissingOrWrongMediatedSpendProfile,
/// The receipt's guarantee level is weaker than the operator-configured
/// floor (R4 truthfulness). Unrelated to `TrustLevel::Mediated`.
GuaranteeLevelBelowFloor {
minimum: String,
actual: String,
},
/// The operator-configured guarantee floor is not a recognized level, so it
/// cannot be ranked. Fail-closed rather than admitting every receipt.
UnknownGuaranteeFloor {
minimum: String,
},
/// The receipt's own guarantee level is not a recognized level, so its
/// truthfulness claim cannot be ranked. An unrecognized level ranks as the
/// weakest, which would silently clear the weakest valid floor; fail-closed
/// instead so a typoed or forged level never passes as authoritative.
UnknownGuaranteeLevel {
actual: String,
},
}The last three variants belong to a separate check. receipt_meets_guarantee_floor compares the level the receipt declares against an operator floor, and refuses when either string is unrecognized rather than ranking an unknown level as the weakest one.
The execution nonce
The nonce is what makes the binding clause checkable. The kernel signs a single-use body that pins one invocation, and the signature covers the canonical JSON of that body.
/// Signable body of a kernel-issued execution nonce.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ExecutionNonce {
pub schema: String,
pub nonce_id: String,
pub issued_at: i64,
pub expires_at: i64,
pub bound_to: NonceBinding,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reserved_hold_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reserving_request_id: Option<String>,
}On the wire the signed form is SignedExecutionNonce, an object with the body under nonce and the Ed25519 signature beside it, not one flat object. The two optional fields are omitted when absent.
bound_to is the whole point. Its six fields are what the predicate compares against the receipt:
| Binding field | Checked against |
|---|---|
capability_id | The receipt's capability_id |
tool_server | The receipt's tool_server |
tool_name | The receipt's tool_name |
parameter_hash | action.parameter_hash on the receipt |
request_id | The invocation the kernel is verifying. An empty value is refused, so a nonce cannot be minted for an unidentified call |
subject_id | Carried on the binding and covered by the signature |
Verification is separate from the authoritative-spend predicate and fails closed on its own terms: a schema that is not the nonce schema, an expiry already passed, a binding field that differs, a signature that does not verify, a nonce already consumed, an encoding failure, or an unreachable replay store. Reservation is single-use, and a durable store must retain the consumed marker until the signed expiry so a pruned row cannot let a live nonce replay.
The declared guarantee level
A hold moving against a capability says nothing about how strong that hold was. The receipt therefore carries a level the budget store declares for itself, and the four levels are totally ordered by rank so an operator can pin a floor.
| Rank | Wire value | Variant | What the name asserts |
|---|---|---|---|
| 3 | ha_linearizable | HaLinearizable | The hold is linearizable across a replicated store |
| 2 | partition_escrowed | PartitionEscrowed | The hold is escrowed so a partition cannot double-spend it |
| 1 | single_node_atomic | SingleNodeAtomic | Hold and reconcile are atomic on one node, which is the authority |
| 0 | advisory_posthoc | AdvisoryPosthoc | No enforced hold. Spend is recorded after the fact |
Two revocation-commit paths accept only the top two levels SingleNodeAtomic and HaLinearizable, so a store declaring an escrowed or advisory hold cannot record a revocation commit. Beyond that, the level is a self-declaration. The predicate checks that the string is a level it recognizes and that it ranks at or above the floor the operator passed. It cannot check that the store really provides what it claims, which is why the truthfulness of the declaration is a conformance obligation rather than a proof.
Authorize the worst case, then reconcile
The hold behind an authoritative receipt follows one lifecycle: authorize the worst case up front, then reconcile down to what actually happened. The authoritative number is the authorize-and-reconcile pair, not either endpoint alone, which is why the predicate refuses a hold whose terminal mutation was a reverse or a release.
- Authorize. The kernel holds the worst case:
quote.quoted_costwhen a quote is present, otherwisemax_cost_per_invocation. - Execute. The governed call runs under the kernel-signed nonce.
- Reconcile. The hold reconciles down to the realized cost, releasing the unused reservation back to the capability budget.
- Reverse. A deny or an abort reverses the hold entirely, so a call that never executed leaves no residual charge and no authoritative receipt.
That lifecycle is durable, not merely in-memory. The kernel records an economic mutation as one of 5 admission states and moves between them over 6 legal transitions, so a crash between the hold and the receipt resolves to a recorded outcome rather than an unknown one.
crates/kernel/chio-kernel/src/admission_operation/state.rs:521-623at fe56570Durability covers the full admission machine, including the dispatch states that share the enum and the reversal steps that run when an evaluation is dropped.
The reserved linkage fields
Two structures carry a slot for a direct pointer back to the nonce and the hold: the comptroller surface report chio.comptroller.surface-report.v1 and the off-chain settlement receipt artifact. Both declare execution_nonce_ref and hold_ref as optional strings.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub execution_nonce_ref: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hold_ref: Option<String>,Both constructors set both fields to None, and skip_serializing_if omits an absent value, so no served report and no minted settlement receipt carries either key. The settlement artifact's validator does not inspect them. A consumer that wants the linkage today reads it from the receipt's own budget-authority block, which is where the predicate reads it. The surface report itself is served at /v1/reports/comptroller-surface on chio trust serve, and Operator Reports specifies the route, the schema, and what the node refuses to serve.
A signed receipt is evidence that spend was governed. It is not the authority to spend. The pre-action gate is capability, policy, and guard: the kernel decides Allow before any money moves, and the receipt is what it leaves behind. The Wall Stops Money works through why that ordering is the load-bearing part.
See also
- Reconciliation for the ledger view of this contract: the exposure ledger, the quoted, observed and charged cost layers, and how reconciled receipts feed billing.
- Budgets & Metering for the authorize, capture, release and reconcile lifecycle against a capability budget, which this contract makes checkable.
- Durability for the full admission machine and what survives a dropped evaluation.
- Receipts for the receipt as a governance record: what it carries and why every governed call emits one.
- Predeclared Settlement for how settlement terms are fixed before the call, upstream of the hold.