Contracts

JSON Schemas

Seven schemas, all JSON Schema 2020-12, all published in schemas/v1/ and declared in this repository's docs.manifest.json. Every one sets additionalProperties: false, so an unknown field is an error rather than a silent extension.

Context manifest

schemas/v1/context-manifest.schema.json

The optional JSON object whose RFC 8785 serialization is hashed into the marker. Structural rules only; the reference validator adds the semantic rules in section 5.

Required: protocol, version, kind, nonce, title, created, expires

  • protocol is the constant witc, version the constant 1, kind the constant circle.
  • nonce is 16 bytes of lowercase hex; alias keys are 32 bytes of lowercase hex and must be unique.
  • Optional fields: orbit, host, media, description, renderer, aliases (at most 16).
  • additionalProperties is false: unknown fields are rejected, which keeps the hash preimage well defined.
  • String length limits count Unicode code points, and every string pattern forbids leading or trailing whitespace.

Decoded marker

schemas/v1/marker.schema.json

The shape of a decoded marker, for interchange between tools that do not share a language.

Required: magic, version, network, networkId, opcode, participantCount, contextHash

  • magic is the constant WITC; opcode is the constant 1.
  • networkId is an integer 0 to 3, matching network in the enum mainnet, testnet3, signet, regtest.
  • participantCount is 2 to 16.
  • contextHash uses the pattern ^(?!0{64})[0-9a-f]{64}$, so an all-zero hash cannot validate.

Validation prevouts

schemas/v1/prevouts.schema.json

The confirmed previous outputs a validator needs. Without these a Circle cannot be checked, because values, scripts and heights are not in the transaction.

Required: txid, vout, valueSats, scriptPubKey, blockHeight for each of 2 to 16 items

  • scriptPubKey must match ^5120[0-9a-fA-F]{64}$, so only native P2TR is expressible.
  • valueSats is a decimal string, not a JSON number, so no implementation loses precision above 2^53.
  • vout is an integer 0 to 4294967295.

Plan request

schemas/v1/plan-request.schema.json

Input to the reference planner: what a coordinator submits to produce a frozen unsigned transaction.

Required: network, manifest, participants, feeRateSatsPerVbyte

  • network is restricted to the enum signet and regtest. The schema itself makes mainnet planning unexpressible.
  • Each participant carries a maximumFeeShareSats cap, which the planner enforces with FEE_CAP_EXCEEDED.
  • feeRateSatsPerVbyte is a positive decimal string; the planner additionally bounds it at 1,000,000.

State snapshot

schemas/v1/state-snapshot.schema.json

The exact object that is hashed to produce the authoritative state hash. This is the interoperability contract between independent indexers.

Required: protocol, version, revision, lineages, shards, circles, edges

  • Four collections: lineages, shards, circles (each with members), and continuation edges.
  • Outpoints are strings of the form txid:vout with a pattern that bounds vout at 4294967295 rather than allowing any digits.
  • Satoshi amounts are decimal strings bounded at 2100000000000000, so MAX_MONEY is enforced by the schema.
  • Integers are bounded at 9007199254740991, the ECMAScript safe integer limit.
  • additionalProperties is false at every level, so no implementation-specific database field can enter the hash preimage.

Golden transaction vector

schemas/v1/golden-circle.schema.json

The shape of the golden vector file, so the fixture itself is validated in CI and cannot drift into an unparseable form.

Required: 16 fields including rawTransaction, txid, wtxid, feeSats, virtualBytes, prevouts, expectedLineageIds, stateTransition

  • markerScript is constrained to ^6a28[0-9a-f]{80}$, which encodes the exact 42 byte marker shape.
  • manifest references the context manifest schema, and prevouts references the prevouts schema.
  • expectedLineageIds holds 2 to 16 lowercase hex hashes.

State lifecycle vector

schemas/v1/state-lifecycle.schema.json

The shape of the lifecycle fixture: genesis reference, continuation circle, ordinary-spend closure, and exactly three rollback roots.

Required: schemaVersion, name, genesis, continuation, closure, rollbackExpectedStateHashes

  • genesis.source is the constant golden-circle.json, binding the two fixtures together.
  • rollbackExpectedStateHashes has minItems and maxItems of 3, matching the three applied transitions.
  • Local $defs define the 64 character hash and the outpoint object reused across the file.

Identifiers and versioning

Each schema declares an $id under https://schemas.bitcoinuniverse.dev/witc/v1/. Those identifiers are stable names used for $ref resolution between the files; resolve them from the repository copies rather than expecting them to be dereferenceable.

Schemas are versioned by directory. A future protocol version gets schemas/v2/; the v1 files are never edited to describe new behaviour, because the published vectors and the deployed indexers depend on them meaning exactly what they meant when they were committed.

Structural validation is necessary but not sufficient. The context manifest in particular carries semantic rules the schema cannot express: real UTC calendar timestamps, expires later than created, well-formed Unicode without unpaired surrogates, and strings unchanged by the ECMAScript trim operation. Those live in src/manifest.ts and are described in section 5.