Conformance

What it takes to say
this implements Tandem.

Conformance is not a verdict about individual transactions. It is a claim that your implementation produces the same events, the same reason codes, the same state, and the same three roots as any other conforming implementation, at every height. This page sets out what that requires and gives you an order to build it in.

Protocol finalized. Mainnet is not active.

The conformance claim

The specification states it as invariant 12: given the same deployment binding, the same exact specification bytes, and the same blocks on the active chain, independent implementations produce identical events, reason codes, state, counters, event roots, object-state roots, and chained roots at every height.

Everything else on this page follows from that sentence. Note how much it demands beyond agreeing on valid or invalid. Two implementations that reject the same transactions for different reasons are both nonconforming, because their event leaves differ, so their event roots differ, so every chained root after that block differs forever.

There is no conformance authority.

Nobody issues a Tandem conformance certificate, and this repository does not run a test service. Conformance is something you demonstrate with reproducible evidence against published artifacts, and that anyone else can re-run. That is the whole mechanism.

Requirements

What a conforming implementation must do, and the rules that define it
RequirementRules
Bind to exactly one network, one configured INIT txid, and one specification digest, selected by configuration and never by discoveryID-1, ID-2
Derive the namespace commitment and object keys by the exact preimages, using wire byte order for transaction identifiers and never reversing raw digestsID-5, ID-6
Detect marker candidates by the broad rule, so that malformed markers remain detectable and cannot evade multiple-marker countingREC-1, REC-2
Remove foreign INIT candidates before counting markersREC-3
Enforce the exact script and payload lengths, minimal push encoding, and absence of trailing bytesREC-4, REC-5, REC-6
Enforce every fixed payload field, including reserved bytes, flags, defined kinds, and defined reasonsREC-7, REC-8, REC-9
Enforce the key pair rules: valid points, distinct, sorted, and bound to their required rolesPAIR-1, PAIR-4
Enforce the exact 71-byte witness script and the four-element carrier witness stack in orderPAIR-2, PAIR-3
Enforce sequence continuity, carrier continuity, and equal terminal payoutsPAIR-5, PAIR-6, PAIR-7
Enforce the exact fee arithmetic, including the ceiling and floor split that gives the odd satoshi to side APAIR-3.3
Enforce every operation template exactly, with exact input and output counts, roles, and sequencesOP-1 to OP-6
Require confirmation in a strictly earlier block for every required prevoutOP-6 note
Apply the exact state machine, including terminating an object on any confirmed carrier spend that does not validateST-1, ST-2, ST-3
Maintain the three post-block counters exactlyST-6
Apply the dispatch order, including its precedence over numeric reason orderINV-1, INV-2
Return the lowest failing reason code within a single-marker operationINV-3, INV-4
Use the stable reason registry with its permanent names and numeric valuesINV-5
Compute event leaves, object-state leaves, both Merkle roots with odd-leaf duplication, and the chained root, for every block including empty onesROOT-1 to ROOT-4
Reverse block application exactly on disconnection, before applying any replacement branchROOT-4
Exclude mempool observations from state, counters, and roots entirelyST-6

Evidence you can produce today

These are reproducible now, against published artifacts, with no network and no permission required.

Available conformance evidence and its coverage
EvidenceCoversDoes not cover
Specification digest and byte contract That you are reading the same protocol as everyone else Anything about your parser
The five published marker encodings Payload field layout, exact lengths, push minimality boundaries Transaction-level rules, signatures, state
Identity derivations Namespace and object key preimages, and byte-order handling Everything downstream of identity
The carrier derivation Key sorting, witness script bytes, P2WSH construction Signature verification
The 31 validation cases All 26 reason codes, and the event type and class each produces Fee arithmetic against real amounts, real signatures, multi-block behaviour
The published preimages and Merkle levels Leaf field order, domain tags, odd-leaf duplication, both roots Root computation over a real chain
The chained root reconstruction The chaining formula and counter encoding Chaining across many blocks and across a reorganization

Read the right-hand column carefully. The published corpus is a necessary conformance gate, not a sufficient one. It contains no raw transactions, no signatures, no block data, and no reorganization scenarios. An implementation that passes every published vector has demonstrated that its encodings and hashing are right. It has not yet demonstrated that its transaction validation or its rollback is.

Do not claim conformance from the corpus alone.

The accurate statement is that your implementation reproduces every published Tandem vector. That is a real and checkable claim. Claiming full protocol conformance requires evidence for the parts the corpus does not reach, which you would have to produce and publish yourself.

Implementation checklist

Build in this order. Each stage is checkable before the next one is written, which is the only realistic way to find a hashing or ordering mistake before it is buried.

Stage 1: bytes

  1. Hash tandem.md as raw bytes. Compare the digest, byte count, and line count against release/spec.json. Do not normalize whitespace or line endings before hashing.
  2. Hash golden.json and compare it against the fixture digest in the vector manifest.
  3. Derive the vector root from the fixture digest and confirm it equals the published root. Derive it, do not copy it.
  4. Implement the primitive encodings: unsigned little-endian integers, the wire and display hash orders, and the rule that a raw digest is never reversed.

Stage 2: identity

  1. Implement the namespace commitment. Confirm it reproduces the published namespace for the published binding.
  2. Implement the object key. Confirm it reproduces the published object key.
  3. Implement the protocol identifier and object display identifier strings, and use binary keys everywhere internally.

Stage 3: markers

  1. Implement candidate detection by the broad rule, including partial payloads and non-minimal pushes.
  2. Implement foreign INIT removal, keyed on payload byte 6 and the configured txid.
  3. Implement strict parsing: complete prefix, length bounds, declared length equal to present length, no trailing bytes, minimal push, exact per-opcode length.
  4. Implement all five payload grammars, with every fixed field, reserved byte, and defined-value set enforced.
  5. Confirm all five published marker scripts parse to their published operation, payload size, and script size.

Stage 4: transactions

  1. Implement P2WPKH and carrier witness shape checks, including the leading empty element and signature order.
  2. Implement key validation: on-curve, distinct, sorted, HASH160-bound to the correct role.
  3. Implement signature verification with strict DER, low-S, SIGHASH_ALL, SegWit v0 hashing, and the exact prevout amount.
  4. Implement each operation template exactly, with exact counts, roles, and sequences.
  5. Implement checked fee arithmetic that cannot wrap, then the exact splits including the ceiling and floor tie-break.
  6. Implement confirmation provenance as a strictly-earlier-block test.
  7. Implement REFUND recognition, including the exact sequence value and consensus maturity.

Stage 5: classification and state

  1. Implement the top-level dispatch in its exact step order.
  2. Implement single-marker validation in ascending reason-code order, returning the lowest failing code, and deferring state-dependent checks that cannot be made.
  3. Implement the state machine and every state delta, including terminal transitions.
  4. Implement the three counters as post-block values.
  5. Confirm all 31 published validation cases produce the published reason, class, and event type.

Stage 6: roots

  1. Implement the event leaf preimage. Confirm each published preimage hashes to its published leaf, and confirm its length is 371 bytes, not 374.
  2. Implement the object-state leaf preimage. Confirm the published preimages and the 204-byte length.
  3. Implement both Merkle trees with odd-leaf duplication and the single-leaf shortcut. Confirm every published intermediate level.
  4. Implement the empty-set roots for both trees.
  5. Implement the chained root, and confirm it for the published block including its counters.
  6. Emit a root for every block from the INIT confirmation block onward, including blocks with no events.

Stage 7: chain handling

  1. Implement block connection as an atomic unit: events, deltas, both roots, counters, chained root.
  2. Implement block disconnection as an exact reversal, completing before any replacement branch is applied.
  3. Confirm that a disconnect and reconnect of the same block returns you to an identical chained root.
  4. Keep mempool observations in storage with no path into state, counters, or roots.

Stage 8: publishing your view

  1. Emit agreement tuples matching the published schema, with counters and heights as decimal strings.
  2. Normalize the tuple with RFC 8785 JCS and sign only the tuple.
  3. Record your own release provenance per height, and do not rewrite historical provenance on a later release.
  4. Compare only the nine semantic fields against another pipeline, never the four release fields.
  5. Fail closed on disagreement, on any missing dependency, and on a stale tip.

Where implementations go wrong

Each of these is a real hazard that the rules single out, and each produces silent divergence rather than an obvious error.

Common divergence causes
MistakeSymptom
Reversing a raw digest as though it were a txidNamespace and object keys differ from everyone else's, and nothing else works
Accepting a same-block prevoutOccasional extra valid events that another implementation rejects
Returning a true but not lowest reason codeVerdicts agree, event roots do not
Padding the event preimage to 374 bytesEvery event leaf differs, so every root differs from the first event onward
Skipping blocks with no Tandem eventsChained roots diverge permanently from the first skipped block
Giving the odd fee satoshi to side BValid transactions rejected, or invalid ones accepted, on odd fees only
Ignoring an invalid carrier spend instead of terminating the objectObjects that should be dead stay active, so object-state roots diverge
Emitting one event for a multiple-carrier spendEvent count and ordering differ, so the event root differs
Parsing agreement counters as numbers and re-serializingSignatures stop verifying at large values or on round trips
Letting a mempool sighting satisfy a predecessor requirementConstructed transactions fail confirmation provenance once mined
Sorting object leaves by display identifier rather than binary keyObject-state root differs whenever ordering differs between the two
Treating key_id as authenticatedAn unsigned envelope field is trusted to select trust

If you are building a product

Parser conformance is one concern. Shipping something to people who hold keys is another, and the second one has its own rules.

  • Label the network and the verification status wherever state is shown. Never present state from a height where authorized pipelines disagree.
  • Keep mainnet construction and broadcast unavailable. Mainnet is not active, and no repository, website, or funded address changes that.
  • Fail closed for state-changing actions during any indexer disagreement or unreadiness.
  • Complete, export, checksum, and restore-test every recovery transaction before its parent is broadcast. The exit is prepared before the move, not after.
  • Reconstruct and display inputs, outputs, amounts, scripts, fees, sequences, locktime, key order, and commitments before requesting a signature. Blind signing defeats the pairing property entirely.
  • Never request a seed phrase or a raw private key, and never accept one if offered.
  • Treat all retrieved content as untrusted. Enforce your own size and type limits, render safely, and never execute retrieved content as application code.
  • Explain permanence and correlation before a user commits personal, legal, location, or relationship data to a public chain.
There is no marketplace to integrate with.

The Bitcoin Universe capability snapshot lists 38 protocols, 29 of them with a marketplace entry. Tandem has no entry at all, so no Universe surface implements a buy, sell, list, or transfer action for a Tandem object. If your product needs a trade path, Tandem does not provide one and this repository does not describe one.