Skip to content

Introduce Commodity - #442

Open
ltardivo wants to merge 64 commits into
stagingfrom
feat/pow
Open

Introduce Commodity#442
ltardivo wants to merge 64 commits into
stagingfrom
feat/pow

Conversation

@ltardivo

@ltardivo ltardivo commented Mar 3, 2026

Copy link
Copy Markdown
Collaborator

feat: introduce Commodity PoW meta-token with determinism hardening and TBC777 zero-amount support

This PR delivers the Commodity standard — a pure-utility meta-token whose issuance is bound 1:1 to host-chain blocks through a min-revision PoW race — together with the foundational determinism work that makes rich on-chain introspection safe inside smart contracts. Commodity reframes the earlier pow-token prototype as a clean digital commodity primitive (deterministic host-block subsidies, genuine-mint lineage via immutable _root, no governance or profit expectations). Along the way we cleaned up the RPC surface, gave contracts first-class access to confirmed chain state, and relaxed TBC777 so zero-amount tokens are first-class citizens.

Commodity (new package)

  • Renamed from pow-token / Pow to commodity / Commodity for clearer regulatory and product positioning.
  • Issuance is strictly one subsidy per host block that contains module creations; the winner is the genuine mint whose creation revision is the lexicographically smallest.
  • Client-side Bitcoin-compatible SHA-256 grinding produces the competitive salt; the subsidy schedule follows Bitcoin (50 coins, halving every 210 000 host blocks, zero after 64 halvings).
  • claim() is fully deterministic and cheap: it uses only txIdToBlockHeight, decode and getOTXOs (all-object TXOs of the block) so every honest validator sees an identical, immutable candidate set. Selecting via getOUTXOs had allowed a same-block loser to claim after the winner’s creation UTXO was spent; that race is closed.
  • Commodity now extends TBC777 (instead of bare Contract) so modules reuse the escrow/auditor machinery. Deployed modules must therefore export the full inheritance chain (TBC20, EscrowAuditor, TBC777, Commodity) for SES resolution.
  • Constructor aligned with TBC777/TBC20 style: a single params object { to, salt?, amount?, name?, … }. Genuine mint roots still require a non-empty salt and amount === 0n.
  • transfer() retains classic fungible shape via a protected _createTransferToken helper that always produces non-mint children (salt === '') and drops escrow bookkeeping.
  • Tests, README examples and the esbuild contract build (now externalising @bitcoin-computer/*) updated accordingly.

TBC777

  • Feature / migration: ordinary tokens may now be created with amount === 0n (empty bags, deferred issuance). Remote-root tokens remain constrained to amount === 0n so bridged value still originates from audited escrow claims.
  • Commodity can therefore pass the amount through directly; the previous temporary 1n + immediate burn() dance is gone. makeRegex and unit tests cover the revised rules.

Lib & Computer API

  • Breaking change: Computer.rpc() (and all downstream helpers) now return the payload directly. The long-standing double-nested .result / .result.result indirection has been removed. Update every call site:
    // before
    const { result } = await computer.rpc('getBlockchainInfo', '')
    // after
    const result = await computer.rpc('getBlockchainInfo', '')
  • New public helpers for chain introspection (also available inside contracts via the InnerComputer):
    • txIdToBlockHeight, txIdToBlockHash
    • getBlockHash, getBlockHeight
    • getRawTransaction, getRawBlock, getBlockHeader
  • getTXOs / getUTXOs / getOTXOs / getOUTXOs gain (and inside contracts require) stabilizing filters: blockHeight, lteBlockHeight, gteBlockHeight, blockHash. Height-based filters must be ≤ current tip; future-height queries set globalInvalidState and are rejected exactly like missing state.
  • The height filters moved from TXORecord to TXOQuery where they belong; types and docs updated.
  • getTxos.md documents the new parameters.

Workspace (lib/ node)

These changes are invisible to public consumers but are the real foundation that lets Commodity (and future Ordinals-/Runes-/BRC-20-style meta-protocols) live as pure on-chain contracts:

  • Centralized _safeCall, _invalidate and _ensureConfirmedTx helpers eliminate duplicated error handling and guarantee uniform diagnostic messages.
  • Every potentially non-deterministic observation (mempool txs, future heights, missing state) is turned into an invalidation before it can leak into contract execution.
  • The core invariant is now explicit and enforceable: any successful observation made against a confirmed chain prefix must return the identical value on every future extension.
  • prev() on a root revision is now fatal (use first() or _id); the previous special-case that returned undefined has been removed.
  • On reorg unconfirm, blockHeight and blockIndex are cleared together with blockHash, preventing stale height matches.
  • Comprehensive contract tests cover happy-path round-trips, raw-data consistency and every invalidation path.

Tests, docs & miscellaneous

  • Full regtest suite for Commodity: same-block competition, post-claim sync, history-stable index behaviour, Tier-1 eligibility guards and Tier-2 canonical selection.
  • getTXOs / RPC / OrdSale tests updated for the new response shape, longer sleeps for stability, and the inclusive height filters.
  • Compliance docs rewritten for uniform Layer-1 (IP/GeoIP + network) screening at the broadcast endpoint and a universal lightweight pre-render gate (generic disclosure + cached click-wrap + CSP sandbox) before every fullscreen-rendered app object. Differentiated canonicalMods / canonicalAppObjectIds screening is gone.
  • Package-lock, tsconfig and build scripts cleaned up; @types/mocha added where needed; trailing commas and formatting fixed throughout.

Together these pieces give Bitcoin Computer a clean, deterministic foundation for fair per-block meta-token issuance while preserving the strict “no non-existent or non-deterministic state” guarantee that makes smart-contract execution reproducible.

ltardivo and others added 17 commits February 27, 2026 13:37
Add `ltBlockHeight` and `gtBlockHeight` to `TXORecord` and `OutputType`. Update `OutputDao` filtering logic together with query parsing, validation, and forwarding in the smart-object route so callers can express block-height range bounds.

The `getTXOs` query (especially when filtered by dynamic criteria such as `mod`) is an essential introspection primitive for smart contracts, but its results are inherently non-deterministic: any newly broadcast matching transaction immediately alters the answer. Exposing the unguarded form inside the InnerComputer would therefore destroy the determinism guarantees that make smart-contract execution reproducible and usable.

This change makes the two new filters available on the outer (non-deterministic) API first. Queries bounded by `ltBlockHeight` become stable once the referenced block is known, providing the guard needed for determinism. A follow-up commit will introduce the corresponding guarded `getTXOs` variant inside the InnerComputer, required to carry an `ltBlockHeight` bound on every potentially non-deterministic call.
This change closes the remaining window for transient observations inside smart contracts. `getTXOs` (and its aliases) now requires not only a stabilizing filter (`lteBlockHeight`, `blockHeight`, or `blockHash`) but also that any height-based filter must be at or before the current tip. Queries pointing into the future set `globalInvalidState` and are rejected exactly like missing state in `sync`, `decode`, etc.

The stabilizing height filters are renamed from the previous exclusive `ltBlockHeight`/`gtBlockHeight` to inclusive `lteBlockHeight`/`gteBlockHeight` (types, InnerComputer validation logic, OutputDao conditions, smart-object route parsing, and all tests) so the allowed range is now precisely `blockHeight <= current tip`. The future-height guard therefore uses a direct `> currentHeight` check with no `+1` offset, and the DAO emits `<=` / `>=` predicates.

Tests were updated to pass the current tip height directly as a safe bound and to assert the new rejection paths. Together these edits make the “no non-existent or non-deterministic state” invariant stricter, simpler to maintain, and impossible to violate through future-height queries.
This change updates TBC777, chess-contracts and the corresponding tests (plus a few lib test and type surfaces) to match the lib-secret refactor that removes the double-nested `.result` indirection from `Computer.rpc`, `RestClient` and all call sites.

The RPC cleanup eliminates a long-standing source of confusion and makes the core invariant—“any successful observation against a confirmed chain prefix must be identical on every future extension”—straightforward to audit. With the noise removed, every transient or non-existent observation is now uniformly turned into an invalidation via the existing `_invalidate` path, future-height guards are direct, and confirmed-tx requirements are explicit.

Concretely:

- `TBC777`: the terminal-revision check was moved out of `EscrowAuditor.getAudit()` / `AuditResult` and into `finalWithdraw()` only. Regular paths (`getBalance`, `withdraw`, `audit`) therefore stay free of chain-tip observations. Documentation was tightened to reflect the clarified no-inflation rules and remote-root token requirements.
- Tests (TBC777, TBC777M, chess): added an explicit `mine()` helper and inserted `await mine()` after every state change that must become stable before a subsequent deterministic read. Several flows that used to be “atomic” (e.g. `cancelGameAndWithdraw`, `finalWithdraw` immediately after creation) now correctly require a block boundary.
- Error expectations updated: attempting `finalWithdraw` on a non-tip revision now surfaces the generic “Accessing non-existent on-chain state inside a smart contract is forbidden” instead of a domain-specific claimable-zero message.
- `ChessContractHelper.cancelGameAndWithdraw` is deprecated; callers must now perform the withdraw step in a later transaction after the next block.
- lib tests and `computer.d.ts` were updated for the direct RPC response shape and the new block/tx lookup helpers (`txIdToBlockHeight`, `getBlockHash`, etc.).

No behavioral change for any well-formed, confirmed on-chain observation. The public contract tests now cleanly exercise the hardened determinism guarantees introduced in the preceding commits.
This change introduces POW.TS, a meta-token whose issuance is bound 1:1 to host-chain blocks (LTC, BTC, …). Exactly one subsidy is awarded per block that contains module creations; the winner is the genuine mint whose creation revision is the lexicographically smallest. The only work is performed off-chain by grinding a salt until the resulting mint produces a competitively small revision; once the transaction confirms, claim() succeeds only while the object is still at its creation revision and only if it holds the absolute minimum.

The design inherits the host chain’s full security model (difficulty retargeting, heaviest-chain rule, finality) while keeping every step inside claim() deterministic and cheap: txIdToBlockHeight, decode and getOUTXOs are used exclusively; no candidate objects are ever materialised or replayed. Lineage authenticity is established via the immutable _root (isGenuine syncs only the short root mint). Transfer and split children inherit the root but are permanently ineligible because their _rev diverges from _root. Host miners enjoy a deliberate inclusion advantage—when the token has value this creates extra fee revenue that strengthens the underlying chain; ordinary transfers carry no MEV surface with respect to the subsidy. After a successful claim the credited amount is sticky (reorgs that would have changed the canonical mint do not revoke it).

A self-contained, Bitcoin-Core-compatible SHA-256 implementation is included to support client-side grinding. The subsidy schedule follows Bitcoin (50 coins halving every 210 000 host blocks, zero after 64 halvings). An extensive Mocha/Chai test skeleton organises the complex claim logic into Tier-1 eligibility guards (no same-block control required) and Tier-2 canonical selection, plus end-to-end workflow and invariant tests; many cases remain as commented stubs to guide incremental implementation on regtest.

Together these pieces establish a clean foundation for any application that needs fair, per-block meta-token issuance on Bitcoin Computer while preserving the strict determinism guarantees the runtime now enforces.
Rename the pow-token package (and its Pow class) to commodity to reframe the min-revision issuance mechanism as a canonical digital commodity standard. The change updates source comments, README, and positioning language to emphasize pure utility characteristics—deterministic host-block subsidies, genuine-mint lineage via immutable _root, no governance rights or profit expectations—while preserving the existing selection and claim logic. This supports clearer regulatory framing and aligns documentation with the standard’s intended use as a functional issuance primitive.
@ClemensLey ClemensLey changed the title Proof of Work Token Introduce Commodity Jul 26, 2026
ClemensLey and others added 12 commits July 25, 2026 19:50
…aim() spends the creation UTXO. Selecting candidates via getOUTXOs (unspent only) made the winner disappear from the candidate set on re-evaluation, so a same-block loser could later claim after the creation was spent. Switch to getOTXOs (all object TXOs in the block) so every honest validator sees the identical, immutable set of revisions. Update comments and replace the test skeleton with a full regtest suite that exercises same-block competition, post-claim sync, and the new index behaviour.
Commodity now extends TBC777 (instead of Contract) so modules can reuse its escrow-capable token machinery. Deployed modules must therefore export the full inheritance chain (TBC20, EscrowAuditor, TBC777, Commodity) for SES resolution.

The constructor is aligned with TBC777/TBC20 style: a single params object
  { to, salt?, amount?, name?, … }
instead of positional arguments. Genuine mint roots still require a non-empty salt and amount === 0n. Because TBC777 forbids amount === 0n without a remoteRoot, the constructor temporarily passes 1n and immediately burns to reach the required zero state.

transfer() retains the classic fungible shape (whole-balance reassignment or partial split) via a protected _createTransferToken helper that always produces non-mint children (salt === '') and drops escrow bookkeeping. Tests, README examples, and the esbuild contract build (now externalising @bitcoin-computer/*) are updated accordingly. The height filter fields are also moved from TXORecord to TXOQuery where they belong.
TBC777 previously rejected amount === 0n unless a remoteRoot was supplied. This forced Commodity (and any other mint-root subclass) to construct with a temporary 1n and immediately burn() to reach the required zero state.

Zero amounts are now permitted for ordinary tokens, supporting empty bags and deferred issuance. Remote-root tokens remain constrained to amount 0n so that all bridged value still originates from audited escrow claims. The Commodity constructor can therefore pass the amount through directly, makeRegex is updated to match, and unit tests cover the revised rules.
ClemensLey and others added 30 commits August 4, 2026 12:25
Refresh the monorepo landing page to accurately describe Bitcoin Computer
as Turing-complete smart contracts written in ordinary JavaScript that
live in UTXOs. Add a concise value-proposition list, a runnable quick-start
example, clearer package tables (including the new TBC777 escrow standard),
a high-level “how it works” outline, and updated community and legal notes.
The previous README was outdated and no longer reflected the client-side
evaluation model, multichain support, or the current documentation structure.
This change updates TBC777, chess-contracts and the corresponding tests (plus a few lib test and type surfaces) to match the lib-secret refactor that removes the double-nested `.result` indirection from `Computer.rpc`, `RestClient` and all call sites.

The RPC cleanup eliminates a long-standing source of confusion and makes the core invariant—“any successful observation against a confirmed chain prefix must be identical on every future extension”—straightforward to audit. With the noise removed, every transient or non-existent observation is now uniformly turned into an invalidation via the existing `_invalidate` path, future-height guards are direct, and confirmed-tx requirements are explicit.

Concretely:

- `TBC777`: the terminal-revision check was moved out of `EscrowAuditor.getAudit()` / `AuditResult` and into `finalWithdraw()` only. Regular paths (`getBalance`, `withdraw`, `audit`) therefore stay free of chain-tip observations. Documentation was tightened to reflect the clarified no-inflation rules and remote-root token requirements.
- Tests (TBC777, TBC777M, chess): added an explicit `mine()` helper and inserted `await mine()` after every state change that must become stable before a subsequent deterministic read. Several flows that used to be “atomic” (e.g. `cancelGameAndWithdraw`, `finalWithdraw` immediately after creation) now correctly require a block boundary.
- Error expectations updated: attempting `finalWithdraw` on a non-tip revision now surfaces the generic “Accessing non-existent on-chain state inside a smart contract is forbidden” instead of a domain-specific claimable-zero message.
- `ChessContractHelper.cancelGameAndWithdraw` is deprecated; callers must now perform the withdraw step in a later transaction after the next block.
- lib tests and `computer.d.ts` were updated for the direct RPC response shape and the new block/tx lookup helpers (`txIdToBlockHeight`, `getBlockHash`, etc.).

No behavioral change for any well-formed, confirmed on-chain observation. The public contract tests now cleanly exercise the hardened determinism guarantees introduced in the preceding commits.
This change updates TBC777, chess-contracts and the corresponding tests (plus a few lib test and type surfaces) to match the lib-secret refactor that removes the double-nested `.result` indirection from `Computer.rpc`, `RestClient` and all call sites.

The RPC cleanup eliminates a long-standing source of confusion and makes the core invariant—“any successful observation against a confirmed chain prefix must be identical on every future extension”—straightforward to audit. With the noise removed, every transient or non-existent observation is now uniformly turned into an invalidation via the existing `_invalidate` path, future-height guards are direct, and confirmed-tx requirements are explicit.

Concretely:

- `TBC777`: the terminal-revision check was moved out of `EscrowAuditor.getAudit()` / `AuditResult` and into `finalWithdraw()` only. Regular paths (`getBalance`, `withdraw`, `audit`) therefore stay free of chain-tip observations. Documentation was tightened to reflect the clarified no-inflation rules and remote-root token requirements.
- Tests (TBC777, TBC777M, chess): added an explicit `mine()` helper and inserted `await mine()` after every state change that must become stable before a subsequent deterministic read. Several flows that used to be “atomic” (e.g. `cancelGameAndWithdraw`, `finalWithdraw` immediately after creation) now correctly require a block boundary.
- Error expectations updated: attempting `finalWithdraw` on a non-tip revision now surfaces the generic “Accessing non-existent on-chain state inside a smart contract is forbidden” instead of a domain-specific claimable-zero message.
- `ChessContractHelper.cancelGameAndWithdraw` is deprecated; callers must now perform the withdraw step in a later transaction after the next block.
- lib tests and `computer.d.ts` were updated for the direct RPC response shape and the new block/tx lookup helpers (`txIdToBlockHeight`, `getBlockHash`, etc.).

No behavioral change for any well-formed, confirmed on-chain observation. The public contract tests now cleanly exercise the hardened determinism guarantees introduced in the preceding commits.
This change updates TBC777, chess-contracts and the corresponding tests (plus a few lib test and type surfaces) to match the lib-secret refactor that removes the double-nested `.result` indirection from `Computer.rpc`, `RestClient` and all call sites.

The RPC cleanup eliminates a long-standing source of confusion and makes the core invariant—“any successful observation against a confirmed chain prefix must be identical on every future extension”—straightforward to audit. With the noise removed, every transient or non-existent observation is now uniformly turned into an invalidation via the existing `_invalidate` path, future-height guards are direct, and confirmed-tx requirements are explicit.

Concretely:

- `TBC777`: the terminal-revision check was moved out of `EscrowAuditor.getAudit()` / `AuditResult` and into `finalWithdraw()` only. Regular paths (`getBalance`, `withdraw`, `audit`) therefore stay free of chain-tip observations. Documentation was tightened to reflect the clarified no-inflation rules and remote-root token requirements.
- Tests (TBC777, TBC777M, chess): added an explicit `mine()` helper and inserted `await mine()` after every state change that must become stable before a subsequent deterministic read. Several flows that used to be “atomic” (e.g. `cancelGameAndWithdraw`, `finalWithdraw` immediately after creation) now correctly require a block boundary.
- Error expectations updated: attempting `finalWithdraw` on a non-tip revision now surfaces the generic “Accessing non-existent on-chain state inside a smart contract is forbidden” instead of a domain-specific claimable-zero message.
- `ChessContractHelper.cancelGameAndWithdraw` is deprecated; callers must now perform the withdraw step in a later transaction after the next block.
- lib tests and `computer.d.ts` were updated for the direct RPC response shape and the new block/tx lookup helpers (`txIdToBlockHeight`, `getBlockHash`, etc.).

No behavioral change for any well-formed, confirmed on-chain observation. The public contract tests now cleanly exercise the hardened determinism guarantees introduced in the preceding commits.
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.

2 participants