diff --git a/src/bindings b/src/bindings index dd2e7e9577..84483cd12a 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit dd2e7e9577d2cb3c16187da74bf89f9b2972cd6a +Subproject commit 84483cd12abca5a8d2b16c03083976cecced721f diff --git a/src/examples/benchmarks/keccak-witness.ts b/src/examples/benchmarks/keccak-witness.ts new file mode 100644 index 0000000000..cedd6982ca --- /dev/null +++ b/src/examples/benchmarks/keccak-witness.ts @@ -0,0 +1,10 @@ +import { Hash, Bytes, Provable } from 'o1js'; + +let Bytes32 = Bytes(32); + +console.time('keccak witness'); +Provable.runAndCheck(() => { + let bytes = Provable.witness(Bytes32.provable, () => Bytes32.random()); + Hash.Keccak256.hash(bytes); +}); +console.timeEnd('keccak witness'); diff --git a/src/lib/gadgets/bitwise.unit-test.ts b/src/lib/gadgets/bitwise.unit-test.ts index e3444552a0..f6f186e941 100644 --- a/src/lib/gadgets/bitwise.unit-test.ts +++ b/src/lib/gadgets/bitwise.unit-test.ts @@ -78,6 +78,7 @@ let Bitwise = ZkProgram({ leftShift32: { privateInputs: [Field], method(a: Field) { + Gadgets.rangeCheck32(a); return Gadgets.leftShift32(a, 12); }, }, @@ -138,7 +139,9 @@ await Bitwise.compile(); ); }); -await equivalentAsync({ from: [uint(64), uint(64)], to: field }, { runs: 3 })( +const runs = 2; + +await equivalentAsync({ from: [uint(64), uint(64)], to: field }, { runs })( (x, y) => { return x ^ y; }, @@ -148,7 +151,7 @@ await equivalentAsync({ from: [uint(64), uint(64)], to: field }, { runs: 3 })( } ); -await equivalentAsync({ from: [maybeField], to: field }, { runs: 3 })( +await equivalentAsync({ from: [maybeField], to: field }, { runs })( (x) => { return Fp.not(x, 254); }, @@ -157,7 +160,7 @@ await equivalentAsync({ from: [maybeField], to: field }, { runs: 3 })( return proof.publicOutput; } ); -await equivalentAsync({ from: [maybeField], to: field }, { runs: 3 })( +await equivalentAsync({ from: [maybeField], to: field }, { runs })( (x) => { if (x > 2n ** 254n) throw Error('Does not fit into 254 bit'); return Fp.not(x, 254); @@ -168,10 +171,7 @@ await equivalentAsync({ from: [maybeField], to: field }, { runs: 3 })( } ); -await equivalentAsync( - { from: [maybeField, maybeField], to: field }, - { runs: 3 } -)( +await equivalentAsync({ from: [maybeField, maybeField], to: field }, { runs })( (x, y) => { if (x >= 2n ** 64n || y >= 2n ** 64n) throw Error('Does not fit into 64 bits'); @@ -183,7 +183,7 @@ await equivalentAsync( } ); -await equivalentAsync({ from: [field], to: field }, { runs: 3 })( +await equivalentAsync({ from: [field], to: field }, { runs })( (x) => { if (x >= 2n ** 64n) throw Error('Does not fit into 64 bits'); return Fp.rot(x, 12n, 'left'); @@ -194,7 +194,7 @@ await equivalentAsync({ from: [field], to: field }, { runs: 3 })( } ); -await equivalentAsync({ from: [uint(32)], to: uint(32) }, { runs: 30 })( +await equivalentAsync({ from: [uint(32)], to: uint(32) }, { runs })( (x) => { return Fp.rot(x, 12n, 'left', 32n); }, @@ -204,7 +204,7 @@ await equivalentAsync({ from: [uint(32)], to: uint(32) }, { runs: 30 })( } ); -await equivalentAsync({ from: [field], to: field }, { runs: 3 })( +await equivalentAsync({ from: [field], to: field }, { runs })( (x) => { if (x >= 2n ** 64n) throw Error('Does not fit into 64 bits'); return Fp.leftShift(x, 12); @@ -215,9 +215,9 @@ await equivalentAsync({ from: [field], to: field }, { runs: 3 })( } ); -await equivalentAsync({ from: [field], to: field }, { runs: 3 })( +await equivalentAsync({ from: [field], to: field }, { runs })( (x) => { - if (x >= 2n ** 64n) throw Error('Does not fit into 64 bits'); + if (x >= 1n << 32n) throw Error('Does not fit into 32 bits'); return Fp.leftShift(x, 12, 32); }, async (x) => { @@ -226,7 +226,7 @@ await equivalentAsync({ from: [field], to: field }, { runs: 3 })( } ); -await equivalentAsync({ from: [field], to: field }, { runs: 3 })( +await equivalentAsync({ from: [field], to: field }, { runs })( (x) => { if (x >= 2n ** 64n) throw Error('Does not fit into 64 bits'); return Fp.rightShift(x, 12); diff --git a/src/lib/keccak.unit-test.ts b/src/lib/keccak.unit-test.ts index 2e4c160b3f..aad02e2342 100644 --- a/src/lib/keccak.unit-test.ts +++ b/src/lib/keccak.unit-test.ts @@ -1,6 +1,10 @@ import { Keccak } from './keccak.js'; import { ZkProgram } from './proof_system.js'; -import { equivalent, equivalentAsync } from './testing/equivalent.js'; +import { + equivalentProvable, + equivalent, + equivalentAsync, +} from './testing/equivalent.js'; import { keccak_224, keccak_256, @@ -47,13 +51,13 @@ for (let length of lengths) { let inputBytes = bytes(preimageLength); let outputBytes = bytes(length / 8); - equivalent({ from: [inputBytes], to: outputBytes, verbose: true })( + equivalentProvable({ from: [inputBytes], to: outputBytes, verbose: true })( testImplementations.sha3[length], (x) => Keccak.nistSha3(length, x), `sha3 ${length}` ); - equivalent({ from: [inputBytes], to: outputBytes, verbose: true })( + equivalentProvable({ from: [inputBytes], to: outputBytes, verbose: true })( testImplementations.preNist[length], (x) => Keccak.preNist(length, x), `keccak ${length}` diff --git a/src/lib/provable-types/bytes.ts b/src/lib/provable-types/bytes.ts index 992e10bd1f..9bde301e69 100644 --- a/src/lib/provable-types/bytes.ts +++ b/src/lib/provable-types/bytes.ts @@ -4,6 +4,7 @@ import { assert } from '../gadgets/common.js'; import { chunkString } from '../util/arrays.js'; import { Provable } from '../provable.js'; import { UInt8 } from '../int.js'; +import { randomBytes } from '../../bindings/crypto/random.js'; export { Bytes, createBytes, FlexibleBytes }; @@ -64,6 +65,14 @@ class Bytes { return this.from(bytes); } + /** + * Create random {@link Bytes} using secure builtin randomness. + */ + static random() { + let bytes = randomBytes(this.size); + return this.from(bytes); + } + /** * Create {@link Bytes} from a hex string. * diff --git a/src/mina b/src/mina index cb151f6a7d..2a968c8347 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit cb151f6a7d34913090b9c19b79f8872389be5c04 +Subproject commit 2a968c83477ed9f9e3b30a02cc357e541b76dcac