Sovereign Circuit · Born Between 2 Generals
Dual Attestation Protocol
Sealed commit–reveal valuation for used hardware. Both sides price the unit privately, both publish a cryptographic commitment before either number is visible, then both reveal. Close numbers settle at the midpoint automatically. Distant numbers are broken by a published index, not by whoever has more leverage.
The single property this buys: neither side can move their number after seeing the other side's number.
1 What this protocol is for
Every hardware program that takes equipment in and gives value back has the same unsolved problem: somebody has to say what the used thing is worth.
In practice one side says it and the other side accepts it. That is how phone carrier trade-ins work, and it is the most resented moment in the entire subscription-hardware model. The customer hands over a working device, is told a number they have no way to check, and has no recourse. The vendor holds all of the information and all of the discretion.
Dual Attestation removes the discretion. It does not ask either party to trust the other. It makes the sequence of events cryptographically impossible to game.
1.1 The doctrine it comes from
The rest of the portfolio already refuses to present an assertion as evidence. This protocol applies the same rule to money: the holder's claim is an assertion, the inspector's finding is an observation, and the sealed record keeps both rather than collapsing them into a single price. The settled figure is derived from the two, and the derivation is published.
1.2 Where it is used
| Moment | Holder side | Inspector side |
|---|---|---|
| Intake of a retiring fleet | The supplying company | The program bench |
| Residual at scheduled upgrade | The subscriber | The program bench |
| Cascade re-grade between tiers | Outgoing tier record | The program bench |
| Certified material recovery | The program | The recovery partner |
Residual at scheduled upgrade is the exact moment carriers lose customer trust. Doing it under sealed dual attestation turns the most resented event in the model into the most defensible one.
3 Cryptographic dependencies
| Function | Standard |
|---|---|
| Hash | SHA-256 — FIPS 180-4 |
| Canonical serialization | RFC 8785, JSON Canonicalization Scheme |
| Nonce generation | CSPRNG per NIST SP 800-90A Rev. 1 |
| Transport authentication | HMAC — RFC 2104 |
| Party signatures (optional) | Ed25519 — RFC 8032 |
| Independent timestamping (optional) | RFC 3161 TSP |
The construction is the standard sealed-bid primitive: publish a hash of your figure plus a blinding nonce, then reveal, and the hash proves the revealed value is the one you were bound to (Chainlink on commit-and-reveal). The known failure mode of naive commit–reveal is the last-revealer advantage — whoever reveals last can compute the outcome and choose to abort. §6.4 addresses that directly, and it is the reason non-reveal is penalised rather than merely logged.
No floats, anywhere
All money is integer cents; all rates are integer basis points. The reference implementation raises on any float rather than canonicalizing it, because IEEE-754 serialization differences between two implementations would silently produce non-matching digests — the worst possible failure, since it looks like fraud.
Domain separation
Every digest is prefixed with exactly one tag —
SCDA1|commit|, SCDA1|record|,
SCDA1|round| — so a digest computed for one purpose can never be
replayed as a digest for another. It costs nothing and there is no reason to omit
it.
4 Commitment
C = SHA256( "SCDA1|commit|" || JCS(commit_body) )
{
"protocol": "sovereign-circuit/dual-attestation/1",
"round_id": "R-2026-08-0417",
"asset_id": "SC-LT-000391",
"party_id": "ACME-HOLDINGS",
"role": "holder",
"amount_cents": 42000,
"grade": "B2",
"nonce": "a1a1a1a1…a1a1"
}
4.1 Why each field is inside the digest
- round_id
- Binds the commitment to one round. Without it, a commitment can be replayed in a later round where the same number happens to be favourable.
- asset_id
- Binds it to one unit.
- party_id + role
-
Prevents a commitment from being attributed to the other side. Without
role, an adversarial coordinator holding both commitments could swap which is which after seeing the reveals and pick the better outcome. - amount_cents + grade
- The substance. Grade is committed alongside amount so a party cannot retroactively justify a price with a different condition claim.
- nonce
- Hiding. Not optional, and 32 bytes is not excessive. The plausible price range for a used business laptop is a few thousand distinct cent values in practice. Without a nonce, anyone holding the commitment can enumerate the entire space in microseconds and read the sealed amount. The nonce is what makes the commitment actually sealed.
- 32 bytes from a CSPRNG, fresh per party per round.
- MUST NOT be derived from the amount, the round id, a timestamp, or a counter.
- Reuse across rounds by the same party leaks equality of amounts.
- Published at reveal. It is not a long-term secret and MUST NOT be reused as a key.
4.4 Grade precedes price
A price round cannot open until a grade is published. This is not a courtesy of sequencing — it is enforced at the station, and it is the reason the whole two-party structure holds.
The reason is the same one that makes policy_hash get published before
any commitment. If price could be committed while the grade was still adjustable, a
party could shade its grade to justify a number it had already picked. Fixing the
grade first makes the number argue against a settled fact rather than against a
movable one.
-
P1
Grade round
Both parties commit a sealed 66-field observation sheet, then reveal. The station recomputes each commitment and refuses a reveal that does not reproduce it. The published grade is derived from the conservative merge of the two sheets — the worse reading of every field — so neither party can improve the grade by being generous to itself.
-
P2
Price round
Only now does the price window open, and only against the published
grade_token. A price commitment carrying any other grade is refused outright rather than settled at a discount.
4.4.1 The three terminal states
Two of the grade-round outcomes end the round and no price window opens on either.
- Void — the two sheets disagree on a Class M field, a machine reading. One instrument, two answers, means the reading procedure failed. This voids even when both sheets happen to derive the same grade, because the defect is in the measurement, not the judgement. The unit is re-read.
- Material divergence — the sheets derive different grades. The station reports the minimal set of fields responsible and stops. Nothing is averaged; there is no midpoint between two grades.
- Immaterial divergence — the sheets differ but derive the same grade. This one proceeds. The conservative merge is authoritative.
Each of these guards was removed from the implementation one at a time to confirm that a real test fails in its absence. The results of that exercise are recorded in the test file rather than asserted here.
The grade binding lives at the station, not inside Policy.
Policy is hashed into policy_hash, and the published test
vectors pin that hash — adding fields to Policy would have silently
invalidated every one of them. The station carries the binding under its own domain
tag SCST1|policy|, and the test suite asserts the original
policy_hash is byte-for-byte unchanged.
5 Round lifecycle
-
01
Open
The coordinator publishes
round_id,asset_id, the policy, the commit deadlineT_c, the reveal deadlineT_r, and the index source that would be used on escalation.Load-bearing rule:
policy_hashMUST be published before the commit window opens. If the policy could change afterwards, the coordinator could pick a tolerance band that produced the outcome it preferred. -
02
Commit
Each party values the unit without access to the other's figure and publishes only
C. The coordinator MUST NOT disclose either commitment to the counterparty beforeT_ccloses; publishing both afterwards is encouraged, because it lets each side confirm the other was genuinely bound before reveals began.If only one party commits, the round is void and reopened. No default applies at commit stage — a party who never committed was never bound, and treating silence as agreement to a number they never saw would be unfair.
-
03
Reveal
Each party publishes
amount_cents,gradeandnonce. The coordinator recomputesCand rejects any reveal that does not match. Reveal ordering is not significant to the arithmetic. -
04
Settle
Deterministic. Given the same two revealed amounts and the same policy, every conforming implementation MUST produce the same result to the cent.
-
05
Seal
The round record is appended to the hash chain and the chain head advances. Any later edit breaks every subsequent link.
6 Settlement
6.1 Policy
{
"tolerance_bp": 1000, // 10.00% auto-settle band
"floor_cents": 2500, // low-value absolute gap
"absolute_floor_bp_exempt_cents": 5000,
"bonus_bp": 250, // verified-condition bonus
"bonus_inner_bp": 300, // bonus band
"bonus_cap_cents": 7500,
"late_reveal_penalty": "counterparty_amount",
"index_name": "SC-COMP-A"
}
policy_hash = f5bbc16aaba884177e6581aa528aa6b84c489aa842e592a9998909154ed5c0c1
6.2 Spread
spread_bp = round_half_up( (max − min) × 10000 / min )
Measured against the lower of the two amounts. This is the conservative choice: it produces a larger number than measuring against the midpoint or the higher amount, so the band is harder to satisfy. Any round that auto-settles under this definition would also auto-settle under the looser ones. In plain language, the gap is expressed as a percentage of the smaller number.
6.3 The ladder
Inside the band → midpoint
If spread_bp ≤ tolerance_bp, settle at
round_half_up((holder + inspector) / 2). Half-up, not banker's
rounding: two independent implementations must agree to the cent, and half-up is
what a non-technical participant expects when they check the arithmetic by hand.
Low-value exemption → midpoint
On a $32 accessory an $8 gap is 2500 bp and means nothing, and escalating it
costs more than the item. If both amounts are small and the absolute gap is
under floor_cents, settle at the midpoint regardless of percentage.
Outside the band → index, clamped
amount = max( min_revealed, min( max_revealed, index ) )
The clamp is not merely defensive. It guarantees escalation can never land outside what both parties actually claimed. If the index says $200 while the holder said $900 and the inspector said $300, settlement is $300 — the inspector's own number. A stale, thin or manipulated index cannot be used to pay a participant less than the program's own bench assessed.
Verified-condition bonus
If spread_bp ≤ bonus_inner_bp, add bonus_bp of the
settled amount, capped at bonus_cap_cents.
This is the economic engine and it is not goodwill. It pays participants for accurate self-assessment. A holder who grades honestly lands inside the inner band and earns more than a holder who inflates. Across a fleet that converts inspection from an adversarial cost centre into a spot-check, because incoming grades are already close. Cheaper inspection is the return on the bonus.
6.4 Non-reveal
If one party commits and then fails to reveal by T_r, settlement is
the counterparty's revealed amount, no bonus is paid, and the
default is recorded as such.
The revealing party does not get to name the price unilaterally. If they did, there would be a direct incentive to induce a non-reveal — delay the counterparty, run out the clock, then name any number. Settling at the counterparty's sealed figure is the only reading that does not reward gamesmanship.
6.5 What the protocol deliberately does not do
-
It does not decide whether a unit is worth anything. That is the
grading rubric, which runs first and must publish a
grade_tokenbefore this protocol's price window opens. - It does not price subscriptions. Published Sentinel prices remain a floor and are not undercut by any credit produced here.
- It does not arbitrate disputes about physical condition. It records both positions and settles the money; a condition dispute is a separate process.
Run a round in your browser.
This is the real protocol, not a mock-up. Hashes are computed with SHA-256 via the Web
Crypto API over RFC 8785-canonical JSON, using the same domain tag as the reference
implementation — the commitment for the §10.1 vector inputs reproduces
f40ccaef… byte for byte. Nothing leaves your device.
—
—
—
7 Security analysis
| Attack | Mitigation |
|---|---|
| Move your number after seeing theirs | Commitment published before reveal; the digest will not match. |
| Brute-force a commitment to read the sealed amount | 32-byte nonce. The search space is 2²⁵⁶, not the price range. |
| Replay a commitment into another round or unit | round_id and asset_id are inside the digest. |
| Swap which commitment belongs to which side | party_id and role are inside the digest. |
| Change the rules after seeing the numbers | policy_hash is published before the commit window opens. |
| Last revealer aborts an unfavourable round | §6.4 — non-reveal settles at the counterparty's amount. |
| Coordinator leaks a commitment to the other party | Commitments are hashes; leaking one reveals no amount. Leaking a reveal early does break the protocol, so reveals MUST be gated. |
| Manipulate or stale-date the index | Index is only reachable outside the band, and is clamped into the revealed range. |
| Silently rewrite a settled round | Hash chain — any edit changes the entry hash and breaks every later link. |
7.1 Residual weakness: the coordinator is not neutral
In most rounds the program is both the inspector and the coordinator. The cryptography stops it changing its own number after seeing the holder's, and stops it rewriting a sealed round. It does not structurally stop it mis-implementing the arithmetic, or withholding a reveal it dislikes and claiming default.
Three mitigations, increasing in strength: publish the reference implementation and vectors so any holder can recompute their own settlement; add RFC 3161 timestamping so commitment timing is attested by a third party rather than the program's own log; and for high-value rounds add a third attesting party — the supplier's auditor or insurer — committing alongside. The protocol generalises to n parties without structural change: the band test becomes max-versus-min across all reveals and settlement becomes the median rather than the midpoint. That is a v1.1 extension and is not specified here.
Honesty about this is the point. The protocol makes a specific, verifiable promise and does not pretend to make a larger one.
8 The sealed record
{
"protocol": "sovereign-circuit/dual-attestation/1",
"round_id": "R-2026-08-0417",
"asset_id": "SC-LT-000391",
"policy_hash": "f5bbc16a…d5c0c1",
"commitments": { "holder": "…", "inspector": "…" },
"reveals": {
"holder": { "amount_cents": 42000, "grade": "B2", "nonce": "…" },
"inspector": { "amount_cents": 39000, "grade": "B3", "nonce": "…" }
},
"settlement": {
"outcome": "auto_settled",
"amount_cents": 40500,
"spread_bp": 769,
"bonus_cents": 0,
"total_cents": 40500,
"reason": "spread 769 bp within 1000 bp band; midpoint settlement"
},
"timestamps": { "commit_opened": "…", "reveal_closed": "…", "settled": "…" }
}
The record retains both revealed amounts, not just the settled figure.
The holder's claim stays visible as an assertion and the inspector's finding stays
visible as an observation. Collapsing them into one price would destroy the evidentiary
value of the record. The reason string is human-readable on purpose: a
participant reading their own record should see the arithmetic without a decoder.
entry_hash = SHA256( "SCDA1|record|" || JCS({ prev, seq, body }) )
Genesis prev is 64 zeros. This reuses the audit-chain pattern already used
elsewhere in the platform. A Merkle log per
RFC 6962 is the natural upgrade
once efficient inclusion proofs are needed — a holder proving their single round is in
the log without downloading it. A linear chain is sufficient at pilot volume and far
easier to audit by reading.
10 Normative test vectors
A conforming implementation MUST reproduce all of these exactly. Every value below was produced by running the reference implementation, not written by hand.
Commitment
round_id R-2026-08-0417
asset_id SC-LT-000391
party_id ACME-HOLDINGS
role holder
amount_cents 42000
grade B2
nonce a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1
C = f40ccaef3378cbfb0574d0499f8a8d3bfd35d2990edcf7943e5f163ed2db9165
Mutating amount_cents to 42001, round_id to
R-2026-08-0418, or role to inspector must all be
rejected against that commitment.
Settlement
| # | Case | Holder | Inspector | Index | Spread | Outcome | Settled | Bonus | Total |
|---|---|---|---|---|---|---|---|---|---|
| TV-1 | inside band | 42000 | 39000 | — | 769 | auto | 40500 | 0 | 40500 |
| TV-2 | identical figures | 40000 | 40000 | — | 0 | auto | 40000 | 1000 | 41000 |
| TV-3 | edge, exactly at band | 44000 | 40000 | — | 1000 | auto | 42000 | 0 | 42000 |
| TV-4 | just outside band | 44100 | 40000 | 41500 | 1025 | escalated | 41500 | 0 | 41500 |
| TV-5 | index below revealed range | 90000 | 30000 | 20000 | 20000 | escalated | 30000 | 0 | 30000 |
| TV-6 | inner band, bonus | 41000 | 40000 | — | 250 | auto | 40500 | 1013 | 41513 |
| TV-7 | low-value exemption | 4000 | 3200 | — | 2500 | auto | 3600 | 0 | 3600 |
| TV-8 | non-reveal default | 38500 | — | — | n/a | defaulted | 38500 | 0 | 38500 |
Why TV-5 exists
The clamp doing its job. The index said 20000, below the inspector's own 30000, so settlement is 30000. The program cannot use a low index to pay a participant less than its own bench assessed.
Why TV-6 exists
250 bp of 40500 is 1012.5, which rounds half-up to 1013. This vector exists purely to pin the rounding direction so two implementations cannot drift by a cent.
Hash chain
entry[0].hash = 5472ffe25bd5e7e2f2cbfc38351017781c8280d6f14670c4c3bbb246c787f133
entry[1].prev = 5472ffe25bd5e7e2f2cbfc38351017781c8280d6f14670c4c3bbb246c787f133
entry[1].hash = 375e31cf0216123658529e6575925543c865b83964def4393a34625b8b1ae1ad
head = 375e31cf0216123658529e6575925543c865b83964def4393a34625b8b1ae1ad
Changing settlement.amount_cents in entry 0 from 40500 to 41000 makes
verification fail. That tamper case is asserted in the test suite.
11 Open items
These are genuinely unresolved and are called out rather than papered over.
-
The grading rubric written, not calibrated
This was the biggest dependency and it is now closed structurally. SCGR1/1.0 defines 66 recorded fields, three derived axes and a
grade_token, asserted by 247 checks. What remains open is calibration, not construction: every threshold in it is a defensible starting guess rather than a number measured from fleet data. Two consequences here —rubric_hashchanges when thresholds are recalibrated, so rounds are only comparable within a rubric version; and the grade-before-price ordering in §4.4 is now enforced bystation.py(SCST1/1.0), covered by 99 checks, with every guard removed one at a time to confirm a real test fails without it. Calibration is now instrumented rather than merely admitted — a twenty-unit blind double-grading worksheet and an analyser report divergence rates, pivotal fields and observed distributions. Batch 1's honest output is a better measurement method, not recalibrated thresholds. -
The index does not exist yet
SC-COMP-Aneeds a defined construction, publication cadence, source list and archive, so a historical round can be re-verified against the value that was current at the time. An index that can be silently restated is not a tie-breaker. -
Tolerance band calibration
1000 bp is a starting guess. It should be set from real paired data — bench grade versus holder self-grade across a first batch — not chosen because it is a round number.
-
Bonus cap
$75 is a placeholder. The cap must sit below the marginal cost of a full inspection, or the bonus stops paying for itself.
-
Deadlines
T_candT_rneed defaults. Too short disadvantages a holder without technical staff; too long stalls the loop. -
Identity and signatures
Ed25519 signing is optional today. It becomes necessary the moment a participant might deny having committed. Key distribution is unspecified.
12 Legal note
Do not market any part of this as insurance, and do not describe the settled figure as an appraisal, until counsel has reviewed it.
Both are regulated terms of art. The distinction between a warranty, a service contract and insurance turns on who bears the risk and whether the obligor is the party providing the goods (IRMI). Service-contract obligors face state-by-state registration and reserve requirements (NCOIL), states such as Virginia have specific statutes (Extended Service Contract Act), and California draws the line by obligor (dealer-obligor versus mechanical breakdown insurance).
The safe framing for this protocol is a contractual valuation mechanism inside a subscription agreement. The program is not producing an appraisal; it is producing a contractually agreed figure derived from two sealed inputs under published rules. That is a materially more defensible claim — and a more accurate description of what actually happens.
| Use | Avoid |
|---|---|
| settled value, agreed value | appraised value, fair market value opinion |
| protection plan, swap-on-failure | insurance, coverage, policy |
| participation credit | rebate, cash-back, payout |
| service-level obligation | claim, indemnity |
13 Why build this first
It requires no hardware. The entire protocol is specifiable, implementable, testable and demonstrable before a single unit is acquired — as this page and its passing vectors demonstrate.
It is also the best sales artifact the program has. A supplying company's procurement or finance team does not need persuading that a laptop can be wiped. They need persuading that they will not be low-balled on a fleet. A working demonstration where they commit their own number, watch the program commit blind, and see the midpoint settle automatically is a more convincing five minutes than any deck.
The artifacts
Everything on this page exists as a file. Nothing here is a rendering of something that only lives in a slide.
-
SPEC.mdThe normative specification, 13 sections, plain Markdown. -
attestation.pyThe reference implementation. Python standard library only — no dependencies to install, nothing to trust beyondhashlib. -
test_spec.pyAsserts every vector in §10 plus the tamper and invariant cases. Runpython test_spec.py; it prints one line. -
test-vectors.jsonThe same vectors, machine-readable, for a second implementation to check against. -
make_vectors.pyRegenerates the vectors, so a change to policy defaults cannot silently drift. -
station.pyThe test station. Enforces §4.4 — no price window opens without a published grade, and a voided or materially-divergent grade round is terminal. -
test_station.py99 checks on the ordering, plus a recorded guard-removal exercise: each guard was deleted in turn to confirm a real test fails without it. -
CALIBRATION.mdWhich thresholds are guesses, what evidence would settle each, and the sample size below which a change is not supportable. -
batch-1-calibration.xlsxThe blind double-grading worksheet for the first twenty units. Generated from the live field registry, so the sheet cannot drift from the code that grades it. -
calibrate.pyReads the filled sheets, reconciles every pair, and reports divergence rates, pivotal fields and observed distributions. It deliberately proposes no new thresholds.