@aztec-labs/native 6.0.0-nightly.20260829

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 ADDED
@@ -0,0 +1,3 @@
1
+ # Native module
2
+
3
+ A package containing all the native bindings needed to run Aztec.
@@ -0,0 +1,3 @@
1
+ export * from './native_module.js';
2
+ export { type RoundtripDuration, MsgpackChannel } from './msgpack_channel.js';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxNQUFNLHNCQUFzQixDQUFDIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,KAAK,iBAAiB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
package/dest/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './native_module.js';
2
+ export { MsgpackChannel } from './msgpack_channel.js';
@@ -0,0 +1,25 @@
1
+ export interface MessageReceiver {
2
+ call(msg: Buffer | Uint8Array): Promise<Buffer | Uint8Array>;
3
+ }
4
+ export type RoundtripDuration = {
5
+ encodingUs: number;
6
+ callUs: number;
7
+ decodingUs: number;
8
+ totalUs: number;
9
+ };
10
+ type MessageBody<T extends number> = {
11
+ [K in T]: object | void;
12
+ };
13
+ export declare class MsgpackChannel<M extends number = number, Req extends MessageBody<M> = any, Resp extends MessageBody<M> = any> {
14
+ private dest;
15
+ /** A long-lived msgpack encoder */
16
+ private encoder;
17
+ private msgId;
18
+ constructor(dest: MessageReceiver);
19
+ sendMessage<T extends M>(msgType: T, body: Req[T]): Promise<{
20
+ duration: RoundtripDuration;
21
+ response: Resp[T];
22
+ }>;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXNncGFja19jaGFubmVsLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbXNncGFja19jaGFubmVsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUtBLE1BQU0sV0FBVyxlQUFlO0lBQzlCLElBQUksQ0FBQyxHQUFHLEVBQUUsTUFBTSxHQUFHLFVBQVUsR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxDQUFDO0NBQzlEO0FBRUQsTUFBTSxNQUFNLGlCQUFpQixHQUFHO0lBQzlCLFVBQVUsRUFBRSxNQUFNLENBQUM7SUFDbkIsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLFVBQVUsRUFBRSxNQUFNLENBQUM7SUFDbkIsT0FBTyxFQUFFLE1BQU0sQ0FBQztDQUNqQixDQUFDO0FBWUYsS0FBSyxXQUFXLENBQUMsQ0FBQyxTQUFTLE1BQU0sSUFBSTtLQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxHQUFHLElBQUk7Q0FBRSxDQUFDO0FBRWpFLHFCQUFhLGNBQWMsQ0FDekIsQ0FBQyxTQUFTLE1BQU0sR0FBRyxNQUFNLEVBQ3pCLEdBQUcsU0FBUyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxFQUNoQyxJQUFJLFNBQVMsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUc7SUFZZCxPQUFPLENBQUMsSUFBSTtJQVYvQixtQ0FBbUM7SUFDbkMsT0FBTyxDQUFDLE9BQU8sQ0FLWjtJQUVILE9BQU8sQ0FBQyxLQUFLLENBQUs7SUFFbEIsWUFBMkIsSUFBSSxFQUFFLGVBQWUsRUFBSTtJQUV2QyxXQUFXLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFDbEMsT0FBTyxFQUFFLENBQUMsRUFDVixJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUNYLE9BQU8sQ0FBQztRQUFFLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQztRQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUE7S0FBRSxDQUFDLENBMEQ3RDtDQUNGIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"msgpack_channel.d.ts","sourceRoot":"","sources":["../src/msgpack_channel.ts"],"names":[],"mappings":"AAKA,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;IAElB,YAA2B,IAAI,EAAE,eAAe,EAAI;IAEvC,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,CA0D7D;CACF"}
@@ -0,0 +1,69 @@
1
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
2
+ import { MessageHeader, TypedMessage } from '@aztec-labs/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
+ dest;
16
+ /** A long-lived msgpack encoder */ encoder;
17
+ msgId;
18
+ constructor(dest){
19
+ this.dest = dest;
20
+ this.encoder = new Encoder({
21
+ // always encode JS objects as MessagePack maps
22
+ // this makes it compatible with other MessagePack decoders
23
+ useRecords: false,
24
+ int64AsType: 'bigint'
25
+ });
26
+ this.msgId = 1;
27
+ }
28
+ async sendMessage(msgType, body) {
29
+ const duration = {
30
+ callUs: 0,
31
+ totalUs: 0,
32
+ decodingUs: 0,
33
+ encodingUs: 0
34
+ };
35
+ const start = process.hrtime.bigint();
36
+ const requestId = this.msgId++;
37
+ const request = new TypedMessage(msgType, new MessageHeader({
38
+ requestId
39
+ }), body);
40
+ const encodedRequest = this.encoder.encode(request);
41
+ const encodingEnd = process.hrtime.bigint();
42
+ duration.encodingUs = Number((encodingEnd - start) / 1000n);
43
+ const encodedResponse = await this.dest.call(encodedRequest);
44
+ const callEnd = process.hrtime.bigint();
45
+ duration.callUs = Number((callEnd - encodingEnd) / 1000n);
46
+ const buf = Buffer.isBuffer(encodedResponse) ? encodedResponse : isAnyArrayBuffer(encodedResponse) ? Buffer.from(encodedResponse) : encodedResponse;
47
+ if (!Buffer.isBuffer(buf)) {
48
+ throw new TypeError('Invalid encoded response: expected Buffer or ArrayBuffer, got ' + (encodedResponse === null ? 'null' : typeof encodedResponse));
49
+ }
50
+ const decodedResponse = this.encoder.unpack(buf);
51
+ if (!TypedMessage.isTypedMessageLike(decodedResponse)) {
52
+ throw new TypeError('Invalid response: expected TypedMessageLike, got ' + (decodedResponse === null ? 'null' : typeof decodedResponse));
53
+ }
54
+ const response = TypedMessage.fromMessagePack(decodedResponse);
55
+ const decodingEnd = process.hrtime.bigint();
56
+ duration.decodingUs = Number((decodingEnd - callEnd) / 1000n);
57
+ if (response.header.requestId !== request.header.messageId) {
58
+ throw new Error('Response ID does not match request: ' + response.header.requestId + ' != ' + request.header.messageId);
59
+ }
60
+ if (response.msgType !== request.msgType) {
61
+ throw new Error('Invalid response message type: ' + response.msgType + ' != ' + response.msgType);
62
+ }
63
+ duration.totalUs = Number((process.hrtime.bigint() - start) / 1000n);
64
+ return {
65
+ duration,
66
+ response: response.value
67
+ };
68
+ }
69
+ }
@@ -0,0 +1,7 @@
1
+ import type { MessageReceiver } from './msgpack_channel.js';
2
+ interface NativeClassCtor {
3
+ new (...args: unknown[]): MessageReceiver;
4
+ }
5
+ export declare const NativeLMDBStore: NativeClassCtor;
6
+ export {};
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX21vZHVsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25hdGl2ZV9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFNUQsVUFBVSxlQUFlO0lBQ3ZCLEtBQUssR0FBRyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsZUFBZSxDQUFDO0NBQzNDO0FBYUQsZUFBTyxNQUFNLGVBQWUsRUFBRSxlQUEyRCxDQUFDIn0=
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native_module.d.ts","sourceRoot":"","sources":["../src/native_module.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,UAAU,eAAe;IACvB,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;CAC3C;AAaD,eAAO,MAAM,eAAe,EAAE,eAA2D,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { findNapiBinary } from '@aztec/bb.js';
2
+ import { createRequire } from 'module';
3
+ function loadNativeModule() {
4
+ const require = createRequire(import.meta.url);
5
+ const napiPath = findNapiBinary();
6
+ if (!napiPath) {
7
+ throw new Error('NAPI binary not found for current platform.');
8
+ }
9
+ return require(napiPath);
10
+ }
11
+ const nativeModule = loadNativeModule();
12
+ export const NativeLMDBStore = nativeModule.LMDBStore;
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@aztec-labs/native",
3
+ "version": "6.0.0-nightly.20260829",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": "./dest/index.js"
7
+ },
8
+ "scripts": {
9
+ "build": "yarn clean && ../scripts/tsc.sh",
10
+ "build:dev": "../scripts/tsc.sh --watch",
11
+ "clean": "rm -rf ./dest .tsbuildinfo",
12
+ "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
13
+ },
14
+ "inherits": [
15
+ "../package.common.json"
16
+ ],
17
+ "dependencies": {
18
+ "@aztec-labs/foundation": "6.0.0-nightly.20260829",
19
+ "@aztec/bb.js": "6.0.0-nightly.20260826",
20
+ "msgpackr": "^1.11.2"
21
+ },
22
+ "devDependencies": {
23
+ "@jest/globals": "^30.0.0",
24
+ "@types/jest": "^30.0.0",
25
+ "@types/node": "^22.15.17",
26
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
27
+ "jest": "^30.0.0",
28
+ "ts-node": "^10.9.1",
29
+ "typescript": "^5.3.3"
30
+ },
31
+ "files": [
32
+ "dest",
33
+ "src",
34
+ "build",
35
+ "!*.test.*"
36
+ ],
37
+ "engines": {
38
+ "node": ">=20.10"
39
+ },
40
+ "jest": {
41
+ "extensionsToTreatAsEsm": [
42
+ ".ts"
43
+ ],
44
+ "transform": {
45
+ "^.+\\.tsx?$": [
46
+ "@swc/jest",
47
+ {
48
+ "jsc": {
49
+ "parser": {
50
+ "syntax": "typescript",
51
+ "decorators": true
52
+ },
53
+ "transform": {
54
+ "decoratorVersion": "2022-03"
55
+ }
56
+ }
57
+ }
58
+ ]
59
+ },
60
+ "moduleNameMapper": {
61
+ "^(\\.{1,2}/.*)\\.[cm]?js$": "$1"
62
+ },
63
+ "reporters": [
64
+ "default"
65
+ ],
66
+ "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$",
67
+ "rootDir": "./src",
68
+ "testTimeout": 120000,
69
+ "setupFiles": [
70
+ "../../foundation/src/jest/setup.mjs"
71
+ ],
72
+ "testEnvironment": "../../foundation/src/jest/env.mjs",
73
+ "setupFilesAfterEnv": [
74
+ "../../foundation/src/jest/setupAfterEnv.mjs"
75
+ ]
76
+ }
77
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './native_module.js';
2
+ export { type RoundtripDuration, MsgpackChannel } from './msgpack_channel.js';
@@ -0,0 +1,108 @@
1
+ import { Fr } from '@aztec-labs/foundation/curves/bn254';
2
+ import { MessageHeader, TypedMessage } from '@aztec-labs/foundation/message';
3
+ import { Encoder, addExtension } from 'msgpackr';
4
+ import { isAnyArrayBuffer } from 'util/types';
5
+
6
+ export interface MessageReceiver {
7
+ call(msg: Buffer | Uint8Array): Promise<Buffer | Uint8Array>;
8
+ }
9
+
10
+ export type RoundtripDuration = {
11
+ encodingUs: number;
12
+ callUs: number;
13
+ decodingUs: number;
14
+ totalUs: number;
15
+ };
16
+
17
+ // small extension to pack an NodeJS Fr instance to a representation that the C++ code can understand
18
+ // this only works for writes. Unpacking from C++ can't create Fr instances because the data is passed
19
+ // as raw, untagged, buffers. On the NodeJS side we don't know what the buffer represents
20
+ // Adding a tag would be a solution, but it would have to be done on both sides and it's unclear where else
21
+ // C++ fr instances are sent/received/stored.
22
+ addExtension({
23
+ Class: Fr,
24
+ write: fr => fr.toBuffer(),
25
+ });
26
+
27
+ type MessageBody<T extends number> = { [K in T]: object | void };
28
+
29
+ export class MsgpackChannel<
30
+ M extends number = number,
31
+ Req extends MessageBody<M> = any,
32
+ Resp extends MessageBody<M> = any,
33
+ > {
34
+ /** A long-lived msgpack encoder */
35
+ private encoder = new Encoder({
36
+ // always encode JS objects as MessagePack maps
37
+ // this makes it compatible with other MessagePack decoders
38
+ useRecords: false,
39
+ int64AsType: 'bigint',
40
+ });
41
+
42
+ private msgId = 1;
43
+
44
+ public constructor(private dest: MessageReceiver) {}
45
+
46
+ public async sendMessage<T extends M>(
47
+ msgType: T,
48
+ body: Req[T],
49
+ ): Promise<{ duration: RoundtripDuration; response: Resp[T] }> {
50
+ const duration: RoundtripDuration = {
51
+ callUs: 0,
52
+ totalUs: 0,
53
+ decodingUs: 0,
54
+ encodingUs: 0,
55
+ };
56
+
57
+ const start = process.hrtime.bigint();
58
+ const requestId = this.msgId++;
59
+
60
+ const request = new TypedMessage(msgType, new MessageHeader({ requestId }), body);
61
+ const encodedRequest = this.encoder.encode(request);
62
+ const encodingEnd = process.hrtime.bigint();
63
+ duration.encodingUs = Number((encodingEnd - start) / 1000n);
64
+
65
+ const encodedResponse = await this.dest.call(encodedRequest);
66
+ const callEnd = process.hrtime.bigint();
67
+ duration.callUs = Number((callEnd - encodingEnd) / 1000n);
68
+
69
+ const buf = Buffer.isBuffer(encodedResponse)
70
+ ? encodedResponse
71
+ : isAnyArrayBuffer(encodedResponse)
72
+ ? Buffer.from(encodedResponse)
73
+ : encodedResponse;
74
+
75
+ if (!Buffer.isBuffer(buf)) {
76
+ throw new TypeError(
77
+ 'Invalid encoded response: expected Buffer or ArrayBuffer, got ' +
78
+ (encodedResponse === null ? 'null' : typeof encodedResponse),
79
+ );
80
+ }
81
+
82
+ const decodedResponse = this.encoder.unpack(buf);
83
+ if (!TypedMessage.isTypedMessageLike(decodedResponse)) {
84
+ throw new TypeError(
85
+ 'Invalid response: expected TypedMessageLike, got ' +
86
+ (decodedResponse === null ? 'null' : typeof decodedResponse),
87
+ );
88
+ }
89
+
90
+ const response = TypedMessage.fromMessagePack<T, Resp[T]>(decodedResponse);
91
+ const decodingEnd = process.hrtime.bigint();
92
+ duration.decodingUs = Number((decodingEnd - callEnd) / 1000n);
93
+
94
+ if (response.header.requestId !== request.header.messageId) {
95
+ throw new Error(
96
+ 'Response ID does not match request: ' + response.header.requestId + ' != ' + request.header.messageId,
97
+ );
98
+ }
99
+
100
+ if (response.msgType !== request.msgType) {
101
+ throw new Error('Invalid response message type: ' + response.msgType + ' != ' + response.msgType);
102
+ }
103
+
104
+ duration.totalUs = Number((process.hrtime.bigint() - start) / 1000n);
105
+
106
+ return { duration, response: response.value };
107
+ }
108
+ }
@@ -0,0 +1,22 @@
1
+ import { findNapiBinary } from '@aztec/bb.js';
2
+
3
+ import { createRequire } from 'module';
4
+
5
+ import type { MessageReceiver } from './msgpack_channel.js';
6
+
7
+ interface NativeClassCtor {
8
+ new (...args: unknown[]): MessageReceiver;
9
+ }
10
+
11
+ function loadNativeModule(): Record<string, NativeClassCtor> {
12
+ const require = createRequire(import.meta.url);
13
+ const napiPath = findNapiBinary();
14
+ if (!napiPath) {
15
+ throw new Error('NAPI binary not found for current platform.');
16
+ }
17
+ return require(napiPath);
18
+ }
19
+
20
+ const nativeModule: Record<string, NativeClassCtor | Function> = loadNativeModule();
21
+
22
+ export const NativeLMDBStore: NativeClassCtor = nativeModule.LMDBStore as NativeClassCtor;