@deroll/cmio 0.1.0
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.
- package/AUTHORS +1 -0
- package/LICENSE +202 -0
- package/README.md +122 -0
- package/binding.gyp +53 -0
- package/deps/machine-guest-tools/AUTHORS +7 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/abi.h +589 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/buf.h +82 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/io.h +168 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/keccak.h +131 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/merkle.h +118 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/rollup.h +260 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/include/libcmt/util.h +34 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/abi.c +315 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/buf.c +121 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/io-mock.c +319 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/io.c +164 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/keccak.c +156 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/merkle.c +202 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/rollup.c +455 -0
- package/deps/machine-guest-tools/sys-utils/libcmt/src/util.c +52 -0
- package/lib/index.d.mts +18 -0
- package/lib/index.d.ts +162 -0
- package/lib/index.js +230 -0
- package/lib/index.mjs +19 -0
- package/package.json +70 -0
- package/prebuilds/darwin-arm64/@deroll+cmio.node +0 -0
- package/src/addon.cc +411 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#include <errno.h>
|
|
2
|
+
#include <stdbool.h>
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
|
|
7
|
+
bool cmt_util_debug_enabled(void) {
|
|
8
|
+
static bool checked = false;
|
|
9
|
+
static bool enabled = false;
|
|
10
|
+
|
|
11
|
+
if (!checked) {
|
|
12
|
+
enabled = getenv("CMT_DEBUG") != NULL;
|
|
13
|
+
checked = true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return enabled;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
int cmt_util_read_whole_file(const char *name, size_t max, void *data, size_t *length) {
|
|
20
|
+
int rc = 0;
|
|
21
|
+
|
|
22
|
+
FILE *file = fopen(name, "rb");
|
|
23
|
+
if (!file) {
|
|
24
|
+
return -errno;
|
|
25
|
+
}
|
|
26
|
+
*length = fread(data, 1, max, file);
|
|
27
|
+
int eof = (fseek(file, 0, SEEK_END) == 0) && (*length == (size_t) ftell(file));
|
|
28
|
+
if (!eof) {
|
|
29
|
+
rc = -EIO;
|
|
30
|
+
}
|
|
31
|
+
if (fclose(file) != 0) {
|
|
32
|
+
rc = -errno;
|
|
33
|
+
}
|
|
34
|
+
return rc;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
int cmt_util_write_whole_file(const char *name, size_t length, const void *data) {
|
|
38
|
+
int rc = 0;
|
|
39
|
+
|
|
40
|
+
FILE *file = fopen(name, "wb");
|
|
41
|
+
if (!file) {
|
|
42
|
+
return -errno;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (fwrite(data, 1, length, file) != length) {
|
|
46
|
+
rc = -EIO;
|
|
47
|
+
}
|
|
48
|
+
if (fclose(file) != 0) {
|
|
49
|
+
rc = -errno;
|
|
50
|
+
}
|
|
51
|
+
return rc;
|
|
52
|
+
}
|
package/lib/index.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright Cartesi and individual authors (see AUTHORS)
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
// Types for the ESM wrapper (lib/index.mjs).
|
|
18
|
+
export * from './index.js';
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Copyright Cartesi and individual authors (see AUTHORS)
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
/// <reference types="node" />
|
|
18
|
+
|
|
19
|
+
/** 0x-prefixed hex string. Compatible with viem's `Hex` and `Address`. */
|
|
20
|
+
export type Hex = `0x${string}`;
|
|
21
|
+
|
|
22
|
+
/** Bytes input: 0x-prefixed hex string, Buffer or Uint8Array. */
|
|
23
|
+
export type BytesLike = Hex | Uint8Array;
|
|
24
|
+
|
|
25
|
+
/** EVM address: 0x-prefixed hex string (20 bytes), Buffer or Uint8Array. */
|
|
26
|
+
export type AddressLike = Hex | Uint8Array;
|
|
27
|
+
|
|
28
|
+
/** Unsigned 256-bit value: bigint, number, or 32 bytes (hex string/Uint8Array). */
|
|
29
|
+
export type U256Like = bigint | number | Hex | Uint8Array;
|
|
30
|
+
|
|
31
|
+
export const ADDRESS_LENGTH: 20;
|
|
32
|
+
export const U256_LENGTH: 32;
|
|
33
|
+
|
|
34
|
+
export interface AdvanceRequest {
|
|
35
|
+
type: 'advance';
|
|
36
|
+
/** Network chain id. */
|
|
37
|
+
chainId: bigint;
|
|
38
|
+
/** Application contract address (0x-prefixed hex). */
|
|
39
|
+
appContract: Hex;
|
|
40
|
+
/** Input sender address (0x-prefixed hex). */
|
|
41
|
+
msgSender: Hex;
|
|
42
|
+
/** Block number of this input. */
|
|
43
|
+
blockNumber: bigint;
|
|
44
|
+
/** Block timestamp of this input (UNIX epoch seconds). */
|
|
45
|
+
blockTimestamp: bigint;
|
|
46
|
+
/** RANDAO mix of the post beacon state of the previous block. */
|
|
47
|
+
prevRandao: bigint;
|
|
48
|
+
/** Input index relative to all inputs ever sent to the application. */
|
|
49
|
+
index: bigint;
|
|
50
|
+
/** Input payload. */
|
|
51
|
+
payload: Buffer;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface InspectRequest {
|
|
55
|
+
type: 'inspect';
|
|
56
|
+
/** Inspect query payload. */
|
|
57
|
+
payload: Buffer;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type RollupRequest = AdvanceRequest | InspectRequest;
|
|
61
|
+
|
|
62
|
+
export interface GioResponse {
|
|
63
|
+
responseCode: number;
|
|
64
|
+
responseData: Buffer;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Arguments for {@link Rollup.emitVoucher}. Encoded on-chain as `Voucher(address,uint256,bytes)`. */
|
|
68
|
+
export interface Voucher {
|
|
69
|
+
/** Address the voucher executes against (20 bytes): an EOA for transfers, a contract for calls. */
|
|
70
|
+
destination: AddressLike;
|
|
71
|
+
/** Amount of wei sent with the execution. Default: `0n`. */
|
|
72
|
+
value?: U256Like;
|
|
73
|
+
/** EVM calldata to execute at `destination`. Default: empty (plain transfer). */
|
|
74
|
+
payload?: BytesLike;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Arguments for {@link Rollup.emitDelegateCallVoucher}. Encoded on-chain as `DelegateCallVoucher(address,bytes)`. */
|
|
78
|
+
export interface DelegateCallVoucher {
|
|
79
|
+
/** Contract whose code runs in the application contract's storage context (20 bytes). */
|
|
80
|
+
destination: AddressLike;
|
|
81
|
+
/** Calldata for the delegate call. Default: empty. There is no `value` — `DELEGATECALL` cannot transfer ether. */
|
|
82
|
+
payload?: BytesLike;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Error thrown when a libcmt binding call fails (e.g. a too-large output, or
|
|
87
|
+
* constructing a second {@link Rollup} while one is open).
|
|
88
|
+
*
|
|
89
|
+
* Argument validation failures throw plain `TypeError`/`RangeError` instead,
|
|
90
|
+
* before anything reaches the device.
|
|
91
|
+
*/
|
|
92
|
+
export class RollupError extends Error {
|
|
93
|
+
readonly name: 'RollupError';
|
|
94
|
+
/** Negative errno reported by libcmt (e.g. `-16` for `EBUSY`). */
|
|
95
|
+
readonly errno: number;
|
|
96
|
+
/** Name of the libcmt call that failed (e.g. `cmt_rollup_init`). */
|
|
97
|
+
readonly syscall: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface RunHandlers {
|
|
101
|
+
advance?: (request: AdvanceRequest, rollup: Rollup) => boolean | void | Promise<boolean | void>;
|
|
102
|
+
inspect?: (request: InspectRequest, rollup: Rollup) => boolean | void | Promise<boolean | void>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class Rollup {
|
|
106
|
+
/**
|
|
107
|
+
* Opens the rollup device and initializes the outputs merkle tree.
|
|
108
|
+
*
|
|
109
|
+
* On riscv64 this talks to the real Cartesi Machine IO driver; on other
|
|
110
|
+
* architectures it uses the libcmt mock, driven by the CMT_INPUTS and
|
|
111
|
+
* CMT_DEBUG environment variables.
|
|
112
|
+
*/
|
|
113
|
+
constructor();
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Accept or reject the previous request and wait for the next one.
|
|
117
|
+
* Synchronous on purpose: the call yields the machine, pausing the whole
|
|
118
|
+
* guest, so nothing else could run concurrently anyway.
|
|
119
|
+
*/
|
|
120
|
+
finish(options?: { accept?: boolean }): RollupRequest;
|
|
121
|
+
|
|
122
|
+
/** Emit a voucher (Voucher(address,uint256,bytes)). Returns the output index. */
|
|
123
|
+
emitVoucher(voucher: Voucher): number;
|
|
124
|
+
|
|
125
|
+
/** Emit a delegate call voucher (DelegateCallVoucher(address,bytes)). Returns the output index. */
|
|
126
|
+
emitDelegateCallVoucher(voucher: DelegateCallVoucher): number;
|
|
127
|
+
|
|
128
|
+
/** Emit a notice (Notice(bytes)). Returns the output index. */
|
|
129
|
+
emitNotice(payload: BytesLike): number;
|
|
130
|
+
|
|
131
|
+
/** Emit a report (raw bytes, not part of the outputs merkle tree). */
|
|
132
|
+
emitReport(payload: BytesLike): void;
|
|
133
|
+
|
|
134
|
+
/** Emit an exception, signaling that the request could not be processed. */
|
|
135
|
+
emitException(payload: BytesLike): void;
|
|
136
|
+
|
|
137
|
+
/** Report progress of the current request (raw uint32 value). */
|
|
138
|
+
progress(value: number): void;
|
|
139
|
+
|
|
140
|
+
/** Perform a generic IO request to the given domain. */
|
|
141
|
+
gio(request: { domain: number; id: BytesLike }): GioResponse;
|
|
142
|
+
|
|
143
|
+
/** Load the outputs merkle tree state from a file. */
|
|
144
|
+
loadMerkle(file: string): void;
|
|
145
|
+
|
|
146
|
+
/** Store the outputs merkle tree state to a file. */
|
|
147
|
+
saveMerkle(file: string): void;
|
|
148
|
+
|
|
149
|
+
/** Reset the outputs merkle tree to pristine state. */
|
|
150
|
+
resetMerkle(): void;
|
|
151
|
+
|
|
152
|
+
/** Release the underlying device. Further calls throw. */
|
|
153
|
+
close(): void;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Convenience request loop. Handlers receive (request, rollup), may be
|
|
157
|
+
* async, and accept the request unless they return false (exceptions
|
|
158
|
+
* reject and are reported). Runs until finish fails, rejecting with that
|
|
159
|
+
* error.
|
|
160
|
+
*/
|
|
161
|
+
run(handlers?: RunHandlers): Promise<never>;
|
|
162
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// Copyright Cartesi and individual authors (see AUTHORS)
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
const path = require('node:path');
|
|
20
|
+
const binding = require('node-gyp-build')(path.join(__dirname, '..'));
|
|
21
|
+
|
|
22
|
+
const ADDRESS_LENGTH = 20;
|
|
23
|
+
const U256_LENGTH = 32;
|
|
24
|
+
const EMPTY = Buffer.alloc(0);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Error thrown when a libcmt binding call fails. Carries the negative errno
|
|
28
|
+
* reported by libcmt (e.g. `-16` for `EBUSY`) in {@link RollupError.errno} and
|
|
29
|
+
* the name of the libcmt call that failed in {@link RollupError.syscall}.
|
|
30
|
+
*
|
|
31
|
+
* Argument validation failures throw plain `TypeError`/`RangeError` instead,
|
|
32
|
+
* before anything reaches the device.
|
|
33
|
+
*/
|
|
34
|
+
class RollupError extends Error {
|
|
35
|
+
constructor(message, { errno, syscall, cause } = {}) {
|
|
36
|
+
super(message, cause === undefined ? undefined : { cause });
|
|
37
|
+
this.name = 'RollupError';
|
|
38
|
+
/** Negative errno reported by libcmt (e.g. `-16` for `EBUSY`). */
|
|
39
|
+
this.errno = errno;
|
|
40
|
+
/** Name of the libcmt call that failed (e.g. `cmt_rollup_init`). */
|
|
41
|
+
this.syscall = syscall;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Normalize an error thrown by the native addon. libcmt failures carry a
|
|
46
|
+
* numeric `errno` and the failed call name in `syscall`; those become a
|
|
47
|
+
* RollupError. Anything else (validation errors, "rollup is closed") is
|
|
48
|
+
* returned unchanged.
|
|
49
|
+
*/
|
|
50
|
+
static from(error) {
|
|
51
|
+
if (error instanceof RollupError) {
|
|
52
|
+
return error;
|
|
53
|
+
}
|
|
54
|
+
if (error != null && typeof error.errno === 'number' && typeof error.syscall === 'string') {
|
|
55
|
+
return new RollupError(error.message, { errno: error.errno, syscall: error.syscall, cause: error });
|
|
56
|
+
}
|
|
57
|
+
return error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Run a libcmt binding call, normalizing its failures into RollupError.
|
|
62
|
+
function bindingCall(fn) {
|
|
63
|
+
try {
|
|
64
|
+
return fn();
|
|
65
|
+
} catch (error) {
|
|
66
|
+
throw RollupError.from(error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function toBytes(value, name) {
|
|
71
|
+
if (typeof value === 'string') {
|
|
72
|
+
if (!/^0x(?:[0-9a-fA-F]{2})*$/.test(value)) {
|
|
73
|
+
throw new TypeError(`${name} must be a 0x-prefixed hex string, Buffer or Uint8Array`);
|
|
74
|
+
}
|
|
75
|
+
return Buffer.from(value.slice(2), 'hex');
|
|
76
|
+
}
|
|
77
|
+
if (value instanceof Uint8Array) {
|
|
78
|
+
return Buffer.isBuffer(value) ? value : Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
79
|
+
}
|
|
80
|
+
throw new TypeError(`${name} must be a 0x-prefixed hex string, Buffer or Uint8Array`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function toAddress(value, name) {
|
|
84
|
+
const bytes = toBytes(value, name);
|
|
85
|
+
if (bytes.length !== ADDRESS_LENGTH) {
|
|
86
|
+
throw new TypeError(`${name} must be ${ADDRESS_LENGTH} bytes long`);
|
|
87
|
+
}
|
|
88
|
+
return bytes;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function toU256(value, name) {
|
|
92
|
+
if (typeof value === 'bigint' || typeof value === 'number') {
|
|
93
|
+
let v = BigInt(value);
|
|
94
|
+
if (v < 0n || v >= 1n << 256n) {
|
|
95
|
+
throw new RangeError(`${name} must fit in an unsigned 256-bit integer`);
|
|
96
|
+
}
|
|
97
|
+
const bytes = Buffer.alloc(U256_LENGTH);
|
|
98
|
+
for (let i = U256_LENGTH - 1; i >= 0 && v > 0n; i--) {
|
|
99
|
+
bytes[i] = Number(v & 0xffn);
|
|
100
|
+
v >>= 8n;
|
|
101
|
+
}
|
|
102
|
+
return bytes;
|
|
103
|
+
}
|
|
104
|
+
const bytes = toBytes(value, name);
|
|
105
|
+
if (bytes.length !== U256_LENGTH) {
|
|
106
|
+
throw new TypeError(`${name} must be ${U256_LENGTH} bytes long`);
|
|
107
|
+
}
|
|
108
|
+
return bytes;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function toHex(bytes) {
|
|
112
|
+
return `0x${bytes.toString('hex')}`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
class Rollup {
|
|
116
|
+
#native;
|
|
117
|
+
|
|
118
|
+
constructor() {
|
|
119
|
+
this.#native = bindingCall(() => new binding.Rollup());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Accept or reject the previous request and wait for the next one.
|
|
124
|
+
* Synchronous on purpose: the call yields the machine, pausing the whole
|
|
125
|
+
* guest, so nothing else could run concurrently anyway.
|
|
126
|
+
*/
|
|
127
|
+
finish({ accept = true } = {}) {
|
|
128
|
+
const request = bindingCall(() => this.#native.finish(accept));
|
|
129
|
+
if (request.type === 'advance') {
|
|
130
|
+
return {
|
|
131
|
+
type: 'advance',
|
|
132
|
+
chainId: request.chainId,
|
|
133
|
+
appContract: toHex(request.appContract),
|
|
134
|
+
msgSender: toHex(request.msgSender),
|
|
135
|
+
blockNumber: request.blockNumber,
|
|
136
|
+
blockTimestamp: request.blockTimestamp,
|
|
137
|
+
prevRandao: BigInt(toHex(request.prevRandao)),
|
|
138
|
+
index: request.index,
|
|
139
|
+
payload: request.payload,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return { type: 'inspect', payload: request.payload };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Emit a voucher (Voucher(address,uint256,bytes)). Returns the output index. */
|
|
146
|
+
emitVoucher({ destination, value = 0n, payload = EMPTY }) {
|
|
147
|
+
return Number(
|
|
148
|
+
bindingCall(() =>
|
|
149
|
+
this.#native.emitVoucher(
|
|
150
|
+
toAddress(destination, 'destination'),
|
|
151
|
+
toU256(value, 'value'),
|
|
152
|
+
toBytes(payload, 'payload'),
|
|
153
|
+
),
|
|
154
|
+
),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Emit a delegate call voucher (DelegateCallVoucher(address,bytes)). Returns the output index. */
|
|
159
|
+
emitDelegateCallVoucher({ destination, payload = EMPTY }) {
|
|
160
|
+
return Number(
|
|
161
|
+
bindingCall(() =>
|
|
162
|
+
this.#native.emitDelegateCallVoucher(toAddress(destination, 'destination'), toBytes(payload, 'payload')),
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Emit a notice (Notice(bytes)). Returns the output index. */
|
|
168
|
+
emitNotice(payload) {
|
|
169
|
+
return Number(bindingCall(() => this.#native.emitNotice(toBytes(payload, 'payload'))));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Emit a report (raw bytes, not part of the outputs merkle tree). */
|
|
173
|
+
emitReport(payload) {
|
|
174
|
+
bindingCall(() => this.#native.emitReport(toBytes(payload, 'payload')));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Emit an exception, signaling that the request could not be processed. */
|
|
178
|
+
emitException(payload) {
|
|
179
|
+
bindingCall(() => this.#native.emitException(toBytes(payload, 'payload')));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Report progress of the current request (raw uint32 value). */
|
|
183
|
+
progress(value) {
|
|
184
|
+
bindingCall(() => this.#native.progress(value));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Perform a generic IO request to the given domain. */
|
|
188
|
+
gio({ domain, id }) {
|
|
189
|
+
return bindingCall(() => this.#native.gio(domain, toBytes(id, 'id')));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
loadMerkle(file) {
|
|
193
|
+
bindingCall(() => this.#native.loadMerkle(String(file)));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
saveMerkle(file) {
|
|
197
|
+
bindingCall(() => this.#native.saveMerkle(String(file)));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
resetMerkle() {
|
|
201
|
+
bindingCall(() => this.#native.resetMerkle());
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Release the underlying device. Further calls throw. */
|
|
205
|
+
close() {
|
|
206
|
+
bindingCall(() => this.#native.close());
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Convenience request loop. Handlers receive (request, rollup), may be
|
|
211
|
+
* async, and accept the request unless they return false (exceptions
|
|
212
|
+
* reject and are reported). Runs until finish fails (e.g. mock inputs are
|
|
213
|
+
* exhausted, or the device is closed), which rejects with that error.
|
|
214
|
+
*/
|
|
215
|
+
async run(handlers = {}) {
|
|
216
|
+
let accept = true;
|
|
217
|
+
for (;;) {
|
|
218
|
+
const request = this.finish({ accept });
|
|
219
|
+
const handler = handlers[request.type];
|
|
220
|
+
try {
|
|
221
|
+
accept = handler ? (await handler(request, this)) !== false : false;
|
|
222
|
+
} catch (error) {
|
|
223
|
+
accept = false;
|
|
224
|
+
this.emitReport(Buffer.from(String(error?.stack ?? error)));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
module.exports = { Rollup, RollupError, ADDRESS_LENGTH, U256_LENGTH };
|
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright Cartesi and individual authors (see AUTHORS)
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
// ESM wrapper over the CommonJS implementation, so both module systems share
|
|
18
|
+
// the single native addon instance (no dual-package hazard).
|
|
19
|
+
export { Rollup, RollupError, ADDRESS_LENGTH, U256_LENGTH } from './index.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deroll/cmio",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Node.js bindings for libcmt, the Cartesi Machine guest rollup library",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cartesi",
|
|
7
|
+
"rollups",
|
|
8
|
+
"libcmt",
|
|
9
|
+
"riscv64"
|
|
10
|
+
],
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"author": "Cartesi and individual authors (see AUTHORS)",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/tuler/deroll"
|
|
16
|
+
},
|
|
17
|
+
"main": "lib/index.js",
|
|
18
|
+
"types": "lib/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./lib/index.d.mts",
|
|
23
|
+
"default": "./lib/index.mjs"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./lib/index.d.ts",
|
|
27
|
+
"default": "./lib/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"AUTHORS",
|
|
34
|
+
"binding.gyp",
|
|
35
|
+
"lib/",
|
|
36
|
+
"src/",
|
|
37
|
+
"prebuilds/",
|
|
38
|
+
"deps/machine-guest-tools/sys-utils/libcmt/include/",
|
|
39
|
+
"deps/machine-guest-tools/sys-utils/libcmt/src/"
|
|
40
|
+
],
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"install": "node-gyp-build",
|
|
46
|
+
"build": "node-gyp rebuild",
|
|
47
|
+
"prebuild": "prebuildify --napi --strip",
|
|
48
|
+
"test": "node --test \"test/*.test.mjs\"",
|
|
49
|
+
"check:package": "attw --pack ."
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"node-addon-api": "^8.3.0",
|
|
53
|
+
"node-gyp-build": "^4.8.4"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@arethetypeswrong/cli": "^0.18.3",
|
|
57
|
+
"@types/node": "^25.9.2",
|
|
58
|
+
"node-gyp": "^11.0.0",
|
|
59
|
+
"prebuildify": "^6.0.1",
|
|
60
|
+
"typescript": "^6.0.3"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18"
|
|
64
|
+
},
|
|
65
|
+
"binary": {
|
|
66
|
+
"napi_versions": [
|
|
67
|
+
8
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
Binary file
|