@aztec/native 0.73.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/README.md +3 -0
- package/dest/index.d.ts +3 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +3 -0
- package/dest/msgpack_channel.d.ts +27 -0
- package/dest/msgpack_channel.d.ts.map +1 -0
- package/dest/msgpack_channel.js +69 -0
- package/dest/native_module.d.ts +8 -0
- package/dest/native_module.d.ts.map +1 -0
- package/dest/native_module.js +5 -0
- package/package.json +78 -0
- package/src/index.ts +2 -0
- package/src/msgpack_channel.ts +109 -0
- package/src/native_module.ts +12 -0
package/README.md
ADDED
package/dest/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dest/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export * from './native_module.js';
|
|
2
|
+
export { MsgpackChannel } from './msgpack_channel.js';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxPQUFPLEVBQXFCLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDIn0=
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
export interface MessageReceiver {
|
|
4
|
+
call(msg: Buffer | Uint8Array): Promise<Buffer | Uint8Array>;
|
|
5
|
+
}
|
|
6
|
+
export type RoundtripDuration = {
|
|
7
|
+
encodingUs: number;
|
|
8
|
+
callUs: number;
|
|
9
|
+
decodingUs: number;
|
|
10
|
+
totalUs: number;
|
|
11
|
+
};
|
|
12
|
+
type MessageBody<T extends number> = {
|
|
13
|
+
[K in T]: object | void;
|
|
14
|
+
};
|
|
15
|
+
export declare class MsgpackChannel<M extends number = number, Req extends MessageBody<M> = any, Resp extends MessageBody<M> = any> {
|
|
16
|
+
private dest;
|
|
17
|
+
/** A long-lived msgpack encoder */
|
|
18
|
+
private encoder;
|
|
19
|
+
private msgId;
|
|
20
|
+
constructor(dest: MessageReceiver);
|
|
21
|
+
sendMessage<T extends M>(msgType: T, body: Req[T]): Promise<{
|
|
22
|
+
duration: RoundtripDuration;
|
|
23
|
+
response: Resp[T];
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=msgpack_channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msgpack_channel.d.ts","sourceRoot":"","sources":["../src/msgpack_channel.ts"],"names":[],"mappings":";;AAMA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;CAC9D;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAYF,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI;KAAG,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI;CAAE,CAAC;AAEjE,qBAAa,cAAc,CACzB,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,GAAG,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG,EAChC,IAAI,SAAS,WAAW,CAAC,CAAC,CAAC,GAAG,GAAG;IAYd,OAAO,CAAC,IAAI;IAV/B,mCAAmC;IACnC,OAAO,CAAC,OAAO,CAKZ;IAEH,OAAO,CAAC,KAAK,CAAK;gBAES,IAAI,EAAE,eAAe;IAEnC,WAAW,CAAC,CAAC,SAAS,CAAC,EAClC,OAAO,EAAE,CAAC,EACV,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,GACX,OAAO,CAAC;QAAE,QAAQ,EAAE,iBAAiB,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC;CA2D/D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { MessageHeader, TypedMessage } from '@aztec/foundation/message';
|
|
3
|
+
import { Encoder, addExtension } from 'msgpackr';
|
|
4
|
+
import { isAnyArrayBuffer } from 'util/types';
|
|
5
|
+
// small extension to pack an NodeJS Fr instance to a representation that the C++ code can understand
|
|
6
|
+
// this only works for writes. Unpacking from C++ can't create Fr instances because the data is passed
|
|
7
|
+
// as raw, untagged, buffers. On the NodeJS side we don't know what the buffer represents
|
|
8
|
+
// Adding a tag would be a solution, but it would have to be done on both sides and it's unclear where else
|
|
9
|
+
// C++ fr instances are sent/received/stored.
|
|
10
|
+
addExtension({
|
|
11
|
+
Class: Fr,
|
|
12
|
+
write: fr => fr.toBuffer(),
|
|
13
|
+
});
|
|
14
|
+
export class MsgpackChannel {
|
|
15
|
+
constructor(dest) {
|
|
16
|
+
this.dest = dest;
|
|
17
|
+
/** A long-lived msgpack encoder */
|
|
18
|
+
this.encoder = new Encoder({
|
|
19
|
+
// always encode JS objects as MessagePack maps
|
|
20
|
+
// this makes it compatible with other MessagePack decoders
|
|
21
|
+
useRecords: false,
|
|
22
|
+
int64AsType: 'bigint',
|
|
23
|
+
});
|
|
24
|
+
this.msgId = 1;
|
|
25
|
+
}
|
|
26
|
+
async sendMessage(msgType, body) {
|
|
27
|
+
const duration = {
|
|
28
|
+
callUs: 0,
|
|
29
|
+
totalUs: 0,
|
|
30
|
+
decodingUs: 0,
|
|
31
|
+
encodingUs: 0,
|
|
32
|
+
};
|
|
33
|
+
const start = process.hrtime.bigint();
|
|
34
|
+
const requestId = this.msgId++;
|
|
35
|
+
const request = new TypedMessage(msgType, new MessageHeader({ requestId }), body);
|
|
36
|
+
const encodedRequest = this.encoder.encode(request);
|
|
37
|
+
const encodingEnd = process.hrtime.bigint();
|
|
38
|
+
duration.encodingUs = Number((encodingEnd - start) / 1000n);
|
|
39
|
+
const encodedResponse = await this.dest.call(encodedRequest);
|
|
40
|
+
const callEnd = process.hrtime.bigint();
|
|
41
|
+
duration.callUs = Number((callEnd - encodingEnd) / 1000n);
|
|
42
|
+
const buf = Buffer.isBuffer(encodedResponse)
|
|
43
|
+
? encodedResponse
|
|
44
|
+
: isAnyArrayBuffer(encodedResponse)
|
|
45
|
+
? Buffer.from(encodedResponse)
|
|
46
|
+
: encodedResponse;
|
|
47
|
+
if (!Buffer.isBuffer(buf)) {
|
|
48
|
+
throw new TypeError('Invalid encoded response: expected Buffer or ArrayBuffer, got ' +
|
|
49
|
+
(encodedResponse === null ? 'null' : typeof encodedResponse));
|
|
50
|
+
}
|
|
51
|
+
const decodedResponse = this.encoder.unpack(buf);
|
|
52
|
+
if (!TypedMessage.isTypedMessageLike(decodedResponse)) {
|
|
53
|
+
throw new TypeError('Invalid response: expected TypedMessageLike, got ' +
|
|
54
|
+
(decodedResponse === null ? 'null' : typeof decodedResponse));
|
|
55
|
+
}
|
|
56
|
+
const response = TypedMessage.fromMessagePack(decodedResponse);
|
|
57
|
+
const decodingEnd = process.hrtime.bigint();
|
|
58
|
+
duration.decodingUs = Number((decodingEnd - callEnd) / 1000n);
|
|
59
|
+
if (response.header.requestId !== request.header.messageId) {
|
|
60
|
+
throw new Error('Response ID does not match request: ' + response.header.requestId + ' != ' + request.header.messageId);
|
|
61
|
+
}
|
|
62
|
+
if (response.msgType !== request.msgType) {
|
|
63
|
+
throw new Error('Invalid response message type: ' + response.msgType + ' != ' + response.msgType);
|
|
64
|
+
}
|
|
65
|
+
duration.totalUs = Number((process.hrtime.bigint() - start) / 1000n);
|
|
66
|
+
return { duration, response: response.value };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXNncGFja19jaGFubmVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21zZ3BhY2tfY2hhbm5lbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUV4RSxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFhOUMscUdBQXFHO0FBQ3JHLHNHQUFzRztBQUN0Ryx5RkFBeUY7QUFDekYsMkdBQTJHO0FBQzNHLDZDQUE2QztBQUM3QyxZQUFZLENBQUM7SUFDWCxLQUFLLEVBQUUsRUFBRTtJQUNULEtBQUssRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDM0IsQ0FBQyxDQUFDO0FBSUgsTUFBTSxPQUFPLGNBQWM7SUFlekIsWUFBMkIsSUFBcUI7UUFBckIsU0FBSSxHQUFKLElBQUksQ0FBaUI7UUFWaEQsbUNBQW1DO1FBQzNCLFlBQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQztZQUM1QiwrQ0FBK0M7WUFDL0MsMkRBQTJEO1lBQzNELFVBQVUsRUFBRSxLQUFLO1lBQ2pCLFdBQVcsRUFBRSxRQUFRO1NBQ3RCLENBQUMsQ0FBQztRQUVLLFVBQUssR0FBRyxDQUFDLENBQUM7SUFFaUMsQ0FBQztJQUU3QyxLQUFLLENBQUMsV0FBVyxDQUN0QixPQUFVLEVBQ1YsSUFBWTtRQUVaLE1BQU0sUUFBUSxHQUFzQjtZQUNsQyxNQUFNLEVBQUUsQ0FBQztZQUNULE9BQU8sRUFBRSxDQUFDO1lBQ1YsVUFBVSxFQUFFLENBQUM7WUFDYixVQUFVLEVBQUUsQ0FBQztTQUNkLENBQUM7UUFFRixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3RDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUUvQixNQUFNLE9BQU8sR0FBRyxJQUFJLFlBQVksQ0FBQyxPQUFPLEVBQUUsSUFBSSxhQUFhLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2xGLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3BELE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDNUMsUUFBUSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFFNUQsTUFBTSxlQUFlLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUM3RCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3hDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLENBQUMsT0FBTyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO1FBRTFELE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDO1lBQzFDLENBQUMsQ0FBQyxlQUFlO1lBQ2pCLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUM7Z0JBQ25DLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQztnQkFDOUIsQ0FBQyxDQUFDLGVBQWUsQ0FBQztRQUVwQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzFCLE1BQU0sSUFBSSxTQUFTLENBQ2pCLGdFQUFnRTtnQkFDOUQsQ0FBQyxlQUFlLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sZUFBZSxDQUFDLENBQy9ELENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1lBQ3RELE1BQU0sSUFBSSxTQUFTLENBQ2pCLG1EQUFtRDtnQkFDakQsQ0FBQyxlQUFlLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sZUFBZSxDQUFDLENBQy9ELENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLGVBQWUsQ0FBYSxlQUFlLENBQUMsQ0FBQztRQUMzRSxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzVDLFFBQVEsQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDO1FBRTlELElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEtBQUssT0FBTyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMzRCxNQUFNLElBQUksS0FBSyxDQUNiLHNDQUFzQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUyxHQUFHLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FDdkcsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLFFBQVEsQ0FBQyxPQUFPLEtBQUssT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pDLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLEdBQUcsUUFBUSxDQUFDLE9BQU8sR0FBRyxNQUFNLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3BHLENBQUM7UUFFRCxRQUFRLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFFckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2hELENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type MessageReceiver } from './msgpack_channel.js';
|
|
2
|
+
interface NativeClassCtor {
|
|
3
|
+
new (...args: unknown[]): MessageReceiver;
|
|
4
|
+
}
|
|
5
|
+
export declare const NativeWorldState: NativeClassCtor;
|
|
6
|
+
export declare const NativeLMDBStore: NativeClassCtor;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=native_module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native_module.d.ts","sourceRoot":"","sources":["../src/native_module.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,UAAU,eAAe;IACvB,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;CAC3C;AAID,eAAO,MAAM,gBAAgB,EAAE,eAAyC,CAAC;AACzE,eAAO,MAAM,eAAe,EAAE,eAAwC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import bindings from 'bindings';
|
|
2
|
+
const nativeModule = bindings('nodejs_module');
|
|
3
|
+
export const NativeWorldState = nativeModule.WorldState;
|
|
4
|
+
export const NativeLMDBStore = nativeModule.LMDBStore;
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX21vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9uYXRpdmVfbW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sUUFBUSxNQUFNLFVBQVUsQ0FBQztBQVFoQyxNQUFNLFlBQVksR0FBb0MsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBRWhGLE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFvQixZQUFZLENBQUMsVUFBVSxDQUFDO0FBQ3pFLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBb0IsWUFBWSxDQUFDLFNBQVMsQ0FBQyJ9
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aztec/native",
|
|
3
|
+
"version": "0.73.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./dest/index.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "yarn clean && yarn generate && tsc -b",
|
|
10
|
+
"build:dev": "tsc -b --watch",
|
|
11
|
+
"build:cpp": "PROJECT=$(pwd); cd $(git rev-parse --show-toplevel)/barretenberg/cpp; cmake --preset ${PRESET:-clang16-pic} && cmake --build --preset ${PRESET:-clang16-pic} --target nodejs_module && cd $PROJECT && yarn generate",
|
|
12
|
+
"clean:cpp": "rm -rf $(git rev-parse --show-toplevel)/barretenberg/cpp/build-pic",
|
|
13
|
+
"clean": "rm -rf ./dest .tsbuildinfo",
|
|
14
|
+
"formatting": "run -T prettier --check ./src && run -T eslint ./src",
|
|
15
|
+
"formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
|
|
16
|
+
"test": "HARDWARE_CONCURRENCY=${HARDWARE_CONCURRENCY:-16} RAYON_NUM_THREADS=${RAYON_NUM_THREADS:-4} NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
|
|
17
|
+
"generate": "mkdir -p build && cp -v $(git rev-parse --show-toplevel)/barretenberg/cpp/build-pic/lib/nodejs_module.node build"
|
|
18
|
+
},
|
|
19
|
+
"inherits": [
|
|
20
|
+
"../package.common.json",
|
|
21
|
+
"./package.local.json"
|
|
22
|
+
],
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@aztec/foundation": "0.73.0",
|
|
25
|
+
"bindings": "^1.5.0",
|
|
26
|
+
"msgpackr": "^1.11.2"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@jest/globals": "^29.5.0",
|
|
30
|
+
"@types/bindings": "^1.5.5",
|
|
31
|
+
"@types/jest": "^29.5.0",
|
|
32
|
+
"@types/node": "^18.7.23",
|
|
33
|
+
"jest": "^29.5.0",
|
|
34
|
+
"ts-node": "^10.9.1",
|
|
35
|
+
"typescript": "^5.0.4"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dest",
|
|
39
|
+
"src",
|
|
40
|
+
"!*.test.*"
|
|
41
|
+
],
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"jest": {
|
|
46
|
+
"extensionsToTreatAsEsm": [
|
|
47
|
+
".ts"
|
|
48
|
+
],
|
|
49
|
+
"transform": {
|
|
50
|
+
"^.+\\.tsx?$": [
|
|
51
|
+
"@swc/jest",
|
|
52
|
+
{
|
|
53
|
+
"jsc": {
|
|
54
|
+
"parser": {
|
|
55
|
+
"syntax": "typescript",
|
|
56
|
+
"decorators": true
|
|
57
|
+
},
|
|
58
|
+
"transform": {
|
|
59
|
+
"decoratorVersion": "2022-03"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"moduleNameMapper": {
|
|
66
|
+
"^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
|
|
67
|
+
},
|
|
68
|
+
"reporters": [
|
|
69
|
+
"default"
|
|
70
|
+
],
|
|
71
|
+
"testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
|
|
72
|
+
"rootDir": "./src",
|
|
73
|
+
"testTimeout": 30000,
|
|
74
|
+
"setupFiles": [
|
|
75
|
+
"../../foundation/src/jest/setup.mjs"
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { MessageHeader, TypedMessage } from '@aztec/foundation/message';
|
|
3
|
+
|
|
4
|
+
import { Encoder, addExtension } from 'msgpackr';
|
|
5
|
+
import { isAnyArrayBuffer } from 'util/types';
|
|
6
|
+
|
|
7
|
+
export interface MessageReceiver {
|
|
8
|
+
call(msg: Buffer | Uint8Array): Promise<Buffer | Uint8Array>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type RoundtripDuration = {
|
|
12
|
+
encodingUs: number;
|
|
13
|
+
callUs: number;
|
|
14
|
+
decodingUs: number;
|
|
15
|
+
totalUs: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// small extension to pack an NodeJS Fr instance to a representation that the C++ code can understand
|
|
19
|
+
// this only works for writes. Unpacking from C++ can't create Fr instances because the data is passed
|
|
20
|
+
// as raw, untagged, buffers. On the NodeJS side we don't know what the buffer represents
|
|
21
|
+
// Adding a tag would be a solution, but it would have to be done on both sides and it's unclear where else
|
|
22
|
+
// C++ fr instances are sent/received/stored.
|
|
23
|
+
addExtension({
|
|
24
|
+
Class: Fr,
|
|
25
|
+
write: fr => fr.toBuffer(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
type MessageBody<T extends number> = { [K in T]: object | void };
|
|
29
|
+
|
|
30
|
+
export class MsgpackChannel<
|
|
31
|
+
M extends number = number,
|
|
32
|
+
Req extends MessageBody<M> = any,
|
|
33
|
+
Resp extends MessageBody<M> = any,
|
|
34
|
+
> {
|
|
35
|
+
/** A long-lived msgpack encoder */
|
|
36
|
+
private encoder = new Encoder({
|
|
37
|
+
// always encode JS objects as MessagePack maps
|
|
38
|
+
// this makes it compatible with other MessagePack decoders
|
|
39
|
+
useRecords: false,
|
|
40
|
+
int64AsType: 'bigint',
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
private msgId = 1;
|
|
44
|
+
|
|
45
|
+
public constructor(private dest: MessageReceiver) {}
|
|
46
|
+
|
|
47
|
+
public async sendMessage<T extends M>(
|
|
48
|
+
msgType: T,
|
|
49
|
+
body: Req[T],
|
|
50
|
+
): Promise<{ duration: RoundtripDuration; response: Resp[T] }> {
|
|
51
|
+
const duration: RoundtripDuration = {
|
|
52
|
+
callUs: 0,
|
|
53
|
+
totalUs: 0,
|
|
54
|
+
decodingUs: 0,
|
|
55
|
+
encodingUs: 0,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const start = process.hrtime.bigint();
|
|
59
|
+
const requestId = this.msgId++;
|
|
60
|
+
|
|
61
|
+
const request = new TypedMessage(msgType, new MessageHeader({ requestId }), body);
|
|
62
|
+
const encodedRequest = this.encoder.encode(request);
|
|
63
|
+
const encodingEnd = process.hrtime.bigint();
|
|
64
|
+
duration.encodingUs = Number((encodingEnd - start) / 1000n);
|
|
65
|
+
|
|
66
|
+
const encodedResponse = await this.dest.call(encodedRequest);
|
|
67
|
+
const callEnd = process.hrtime.bigint();
|
|
68
|
+
duration.callUs = Number((callEnd - encodingEnd) / 1000n);
|
|
69
|
+
|
|
70
|
+
const buf = Buffer.isBuffer(encodedResponse)
|
|
71
|
+
? encodedResponse
|
|
72
|
+
: isAnyArrayBuffer(encodedResponse)
|
|
73
|
+
? Buffer.from(encodedResponse)
|
|
74
|
+
: encodedResponse;
|
|
75
|
+
|
|
76
|
+
if (!Buffer.isBuffer(buf)) {
|
|
77
|
+
throw new TypeError(
|
|
78
|
+
'Invalid encoded response: expected Buffer or ArrayBuffer, got ' +
|
|
79
|
+
(encodedResponse === null ? 'null' : typeof encodedResponse),
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const decodedResponse = this.encoder.unpack(buf);
|
|
84
|
+
if (!TypedMessage.isTypedMessageLike(decodedResponse)) {
|
|
85
|
+
throw new TypeError(
|
|
86
|
+
'Invalid response: expected TypedMessageLike, got ' +
|
|
87
|
+
(decodedResponse === null ? 'null' : typeof decodedResponse),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const response = TypedMessage.fromMessagePack<T, Resp[T]>(decodedResponse);
|
|
92
|
+
const decodingEnd = process.hrtime.bigint();
|
|
93
|
+
duration.decodingUs = Number((decodingEnd - callEnd) / 1000n);
|
|
94
|
+
|
|
95
|
+
if (response.header.requestId !== request.header.messageId) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
'Response ID does not match request: ' + response.header.requestId + ' != ' + request.header.messageId,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (response.msgType !== request.msgType) {
|
|
102
|
+
throw new Error('Invalid response message type: ' + response.msgType + ' != ' + response.msgType);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
duration.totalUs = Number((process.hrtime.bigint() - start) / 1000n);
|
|
106
|
+
|
|
107
|
+
return { duration, response: response.value };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import bindings from 'bindings';
|
|
2
|
+
|
|
3
|
+
import { type MessageReceiver } from './msgpack_channel.js';
|
|
4
|
+
|
|
5
|
+
interface NativeClassCtor {
|
|
6
|
+
new (...args: unknown[]): MessageReceiver;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const nativeModule: Record<string, NativeClassCtor> = bindings('nodejs_module');
|
|
10
|
+
|
|
11
|
+
export const NativeWorldState: NativeClassCtor = nativeModule.WorldState;
|
|
12
|
+
export const NativeLMDBStore: NativeClassCtor = nativeModule.LMDBStore;
|