Skip to content

feat: module deploys (BC protocol, Module index & getModules API) - #483

Open
ltardivo wants to merge 8 commits into
stagingfrom
feat/refactor-modules
Open

feat: module deploys (BC protocol, Module index & getModules API)#483
ltardivo wants to merge 8 commits into
stagingfrom
feat/refactor-modules

Conversation

@ltardivo

@ltardivo ltardivo commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Multisig modules now live as cleartext { ept } data outputs, taproot modules use the new BC protocol id (replacing ordinals-style ORD), and the node gains a dedicated Module table plus list/get endpoints. The client follows with getModules / getModule so apps can inspect source without evaluating it. Everything is versioned as 0.27.0-beta.1.

Breaking changes

  • Wire format
    Multisig: only { ept: string } is written (no exp / env / mod / v, no encryption).
    Taproot: reveal witness envelope now carries protocol id BC (content-type remains text/javascript).
    Legacy shapes that stored modules as transition exp fields or ord inscriptions are no longer read.

  • Client
    computer.decode(tx) now throws ModuleDecodeError on a module deploy. Use computer.load(rev) instead.
    Prefer getOUTXOs / latest + sync over the deprecated query (especially the old ids filter).

  • Node
    Existing Postgres volumes created before this feature need the Module table applied manually (see migration below).
    Lib and node must be the same version line; mismatched pairs produce 404s, parse failures, or empty indexes.

Lib

  • PROTOCOL_ID constant changed from ORD to BC.
  • Modules.toTx / broadcast emit pure multisig { ept } (still creates an owner output so the UTXO appears in the Output graph).
  • Taproot path uses the BC envelope; TxInscription.read and parseInscriptionData understand only the new format.
  • New helpers in module-meta: isModuleMeta, tryParseModuleFromTx, tryParseModule (keyless, ready for node indexing).
  • Computer.decode rejects module deploys with a clear error pointing to load.
  • New client API
// verbosity 0 (default) → string[] of mod specifiers
// verbosity 1 → ModuleRecord[] including ept + storageType + confirmation fields
await computer.getModules({ verbosity: 1, storageType: 'taproot', isConfirmed: true })
await computer.getModule(mod) // single ModuleRecord
  • Types: ModuleRecord, ModuleQuery, ModuleOnChainMeta, ExtractedModule.

Node

  • New Module table (mod, ept, storageType, blockHash, blockHeight, timestamp) with indexes.
  • Detection via module-extract (multisig { ept } and taproot BC witnesses).
  • Full stack: ModuleDao → ModuleService → ModuleAction.
  • Wired into insertSpendGraph / insertAndUpdateMod, ZMQ, blockchain sync, reorg (eraseBlockHash), and mempool hard-delete.
  • HTTP API
    GET /v1/:chain/:network/modules (verbosity, limit, offset, order, storageType, isConfirmed)
    GET /v1/:chain/:network/module/:mod

Docs

  • New changelog.md documenting the 0.27 protocol break and migration steps.
  • Comprehensive Node → Operate & Troubleshoot guide covering authentication, empty-result checklists, Module-table upgrade, version matching, reorg behaviour, and FAQ.
  • Computer reference updated: deploy / load / decode / constructor, plus brand-new pages for getModules, getModule, getInscription, isIndexed, waitForIndexed, delete, etc.
  • Tutorial rewritten to prefer getOUTXOs + latest + sync; load now correctly returns exports (use getModule for the raw ept source).
  • Cross-links between client methods and node endpoints; comparison page and onChainMetaData docs distinguish transitions vs module deploys.

Migration

  • Upgrade node image / monorepo tag to the 0.27.0-beta.1 line.
  • On any existing Postgres volume, run the Module DDL (also present in packages/node/db/db_schema.sql):
CREATE TABLE IF NOT EXISTS "Module" (
  "mod" VARCHAR(70) NOT NULL PRIMARY KEY,
  "ept" TEXT NOT NULL,
  "storageType" VARCHAR(16) NOT NULL,
  "blockHash" VARCHAR(64),
  "blockHeight" INTEGER,
  "timestamp" timestamp default CURRENT_TIMESTAMP not null
);
  • Upgrade @bitcoin-computer/lib to the matching version.
  • Replace any code that treated module transactions as transitions (decode, fake exp).
  • Prefer getOUTXOs over the deprecated query for listing smart objects.
  • Pin both sides to the same version:
{
  "dependencies": {
    "@bitcoin-computer/lib": "0.27.0-beta.1"
  }
}

ltardivo added 8 commits July 22, 2026 20:55
…tadata

Break module deploys out of the transition/Update path so they are no longer
encoded as fake expressions.

lib:
- Multisig: Modules.toTx/broadcast store cleartext { ept } only (no exp/env/mod/v,
  no encryption); still create an owner output for the UTXO/Output graph.
- Taproot: reveal scripts use protocol id BC (not ordinals ord); content-type
  remains text/javascript; TxInscription.read uses parseInscriptionData.
- Modules.load/fetchSource read ept or the BC witness only (no legacy exp/ord).
- Computer.decode and Update.fromTx reject module deploys with ModuleDecodeError
  (use load). Computer.deploy/load JSDoc updated.
- module-meta: isModuleMeta, tryParseModuleFromTx, tryParseModule for keyless
  detection (prep for a future node Modules table; table not added yet).
- Types: ModuleOnChainMeta, ExtractedModule.
- Tests: module-meta unit tests; modules async ept/decode coverage; getInscription
  builds a BC witness tx instead of a frozen ordinals hex fixture.
- monorepo types: PROTOCOL_ID constant 'BC'.

docs (monorepo/packages/docs):
- Transaction.onChainMetaData: transition vs multisig module vs taproot module.
- Computer deploy/load/decode/constructor and comparison page aligned with the
  new wire formats.
Add first-class Module indexing so multisig { ept } and taproot BC
witness deploys are stored and queryable, not treated as transitions.

node:
- Schema: Module table (mod, ept, storageType, blockHash, blockHeight,
  timestamp) with blockHash/blockHeight indexes; mirrored in monorepo
  packages/node/db.
- Detection: module-extract (isModuleMeta, tryParseModuleFromTx) for
  cleartext { ept } and BC reveal witnesses (protocol id BC).
- Stack: ModuleDao / ModuleService / ModuleAction; getModules attaches
  optional block context for sync and ZMQ.
- Wire-in: insertSpendGraph / insertAndUpdateMod accept modules;
  ZMQ and sync-blockchain batch inserts; reorg eraseBlockHash; mempool
  hard-delete removes unconfirmed modules with outputs/inputs.
- API: GET /modules (verbosity 0 = specifiers, 1 = full rows; limit,
  offset, order, storageType, isConfirmed) and GET /module/:mod.
- Utils: formatPositions5 for 5-column Module inserts.
- Fix: Module.query prepared-statement names unique per filter combo
  (storageType × isConfirmed × order) to avoid pg name collisions.

tests:
- module-extract unit coverage (meta, multisig/taproot, getModules).
- ModuleAction async: insert/upsert, filters, reorg, mempool delete,
  insertSpendGraph.
- smart-object routes for /modules and /module/:mod; formatPositions5.

docs (monorepo/packages/docs):
- Node: modules.md, module.md; index architecture/API/Postgres notes.
- Clarify non-standard-utxos / get-txos mod = membership, not source.
- Cross-link deploy/load to the node module endpoints.
Expose the node Module index on the client so apps can list and fetch
deployed module sources without evaluating them.

lib:
- Types: ModuleRecord and ModuleQuery (verbosity, limit, offset, order, storageType, isConfirmed).
- RestClient.getModules → GET /modules; RestClient.getModule → GET
  /module/:mod (validates specifier via isValidRevString).
- Computer.getModules / getModule thin wrappers next to deploy/load;
  verbosity 0 returns specifier strings, 1 returns full rows with ept.
- Does not evaluate modules (still use load for exports).

tests:
- modules.async-test: after deploy, poll getModules and assert getModule
  returns the indexed source and storageType.
…ence

Bring Computer method docs in line with the current public API: add the
module index helpers, fill missing method pages, and fix outdated
signatures and recommendations.

docs:
- index.md: reorganize Basic / Modules / Query outputs / History /
  Wallet / Indexer readiness / SSE / Deprecated; prefer getOUTXOs over
  query; fix faucet link; link getTXOs family, fund, streams, etc.
- New: getModules, getModule, getInscription, isIndexed, waitForIndexed,
  listTxs, getUrl, getPath, getFee, setFee, delete, last, spendingInput,
  isUnspent.
- waitForIndex.md: redirect to waitForIndexed (correct method name and
  return type with timeout options).
- query.md: mark deprecated; real Query shape (no ids); point to
  getOUTXOs; distinguish object membership vs module source.
- getTXOs / getUTXOs / getOTXOs / getOUTXOs / getUtxos: fix getUOTXOs →
  getOUTXOs, isSpent naming, TXORecord types, mod = membership.
- deploy/load: link client getModules/getModule; Node modules/module
  pages cross-link the client methods.
- fund, faucet, getAncestors, streamMempoolCleanup: accuracy fixes.
Document authentication, empty results, Module schema upgrades, and version matching in Node/operations.md, plus a 0.27 changelog for module deploy breaking changes. Correct the tutorial (load exports, getOUTXOs/latest instead of query ids), rename getTXOs/getUTXOs pages to match the API, and cross-link Node and Computer docs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant