Cross-check

draft-fassbender-scitt-time-anchor, revisions -03 and -06. Bitcoin-Anchored Temporal Proof for Transparency Services

What this is

One artifact, anchored by the independent producer-side implementation of -03 published on this site, and verified by a second verifier written independently by someone else: the clean-room verifier for -06 published by EMILIA Protocol, used unmodified at commit 6ea9afb. The producer and the verifier were written by different people, from different revisions of the published document, with no shared code. Both revisions pin the same OpenTimestamps release, python-opentimestamps v0.4.5, for the proof format.

Not commissioned. This implementer proposed the cross-check to the document's author when she told him of the second implementation. She introduced the two implementers by email, asked that nothing be routed through her, and took no part in the runs; from there it was arranged directly between them. The runs EMILIA Protocol performed on its own side are reported here as its author stated them in writing; the runs performed on this side are marked as such.

The proposal was for each verifier to check an artifact produced by the other. Only one direction was possible: the EMILIA release is a verifier and produces no proofs, so this cross-check runs from the -03 producer to the -06 verifier.

Result

The two implementations agree on the proof. It was produced by the -03 implementation, whose verifier returns valid on it. The EMILIA verifier replays each of its three Bitcoin branches to the digest reported by the producer side, and each of those digests is the Merkle root of the block at that branch's attested height. The artifact predates block 968588.

They differ only where the profile allows a verifier to differ: on whether it can place the attested block on the validated most-work chain. With a validated chain source the verifier returns valid; without one it returns unverifiable. Both outcomes were observed, and both are correct under the note on header sources in Section 3.1.

The vector

SHA-256 of the anchored artifact vector/cc1.txt d2d6506942e9e4784d0d0e67e8da7020aae847db2801985dda50e600f5403c6f
Content:
crosscheck emilia/donttrustverify 2026-09-25 vector 1, 53 bytes, no trailing newline.
Producer:
the -03 implementation on this site, whose manifest (SHA-256 9c55d358...) is anchored at block 960468.
Proof:
three Bitcoin branches, two attested at block 968588 and one at block 968635.
Block-height binding:
block 968588 (normative), the lowest verified height.
Reference Wall-Clock Projection:
2026-09-25T21:04:53Z (informative only).
Blinding:
the proof first appends a 16-byte nonce to the artifact digest and hashes the result, so the calendars received ddff22a7068212ae550ed9c1e2aca2aa0233965f6aec54f5d05ebdae9dde9183, not the artifact digest.

Runs

VerifierChain sourceRun byOutcome
EMILIA -06 verifier, 6ea9afbnone validatedEMILIA Protocolunverifiable at step 7 (-06 numbering); all three branches replay to the expected digests
-03 verifier on this site, verify_run.pythis implementer's own full nodethis implementervalid at 968588, 144 confirmations
EMILIA -06 verifier, 6ea9afb, through this implementer's adapterthis implementer's own full nodethis implementervalid at 968588, 154 confirmations; all three branches verified
EMILIA -06 verifier, 6ea9afbnonethis implementerunverifiable

On its side, EMILIA Protocol checked the two block headers against public sources and recomputed their hashes and proof of work. That is not placing them on a validated chain, so its verifier correctly returned unverifiable. On the pending proof, which carries calendar attestations only, it also returned unverifiable, as it should. It independently fetched the producer's published manifest and its proof: the manifest hashes to 9c55d358..., all 16 files match it, and the proof replays to block 960468.

The third run, the EMILIA verifier returning valid through this implementer's node, is this implementer's run. It has not been reproduced by EMILIA Protocol, which has no independently validated chain source. Anyone who operates a full node can repeat it with the commands below.

The confirmation counts differ between runs because they were taken at different chain tips.

Reorganisation handling

The verifier asks its header source two questions at different times: the header at a height, then the confirmation depth at the selected height. The adapter written for this cross-check, node_header_source.py, answers both only from the node's active chain, and answers the depth only if that chain still carries the same block at that height both before and after the depth is read. Otherwise it answers nothing, and the verifier returns unverifiable.

A test against a simulated node, test_reorg.py, replaces the block at the attested height at two points: between the header read and the depth read, and after the depth value is read but before the re-check. Both return unverifiable; without a change the run returns valid. The same test against a copy of the adapter with the re-check removed fails the second case, which shows the re-check is necessary. EMILIA Protocol reproduced the test on its side, at commit 0eb4238 of the mirror and with its verifier at 6ea9afb, with the same three results.

The simulated headers carry the real Merkle roots and nTime values of the two blocks but no proof of work. The test is about how the adapter behaves when the chain changes, not about the chain.

What this establishes, and what it does not

Established by the chain: the artifact predates block 968588, and the producer's published manifest predates block 960468. These are block-height bindings, and they are the only strong claims here.

Not established: the time at which the producer recorded the pending proof, 2026-09-25T19:55:58Z. That is the producer's own record, not a cryptographic bound. The nTime of block 968588 is informative and is shown only alongside the height. The node-backed valid of the EMILIA verifier is this implementer's run. Nothing here says either implementation is correct beyond this vector.

Two statements made by this implementer during the exchange were corrected in writing. The pending proof was first offered as making the ordering checkable; it does not, since only the block-height binding is cryptographic. And the artifact was at one point bounded by the block's nTime rather than by its height.

Files

The files below are the mirror at commit ad31c27, served here unchanged. SHA256SUMS lists paths relative to this directory, including the subdirectories vector/, evidence/ and anchors/. Fetch the set with the same layout, or clone the mirror, and run sha256sum -c SHA256SUMS.

One correction to the mirror, recorded here rather than made there. Its README says a joint description of the cross-check would be published separately. There is none: each party describes the cross-check in its own words, and this page is this implementer's. The README is left as committed, because the manifest that covers it is anchored and is the state EMILIA Protocol verified.

How to re-verify

Requires Python 3.11 or later. From this directory or a clone of the mirror, with the EMILIA verifier at 6ea9afb cloned alongside as emilia-verifier and the -03 package as producer-03:

sha256sum -c SHA256SUMS
PYTHONPATH=../emilia-verifier/src:. python3 test_reorg.py vector/cc1.txt vector/cc1.txt.anchored.ots

The node-backed run also requires a Bitcoin full node you operate, with RPC credentials in ~/.bitcoin/bitcoin.conf:

PYTHONPATH=../emilia-verifier/src:.:../producer-03 python3 run_emilia.py vector/cc1.txt vector/cc1.txt.anchored.ots

The full sequence, including the mutant check, is in README.md. A verifier that cannot place the attested block on the validated most-work chain returns unverifiable, not valid; a public block explorer is not sufficient for valid.

Source

Produced by Tiago Pinto, Portugal, September 2026. The adapter, runner and test are MIT-licensed. The EMILIA verifier is EMILIA Protocol's, MIT-licensed separately, and is not included here. This page is served from the author's own server, in static HTML, without JavaScript, without analytics, without cookies, without external dependencies.