Skip to content

Commit 0760176

Browse files
committed
feat!: track the input completion changes of next/2.0
These two changes are not part of rollups-node PR 793, but that PR has now merged, so they are simply part of the node API these packages target. `InputStatus` loses its resource-limit members. The node collapsed OUTPUTS_LIMIT_EXCEEDED, REPORTS_LIMIT_EXCEEDED, CYCLE_LIMIT_EXCEEDED, TIME_LIMIT_EXCEEDED and PAYLOAD_LENGTH_LIMIT_EXCEEDED into the remaining outcomes, leaving NONE, ACCEPTED, REJECTED, EXCEPTION and MACHINE_HALTED. Declaring the removed ones promised statuses the node can no longer return. `waitForInput` listed four of them under `rejectErrors`; it now aborts on EXCEPTION, MACHINE_HALTED and REJECTED, which is every terminal status other than ACCEPTED — and, incidentally, no longer omits a failure status the way the old list omitted REPORTS_LIMIT_EXCEEDED. `Input` gains `exception_data` / `exceptionData`, the raw guest-provided CMIO exception payload, non-null only when the status is EXCEPTION and empty-encoded as 0x. The bytes are passed through undecoded, matching how `raw_data` is handled. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UJpa3KXxvUarBGpHvW8Qdb
1 parent 8410eca commit 0760176

6 files changed

Lines changed: 56 additions & 12 deletions

File tree

.changeset/tricky-pianos-shake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ New filters on the listing methods:
2020

2121
The node rejects an empty filter list with invalid params, so both list-valued filters use the new `NonEmptyArray` type exported by `@cartesi/rpc` (and re-exported by `@cartesi/client`): `status: []` and `outputType: []` are compile errors rather than failed requests.
2222

23+
Input completion changes:
24+
25+
- `InputStatus` lost its resource-limit members. The node collapsed `OUTPUTS_LIMIT_EXCEEDED`, `REPORTS_LIMIT_EXCEEDED`, `CYCLE_LIMIT_EXCEEDED`, `TIME_LIMIT_EXCEEDED` and `PAYLOAD_LENGTH_LIMIT_EXCEEDED` into the remaining outcomes, so the union is now `NONE | ACCEPTED | REJECTED | EXCEPTION | MACHINE_HALTED`. Code that switches on the removed members no longer compiles; `waitForInput` with `rejectErrors` now aborts on `EXCEPTION`, `MACHINE_HALTED` and `REJECTED`, which is every terminal status other than `ACCEPTED`.
26+
- `Input` gained `exceptionData: Hex | null` (`exception_data` on the wire), the raw guest-provided CMIO exception payload. It is non-null only when `status` is `EXCEPTION`, and an empty payload is `0x`. The bytes are passed through undecoded.
27+
2328
Breaking changes:
2429

2530
- `cartesi_getMatchAdvanced` was renamed to `cartesi_getMatchAdvance`, following the node. The `getMatchAdvanced` action is now `getMatchAdvance`, the `useMatchAdvanced` hook is now `useMatchAdvance` (with `matchAdvanceOptions` / `matchAdvanceQueryKey`), and `GetMatchAdvancedParams` / `GetMatchAdvancedReturnType` are now `GetMatchAdvanceParams` / `GetMatchAdvanceReturnType`.

packages/client/__tests__/converter.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ describe("converter", () => {
491491
payload: "0xdeadbeef",
492492
},
493493
status: "ACCEPTED",
494+
exception_data: null,
494495
machine_hash: null,
495496
outputs_hash: null,
496497
transaction_hash:
@@ -506,6 +507,7 @@ describe("converter", () => {
506507
expect(input.blockNumber).toBe(hexToBigInt(rpcInput.block_number));
507508
expect(input.rawData).toBe(rpcInput.raw_data);
508509
expect(input.status).toBe(rpcInput.status);
510+
expect(input.exceptionData).toBeNull();
509511
expect(input.machineHash).toBeNull();
510512
expect(input.outputsHash).toBeNull();
511513
expect(input.transactionHash).toBe(rpcInput.transaction_hash);
@@ -528,6 +530,30 @@ describe("converter", () => {
528530
expect(input.updatedAt).toStrictEqual(new Date(rpcInput.updated_at));
529531
});
530532

533+
it("should carry the exception data of a failed input", () => {
534+
const rpcInput: Input = {
535+
epoch_index: "0x1",
536+
index: "0x8",
537+
block_number: "0x1f5",
538+
raw_data: "0x415bf363",
539+
decoded_data: null,
540+
status: "EXCEPTION",
541+
exception_data: "0x6f6f7073",
542+
machine_hash: null,
543+
outputs_hash: null,
544+
transaction_hash:
545+
"0x8f2c9ab4d7e15c30b6f18a4ee2d9037c4a1f5d2e9b7c63a0d4e8f1b25c7a9d3e",
546+
log_index: "0x3",
547+
created_at: "2025-04-11T10:00:00.000Z",
548+
updated_at: "2025-04-11T10:05:00.000Z",
549+
};
550+
551+
const input = inputConverter(rpcInput);
552+
expect(input.status).toBe("EXCEPTION");
553+
// passed through as raw bytes, not decoded
554+
expect(input.exceptionData).toBe("0x6f6f7073");
555+
});
556+
531557
it("should convert the report", () => {
532558
const rpcReport: Report = {
533559
epoch_index: "0x1",

packages/client/src/actions/waitForInput.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,13 @@ export const waitForInput = async (
3737
throw new Error("Input is not processed");
3838
}
3939

40+
// every terminal status other than ACCEPTED; the node collapsed its
41+
// resource-limit statuses into these
4042
if (
4143
rejectErrors &&
42-
(input.status === "CYCLE_LIMIT_EXCEEDED" ||
43-
input.status === "EXCEPTION" ||
44+
(input.status === "EXCEPTION" ||
4445
input.status === "MACHINE_HALTED" ||
45-
input.status === "PAYLOAD_LENGTH_LIMIT_EXCEEDED" ||
46-
input.status === "REJECTED" ||
47-
input.status === "TIME_LIMIT_EXCEEDED" ||
48-
input.status === "OUTPUTS_LIMIT_EXCEEDED")
46+
input.status === "REJECTED")
4947
) {
5048
throw new AbortError(`Input status: ${input.status}`);
5149
}

packages/client/src/types/actions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,11 @@ export type Input = {
298298
payload: Hex;
299299
} | null;
300300
status: InputStatus;
301+
/**
302+
* Raw guest-provided CMIO exception payload. Non-null only when `status` is
303+
* `EXCEPTION`; an empty payload is `0x`.
304+
*/
305+
exceptionData: Hex | null;
301306
machineHash: Hash | null;
302307
outputsHash: Hash | null;
303308
transactionHash: Hash;

packages/client/src/types/converter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ export const inputConverter = (input: InputRpc): Input => {
320320
}
321321
: null,
322322
status: input.status,
323+
exceptionData: input.exception_data,
323324
machineHash: input.machine_hash,
324325
outputsHash: input.outputs_hash,
325326
transactionHash: input.transaction_hash,

packages/rpc/src/types.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,21 @@ export type EpochStatus =
6060
| "CLAIM_REJECTED"
6161
| "CLAIM_FORECLOSED";
6262

63+
/**
64+
* Outcome of running an input through the machine. `NONE` means the input has
65+
* not completed yet; the rest are terminal.
66+
*
67+
* The node collapsed its former resource-limit statuses
68+
* (`OUTPUTS_LIMIT_EXCEEDED`, `REPORTS_LIMIT_EXCEEDED`, `CYCLE_LIMIT_EXCEEDED`,
69+
* `TIME_LIMIT_EXCEEDED`, `PAYLOAD_LENGTH_LIMIT_EXCEEDED`) into the outcomes
70+
* below, so they are no longer part of the union.
71+
*/
6372
export type InputStatus =
6473
| "NONE"
6574
| "ACCEPTED"
6675
| "REJECTED"
6776
| "EXCEPTION"
68-
| "MACHINE_HALTED"
69-
| "OUTPUTS_LIMIT_EXCEEDED"
70-
| "REPORTS_LIMIT_EXCEEDED"
71-
| "CYCLE_LIMIT_EXCEEDED"
72-
| "TIME_LIMIT_EXCEEDED"
73-
| "PAYLOAD_LENGTH_LIMIT_EXCEEDED";
77+
| "MACHINE_HALTED";
7478

7579
export type ConsensusType = "AUTHORITY" | "QUORUM" | "PRT";
7680

@@ -221,6 +225,11 @@ export type Input = {
221225
payload: Hex;
222226
} | null;
223227
status: InputStatus;
228+
/**
229+
* Raw guest-provided CMIO exception payload. Non-null only when `status` is
230+
* `EXCEPTION`; an empty payload is encoded as `0x`.
231+
*/
232+
exception_data: Hex | null;
224233
machine_hash: Hash | null;
225234
outputs_hash: Hash | null;
226235
transaction_hash: Hash;

0 commit comments

Comments
 (0)