Skip to content

Commit 82d1f68

Browse files
committed
conversion: first attempt of napi-friendly core
1 parent 9938faf commit 82d1f68

File tree

1 file changed

+142
-6
lines changed

1 file changed

+142
-6
lines changed
Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,147 @@
1-
import type * as wasmNamespace from '../../compiled/node_bindings/plonk_wasm.cjs';
1+
import type * as napiNamespace from '../../compiled/node_bindings/plonk_wasm.cjs';
2+
import { MlArray } from '../../../lib/ml/base.js';
3+
import { OrInfinity, Gate, PolyComm, Wire } from './kimchi-types.js';
4+
import {
5+
WasmAffine as NapiAffine,
6+
affineFromRust,
7+
affineToRust,
8+
fieldsFromRustFlat,
9+
fieldsToRustFlat,
10+
} from './conversion-base.js';
11+
import { mapTuple } from './util.js';
212

3-
import { conversionCore as conversionCoreWasm, ConversionCores } from '../bindings/conversion-core.js';
413

5-
export type NativeConversionCores = ConversionCores;
14+
type Napi = typeof napiNamespace;
615

7-
type Wasm = typeof wasmNamespace;
16+
type NapiPolyComm = napiNamespace.WasmFpPolyComm | napiNamespace.WasmFqPolyComm;
817

9-
export function conversionCore(wasm: Wasm): NativeConversionCores {
10-
return conversionCoreWasm(wasm);
18+
type NapiClasses = {
19+
makeAffine: () => NapiAffine;
20+
PolyComm: typeof napiNamespace.WasmFpPolyComm | typeof napiNamespace.WasmFqPolyComm;
21+
};
22+
23+
export function conversionCore(napi: Napi) {
24+
const fp = conversionCorePerField({
25+
makeAffine: napi.caml_vesta_affine_one,
26+
PolyComm: napi.WasmFpPolyComm,
27+
});
28+
const fq = conversionCorePerField({
29+
makeAffine: napi.caml_pallas_affine_one,
30+
PolyComm: napi.WasmFqPolyComm,
31+
});
32+
33+
return {
34+
fp,
35+
fq,
36+
wireToRust: fp.wireToRust, // doesn't depend on the field
37+
mapMlArrayToRustVector<TMl, TRust extends {}>(
38+
[, ...array]: MlArray<TMl>,
39+
map: (x: TMl) => TRust
40+
): TRust[] {
41+
return array.map(map);
42+
},
43+
};
44+
}
45+
46+
function conversionCorePerField({ makeAffine, PolyComm: PolyCommClass }: NapiClasses) {
47+
const self = {
48+
wireToRust([, row, col]: Wire) {
49+
return { row, col };
50+
},
51+
52+
vectorToRust: fieldsToRustFlat,
53+
vectorFromRust: fieldsFromRustFlat,
54+
55+
gateToRust(gate: Gate): any {
56+
const [, typ, [, ...wires], coeffs] = gate;
57+
const mapped = mapTuple(wires, self.wireToRust);
58+
const nativeWires = {
59+
w0: mapped[0],
60+
w1: mapped[1],
61+
w2: mapped[2],
62+
w3: mapped[3],
63+
w4: mapped[4],
64+
w5: mapped[5],
65+
w6: mapped[6],
66+
} as const;
67+
return {
68+
typ,
69+
wires: nativeWires,
70+
coeffs: toBuffer(fieldsToRustFlat(coeffs)),
71+
};
72+
},
73+
gateFromRust(nativeGate: any): Gate {
74+
const { typ, wires, coeffs } = nativeGate;
75+
const mlWires: Gate[2] = [
76+
0,
77+
[0, wires.w0.row, wires.w0.col],
78+
[0, wires.w1.row, wires.w1.col],
79+
[0, wires.w2.row, wires.w2.col],
80+
[0, wires.w3.row, wires.w3.col],
81+
[0, wires.w4.row, wires.w4.col],
82+
[0, wires.w5.row, wires.w5.col],
83+
[0, wires.w6.row, wires.w6.col],
84+
];
85+
const mlCoeffs = fieldsFromRustFlat(toUint8Array(coeffs));
86+
return [0, typ, mlWires, mlCoeffs];
87+
},
88+
89+
pointToRust(point: OrInfinity) {
90+
return affineToRust(point, makeAffine);
91+
},
92+
pointFromRust(point: any): OrInfinity {
93+
return affineFromRust(point);
94+
},
95+
96+
pointsToRust([, ...points]: MlArray<OrInfinity>): any[] {
97+
return points.map(self.pointToRust);
98+
},
99+
pointsFromRust(points: unknown): MlArray<OrInfinity> {
100+
return [0, ...asArray(points, 'pointsFromRust').map(self.pointFromRust)];
101+
},
102+
103+
polyCommToRust(polyComm: PolyComm): NapiPolyComm {
104+
const [, camlElems] = polyComm;
105+
const rustUnshifted = self.pointsToRust(camlElems);
106+
return new PolyCommClass(rustUnshifted, undefined);
107+
},
108+
polyCommFromRust(polyComm: NapiPolyComm): PolyComm {
109+
const rustUnshifted = asArray((polyComm as any).unshifted, 'polyComm.unshifted');
110+
const mlUnshifted = rustUnshifted.map(self.pointFromRust);
111+
return [0, [0, ...mlUnshifted]];
112+
},
113+
114+
polyCommsToRust([, ...comms]: MlArray<PolyComm>): NapiPolyComm[] {
115+
return comms.map(self.polyCommToRust);
116+
},
117+
polyCommsFromRust(rustComms: NapiPolyComm[]): MlArray<PolyComm> {
118+
return [0, ...asArray(rustComms, 'polyCommsFromRust').map(self.polyCommFromRust)];
119+
},
120+
};
121+
122+
return self;
123+
}
124+
125+
function asArray<T>(value: unknown, context: string): T[] {
126+
if (value == null) return [];
127+
if (Array.isArray(value)) return value as T[];
128+
throw Error(`${context}: expected array of native values`);
129+
}
130+
131+
function toUint8Array(value: any): Uint8Array {
132+
if (value instanceof Uint8Array) return value;
133+
if (Array.isArray(value)) return Uint8Array.from(value);
134+
if (value && typeof value === 'object') {
135+
if (ArrayBuffer.isView(value)) {
136+
const view = value as ArrayBufferView;
137+
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
138+
}
139+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
140+
}
141+
throw Error('Expected byte array');
142+
}
143+
144+
function toBuffer(bytes: Uint8Array): Buffer {
145+
if (Buffer.isBuffer(bytes)) return bytes;
146+
return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
11147
}

0 commit comments

Comments
 (0)