1- import { fieldsFromRustFlat , fieldsToRustFlat } from './bindings/conversion-base.js' ;
2- import { Gate , Wire } from './bindings/kimchi-types.js' ;
1+ import { Buffer } from 'node:buffer' ;
2+ import { fieldFromRust , fieldToRust , fieldsFromRustFlat , fieldsToRustFlat } from './bindings/conversion-base.js' ;
3+ import { Gate , OrInfinity , PolyComm , Wire , Field } from './bindings/kimchi-types.js' ;
4+ import { MlArray } from '../../lib/ml/base.js' ;
35import { mapTuple } from './bindings/util.js' ;
6+ import type * as napiNamespace from '../compiled/node_bindings/plonk_wasm.cjs' ;
47
58export { bindingsNapi } ;
69
10+ type NapiAffine = napiNamespace . WasmGVesta | napiNamespace . WasmGPallas ;
11+ type NapiPolyComm = { unshifted : unknown ; shifted ?: NapiAffine | undefined } ;
12+ type PolyCommCtor = new ( unshifted : unknown , shifted ?: NapiAffine | undefined ) => NapiPolyComm ;
13+
14+ //const FIELD_BYTE_LENGTH = fieldToRust([0, 0n]).length;
15+
16+ type NapiClasses = {
17+ CommitmentCurve : typeof napiNamespace . WasmGVesta | typeof napiNamespace . WasmGPallas ;
18+ makeAffine : ( ) => NapiAffine ;
19+ PolyComm : napiNamespace . WasmFpPolyComm | napiNamespace . WasmFqPolyComm ;
20+ }
21+
722function bindingsNapi ( napi : any ) {
8- return {
9- fp : {
10- vectorToRust : ( fields : any ) => {
11- //console.log('values going in ', fields);
12- let res = fieldsToRustFlat ( fields ) ;
13- //console.log('values going out ', res);
14- return res ;
15- } ,
16- vectorFromRust : fieldsFromRustFlat ,
17- wireToRust ( [ , row , col ] : Wire ) {
18- return { row, col } ;
19- } ,
20- gateToRust ( gate : Gate ) : any {
21- const [ , typ , [ , ...wires ] , coeffs ] = gate ;
22- const mapped = mapTuple ( wires , ( wire ) => this . wireToRust ( wire ) ) ;
23- const nativeWires = {
24- w0 : mapped [ 0 ] ,
25- w1 : mapped [ 1 ] ,
26- w2 : mapped [ 2 ] ,
27- w3 : mapped [ 3 ] ,
28- w4 : mapped [ 4 ] ,
29- w5 : mapped [ 5 ] ,
30- w6 : mapped [ 6 ] ,
31- } as const ;
32- return {
33- typ,
34- wires : nativeWires ,
35- coeffs : Array . from ( fieldsToRustFlat ( coeffs ) ) ,
36- } ;
37- } ,
23+ const fpCore = conversionCorePerField ( {
24+ CommitmentCurve : napi . WasmGVesta ,
25+ makeAffine : napi . caml_vesta_affine_one ,
26+ PolyComm : napi . WasmFpPolyComm ,
27+ } ) ;
28+ const fqCore = conversionCorePerField ( {
29+ CommitmentCurve : napi . WasmGPallas ,
30+ makeAffine : napi . caml_pallas_affine_one ,
31+ PolyComm : napi . WasmFqPolyComm ,
32+ } ) ;
33+
34+ const shared = {
35+ vectorToRust : ( fields : any ) => fieldsToRustFlat ( fields ) ,
36+ vectorFromRust : fieldsFromRustFlat ,
37+ wireToRust ( [ , row , col ] : Wire ) {
38+ return { row, col } ;
3839 } ,
39- fq : {
40- vectorToRust : ( fields : any ) => {
41- //console.log('values going in ', fields);
42- let res = fieldsToRustFlat ( fields ) ;
43- //console.log('values going out ', res);
44- return res ;
45- } ,
46- vectorFromRust : ( fieldBytes : any ) => {
47- //console.log('values going in ', fieldBytes);
48- let res = fieldsFromRustFlat ( fieldBytes ) ;
49- //console.log('values going out ', res);
50- return res ;
51- } ,
52- wireToRust ( [ , row , col ] : Wire ) {
53- return { row, col } ;
54- } ,
55- gateToRust ( gate : Gate ) : any {
40+ gateToRust ( gate : Gate ) : any {
5641 const [ , typ , [ , ...wires ] , coeffs ] = gate ;
5742 const mapped = mapTuple ( wires , ( wire ) => this . wireToRust ( wire ) ) ;
5843 const nativeWires = {
@@ -70,6 +55,86 @@ function bindingsNapi(napi: any) {
7055 coeffs : Array . from ( fieldsToRustFlat ( coeffs ) ) ,
7156 } ;
7257 } ,
73- } ,
7458 } ;
59+
60+ return {
61+ fp : { ...shared , ...fpCore } ,
62+ fq : { ...shared , ...fqCore } ,
63+ } ;
64+ }
65+
66+ function conversionCorePerField ( { makeAffine, PolyComm } : NapiClasses ) {
67+ const affineToRust = ( pt : OrInfinity ) : NapiAffine => {
68+ function isFinitePoint ( point : OrInfinity ) : point is [ 0 , [ 0 , Field , Field ] ] {
69+ return Array . isArray ( point ) ;
70+ }
71+ let res = makeAffine ( ) ;
72+ if ( ! isFinitePoint ( pt ) ) {
73+ res . infinity = true ;
74+ } else {
75+ const tmpBytes = new Uint8Array ( 32 ) ;
76+ const [ , pair ] = pt ;
77+ const [ , x , y ] = pair ;
78+ res . x = fieldToRust ( x , tmpBytes ) ;
79+ res . y = fieldToRust ( y , tmpBytes ) ;
80+ }
81+ return res ;
82+ } ;
83+ const affineFromRust = ( pt : NapiAffine ) : OrInfinity => {
84+ if ( pt . infinity ) return 0 ;
85+ const xField = fieldFromRust ( pt . x ) ;
86+ const yField = fieldFromRust ( pt . y ) ;
87+ return [ 0 , [ 0 , xField , yField ] ] ;
88+ } ;
89+
90+ const pointToRust = ( point : OrInfinity ) : NapiAffine => affineToRust ( point ) ;
91+ const pointFromRust = ( point : NapiAffine ) : OrInfinity => affineFromRust ( point ) ;
92+
93+ const pointsToRust = ( [ , ...points ] : MlArray < OrInfinity > ) : NapiAffine [ ] => points . map ( affineToRust ) ;
94+ const pointsFromRust = ( points : NapiAffine [ ] ) : MlArray < OrInfinity > => [ 0 , ...points . map ( affineFromRust ) ] ;
95+
96+ const polyCommToRust = ( polyComm : PolyComm ) : NapiPolyComm => {
97+ const [ , camlElems ] = polyComm ;
98+ const unshifted = pointsToRust ( camlElems ) ;
99+ const PolyCommClass = PolyComm as unknown as PolyCommCtor ;
100+ return new PolyCommClass ( unshifted as unknown , undefined ) ;
101+ } ;
102+
103+ const polyCommFromRust = ( polyComm : NapiPolyComm ) : PolyComm => {
104+ const rustUnshifted = asArrayLike < NapiAffine > ( polyComm . unshifted , 'polyComm.unshifted' ) ;
105+ const mlUnshifted = rustUnshifted . map ( affineFromRust ) ;
106+ return [ 0 , [ 0 , ...mlUnshifted ] ] ;
107+ } ;
108+
109+ const polyCommsToRust = ( [ , ...comms ] : MlArray < PolyComm > ) : NapiPolyComm [ ] =>
110+ comms . map ( polyCommToRust ) ;
111+
112+ const polyCommsFromRust = ( rustComms : unknown ) : MlArray < PolyComm > => {
113+ const comms = asArrayLike < NapiPolyComm > ( rustComms , 'polyCommsFromRust' ) ;
114+ return [ 0 , ...comms . map ( polyCommFromRust ) ] ;
115+ } ;
116+
117+ return {
118+ affineToRust,
119+ affineFromRust,
120+ pointToRust,
121+ pointFromRust,
122+ pointsToRust,
123+ pointsFromRust,
124+ polyCommToRust,
125+ polyCommFromRust,
126+ polyCommsToRust,
127+ polyCommsFromRust,
128+ } ;
129+ }
130+
131+ function asArrayLike < T > ( value : unknown , context : string ) : T [ ] {
132+ if ( value == null ) return [ ] ;
133+ if ( Array . isArray ( value ) ) return value as T [ ] ;
134+ if ( ArrayBuffer . isView ( value ) ) return Array . from ( value as unknown as ArrayLike < T > ) ;
135+ if ( typeof value === 'object' && value !== null && 'length' in ( value as { length : unknown } ) ) {
136+ const { length } = value as { length : unknown } ;
137+ if ( typeof length === 'number' ) return Array . from ( value as ArrayLike < T > ) ;
138+ }
139+ throw Error ( `${ context } : expected array-like native values` ) ;
75140}
0 commit comments