Skip to content

Added Anan-AS PVM Interpreter#716

Merged
tomusdrw merged 57 commits into
mainfrom
maso-ananas
Oct 26, 2025
Merged

Added Anan-AS PVM Interpreter#716
tomusdrw merged 57 commits into
mainfrom
maso-ananas

Conversation

@DrEverr

@DrEverr DrEverr commented Oct 13, 2025

Copy link
Copy Markdown
Member

Created interface fo external interpreters.
Changed HostCallRegister, HCMemory and GasCounter API.
Added Ananas as second possible backend to run services on.
Added flag --pvm to choose pvm backend for accumulate execution.
Currently supported backends: ['built-in', 'ananas'].

@coderabbitai

coderabbitai Bot commented Oct 13, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added support for multiple PVM backend implementations (BuiltIn and Ananas).
    • Introduced configurable PVM backend selection via --pvm command-line option and configuration files.
    • Enabled parallel execution of multiple interpreter engines for enhanced testing and validation.
  • Chores

    • Reorganized core VM infrastructure into separate interface and implementation packages for improved modularity.

Walkthrough

Adds a PVM backend abstraction and multiplatform PVM support across the repo. Introduces packages/core/pvm-interface and packages/core/pvm-interpreter-ananas, an IPvmInterpreter interface, and an Ananas WASM-backed interpreter implementation. Refactors the existing interpreter to implement the new interface, replaces many local gas/memory/register APIs with interface types (IGasCounter, IMemory, IRegisters, HostCallMemory, HostCallRegisters), and threads a new PvmBackend enum and CLI --pvm option through jam, importer, workers, and transition code. Accumulate and related host-calls are adapted for backend selection and async executor creation; many tests updated for multi-backend runs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • packages/core/pvm-interpreter/interpreter.ts — public API reshaping to IPvmInterpreter, new resetJam/resetGeneric, public registers/memory/gas fields.
  • packages/core/pvm-host-calls/host-calls.ts and interpreter-instance-manager.ts — migration to IPvmInterpreter, runProgram/resetJam flow, instance manager factory and async lifecycle.
  • packages/core/pvm-interpreter-ananas/index.ts — new WASM interpreter wrapper (reset/run/step/gas/registers/memory integration).
  • packages/jam/transition/accumulate/pvm-executor.ts and accumulate.ts — async factory methods, PvmBackend plumbing, createAccumulateExecutor signature changes.
  • Wide, repetitive type/import migrations (IGasCounter, HostCallMemory/HostCallRegisters, pvm-interface imports) — verify all import sources and downstream callsites.

Possibly related PRs

Suggested reviewers

  • skoszuta
  • mateuszsikora

Poem

"I’m a rabbit with a tiny drum,
Two PVMs now leap and hum.
Built-in hops, Ananas springs,
Registers, gas — delightful things.
CLI picks the backend tune — hop on, run!"

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Added Anan-AS PVM Interpreter" accurately captures the primary objective of this pull request. The changeset introduces support for the Ananas PVM interpreter as a second backend alongside the existing built-in interpreter, creates a new pvm-interface module for external interpreter abstraction, and adds command-line configuration to select between backends. The title is specific, concise, and clearly communicates the main addition without being vague or overly broad.
Description Check ✅ Passed The description is directly related to the changeset and adequately summarizes the key changes. It mentions creating an interface for external interpreters (pvm-interface), refactoring the HostCallRegister, HCMemory, and GasCounter API surfaces, adding Ananas as a backend option, introducing the --pvm flag for selection, and lists the supported backends. While the description could include more detail about scope or impact, it is sufficiently related to the actual changes in the pull request to satisfy the lenient criteria for this check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch maso-ananas

Comment @coderabbitai help to get the list of available commands and usage tips.

@DrEverr DrEverr linked an issue Oct 15, 2025 that may be closed by this pull request
@DrEverr

DrEverr commented Oct 15, 2025

Copy link
Copy Markdown
Member Author

@fluffylabs-bot benchmark

@tomusdrw tomusdrw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like a good start!

Some potential for improvements:

  1. Passing & parsing service code is probably pretty heavy and could be done asynchronously.
  2. We currently can't have multiple instances of ananas due to API restrictions. We could consider instantiating multiple WASM modules though.
  3. We should run stateTransition test vectors on both pvm backends.
  4. We might consider adding pvm backend that executes on both pvms (in parallel!) and makes sure that they yield the same results.

Comment thread bin/jam/args.test.ts Outdated
Comment thread packages/core/pvm-host-calls/host-calls.ts Outdated
Comment thread packages/core/pvm-host-calls/host-calls.ts Outdated
Comment thread packages/core/pvm-host-calls/interpreter-instance-manager.ts
Comment thread packages/core/pvm-interpreter-ananas/index.ts Outdated
Comment thread packages/jam/config-node/node-config.ts Outdated
Comment thread packages/jam/node/jam-config.ts Outdated
Comment thread packages/jam/config-node/node-config.ts Outdated
Comment thread packages/jam/transition/accumulate/accumulate.ts Outdated
Comment thread packages/jam/transition/accumulate/deferred-transfers.ts Outdated
@DrEverr

DrEverr commented Oct 26, 2025

Copy link
Copy Markdown
Member Author

@fluffylabs-bot benchmark

@fluffylabs-bot

fluffylabs-bot Bot commented Oct 26, 2025

Copy link
Copy Markdown
Contributor

Benchmark workflow triggered successfully! 🎉
Requested by: @DrEverr
PR number: #716
Target repository: FluffyLabs/typeberry-testing

🔗 Check the Actions tab for workflow progress.

@DrEverr
DrEverr marked this pull request as ready for review October 26, 2025 00:50
@DrEverr DrEverr changed the title Added Anan-as PVM Interpreter Added Anan-AS PVM Interpreter Oct 26, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 23

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
packages/jam/jam-host-calls/fetch.ts (1)

15-239: Based on the shell output and web search results:

The latest release is v0.7.1 (marked as "Latest"), not v0.7.2.

Align graypaper links to v0.7.1 (current latest version).

The code in packages/jam/jam-host-calls/fetch.ts contains references to mixed versions:

  • v0.6.6 (27 links)
  • v0.7.2 (lines 183, 208) — This version does not exist; v0.7.1 is the latest release
  • v0.6.7 (line 244)

All graypaper links in fetch.ts should reference v0.7.1, the current stable version. The references to v0.7.2 appear to be forward-references to a non-existent version and require correction.

packages/jam/jam-host-calls/externalities/refine-externalities.ts (2)

70-73: Avoid unchecked BigInt→Number cast; annotate or constrain.

Number(v) on number | bigint needs an explicit safety note or guard since BigInt→Number is lossy. Here the valid range is 0..4.

As per coding guidelines (BigInt→Number), add a comment and constrain the cast:

-export const toMemoryOperation = (v: number | bigint): MemoryOperation | null =>
-  v <= MemoryOperation.Write && v >= MemoryOperation.Void ? Number(v) : null;
+export const toMemoryOperation = (v: number | bigint): MemoryOperation | null => {
+  // Safe cast: MemoryOperation is 0..4 which fits in JS Number precisely.
+  const n = typeof v === "bigint" ? Number(v) : v;
+  return n <= MemoryOperation.Write && n >= MemoryOperation.Void ? n as MemoryOperation : null;
+}

56-68: Fix typos in documentation.

“possbile” → “possible”; “writeable” → “writable”.

-/** Types of possbile operations to request by Pages host call. */
+/** Types of possible operations to request by Pages host call. */
@@
-  /** Set given range of pages as writeable and initialize them with zeros. */
+  /** Set given range of pages as writable and initialize them with zeros. */

Also applies to: 116-118

packages/jam/jam-host-calls/refine/invoke.ts (1)

117-124: Handle Status.OK; current code throws unexpectedly.

MachineStatus allows OK, but the code throws for it. Treat it like other terminal statuses.

-    if ([Status.PANIC, Status.HALT, Status.OOG].includes(returnState.status)) {
+    if ([Status.PANIC, Status.HALT, Status.OOG, Status.OK].includes(returnState.status)) {
       regs.set(IN_OUT_REG_1, tryAsU64(returnState.status));
       return;
     }
packages/jam/transition/accumulate/pvm-executor.ts (1)

67-75: Nit: spelling.

“PVM exectutor” → “PVM executor”.

- * PVM exectutor class that prepares PVM together with host call handlers to be run in requested context
+ * PVM executor class that prepares PVM together with host call handlers to be run in requested context
packages/core/pvm-interpreter/interpreter.ts (1)

311-313: Typo in helper name.

Rename getNextIstructionIndex to getNextInstructionIndex for clarity.

-    const getNextIstructionIndex = (index: number) => index + 1 + this.mask.getNoOfBytesToNextInstruction(index + 1);
+    const getNextInstructionIndex = (index: number) =>
+      index + 1 + this.mask.getNoOfBytesToNextInstruction(index + 1);
-    for (let index = 0; index < codeLength; index = getNextIstructionIndex(index)) {
+    for (let index = 0; index < codeLength; index = getNextInstructionIndex(index)) {
♻️ Duplicate comments (2)
bin/test-runner/w3f/accumulate.ts (1)

144-149: Run both backends sequentially or gate via a flag; don’t leave Ananas commented out.

Tests should cover BuiltIn and Ananas. Run in sequence to avoid interference, or gate with an env/CLI switch.

 export async function runAccumulateTest(test: AccumulateTest, path: string) {
-  await runAccumulateInternal(test, path, PvmBackend.BuiltIn);
-  // TODO [MaSo] running separate passes the test, running both at the same time fails.
-  //
-  //await runAccumulateInternal(test, path, PVMBackend.Ananas);
+  const backend = process.env.TYPEBERRY_PVM_BACKENDS ?? 'both';
+  if (backend === 'built-in') {
+    await runAccumulateInternal(test, path, PvmBackend.BuiltIn);
+  } else if (backend === 'ananas') {
+    await runAccumulateInternal(test, path, PvmBackend.Ananas);
+  } else {
+    // run sequentially to avoid interference
+    await runAccumulateInternal(test, path, PvmBackend.BuiltIn);
+    await runAccumulateInternal(test, path, PvmBackend.Ananas);
+  }
 }
packages/core/pvm-interpreter-ananas/api.ts (1)

1-8: Raw-generated type surface is brittle; keep temporary and document.

This mirrors @fluffylabs/anan-as/raw internals (__Record.., __Internref..). It’s OK short‑term, but prone to break on generator updates. Add a prominent TODO with the linked issue and consider a thin adapter that exposes a stable, minimal API surface.

Also applies to: 10-182

🧹 Nitpick comments (27)
bin/test-runner/w3f/pvm.ts (1)

65-65: Follow-up issue needed for Ananas testing.

The TODO comment indicates that W3F PVM tests should also run on the Ananas backend. Based on the past review comments, this was discussed and deferred to a follow-up issue, but the issue doesn't appear to have been created yet.

Would you like me to open a GitHub issue to track running W3F PVM tests on both BuiltIn and Ananas interpreters?

packages/core/pvm-host-calls/host-call-registers.ts (1)

38-40: Avoid leaking internal buffer from getEncoded().

Returning this.bytes exposes mutable internal storage to callers.

Return a copy or clearly document mutability:

-  getEncoded(): Uint8Array {
-    return this.bytes;
-  }
+  getEncoded(): Uint8Array {
+    return this.bytes.slice(); // return copy to prevent external mutation
+  }

As per coding guidelines.

packages/core/pvm-interface/gas.ts (1)

25-55: Make initialGas immutable and clarify used() range.

initialGas is initialized once; make it readonly. Also specify used() is clamped to [0, initialGas] for consistency with implementations.

Proposed tweaks:

-export interface IGasCounter {
+export interface IGasCounter {
   /**
    * Set during initialization of GasCounter.
    *
    * NOTE: Needed to calculate `used()` gas.
    */
-  initialGas: Gas;
+  readonly initialGas: Gas;
@@
-  /**
-   * Calculates used gas since creation of GasCounter.
-   *
-   * NOTE: Capped to `initialGas`.
-   */
+  /**
+   * Calculates used gas since creation of GasCounter.
+   *
+   * Range: 0 … initialGas (clamped).
+   */
   used(): Gas;
 }

As per coding guidelines.

packages/jam/jam-host-calls/accumulate/assign.test.ts (1)

11-13: LGTM; align gasCounter import path for consistency

The switch to emptyRegistersBuffer and single HostCallMemory is correct. To keep imports uniform (like in gas.test.ts), consider importing gasCounter from the package root.

-import { gasCounter } from "@typeberry/pvm-interpreter/gas.js";
+import { gasCounter } from "@typeberry/pvm-interpreter";

Also applies to: 36-37, 57-60

packages/core/pvm-host-calls/host-call-memory.test.ts (1)

55-66: Verification passed; maintain optional refactoring for brittle assertions

MEMORY_SIZE is correctly exported from @typeberry/pvm-interface and properly imported in the test file. The PageFault semantics align with the runtime implementation.

The optional suggestion to reduce brittle string assertions remains valid. Replace full error message comparisons with type checks:

- deepEqual(
-   res,
-   Result.error(PageFault.fromMemoryIndex(0, true), () => "Page fault: attempted to access reserved page 0"),
- );
+ if (!res.isError) throw new Error("expected error");
+ if (!(res.error instanceof PageFault)) throw new Error("expected PageFault");

Also applies to: 105-116

packages/jam/jam-host-calls/read.ts (1)

21-25: Update graypaper link to the current version used elsewhere (v0.7.2) or confirm correctness

Host-call docs link points to v0.7.1, while related code references v0.7.2. Please align to the current spec version or confirm this section must stay at 0.7.1.

As per coding guidelines.

packages/jam/jam-host-calls/accumulate/query.test.ts (1)

52-58: Avoid BigInt→Number casts or add a safety comment

Calls like tryAsU32(Number(w7)) / tryAsU32(Number(w8)) convert U64→number without an explicative comment. Either:

  • Pass the literal constants directly (e.g., tryAsU32(2 ** 16), tryAsU32(32)), or
  • Mask to lower 32 bits and add a brief “safe because…” note, or
  • Provide a helper (e.g., getLowerU32) to avoid Number on bigint in tests.

This keeps tests aligned with the “Number(bigint) requires justification” rule.

As per coding guidelines.

Also applies to: 80-81, 105-106, 133-134, 162-163, 192-193

packages/core/pvm-host-calls/host-call-memory.ts (2)

31-34: Add explicit safety comment for Number() conversion.

Per coding guidelines, casting a bigint using Number(x) must have an explanation comment why it is safe. While the masking to 32 bits ensures the value is within safe integer range, please add an explicit comment.

As per coding guidelines.

Apply this diff:

     // NOTE: We always take lower 32 bits from register value.
     //
     // https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
+    // NOTE: It's safe to convert to number because the value is masked to 32 bits (max 0xFFFFFFFF).
     const address = tryAsU32(Number(regAddress & 0xffff_ffffn));

51-54: Add explicit safety comment for Number() conversion.

Per coding guidelines, casting a bigint using Number(x) must have an explanation comment why it is safe. While the masking to 32 bits ensures the value is within safe integer range, please add an explicit comment.

As per coding guidelines.

Apply this diff:

     // NOTE: We always take lower 32 bits from register value.
     //
     // https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
+    // NOTE: It's safe to convert to number because the value is masked to 32 bits (max 0xFFFFFFFF).
     const address = tryAsU32(Number(regAddress & 0xffff_ffffn));
packages/core/pvm-interface/pvm.ts (1)

17-19: Consider a backend-neutral method name.

resetJam leaks JAM naming into a core interface. resetProgram or reset would be clearer and backend-agnostic.

packages/jam/transition/accumulate/accumulate.ts (1)

363-371: Simplify zero-work early-return condition.

const n = transfers.length + i + reports.length; if (n === 0) { ... } is equivalent to checking both collections empty.

-    const n = transfers.length + i + reports.length;
-
-    if (n === 0) {
+    if (transfers.length === 0 && reports.length === 0) {
       return {
         accumulatedReports: tryAsU32(0),
         gasCost: tryAsServiceGas(0),
         state: stateUpdate,
       };
     }
packages/jam/transition/accumulate/accumulate.test.ts (2)

422-424: Optional: move fixture blob near top.

preimageBlob is referenced inside test bodies; moving it above the describes improves readability and avoids TDZ surprises if this file is later refactored.


22-22: Verify PvmBackendNames index mapping.

PvmBackendNames indexing by enum ordinal assumes the array order stays synchronized with enum member values. Current state: enum has exactly BuiltIn=0, Ananas=1 and array is ["built-in", "ananas"], so indices align correctly. However, if a new enum member is added or members reordered, the array indexing breaks silently. Deriving the mapping from the enum using a Record<PvmBackend, string> pattern would provide compile-time safety—TypeScript would error if enum changes without updating the Record.

packages/jam/jam-host-calls/accumulate/solicit.test.ts (1)

8-10: Align gas import path with other tests.

This imports gasCounter from "@typeberry/pvm-interpreter/gas.js" while lookup.test.ts imports from "@typeberry/pvm-interpreter". Standardize on one.

packages/jam/transition/accumulate/pvm-executor.ts (1)

87-89: Pool size is magic.

prepareBackend hardcodes pool size 4. Consider making it a parameter with a sensible default and documenting the rationale (CPU cores, throughput vs memory).

-  private static async prepareBackend(pvm: PvmBackend) {
-    return PvmInstanceManager.new(4, pvm);
+  private static async prepareBackend(pvm: PvmBackend, poolSize = 4) {
+    return PvmInstanceManager.new(poolSize, pvm);
   }
packages/jam/jam-host-calls/lookup.test.ts (1)

8-11: Unify gas import path across test files for consistency.

The codebase inconsistently imports gasCounter—some files use "@typeberry/pvm-interpreter" (e.g., lookup.test.ts) while others use "@typeberry/pvm-interpreter/gas.js" (e.g., solicit.test.ts). Pick one canonical import path and apply it consistently across all test files to avoid duplicate bundles at build time.

packages/core/pvm-host-calls/bin.ts (1)

29-29: Minor: drop the IIFE; use TLA consistently.

Since you already use TLA above, you can await runProgram at top level and simplify.

- (async () => {
-   await pvmHostCallExtension.runProgram(program, args, 5, tryAsGas(1000));
- })();
+await pvmHostCallExtension.runProgram(program, args, 5, tryAsGas(1000));
packages/jam/jam-host-calls/accumulate/eject.test.ts (1)

8-11: Import migration to pvm-interface and utils — OK; consider consolidating gasCounter import.

The move to tryAsGas from @typeberry/pvm-interface and emptyRegistersBuffer is correct. Optionally, import gasCounter from the package root for consistency with other tests.

-import { MemoryBuilder } from "@typeberry/pvm-interpreter";
-import { gasCounter } from "@typeberry/pvm-interpreter/gas.js";
+import { gasCounter, MemoryBuilder } from "@typeberry/pvm-interpreter";

Also applies to: 18-18

packages/core/pvm-host-calls/interpreter-instance-manager.ts (3)

15-33: Async factory is the right shape; add basic parameter validation.

new() now awaits backends (incl. Ananas) — good. Validate noOfPvmInstances >= 1 to fail fast on misconfiguration.

 static async new(noOfPvmInstances: number, interpreter: PvmBackend): Promise<InterpreterInstanceManager> {
+  if (noOfPvmInstances < 1) {
+    throw new Error(`noOfPvmInstances must be >= 1 (got ${noOfPvmInstances})`);
+  }
   const instances: IPvmInterpreter[] = [];
   for (let i = 0; i < noOfPvmInstances; i++) {
     switch (interpreter) {

36-44: Nit: avoid Promise.resolve in async function.

Just return instance; — async will wrap it. Keeps code tidy.

-  if (instance !== undefined) {
-    return Promise.resolve(instance);
-  }
+  if (instance !== undefined) {
+    return instance;
+  }

9-9: Leftover TODO label.

Either remove the TODO or open a tracking issue and reference it.

I can open a tracking issue for removal once the dual-backend path fully lands.

bin/test-runner/w3f/accumulate.ts (1)

168-169: Typo in failure message.

“successfull” → “successful”.

-    assert.fail(`Expected successfull accumulation for ${PvmBackendNames[pvm]}, got: ${result}`);
+    assert.fail(`Expected successful accumulation for ${PvmBackendNames[pvm]}, got: ${result}`);
packages/core/pvm-interpreter/memory/errors.ts (1)

7-23: PageFault construction semantics: modulo wrap and default flag.

  • Using maybeMemoryIndex % MEMORY_SIZE wraps negatives and OOB indices; this may mask true OOB faults. Confirm intended behavior vs. reporting the actual offending address.
  • Private ctor defaults isAccessFault = true, but both factories default to false; effectively all faults created via factories are not access faults. Confirm this is deliberate.

If wrap is unintended, prefer validation and mapping to the start page without %:

-    const memoryIndex = tryAsMemoryIndex(maybeMemoryIndex % MEMORY_SIZE);
+    const memoryIndex = tryAsMemoryIndex(maybeMemoryIndex);

If you need clamping (not wrapping), clamp instead of modulo and add a short comment.

packages/core/pvm-interpreter-ananas/index.ts (2)

153-159: Status mapping needs rationale.

status < 0 => Status.OK is non-obvious. Add a short comment referencing Ananas status encoding or guard only for a known sentinel.


165-167: Exit param should be null unless HOST/FAULT.

Interface docs imply the exit arg is meaningful only on HOST/FAULT. Consider returning null otherwise.

-  getExitParam(): U32 | null {
-    return tryAsU32(this.instance.getExitArg());
-  }
+  getExitParam(): U32 | null {
+    const s = this.getStatus();
+    if (s !== Status.HOST && s !== Status.FAULT) return null;
+    return tryAsU32(this.instance.getExitArg());
+  }
bin/pvm/index.ts (2)

29-30: Gas prints may be unreadable.

gas.get() returns an opaque Gas. Convert to BigInt for consistent output.

-  console.info(`Gas: 🫐 ${pvmTb.gas.get()}| 🍍 ${pvmAnanas.gas.get()}`);
+  console.info(`Gas: 🫐 ${BigInt(pvmTb.gas.get())} | 🍍 ${BigInt(pvmAnanas.gas.get())}`);

And same for the final log.

Also applies to: 46-47


21-39: Stepping loop semantics OK for demo; consider run-to-yield for Ananas.

For performance, you can use runProgram() on Ananas (it already batches with nSteps(INF)), then advance TB until yield to reduce JS↔WASM thrash.

Comment thread bin/test-runner/w3f/accumulate.ts Outdated
Comment thread package.json
Comment thread packages/core/pvm-host-calls/host-call-registers.ts Outdated
Comment thread packages/core/pvm-host-calls/host-call-registers.ts Outdated
Comment thread packages/core/pvm-host-calls/host-call-registers.ts Outdated
Comment thread packages/jam/jam-host-calls/refine/invoke.ts
Comment thread packages/jam/node/jam-config.ts Outdated
Comment thread packages/jam/transition/accumulate/accumulate.test.ts
Comment thread packages/jam/transition/accumulate/pvm-executor.ts
Comment thread packages/workers/importer/protocol.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/jam/transition/accumulate/deferred-transfers.ts (1)

75-77: Comparator may return BigInt — risk of TypeError in sort.

If source is a U64/bigint, a.source - b.source yields BigInt; engines compare against 0 (Number) internally, which can throw. Use relational compare returning Number.

-        .toSorted((a, b) => a.source - b.source);
+        .toSorted((a, b) => (a.source < b.source ? -1 : a.source > b.source ? 1 : 0));
packages/jam/jam-host-calls/refine/invoke.test.ts (1)

56-56: Add safety note for bigint→Number cast.

const addressAsNumber = Number(address); converts U64 to Number; add a short comment explaining why it’s safe (address is bounded to 32‑bit memory index).

As per coding guidelines.

Suggested change:

-  const addressAsNumber = Number(address);
+  // Safe: addresses are constrained to 32-bit memory indices in tests, well within JS Number precision.
+  const addressAsNumber = Number(address);
♻️ Duplicate comments (1)
packages/core/pvm-interpreter-ananas/api.ts (1)

1-8: Interface breadth tightly couples to raw WASM types.

Prefer narrowing to the minimal surface used by our wrapper to reduce churn when raw types change. I see this was already raised and tracked.

Also applies to: 10-182

🧹 Nitpick comments (18)
bin/jam/args.ts (1)

86-97: Avoid as conversion by using explicit switch statement.

The as PvmBackend cast on line 92 violates the coding guideline requiring tryAs methods instead of as conversions. Although the cast is safe due to the indexOf validation, an explicit switch statement would eliminate the cast entirely and improve type safety.

As per coding guidelines.

Apply this diff to replace the indexOf approach with an explicit switch:

  const { pvm } = parseStringOption(
    args,
    "pvm",
    (v) => {
-     const pvm = PvmBackendNames.indexOf(v);
-     if (pvm >= 0) {
-       return pvm as PvmBackend;
-     }
-     throw Error(`Use one of ${PvmBackendNames.join(", ")}`);
+     switch (v) {
+       case "built-in":
+         return PvmBackend.BuiltIn;
+       case "ananas":
+         return PvmBackend.Ananas;
+       default:
+         throw Error(`Use one of ${PvmBackendNames.join(", ")}`);
+     }
    },
    NODE_DEFAULTS.pvm,
  );
packages/jam/node/jam-config.ts (1)

26-39: Consider consistent naming between parameter and field.

The method parameter is named nodeBackend (line 26, 34) but is stored as the field pvmBackend (line 50). While the field naming was correctly updated based on past review comments, using consistent naming throughout would improve clarity.

Apply this diff to align parameter naming with the field:

   static new({
     isAuthoring,
     nodeName,
     nodeConfig,
-    nodeBackend,
+    pvmBackend,
     devConfig = null,
     networkConfig = null,
     ancestry = [],
   }: {
     isAuthoring?: boolean;
     nodeName: string;
     nodeConfig: NodeConfiguration;
-    nodeBackend: PvmBackend;
+    pvmBackend: PvmBackend;
     devConfig?: DevConfig | null;
     networkConfig?: NetworkConfig | null;
     ancestry?: [HeaderHash, TimeSlot][];
   }) {
-    return new JamConfig(isAuthoring ?? false, nodeName, nodeConfig, nodeBackend, devConfig, networkConfig, ancestry);
+    return new JamConfig(isAuthoring ?? false, nodeName, nodeConfig, pvmBackend, devConfig, networkConfig, ancestry);
   }
packages/jam/jam-host-calls/info.test.ts (1)

23-23: Test hermeticity: avoid shared gas counter across tests.

Minor: create const gas = gasCounter(tryAsGas(0)) per test to prevent accidental state coupling in future changes.

packages/jam/jam-host-calls/externalities/refine-externalities.ts (1)

71-73: Avoid Number(BigInt) cast; return enum safely without casts.

Comply with guideline on bigint->number casts and eliminate need for as.

-export const toMemoryOperation = (v: number | bigint): MemoryOperation | null =>
-  v <= MemoryOperation.Write && v >= MemoryOperation.Void ? Number(v) : null;
+export const toMemoryOperation = (v: number | bigint): MemoryOperation | null => {
+  if (typeof v === "bigint") {
+    if (v === 0n) return MemoryOperation.Void;
+    if (v === 1n) return MemoryOperation.ZeroRead;
+    if (v === 2n) return MemoryOperation.ZeroWrite;
+    if (v === 3n) return MemoryOperation.Read;
+    if (v === 4n) return MemoryOperation.Write;
+    return null;
+  }
+  switch (v) {
+    case MemoryOperation.Void:
+    case MemoryOperation.ZeroRead:
+    case MemoryOperation.ZeroWrite:
+    case MemoryOperation.Read:
+    case MemoryOperation.Write:
+      return v;
+    default:
+      return null;
+  }
+}

As per coding guidelines.

packages/core/pvm-debugger-adapter/debugger-adapter.ts (1)

46-48: Handle memory write Result to avoid silent faults

memory.storeFrom(...) returns a Result; ignoring it may mask page faults in the debugger. Either unwrap and throw, or propagate an explicit error to the UI.

-  this.pvm.memory.storeFrom(tryAsMemoryIndex(address), value);
+  const r = this.pvm.memory.storeFrom(tryAsMemoryIndex(address), value);
+  // TODO: surface PageFault details in debugger instead of silently ignoring
+  // if (r.isError?.()) throw r.error; // adjust to your Result API
packages/jam/jam-host-calls/accumulate/yield.test.ts (1)

8-10: Imports and test helpers: LGTM; avoid shared gas across tests

  • Interface/import shifts and use of emptyRegistersBuffer() and direct HostCallMemory are good.
  • Consider creating a fresh gasCounter(tryAsGas(0)) per test to avoid state leakage if gas is mutated.
-const gas = gasCounter(tryAsGas(0));
+// In each test:
+const gas = gasCounter(tryAsGas(0));

Also applies to: 13-14, 25-37

packages/core/pvm-interpreter/memory/errors.ts (1)

19-23: Optional: normalize negative indices before modulo

If negatives can reach fromMemoryIndex, (x % MEMORY_SIZE) is negative in JS. Either rely on tryAsMemoryIndex throwing (current behavior) or normalize explicitly.

-const memoryIndex = tryAsMemoryIndex(maybeMemoryIndex % MEMORY_SIZE);
+const idx = ((maybeMemoryIndex % MEMORY_SIZE) + MEMORY_SIZE) % MEMORY_SIZE;
+const memoryIndex = tryAsMemoryIndex(idx);
bin/test-runner/w3f/pvm.ts (1)

65-65: Track TODO for dual-backend testing.

This TODO aligns with past review discussions about running PVM tests on both Ananas and BuiltIn backends. Based on PR comments, a follow-up issue was requested to implement both PVM backends for w3f/pvm tests.

Would you like me to verify if a GitHub issue has been created to track this work, or help draft one?

packages/core/pvm-interpreter/interpreter.ts (1)

136-160: Avoid reassigning gas object after making it readonly.

After the change above, update resetGeneric to set the private field.

-    this.gas = gasCounter(gas);
+    this._gas = gasCounter(gas);

Optionally, expose a reset(initialGas) on the counter to reuse the instance and avoid reallocations.

packages/core/pvm-host-calls/interpreter-instance-manager.ts (2)

36-44: Tiny nit: avoid Promise.resolve in async function.

You can just return instance; here.

-      return Promise.resolve(instance);
+      return instance;

46-53: Release path OK. Consider FIFO for fairness.

Optional: using a queue (shift from instances) can distribute wear on instances more evenly.

packages/core/pvm-host-calls/bin.ts (1)

8-8: Avoid hard-coding the backend; allow switching via env/CLI.

Makes benchmarking Ananas vs BuiltIn trivial without code edits.

Apply:

-import { PvmBackend } from "@typeberry/config";
+import { PvmBackend } from "@typeberry/config";
+const pickBackend = () =>
+  (process.env.PVM_BACKEND?.toLowerCase() === "ananas" ? PvmBackend.Ananas : PvmBackend.BuiltIn);
 ...
-const pvmInstanceManager = await InterpreterInstanceManager.new(1, PvmBackend.BuiltIn);
+const pvmInstanceManager = await InterpreterInstanceManager.new(1, pickBackend());
bin/pvm/index.ts (1)

41-41: Guard against OOB access when printing the last instruction.

Prevents undefined when i === instructions.length.

-console.info(`Instruction ${i}: ${instructions[i]}`);
+const last = instructions[i] ?? "<end>";
+console.info(`Instruction ${i}: ${last}`);
packages/core/pvm-interpreter-ananas/index.ts (4)

134-141: Avoid magic numbers for register layout.

Use the imported constants for clarity and future‑proofing.

-  const emptyRegisters = Array(13 * 8).fill(0);
+  const emptyRegisters = Array(NO_OF_REGISTERS * REGISTER_BYTE_SIZE).fill(0);

91-99: Use 0n when comparing bigint.

Keeps types consistent and avoids accidental number/bigint mixing.

-  if (gasConsumed < 0) {
+  if (gasConsumed < 0n) {

39-43: Optional: assert 8‑byte alignment before creating BigUint64Array.

Defensive check to prevent accidental misaligned views.

  getAllU64(): BigUint64Array {
    const bytes = this.getAllEncoded();
-   return new BigUint64Array(bytes.buffer, bytes.byteOffset);
+   check`${bytes.byteOffset % REGISTER_BYTE_SIZE === 0} Unaligned register buffer.`;
+   return new BigUint64Array(bytes.buffer, bytes.byteOffset);
  }

170-177: Minor: simplify byte lowering.

Array.from is clearer and V8 optimizes it well.

-function lowerBytes(data: Uint8Array): number[] {
-  const r = new Array<number>(data.length);
-  for (let i = 0; i < data.length; i++) {
-    r[i] = data[i];
-  }
-  return r;
-}
+function lowerBytes(data: Uint8Array): number[] {
+  return Array.from(data);
+}
packages/jam/transition/accumulate/pvm-executor.ts (1)

87-89: Make instance pool size configurable.

Expose via parameter or ChainSpec to tune throughput vs memory.

-  private static async prepareBackend(pvm: PvmBackend) {
-    return PvmInstanceManager.new(4, pvm);
-  }
+  private static async prepareBackend(pvm: PvmBackend, poolSize = 4) {
+    return PvmInstanceManager.new(poolSize, pvm);
+  }

Comment thread bin/jam/args.test.ts Outdated
Comment thread package.json
Comment thread packages/core/pvm-host-calls/host-call-memory.ts
Comment thread packages/core/pvm-host-calls/host-call-memory.ts Outdated
Comment thread packages/core/pvm-host-calls/host-call-registers.ts Outdated
Comment thread packages/core/pvm-interpreter/gas.ts
Comment thread packages/core/pvm-interpreter/interpreter.ts
Comment thread packages/jam/jam-host-calls/refine/invoke.test.ts
Comment thread packages/jam/transition/accumulate/accumulate.ts
Comment thread packages/workers/importer/protocol.ts
Comment thread bin/test-runner/w3f/pvm.ts Outdated
@github-actions

Copy link
Copy Markdown
View all
File Benchmark Ops
bytes/hex-from.ts[0] parse hex using Number with NaN checking 122295.63 ±3.75% 85.83% slower
bytes/hex-from.ts[1] parse hex from char codes 862942.36 ±0.63% fastest ✅
bytes/hex-from.ts[2] parse hex from string nibbles 526039.4 ±0.6% 39.04% slower
math/add_one_overflow.ts[0] add and take modulus 202828272.98 ±9.62% 22.16% slower
math/add_one_overflow.ts[1] condition before calculation 260558822.02 ±6.51% fastest ✅
math/count-bits-u32.ts[0] standard method 102555362 ±2.33% 59.86% slower
math/count-bits-u32.ts[1] magic 255505617.08 ±5.96% fastest ✅
hash/index.ts[0] hash with numeric representation 187.92 ±0.43% 17.92% slower
hash/index.ts[1] hash with string representation 119.4 ±0.37% 47.85% slower
hash/index.ts[2] hash with symbol representation 179.49 ±1.91% 21.61% slower
hash/index.ts[3] hash with uint8 representation 155.4 ±0.45% 32.13% slower
hash/index.ts[4] hash with packed representation 228.96 ±0.38% fastest ✅
hash/index.ts[5] hash with bigint representation 179.3 ±0.49% 21.69% slower
hash/index.ts[6] hash with uint32 representation 199.65 ±0.41% 12.8% slower
collections/map-set.ts[0] 2 gets + conditional set 106893.83 ±0.43% fastest ✅
collections/map-set.ts[1] 1 get 1 set 59717.82 ±0.38% 44.13% slower
codec/bigint.compare.ts[0] compare custom 246759784.59 ±7.41% fastest ✅
codec/bigint.compare.ts[1] compare bigint 236505118.28 ±7.19% 4.16% slower
bytes/hex-to.ts[0] number toString + padding 303131.13 ±0.35% fastest ✅
bytes/hex-to.ts[1] manual 15557.59 ±0.29% 94.87% slower
codec/bigint.decode.ts[0] decode custom 197995000.5 ±5.55% fastest ✅
codec/bigint.decode.ts[1] decode bigint 102385530.59 ±2.61% 48.29% slower
logger/index.ts[0] console.log with string concat 8047497.09 ±32% fastest ✅
logger/index.ts[1] console.log with args 768630.42 ±93.23% 90.45% slower
codec/encoding.ts[0] manual encode 2032268.17 ±4.83% 20.85% slower
codec/encoding.ts[1] int32array encode 2434916.67 ±1.64% 5.16% slower
codec/encoding.ts[2] dataview encode 2567528.32 ±1.01% fastest ✅
codec/decoding.ts[0] manual decode 12592511.39 ±1.17% 92.92% slower
codec/decoding.ts[1] int32array decode 177914950.44 ±5.22% fastest ✅
codec/decoding.ts[2] dataview decode 176215928.89 ±4.25% 0.95% slower
math/count-bits-u64.ts[0] standard method 2641787.93 ±5.19% 97.1% slower
math/count-bits-u64.ts[1] magic 91049203.77 ±1.49% fastest ✅
math/mul_overflow.ts[0] multiply and bring back to u32 253871632.82 ±6.75% fastest ✅
math/mul_overflow.ts[1] multiply and take modulus 247881947.2 ±6.6% 2.36% slower
math/switch.ts[0] switch 216982065.39 ±7.18% 8.68% slower
math/switch.ts[1] if 237599646.44 ±7.33% fastest ✅
codec/view_vs_object.ts[0] Get the first field from Decoded 384813.17 ±1.18% fastest ✅
codec/view_vs_object.ts[1] Get the first field from View 69600.04 ±4.63% 81.91% slower
codec/view_vs_object.ts[2] Get the first field as view from View 79270.3 ±1.78% 79.4% slower
codec/view_vs_object.ts[3] Get two fields from Decoded 328693.58 ±6.09% 14.58% slower
codec/view_vs_object.ts[4] Get two fields from View 56667.44 ±4.37% 85.27% slower
codec/view_vs_object.ts[5] Get two fields from materialized from View 133327.69 ±1.12% 65.35% slower
codec/view_vs_object.ts[6] Get two fields as views from View 55558.49 ±4.92% 85.56% slower
codec/view_vs_object.ts[7] Get only third field from Decoded 369007.96 ±1.21% 4.11% slower
codec/view_vs_object.ts[8] Get only third field from View 78262.34 ±1.37% 79.66% slower
codec/view_vs_object.ts[9] Get only third field as view from View 72946.69 ±1% 81.04% slower
codec/view_vs_collection.ts[0] Get first element from Decoded 24817.28 ±3.71% 59.33% slower
codec/view_vs_collection.ts[1] Get first element from View 61016.64 ±1.83% fastest ✅
codec/view_vs_collection.ts[2] Get 50th element from Decoded 26388.13 ±1.64% 56.75% slower
codec/view_vs_collection.ts[3] Get 50th element from View 29192.93 ±2.12% 52.16% slower
codec/view_vs_collection.ts[4] Get last element from Decoded 22710.53 ±2.73% 62.78% slower
codec/view_vs_collection.ts[5] Get last element from View 17819.23 ±3.51% 70.8% slower
bytes/compare.ts[0] Comparing Uint32 bytes 19519.97 ±1.67% 4.05% slower
bytes/compare.ts[1] Comparing raw bytes 20343.59 ±4.25% fastest ✅
collections/map_vs_sorted.ts[0] Map 301689.2 ±4.47% fastest ✅
collections/map_vs_sorted.ts[1] Map-array 98754.43 ±0.62% 67.27% slower
collections/map_vs_sorted.ts[2] Array 40316.02 ±4.85% 86.64% slower
collections/map_vs_sorted.ts[3] SortedArray 192262.76 ±0.54% 36.27% slower
hash/blake2b.ts[0] our hasher 2.07 ±2.85% fastest ✅
hash/blake2b.ts[1] blake2b js 0.05 ±3.19% 97.58% slower
crypto/ed25519.ts[0] native crypto 5.01 ±20.56% 82.83% slower
crypto/ed25519.ts[1] wasm lib 10.7 ±0.51% 63.33% slower
crypto/ed25519.ts[2] wasm lib batch 29.18 ±0.92% fastest ✅

Benchmarks summary: 63/63 OK ✅

@tomusdrw
tomusdrw enabled auto-merge (squash) October 26, 2025 10:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/jam/jam-host-calls/fetch.ts (1)

269-272: Fix numeric bound comment (2^32) and optional clarity on conversion.

The comment should reference 2^32, not 2*32. Suggest tightening the note.

-    // NOTE: casting to `Number` is safe in both places, since we are always bounded
-    // by the actual length of the value returned which is smaller than `2*32`.
+    // NOTE: casting to Number is safe: indices are bounded by the actual value length,
+    // which is strictly less than 2^32 (TypedArray index range).

Optionally, you can self-document the 32-bit bound:

-    const chunk = value === null ? new Uint8Array() : value.raw.subarray(Number(offset), Number(offset + length));
+    const start = Number(offset);
+    const end = Number(offset + length);
+    const chunk = value === null ? new Uint8Array() : value.raw.subarray(start, end);
♻️ Duplicate comments (7)
packages/jam/transition/accumulate/pvm-executor.ts (1)

80-84: Critical: HostCalls constructor contract still violated — issue from past review not resolved.

The past review correctly identified that HostCalls expects two parameters (pvmInstanceManager, hostCallsManager), but lines 80-83 still pass an object config. Per the constructor signature in the relevant code snippets, you must first instantiate HostCallsManager with the config object, then pass both the manager and pvmInstanceManager to HostCalls.

Apply this diff to fix the constructor call:

+    const hostCallsManager = new HostCallsManager({
+      missing: new Missing(),
+      handlers: hostCallHandlers,
+    });
-    this.hostCalls = new HostCalls({
-      missing: new Missing(),
-      handlers: hostCallHandlers,
-    });
+    this.hostCalls = new HostCalls(pvmInstanceManager, hostCallsManager);
     this.pvm = new PvmHostCallExtension(pvmInstanceManager, this.hostCalls);

You'll also need to add HostCallsManager to the imports on line 30.

packages/core/pvm-interpreter-ananas/index.ts (1)

137-144: Replace magic number with constants.

Line 139 uses the magic number Array(13 * 8).fill(0) instead of the exported constants NO_OF_REGISTERS * REGISTER_BYTE_SIZE.

As per coding guidelines.

Apply this diff:

   resetGeneric(program: Uint8Array, _pc: number, gas: Gas): void {
     const programArr = lowerBytes(program);
-    const emptyRegisters = Array(13 * 8).fill(0);
+    const emptyRegisters = Array(NO_OF_REGISTERS * REGISTER_BYTE_SIZE).fill(0);
     const pageMap = new Uint8Array();
     const chunks = new Uint8Array();
     this.gas.initialGas = gas;
     this.instance.resetGenericWithMemory(programArr, emptyRegisters, pageMap, chunks, BigInt(gas), false);
   }
packages/core/pvm-interpreter/gas.ts (1)

34-43: Fix BigInt comparison bug and incorrect logic.

Line 38 compares a bigint (gasConsumed) to the number 0, which will throw a TypeError at runtime. Additionally, the logic is incorrect: when current gas exceeds initial gas (negative consumption), used() should return 0, not initialGas.

Apply this diff:

  used(): Gas {
-   const gasConsumed = tryAsU64(this.initialGas) - this.gas;
-
-   // In we have less than zero left we assume that all gas has been consumed.
-   if (gasConsumed < 0) {
-     return this.initialGas;
-   }
-
-   return tryAsGas(gasConsumed);
+   const init = tryAsU64(this.initialGas);
+   // Clamp to [0, initialGas]
+   if (this.gas >= init) {
+     return tryAsGas(0n);
+   }
+   return tryAsGas(init - this.gas);
  }
packages/core/pvm-interface/memory.ts (1)

7-7: Address the PAGE_SIZE_SHIFT duplication flagged in past review.

A previous review identified that PAGE_SIZE_SHIFT is duplicated between this file and packages/core/pvm-interpreter/memory/memory-consts.ts (line 4). The constant should be exported from this interface file to establish a single source of truth, then imported by the interpreter implementation.

packages/core/pvm-host-calls/interpreter-instance-manager.ts (1)

9-10: Document Ananas concurrency constraints near this class.

Add a brief note that Ananas must not run concurrently; this manager intentionally serializes access.

-// TODO [MaSo] Delete this & also make host calls independent from intepreters.
+// TODO [MaSo] Delete this & make host calls independent from interpreters.
+// NOTE: Ananas backend must not be instantiated/run concurrently. This manager
+// serializes access (pool size = 1) to prevent parallel usage.
packages/core/pvm-host-calls/host-call-memory.ts (2)

19-22: Add explicit safety justification for Number() cast on bigint.

The comment explains that the lower 32 bits are taken but doesn't explicitly state why the Number() conversion is safe. Per coding guidelines, bigint-to-Number casts require a safety explanation.

The mask 0xffff_ffffn ensures the value is ≤ 0xFFFFFFFF (2³²-1), which is well within JavaScript's safe integer range (2⁵³-1), making the Number() conversion safe.

Apply this diff:

     // NOTE: We always take lower 32 bits from register value.
     //
     // https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
+    // Safe to convert to Number: masking to 32 bits guarantees value ≤ 2^32-1, within JS safe integer range.
     const address = tryAsU32(Number(regAddress & 0xffff_ffffn));

As per coding guidelines.


37-40: Add explicit safety justification for Number() cast on bigint.

The comment mentions "it's safe" but doesn't explain why. Per coding guidelines, bigint-to-Number casts require explicit safety reasoning.

Apply this diff:

     // https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
     //
-    // NOTE we are taking the the lower U32 part of the register, hence it's safe.
+    // NOTE: We take the lower U32 part of the register (masked to 32 bits).
+    // Safe to convert to Number: value ≤ 2^32-1, within JS safe integer range.
     const address = tryAsU32(Number(regAddress & 0xffff_ffffn));

As per coding guidelines.

🧹 Nitpick comments (6)
packages/core/pvm-interpreter-ananas/index.ts (3)

23-24: TODO: Track WASM inlining implementation.

The TODO comment indicates this WASM file loading approach is temporary. Consider tracking this technical debt.

Would you like me to create an issue to track the implementation of WASM file inlining for the final build?


96-104: Add comment explaining negative gasConsumed handling.

The check for negative gasConsumed at lines 99-100 handles an edge case where set() might have been called with a value exceeding initialGas. Since this is non-obvious, add a brief comment explaining why this defensive check is necessary.

Apply this diff:

   used(): Gas {
     const gasConsumed = BigInt(this.initialGas) - BigInt(this.get());
 
+    // Handle edge case where set() was called with value > initialGas
     if (gasConsumed < 0) {
       return this.initialGas;
     }

156-163: Document why negative status maps to Status.OK.

The logic at lines 158-160 returns Status.OK when the status is negative, but there's no explanation for why Ananas returns negative status values or what they represent. Add a comment explaining this Ananas-specific behavior.

Apply this diff:

   getStatus(): Status {
     const status = this.instance.getStatus();
+    // Ananas returns negative status values to indicate [TODO: explain what negative means]
     if (status < 0) {
       return Status.OK;
     }
packages/jam/jam-host-calls/fetch.ts (3)

278-282: Trace log for null value.

When value is null, the trace prints undefined. Consider logging an explicit sentinel for consistency with HostCallResult.NONE.

-    logger.trace`FETCH(${kind}) <- ${value?.toStringTruncated()}`;
+    logger.trace`FETCH(${kind}) <- ${value ? value.toStringTruncated() : 'NONE'}`;

284-379: getValue type update LGTM; optional readability refactor.

Type change to HostCallRegisters is consistent. Optionally, convert the if‑chain to a switch (kind) for readability; no behavior change needed.


382-403: Duplicate enum values: add a note to avoid confusion.

Sharing values between legacy and new variants (14, 15) is intentional due to GP version gating. Add a brief comment explaining the aliasing and the Compatibility.isGreaterOrEqual(V0_7_1) guard.

 export enum FetchKind {
@@
-  LegacyAllOperands = 14,
-  AllTransfersAndOperands = 14,
+  // 14: legacy/new alias; gated by GP >= 0.7.1
+  LegacyAllOperands = 14,
+  AllTransfersAndOperands = 14,
@@
-  LegacyOneOperand = 15,
-  OneTransferOrOperand = 15,
+  // 15: legacy/new alias; gated by GP >= 0.7.1
+  LegacyOneOperand = 15,
+  OneTransferOrOperand = 15,
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5d4d25 and b37c58b.

📒 Files selected for processing (61)
  • bin/jam/args.test.ts (3 hunks)
  • bin/jam/build-for-npm.sh (2 hunks)
  • bin/jam/index.ts (1 hunks)
  • bin/rpc/test/e2e-setup.ts (1 hunks)
  • bin/tci/index.test.ts (1 hunks)
  • bin/tci/index.ts (1 hunks)
  • bin/test-runner/w3f/accumulate.ts (3 hunks)
  • bin/test-runner/w3f/pvm.ts (2 hunks)
  • bin/test-runner/w3f/runners.ts (2 hunks)
  • packages/README.md (2 hunks)
  • packages/core/pvm-debugger-adapter/index.ts (2 hunks)
  • packages/core/pvm-host-calls/bin.ts (1 hunks)
  • packages/core/pvm-host-calls/host-call-handler.ts (3 hunks)
  • packages/core/pvm-host-calls/host-call-memory.test.ts (5 hunks)
  • packages/core/pvm-host-calls/host-call-memory.ts (1 hunks)
  • packages/core/pvm-host-calls/host-call-registers.test.ts (1 hunks)
  • packages/core/pvm-host-calls/host-call-registers.ts (1 hunks)
  • packages/core/pvm-host-calls/host-calls-manager.ts (2 hunks)
  • packages/core/pvm-host-calls/host-calls.ts (7 hunks)
  • packages/core/pvm-host-calls/index.ts (1 hunks)
  • packages/core/pvm-host-calls/interpreter-instance-manager.ts (2 hunks)
  • packages/core/pvm-interface/gas.ts (1 hunks)
  • packages/core/pvm-interface/memory.ts (1 hunks)
  • packages/core/pvm-interpreter-ananas/index.ts (1 hunks)
  • packages/core/pvm-interpreter-ananas/package.json (1 hunks)
  • packages/core/pvm-interpreter/gas.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/assign.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/bless.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/checkpoint.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/designate.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/eject.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/forget.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/new.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/provide.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/query.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/solicit.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/transfer.ts (3 hunks)
  • packages/jam/jam-host-calls/accumulate/upgrade.ts (2 hunks)
  • packages/jam/jam-host-calls/accumulate/yield.ts (2 hunks)
  • packages/jam/jam-host-calls/externalities/refine-externalities.test.ts (4 hunks)
  • packages/jam/jam-host-calls/externalities/refine-externalities.ts (6 hunks)
  • packages/jam/jam-host-calls/fetch.ts (3 hunks)
  • packages/jam/jam-host-calls/gas.ts (2 hunks)
  • packages/jam/jam-host-calls/info.ts (2 hunks)
  • packages/jam/jam-host-calls/log.ts (2 hunks)
  • packages/jam/jam-host-calls/lookup.ts (2 hunks)
  • packages/jam/jam-host-calls/missing.ts (2 hunks)
  • packages/jam/jam-host-calls/read.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/export.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/expunge.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/historical-lookup.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/invoke.ts (5 hunks)
  • packages/jam/jam-host-calls/refine/machine.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/pages.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/peek.ts (2 hunks)
  • packages/jam/jam-host-calls/refine/poke.ts (2 hunks)
  • packages/jam/jam-host-calls/utils.ts (3 hunks)
  • packages/jam/jam-host-calls/write.ts (2 hunks)
  • packages/jam/node/jam-config.ts (3 hunks)
  • packages/jam/transition/accumulate/pvm-executor.ts (4 hunks)
  • packages/workers/importer/protocol.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (24)
  • packages/README.md
  • bin/jam/index.ts
  • bin/jam/build-for-npm.sh
  • packages/jam/jam-host-calls/accumulate/forget.ts
  • packages/workers/importer/protocol.ts
  • packages/jam/jam-host-calls/refine/historical-lookup.ts
  • packages/jam/jam-host-calls/refine/expunge.ts
  • packages/jam/jam-host-calls/externalities/refine-externalities.ts
  • packages/core/pvm-interpreter-ananas/package.json
  • packages/core/pvm-debugger-adapter/index.ts
  • packages/core/pvm-interface/gas.ts
  • packages/jam/jam-host-calls/refine/export.ts
  • packages/jam/jam-host-calls/log.ts
  • packages/jam/jam-host-calls/refine/machine.ts
  • bin/test-runner/w3f/runners.ts
  • bin/jam/args.test.ts
  • packages/core/pvm-host-calls/index.ts
  • packages/jam/jam-host-calls/accumulate/bless.ts
  • packages/jam/jam-host-calls/accumulate/upgrade.ts
  • packages/core/pvm-host-calls/host-call-registers.test.ts
  • packages/jam/jam-host-calls/write.ts
  • packages/jam/jam-host-calls/accumulate/transfer.ts
  • packages/core/pvm-host-calls/host-call-registers.ts
  • packages/jam/jam-host-calls/accumulate/assign.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

⚙️ CodeRabbit configuration file

**/*.ts: rules from ./CODESTYLE.md should be adhered to.

**/*.ts: Any function whose documentation mention it must not be used in production code,
can be safely used in *.test.ts files. Other usage should be carefuly reviewed
and the comment must explain why it's safe to use there.

**/*.ts: as conversions must not be used. Suggest using tryAs conversion methods.

**/*.ts: Classes with static Codec field must have private constructor and static create method.

**/*.ts: Casting a bigint (or U64) using Number(x) must have an explanation comment why
it is safe.

**/*.ts: When making changes to code with comments containing links (in classes, constants, methods, etc.)
to graypaper.fluffylabs.dev, ensure those links point to the current version for this update.

Files:

  • packages/jam/jam-host-calls/lookup.ts
  • bin/tci/index.test.ts
  • bin/test-runner/w3f/accumulate.ts
  • packages/jam/jam-host-calls/accumulate/new.ts
  • packages/jam/jam-host-calls/accumulate/solicit.ts
  • packages/jam/jam-host-calls/refine/peek.ts
  • packages/jam/jam-host-calls/missing.ts
  • packages/jam/jam-host-calls/accumulate/checkpoint.ts
  • bin/rpc/test/e2e-setup.ts
  • packages/jam/jam-host-calls/accumulate/query.ts
  • packages/jam/jam-host-calls/info.ts
  • packages/jam/jam-host-calls/refine/pages.ts
  • packages/core/pvm-interpreter-ananas/index.ts
  • packages/jam/jam-host-calls/externalities/refine-externalities.test.ts
  • packages/jam/jam-host-calls/refine/invoke.ts
  • packages/core/pvm-host-calls/host-calls.ts
  • packages/core/pvm-host-calls/host-call-memory.ts
  • packages/core/pvm-host-calls/host-call-handler.ts
  • packages/jam/jam-host-calls/accumulate/provide.ts
  • packages/jam/jam-host-calls/gas.ts
  • packages/jam/jam-host-calls/accumulate/eject.ts
  • bin/tci/index.ts
  • packages/jam/jam-host-calls/accumulate/yield.ts
  • packages/core/pvm-interpreter/gas.ts
  • bin/test-runner/w3f/pvm.ts
  • packages/jam/node/jam-config.ts
  • packages/jam/jam-host-calls/accumulate/designate.ts
  • packages/jam/jam-host-calls/utils.ts
  • packages/core/pvm-host-calls/host-calls-manager.ts
  • packages/core/pvm-host-calls/interpreter-instance-manager.ts
  • packages/jam/jam-host-calls/refine/poke.ts
  • packages/core/pvm-interface/memory.ts
  • packages/jam/transition/accumulate/pvm-executor.ts
  • packages/core/pvm-host-calls/host-call-memory.test.ts
  • packages/core/pvm-host-calls/bin.ts
  • packages/jam/jam-host-calls/fetch.ts
  • packages/jam/jam-host-calls/read.ts
packages/core/**/*.ts

⚙️ CodeRabbit configuration file

packages/core/**/*.ts: Core packages must not import any JAM-related packages
(i.e. packages defined under packages/jam/**)

Files:

  • packages/core/pvm-interpreter-ananas/index.ts
  • packages/core/pvm-host-calls/host-calls.ts
  • packages/core/pvm-host-calls/host-call-memory.ts
  • packages/core/pvm-host-calls/host-call-handler.ts
  • packages/core/pvm-interpreter/gas.ts
  • packages/core/pvm-host-calls/host-calls-manager.ts
  • packages/core/pvm-host-calls/interpreter-instance-manager.ts
  • packages/core/pvm-interface/memory.ts
  • packages/core/pvm-host-calls/host-call-memory.test.ts
  • packages/core/pvm-host-calls/bin.ts
🧠 Learnings (1)
📚 Learning: 2025-05-16T16:23:08.685Z
Learnt from: tomusdrw
PR: FluffyLabs/typeberry#390
File: packages/jam/jam-host-calls/fetch.ts:220-226
Timestamp: 2025-05-16T16:23:08.685Z
Learning: In the typeberry codebase, host call (HC) implementations define a gas cost but don't need to explicitly consume gas in their execute() methods. Gas accounting is handled outside of the host call implementation.

Applied to files:

  • packages/jam/jam-host-calls/refine/peek.ts
  • packages/jam/jam-host-calls/missing.ts
  • packages/core/pvm-host-calls/host-call-handler.ts
  • packages/jam/jam-host-calls/accumulate/yield.ts
  • packages/jam/jam-host-calls/refine/poke.ts
🧬 Code graph analysis (37)
packages/jam/jam-host-calls/lookup.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
bin/tci/index.test.ts (1)
packages/jam/config-node/node-config.ts (1)
  • NODE_DEFAULTS (19-23)
bin/test-runner/w3f/accumulate.ts (4)
bin/test-runner/w3f/spec.ts (1)
  • getChainSpec (3-9)
packages/core/hash/blake2b.ts (1)
  • Blake2b (8-44)
packages/jam/transition/accumulate/accumulate-output.ts (1)
  • AccumulateOutput (14-19)
packages/jam/config/pvm-backend.ts (1)
  • PvmBackendNames (2-2)
packages/jam/jam-host-calls/accumulate/new.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/accumulate/solicit.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/refine/peek.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/missing.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/accumulate/checkpoint.ts (2)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
bin/rpc/test/e2e-setup.ts (2)
packages/jam/node/jam-config.ts (1)
  • JamConfig (21-58)
packages/jam/config-node/node-config.ts (1)
  • NODE_DEFAULTS (19-23)
packages/jam/jam-host-calls/accumulate/query.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/info.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/refine/pages.ts (2)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-interpreter-ananas/index.ts (6)
packages/core/pvm-interface/registers.ts (3)
  • IRegisters (5-18)
  • NO_OF_REGISTERS (1-1)
  • REGISTER_BYTE_SIZE (2-2)
packages/core/utils/debug.ts (1)
  • check (15-26)
packages/core/pvm-interface/memory.ts (3)
  • IMemory (18-24)
  • PageFault (9-11)
  • getPageStartAddress (13-15)
packages/core/numbers/index.ts (2)
  • U32 (24-24)
  • tryAsU32 (48-51)
packages/core/pvm-interface/gas.ts (4)
  • IGasCounter (25-57)
  • Gas (9-9)
  • tryAsGas (18-19)
  • tryAsBigGas (15-15)
packages/core/pvm-interface/pvm.ts (1)
  • IPvmInterpreter (7-31)
packages/jam/jam-host-calls/externalities/refine-externalities.test.ts (2)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/jam/jam-host-calls/refine/invoke.ts (5)
packages/core/pvm-interface/registers.ts (2)
  • NO_OF_REGISTERS (1-1)
  • REGISTER_BYTE_SIZE (2-2)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/core/bytes/bytes.ts (1)
  • Bytes (176-242)
packages/core/pvm-host-calls/host-calls.ts (4)
packages/core/pvm-interface/pvm.ts (1)
  • IPvmInterpreter (7-31)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/core/utils/safe-alloc-uint8array.ts (1)
  • safeAllocUint8Array (7-13)
packages/core/pvm-host-calls/host-call-memory.ts (3)
packages/core/pvm-interface/memory.ts (2)
  • IMemory (18-24)
  • PageFault (9-11)
packages/core/numbers/index.ts (2)
  • U64 (27-27)
  • tryAsU32 (48-51)
packages/core/utils/result.ts (4)
  • Result (4-4)
  • Result (81-111)
  • OK (25-25)
  • OK (26-26)
packages/core/pvm-host-calls/host-call-handler.ts (3)
packages/core/pvm-interface/gas.ts (2)
  • Gas (9-9)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/accumulate/provide.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/gas.ts (2)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/jam/jam-host-calls/accumulate/eject.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
bin/tci/index.ts (1)
packages/jam/config-node/node-config.ts (1)
  • NODE_DEFAULTS (19-23)
packages/jam/jam-host-calls/accumulate/yield.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/core/pvm-interpreter/gas.ts (2)
packages/core/pvm-interface/gas.ts (3)
  • Gas (9-9)
  • IGasCounter (25-57)
  • tryAsGas (18-19)
packages/core/numbers/index.ts (2)
  • tryAsU64 (57-61)
  • U64 (27-27)
bin/test-runner/w3f/pvm.ts (1)
packages/core/pvm-interface/gas.ts (1)
  • tryAsGas (18-19)
packages/jam/node/jam-config.ts (2)
packages/jam/config-node/node-config.ts (1)
  • NodeConfiguration (44-73)
packages/jam/block/common.ts (1)
  • TimeSlot (16-16)
packages/jam/jam-host-calls/accumulate/designate.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/utils.ts (3)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/utils/safe-alloc-uint8array.ts (1)
  • safeAllocUint8Array (7-13)
packages/core/pvm-interface/registers.ts (1)
  • REGISTER_BYTE_SIZE (2-2)
packages/core/pvm-host-calls/host-calls-manager.ts (1)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/interpreter-instance-manager.ts (3)
packages/core/pvm-interface/pvm.ts (1)
  • IPvmInterpreter (7-31)
packages/core/pvm-interpreter-ananas/index.ts (1)
  • AnanasInterpreter (107-172)
packages/core/utils/debug.ts (1)
  • assertNever (36-38)
packages/jam/jam-host-calls/refine/poke.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/core/pvm-interface/memory.ts (3)
packages/core/pvm-interpreter/memory/memory-consts.ts (1)
  • PAGE_SIZE_SHIFT (4-4)
packages/core/pvm-interpreter/memory/errors.ts (1)
  • PageFault (7-24)
packages/core/numbers/index.ts (2)
  • U32 (24-24)
  • tryAsU32 (48-51)
packages/jam/transition/accumulate/pvm-executor.ts (2)
packages/core/pvm-host-calls/host-calls.ts (1)
  • HostCalls (37-144)
packages/core/pvm-host-calls/index.ts (1)
  • HostCalls (4-4)
packages/core/pvm-host-calls/host-call-memory.test.ts (4)
packages/core/pvm-interface/memory.ts (4)
  • IMemory (18-24)
  • PageFault (9-11)
  • getPageStartAddress (13-15)
  • MAX_MEMORY_INDEX (4-4)
packages/core/numbers/index.ts (3)
  • U32 (24-24)
  • tryAsU32 (48-51)
  • tryAsU64 (57-61)
packages/core/utils/result.ts (4)
  • Result (4-4)
  • Result (81-111)
  • OK (25-25)
  • OK (26-26)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/core/pvm-host-calls/bin.ts (4)
packages/core/pvm-host-calls/host-calls-manager.ts (2)
  • HostCallsManager (16-59)
  • NoopMissing (61-70)
packages/core/pvm-host-calls/interpreter-instance-manager.ts (1)
  • InterpreterInstanceManager (10-51)
packages/core/pvm-host-calls/host-calls.ts (1)
  • HostCalls (37-144)
packages/core/pvm-interface/gas.ts (1)
  • tryAsGas (18-19)
packages/jam/jam-host-calls/fetch.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
packages/jam/jam-host-calls/read.ts (3)
packages/core/pvm-interface/gas.ts (1)
  • IGasCounter (25-57)
packages/core/pvm-host-calls/host-call-registers.ts (1)
  • HostCallRegisters (4-25)
packages/core/pvm-host-calls/host-call-memory.ts (1)
  • HostCallMemory (5-43)
⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: run (22.x)
  • GitHub Check: benchmarks (22.x)
🔇 Additional comments (46)
packages/jam/node/jam-config.ts (1)

8-8: LGTM! pvmBackend parameter properly integrated.

The pvmBackend parameter is consistently threaded through the import, factory method signature, constructor call, and class field declaration. The naming matches the previous review feedback, and the implementation follows the existing pattern for other JamConfig parameters.

Also applies to: 26-26, 34-34, 39-39, 49-50

bin/tci/index.test.ts (1)

16-16: LGTM! Test properly updated for new signature.

The test correctly adds the pvmBackend parameter using NODE_DEFAULTS.pvm, ensuring the test remains aligned with the updated JamConfig.new signature.

bin/tci/index.ts (1)

83-88: LGTM! TCI entry point updated correctly.

The createJamConfig function now properly includes pvmBackend: NODE_DEFAULTS.pvm in the JamConfig creation, ensuring the TCI uses the default built-in PVM backend.

bin/rpc/test/e2e-setup.ts (1)

14-14: LGTM! E2E setup updated correctly.

The end-to-end test setup now includes the pvmBackend parameter with the default built-in backend, ensuring tests run with the expected PVM configuration.

bin/test-runner/w3f/pvm.ts (2)

4-7: LGTM! Import reorganization follows the new abstraction layer.

The imports correctly use the new @typeberry/pvm-interface package for interface types and constants, while keeping the concrete Interpreter from @typeberry/pvm-interpreter. This separation supports the multi-backend architecture introduced in this PR.


116-121: API migration to new interface looks correct.

The changes properly migrate to the new PVM interface API:

  • resetGeneric correctly passes all required arguments with proper type conversion via tryAsGas
  • pvm.gas.get() provides the new gas access pattern
  • pvm.registers.getAllU64() uses the direct registers property

Note: Running these tests on both Ananas and Built-in backends is tracked in issue #738 as per past review discussions.

packages/jam/transition/accumulate/pvm-executor.ts (4)

1-31: LGTM: Import updates support multi-backend architecture.

The imports correctly bring in PvmBackend and Gas types to support the new PVM backend abstraction.


87-89: LGTM: Clean backend preparation abstraction.

The async factory method correctly delegates to PvmInstanceManager.new() and is appropriately used by the public factory methods.


140-150: LGTM: Factory method correctly supports async backend initialization.

The async signature, PvmBackend parameter, and proper awaiting of prepareBackend() correctly implement the multi-backend architecture.


153-162: LGTM: Factory method correctly implements async backend pattern.

Consistent with createAccumulateExecutor, this factory properly handles async backend initialization and multi-backend support.

bin/test-runner/w3f/accumulate.ts (3)

15-15: LGTM: Backend imports added correctly.

The new imports PvmBackend and PvmBackendNames are properly used throughout the file for backend parameterization and error messaging.


152-177: LGTM: Internal runner correctly parameterized by backend.

The internal implementation properly threads the pvm parameter through to the Accumulate constructor and includes the backend name in error messages for clarity. The removal of as casts (lines 162, 164) complies with coding guidelines.

As per coding guidelines.


144-150: Both backends are correctly tested via runner registration.

Verification confirms that runAccumulateTest and runAccumulateTestAnanas are properly imported in bin/test-runner/w3f/runners.ts and registered as separate test entries ("accumulate" and "accumulate_ananas"). The test infrastructure will invoke both functions, ensuring accumulate tests run on both BuiltIn and Ananas backends as intended.

packages/core/pvm-interpreter-ananas/index.ts (3)

30-48: LGTM!

The AnanasRegisters implementation is clean and correct. The size validation in setAllEncoded() properly uses the exported constants, and getAllU64() provides a convenient view over the register buffer.


50-71: LGTM!

The AnanasMemory implementation correctly handles both store and read operations with proper error handling and PageFault reporting.


174-181: LGTM!

The lowerBytes helper is straightforward and serves its purpose of converting Uint8Array to number[] for WASM interop.

packages/jam/jam-host-calls/fetch.ts (4)

256-282: Let me verify the complete HostCallHandler interface definition:

Interface signature verified; no drift detected.

The execute method in fetch.ts (line 256) correctly implements the HostCallHandler interface signature from packages/core/pvm-host-calls/host-call-handler.ts (line 52). The parameter names match expected types, and in TypeScript, the names of the parameters do not need to match, so the underscore prefix on _gas is a valid TypeScript convention indicating an unused parameter. All 26+ implementations across the codebase follow this same pattern with no deviations.


6-6: IGasCounter migration verified successfully.

The verification confirms the switch to IGasCounter from @typeberry/pvm-interface is complete across all jam-host-calls files. No lingering GasCounter imports or code usages exist—all 28 relevant files correctly import IGasCounter. The two GasCounter references found are documentation comments in the interface source file (packages/core/pvm-interface/gas.ts), which is appropriate.


4-4: Import type swap verified; no runtime instanceof checks detected.

Confirmed that import type { HostCallHandler, HostCallMemory, HostCallRegisters } is correctly used without runtime dependencies, and no instanceof checks for HostCallRegisters or HostCallMemory exist in the codebase.


12-239: Update Graypaper links to consistent version; clarify deprecated method policy.

The code mixes v=0.6.6 (24 links), v=0.6.7 (1 link), and v=0.7.2 (2 links for new methods). Per coding guidelines, links should reflect the current version when the file is modified. Evidence suggests v=0.7.2 is current (used only for newly added methods).

Decide whether to:

  1. Update all links (including deprecated methods) to v=0.7.2, or
  2. Keep deprecated method links at v=0.6.6 with explanatory comments indicating intentional version preservation.

Then audit all 27 links accordingly.

packages/jam/jam-host-calls/lookup.ts (1)

5-7: LGTM: Clean migration to public interface types.

The type updates correctly align with the new public API surface (HostCallRegisters, HostCallMemory, IGasCounter), and the async signature matches the HostCallHandler interface requirements.

Also applies to: 37-37

packages/jam/jam-host-calls/refine/invoke.ts (1)

6-19: LGTM: Public interface migration complete and past issue resolved.

The type updates are consistent, and the previous review concern about using REGISTER_BYTE_SIZE instead of the literal 8 has been properly addressed at lines 30 and 90.

Also applies to: 47-47, 74-74, 90-90

packages/core/pvm-host-calls/bin.ts (1)

1-2: LGTM: Correct async instantiation with backend selection.

The changes properly instantiate the interpreter manager asynchronously with PvmBackend.BuiltIn and update the runProgram call to match the new signature.

Also applies to: 8-8, 29-29

packages/jam/jam-host-calls/refine/peek.ts (1)

3-4: LGTM: Consistent type migration.

The updates correctly adopt the public interface types (HostCallMemory, HostCallRegisters, IGasCounter) and async signature.

Also applies to: 9-9, 31-31

packages/jam/jam-host-calls/refine/pages.ts (1)

3-3: LGTM: Type updates consistent with public API.

The changes correctly adopt HostCallRegisters and IGasCounter from the public interfaces.

Also applies to: 8-8, 36-36

packages/core/pvm-host-calls/host-calls-manager.ts (1)

3-3: LGTM: Consistent type migration.

The updates correctly use Gas and HostCallRegisters types from the public interfaces.

Also applies to: 11-11, 44-44

packages/jam/jam-host-calls/gas.ts (1)

3-5: LGTM: Type updates align with public API.

The signature correctly uses IGasCounter and HostCallRegisters from the public interfaces.

Also applies to: 22-22

packages/jam/jam-host-calls/utils.ts (2)

3-5: LGTM! Type migration aligns with the new public API surface.

The import updates replacing IHostCallRegisters with HostCallRegisters and sourcing constants from @typeberry/pvm-interface are consistent with the broader refactor to establish a clean public interface boundary.

Also applies to: 14-14


45-47: Well-implemented utility function.

The emptyRegistersBuffer() function correctly allocates a zeroed buffer using safeAllocUint8Array, which provides protection against excessive allocations. The size calculation (NO_OF_REGISTERS * REGISTER_BYTE_SIZE) is correct and aligns with the register structure.

packages/core/pvm-interface/memory.ts (1)

1-24: Clean memory interface design.

The IMemory interface and supporting types (PageFault, getPageStartAddress) provide a well-structured abstraction for memory operations. The interface correctly uses Result types for error handling and properly documents the store/read operations.

packages/jam/jam-host-calls/accumulate/checkpoint.ts (1)

2-4: LGTM! Consistent type migration to public interfaces.

The updates replacing IHostCallRegisters with HostCallRegisters and GasCounter with IGasCounter align with the broader refactor. The explicit return statement on line 34 improves code clarity.

Also applies to: 30-35

packages/jam/jam-host-calls/accumulate/eject.ts (1)

5-7: LGTM! Type updates are consistent.

The migration to HostCallMemory, HostCallRegisters, and IGasCounter follows the established pattern across host-call implementations and maintains backward-compatible behavior.

Also applies to: 31-31

packages/jam/jam-host-calls/accumulate/new.ts (1)

5-7: LGTM! Type migration follows the established pattern.

The updates to use HostCallMemory, HostCallRegisters, and IGasCounter are consistent with the interface standardization across the accumulate module.

Also applies to: 32-32

packages/jam/jam-host-calls/info.ts (1)

6-8: LGTM! Consistent interface adoption.

The type updates align with the standardized public API surface for host-call handlers, maintaining consistent behavior while improving type clarity.

Also applies to: 56-56

packages/jam/jam-host-calls/accumulate/query.ts (1)

7-8: LGTM! Type migration is consistent.

The updates to HostCallMemory, HostCallRegisters, and IGasCounter follow the established pattern for host-call interface standardization.

Also applies to: 13-13, 37-37

packages/jam/jam-host-calls/read.ts (1)

4-6: LGTM! Type migration completes the interface standardization.

The updates to HostCallMemory, HostCallRegisters, and IGasCounter complete the consistent adoption of the new public API surface across host-call implementations.

Also applies to: 35-35

packages/jam/jam-host-calls/externalities/refine-externalities.test.ts (1)

6-7: Tests aligned with public HostCall types: LGTM.

Type updates for HostCallMemory/HostCallRegisters and Status look consistent with the new interfaces.

Also applies to: 101-107, 117-123, 133-137

packages/jam/jam-host-calls/accumulate/solicit.ts (1)

4-7: Confirm graypaper link version alignment with this update's target version.

The link at line 17 uses v=0.6.7, consistent with most other accumulate module functions. However, transfer.ts (same module) uses v=0.7.2, and the codebase contains references up to v=0.7.2. Without explicit knowledge of this update's target graypaper version, unable to definitively confirm if 0.6.7 is current. Please verify v=0.6.7 matches your update scope.

packages/jam/jam-host-calls/refine/poke.ts (1)

1-31: LGTM! Clean migration to interface types.

The type updates from IHostCallMemory/IHostCallRegisters/GasCounter to HostCallMemory/HostCallRegisters/IGasCounter are consistent with the PR's interface abstraction objectives. The method logic remains unchanged.

packages/jam/jam-host-calls/missing.ts (1)

1-19: LGTM! Consistent type migration.

The updates from IHostCallMemory/IHostCallRegisters/GasCounter to HostCallMemory/HostCallRegisters/IGasCounter align with the interface abstraction introduced in this PR.

packages/jam/jam-host-calls/accumulate/designate.ts (1)

4-32: LGTM! Type migration aligns with interface abstraction.

The signature and import updates correctly adopt HostCallMemory/HostCallRegisters/IGasCounter from the new PVM interface. Logic remains functionally identical.

packages/core/pvm-host-calls/host-calls.ts (2)

43-68: Verify the IPvmInterpreter-based refactoring, particularly the memory load logic.

The refactoring introduces encoded register/memory views and updates gas accounting to use pvmInstance.gas.used(). The HALT path reconstruction looks correct.

One concern: Line 54 performs a Number() cast on a bigint without an explicit safety comment, violating the coding guidelines.

Apply this diff to add the required safety comment:

     const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
     const memory = new HostCallMemory(pvmInstance.memory);
     const address = regs.get(7);
-    // NOTE we are taking the the lower U32 part of the register, hence it's safe.
+    // NOTE: We take the lower U32 part of the register (masked to 32 bits).
+    // Safe to convert to Number: value ≤ 2^32-1, within JS safe integer range.
     const length = Number(regs.get(8) & 0xffff_ffffn);

As per coding guidelines.


70-143: LGTM! IPvmInterpreter integration is well-structured.

The execution loop correctly:

  • Creates encoded register/memory views for each host call
  • Synchronizes register state back to the interpreter instance after host-call execution (line 108)
  • Handles gas accounting via the new IGasCounter interface
  • Properly manages the PVM lifecycle with resetJam and runProgram
packages/core/pvm-host-calls/host-call-handler.ts (1)

1-52: LGTM! Interface definition properly migrated.

The HostCallHandler interface correctly adopts the new abstraction types (IGasCounter, HostCallMemory, HostCallRegisters) from @typeberry/pvm-interface. The execute signature and documentation are consistent with the broader refactoring.

packages/core/pvm-host-calls/host-call-memory.test.ts (2)

13-38: LGTM! Test infrastructure properly migrated to IMemory interface.

The FakeMemory test double correctly implements IMemory and returns PageFault errors as expected. The test setup cleanly adopts the new interface abstraction.


74-84: LGTM! Address wrapping tests align with GP specification.

The tests correctly verify that addresses exceeding MAX_MEMORY_INDEX wrap (mod 2³²) and result in page faults at the wrapped address. This aligns with the Gray Paper specification for memory addressing.

Also applies to: 121-131

Comment thread packages/core/pvm-host-calls/interpreter-instance-manager.ts
Comment thread packages/jam/jam-host-calls/accumulate/provide.ts
Comment thread packages/jam/jam-host-calls/accumulate/yield.ts
Comment thread packages/jam/transition/accumulate/pvm-executor.ts
@tomusdrw
tomusdrw merged commit 5746fdc into main Oct 26, 2025
16 checks passed
@tomusdrw
tomusdrw deleted the maso-ananas branch October 26, 2025 10:35
@coderabbitai coderabbitai Bot mentioned this pull request Oct 31, 2025
7 tasks
This was referenced Jan 9, 2026
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.

Run SPI with Anan-as 🍍

2 participants