diff --git a/CHANGELOG.md b/CHANGELOG.md index bef8f58bb6..6e28c913f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - To recover existing verification keys and behavior, change the order of properties in your Struct definitions to be alphabetical - The `customObjectKeys` option is removed from `Struct` +### Changed + +- Improve prover performance by ~25% https://github.com/o1-labs/o1js/pull/1092 + - Change internal representation of field elements to be JS bigint instead of Uint8Array + ## [0.13.0](https://github.com/o1-labs/o1js/compare/fbd4b2717...c2f392fe5) ### Breaking changes diff --git a/src/bindings b/src/bindings index ffaaf33cc6..43950db0e3 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit ffaaf33cc6101d960f527ac09321b5f7c910d669 +Subproject commit 43950db0e38afdda83ec9d7bf1124e6e9b416183 diff --git a/src/build/buildExample.js b/src/build/buildExample.js index a7f75c3038..b58cda4e2c 100644 --- a/src/build/buildExample.js +++ b/src/build/buildExample.js @@ -37,6 +37,7 @@ async function build(srcPath, isWeb = false) { makeNodeModulesExternal(), makeJsooExternal(), ], + dropLabels: ['CJS'], }); let absPath = path.resolve('.', outfile); @@ -110,7 +111,7 @@ function makeNodeModulesExternal() { } function makeJsooExternal() { - let isJsoo = /(bc.cjs|plonk_wasm.cjs|wrapper.js)$/; + let isJsoo = /(bc.cjs|plonk_wasm.cjs)$/; return { name: 'plugin-external', setup(build) { diff --git a/src/build/buildWeb.js b/src/build/buildWeb.js index 61149e821a..b9282f14c5 100644 --- a/src/build/buildWeb.js +++ b/src/build/buildWeb.js @@ -90,6 +90,7 @@ async function buildWeb({ production }) { outfile: 'dist/web/index.js', resolveExtensions: ['.js', '.ts'], plugins: [wasmPlugin(), srcStringPlugin()], + dropLabels: ['CJS'], external: ['*.bc.js'], target, allowOverwrite: true, diff --git a/src/examples/benchmarks/hash-witness.ts b/src/examples/benchmarks/hash-witness.ts index 047e14d22d..7e87e96917 100644 --- a/src/examples/benchmarks/hash-witness.ts +++ b/src/examples/benchmarks/hash-witness.ts @@ -1,7 +1,7 @@ /** * benchmark witness generation for an all-mul circuit */ -import { Field, Provable, Poseidon } from 'snarkyjs'; +import { Field, Provable, Poseidon } from 'o1js'; import { tic, toc } from './tic-toc.js'; // parameters diff --git a/src/examples/benchmarks/import.web.ts b/src/examples/benchmarks/import.web.ts index 51a518e1c9..6c8c06e62b 100644 --- a/src/examples/benchmarks/import.web.ts +++ b/src/examples/benchmarks/import.web.ts @@ -1,5 +1,5 @@ let start = performance.now(); -await import('snarkyjs'); +await import('o1js'); let time = performance.now() - start; console.log(`import jsoo: ${time.toFixed(0)}ms`); diff --git a/src/examples/benchmarks/mul-witness.ts b/src/examples/benchmarks/mul-witness.ts index c9804c3e83..dd4b164929 100644 --- a/src/examples/benchmarks/mul-witness.ts +++ b/src/examples/benchmarks/mul-witness.ts @@ -1,7 +1,7 @@ /** * benchmark witness generation for an all-mul circuit */ -import { Field, Provable } from 'snarkyjs'; +import { Field, Provable } from 'o1js'; import { tic, toc } from './tic-toc.js'; // parameters diff --git a/src/lib/field.ts b/src/lib/field.ts index 91eed831fb..8b7bf25df1 100644 --- a/src/lib/field.ts +++ b/src/lib/field.ts @@ -21,23 +21,20 @@ export { toConstantField, }; -type FieldConst = Uint8Array; +type FieldConst = [0, bigint]; function constToBigint(x: FieldConst): Fp { - return Fp.fromBytes([...x]); + return x[1]; } -function constFromBigint(x: Fp) { - return Uint8Array.from(Fp.toBytes(x)); +function constFromBigint(x: Fp): FieldConst { + return [0, x]; } const FieldConst = { fromBigint: constFromBigint, toBigint: constToBigint, equal(x: FieldConst, y: FieldConst) { - for (let i = 0, n = Fp.sizeInBytes(); i < n; i++) { - if (x[i] !== y[i]) return false; - } - return true; + return x[1] === y[1]; }, [0]: constFromBigint(0n), [1]: constFromBigint(1n), @@ -145,15 +142,16 @@ class Field { this.value = x.value; return; } - // FieldVar if (Array.isArray(x)) { - this.value = x; - return; - } - // FieldConst - if (x instanceof Uint8Array) { - this.value = FieldVar.constant(x); - return; + if (typeof x[1] === 'bigint') { + // FieldConst + this.value = FieldVar.constant(x as FieldConst); + return; + } else { + // FieldVar + this.value = x as FieldVar; + return; + } } // TODO this should handle common values efficiently by reading from a lookup table this.value = FieldVar.constant(Fp(x)); @@ -1269,12 +1267,14 @@ class Field { const FieldBinable = defineBinable({ toBytes(t: Field) { - return [...toConstantField(t, 'toBytes').value[1]]; + let t0 = toConstantField(t, 'toBytes').toBigInt(); + return Fp.toBytes(t0); }, readBytes(bytes, offset) { let uint8array = new Uint8Array(32); uint8array.set(bytes.slice(offset, offset + 32)); - return [new Field(uint8array), offset + 32]; + let x = Fp.fromBytes([...uint8array]); + return [new Field(x), offset + 32]; }, }); diff --git a/src/lib/scalar.ts b/src/lib/scalar.ts index dcef9e20d1..176478947f 100644 --- a/src/lib/scalar.ts +++ b/src/lib/scalar.ts @@ -10,11 +10,14 @@ export { Scalar, ScalarConst, unshift, shift }; export { constantScalarToBigint }; type BoolVar = FieldVar; -type ScalarConst = Uint8Array; +type ScalarConst = [0, bigint]; const ScalarConst = { fromBigint: constFromBigint, toBigint: constToBigint, + is(x: any): x is ScalarConst { + return Array.isArray(x) && x[0] === 0 && typeof x[1] === 'bigint'; + }, }; let scalarShift = Fq(1n + 2n ** 255n); @@ -44,9 +47,9 @@ class Scalar { * * If the input is too large, it is reduced modulo the scalar field size. */ - static from(x: Scalar | Uint8Array | bigint | number | string) { + static from(x: Scalar | ScalarConst | bigint | number | string) { if (x instanceof Scalar) return x; - if (x instanceof Uint8Array) x = ScalarConst.toBigint(x); + if (ScalarConst.is(x)) x = constToBigint(x); let scalar = Fq(x); let bits = toBits(scalar); return new Scalar(bits, scalar); @@ -348,10 +351,10 @@ function unshift(s: Fq): Fq { } function constToBigint(x: ScalarConst): Fq { - return Fq.fromBytes([...x]); + return x[1]; } -function constFromBigint(x: Fq) { - return Uint8Array.from(Fq.toBytes(x)); +function constFromBigint(x: Fq): ScalarConst { + return [0, x]; } function constantScalarToBigint(s: Scalar, name: string) { diff --git a/src/mina-signer/src/sign-zkapp-command.unit-test.ts b/src/mina-signer/src/sign-zkapp-command.unit-test.ts index b00cfacf07..7538dbd9ff 100644 --- a/src/mina-signer/src/sign-zkapp-command.unit-test.ts +++ b/src/mina-signer/src/sign-zkapp-command.unit-test.ts @@ -275,7 +275,7 @@ function fixVerificationKey(a: AccountUpdate) { let [, data, hash] = Pickles.dummyVerificationKey(); a.body.update.verificationKey.value = { data, - hash: Field.fromBytes([...hash]), + hash: FieldConst.toBigint(hash), }; } else { a.body.update.verificationKey.value = {