Files
zeekay 7581fd9d61 chore: sync working tree
Commits 2 outstanding change(s) that were sitting uncommitted.
No build artifacts and no secrets in the changeset (both checked).
2026-07-26 10:02:10 -07:00

8.6 KiB

chains

Org: luxfi · Ecosystem: lux · Path: /Users/a/work/lux/luxfi/chains Origin: https://github.com/luxfi/chains.git

Discovery

This file (CLAUDE.md) is the canonical agent-facing readme; LLM.md is a symlink to it. Update either name and both stay in sync.

Where to look first

  • README.md — human-facing overview (if present)
  • package.json / Cargo.toml / pyproject.toml / go.mod — language & deps
  • .github/workflows/ — CI surface
  • docs/ — extended docs (if present)

Canonical chain roster (LP-0130)

The topology, UTXO ownership rule, and cross-chain fee model are normatively specified by LP-0130 (Chain Topology, UTXO Ownership, and Fee Model). Read that LP before touching any VM's fee/settlement path.

Only P (in node/vms/platformvm) and X (in node/vms/xvm) are canonical UTXO state machines. Every VM in THIS repo is a domain-execution chain that MUST consume UTXO settlement via the chains/fee primitive funded from X.

Dir Letter Role LP
evm/ C Contract / EVM account state LP-1200
dexvm/ D DEX matching + settlement receipts LP-9000
quantumvm/ Q Finality-cert / Quasar aggregation. No user-payable blockspace (validator obligation, LP-0130 §6) LP-1300
zkvm/ Z Rollup / private commitment + nullifier. Shielded supply is an X-escrow wrapper (LP-0130 §2, I-5) LP-8000
aivm/ A Inference receipt + attestation. Rides B's settlement engine (LP-0130 §9) LP-5000
bridgevm/ B Cross-chain message lifecycle. Fees deducted from bridged amount (LP-0130 §8) LP-6000
mpcvm/ M MPC signing / custody. Service fees paid by originating chain (LP-0130 §7); no user M-balance LP-7100
mpcvm/fhe/ F FHE runtime library — a package inside mpcvm, not a chain. See the deployment note below. LP-8200

Deployment reality (probed on mainnet 96369, platform.getBlockchains). Ten chains are live: P X + C D Q Z A B G K. M and F are NOT deployed, and the two are not equally close to shipping:

  • M has a full VM (mpcvm/, mpcvm/cmd/plugin) — it builds, it just has no chain registered on any network.
  • F has no VM at all. luxfi/constants reserves FHEVMID = {'f','h','e','v','m'} and luxfi/node/node/vms.go lists it in OptionalVMs as plugin fhevm, so luxd scans --plugin-dir for a binary that this repo never produces (no fhevm/ directory ⇒ no make target ⇒ no binary). mpcvm/fhe/ above is the FHE runtime library, not a standalone F-Chain. F-Chain is a spec (LP-8200, LP-167) with no shipping VM.

T-Chain is gone entirely — LP-134 dissolves it with zero remainder (threshold signing → M, FHE → F, cross-chain messaging/teleport → B). There is no teleportvm here and no teleportvm VM ID in luxfi/constants.

Service VMs (not canonical primary chains under LP-0130):

Dir Letter Purpose
schain/ S S3-style object storage (on-chain metadata, off-chain blob)
keyvm/ K Key registry / cryptographic algorithm addressing
identityvm/ I DID / identity
graphvm/ G Graph indexing / GraphQL surface
relayvm/ R Relay message queue
oraclevm/ O Oracle price / data feed

Service VMs MAY have domain state and MAY charge fees, but MUST fund their fee balance from X and MUST NOT hold canonical UTXO asset supply.

Fee settlement primitive — chains/fee

chains/fee/{balance,meter,settle,ledger}.go is the shared admission → meter → burn primitive every non-P/X VM in this repo uses. Its Burn is a native LUX burn (no coinbase credit) that reconciles against X-side fee escrow at the epoch fee root (LP-0130 §4). chains/fee/doc.go is the design intent.

Σ-escrow invariant

At every Q checkpoint (LP-0130 I-8):

Σ (non-P/X fee balances)  ==  Σ (X-side fee escrow)

Drift is a finality-blocking fault. This is the audit invariant every VM's epoch-fee-root emission and reconciliation path exists to satisfy.

VMs in this repo

Each *vm/ dir is a self-contained block.ChainVM plugin. dexvm is the reference for VM structure + commit discipline (dual-DB: durable baseDB + per-block versiondb; one db.CommitBatch() at block Accept).

  • schain (schain/) — the Lux S-Chain storage VM, forked from dexvm's structure. VMID = ids.ID{'s','c','h','a','i','n'} (dexvm's byte pattern). M0 (DONE): one mutation PutManifest{bucket,object,fileIds,size,etag} round-trips through a real Lux block (BuildBlock→Verify→Accept) and commits the manifest to a real on-disk zapdb in ONE atomic batch at Accept; GetManifest returns it only after Accept. Commit discipline copied verbatim from dexvm/vm.go:1194 (acceptBlock), minus the cross-chain shared-memory leg a storage VM does not have — accept reduces to CommitBatch() + batch.Write() + db.Abort(). State = typed manifest accessors over versiondb (no protobuf; JSON value bodies, prefix keys), mirroring dexvm/state/state.go. Tx wire = type-byte + JSON, one codec (mirror dexvm/txs/tx.go). No blobs/pinning/ networking yet — that is M1+. Test: schain/schain_test.go drives the genuine VM↔engine contract (SubmitTx→ToEngine PendingTxs→BuildBlock→Verify→Accept) over a REAL zapdb.New(t.TempDir(),…); proves staged-not-durable before Accept, durable after, and Reject→Abort discards. M1 (DONE): TWO parts. PART A — manifest STATE ROOT (the multi-validator safety prerequisite M0 omitted): state.Root() hashes the committed manifest keyspace deterministically via the zapdb prefix iterator NewIteratorWithStartAndPrefix(nil, prefixManifest), folding each entry length-prefixed (len(k)||k||len(v)||v) in lexicographic key order (mirror of dexvm/state/state.go:395 StateHash, narrowed to the one keyspace; last-block pointer excluded — it is consensus binding folded via blockHash/height, not object state). VM.computeStateRoot folds blockHash+height with state.Root() (mirror dexvm/vm.go:1260); ProcessBlock stamps it into BlockResult.StateRoot (mirror dexvm/vm.go:584). The root travels in the block HEADER (new 32-byte field after parentID; block id commits to it) and Block.Verify recomputes it and REJECTS a mismatch (errStateRootMismatch) + Aborts staged writes — this is the >1-validator safety gate dexvm computed but never compared. Tests (schain/stateroot_test.go): determinism across write order, change-sensitivity (object set / etag / size / fileIds each move the root), and Verify-rejects-tampered-root. PART B — S3 OBJECT path, on-chain-metadata / off-chain-blob split proven end to end (schain/object/): Store.PutObject streams the blob to a Volume (OFF chain) → fid, then commits only PutManifest{bucket,object,[fid],size,etag} to the VM through a real block (ON chain); GetObject reads the manifest back and reconstructs the blob from the volume. object.Volume is the SEAM (Write(blob)→fid, Read(fid)→blob); M1 satisfies it with a faithful in-memory MemVolume whose fid shape mirrors hanzo/s3's needle.FileId (volumeId,needleIdCookie) and whose etag is base64(md5(blob)) (= hanzo/s3 ContentMd5). M2 PLUG POINT (marked in object/volume.go): swap MemVolume for a thin adapter over github.com/ hanzoai/s3 s3/operation.SubmitFiles (assign volume + stream needle → .Fid) and a needle GET — nothing in the VM or object.Store changes. Kept inside chains/schain (not importing the hanzoai/s3 module into luxfi/chains) to respect the org/module boundary while proving the exact data model. Test (schain/object_roundtrip_test.go): asserts the blob bytes appear in NO accepted block (bytes.Contains over blk.Bytes()) and the block stays manifest-small (<4KiB for a 68KiB blob), the manifest IS on chain, and GET byte-reconstructs.

Test/build env gotcha (macOS)

The whole chains test suite links CGO deps that need -lresolv; the CLT cc fails with library 'resolv' not found unless the macOS SDK syslibroot is set. Run tests with SDKROOT="$(xcrun --show-sdk-path)" go test ./schain/.... This affects dexvm and every other VM here too — it is NOT schain-specific.

Sibling repos

See the org-level LLM.md at /Users/a/work/lux/luxfi/LLM.md for the full inventory of sibling repos and inter-repo dependencies.