diff --git a/.config/cspell.json b/.config/cspell.json index 7918f7220..68372b4b8 100644 --- a/.config/cspell.json +++ b/.config/cspell.json @@ -4,7 +4,16 @@ // language - current active spelling language "language": "en", // words - list of words to be always considered correct - "words": ["tarides", "nixbuild", "stefanzweifel", "ACMRT", "Oxlint"], + "words": [ + "ACMRT", + "arkworks", + "caml", + "coeffs", + "Napi", + "nixbuild", + "Oxlint", + "tarides" + ], // flagWords - list of words to be always considered incorrect // This is useful for offensive words and common spelling errors. // For example "hte" should be "the" diff --git a/src/bindings/crypto/bindings-napi.ts b/src/bindings/crypto/bindings-napi.ts index 824e31e18..0b833b90f 100644 --- a/src/bindings/crypto/bindings-napi.ts +++ b/src/bindings/crypto/bindings-napi.ts @@ -1,4 +1,6 @@ import { fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js'; +import { Gate, Wire } from './bindings/kimchi-types.js'; +import { mapTuple } from './bindings/util.js'; export { bindingsNapi }; @@ -6,26 +8,68 @@ function bindingsNapi(napi: any) { return { fp: { vectorToRust: (fields: any) => { - console.log('values going in ', fields); + //console.log('values going in ', fields); let res = fieldsToRustFlat(fields); - console.log('values going out ', res); + //console.log('values going out ', res); return res; }, vectorFromRust: fieldsFromRustFlat, + wireToRust([, row, col]: Wire) { + return { row, col }; + }, + gateToRust(gate: Gate): any { + const [, typ, [, ...wires], coeffs] = gate; + const mapped = mapTuple(wires, (wire) => this.wireToRust(wire)); + const nativeWires = { + w0: mapped[0], + w1: mapped[1], + w2: mapped[2], + w3: mapped[3], + w4: mapped[4], + w5: mapped[5], + w6: mapped[6], + } as const; + return { + typ, + wires: nativeWires, + coeffs: Array.from(fieldsToRustFlat(coeffs)), + }; + }, }, fq: { vectorToRust: (fields: any) => { - console.log('values going in ', fields); + //console.log('values going in ', fields); let res = fieldsToRustFlat(fields); - console.log('values going out ', res); + //console.log('values going out ', res); return res; }, vectorFromRust: (fieldBytes: any) => { - console.log('values going in ', fieldBytes); + //console.log('values going in ', fieldBytes); let res = fieldsFromRustFlat(fieldBytes); - console.log('values going out ', res); + //console.log('values going out ', res); return res; }, + wireToRust([, row, col]: Wire) { + return { row, col }; + }, + gateToRust(gate: Gate): any { + const [, typ, [, ...wires], coeffs] = gate; + const mapped = mapTuple(wires, (wire) => this.wireToRust(wire)); + const nativeWires = { + w0: mapped[0], + w1: mapped[1], + w2: mapped[2], + w3: mapped[3], + w4: mapped[4], + w5: mapped[5], + w6: mapped[6], + } as const; + return { + typ, + wires: nativeWires, + coeffs: Array.from(fieldsToRustFlat(coeffs)), + }; + }, }, }; } diff --git a/src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts b/src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts new file mode 100644 index 000000000..65d78b663 --- /dev/null +++ b/src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts @@ -0,0 +1,67 @@ +import { expect } from 'expect'; +import { createRequire } from 'node:module'; +import { bindingsNapi } from '../bindings-napi.js'; +import type { Field, Gate, Wire } from './kimchi-types.js'; + +const require = createRequire(import.meta.url); + +function loadNative() { + const candidates = [ + '../../compiled/_node_bindings/plonk_napi.node', + '../../compiled/node_bindings/plonk_napi.node', + ]; + for (const path of candidates) { + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + return require(path); + } catch (err) { + if ((err as any).code !== 'MODULE_NOT_FOUND') throw err; + } + } + throw new Error('plonk_napi.node not found in compiled bindings'); +} + +const native: any = loadNative(); + +const { fp } = bindingsNapi(native); + +const zeroField: Field = [0, 0n]; +const mlWire = (row: number, col: number): Wire => [0, row, col]; + +const sampleGate: Gate = [ + 0, + 1, + [ + 0, + mlWire(0, 0), + mlWire(0, 1), + mlWire(0, 2), + mlWire(0, 3), + mlWire(0, 4), + mlWire(0, 5), + mlWire(0, 6), + ], + [0, zeroField, zeroField, zeroField, zeroField, zeroField, zeroField, zeroField], +]; + +const vector = native.camlPastaFpPlonkGateVectorCreate(); +expect(native.camlPastaFpPlonkGateVectorLen(vector)).toBe(0); + +native.camlPastaFpPlonkGateVectorAdd(vector, fp.gateToRust(sampleGate)); +expect(native.camlPastaFpPlonkGateVectorLen(vector)).toBe(1); + +const gate0 = native.camlPastaFpPlonkGateVectorGet(vector, 0); +expect(gate0.typ).toBe(sampleGate[1]); + +const rustTarget = fp.wireToRust(mlWire(0, 0)); +const rustHead = fp.wireToRust(mlWire(1, 2)); +native.camlPastaFpPlonkGateVectorWrap(vector, rustTarget, rustHead); +const wrapped = native.camlPastaFpPlonkGateVectorGet(vector, 0); +expect(wrapped.wires.w0).toEqual({ row: 1, col: 2 }); + +native.camlPastaFpPlonkGateVectorDigest(0, vector); +native.camlPastaFpPlonkCircuitSerialize(0, vector); + +console.log('{}', native.camlPastaFpPlonkGateVectorDigest(0, vector)); + +console.log('gate vector napi bindings (fp) are working ✔️'); diff --git a/src/mina b/src/mina index fa807948b..677dcd250 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit fa807948b4298eabff9ecf79418068e58415bc91 +Subproject commit 677dcd25069c7c2fe02d05431ac4f4b80f5a4521