From 194784830c190f9b692c98d4b376fcab2869c8af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Tue, 30 Sep 2025 17:07:09 +0200 Subject: [PATCH 01/14] scripts: update build to account for napi --- .../scripts/build-o1js-node-artifacts.sh | 17 +++++++++++++++++ src/build/copy-to-dist.js | 1 + 2 files changed, 18 insertions(+) diff --git a/src/bindings/scripts/build-o1js-node-artifacts.sh b/src/bindings/scripts/build-o1js-node-artifacts.sh index 045a8d9922..4c2698afe3 100755 --- a/src/bindings/scripts/build-o1js-node-artifacts.sh +++ b/src/bindings/scripts/build-o1js-node-artifacts.sh @@ -51,6 +51,10 @@ run_cmd cp "${MINA_PATH}"/src/config.mlh "src" run_cmd cp -r "${MINA_PATH}"/src/config "src/config" ok "Mina config files copied" +info "Building Kimchi native bindings for Node.js..." +run_cmd dune b "${KIMCHI_BINDINGS}"/js/native +ok "Kimchi native bindings built" + info "Building Kimchi bindings for Node.js..." run_cmd dune b "${KIMCHI_BINDINGS}"/js/node_js ok "Kimchi bindings built" @@ -96,6 +100,14 @@ run_cmd mkdir -p "${BINDINGS_PATH}" run_cmd chmod -R 777 "${BINDINGS_PATH}" ok "Output directory prepared" +info "Preparing native bindings directory..." +run_cmd mkdir -p src/bindings/compiled/native +ok "Native bindings directory prepared" + +info "Copying N-API bindings..." +run_cmd cp _build/default/"${KIMCHI_BINDINGS}"/js/native/plonk_napi* "${BINDINGS_PATH}" +ok "N-API bindings copied" + info "Copying WASM bindings..." run_cmd cp _build/default/"${KIMCHI_BINDINGS}"/js/node_js/plonk_wasm* "${BINDINGS_PATH}" run_cmd mv -f "${BINDINGS_PATH}"/plonk_wasm.js "${BINDINGS_PATH}"/plonk_wasm.cjs @@ -114,6 +126,11 @@ fi run_cmd mv -f "${BINDINGS_PATH}"/o1js_node.bc.js "${BINDINGS_PATH}"/o1js_node.bc.cjs ok "Node.js bindings copied" +info "Copying native bindings..." +run_cmd cp _build/default/"${KIMCHI_BINDINGS}"/js/native/plonk_napi.node src/bindings/compiled/native/ +run_cmd chmod 777 src/bindings/compiled/native/plonk_napi.node +ok "Native bindings copied" + info "Updating WASM references in bindings..." run_cmd sed -i 's/plonk_wasm.js/plonk_wasm.cjs/' "${BINDINGS_PATH}"/o1js_node.bc.cjs ok "WASM references updated" diff --git a/src/build/copy-to-dist.js b/src/build/copy-to-dist.js index d2786c8582..6a3db7a1bd 100644 --- a/src/build/copy-to-dist.js +++ b/src/build/copy-to-dist.js @@ -5,6 +5,7 @@ await copyFromTo( [ 'src/bindings.d.ts', 'src/bindings/compiled/_node_bindings', + 'src/bindings/compiled/native', 'src/bindings/compiled/node_bindings/plonk_wasm.d.cts', ], 'src/', From 3d7a180e7041f006d9d12f3e59e472a5f52e971c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Thu, 2 Oct 2025 16:41:46 +0200 Subject: [PATCH 02/14] bindings: initialize native conversion --- src/bindings/crypto/bindings.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/bindings/crypto/bindings.ts b/src/bindings/crypto/bindings.ts index 8e9fcb35ff..f98c8dcc6f 100644 --- a/src/bindings/crypto/bindings.ts +++ b/src/bindings/crypto/bindings.ts @@ -17,7 +17,7 @@ import { oraclesConversion } from './bindings/conversion-oracles.js'; import { jsEnvironment } from './bindings/env.js'; import { srs } from './bindings/srs.js'; -export { getRustConversion, RustConversion, Wasm }; +export { getRustConversion, RustConversion, Wasm, createNativeRustConversion }; const tsBindings = { jsEnvironment, @@ -31,6 +31,7 @@ const tsBindings = { ...FpVectorBindings, ...FqVectorBindings, rustConversion: createRustConversion, + nativeRustConversion: createNativeRustConversion, srs: (wasm: Wasm) => srs(wasm, getRustConversion(wasm)), }; @@ -39,7 +40,15 @@ const tsBindings = { type Wasm = typeof wasmNamespace; +function createNativeRustConversion(wasm: Wasm) { + return buildConversion(wasm); +} + function createRustConversion(wasm: Wasm) { + return buildConversion(wasm); +} + +function buildConversion(wasm: Wasm) { let core = conversionCore(wasm); let verifierIndex = verifierIndexConversion(wasm, core); let oracles = oraclesConversion(wasm); @@ -55,7 +64,7 @@ function createRustConversion(wasm: Wasm) { }; } -type RustConversion = ReturnType; +type RustConversion = ReturnType; let rustConversion: RustConversion | undefined; From 9933ac2d42e15c770e51b677e10cdff5ac35a1ad Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 8 Oct 2025 15:47:46 +0700 Subject: [PATCH 03/14] proxy for napi conversion core --- src/bindings/crypto/bindings-napi.ts | 31 ++++++++++++++++++++++++++++ src/bindings/crypto/bindings.ts | 5 +++-- 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/bindings/crypto/bindings-napi.ts diff --git a/src/bindings/crypto/bindings-napi.ts b/src/bindings/crypto/bindings-napi.ts new file mode 100644 index 0000000000..824e31e187 --- /dev/null +++ b/src/bindings/crypto/bindings-napi.ts @@ -0,0 +1,31 @@ +import { fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js'; + +export { bindingsNapi }; + +function bindingsNapi(napi: any) { + return { + fp: { + vectorToRust: (fields: any) => { + console.log('values going in ', fields); + let res = fieldsToRustFlat(fields); + console.log('values going out ', res); + return res; + }, + vectorFromRust: fieldsFromRustFlat, + }, + fq: { + vectorToRust: (fields: any) => { + console.log('values going in ', fields); + let res = fieldsToRustFlat(fields); + console.log('values going out ', res); + return res; + }, + vectorFromRust: (fieldBytes: any) => { + console.log('values going in ', fieldBytes); + let res = fieldsFromRustFlat(fieldBytes); + console.log('values going out ', res); + return res; + }, + }, + }; +} diff --git a/src/bindings/crypto/bindings.ts b/src/bindings/crypto/bindings.ts index f98c8dcc6f..abd3d879d9 100644 --- a/src/bindings/crypto/bindings.ts +++ b/src/bindings/crypto/bindings.ts @@ -16,6 +16,7 @@ import { verifierIndexConversion } from './bindings/conversion-verifier-index.js import { oraclesConversion } from './bindings/conversion-oracles.js'; import { jsEnvironment } from './bindings/env.js'; import { srs } from './bindings/srs.js'; +import { bindingsNapi } from './bindings-napi.js'; export { getRustConversion, RustConversion, Wasm, createNativeRustConversion }; @@ -40,8 +41,8 @@ const tsBindings = { type Wasm = typeof wasmNamespace; -function createNativeRustConversion(wasm: Wasm) { - return buildConversion(wasm); +function createNativeRustConversion(napi: any) { + return bindingsNapi(napi); } function createRustConversion(wasm: Wasm) { From f4d9de4c518acd45f419af2dc25c93dad530163d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Tue, 30 Sep 2025 17:07:20 +0200 Subject: [PATCH 04/14] submodule: update mina --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index 569e99c958..c0e7f3e780 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 569e99c95834841d64858644c5d80ac7e63d0157 +Subproject commit c0e7f3e78050705ee2973991ecc704d6fba3160b From 936d9f0aa7227e313b7e250b330452f9f6091eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Thu, 9 Oct 2025 16:44:01 +0200 Subject: [PATCH 05/14] bindings: comment out conversion bundle --- src/bindings/crypto/bindings.ts | 89 ++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/src/bindings/crypto/bindings.ts b/src/bindings/crypto/bindings.ts index abd3d879d9..a616c8b3a8 100644 --- a/src/bindings/crypto/bindings.ts +++ b/src/bindings/crypto/bindings.ts @@ -20,6 +20,16 @@ import { bindingsNapi } from './bindings-napi.js'; export { getRustConversion, RustConversion, Wasm, createNativeRustConversion }; + +/* TODO: Uncomment in phase 2 of conversion layer +import { conversionCore as conversionCoreNative } from './native/conversion-core.js'; +import { fieldsFromRustFlat as fieldsFromRustFlatNative, fieldsToRustFlat as fieldsToRustFlatNative } from './native/conversion-base.js'; +import { proofConversion as proofConversionNative } from './native/conversion-proof.js'; +import { verifierIndexConversion as verifierIndexConversionNative } from './native/conversion-verifier-index.js'; +import { oraclesConversion as oraclesConversionNative } from './native/conversion-oracles.js'; + +export { getRustConversion, type RustConversion, type NativeConversion, type Wasm };*/ + const tsBindings = { jsEnvironment, prefixHashes, @@ -33,6 +43,11 @@ const tsBindings = { ...FqVectorBindings, rustConversion: createRustConversion, nativeRustConversion: createNativeRustConversion, + /* TODO: Uncomment in phase 2 of conversion layer + srs: (wasm: Wasm) => { + const bundle = getConversionBundle(wasm); + return bundle.srsFactory(wasm, bundle.conversion); + },*/ srs: (wasm: Wasm) => srs(wasm, getRustConversion(wasm)), }; @@ -41,15 +56,17 @@ const tsBindings = { type Wasm = typeof wasmNamespace; -function createNativeRustConversion(napi: any) { - return bindingsNapi(napi); +type RustConversion = ReturnType; + +function getRustConversion(wasm: Wasm): RustConversion { + return createRustConversion(wasm); } function createRustConversion(wasm: Wasm) { - return buildConversion(wasm); + return buildWasmConversion(wasm); } -function buildConversion(wasm: Wasm) { +function buildWasmConversion(wasm: Wasm) { let core = conversionCore(wasm); let verifierIndex = verifierIndexConversion(wasm, core); let oracles = oraclesConversion(wasm); @@ -65,10 +82,68 @@ function buildConversion(wasm: Wasm) { }; } +function createNativeRustConversion(napi: any) { + return bindingsNapi(napi); +} + +/* TODO: Uncomment in phase 2 of conversion layer + +function shouldUseNativeConversion(wasm: Wasm): boolean { + const marker = (wasm as any).__kimchi_use_native; + const globalMarker = + typeof globalThis !== 'undefined' && + (globalThis as any).__kimchi_use_native; + return Boolean(marker || globalMarker); +} + +function createRustConversion(wasm: Wasm): RustConversion { + return shouldUseNativeConversion(wasm) + ? createNativeConversion(wasm) + : createWasmConversion(wasm); +} + +function createWasmConversion(wasm: Wasm) { + const core = conversionCore(wasm); + const verifierIndex = verifierIndexConversion(wasm, core); + const oracles = oraclesConversion(wasm); + const proof = proofConversion(wasm, core); + + return { + fp: { ...core.fp, ...verifierIndex.fp, ...oracles.fp, ...proof.fp }, + fq: { ...core.fq, ...verifierIndex.fq, ...oracles.fq, ...proof.fq }, + fieldsToRustFlat, + fieldsFromRustFlat, + wireToRust: core.wireToRust, + mapMlArrayToRustVector: core.mapMlArrayToRustVector, + }; +} + type RustConversion = ReturnType; -let rustConversion: RustConversion | undefined; +function createNativeConversion(wasm: Wasm) { + const core = conversionCoreNative(wasm); + const verifierIndex = verifierIndexConversionNative(wasm, core); + const oracles = oraclesConversionNative(wasm); + const proof = proofConversionNative(wasm, core); + + return { + fp: { ...core.fp, ...verifierIndex.fp, ...oracles.fp, ...proof.fp }, + fq: { ...core.fq, ...verifierIndex.fq, ...oracles.fq, ...proof.fq }, + fieldsToRustFlatNative, + fieldsFromRustFlatNative, + wireToRust: core.wireToRust, + mapMlArrayToRustVector: core.mapMlArrayToRustVector, + }; +} + +type ConversionBundle = + | { conversion: WasmConversion; srsFactory: typeof srs } + | { conversion: NativeConversion; srsFactory: typeof srsNative }; -function getRustConversion(wasm: Wasm) { - return rustConversion ?? (rustConversion = createRustConversion(wasm)); +function getConversionBundle(wasm: Wasm): ConversionBundle { + if (shouldUseNativeConversion(wasm)) { + return { conversion: createNativeConversion(wasm), srsFactory: srsNative }; + } + return { conversion: createWasmConversion(wasm), srsFactory: srs }; } +*/ From b46036fd0622da095fff213951bb9aaecf03ff74 Mon Sep 17 00:00:00 2001 From: querolita Date: Thu, 16 Oct 2025 19:46:32 +0200 Subject: [PATCH 06/14] submodule: update mina --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index c0e7f3e780..fa807948b4 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit c0e7f3e78050705ee2973991ecc704d6fba3160b +Subproject commit fa807948b4298eabff9ecf79418068e58415bc91 From fb1a77ae7ad17d39500307e949dcefa09cf21bf1 Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 15 Oct 2025 18:53:11 +0700 Subject: [PATCH 07/14] `prover_to_json` napi implementation --- src/examples/zkfunction/preimage.ts | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/examples/zkfunction/preimage.ts b/src/examples/zkfunction/preimage.ts index f0e621ba40..bcd48adc5b 100644 --- a/src/examples/zkfunction/preimage.ts +++ b/src/examples/zkfunction/preimage.ts @@ -1,4 +1,4 @@ -import { Poseidon, Field, Experimental } from 'o1js'; +import { Experimental, Field, Poseidon } from 'o1js'; const { ZkFunction } = Experimental; /** @@ -16,17 +16,8 @@ const main = ZkFunction({ }, }); -console.log('compile...'); -const { verificationKey } = await main.compile(); - -const preimage = Field(1); -const hash = Poseidon.hash([preimage]); - -console.log('prove...'); -const pi = await main.prove(hash, preimage); - -console.log('verify...'); -let ok = await main.verify(pi, verificationKey); -console.log('ok?', ok); - -if (!ok) throw Error('verification failed'); +await main.compile(); +console.log('analyze'); +let res = await main.analyzeMethod(); +console.log('done'); +console.log(res); From 7e82f96cdc89c76eae14c2809c04c67ecc10a266 Mon Sep 17 00:00:00 2001 From: querolita Date: Wed, 22 Oct 2025 19:00:52 +0200 Subject: [PATCH 08/14] bump mina --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index fa807948b4..3841d2354c 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit fa807948b4298eabff9ecf79418068e58415bc91 +Subproject commit 3841d2354c35764da55ea7dfeb156a588ec1ef1b From 02bfc01b688666fb13e0885690c5758f07610829 Mon Sep 17 00:00:00 2001 From: leon chou Date: Wed, 22 Oct 2025 16:54:13 -0400 Subject: [PATCH 09/14] merge with main, and break out native build --- package.json | 1 + scripts/build/native/build-node.sh | 23 +++++++++++++++++++ .../scripts/build-o1js-node-artifacts.sh | 1 + 3 files changed, 25 insertions(+) create mode 100755 scripts/build/native/build-node.sh diff --git a/package.json b/package.json index a6c348c5df..b1364a6cd8 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "build:jsoo": "npm run build:jsoo:web && npm run build:jsoo:node", "build:jsoo:web": "./scripts/build/jsoo/build-web.sh", "build:jsoo:node": "./scripts/build/jsoo/build-node.sh", + "build:native:node": "./scripts/build/native/build-node.sh", "build:docs": "typedoc", "prepublish:web": "./scripts/prepublish/prepublish-web.sh", "prepublish:node": "./scripts/prepublish/prepublish-node.sh", diff --git a/scripts/build/native/build-node.sh b/scripts/build/native/build-node.sh new file mode 100755 index 0000000000..43f8a15544 --- /dev/null +++ b/scripts/build/native/build-node.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +source ./scripts/lib/ux.sh + +setup_script "native-node-build" "native node build" + +KIMCHI_PATH=./src/mina/src/lib/crypto/kimchi_bindings/js/native +BUILT_PATH=./_build/default/$KIMCHI_PATH +BINDINGS_PATH=./src/bindings/compiled/native + +mkdir -p $BINDINGS_PATH + +info "building native Kimchi bindings..." + +dune build $KIMCHI_PATH + +info "copying artifacts into the right place..." + +cp $BUILT_PATH/plonk_napi.node $BINDINGS_PATH/plonk_napi.node +chmod 660 $BINDINGS_PATH/plonk_napi.node + +success "Native build success!" \ No newline at end of file diff --git a/src/bindings/scripts/build-o1js-node-artifacts.sh b/src/bindings/scripts/build-o1js-node-artifacts.sh index 0748a0bd4a..cb8b5ff7a9 100755 --- a/src/bindings/scripts/build-o1js-node-artifacts.sh +++ b/src/bindings/scripts/build-o1js-node-artifacts.sh @@ -33,6 +33,7 @@ ok "Mina config files copied" npm run build:wasm:node npm run build:jsoo:node +npm run build:native:node info "Building transaction layout TypeScript definitions..." run_cmd dune b src/bindings/mina-transaction/gen/v1/js-layout.ts \ From ce8f5997cc95a5917cebeac38da3bc2558a1e0e5 Mon Sep 17 00:00:00 2001 From: querolita Date: Thu, 23 Oct 2025 17:11:57 +0200 Subject: [PATCH 10/14] submodule: update to mina commit coming from florian/napi-prover-json --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index 8e111e81ca..3841d2354c 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 8e111e81ca36ea01bc5cb2d204e195ee8ac967c2 +Subproject commit 3841d2354c35764da55ea7dfeb156a588ec1ef1b From 9a9bfb9120608daa47aee23b7f0a970309a70672 Mon Sep 17 00:00:00 2001 From: leon chou Date: Thu, 23 Oct 2025 11:46:13 -0400 Subject: [PATCH 11/14] adding napi to spellcheck --- .config/cspell.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/cspell.json b/.config/cspell.json index e0e3673f5e..1bd10af3d7 100644 --- a/.config/cspell.json +++ b/.config/cspell.json @@ -142,6 +142,7 @@ "minascan", "modul", "Muls", + "napi", "Nexts", "nixbuild", "nixfmt", From 39003cbfea53b70247be7d8619b4ef40b0bdee5d Mon Sep 17 00:00:00 2001 From: leon chou Date: Fri, 31 Oct 2025 16:09:15 -0400 Subject: [PATCH 12/14] native napi workflow --- .gitignore | 4 ++ package-lock.json | 79 +++++++++++++++++++--------- package.json | 12 ++++- scripts/build/native/build-node.sh | 43 +++++++++++++-- scripts/publish/publish-native.sh | 16 ++++++ scripts/publish/publish-native.ts | 31 +++++++++++ scripts/publish/publish.sh | 11 ++++ scripts/publish/publish.ts | 46 ++++++++++++++++ scripts/publish/slug.ts | 3 ++ src/bindings/crypto/bindings-napi.ts | 6 --- src/bindings/crypto/bindings.ts | 17 +++--- src/bindings/ocaml/jsoo_exports/dune | 5 +- src/mina | 2 +- 13 files changed, 230 insertions(+), 45 deletions(-) create mode 100755 scripts/publish/publish-native.sh create mode 100644 scripts/publish/publish-native.ts create mode 100755 scripts/publish/publish.sh create mode 100644 scripts/publish/publish.ts create mode 100644 scripts/publish/slug.ts diff --git a/.gitignore b/.gitignore index 67c500da69..216ff43255 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ result # precompiled bindings src/bindings/compiled .bindings_download +native/ + +# rust-analyzer +target/ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b21da24eba..147f2ecf67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@types/libsodium-wrappers-sumo": "^0.7.8", "@types/minimist": "^1.2.5", "@types/node": "^18.14.2", + "@types/semver": "^7.7.1", "esbuild": "^0.25.5", "expect": "^29.0.1", "fs-extra": "^10.0.0", @@ -44,6 +45,7 @@ "prettier-plugin-organize-imports": "^4.3.0", "replace-in-file": "^6.3.5", "rimraf": "^3.0.2", + "semver": "^7.7.3", "ts-jest": "^28.0.8", "typedoc": "^0.28.5", "typedoc-plugin-markdown": "^4.6.4", @@ -52,8 +54,34 @@ }, "engines": { "node": ">=18.14.0" + }, + "optionalDependencies": { + "@o1js/native-darwin-arm64": "file:native/darwin-arm64", + "@o1js/native-darwin-x64": "file:./native/darwin-x64", + "@o1js/native-linux-arm64": "file:./native/linux-arm64", + "@o1js/native-win32-x64": "file:./native/win32-x64" } }, + "native/darwin-arm64": { + "name": "@o1js/native-darwin-arm64", + "version": "0.0.0", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "native/darwin-x64": { + "optional": true + }, + "native/linux-arm64": { + "optional": true + }, + "native/win32-x64": { + "optional": true + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -1981,6 +2009,22 @@ "node": ">= 8" } }, + "node_modules/@o1js/native-darwin-arm64": { + "resolved": "native/darwin-arm64", + "link": true + }, + "node_modules/@o1js/native-darwin-x64": { + "resolved": "native/darwin-x64", + "link": true + }, + "node_modules/@o1js/native-linux-arm64": { + "resolved": "native/linux-arm64", + "link": true + }, + "node_modules/@o1js/native-win32-x64": { + "resolved": "native/win32-x64", + "link": true + }, "node_modules/@octokit/action": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@octokit/action/-/action-6.1.0.tgz", @@ -2584,6 +2628,13 @@ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -6199,13 +6250,11 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -6213,24 +6262,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/package.json b/package.json index b1364a6cd8..e2f06b6192 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,9 @@ "e2e:install": "npx playwright install --with-deps", "e2e:show-report": "npx playwright show-report tests/report", "update-changelog": "./scripts/changelog/update-changelog.sh", - "prepare": "husky" + "prepare": "husky", + "publish": "./scripts/publish/publish.sh", + "publish:native": "./scripts/publish/publish-native.sh" }, "author": "O(1) Labs", "devDependencies": { @@ -105,6 +107,7 @@ "@types/libsodium-wrappers-sumo": "^0.7.8", "@types/minimist": "^1.2.5", "@types/node": "^18.14.2", + "@types/semver": "^7.7.1", "esbuild": "^0.25.5", "expect": "^29.0.1", "fs-extra": "^10.0.0", @@ -120,6 +123,7 @@ "prettier-plugin-organize-imports": "^4.3.0", "replace-in-file": "^6.3.5", "rimraf": "^3.0.2", + "semver": "^7.7.3", "ts-jest": "^28.0.8", "typedoc": "^0.28.5", "typedoc-plugin-markdown": "^4.6.4", @@ -134,5 +138,11 @@ "reflect-metadata": "^0.1.13", "stacktrace-js": "^2.0.2", "tslib": "^2.3.0" + }, + "optionalDependencies": { + "@o1js/native-darwin-arm64": "file:native/darwin-arm64", + "@o1js/native-darwin-x64": "file:./native/darwin-x64", + "@o1js/native-linux-arm64": "file:./native/linux-arm64", + "@o1js/native-win32-x64": "file:./native/win32-x64" } } diff --git a/scripts/build/native/build-node.sh b/scripts/build/native/build-node.sh index 43f8a15544..6a57b105b2 100755 --- a/scripts/build/native/build-node.sh +++ b/scripts/build/native/build-node.sh @@ -5,9 +5,15 @@ source ./scripts/lib/ux.sh setup_script "native-node-build" "native node build" +NODE_PLATFORM=$(node -e 'console.log(process.platform)') +NODE_ARCH=$(node -e 'console.log(process.arch)') +TARGET_SLUG=$NODE_PLATFORM-$NODE_ARCH + +info "building bindings for $TARGET_SLUG" + KIMCHI_PATH=./src/mina/src/lib/crypto/kimchi_bindings/js/native -BUILT_PATH=./_build/default/$KIMCHI_PATH -BINDINGS_PATH=./src/bindings/compiled/native +BUILT_PATH=./src/mina/src/lib/crypto/kimchi_bindings/js/native/artifacts +BINDINGS_PATH=./native/$TARGET_SLUG/ mkdir -p $BINDINGS_PATH @@ -15,9 +21,40 @@ info "building native Kimchi bindings..." dune build $KIMCHI_PATH -info "copying artifacts into the right place..." +info "creating package for $TARGET_SLUG bindings..." + +cat > $BINDINGS_PATH/package.json < $BINDINGS_PATH/index.js +info "copying artifacts into the right place..." cp $BUILT_PATH/plonk_napi.node $BINDINGS_PATH/plonk_napi.node chmod 660 $BINDINGS_PATH/plonk_napi.node +cp $BUILT_PATH/index.d.ts $BINDINGS_PATH/index.d.ts +chmod 660 $BINDINGS_PATH/index.d.ts success "Native build success!" \ No newline at end of file diff --git a/scripts/publish/publish-native.sh b/scripts/publish/publish-native.sh new file mode 100755 index 0000000000..bc05eecfbc --- /dev/null +++ b/scripts/publish/publish-native.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -Eeuxo pipefail + +source ./scripts/lib/ux.sh +setup_script "npm-publish-native" "NPM publish native" + +NODE_PLATFORM=$(node -e 'console.log(process.platform)') +NODE_ARCH=$(node -e 'console.log(process.arch)') +TARGET_SLUG=$NODE_PLATFORM-$NODE_ARCH +BINDINGS_PATH=./native/$TARGET_SLUG + +./run ./scripts/publish/publish-native.ts --bundle --write --native-version=0.0.2 $BINDINGS_PATH + +pushd $BINDINGS_PATH +npm publish --access public +popd \ No newline at end of file diff --git a/scripts/publish/publish-native.ts b/scripts/publish/publish-native.ts new file mode 100644 index 0000000000..0488099dcb --- /dev/null +++ b/scripts/publish/publish-native.ts @@ -0,0 +1,31 @@ +import minimist from 'minimist'; +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import semver from 'semver'; + +const { + ['native-version']: nativeVersionIn, + write, + _: [packagePath], +} = minimist(process.argv.slice(3), { + boolean: 'write', +}); + +const packageJsonPath = join(packagePath, 'package.json'); + +const nativeVersion = semver.valid(nativeVersionIn); +if (nativeVersion === null) { + console.error(`${nativeVersionIn} is not valid semver`); + process.exit(1); +} + +const pkgJson = await readFile(packageJsonPath, 'utf8').then(JSON.parse); + +pkgJson.version = nativeVersion; + +if (write) { + await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2)); +} else { + console.log(pkgJson); + console.log('dry run, use --write to commit file.'); +} diff --git a/scripts/publish/publish.sh b/scripts/publish/publish.sh new file mode 100755 index 0000000000..083a1b1b2d --- /dev/null +++ b/scripts/publish/publish.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -Eeuxo pipefail + +source ./scripts/lib/ux.sh +setup_script "npm-publish" "NPM publish" + +./run ./scripts/publish/publish.ts --bundle --write --native-version=0.0.1 ./ + +info "to return to local development, use \`git checkout package.json\`" + +npm publish --access public \ No newline at end of file diff --git a/scripts/publish/publish.ts b/scripts/publish/publish.ts new file mode 100644 index 0000000000..7c0fcc9927 --- /dev/null +++ b/scripts/publish/publish.ts @@ -0,0 +1,46 @@ +import minimist from 'minimist'; +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import semver from 'semver'; +import { targetToSlug } from './slug'; + +const nativeTargets = [ + { platform: 'darwin', arch: 'arm64' }, + { platform: 'darwin', arch: 'x64' }, + { platform: 'linux', arch: 'arm64' }, + { platform: 'win32', arch: 'x64' }, +]; + +const { + ['native-version']: nativeVersionIn, + write, + _: [packagePath], +} = minimist(process.argv.slice(3), { + boolean: 'write', +}); + +const packageJsonPath = join(packagePath, 'package.json'); + +const nativeVersion = semver.valid(nativeVersionIn); +if (nativeVersion === null) { + console.error(`${nativeVersionIn} is not valid semver`); + process.exit(1); +} + +const pkgJson = await readFile(packageJsonPath, 'utf8').then(JSON.parse); + +const explicitVersion = `^${nativeVersion}`; +for (const target of nativeTargets) { + const slug = targetToSlug(target); + + if (slug in pkgJson.optionalDependencies) { + pkgJson.optionalDependencies[slug] = explicitVersion; + } +} + +if (write) { + await writeFile(packageJsonPath, JSON.stringify(pkgJson, null, 2)); +} else { + console.log(pkgJson); + console.log('dry run, use --write to commit file.'); +} diff --git a/scripts/publish/slug.ts b/scripts/publish/slug.ts new file mode 100644 index 0000000000..1af6428cf1 --- /dev/null +++ b/scripts/publish/slug.ts @@ -0,0 +1,3 @@ +export function targetToSlug(target: { platform: string; arch: string }) { + return `@o1js/native-${target.platform}-${target.arch}`; +} diff --git a/src/bindings/crypto/bindings-napi.ts b/src/bindings/crypto/bindings-napi.ts index 824e31e187..8e8115cbf2 100644 --- a/src/bindings/crypto/bindings-napi.ts +++ b/src/bindings/crypto/bindings-napi.ts @@ -6,24 +6,18 @@ function bindingsNapi(napi: any) { return { fp: { vectorToRust: (fields: any) => { - console.log('values going in ', fields); let res = fieldsToRustFlat(fields); - console.log('values going out ', res); return res; }, vectorFromRust: fieldsFromRustFlat, }, fq: { vectorToRust: (fields: any) => { - console.log('values going in ', fields); let res = fieldsToRustFlat(fields); - console.log('values going out ', res); return res; }, vectorFromRust: (fieldBytes: any) => { - console.log('values going in ', fieldBytes); let res = fieldsFromRustFlat(fieldBytes); - console.log('values going out ', res); return res; }, }, diff --git a/src/bindings/crypto/bindings.ts b/src/bindings/crypto/bindings.ts index a616c8b3a8..163a12d96c 100644 --- a/src/bindings/crypto/bindings.ts +++ b/src/bindings/crypto/bindings.ts @@ -3,23 +3,22 @@ * It is exposed to JSOO by populating a global variable with an object. * It gets imported as the first thing in ../../bindings.js so that the global variable is ready by the time JSOO code gets executed. */ +import type * as wasmNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; import { prefixHashes, prefixHashesLegacy } from '../crypto/constants.js'; +import { bindingsNapi } from './bindings-napi.js'; import { Bigint256Bindings } from './bindings/bigint256.js'; -import { PallasBindings, VestaBindings } from './bindings/curve.js'; -import { FpBindings, FqBindings } from './bindings/field.js'; -import { FpVectorBindings, FqVectorBindings } from './bindings/vector.js'; -import type * as wasmNamespace from '../compiled/node_bindings/plonk_wasm.cjs'; import { fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js'; -import { proofConversion } from './bindings/conversion-proof.js'; import { conversionCore } from './bindings/conversion-core.js'; -import { verifierIndexConversion } from './bindings/conversion-verifier-index.js'; import { oraclesConversion } from './bindings/conversion-oracles.js'; +import { proofConversion } from './bindings/conversion-proof.js'; +import { verifierIndexConversion } from './bindings/conversion-verifier-index.js'; +import { PallasBindings, VestaBindings } from './bindings/curve.js'; import { jsEnvironment } from './bindings/env.js'; +import { FpBindings, FqBindings } from './bindings/field.js'; import { srs } from './bindings/srs.js'; -import { bindingsNapi } from './bindings-napi.js'; - -export { getRustConversion, RustConversion, Wasm, createNativeRustConversion }; +import { FpVectorBindings, FqVectorBindings } from './bindings/vector.js'; +export { createNativeRustConversion, getRustConversion, RustConversion, Wasm }; /* TODO: Uncomment in phase 2 of conversion layer import { conversionCore as conversionCoreNative } from './native/conversion-core.js'; diff --git a/src/bindings/ocaml/jsoo_exports/dune b/src/bindings/ocaml/jsoo_exports/dune index 801324c5d6..d2c3233a2b 100644 --- a/src/bindings/ocaml/jsoo_exports/dune +++ b/src/bindings/ocaml/jsoo_exports/dune @@ -70,7 +70,10 @@ (flags +toplevel.js +dynlink.js --pretty --source-map) (link_flags --source-map) (javascript_files overrides.js)) - (libraries o1js_bindings.lib bindings_js.node_backend) + (libraries + o1js_bindings.lib + bindings_js.node_backend + bindings_js.native_backend) (link_deps node_js_plonk_wasm.js node_js_plonk_wasm_bg.wasm) (instrumentation (backend bisect_ppx)) diff --git a/src/mina b/src/mina index 3841d2354c..4d28733ed3 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 3841d2354c35764da55ea7dfeb156a588ec1ef1b +Subproject commit 4d28733ed35ff10acb009af203ecbf91532d5fd5 From 896940ceb635336e1477252af332e5ddac4503b2 Mon Sep 17 00:00:00 2001 From: Florian Date: Thu, 30 Oct 2025 18:54:11 +0700 Subject: [PATCH 13/14] add shiftsFromRust --- src/bindings/crypto/bindings-napi.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/bindings/crypto/bindings-napi.ts b/src/bindings/crypto/bindings-napi.ts index 8e8115cbf2..957bf14bd1 100644 --- a/src/bindings/crypto/bindings-napi.ts +++ b/src/bindings/crypto/bindings-napi.ts @@ -1,4 +1,4 @@ -import { fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js'; +import { fieldFromRust, fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js'; export { bindingsNapi }; @@ -6,19 +6,26 @@ function bindingsNapi(napi: any) { return { fp: { vectorToRust: (fields: any) => { - let res = fieldsToRustFlat(fields); - return res; + return fieldsToRustFlat(fields); }, vectorFromRust: fieldsFromRustFlat, + shiftsFromRust(s: any) { + let shifts = [s.s0, s.s1, s.s2, s.s3, s.s4, s.s5, s.s6].map((x) => Uint8Array.from(x)); + let shifted = [0, ...shifts.map(fieldFromRust)]; + return shifted; + }, }, fq: { + shiftsFromRust(s: any) { + let shifts = [s.s0, s.s1, s.s2, s.s3, s.s4, s.s5, s.s6].map((x) => Uint8Array.from(x)); + let shifted = [0, ...shifts.map(fieldFromRust)]; + return shifted; + }, vectorToRust: (fields: any) => { - let res = fieldsToRustFlat(fields); - return res; + return fieldsToRustFlat(fields); }, vectorFromRust: (fieldBytes: any) => { - let res = fieldsFromRustFlat(fieldBytes); - return res; + return fieldsFromRustFlat(fieldBytes); }, }, }; From 013f36a5184876edcf94cc8434ea48bea99114d1 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 3 Nov 2025 19:26:12 +0100 Subject: [PATCH 14/14] submodule: update mina --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index 4d28733ed3..f7c9778758 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 4d28733ed35ff10acb009af203ecbf91532d5fd5 +Subproject commit f7c97787587100218310b7484c2c85900ae54f23