@fluffylabs/anan-as 1.1.6 → 1.2.0-1c29182

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/bin/index.js +186 -53
  2. package/dist/bin/src/fuzz.js +1 -1
  3. package/dist/bin/src/test-json.js +2 -6
  4. package/dist/bin/src/trace-replay.js +8 -4
  5. package/dist/build/compiler-inline.js +1 -1
  6. package/dist/build/compiler.d.ts +17 -13
  7. package/dist/build/compiler.js +13 -21
  8. package/dist/build/compiler.wasm +0 -0
  9. package/dist/build/debug-inline.js +1 -1
  10. package/dist/build/debug-raw-inline.js +1 -1
  11. package/dist/build/debug-raw.d.ts +63 -112
  12. package/dist/build/debug-raw.js +86 -139
  13. package/dist/build/debug-raw.wasm +0 -0
  14. package/dist/build/debug.d.ts +63 -112
  15. package/dist/build/debug.js +91 -147
  16. package/dist/build/debug.wasm +0 -0
  17. package/dist/build/js/assembly/api-debugger.d.ts +55 -0
  18. package/dist/build/js/assembly/api-debugger.js +245 -0
  19. package/dist/build/js/assembly/api-internal.d.ts +13 -0
  20. package/dist/build/js/assembly/api-internal.js +191 -0
  21. package/dist/build/js/assembly/api-types.d.ts +45 -0
  22. package/dist/build/js/assembly/api-types.js +52 -0
  23. package/dist/build/js/assembly/api-utils.d.ts +79 -0
  24. package/dist/build/js/assembly/api-utils.js +221 -0
  25. package/dist/build/js/assembly/arguments.d.ts +44 -0
  26. package/dist/build/js/assembly/arguments.js +164 -0
  27. package/dist/build/js/assembly/codec.d.ts +24 -0
  28. package/dist/build/js/assembly/codec.js +139 -0
  29. package/dist/build/js/assembly/gas.d.ts +11 -0
  30. package/dist/build/js/assembly/gas.js +33 -0
  31. package/dist/build/js/assembly/index-shared.d.ts +4 -0
  32. package/dist/build/js/assembly/index-shared.js +4 -0
  33. package/dist/build/js/assembly/instructions/bit.d.ts +11 -0
  34. package/dist/build/js/assembly/instructions/bit.js +53 -0
  35. package/dist/build/js/assembly/instructions/branch.d.ts +17 -0
  36. package/dist/build/js/assembly/instructions/branch.js +120 -0
  37. package/dist/build/js/assembly/instructions/jump.d.ts +5 -0
  38. package/dist/build/js/assembly/instructions/jump.js +21 -0
  39. package/dist/build/js/assembly/instructions/load.d.ts +17 -0
  40. package/dist/build/js/assembly/instructions/load.js +134 -0
  41. package/dist/build/js/assembly/instructions/logic.d.ts +10 -0
  42. package/dist/build/js/assembly/instructions/logic.js +47 -0
  43. package/dist/build/js/assembly/instructions/math.d.ts +28 -0
  44. package/dist/build/js/assembly/instructions/math.js +225 -0
  45. package/dist/build/js/assembly/instructions/misc.d.ts +6 -0
  46. package/dist/build/js/assembly/instructions/misc.js +22 -0
  47. package/dist/build/js/assembly/instructions/mov.d.ts +6 -0
  48. package/dist/build/js/assembly/instructions/mov.js +35 -0
  49. package/dist/build/js/assembly/instructions/outcome.d.ts +30 -0
  50. package/dist/build/js/assembly/instructions/outcome.js +88 -0
  51. package/dist/build/js/assembly/instructions/rot.d.ts +15 -0
  52. package/dist/build/js/assembly/instructions/rot.js +66 -0
  53. package/dist/build/js/assembly/instructions/set.d.ts +7 -0
  54. package/dist/build/js/assembly/instructions/set.js +36 -0
  55. package/dist/build/js/assembly/instructions/shift.d.ts +19 -0
  56. package/dist/build/js/assembly/instructions/shift.js +121 -0
  57. package/dist/build/js/assembly/instructions/store.d.ts +17 -0
  58. package/dist/build/js/assembly/instructions/store.js +101 -0
  59. package/dist/build/js/assembly/instructions/utils.d.ts +25 -0
  60. package/dist/build/js/assembly/instructions/utils.js +91 -0
  61. package/dist/build/js/assembly/instructions-exe.d.ts +2 -0
  62. package/dist/build/js/assembly/instructions-exe.js +245 -0
  63. package/dist/build/js/assembly/instructions.d.ts +10 -0
  64. package/dist/build/js/assembly/instructions.js +252 -0
  65. package/dist/build/js/assembly/interpreter.d.ts +28 -0
  66. package/dist/build/js/assembly/interpreter.js +221 -0
  67. package/dist/build/js/assembly/math.d.ts +6 -0
  68. package/dist/build/js/assembly/math.js +22 -0
  69. package/dist/build/js/assembly/memory-page.d.ts +36 -0
  70. package/dist/build/js/assembly/memory-page.js +74 -0
  71. package/dist/build/js/assembly/memory.d.ts +83 -0
  72. package/dist/build/js/assembly/memory.js +482 -0
  73. package/dist/build/js/assembly/portable.d.ts +24 -0
  74. package/dist/build/js/assembly/portable.js +363 -0
  75. package/dist/build/js/assembly/program-build.d.ts +2 -0
  76. package/dist/build/js/assembly/program-build.js +104 -0
  77. package/dist/build/js/assembly/program.d.ts +85 -0
  78. package/dist/build/js/assembly/program.js +340 -0
  79. package/dist/build/js/assembly/registers.d.ts +6 -0
  80. package/dist/build/js/assembly/registers.js +9 -0
  81. package/dist/build/js/assembly/spi.d.ts +92 -0
  82. package/dist/build/js/assembly/spi.js +152 -0
  83. package/dist/build/js/portable/bootstrap.d.ts +1 -0
  84. package/dist/build/js/portable/bootstrap.js +5 -0
  85. package/dist/build/js/portable/index.d.ts +4 -0
  86. package/dist/build/js/portable/index.js +6 -0
  87. package/dist/build/js/portable-bundle.js +4496 -0
  88. package/dist/build/release-inline.js +1 -1
  89. package/dist/build/release-mini-inline.js +1 -1
  90. package/dist/build/release-mini.d.ts +63 -112
  91. package/dist/build/release-mini.js +91 -147
  92. package/dist/build/release-mini.wasm +0 -0
  93. package/dist/build/release-stub-inline.js +1 -1
  94. package/dist/build/release-stub.d.ts +63 -112
  95. package/dist/build/release-stub.js +91 -147
  96. package/dist/build/release-stub.wasm +0 -0
  97. package/dist/build/release.d.ts +63 -112
  98. package/dist/build/release.js +91 -147
  99. package/dist/build/release.wasm +0 -0
  100. package/dist/build/test-inline.js +1 -1
  101. package/dist/build/test.wasm +0 -0
  102. package/dist/test/test-gas-cost.js +2 -3
  103. package/dist/test/test-w3f-common.js +125 -0
  104. package/dist/test/test-w3f-portable.js +5 -0
  105. package/dist/test/test-w3f.js +3 -120
  106. package/package.json +24 -12
package/dist/bin/index.js CHANGED
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFileSync } from "node:fs";
3
- import minimist from "minimist";
4
- import { disassemble, HasMetadata, InputKind, prepareProgram, pvmDestroy, pvmResume, pvmSetRegisters, pvmStart, } from "../build/release.js";
3
+ import { parseArgs } from "node:util";
4
+ import { disassemble, HasMetadata, InputKind, prepareProgram, pvmDestroy, pvmReadMemory, pvmResume, pvmSetRegisters, pvmStart, } from "../build/release.js";
5
5
  import { LOG_GAS_COST, LOG_HOST_CALL_INDEX, printLogHostCall, WHAT } from "./src/log-host-call.js";
6
6
  import { STATUS } from "./src/trace-parse.js";
7
7
  import { replayTraceFile } from "./src/trace-replay.js";
8
8
  import { hexDecode, hexEncode } from "./src/utils.js";
9
+ // Page access modes (matches assembly/memory-page.ts Access enum)
10
+ const ACCESS_READ = 1;
11
+ const ACCESS_WRITE = 2;
9
12
  const HELP_TEXT = `Usage:
10
13
  anan-as disassemble [--spi] [--no-metadata] <file.(jam|pvm|spi|bin)>
11
- anan-as run [--spi] [--no-logs] [--no-metadata] [--no-log-host-call] [--pc <number>] [--gas <number>] <file.jam> [spi-args.bin or hex]
14
+ anan-as run [--spi] [--no-logs] [--no-metadata] [--no-log-host-call] [--pc <number>] [--gas <number>] [--regs <r0,r1,...,r12>] <file.jam> [spi-args.bin or hex]
12
15
  anan-as replay-trace [--no-metadata] [--no-verify] [--no-logs] [--no-log-host-call] <trace.log>
13
16
 
14
17
  Commands:
@@ -24,6 +27,10 @@ Flags:
24
27
  --no-verify Skip verification against trace data (replay-trace only)
25
28
  --pc <number> Set initial program counter (default: 0)
26
29
  --gas <number> Set initial gas amount (default: 10_000)
30
+ --regs <values> Set initial registers (comma-separated, 13 values: r0,r1,...,r12; supports decimal and 0x hex)
31
+ --pages <specs> Add memory pages (semicolon-separated: "addr:size;addr:size:ro"; append ":r" or ":ro" for read-only)
32
+ --mem <specs> Initialize memory (semicolon-separated: "addr:hex_bytes;addr:hex_bytes")
33
+ --dump <specs> Dump memory after execution (semicolon-separated: "addr:len;addr:len")
27
34
  --help, -h Show this help message`;
28
35
  main();
29
36
  function main() {
@@ -52,16 +59,19 @@ function main() {
52
59
  }
53
60
  }
54
61
  function handleDisassemble(args) {
55
- const parsed = minimist(args, {
56
- boolean: ["spi", "metadata", "help"],
57
- alias: { h: "help" },
58
- default: { metadata: true },
62
+ const { values, positionals: files } = parseArgs({
63
+ args,
64
+ allowPositionals: true,
65
+ options: {
66
+ spi: { type: "boolean", default: false },
67
+ "no-metadata": { type: "boolean", default: false },
68
+ help: { type: "boolean", short: "h", default: false },
69
+ },
59
70
  });
60
- if (parsed.help) {
71
+ if (values.help) {
61
72
  console.log(HELP_TEXT);
62
73
  return;
63
74
  }
64
- const files = parsed._;
65
75
  if (files.length === 0) {
66
76
  console.error("Error: No file provided for disassemble command.");
67
77
  console.error("Usage: anan-as disassemble [--spi] [--no-metadata] <file.(jam|pvm|spi|bin)>");
@@ -87,32 +97,41 @@ function handleDisassemble(args) {
87
97
  console.error("Supported extensions: .jam, .pvm, .spi, .bin");
88
98
  process.exit(1);
89
99
  }
90
- const kind = parsed.spi ? InputKind.SPI : InputKind.Generic;
91
- const hasMetadata = parsed.metadata ? HasMetadata.Yes : HasMetadata.No;
100
+ const kind = values.spi ? InputKind.SPI : InputKind.Generic;
101
+ const hasMetadata = values["no-metadata"] ? HasMetadata.No : HasMetadata.Yes;
92
102
  const f = readFileSync(file);
93
103
  const name = kind === InputKind.Generic ? "generic PVM" : "JAM SPI";
94
104
  console.log(`🤖 Assembly of ${file} (as ${name})`);
95
105
  console.log(disassemble(Array.from(f), kind, hasMetadata));
96
106
  }
97
107
  function handleRun(args) {
98
- const parsed = minimist(args, {
99
- boolean: ["spi", "logs", "metadata", "help", "log-host-call"],
100
- /** Prevents parsing hex values as numbers. */
101
- string: ["pc", "gas", "_"],
102
- alias: { h: "help" },
103
- default: { metadata: true, logs: true, "log-host-call": true },
108
+ const { values, positionals: files } = parseArgs({
109
+ args,
110
+ allowPositionals: true,
111
+ options: {
112
+ spi: { type: "boolean", default: false },
113
+ "no-logs": { type: "boolean", default: false },
114
+ "no-metadata": { type: "boolean", default: false },
115
+ "no-log-host-call": { type: "boolean", default: false },
116
+ help: { type: "boolean", short: "h", default: false },
117
+ pc: { type: "string" },
118
+ gas: { type: "string" },
119
+ regs: { type: "string" },
120
+ pages: { type: "string" },
121
+ mem: { type: "string" },
122
+ dump: { type: "string" },
123
+ },
104
124
  });
105
- if (parsed.help) {
125
+ if (values.help) {
106
126
  console.log(HELP_TEXT);
107
127
  return;
108
128
  }
109
- const files = parsed._;
110
129
  if (files.length === 0) {
111
130
  console.error("Error: No file provided for run command.");
112
131
  console.error("Usage: anan-as run [--spi] [--no-logs] [--no-metadata] [--pc <number>] [--gas <number>] <file.jam> [spi-args.bin]");
113
132
  process.exit(1);
114
133
  }
115
- const kind = parsed.spi ? InputKind.SPI : InputKind.Generic;
134
+ const kind = values.spi ? InputKind.SPI : InputKind.Generic;
116
135
  let programFile;
117
136
  let spiArgsStr;
118
137
  if (kind === InputKind.SPI) {
@@ -136,19 +155,24 @@ function handleRun(args) {
136
155
  }
137
156
  // Validate SPI args file if provided
138
157
  const spiArgs = parseSpiArgs(spiArgsStr);
139
- const logs = parsed.logs;
140
- const logHostCall = parsed["log-host-call"];
141
- const hasMetadata = parsed.metadata ? HasMetadata.Yes : HasMetadata.No;
158
+ const logs = !values["no-logs"];
159
+ const logHostCall = !values["no-log-host-call"];
160
+ const hasMetadata = values["no-metadata"] ? HasMetadata.No : HasMetadata.Yes;
142
161
  // Parse and validate PC and gas options
143
- const initialPc = parsePc(parsed);
144
- const initialGas = parseGas(parsed);
162
+ const initialPc = parsePc(values.pc);
163
+ const initialGas = parseGas(values.gas);
164
+ const initialRegisters = parseRegs(values.regs);
165
+ const initialPages = parsePages(values.pages);
166
+ const initialMemory = parseMem(values.mem);
167
+ const dumpRegions = parseDump(values.dump);
145
168
  const programCode = Array.from(readFileSync(programFile));
146
169
  const name = kind === InputKind.Generic ? "generic PVM" : "JAM SPI";
147
170
  console.log(`🚀 Running ${programFile} (as ${name})`);
148
171
  try {
149
172
  const preallocateMemoryPages = 128;
150
- const program = prepareProgram(kind, hasMetadata, programCode, [], [], [], spiArgs, preallocateMemoryPages);
151
- const id = pvmStart(program, false);
173
+ const useBlockGas = true;
174
+ const program = prepareProgram(kind, hasMetadata, programCode, initialRegisters, initialPages, initialMemory, spiArgs, preallocateMemoryPages, useBlockGas);
175
+ const id = pvmStart(program);
152
176
  let gas = initialGas;
153
177
  let pc = initialPc;
154
178
  for (;;) {
@@ -171,6 +195,24 @@ function handleRun(args) {
171
195
  break;
172
196
  }
173
197
  }
198
+ // Dump memory regions before destroying the VM
199
+ for (const region of dumpRegions) {
200
+ const data = pvmReadMemory(id, region.address, region.length);
201
+ const addrHex = `0x${region.address.toString(16)}`;
202
+ if (data) {
203
+ console.log(`\nMemory @ ${addrHex} (${region.length} bytes):`);
204
+ for (let off = 0; off < data.length; off += 16) {
205
+ const addr = region.address + off;
206
+ const slice = Array.from(data.slice(off, Math.min(off + 16, data.length)));
207
+ const hex = slice.map((b) => b.toString(16).padStart(2, "0")).join(" ");
208
+ const ascii = slice.map((b) => (b >= 0x20 && b < 0x7f ? String.fromCharCode(b) : ".")).join("");
209
+ console.log(` ${addr.toString(16).padStart(8, "0")}: ${hex.padEnd(47)} ${ascii}`);
210
+ }
211
+ }
212
+ else {
213
+ console.log(`\nMemory @ ${addrHex}: <page fault>`);
214
+ }
215
+ }
174
216
  const result = pvmDestroy(id);
175
217
  console.log(`Status: ${result?.status}`);
176
218
  console.log(`Exit code: ${result?.exitCode}`);
@@ -185,16 +227,21 @@ function handleRun(args) {
185
227
  }
186
228
  }
187
229
  function handleReplayTrace(args) {
188
- const parsed = minimist(args, {
189
- boolean: ["metadata", "verify", "logs", "help", "log-host-call"],
190
- alias: { h: "help" },
191
- default: { metadata: true, logs: true, verify: true, "log-host-call": true },
230
+ const { values, positionals: files } = parseArgs({
231
+ args,
232
+ allowPositionals: true,
233
+ options: {
234
+ "no-metadata": { type: "boolean", default: false },
235
+ "no-verify": { type: "boolean", default: false },
236
+ "no-logs": { type: "boolean", default: false },
237
+ "no-log-host-call": { type: "boolean", default: false },
238
+ help: { type: "boolean", short: "h", default: false },
239
+ },
192
240
  });
193
- if (parsed.help) {
241
+ if (values.help) {
194
242
  console.log(HELP_TEXT);
195
243
  return;
196
244
  }
197
- const files = parsed._;
198
245
  if (files.length === 0) {
199
246
  console.error("Error: No trace file provided for replay-trace command.");
200
247
  console.error("Usage: anan-as replay-trace [--no-metadata] [--no-verify] [--no-logs] <trace.log>");
@@ -206,10 +253,10 @@ function handleReplayTrace(args) {
206
253
  process.exit(1);
207
254
  }
208
255
  const file = files[0];
209
- const hasMetadata = parsed.metadata ? HasMetadata.Yes : HasMetadata.No;
210
- const verify = parsed.verify;
211
- const logs = parsed.logs;
212
- const logHostCall = parsed["log-host-call"];
256
+ const hasMetadata = values["no-metadata"] ? HasMetadata.No : HasMetadata.Yes;
257
+ const verify = !values["no-verify"];
258
+ const logs = !values["no-logs"];
259
+ const logHostCall = !values["no-log-host-call"];
213
260
  try {
214
261
  const summary = replayTraceFile(file, {
215
262
  logs,
@@ -227,16 +274,10 @@ function handleReplayTrace(args) {
227
274
  process.exit(1);
228
275
  }
229
276
  }
230
- function parseGas(parsed) {
231
- if (parsed.gas === undefined) {
277
+ function parseGas(gasStr) {
278
+ if (gasStr === undefined) {
232
279
  return BigInt(10_000);
233
280
  }
234
- // Ensure it's a string/number, not boolean
235
- if (typeof parsed.gas === "boolean") {
236
- console.error("Error: --gas requires a value.");
237
- process.exit(1);
238
- }
239
- const gasStr = String(parsed.gas);
240
281
  // Reject floats and non-integer strings
241
282
  if (gasStr.includes(".") || !/^-?\d+$/.test(gasStr)) {
242
283
  console.error("Error: --gas must be a valid integer.");
@@ -269,16 +310,10 @@ function parseSpiArgs(spiArgsStr) {
269
310
  return Array.from(readFileSync(spiArgsStr));
270
311
  }
271
312
  }
272
- function parsePc(parsed) {
273
- if (parsed.pc === undefined) {
313
+ function parsePc(pcStr) {
314
+ if (pcStr === undefined) {
274
315
  return 0;
275
316
  }
276
- // Ensure it's a string/number, not boolean
277
- if (typeof parsed.pc === "boolean") {
278
- console.error("Error: --pc requires a value.");
279
- process.exit(1);
280
- }
281
- const pcStr = String(parsed.pc);
282
317
  // Reject floats and non-integer strings
283
318
  if (pcStr.includes(".") || !/^-?\d+$/.test(pcStr)) {
284
319
  console.error("Error: --pc must be a valid integer.");
@@ -291,3 +326,101 @@ function parsePc(parsed) {
291
326
  }
292
327
  return pcValue;
293
328
  }
329
+ function parseRegs(regsStr) {
330
+ if (regsStr === undefined) {
331
+ return [];
332
+ }
333
+ const parts = regsStr.split(",");
334
+ if (parts.length !== 13) {
335
+ throw new Error(`--regs must have exactly 13 comma-separated values (got ${parts.length}).\nFormat: --regs r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12`);
336
+ }
337
+ return parts.map((s, i) => {
338
+ try {
339
+ return BigInt.asUintN(64, BigInt(s.trim()));
340
+ }
341
+ catch (_e) {
342
+ throw new Error(`--regs value at index ${i} ("${s.trim()}") is not a valid integer.`);
343
+ }
344
+ });
345
+ }
346
+ function parseNum(s) {
347
+ return Number(s.trim());
348
+ }
349
+ function parsePages(pagesStr) {
350
+ if (pagesStr === undefined) {
351
+ return [];
352
+ }
353
+ // Format: "addr:size;addr:size" — all pages are writable
354
+ // Or "addr:size:ro" (or "addr:size:r") for read-only
355
+ const specs = pagesStr.split(";").filter((s) => s.trim().length > 0);
356
+ return specs.map((spec, i) => {
357
+ const parts = spec.split(":");
358
+ if (parts.length < 2 || parts.length > 3) {
359
+ throw new Error(`--pages entry ${i} ("${spec}") must be "addr:size" or "addr:size:ro" (or "addr:size:r").`);
360
+ }
361
+ const address = parseNum(parts[0]);
362
+ const length = parseNum(parts[1]);
363
+ const flag = parts[2]?.trim();
364
+ const access = flag === "ro" || flag === "r" ? ACCESS_READ : ACCESS_WRITE;
365
+ if (Number.isNaN(address) || Number.isNaN(length) || length <= 0) {
366
+ throw new Error(`--pages entry ${i} ("${spec}") has invalid address or size.`);
367
+ }
368
+ return { address, length, access };
369
+ });
370
+ }
371
+ function parseMem(memStr) {
372
+ if (memStr === undefined) {
373
+ return [];
374
+ }
375
+ // Format: "addr:hexbytes;addr:hexbytes"
376
+ // Example: "0x20000:0500000000000000;0x20008:0300000000000000"
377
+ const specs = memStr.split(";").filter((s) => s.trim().length > 0);
378
+ return specs.map((spec, i) => {
379
+ const colonIdx = spec.indexOf(":");
380
+ if (colonIdx === -1) {
381
+ throw new Error(`--mem entry ${i} ("${spec}") must be "addr:hexbytes".`);
382
+ }
383
+ const addrStr = spec.substring(0, colonIdx).trim();
384
+ let hexStr = spec.substring(colonIdx + 1).trim();
385
+ const address = parseNum(addrStr);
386
+ if (Number.isNaN(address)) {
387
+ throw new Error(`--mem entry ${i} has invalid address "${addrStr}".`);
388
+ }
389
+ // Strip 0x prefix from hex data
390
+ if (hexStr.startsWith("0x") || hexStr.startsWith("0X")) {
391
+ hexStr = hexStr.substring(2);
392
+ }
393
+ if (hexStr.length % 2 !== 0) {
394
+ throw new Error(`--mem entry ${i} hex data has odd length.`);
395
+ }
396
+ const data = [];
397
+ for (let j = 0; j < hexStr.length; j += 2) {
398
+ const byte = parseInt(hexStr.substring(j, j + 2), 16);
399
+ if (Number.isNaN(byte)) {
400
+ throw new Error(`--mem entry ${i} has invalid hex byte at position ${j}: "${hexStr.substring(j, j + 2)}".`);
401
+ }
402
+ data.push(byte);
403
+ }
404
+ return { address, data };
405
+ });
406
+ }
407
+ function parseDump(dumpStr) {
408
+ if (dumpStr === undefined) {
409
+ return [];
410
+ }
411
+ // Format: "addr:len;addr:len"
412
+ // Example: "0x20000:64;0x20100:32"
413
+ const specs = dumpStr.split(";").filter((s) => s.trim().length > 0);
414
+ return specs.map((spec, i) => {
415
+ const parts = spec.split(":");
416
+ if (parts.length !== 2) {
417
+ throw new Error(`--dump entry ${i} ("${spec}") must be "addr:len".`);
418
+ }
419
+ const address = parseNum(parts[0]);
420
+ const length = parseNum(parts[1]);
421
+ if (Number.isNaN(address) || Number.isNaN(length) || length <= 0) {
422
+ throw new Error(`--dump entry ${i} ("${spec}") has invalid address or length.`);
423
+ }
424
+ return { address, length };
425
+ });
426
+ }
@@ -21,7 +21,7 @@ export function fuzz(data) {
21
21
  .join(",")
22
22
  .split(",")
23
23
  .map(() => BigInt(0));
24
- const exe = prepareProgram(InputKind.Generic, HasMetadata.No, Array.from(program), registers, [], [], [], 0);
24
+ const exe = prepareProgram(InputKind.Generic, HasMetadata.No, Array.from(program), registers, [], [], [], 0, false);
25
25
  const output = runProgram(exe, gas, pc, printDebugInfo);
26
26
  const vmRegisters = decodeRegistersFromTypeberry(vm);
27
27
  collectErrors((assertFn) => {
@@ -16,18 +16,14 @@ export function run(processJson, options) {
16
16
  args.shift();
17
17
  options.isDebug = true;
18
18
  }
19
- else if (args[0] === "--sbrk-gas") {
20
- args.shift();
21
- options.useSbrkGas = true;
22
- }
23
19
  else {
24
20
  break;
25
21
  }
26
22
  }
27
23
  if (args.length === 0) {
28
24
  console.error("Error: No JSON files provided.");
29
- console.error("Usage: index.js [--debug] [--sbrk-gas] <file1.json> [file2.json ...]");
30
- console.error("read from stdin: index.js [--debug] [--sbrk-gas] -");
25
+ console.error("Usage: index.js [--debug] <file1.json> [file2.json ...]");
26
+ console.error("read from stdin: index.js [--debug] -");
31
27
  process.exit(1);
32
28
  }
33
29
  if (args[0] === "-") {
@@ -1,10 +1,12 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { InputKind, prepareProgram, pvmDestroy, pvmReadMemory, pvmResume, pvmSetRegisters, pvmStart, pvmWriteMemory, } from "../../build/release.js";
2
+ import * as defaultPvm from "../../build/release.js";
3
3
  import { LOG_HOST_CALL_INDEX, printLogHostCall } from "./log-host-call.js";
4
4
  import { ARGS_SEGMENT_START, buildInitialChunks, buildInitialPages, encodeRegistersFromDump, extractSpiArgs, isSpiTrace, parseTrace, STATUS, statusToTermination, } from "./trace-parse.js";
5
5
  import { ConsoleTracer } from "./tracer.js";
6
6
  import { hexEncode } from "./utils.js";
7
7
  export function replayTraceFile(filePath, options) {
8
+ const pvm = options.pvm ?? defaultPvm;
9
+ const { prepareProgram, pvmStart, pvmDestroy, pvmResume, pvmReadMemory, pvmWriteMemory, pvmSetRegisters, InputKind } = pvm;
8
10
  const input = readFileSync(filePath, "utf8");
9
11
  const trace = parseTrace(input);
10
12
  const { program, initialMemWrites, start, ecalliEntries, termination } = trace;
@@ -12,10 +14,12 @@ export function replayTraceFile(filePath, options) {
12
14
  const useSpi = isSpiTrace(start, initialMemWrites);
13
15
  const programInput = Array.from(program);
14
16
  const spiArgs = Array.from(extractSpiArgs(start, initialMemWrites));
17
+ const preallocateMemoryPages = 128;
18
+ const useBlockGas = options.useBlockGas ?? false;
15
19
  const preparedProgram = useSpi
16
- ? prepareProgram(InputKind.SPI, hasMetadata, programInput, [], [], [], spiArgs, 0)
17
- : prepareProgram(InputKind.Generic, hasMetadata, programInput, encodeRegistersFromDump(start.registers), buildInitialPages(initialMemWrites), buildInitialChunks(initialMemWrites), [], 0);
18
- const id = pvmStart(preparedProgram, true);
20
+ ? prepareProgram(InputKind.SPI, hasMetadata, programInput, [], [], [], spiArgs, preallocateMemoryPages, useBlockGas)
21
+ : prepareProgram(InputKind.Generic, hasMetadata, programInput, encodeRegistersFromDump(start.registers), buildInitialPages(initialMemWrites), buildInitialChunks(initialMemWrites), [], preallocateMemoryPages, useBlockGas);
22
+ const id = pvmStart(preparedProgram);
19
23
  const initialEcalliCount = ecalliEntries.length;
20
24
  const tracer = options.tracer ?? new ConsoleTracer();
21
25
  try {