Test vectors
Committed test vectors
These files are normative. An implementation that disagrees with any of them is not interoperable. They live in test-vectors/v1/ and are dedicated under CC0 1.0 so anyone can reuse them.
Marker vectors
File: test-vectors/v1/marker-vectors.json. One accepted encoding and three rejected ones, each pinned to the error code a conforming decoder must produce.
Valid
| Name | Script | Decodes to |
|---|---|---|
| signet-three-participant | 6a285749544301020103ad2608134839e732280cb93bdd5b8682626dce5748a65c437a39cdcb680c2a82 | Signet, version 1, CIRCLE, 3 participants, context hash ad260813…680c2a82 |
Invalid
| Name | What is wrong | Required error |
|---|---|---|
| pushdata1-is-ambiguous | Uses 6a4c28, a PUSHDATA1 push of the same 40 bytes. The payload is identical, the encoding is not minimal. | AMBIGUOUS_ENCODING |
| reserved-refuel-opcode | Operation byte 0x02. A future or reserved operation must be rejected, never guessed. | INVALID_OPCODE |
| zero-context-hash | Thirty-two zero bytes where the context hash belongs. | CONTEXT_HASH_ZERO |
The first case is the one that separates a careful parser from a lax one. Both encodings push the same 40 bytes, so a decoder that reads the payload without checking how it was pushed will accept a second valid encoding of the same Circle, and two implementations will then disagree about which transactions exist.
Golden circle vector
File: test-vectors/v1/golden-circle.json. A complete, fully signed three participant Signet transaction with every derived value committed.
| Committed field | Value |
|---|---|
| network | signet, currentBlockHeight 200 |
| contextHash | ad2608134839e732280cb93bdd5b8682626dce5748a65c437a39cdcb680c2a82 |
| markerScript | 6a285749544301020103ad2608134839e732280cb93bdd5b8682626dce5748a65c437a39cdcb680c2a82 |
| txid | 3703d5b332ebf2871a0a24066f7ea4b84dd3e9ebca1b1a879140e844c64b0f65 |
| wtxid | 772b6d1d179e6f5ba1c4699486a754ef7681b6299ee0e023fc2a5dd0c11245ab |
| feeSats | 3630 |
| virtualBytes | 363 |
| expectedLineageIds | 4bc0f5c804bffee98f9d5239c11d6b9ed7473af856c6f9709763cb44276f5617 63c22eae014513dbabfffe84db6131635ce44e066156be0a396b9db4f2dc18b7 ee745631e7bea77a35e38ed050e495c0a5eafca41cef5dd59ce7243b5aceacdb |
| stateTransition.expectedStateHash | 07b97f0c2cbaa172e66a2137fefbee64c5a05f03e03967d46936cd14070523f1 |
An implementation must reproduce every one of those from the raw transaction and the three listed prevouts alone. The vector also carries the RFC 8785 serialization of the context manifest as a string, so a JCS implementation can be checked without a Bitcoin transaction at all.
The fixture private keys behind these signatures are small public test constants used only to make the signatures deterministic. They must never receive real funds on any network.
State lifecycle vector
File: test-vectors/v1/state-lifecycle.json. Three confirmed transitions and the three rollback roots, which together pin the entire state machine including reorganization behaviour.
| Step | Event | Effect on state | Expected state hash |
|---|---|---|---|
| 0 | Empty index | revision 0, nothing recorded | 90e749b7720fac379610d979e29998c7d650150548622f0a47d9d3e181f1be52 |
| 1 | Genesis Circle at height 200, tx index 4 | revision 1, three lineages created, three shards, no edges | 07b97f0c2cbaa172e66a2137fefbee64c5a05f03e03967d46936cd14070523f1 |
| 2 | Continuation Circle at height 201, tx index 1 | revision 2, two lineages advance to circleCount 2, two continuation edges, two new shards | b29662d78f73f3f8940b2dccaf935dc2a7f1ceba21ef6b1c5b11a7d7f3f5a6fc |
| 3 | Ordinary spend of f7c7…28ef:1 at height 202 | revision 3, one lineage closed, its shard marked spent | faf7f730b9b48b39c4509dc3ccb23c94cac6979d334a57fbd1eda20dab7af84c |
Rolling the three transitions back in reverse order must produce exactly:
b29662d78f73f3f8940b2dccaf935dc2a7f1ceba21ef6b1c5b11a7d7f3f5a6fc07b97f0c2cbaa172e66a2137fefbee64c5a05f03e03967d46936cd14070523f190e749b7720fac379610d979e29998c7d650150548622f0a47d9d3e181f1be52
Note that the third rollback root is the empty-state hash, so a correct implementation returns to a byte-identical empty index rather than to a nearly empty one.
Replay all three transitions in your browser
Running the vectors
Against the reference implementation, from a clone of the repository:
npm ci
npm run build
node dist/cli.js vectors verify # golden transaction and state lifecycle
npm run verify # lint, types, tests, build, content and vectors
Against your own implementation, follow the differential procedure on the conformance page. This site also ships a browser reimplementation of the parser, validator and state engine, and the simulator replays every vector on the page so you can see each expected value being reproduced.
Fixture policy
- Adding or changing a normative rule requires a vector that fails before the change and passes after it, plus an inverse invalid case where one applies.
- Vectors are versioned by directory (
v1). A new protocol version gets a new directory, and existing vectors are never edited to match new behaviour. - Error strings may differ between implementations. The published error codes and the valid or invalid verdict may not.
- Every vector is validated against its JSON Schema in this repository's own test suite, so a malformed vector cannot be committed.