Vestige protocol · co-signature lab

Two keys, one recent block, proof on-chain.

A signer signs a statement about the chain's latest block. A passkey co-signs it. Vestige.sol checks both P-256 signatures against the chain's own block hash and records the encounter for anyone to verify.

Init Initializing…
In this lab
  • Real passkeys (WebAuthn)
  • Real contract on a local node
  • Native P-256 verification
  • Record rebuilt from chain events

01 · 02 / The ceremony

Co-sign a block

Beacon: A is an unattended device key that re-signs block head − 1 every block, like a door reader or an IoT device. Handshake: A is a person whose passkey signs once. Either way A declares a window, maxAge blocks, inside what it signs, and B must co-sign within it. The contract sees a signer, a window and a cosigner.

A signs every block without a prompt.

Passkeys on this device

None enrolled
signer · beacon device key

Beacon

Non-extractable WebCrypto P-256 key in IndexedDB. Signs sha256(abi.encode(tag, chainId, vestige, n, blockhash, maxAge)) every block.

blocks · signed by A, enforced by the contract
Signer
—
Format
—
Anchor
—
Window
—
Block hash
—
Digest
—
Signature
—
cosigner · webauthn passkey

Cosigner

The passkey signs keccak256(COSIGN_TAG, digest, signerKey), binding itself to A's exact statement.

Not recorded Idle
No statement yet
Enroll a passkey, then co-sign.
Evidence payload
None

03 · 04 / Contract

Try to break it

Each attack submits a variant of the current or last accepted evidence. The contract rejects it, and its custom error is logged here.

vestige.sol · local node

Contract

RPC
—
Chain
—
Vestige
—
Head
Policy
—
Relayer
—
Source
Read the verified source ↓
rejected attempts · this page only

Rejected

Reverts are not events, so this log lives in the page. Accepted co-signatures are read back from the chain below.

0 events recorded

The JSON log covers what the node never sees: passkey prompts and cancellations, clientDataJSON and authenticator flags, evidence and decoded errors. Match it to the node log by block number or tx hash. Public data only.

attempt → custom error
  • None yet.

05 / Public record

On the record

Every Cosigned event, read from the contract's logs, not this browser's storage. Any client with the RPC can rebuild this table and check each co-signature's anchor gap.

IncludedAnchorAge / windowModeSignerCosignercosignIdTx

06 / Source

Read the contract

The exact files compiled into the deployed bytecode, checked by this page against the code at the contract's address: bytecode, compiler metadata, and every source file's hash.

Deployed code ↔ source

Checking
  • Loading the source bundle…

What this proves: the code at the address is byte-for-byte the compiler output shipped with this page (no constructor arguments or immutables, so the same build is the same code on every chain), and that output's embedded metadata hash commits to these exact files. What it does not: that the compiler turned these files into that output. For that, recompile with the settings above and compare.

—
—