testnet-10 · 2026-09-24
A coordinator took a job, split it, hired a specialist for each part, and paid each one for its own piece. The rules were enforced by Kaspa rather than by anybody’s good behaviour. This is the whole run, from the first transaction to the last — including the payment that settled and delivered nothing, and how that was recovered without paying twice.
Every figure on this page is read from one-job.json, written by the script that ran it.
The cast · covenant v4
The coordinator signs the genesis spend and both delegations and never signs a purchase. Each worker signs its own purchase and nothing else. A fourth key — the stopper — can end any of it at any moment and receives nothing, and no agent here holds it.
All three run the covenant version above — read from the manifests, not typed here. A grant’s script is committed in its address, so a version is not an upgrade: it is a second covenant, and grants issued under the first keep running it until they are reissued. covenant/versions.json maps every fingerprint to its version, and each one is re-derived from its archived template rather than asserted.
The narrowing
The coordinator’s allowlist has two members. Each child was delegated down to one of them — and the child does not merely promise that. It commits to a node of the parent’s allowlist tree and carries the path from that node up to the parent’s root, so the chain can check the narrowing without ever seeing the list. That is why the roots below differ: a different root is the narrowing, visible rather than asserted.
RESEARCH could not have paid the Auditor. VERIFY could not have paid the Researcher. Neither could have paid anyone else at any price, however their code was written.
The sequence
Hiring is serial because a grant is one UTXO: the second delegation’s input is the first one’s output and does not exist until it confirms. Settlement runs backwards because the reserve chain is popped from the end — VERIFY was hired second, so it came home first, and a child settled out of order is refused before anything is built.
| UTC | Step | Transaction |
|---|---|---|
| 11:49:35 | Generated three keys one coordinator, two workers; the stopper is a fourth nobody here holds | — |
| 11:49:36 | Created the coordinator grant 0.8 KAS, two payees, may delegate 2 deep | b5338f8f3fbaa910… |
| 11:49:51 | Opened the batch a local record of what is committed to whom | — |
| 11:49:52 | Delegated to RESEARCH narrowed to 1 of 2 payees, proven by witness | e889c208983f033d… |
| 11:50:09 | Delegated to VERIFY narrowed to the other one, same way | a7f3ea9f5d1c32d9… |
| 11:50:29 | RESEARCH bought its record from the Researcher, at its listed price | 186570c82688f263… |
| 11:57:36 | VERIFY bought the audit paid at 11:50, delivered at 11:57 — see below | e92bd705f3123830… |
| 11:57:38 | Settled VERIFY reserve released, the parent charged what it spent | 1c6b956e4e601101… |
| 11:57:54 | Settled RESEARCH last hired settles first; the chain pops from the end | 290e06f53a5d3936… |
| 11:58:10 | Closed the batch nothing outstanding | — |
| 12:02:45 | Wrote the trace this page is built from it | — |
What was bought
RESEARCH bought a checkable record about kaspanet/silverscript from Warda’s
Researcher. VERIFY bought an audit of covenant/warda_grant.sil from the Covenant
Auditor — so the thing being audited is the thing that enforced the payment. Both
services were already running and neither was told anything about this demonstration.
| UTC | What | Result | Payment | |
|---|---|---|---|---|
| 11:50:24 | research https://github.com/kaspanet/silverscript warda-growth.vercel.app | 200 bought | 186570c82688… | first try |
| 11:50:29 | audit warda_grant.sil warda-node.tailc0c0ec.ts.net:8443 | 502 paid-but-refused | e92bd705f312… | first try |
| 11:53:58 | audit warda_grant.sil warda-node.tailc0c0ec.ts.net:8443 | 409 paid-but-refused | e92bd705f312… | resumed |
| 11:55:13 | audit warda_grant.sil warda-node.tailc0c0ec.ts.net:8443 | 409 paid-but-refused | e92bd705f312… | resumed |
| 11:57:35 | audit warda_grant.sil warda-node.tailc0c0ec.ts.net:8443 | 200 bought | e92bd705f312… | resumed |
VERIFY’s 0.04 KAS reached the Auditor and the report did not come back. The fault was the seller’s: its delivery callback read the covenant off an argument that carries the payment’s metadata, not the request, so it compiled undefined. The free endpoint never had the bug, which is why it survived — the paid path was the only one that could break and the only one never run end to end.
The seller records a payment as spent before it delivers, on purpose: recorded after, a crash leaves a payment that can be replayed forever. So the second attempt was refused as a replay, correctly. Only the operator could undo that — and the buyer never paid twice, because it keeps the proof it was issued and re-presents it rather than buying again.
Fixed, then redeemed: e92bd705f312… paid at 11:50:29 and delivered at 11:57:35 UTC, against the same proof. Four records of one payment, one delivery.
What the network would carry
KIP-9 storage mass counts 1/value over a transaction’s outputs, and a
grant that pays out creates two: the payment, and the grant’s own successor. A covenant
output carries a 32-byte binding that pushes it into a second storage unit and squares its
weight, so the successor dominates. What costs is what the grant has left.
A nearly-empty grant is the expensive one.
This is consensus, not the covenant, and no grant term relaxes it. The per-payment caps below are the sellers’ listed prices to the sompi; the budgets are the smallest amounts the network will let a worker pay out of, with headroom. Every transaction is massed before anything is built.
| Transaction | Storage mass | Against a ceiling of 500,000 |
|---|---|---|
| delegate research | 185,329 | 37% of the ceiling |
| delegate verify | 243,476 | 48% of the ceiling |
| buy research | 262,222 | 52% of the ceiling |
| buy verify | 318,182 | 63% of the ceiling |
| settle verify | 0 | 0% of the ceiling |
| settle research | 0 | 0% of the ceiling |
What this does not show
Everyone joining one agreement in a single step is the shape people usually describe,
and it is what the covenant forbids: #[covenant.fanout(to = 2)] with
require(OpAuthOutputCount == 2) fixes the topology at parent plus
one child. Two workers is two delegations, in two transactions.
A grant is one UTXO, so the second delegation’s input is the first one’s output. Hiring is serial by construction, not by scheduling.
A grant’s payee set is fixed at genesis and a child may only narrow it, so a coordinator can hire from the cast it was created with and nobody else. An agent discovered at run time cannot be paid, at any delegation depth. That is the honest distance between this and an open market, and no amount of tooling closes it — it needs the covenant to change.
The reserve came back. reabsorb requires
newState.reserved == reserved - child.budgetTotal, so settling a worker
restores the coordinator’s capacity to delegate again rather than consuming it for the
grant’s whole life. The cost is ordering: child.reserved == 0 means a
subtree settles from the leaves up, and a long-lived child at the bottom of the chain holds
everything above it.