Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into rb/wasm-custom-gat…
Browse files Browse the repository at this point in the history
…es-revived
  • Loading branch information
rbonichon committed Jul 27, 2023
2 parents b917f85 + 6aba5bd commit 3872e20
Show file tree
Hide file tree
Showing 41 changed files with 2,237 additions and 1,817 deletions.
1 change: 1 addition & 0 deletions compiled/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_node_bindings
File renamed without changes.
1 change: 1 addition & 0 deletions compiled/node_bindings/snarky_js_node.bc.d.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// this file exists to prevent TS from type-checking `snarky_js_node.bc.cjs`
6 changes: 5 additions & 1 deletion crypto/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @gen this file is generated - don't edit it directly
export { prefixes, versionBytes, poseidonParamsKimchiFp, poseidonParamsLegacyFp }
export { prefixes, versionBytes, poseidonParamsKimchiFp, poseidonParamsLegacyFp, mocks }

let prefixes = {
"event": "MinaZkappEvent******",
Expand Down Expand Up @@ -856,4 +856,8 @@ let poseidonParamsLegacyFp = {
"rate": 2,
"power": 5
};
let mocks = {
"dummyVerificationKeyHash":
"3392518251768960475377392625298437850623664973002200885669375116181514017494"
};

17 changes: 11 additions & 6 deletions crypto/elliptic_curve.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FiniteField, Fp, inverse, mod, p, q } from "./finite_field.js";
import { FiniteField, Fp, inverse, mod, p, q } from './finite_field.js';
export { Pallas, Vesta, GroupAffine, GroupProjective, GroupMapPallas };

// TODO: constants, like generator points and cube roots for endomorphisms, should be drawn from
Expand All @@ -22,8 +22,9 @@ const vestaEndoScalar =
const pallasEndoScalar =
26005156700822196841419187675678338661165322343552424574062261873906994770353n;

// the b in y^2 = x^3 + b
// the b and a in y^2 = x^3 + ax + b
const b = 5n;
const a = 0n;

const projectiveZero = { x: 1n, y: 1n, z: 0n };

Expand Down Expand Up @@ -153,7 +154,7 @@ function projectiveAdd(g: GroupProjective, h: GroupProjective, p: bigint) {
if (S1 === S2) return projectiveDouble(g, p);
// if S1 = -S2, the points are inverse, so return zero
if (mod(S1 + S2, p) === 0n) return projectiveZero;
throw Error("projectiveAdd: invalid point");
throw Error('projectiveAdd: invalid point');
}
// I = (2*H)^2
let I = mod((H * H) << 2n, p);
Expand Down Expand Up @@ -262,14 +263,16 @@ function createCurveProjective(
generator: GroupProjective,
endoBase: bigint,
endoScalar: bigint,
b: bigint
b: bigint,
a: bigint
) {
return {
zero: projectiveZero,
one: generator,
endoBase,
endoScalar,
b,
a,

equal(g: GroupProjective, h: GroupProjective) {
return projectiveEqual(g, h, p);
Expand Down Expand Up @@ -310,12 +313,14 @@ const Pallas = createCurveProjective(
pallasGeneratorProjective,
pallasEndoBase,
pallasEndoScalar,
b
b,
a
);
const Vesta = createCurveProjective(
q,
vestaGeneratorProjective,
vestaEndoBase,
vestaEndoScalar,
b
b,
a
);
18 changes: 11 additions & 7 deletions crypto/poseidon.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { testPoseidonLegacyFp } from './test_vectors/poseidonLegacy.js';
import { expect } from 'expect';
import { bigIntToBytes, parseHexString } from './bigint-helpers.js';
import { test, Random } from '../../lib/testing/property.js';
import { Poseidon as SnarkyPoseidon } from '../../lib/hash.js';
import { Field } from '../../lib/core.js';
import { Test } from '../../snarky.js';
import { FieldConst } from '../../lib/field.js';
import { MlArray } from '../../lib/ml/base.js';

function checkTestVectors(testVectors: {input: string[], output: string}[], hash: (input: bigint[]) => bigint) {
for (let i = 0; i < testVectors.length; i++) {
Expand All @@ -24,14 +25,17 @@ checkTestVectors(testPoseidonLegacyFp.test_vectors, PoseidonLegacy.hash);
console.log('poseidon implementation matches the test vectors! 🎉');

test(Random.array(Random.field, Random.nat(20)), (xs) => {
let g1 = Poseidon.hashToGroup(xs);
let g2 = SnarkyPoseidon.hashToGroup(xs.map(Field));
let g1 = Poseidon.hashToGroup(xs)!;
let [, g2x, g2y] = Test.poseidon.hashToGroup(
MlArray.to(xs.map(FieldConst.fromBigint))
);

expect(g1).toBeDefined();

expect(g1?.x).toEqual(g2.x.toBigInt());
expect(g1?.y.x0).toEqual(g2.y.x0.toBigInt());
expect(g1?.y.x1).toEqual(g2.y.x1.toBigInt());
expect(g1.x).toEqual(FieldConst.toBigint(g2x));

let g2y_ = FieldConst.toBigint(g2y);
expect(g1.y.x0 === g2y_ || g1.y.x1 === g2y_).toEqual(true);
});

console.log('poseidon hashToGroup implementations match! 🎉');
Expand Down
2 changes: 1 addition & 1 deletion js/node/node-backend.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isMainThread, parentPort, workerData, Worker } from 'worker_threads';
import os from 'os';
import wasm_ from '../../../_node_bindings/plonk_wasm.cjs';
import wasm_ from '../../compiled/_node_bindings/plonk_wasm.cjs';
import { fileURLToPath } from 'url';
let url = import.meta.url;
let filename = url !== undefined ? fileURLToPath(url) : __filename;
Expand Down
20 changes: 6 additions & 14 deletions js/snarky-class-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,8 @@ export default [
{ name: 'exists', type: 'function' },
{ name: 'existsVar', type: 'function' },
{
name: 'asProver',
type: 'function',
},
{
name: 'runAndCheck',
type: 'function',
},
{
name: 'runUnchecked',
type: 'function',
},
{
name: 'constraintSystem',
type: 'function',
name: 'run',
type: 'object',
},
{
name: 'field',
Expand Down Expand Up @@ -95,6 +83,10 @@ export default [
name: 'tokenId',
type: 'object',
},
{
name: 'poseidon',
type: 'object',
},
{
name: 'signature',
type: 'object',
Expand Down
2 changes: 1 addition & 1 deletion js/web/web-backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let init = wasm.default;
let worker;

async function initSnarkyJS() {
const memory = allocateWasmMemoryForUserAgent(window.navigator.userAgent);
const memory = allocateWasmMemoryForUserAgent(navigator.userAgent);
await init(undefined, memory);

let module = init.__wbindgen_wasm_module;
Expand Down
2 changes: 1 addition & 1 deletion js/wrapper.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as wasm from '../compiled/node_bindings/plonk_wasm.js';
import * as wasm from '../compiled/node_bindings/plonk_wasm.cjs';

export { WasmModule, getWasm, getSnarky, withThreadPool };

Expand Down
2 changes: 1 addition & 1 deletion js/wrapper.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { wasm, withThreadPool } from './node/node-backend.js';
import { default as snarky } from '../../_node_bindings/snarky_js_node.bc.cjs';
import { default as snarky } from '../compiled/_node_bindings/snarky_js_node.bc.cjs';

export { getSnarky, getWasm, withThreadPool };

Expand Down
4 changes: 2 additions & 2 deletions kimchi/wasm/src/arkworks/bigint_256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ pub fn caml_bigint_256_of_decimal_string(s: String) -> WasmBigInteger256 {

#[wasm_bindgen]
pub fn caml_bigint_256_num_limbs() -> i32 {
return BIGINT256_NUM_LIMBS.try_into().unwrap();
BIGINT256_NUM_LIMBS
}

#[wasm_bindgen]
pub fn caml_bigint_256_bytes_per_limb() -> i32 {
return BIGINT256_LIMB_BYTES.try_into().unwrap();
BIGINT256_LIMB_BYTES
}

#[wasm_bindgen]
Expand Down
4 changes: 2 additions & 2 deletions kimchi/wasm/src/arkworks/pasta_fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub fn caml_pasta_fp_div(x: WasmPastaFp, y: WasmPastaFp) -> WasmPastaFp {

#[wasm_bindgen]
pub fn caml_pasta_fp_inv(x: WasmPastaFp) -> Option<WasmPastaFp> {
x.0.inverse().map(|x| WasmPastaFp(x))
x.0.inverse().map(WasmPastaFp)
}

#[wasm_bindgen]
Expand All @@ -134,7 +134,7 @@ pub fn caml_pasta_fp_is_square(x: WasmPastaFp) -> bool {

#[wasm_bindgen]
pub fn caml_pasta_fp_sqrt(x: WasmPastaFp) -> Option<WasmPastaFp> {
x.0.sqrt().map(|x| WasmPastaFp(x))
x.0.sqrt().map(WasmPastaFp)
}

#[wasm_bindgen]
Expand Down
4 changes: 2 additions & 2 deletions kimchi/wasm/src/arkworks/pasta_fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub fn caml_pasta_fq_div(x: WasmPastaFq, y: WasmPastaFq) -> WasmPastaFq {

#[wasm_bindgen]
pub fn caml_pasta_fq_inv(x: WasmPastaFq) -> Option<WasmPastaFq> {
x.0.inverse().map(|x| WasmPastaFq(x))
x.0.inverse().map(WasmPastaFq)
}

#[wasm_bindgen]
Expand All @@ -134,7 +134,7 @@ pub fn caml_pasta_fq_is_square(x: WasmPastaFq) -> bool {

#[wasm_bindgen]
pub fn caml_pasta_fq_sqrt(x: WasmPastaFq) -> Option<WasmPastaFq> {
x.0.sqrt().map(|x| WasmPastaFq(x))
x.0.sqrt().map(WasmPastaFq)
}

#[wasm_bindgen]
Expand Down
3 changes: 2 additions & 1 deletion kimchi/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern "C" {

#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
alert(&format!("Hello, {name}!"));
}

#[wasm_bindgen]
Expand Down Expand Up @@ -59,6 +59,7 @@ pub fn set_u32_ptr(ptr: *mut u32, arg: u32) {
}
}

#[allow(unreachable_code)]
#[wasm_bindgen]
pub fn wait_until_non_zero(ptr: *const u32) -> u32 {
// The rust docs explicitly forbid using this for cross-thread syncronization. Oh well, we
Expand Down
1 change: 1 addition & 0 deletions kimchi/wasm/src/oracles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ macro_rules! impl_oracles {

#[wasm_bindgen]
impl [<Wasm $field_name:camel RandomOracles>] {
#[allow(clippy::too_many_arguments)]
#[wasm_bindgen(constructor)]
pub fn new(
joint_combiner_chal: Option<$WasmF>,
Expand Down
80 changes: 72 additions & 8 deletions kimchi/wasm/src/pasta_fp_plonk_index.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
use ark_poly::EvaluationDomain;
use kimchi::circuits::lookup::runtime_tables::RuntimeTableCfg;

use crate::arkworks::WasmPastaFp;
use crate::gate_vector::fp::WasmGateVector;
use crate::srs::fp::WasmFpSrs as WasmSrs;
use crate::wasm_flat_vector::WasmFlatVector;
use crate::wasm_vector::fp::*;
use kimchi::circuits::lookup::tables::LookupTable;
use kimchi::circuits::{constraints::ConstraintSystem, gate::CircuitGate};
use kimchi::linearization::expr_linearization;
use kimchi::prover_index::ProverIndex;
Expand All @@ -22,7 +27,67 @@ use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct WasmPastaFpPlonkIndex(#[wasm_bindgen(skip)] pub Box<ProverIndex<GAffine>>);

//
// This should mimic LookupTable structure
#[wasm_bindgen]
pub struct WasmPastaFpLookupTable {
#[wasm_bindgen(skip)]
pub id: i32,
#[wasm_bindgen(skip)]
pub data: WasmVecVecFp,
}

// Converter from WasmPastaFpLookupTable to LookupTable, used by the binding
// below.
impl From<WasmPastaFpLookupTable> for LookupTable<Fp> {
fn from(wasm_lt: WasmPastaFpLookupTable) -> LookupTable<Fp> {
LookupTable {
id: wasm_lt.id.into(),
data: wasm_lt.data.0,
}
}
}

// JS constructor for js/bindings.js
#[wasm_bindgen]
impl WasmPastaFpLookupTable {
#[wasm_bindgen(constructor)]
pub fn new(id: i32, data: WasmVecVecFp) -> WasmPastaFpLookupTable {
WasmPastaFpLookupTable { id, data }
}
}

// Runtime table config

#[wasm_bindgen]
pub struct WasmPastaFpRuntimeTableCfg {
#[wasm_bindgen(skip)]
pub id: i32,
#[wasm_bindgen(skip)]
pub first_column: WasmFlatVector<WasmPastaFp>,
}

// JS constructor for js/bindings.js
#[wasm_bindgen]
impl WasmPastaFpRuntimeTableCfg {
#[wasm_bindgen(constructor)]
pub fn new(id: i32, first_column: WasmFlatVector<WasmPastaFp>) -> Self {
Self { id, first_column }
}
}

impl From<WasmPastaFpRuntimeTableCfg> for RuntimeTableCfg<Fp> {
fn from(wasm_rt_table_cfg: WasmPastaFpRuntimeTableCfg) -> Self {
Self {
id: wasm_rt_table_cfg.id,
first_column: wasm_rt_table_cfg
.first_column
.into_iter()
.map(Into::into)
.collect(),
}
}
}

// CamlPastaFpPlonkIndex methods
//

Expand Down Expand Up @@ -121,14 +186,13 @@ pub fn caml_pasta_fp_plonk_index_read(

// optional offset in file
if let Some(offset) = offset {
r.seek(Start(offset as u64)).map_err(|err| {
JsValue::from_str(&format!("caml_pasta_fp_plonk_index_read: {}", err))
})?;
r.seek(Start(offset as u64))
.map_err(|err| JsValue::from_str(&format!("caml_pasta_fp_plonk_index_read: {err}")))?;
}

// deserialize the index
let mut t = ProverIndex::<GAffine>::deserialize(&mut rmp_serde::Deserializer::new(r))
.map_err(|err| JsValue::from_str(&format!("caml_pasta_fp_plonk_index_read: {}", err)))?;
.map_err(|err| JsValue::from_str(&format!("caml_pasta_fp_plonk_index_read: {err}")))?;
t.srs = srs.0.clone();
let (linearization, powers_of_alpha) = expr_linearization(Some(&t.cs.feature_flags), true);
t.linearization = linearization;
Expand All @@ -152,7 +216,7 @@ pub fn caml_pasta_fp_plonk_index_write(
index
.0
.serialize(&mut rmp_serde::Serializer::new(w))
.map_err(|e| JsValue::from_str(&format!("caml_pasta_fp_plonk_index_read: {}", e)))
.map_err(|e| JsValue::from_str(&format!("caml_pasta_fp_plonk_index_read: {e}")))
}

#[wasm_bindgen]
Expand All @@ -165,14 +229,14 @@ pub fn caml_pasta_fp_plonk_index_serialize(index: &WasmPastaFpPlonkIndex) -> Str

fn format_field(f: &Fp) -> String {
// TODO this could be much nicer, should end up as "1", "-1", "0" etc
format!("{}", f)
format!("{f}")
}

pub fn format_circuit_gate(i: usize, gate: &CircuitGate<Fp>) -> String {
let coeffs = gate
.coeffs
.iter()
.map(|coeff: &Fp| format_field(coeff))
.map(format_field)
.collect::<Vec<_>>()
.join("\n");
let wires = gate
Expand Down
Loading

0 comments on commit 3872e20

Please sign in to comment.