OpenTimestamps timestamping
Every block is anchored in the Bitcoin blockchain through OpenTimestamps: proof, independent of the platform, that its exact bytes existed no later than a given date.
The blockchain is the over-protocol that makes the integrity and immutability of the public register checkable by anyone; OpenTimestamps anchoring is the part of it that proves when each block existed. It requires no trust in the platform or its keys: the .ots file is verified against the block with standard OpenTimestamps tooling.
Protocol v1
A date the platform cannot back-date.
The platform’s signature proves that a block comes from it; it does not prove that history was not rewritten. An external anchor, out of reach of its keys, closes part of that gap.
- A signature is not immutability. The platform holds its signing key: it could re-sign a rewritten chain, and every block of it would still verify.
- A signature’s date is a claim. signed_at is the creation time the signer writes into the signature itself: a leaked key can back-date a signature within its validity window.
- A Bitcoin block cannot be back-dated. A Bitcoin attestation is not a claim by the platform: it proves the block’s exact bytes existed no later than the attested Bitcoin block, independently of the platform’s keys. It thereby bounds the back-dating window of a leaked key.
- Backing for independent copies. Immutability rests in practice on the copies anyone can keep of the published blocks. The anchor adds third-party proof of existence: a rewritten history cannot obtain back-dated attestations.
The SHA-256 of the file, as published.
Every block, whatever its type (configuration, rings, votes, closure), gets its own proof. It is submitted to the OpenTimestamps calendars when it is sealed, right after its anchor row is committed to the database. The commitment covers the published file itself: the proof is verified against the downloaded block, and nothing else.
-
sha256({n}.json)SHA-256 · commitment - The plain SHA-256 of the block file’s bytes: the exact bytes that are stored, served, hashed and signed.
-
noncenone - Deliberately submitted without OpenTimestamps’ usual privacy nonce, since the bytes are public by design: the calendar commitment equals sha256({n}.json), and any standard OpenTimestamps tooling verifies the proof with no trust in the platform.
-
SHA3-512chaining digest - Not to be confused: a block’s digest in the chain (content_hash, the next block’s previous_hash) remains the file’s SHA3-512. The SHA-256 is only the OpenTimestamps commitment.
From pending to completed.
An OpenTimestamps proof completes in two stages: the calendars commit at once, Bitcoin confirms later, typically within a few hours. The proof’s status is the only mutable piece of data of a block, and it changes once, in one direction.
-
1
Submission at sealing.
The platform submits the commitment to the public OpenTimestamps calendar servers and stores the returned proof next to the block. Submission is best-effort: a calendar outage never delays or fails the block’s publication, and its .ots file is then missing until the next reconciliation.
-
2
pending: the calendars have committed.
The proof carries the calendar commitments, not yet a Bitcoin attestation. It is already downloadable, but does not yet prove any date in Bitcoin.
-
3
An hourly reconciliation.
Every hour, each block still pending is picked up. A missing proof is resubmitted from the stored bytes: the anchoring then starts from that new submission. For a block published more than 4 hours ago, the typical Bitcoin confirmation latency, the calendars are polled. That hourly cadence is the retry policy.
-
4
completed: Bitcoin has confirmed.
As soon as the calendars provide the Bitcoin attestation, the enriched proof replaces the stored .ots file and the block’s status flips to completed. It never goes back to pending.
A third file, next to the block and its signature.
The proof is served with the block {n}.json and its signature {n}.json.sig, whatever its state, and its status appears in the election’s manifest. These files exist as long as the election has a public register, from opening to archiving; a cancelled election withdraws them.
-
/elections/{election}/chain/{n}.json.otsPublic route - Redirects to the stored file. Served pending or completed alike: a pending proof already carries the calendar commitments.
-
{election}/{election}_{n}.json.otsStored file - Stored next to the block and named with the election id: a copy detached from its URL stays identifiable.
-
ots_url · ots_statusManifest - For each block, the manifest (/elections/{election}/chain) gives the proof’s direct URL and its status, pending or completed. The register page shows the same state on every .ots download: “awaiting Bitcoin anchoring” or “anchored in Bitcoin”.
-
pending → completedReplaced once - The .ots file is not frozen: the enriched proof replaces the pending one, so downloads and mirrors always get the most complete proof. The block itself never changes; in the database, the status is the only column the append-only block table lets change, and only in that direction.
-
{n}.json.otsAccess - .ots proofs, like the manifest and the block JSON, stay downloadable for every election, whatever the offer. Only the download of the .sig signatures is reserved for Official elections, and only in the interface.
ots verify, against the downloaded file.
The platform reports the proof’s state but performs no verification against the Bitcoin blockchain itself: that is the verifier’s job, with standard OpenTimestamps tooling. In the full verification procedure, this check is optional.
-
1
Fetch the block and its proof.
The file {n}.json and its proof {n}.json.ots, from the election’s public register or the manifest URLs. The status shown by the manifest is the platform’s statement; only the verification counts.
-
2
Verify the proof against the file.
ots verify -f {n}.json {n}.json.ots. Since the commitment is the file’s plain SHA-256, no platform data is involved: a file changed by a single byte no longer matches the proof.
-
3
Come back to a pending proof.
A pending proof does not point to a Bitcoin block yet. Since the stored file is replaced by the completed proof, downloading it again once the status has become completed is enough, usually a few hours after the block was published.
What it proves: A completed proof that verifies establishes that the block existed, byte for byte, no later than the attested Bitcoin block, independently of the platform’s keys.
The full verification procedure# each proof's status (ots_status), in the manifest
curl -s https://admin.stg.condorcet.vote/elections/{election}/chain
# block n and its proof (the routes redirect to the stored files)
curl -sL -o {n}.json https://admin.stg.condorcet.vote/elections/{election}/chain/{n}.json
curl -sL -o {n}.json.ots https://admin.stg.condorcet.vote/elections/{election}/chain/{n}.json.ots
# the commitment: the file's plain SHA-256
openssl dgst -sha256 {n}.json
# the proof against the file
ots verify -f {n}.json {n}.json.ots
What the anchoring does not prove.
The anchoring proves when bytes existed. It adds to the other checks; it does not replace them.
- An upper bound, not an exact date. A completed proof establishes that the block existed no later than the attested Bitcoin block. A proof still pending proves no date in Bitcoin at all.
- Not the correctness of the content. The anchoring covers bytes, whatever they are: the validity of the ballots, the participation bounds and the result is checked through the verification procedure.
- Not authenticity. The proof is independent of the platform’s keys, and therefore says nothing about who produced the block. That is the OpenPGP signature’s role, checked with the published verification keys.
- Not the uniqueness of history. A rewritten history cannot obtain back-dated attestations, but the anchoring alone does not prove that a given history is the only one published: independent copies remain the defence against rewriting.
- Not a qualified timestamp. An RFC 3161 timestamp from a timestamping authority, with eIDAS-grade probative value, remains a possible complement; it is not offered today.
See also
- Blockchain The over-protocol that seals the register: envelope, four block types, serialization, chaining, signature, timestamping.
- Platform keys The OpenPGP v6 certificates that sign the blocks, their rotation and their machine endpoint.
- Verification procedure Verifying an election end to end: from the register alone, or with the blockchain.