OpNS
Low-difficulty proof-of-work name service for Bitcoin SV
Overview
OpNS is a name service for Bitcoin SV. Names are claimed permissionlessly by low-difficulty proof of work — enough cost to deter spam, not a serious mining race — with no registrar, no auction, and no renewal. Each name can exist exactly once. A claimed name is an ordinary 1Sat ordinal inscription, so holding, transferring, and selling a name works like any other ordinal.
Uniqueness is enforced on-chain by a stateful covenant. Contract UTXOs form a trie — the mine tree — where each live UTXO represents a name prefix. Spending a node extends its prefix by one character, and the spend is only valid with a proof-of-work solution. Every spend emits the newly formed name as an inscription.
Protocol Constants
Genesis outpoint
58b7558ea379f24266c7e2f5fe321992ad9a724fd7a87423ba412677179ccb25_0
Difficulty
22 bits
Character set
a-z, 0-9, -
Content type
application/op-ns
Protocol marker
1opNSUJVbBc2Vf8LFNSoywGGK4jMcGVrC
The genesis output (block 806214) holds the root contract instance — the empty prefix from which all names descend. Difficulty and an optional TLD suffix were fixed at deployment; the mainnet deployment uses 22 bits and no TLD. The original contract source is at github.com/shruggr/opns for reference and for validating the deployed bytecode.
The Mine Tree
Each node in the tree carries four state variables:
genesis
36 bytes
Outpoint of the deployment output (txid + little-endian vout). Identifies the lineage
claimed
variable
Little-endian bitmask; bit n set means the character with ASCII code n has been claimed from this node
domain
variable
The name prefix this node represents
pow
32 bytes
The previous proof-of-work solution hash; seed for the next solution
A freshly spawned node has claimed = 0x00 and domain equal to its full prefix. The root node's domain is the empty string.
The Mint Operation
Nodes are not owned. The contract has a single public method, mint, with no signature check — anyone who produces a valid proof of work may spend a node. The contract enforces everything:
Character validation. The character must be in the allowed set (a-z, 0-9, -), and its bit must not already be set in claimed. Each character can be claimed from a given node exactly once — and since every name is exactly one path through the tree, each name can only ever be minted once.
Proof of work. The solution is a nonce such that:
has its top 22 bits zero when the hash is read byte-reversed (leading zero bits of that view) — about 4.2 million attempts (2²²) on average. pow is the spent node's 32-byte seed, char the single character byte, nonce miner-chosen. The winning hash becomes the pow seed of both resulting nodes, so solutions chain: future work cannot be precomputed.
Output structure. The contract verifies hashOutputs against exactly this layout (extending prefix app with l):
Output 0 keeps the prefix alive so its remaining characters stay minable. Output 1 opens the next level of the tree. Output 2 is the name itself.
The unlocking script pushes five values: the character, the nonce, the owner locking script for output 2, the concatenated raw bytes of any outputs past index 2, and the sighash preimage (SIGHASH_ALL | ANYONECANPAY | FORKID), which the contract uses for output introspection.
Mining races. Every spend consumes the node and recreates it at a new outpoint with a new seed. Two miners working from the same node — even on different characters — are racing for one UTXO: only one spend confirms, and the loser's solution is worthless because the seed changed. Mining from any given node is inherently serialized.
Name Inscriptions
Output 2 is a standard 1Sat ordinal inscription, built by the contract:
The content type is application/op-ns and the content is the full name. The OP_RETURN carries the protocol marker and the genesis outpoint so indexers can recognize a claimed OpNS name and its lineage without decoding the mine tree — though the claim still requires verification (see Validation Rules).
Every character mint emits an inscription: mining appl when only ap existed also mints app along the way. Each intermediate name goes to whatever lock the miner supplied for that step.
Ownership and Transfer
The contract's involvement ends when the inscription is created. The name ordinal is an ordinary spendable output: transfers, sales (e.g. Ordinal Lock), and custom locking scripts all work exactly as for any other 1Sat ordinal. The current owner of a name is the current holder of its ordinal, resolved by standard ordinal tracking from the name's origin. Names never expire.
Identity Binding
By application convention, a name can be bound to an identity key and used as a paymail handle. This is not part of the contract protocol — the holder re-locks the name ordinal with a signed PushDrop script carrying the identity key. See Payments.
Validation Rules
Mints are valid by construction. The script enforces proof of work, the character set, the claimed bitmask, and the exact output structure. An invalid mint cannot be confirmed, so any observed spend of a genuine node is a valid mint.
Lineage must be verified. Anything in a script can be forged — a fake node or an inscription carrying the genesis outpoint in its OP_RETURN proves nothing by itself. A name is genuine only if its mint traces back through node spends to the genesis outpoint. Indexers must follow the tree from genesis rather than pattern-match scripts.
Names are unique. Each character is claimable once per node, each name is one path through the tree, so a genuine name has exactly one origin.
Transfers need no OpNS validation. Once minted, a name ordinal follows ordinary ordinal rules; only the mint itself is protocol-governed.
Resolution
An OpNS indexer starts at the genesis outpoint and follows spends of node outputs (outputs 0 and 1 of each mint), producing two kinds of records:
Prefix nodes — the live UTXO for each prefix, where mining continues
Name origins — the inscription outpoint where each name was minted
Availability follows from the tree: a name is taken if a node with that exact domain exists (it was spawned when the name was minted). If not, the longest mined prefix is the node to mine from — the remaining characters each take one mint transaction.
The hosted overlay at api.1sat.app exposes this index:
GET /1sat/opns/origin/:name
The origin outpoint of a claimed name
GET /1sat/opns/mine/:name
Nothing if the name is taken; otherwise the longest mined prefix and its live node outpoint
POST /1sat/opns/origins
For a JSON array of outpoints, which are genuine OpNS origins
Ownership and metadata lookups from an origin use standard ordinal resolution; content and accumulated MAP are available through OrdFS.
Mining a Name
Mining ab from an empty tree takes two transactions.
1. Mine a from the root
The miner found a nonce where hash256(S0 ‖ 'a' ‖ nonce) meets difficulty (22 leading zero bits of the byte-reversed hash); that hash is S1.
2. Mine b from node a
The names a and ab now exist, each as a 1-sat ordinal. The root can still mint b through z, node a can still mint every character except b, and node ab is open for a third character. No transaction can ever mint a or ab again.
Summary
OpNS names are mined, not registered. A covenant trie makes each name mintable exactly once, proof of work is the only cost of claiming one, and the result is a plain 1Sat ordinal that transfers and trades like any other. The contract enforces the entire mint; indexers only need to follow the tree from genesis to know every name, its origin, and what remains available.
Reference implementations
TypeScript template —
@1sat/templatesOpNS(lock,decode,unlock,buildInscription,claimBit,testSolution)Go template / overlay —
1sat-stackpkg/template/opnsandpkg/opns(mine-tree index and HTTP API above)
Identity binding and paymail are application conventions; see Payments. The wider network around names: Introduction.
Last updated