diff --git a/packages/jam/in-core/externalities/refine.test.ts b/packages/jam/in-core/externalities/refine.test.ts index bbeb42d9c..f11e0fe76 100644 --- a/packages/jam/in-core/externalities/refine.test.ts +++ b/packages/jam/in-core/externalities/refine.test.ts @@ -274,4 +274,72 @@ describe("RefineExternalitiesImpl", () => { assert.strictEqual(result.isOk, true); }); }); + + describe("machineExpunge", () => { + it("should remove machine and return its program counter (0)", async () => { + const ext = createExt(); + const code = BytesBlob.blobFrom(MINIMAL_PROGRAM); + const initResult = await ext.machineInit(code, tryAsProgramCounter(0)); + assert.strictEqual(initResult.isOk, true); + + const machineId = initResult.ok; + const result = await ext.machineExpunge(machineId); + + assert.strictEqual(result.isOk, true); + // PC should be 0 since we initialized with PC=0 + assert.strictEqual(result.ok, tryAsProgramCounter(0)); + }); + + it("should remove machine and return its program counter (10)", async () => { + const ext = createExt(); + const code = BytesBlob.blobFrom(MINIMAL_PROGRAM); + const initResult = await ext.machineInit(code, tryAsProgramCounter(10)); + assert.strictEqual(initResult.isOk, true); + + const machineId = initResult.ok; + const result = await ext.machineExpunge(machineId); + + assert.strictEqual(result.isOk, true); + // PC should be 10 since we initialized with PC=10 + assert.strictEqual(result.ok, tryAsProgramCounter(10)); + }); + + it("should return NoMachineError for non-existent machine", async () => { + const ext = createExt(); + const result = await ext.machineExpunge(tryAsMachineId(999)); + + assert.strictEqual(result.isError, true); + }); + + it("should not allow double expunge", async () => { + const ext = createExt(); + const code = BytesBlob.blobFrom(MINIMAL_PROGRAM); + const initResult = await ext.machineInit(code, tryAsProgramCounter(0)); + + assert.strictEqual(initResult.isOk, true); + const machineId = initResult.ok; + + const r1 = await ext.machineExpunge(machineId); + assert.strictEqual(r1.isOk, true); + + const r2 = await ext.machineExpunge(machineId); + assert.strictEqual(r2.isError, true); + }); + + it("should remove exact machine from multiple and return its program counter (10)", async () => { + const ext = createExt(); + const code = BytesBlob.blobFrom(MINIMAL_PROGRAM); + await ext.machineInit(code, tryAsProgramCounter(0)); + const initResult = await ext.machineInit(code, tryAsProgramCounter(10)); + await ext.machineInit(code, tryAsProgramCounter(20)); + assert.strictEqual(initResult.isOk, true); + + const machineId = initResult.ok; + const result = await ext.machineExpunge(machineId); + + assert.strictEqual(result.isOk, true); + // PC should be 10 since we initialized with PC=10 + assert.strictEqual(result.ok, tryAsProgramCounter(10)); + }); + }); }); diff --git a/packages/jam/in-core/externalities/refine.ts b/packages/jam/in-core/externalities/refine.ts index 65f13438c..578222d64 100644 --- a/packages/jam/in-core/externalities/refine.ts +++ b/packages/jam/in-core/externalities/refine.ts @@ -13,13 +13,14 @@ import { type MachineId, type MachineResult, type MemoryOperation, - type NoMachineError, + NoMachineError, type PagesError, type PeekPokeError, type ProgramCounter, type RefineExternalities, SegmentExportError, tryAsMachineId, + tryAsProgramCounter, type ZeroVoidError, } from "@typeberry/jam-host-calls"; import type { U64 } from "@typeberry/numbers"; @@ -88,8 +89,15 @@ export class RefineExternalitiesImpl implements RefineExternalities { return this.exportedSegments; } - machineExpunge(_machineIndex: MachineId): Promise> { - throw new Error("Method not implemented."); + machineExpunge(machineIndex: MachineId): Promise> { + // We just care about machineIndex + const entry = this.machines.findExact([machineIndex, undefined as unknown as IPvmInterpreter]); + if (entry === undefined) { + return Promise.resolve(Result.error(NoMachineError, () => `Machine not found (id: ${machineIndex})`)); + } + const pc = tryAsProgramCounter(entry[1].getPC()); + this.machines.removeOne(entry); + return Promise.resolve(Result.ok(pc)); } machinePages( diff --git a/packages/jam/jam-host-calls/externalities/refine-externalities.ts b/packages/jam/jam-host-calls/externalities/refine-externalities.ts index bc858b467..ff501d7ab 100644 --- a/packages/jam/jam-host-calls/externalities/refine-externalities.ts +++ b/packages/jam/jam-host-calls/externalities/refine-externalities.ts @@ -110,7 +110,7 @@ export interface RefineExternalities { /** Get the segments exported during this work item's refinement. */ getExportedSegments(): readonly Segment[]; - /** Forget a previously started nested VM. */ + /** Forget a previously started nested VM. Return its current program counter.*/ machineExpunge(machineIndex: MachineId): Promise>; /** Set given range of pages as non-accessible and re-initialize them with zeros. */