Orgchain v1.13: whole trees change hands
An org now changes hands with its tree, the derived orgs and agents below it and the items they hold, and a holding changes hands whole, sold by its owner, whom the lab wallet plays (the price goes there). Sales stay cash-free: the money in the tree, every gas tank included, goes to the seller first, and the items go with the tree. An ask signs one input, so listing a tree bundles every inscription in it into one output at the lot's key; an offer spends every output the tree sits in and merges them. After the join and the adopt, which now move a holding too (it becomes its buyer's next org), the buyer splits the output back, one inscription to an output at its new key, each item with the node that held it, by the layout the deal recorded. A listed or sold tree is frozen whole: nothing in it acts, sends, is funded or sells alone, nothing above it graduates or closes it, and a listed holding mines nothing. Graduation roots are kept by graduation event, since a node can graduate, move and graduate again. Transactions take up to 64 inputs and outputs. Rehearsed on Bitcoin Core regtest from height 144: sixteen beats and 131 transactions, time with its six below it bought on an offer, and acme sold whole on an ask, eleven inscriptions in one output, then split again; ord puts every inscription in the same output as the lab. 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
adca2709f0
commit
74ed801176
23 files changed
+904
-390
No files matched your search
@@ -1,9 +1,9 @@
|
||||
# Regtest rehearsal
|
||||
|
||||
Lineage is an ordinals metaprotocol (`SPEC.md`). This folder checks that on real Bitcoin Core and real `ord`: the lab's
|
||||
own action code makes the yolopreneur sample, keyrings, asks, offers and moves included, Bitcoin Core (regtest,
|
||||
standardness on) accepts its transactions byte for byte, `ord` indexes the inscriptions, and the same reducer folds
|
||||
ord's view back into the same trees.
|
||||
own action code makes the yolopreneur sample, keyrings, asks, offers and whole trees changing hands included, Bitcoin
|
||||
Core (regtest, standardness on) accepts its transactions byte for byte, `ord` indexes the inscriptions, and the same
|
||||
reducer folds ord's view back into the same trees.
|
||||
|
||||
Regtest is local and private: nothing is downloaded, blocks are mined on demand, and the data folders stay a few MB.
|
||||
Test coins only.
|
||||
@@ -26,7 +26,7 @@ since the lab pays a fixed 500 sats per transaction.
|
||||
## Rehearse, index, compare
|
||||
|
||||
```
|
||||
node tools/regtest/rehearse.mjs # twelve beats; saves the lab to tools/regtest/out/lab.json
|
||||
node tools/regtest/rehearse.mjs # sixteen beats; saves the lab to tools/regtest/out/lab.json
|
||||
node bin/lineage-index.mjs --from 100 --compare tools/regtest/out/lab.json
|
||||
node tools/regtest/record.mjs # refresh tests/fixtures/regtest-rehearsal.json (public data only)
|
||||
```
|
||||
@@ -39,7 +39,10 @@ unspendable key, so nothing it signs spends a coin regtest doesn't have. After e
|
||||
transactions and mines one regtest block. `--compare` checks that every event landed in the same beat with the same
|
||||
metadata and parent, that every inscription sits in the same output, and that both fold into the same trees. Within a
|
||||
block the miner may order independent events differently from the lab, a join and its adoption included; that changes
|
||||
nothing (`SPEC.md`, sections 2 and 5).
|
||||
nothing (`SPEC.md`, sections 2 and 5). The last four beats sell whole trees: time with its six below it, on an offer
|
||||
whose inputs are their seven inscriptions, and acme whole, on an ask that signs one output holding eleven; each tree
|
||||
then splits back at its buyer's keys, one inscription to an output, and ord puts every one where the lab does
|
||||
(`SPEC.md`, section 7).
|
||||
|
||||
`out/` holds the lab backup, test keys included, and is not committed.
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Rehearse the yolopreneur sample on real Bitcoin Core (regtest). The lab's own action code signs every transaction on
|
||||
// a LocalChain whose only money is coins imported from regtest, so nothing it makes spends a local coinbase. After each
|
||||
// beat, that beat's transactions go to bitcoind byte for byte and are mined into a block; ord then indexes them like
|
||||
// any other inscriptions, and bin/lineage-index.mjs folds them back into trees. Test coins on a private chain only.
|
||||
// Rehearse the yolopreneur sample on real Bitcoin Core (regtest), with its deals and the trees that change hands. The
|
||||
// lab's own action code signs every transaction on a LocalChain whose only money is coins imported from regtest, so
|
||||
// nothing it makes spends a local coinbase. After each beat, that beat's transactions go to bitcoind byte for byte and
|
||||
// are mined into a block; ord then indexes them like any other inscriptions, and bin/lineage-index.mjs folds them back
|
||||
// into trees. Test coins on a private chain only.
|
||||
// Usage: node tools/regtest/rehearse.mjs [out.json] (tools/regtest/README.md starts bitcoind and ord)
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
@@ -36,7 +37,7 @@ const mine = n => node('generatetoaddress', n, miner);
|
||||
const height = await node('getblockcount');
|
||||
if (height < 120) await mine(120 - height); // mature coins for the funder, and past ord's regtest jubilee
|
||||
const funding = [];
|
||||
for (const btc of [20, 20, 20, 10]) funding.push(await funder('sendtoaddress', lab.wallet.address, btc));
|
||||
for (const btc of [20, 20, 20, 20, 10]) funding.push(await funder('sendtoaddress', lab.wallet.address, btc));
|
||||
await mine(1);
|
||||
for (const txid of funding) {
|
||||
const o = (await node('getrawtransaction', txid, true)).vout.find(v => v.scriptPubKey.hex === hex(lab.wallet.script));
|
||||
@@ -115,6 +116,20 @@ await beat('acme buys docscope on an offer time accepts');
|
||||
adopt(lab, docscope, acme);
|
||||
take(lab, askId(sell(lab, kit, 0.2 * SAT)), scout);
|
||||
await beat('acme adopts docscope, and scout takes the ask for the launch kit');
|
||||
// Whole trees (v1.13). An offer: acme bids for time with its six below it, every coin they sit in as an input, and
|
||||
// yolopreneur accepts cash-free; acme adopts it a beat later, and the coin it bought splits back into the tree at
|
||||
// acme's keys. An ask: acme's owner lists acme whole, its tree bundled into one coin (eleven inscriptions, the launch
|
||||
// kit scout holds among them), and lineage takes it, adopts it, and splits it back at lineage's keys.
|
||||
deposit(lab, acme, 10 * SAT);
|
||||
accept(lab, offer(lab, time, acme, SAT).txid);
|
||||
await beat('acme buys time with its tree, on an offer yolopreneur accepts');
|
||||
adopt(lab, time, acme);
|
||||
await beat("acme adopts time, and the tree splits back at acme's keys");
|
||||
deposit(lab, lineage, 5 * SAT);
|
||||
const whole = sell(lab, acme, 2 * SAT);
|
||||
await beat("acme's owner lists acme whole, its tree in one coin");
|
||||
take(lab, askId(whole), lineage);
|
||||
await beat('lineage takes acme whole and adopts it');
|
||||
|
||||
const live = reduce(lineageEvents(new MetadataIndex(lab.chain)), { pending: true });
|
||||
for (const root of live.roots) {
|
||||
|
||||
Reference in new issue
Block a user