Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .config/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
56 changes: 50 additions & 6 deletions src/bindings/crypto/bindings-napi.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,75 @@
import { fieldsFromRustFlat, fieldsToRustFlat } from './bindings/conversion-base.js';
import { Gate, Wire } from './bindings/kimchi-types.js';
import { mapTuple } from './bindings/util.js';

export { bindingsNapi };

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)),
};
},
},
};
}
67 changes: 67 additions & 0 deletions src/bindings/crypto/bindings/gate-vector-napi.unit-test.ts
Original file line number Diff line number Diff line change
@@ -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 ✔️');