Files
orgchain/SPEC.md
T
teahubxyzandClaude Opus 5.5 6998ae47aa Orgchain v1.10: keyrings, each key signing in its own chain's standard
A new lineage/v0 op binds a node's keys in one inscription whose parent is the
node itself: its Taproot and SegWit addresses, its npub and its Ethereum
address. Every key signs the same statement the way its own wallets sign a
message: BIP-322 simple signatures for the Bitcoin addresses, a NIP-01 note
(kind 1, created_at 0) for the npub, EIP-191 for Ethereum. The reducer checks
every proof, binds a standing keyring's keys to its node, lets the newest
keyring replace the older, and retires keyrings at a graduation (the keys
change with the new root) and at a close.

Every account gets an Ethereum key at m/44'/60'/account'/0/0; an org's, at
account 0, is the key tree page's legal-control key and matches its published
vector. Keyring is the ninth verb; Inspect shows each node's keyring and the
statement its keys signed, and Reveal its Ethereum private key. The sample
publishes three keyrings, and lineage's retires when it graduates.

Tests pin BIP-322's published vectors and values cross-checked with
bip322-js, ethers and nostr-tools. The regtest rehearsal, rerun with five
keyrings, confirmed 89 transactions on Bitcoin Core; ord's 26 events fold to
the same trees and keyrings, every proof checked from ord's copy, and the
fixture is re-recorded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H4upF5LVwmPDDqrhdUfnXh
2026-10-15 10:48:28 -07:00

153 lines
10 KiB
Markdown

# lineage/v0
lineage/v0 is an ordinals metaprotocol for lineage holdings: LLCs, the orgs and agents they birth, the belts and
decisions on their record, and the items they make. Every event is an inscription. The chain orders the events and
proves who was allowed to make each one; the state (the trees) is stored nowhere, and every indexer that applies these
rules to the same inscriptions gets the same trees.
Status: test networks only (Orgchain's in-browser chain and Bitcoin Core regtest). The reference implementation is
`reduce()` in `src/orgchain/lineage.js`; `src/indexer/ord.js` and `bin/lineage-index.mjs` run it over a real ord index.
## 1. Inscriptions
lineage/v0 uses these fields of the ord envelope ([inscriptions](https://docs.ordinals.com/inscriptions.html)):
| tag | field | use |
| --- | --- | --- |
| 7 | metaprotocol | exactly `lineage/v0`; inscriptions without it are not lineage's |
| 5 | metadata | a CBOR map: `op` and its fields (section 4), strings except a keyring's `proof` map, in 520-byte pushes (Orgchain keeps it under 2048 bytes) |
| 3 | parent | the inscription id of the node that authorizes the event; exactly one, except for `found` |
| 1 | content type | `text/plain;charset=utf-8`; the body is a short label such as `birth time` (a keyring's is its statement), ignored by the rules |
| 2 | pointer | puts a child's inscription in its own output when the parent is spent first |
The body, delegate (tag 11) and properties (tag 17) carry no meaning here; properties may later carry display traits
such as a belt's colour, never authority. Unknown odd tags are ignored. Never use unknown even tags: ord treats such an
inscription as unbound, so it has no location.
A reveal is a script-path spend whose tapleaf commits to the envelope script's exact bytes (BIP-341). Orgchain's reveals
before v1.9 committed to a re-encoded script; real Bitcoin rejects those, and Orgchain's local chain still loads them.
## 2. Order
Events fold in chain order: block height, then transaction order in the block, then envelope order in the transaction.
ord's inscription numbers follow the same order. Unconfirmed events are provisional, and ord indexes none.
Within a block, the miner sets the order. Events that share an authority are chained, because each one spends that
authority's inscription, so their order is fixed. Independent events may land in any order, and outside the conflicts
in section 6 that changes nothing.
## 3. Nodes and authority
A node is created by an accepted `found` (a holding) or `birth` (an org or an agent), and its id is that event's
inscription id. Each node has a kind (holding, org or agent), a status (active or closed), and, below a holding, an
edge: derived (the parent holds the child's seed) or adopted (it graduated and holds its own root). A child's index
counts its parent's earlier children of the same kind, orgs and agents separately, and is never reused.
An event's parent is the node that authorizes it, and it counts only if the inscribing transaction spends that node's
inscription: ord records a parent only then ([provenance](https://docs.ordinals.com/inscriptions/provenance.html)).
Indexers use ord's recorded parents, never the raw tag. So acting for a node means holding its inscription, and moving
the inscription moves the authority.
## 4. Events
| op | parent | metadata | effect |
| --- | --- | --- | --- |
| `found` | none | `name` | a holding; no active holding may already have that name |
| `birth` | an active holding or org | `name`, `kind` (`org` or `agent`, default `org`) | a child; the parent may not already have an active child of that name |
| `award` | an active holding or org | `to`, `skill`, `belt` (`white`, `green` or `black`) | `to` (any other active node, in any holding) holds that belt in that skill, replacing its earlier belt in it |
| `decide` | an active node | `title` (required), `why` (optional) | a decision on the node's record |
| `make` | an active node | `name`, `note` (optional) | an item, made and first held by the node; a node makes one item per name |
| `keyring` | the node itself, active | `taproot`, `segwit`, `nostr`, `ethereum`, and `proof`: each key's signature | the node's keys are bound to it, replacing its earlier keyring (section 8) |
| `graduate` | the child's parent, active | `of` (an active org child, not yet adopted) | the edge becomes adopted, and the org becomes a holding of its own (section 5) |
| `close` | the node itself, active | none | the node closes, with every active derived descendant; adopted ones stay open |
Names (holdings, children, skills, items) are 1 to 40 lowercase letters, digits or hyphens, starting and ending with a
letter or digit, because they become domains. Text fields are trimmed, and only their first characters count: 140
for a title, 400 for a why, 280 for a note. Agents do not birth or award. An event that
breaks a rule is rejected: it stays on the chain and changes nothing. Any other `op` is rejected.
## 5. Holdings and graduation
A holding is a root: a `found`, or an org that graduated. When an org graduates, it and its descendants still in the
old holding re-root under it, and it joins the holdings. Its parent stays its parent, so where it came from stays on the
record, and its old holding's tree keeps a row for it. A graduation event belongs to both holdings. Its keys change with
its new root, and so do its derived descendants', so their keyrings retire (section 8).
In Orgchain a graduation is followed by a handoff: the org's fresh root claims its inscription, and the derived key that
held it countersigns. After that, only the new root can act for the org.
## 6. Order-sensitive conflicts
Where independent events conflict within one block, the block's order decides. These are the cases: a close and an act
by one of its derived descendants; an award and its recipient's close; two foundings with the same name; a keyring and
a graduation or close that retires it; two keyrings that list the same key. Orgchain keeps a keyring and the graduation
that would retire it a block apart.
## 7. Ownership, items and deals
Whoever controls the output that holds an inscription's sat holds that node or item; for indexers that is ord's
satpoint. Items move like any inscription. A deal is not an event: it is one transaction that carries the item and the
buyer's coins in, and the item to the buyer, the price to the holder and the buyer's change out. The buyer signs its
inputs first (SIGHASH_ALL) and the holder countersigns the item's. ord sees the item move, and nothing else needs
indexing.
## 8. Keys and keyrings
Indexers need no keys to fold the trees. Keys say where a node's inscription is expected to live, and who can sign for
it. Each holding has a 24-word root (BIP-39), and an org's seed is BIP-85 from its parent's (`m/83696968'/39'/0'/24'/i'`)
until it graduates. An org is account 0 of its seed and its agents are accounts 1 to n. Each account holds its
inscription at its BIP-86 Taproot address (`m/86'/coin'/account'/0/0`), keeps its money at BIP-84 SegWit, and has a
NIP-06 npub (`m/44'/1237'/account'/0/0`) and an Ethereum address (`m/44'/60'/account'/0/0`). An org's Ethereum key, at
account 0, is its legal-control key: the one that holds its entity NFT.
A `keyring` publishes a node's keys, so other chains and registries can find them without deriving anything. Its parent
is the node itself. Its metadata lists four keys, each written the way its chain writes it, and a proof from each:
| field | key | proof, in `proof` under the same name |
| --- | --- | --- |
| `taproot` | the Taproot address that holds the node's inscription, lowercase | a BIP-322 simple signature, base64 |
| `segwit` | its P2WPKH address, lowercase, on the same network | a BIP-322 simple signature, base64 |
| `nostr` | its npub | the BIP-340 signature, in hex, of the NIP-01 event `{pubkey, created_at: 0, kind: 1, tags: [], content: statement}` |
| `ethereum` | its address, in EIP-55 case | an EIP-191 `personal_sign` signature: `0x`, then r, s and v in hex |
Every proof signs the same statement, one line each:
```
lineage/v0 keyring
node: <the node's inscription id>
taproot: <address>
segwit: <address>
nostr: <npub>
ethereum: <address>
```
The lines are joined by a line feed, with none after the last. Each key signs the way its own wallets sign a message, so
any wallet can make a proof and any library can check one. A Taproot proof is a 64-byte signature (SIGHASH_DEFAULT) or a
65-byte one ending in SIGHASH_ALL; a P2WPKH proof is a low-S DER signature with SIGHASH_ALL and the compressed key. The
inscription's body is the statement, for people to read; the rules rebuild it from the metadata.
A keyring is rejected unless every key is well formed and every proof checks out. While a node's keyring stands, its keys
are bound to that node, and a keyring that lists a key bound to another node is rejected; a key binds once, whatever
network it is written for. A node's newer keyring replaces its older one and frees the keys it no longer lists. A
graduation retires the keyrings of the graduate and its derived descendants, since their keys change with the new root,
and a close retires the keyrings of the nodes it closes. A retired keyring binds nothing, so the node publishes a new one.
Lineage's key tree page also makes an agent's keyring as a nostr event (kind 30078, `d` = `lineage/keyring/v0`), signed
by its npub and listing its leaves too. The inscription is the chain's record, with a proof from every key.
## 9. Versions and other chains
Tag 7 carries the version. A new version is a new string with its own rules, which v0 indexers ignore. The events and
the rules are chain-agnostic. What another chain must supply is its own proof of order and of authority (a signature
by the node's key where nothing is spent). Each holding's events would live on one home chain, and its nodes' keyrings
(section 8) bind their keys on the others. Another chain's key joins the keyring in a new version, proven the way that
chain's own wallets sign a message.
## 10. Conformance
`tools/regtest` rehearses Orgchain's sample on Bitcoin Core regtest, byte for byte, keyrings included, and
`bin/lineage-index.mjs --compare` checks that ord and the lab tell the same story: the same events in the same beats,
the same metadata and parents, the same trees and keyrings, and every inscription in the same output.
`tests/indexer.test.js` replays a recorded run. `tests/keyring.test.js` checks the proofs against BIP-322's published
vectors, the key tree page's Ethereum vector, and values cross-checked with bip322-js, ethers and nostr-tools.