Orgchain v1.9: lineage/v0 as an ordinals metaprotocol, rehearsed on regtest
SPEC.md writes lineage/v0 down as an ordinals metaprotocol: the envelope fields, chain order, authority by verified parents, every rule, ownership by sat. bin/lineage-index.mjs reads lineage events from a real ord server and folds them with the same reducer the lab uses. tools/regtest rehearses the sample on Bitcoin Core regtest with standardness on: the lab's own action code signs on a chain funded only by coins imported from regtest (LocalChain.importCoin), each beat's transactions are broadcast byte for byte and mined, ord indexes them, and --compare checks the same events in the same beats, the same metadata and parents, every inscription in the same output and the same trees. tests/indexer.test.js replays a recorded run. The first rehearsal found that reveals committed to tapscript's re-encoded tapleaf, which real Bitcoin rejects. They now commit to the exact script bytes, and the local chain checks script paths per BIP-341/342, still loading reveals made before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4upF5LVwmPDDqrhdUfnXh
This commit is contained in:
1 parent
7d981341ff
commit
7c9306402d
21 files changed
+602
-21
No files matched your search
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env node
|
||||
// lineage-index: read lineage/v0 events from an ord server and print the trees they imply, with the same reducer the
|
||||
// lab uses. --compare <lab.json> checks that ord and a lab backup tell the same story (tools/regtest/README.md).
|
||||
// node bin/lineage-index.mjs [--ord http://127.0.0.1:8088] [--from <height>] [--compare <lab.json>]
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { decodeLab } from '../src/orgchain/store.js';
|
||||
import { census, rows, summary } from '../src/orgchain/lineage.js';
|
||||
import { ordClient, ordEvents, ordState } from '../src/indexer/ord.js';
|
||||
import { compareWithLab } from '../src/indexer/compare.js';
|
||||
|
||||
const { values } = parseArgs({ options: { ord: { type: 'string', default: 'http://127.0.0.1:8088' }, from: { type: 'string', default: '0' },
|
||||
compare: { type: 'string' } } });
|
||||
const events = await ordEvents(ordClient(values.ord), { from: Number(values.from) });
|
||||
const state = ordState(events), plural = (n, w) => `${n} ${w}${n === 1 ? '' : 's'}`;
|
||||
for (const root of state.roots) {
|
||||
const c = census(state, root.id);
|
||||
console.log(`\n${root.name} · ${plural(c.orgs, 'org')}, ${plural(c.agents, 'agent')}, ${plural(c.belts, 'belt')}, ${plural(c.decisions, 'decision')}`);
|
||||
console.log(rows(state, root.id).map(r => (r.type === 'group' ? `${r.guide}${r.label}` : `${r.guide}${r.path} ${r.node.name}${r.away ? ' · graduated' : ''}`)).join('\n'));
|
||||
}
|
||||
const rejected = state.log.filter(e => !e.ok);
|
||||
console.log(`\n${plural(events.length, 'lineage/v0 event')} on ord, ${plural(state.items.size, 'item')}${rejected.length ? `, ${rejected.length} rejected:` : ''}`);
|
||||
for (const e of rejected) console.log(` ${summary(e, state)} (${e.id})`);
|
||||
if (values.compare) {
|
||||
const { problems, ...n } = compareWithLab(decodeLab(readFileSync(values.compare, 'utf8')), events);
|
||||
console.log(problems.length ? `\nord and the lab differ:\n${problems.map(p => ` ${p}`).join('\n')}`
|
||||
: `\nSame story as ${values.compare}: ${plural(n.events, "event")}, ${plural(n.nodes, "node")} and ${plural(n.items, "item")}, each event in the same beat and every inscription in the same output.${n.reordered ? ` The miner ordered ${n.reordered} independent events differently within their blocks, which changes nothing.` : ""}`);
|
||||
process.exitCode = problems.length ? 1 : 0;
|
||||
}
|
||||
Reference in new issue
Block a user