Where is the trust?
The trust root is a 7-key notary federation. Each notary independently fetches a CEX price over TLS and signs (serverName, sourceId, price, timestamp, cycleSeq) with their Schnorr key. The Oracle covenant trusts these signatures and nothing else off-chain.
Publishers are interchangeable relays. They request a notary signature, pay tx fees, broadcast. They have no special role and cannot fake notary sigs. Anyone with chipnet funds can run one.
Sources are operator-diverse. 13 endpoints: 7 USD-quoted spot markets (Kraken, Coinbase, Gemini, Binance.US, Bitstamp, Crypto.com, Bitfinex, EXMO, Independent Reserve — 4 US, 5 non-US), 2 USDC (OKX, KuCoin), 2 USDT (Bybit, HTX). No two share an operator family; no quote-currency dominates. A position-checked median absorbs ≤6 outliers without bias — both stablecoin clusters could depeg the same direction simultaneously and the median still lands in the 7-USD cluster.
The covenant is the only on-chain rule. It enforces: ≥7 distinct publishers attest per cycle (the quorum ratchets up with active committee at ~50%), notary-attested time is strictly forward, the median is position-checked, the threshold-ratchet bleeds 10%/cycle so a single spike doesn't lock the system. Distinct-pubkeyHash160 across VA inputs is the load-bearing anti-Sybil check.
No admin keys. No upgrade path. The Oracle UTXO chain is self-perpetuating; the only way to update behavior is to deploy a new covenant at a new address.
What the federation can do if a majority (≥ 4 of 7) of notaries collude: fast-forward time within a 7200-second-per-cycle stride cap, sign attestations for arbitrary prices. With 7 keys held by independent operators, the collusion cost is comparable to Wormhole-class bridges (~$1M+ bribery floor). What the federation cannot do: rewind time, skip the quorum check, hide a cycle from observers, run faster than ~1 cycle/minute (notary throughput cap).
How to consume the price NFT
Each cycle mints 4 Ticker NFTs at the address shown in §3. They are mutable (capability 0x01), anyone-can-spend, and self-replicate via the Ticker covenant. A consumer's tx that spends a Ticker becomes a chain-descendant of the Oracle.update that produced it — BCH consensus refuses to confirm the consumer's tx in any chain that excludes the Oracle.update. That is co-finality, atomic by construction.
Minimal tx shape:
input[0] — your consumer contract
input[1] — Ticker NFT from the pinned Oracle category
output[0] — your business logic (payment, mint, settle…)
output[1] — identical Ticker re-emit (Ticker covenant enforces this, mutable cap, same commit)
output[2] — optional change
Read price and lastTs from tx.inputs[1].nftCommitment. The 17-byte layout is 0x80 | seq(4) | lastTs(4) | medianPrice(8). Use medianPrice / 10⁸ for USD. Pin the Oracle category as a constructor arg (LE-reversed) so an attacker can't feed you a Ticker from a different oracle.
A working reference covenant (PriceGatedRelease — locks BCH, releases on price ≥ strike) lives at contracts/v11/examples/ in the source tree, ~286 bytes compiled. Drop your own freshness gate on lastTs (avoid tx.locktime; that introduces a chain-MTP lag the design was built to escape).
Run a notary or publisher
Notary: a stateless HTTP daemon that holds one Schnorr key from the OR-list. Exposes POST /sign; on each request fetches the current price from its assigned CEX, signs (serverName, sourceId, price, ts, cycleSeq), returns the signature. The federation's seven keys live independently — separate hosts, separate operators. Add an 8th notary by deploying a new Gateway covenant with the extended OR-list.
Publisher: a daemon that polls the Oracle UTXO, requests notary signatures for its assigned source, mints a VerifiedAttestation NFT via the Gateway, waits ~25 s for peer VAs from other publishers, then builds and broadcasts the Oracle.update tx consuming all VAs. First publisher to broadcast wins the cycle; losers retry on the new tip. A publisher needs ~12 k sats per cycle (VA mint + Oracle.update share of fee + Ticker dust).
Unified binary: scripts/ticker-node.ts wraps both daemons. Run as ticker-node --notary --slot 0, ticker-node --publisher --slot 0, or both flags together. Federation operators bundle both for their slot (no HTTP roundtrip for own attestations); community operators run publisher-only.
No registration. No allowlist. Run as many publishers as you can fund — they compete to land the cycle, but they all contribute their attestation toward the median.