Skip to content
Specification v1.0 Draft — not legally reviewed 29 Aug 2026

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.

StatusDraft for review
HashSHA-256, FIPS 180-4
SerializationRFC 8785 JCS
MoneyInteger cents, no floats
Vectors8 normative, all passing
Hardware neededNone

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
The commercially important one

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.
Nonce requirements
  • 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.

5 Round lifecycle

  1. 01

    Open

    The coordinator publishes round_id, asset_id, the policy, the commit deadline T_c, the reveal deadline T_r, and the index source that would be used on escalation.

    Load-bearing rule: policy_hash MUST 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.

  2. 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 before T_c closes; 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.

  3. 03

    Reveal

    Each party publishes amount_cents, grade and nonce. The coordinator recomputes C and rejects any reveal that does not match. Reveal ordering is not significant to the arithmetic.

  4. 04

    Settle

    Deterministic. Given the same two revealed amounts and the same policy, every conforming implementation MUST produce the same result to the cent.

  5. 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

1

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.

2

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.

3

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.

4

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.
  • 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.
Live demonstration

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.

What the possessor says it is worth
Self-assessed condition token
What the bench observes it is worth
Bench-verified condition token
Only reachable outside the band
1000 bp = 10%
state awaiting commit
holder C
inspector C
reveals sealed
spread
outcome
settled
reason
chain head

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

Stated plainly

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-1inside band4200039000 769auto 40500040500
TV-2identical figures4000040000 0auto 40000100041000
TV-3edge, exactly at band4400040000 1000auto 42000042000
TV-4just outside band4410040000 415001025escalated 41500041500
TV-5index below revealed range9000030000 2000020000escalated 30000030000
TV-6inner band, bonus4100040000 250auto 40500101341513
TV-7low-value exemption40003200 2500auto 360003600
TV-8non-reveal default38500 n/adefaulted 38500038500

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.

  1. The grading rubric biggest dependency

    The protocol is only as fair as the grade tokens it commits to. The rubric needs testable criteria — firmware support status, TPM version, RAM, storage class, battery health — so a demotion reason is objective rather than a judgment call.

  2. The index does not exist yet

    SC-COMP-A needs 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.

  3. 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.

  4. 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.

  5. Deadlines

    T_c and T_r need defaults. Too short disadvantages a holder without technical staff; too long stalls the loop.

  6. 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

Use Avoid
settled value, agreed valueappraised value, fair market value opinion
protection plan, swap-on-failureinsurance, coverage, policy
participation creditrebate, cash-back, payout
service-level obligationclaim, 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.md The normative specification, 13 sections, plain Markdown.
  • attestation.py The reference implementation. Python standard library only — no dependencies to install, nothing to trust beyond hashlib.
  • test_spec.py Asserts every vector in §10 plus the tamper and invariant cases. Run python test_spec.py; it prints one line.
  • test-vectors.json The same vectors, machine-readable, for a second implementation to check against.
  • make_vectors.py Regenerates the vectors, so a change to policy defaults cannot silently drift.

← Back to the program board Read SPEC.md