From df7c41365977e641458e7125d34c5d7745b1ca12 Mon Sep 17 00:00:00 2001 From: ltardivo Date: Thu, 16 Jul 2026 17:13:57 -0700 Subject: [PATCH 1/2] Updates retype version --- retype.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retype.yml b/retype.yml index 31b7c6eda..296b0ee3e 100644 --- a/retype.yml +++ b/retype.yml @@ -3,7 +3,7 @@ output: packages/docs/.retype url: https://docs.bitcoincomputer.io/ branding: title: Bitcoin Computer - label: 0.26.0 + label: 0.27.0 favicon: static/favicon.ico footer: copyright: "© Copyright BCDB Inc. {{ year }}. All rights reserved." From 29b7e897f45797dd727e0fb7b7a70cd534d6018a Mon Sep 17 00:00:00 2001 From: ltardivo Date: Thu, 16 Jul 2026 17:35:48 -0700 Subject: [PATCH 2/2] Updates InnerComputer documentation --- packages/docs/Lib/Contract/index.md | 147 +++++++++++++++++++++------- 1 file changed, 110 insertions(+), 37 deletions(-) diff --git a/packages/docs/Lib/Contract/index.md b/packages/docs/Lib/Contract/index.md index e5a855de3..390dde632 100644 --- a/packages/docs/Lib/Contract/index.md +++ b/packages/docs/Lib/Contract/index.md @@ -74,86 +74,159 @@ expect(c.n).eq(0) ## Querying inside of a Contract -Smart contracts can access several built-in functions to explore information related to revisions, transaction outputs, trace transaction ancestry or query for balances. These functions do not modify blockchain data. Instead, they allow a contract to traverse its own revision graph, another contract's revision graph or access contextual information derived from transactions. +Smart contracts can access several built-in functions (provided by `InnerComputer`) to explore information related to revisions, transaction ancestry, on-chain state, and block metadata. These functions do not modify blockchain data. Instead, they allow a contract to traverse its own revision graph, another contract's revision graph, load modules, or access contextual information derived from transactions in a safe and deterministic way. -### Determinism rule +### Determinism and Safety Rules -The build-in functions are designed to be deterministic, ensuring that they yield consistent results across different instances of the same blockchain state. This means that given two instances of the same blockchain state, executing a contract method with the same parameters will always return the same result. +The built-in functions are designed to be **deterministic**: given two identical blockchain states and two identical Bitcoin Computer node states, a contract method invoked with the same parameters must always return the same result. -Definition +To enforce safety and determinism: + +- Accessing **non-existent on-chain state** (a revision, transaction, or module that cannot be found) is **forbidden** inside smart contracts. +- If a query function is called with malformed identifiers, or identifiers that do not correspond to actual Bitcoin Computer state, **the entire contract evaluation is invalidated**. +- Internally, a global invalid-state flag is set. After evaluation, `Db.eval` checks this flag; if set, the evaluation (and thus the transaction) is rejected. +- The flag is reset at the start of every new compartment evaluation. + +When invalidation occurs, the function throws an error with a message like: + +> "Accessing non-existent on-chain state inside a smart contract is forbidden." + +This acts as a hard safety boundary: contracts cannot silently read missing data or depend on off-chain assumptions. + +### Full API Reference + +All query functions available inside `Contract` methods (injected via the secure `InnerComputer` compartment): + +| Function | Signature | Returns | Invalidates on missing / error? | Notes | +| ----------------- | ------------------------------------------------------------- | ------------------------------------ | ------------------------------------ | ------------------------------------------------------------- | +| `sync` | `sync(location: string): Promise` | The latest object state | Yes | Deep-cloned with BigInt support | +| `decode` | `decode(txId: string): Promise` | `{ exp, env?, mod? }` metadata | Yes | Normalizes `mod` to `undefined` if absent | +| `load` | `load(location: string): Promise>` | Module exports namespace | Yes | For dynamic module loading inside contracts | +| `getAncestors` | `getAncestors(location: string): Promise` | Array of ancestor locations | Yes (on error) | Empty array `[]` if no ancestors | +| `first` | `first(rev: string): Promise` | First revision in lineage | Yes | Always returns a string for valid input | +| `prev` | `prev(rev: string): Promise` | Previous revision or `undefined` | Only on underlying error | Safe to call on tip; returns `undefined` without invalidation | +| `next` | `next(rev: string): Promise` | Next revision or throws | **Yes, including if no next exists** | Strict: absence of next **invalidates** execution | +| `last` | `last(rev: string): Promise` | Latest (tip) revision or `undefined` | Only on underlying error | Returns tip of lineage | +| `txIdToBlockTime` | `txIdToBlockTime(txId: string): Promise` | Block time as `bigint` | Yes | Requires mined Bitcoin Computer transaction | + +**Quick tip:** Use `getAncestors`, `first`, `last`, and `prev` for safe traversal. Be cautious with `next()` — it will invalidate the contract if you call it on the current tip revision. + +### Detailed Function Documentation + +#### `sync` + +Returns the latest on-chain state for the given `location` (revision identifier) as a plain JavaScript object. ```ts -Given two identical blockchain states and two identical Bitcoin Computer Node states, a contract method invoked with the same parameters must always return the same result. +sync(location: string): Promise ``` -To warrant this determinism, the functions will throw an error if they are called with invalid arguments, such as malformed revisions/transactionIds, a revision identifier that does not correspond to a Bitcoin Computer revision or a transaction ID that does not correspond to a Bitcoin Computer transaction. +- Performs a deep clone (via `stringify`/`parse` with BigInt support) so contracts receive a plain, side-effect-free object. +- If the location does not exist or cannot be synced, the evaluation is **invalidated** and an error is thrown. -### Available Functions +#### `decode` -These functions are: +Parses a Bitcoin transaction ID and returns its Bitcoin Computer metadata if it is a valid Bitcoin Computer transaction. -#### `prev` +```ts +decode(txId: string): Promise +``` -Returns the immediate previous revision of the provided revision identifier, or undefined if there is no immediate previous object. -If the provided revision identifier is not valid or does not correspond to a Bitcoin Computer revision, the full execution is invalidated and an error is thrown. +Returned shape (approximate): ```ts -prev(rev: string): Promise +{ + exp: string + env?: { [s: string]: string } + mod?: string +} ``` -#### `next` +- If `mod` is falsy in the raw transition, it is normalized to `undefined`. +- If the `txId` is malformed or does not correspond to a Bitcoin Computer transaction, the evaluation is **invalidated**. + +#### `load` -Returns the immediate next revision that follows the provided revision identifier, if any. -If the provided revision identifier is not valid, does not correspond to a Bitcoin Computer revision, or there is no next object, the full execution is invalidated and an error is thrown. +Dynamically loads a module by its specifier (location) and returns its exports. ```ts -next(rev: string): Promise +load(location: string): Promise> +``` + +- Useful for importing shared contract logic or libraries inside a contract method. +- If the module specifier is invalid or the module cannot be loaded, the evaluation is **invalidated**. + +#### `getAncestors` + +Returns the full ancestry chain for a revision/location as an array of revision identifiers. + +```ts +getAncestors(location: string): Promise ``` +- Returns `[]` if there are no ancestors. +- If the location is invalid or cannot be resolved, the evaluation is **invalidated**. +- This is the recommended safe way to traverse history without risking invalidation from `next()`. + #### `first` -Returns the first revision in the lineage of the given revision, i.e., the original revision from which it was derived. -If the provided revision identifier is not valid or does not correspond to a Bitcoin Computer revision, the full execution is invalidated and an error is thrown. +Returns the very first (root/original) revision in the lineage of the given revision. ```ts first(rev: string): Promise ``` -#### `getAncestors` +- Always returns a `string` for a valid revision. +- Invalidates the evaluation if the revision does not exist. + +#### `prev` -Returns the ancestry of a transaction identifier, describing how it was derived. -If there is no ancestor, returns an empty array. -If the provided transaction identifier is malformed, the full execution is invalidated and an error is thrown. +Returns the immediately preceding revision in the lineage, or `undefined` if the given revision is the first in its chain. ```ts -getAncestors(location: string): Promise> +prev(rev: string): Promise ``` -### `sync` +- Safe to call on any revision: if there is no previous revision, it returns `undefined` **without** invalidating the contract. +- Only invalidates on malformed input or internal retrieval errors. + +#### `next` -The `sync` the latest state for a revision, and returns the object representation of that state. If the provided revision identifier is not valid or does not correspond to a Bitcoin Computer revision, the full execution is invalidated and an error is thrown. +Returns the immediately following revision in the lineage. ```ts -sync(rev: string): Promise +next(rev: string): Promise ``` -### `decode` +- **Critical behavior**: If there is no next revision (i.e. you are at the tip of the lineage), this function **invalidates the entire contract evaluation** and throws. +- This is stricter than `prev()`. Use it only when you are certain a next revision must exist, or prefer `last()` / `getAncestors()` for safer traversal. +- Invalidates on malformed input or retrieval errors as well. + +#### `last` -Parses a Bitcoin transaction ID and returns its metadata if it is a Bitcoin Computer transaction. If the provided transaction identifier is malformed or does not correspond to a Bitcoin Computer transaction, the full execution is invalidated and an error is thrown. +Returns the most recent (tip) revision in the lineage of the given revision. ```ts -decode(txId: string) => - Promise<{ - exp: string - env?: { [s: string]: string } - mod?: string - }> +last(rev: string): Promise ``` -### `load` +- Returns the current latest revision for that object lineage. +- Only invalidates on errors retrieving the lineage; may return `undefined` in edge cases without invalidation. -Loads a module from a given module specifier. If the provided module specifier is malformed or does not correspond to a valid Bitcoin Computer module, the full execution is invalidated and an error is thrown. +#### `txIdToBlockTime` + +Returns the Unix block time (as `bigint`) at which the given transaction was included in a block. ```ts -load(location: string): Promise +txIdToBlockTime(txId: string): Promise ``` + +- Useful for time-based logic inside contracts (e.g. vesting, expiration, chess time locks). +- If the transaction is not found or has no associated block time (e.g. unmined or non-Bitcoin-Computer tx), the evaluation is **invalidated**. + +### Usage Notes & Best Practices + +1. **Prefer safe traversal methods**: Use `getAncestors()`, `first()`, `last()`, and `prev()` when exploring history. Reserve `next()` for cases where you have already verified a successor must exist. +2. **Handle `undefined`**: Several functions (`prev`, `last`, possibly `txIdToBlockTime`) can legitimately return `undefined`. Always check before using the result. + +This querying API, combined with the strict property update rules of `Contract`, enables powerful, verifiable, and safe on-chain logic while protecting the network from non-deterministic or invalid contract executions.