diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a80a25b..80b986901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed - Expose raw provable methods of a `ZkProgram` on `zkProgram.rawMethods` https://github.com/o1-labs/o1js/pull/1241 +- Reduce number of constraints needed by `rotate()`, `leftShift()` and, `rightShift()` gadgets https://github.com/o1-labs/o1js/pull/1201 ### Fixed diff --git a/src/bindings b/src/bindings index 5df84bf1f..cea062267 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 5df84bf1f06c9c1e984e19d067fcf10c8ae53299 +Subproject commit cea062267c2cf81edf50fee8ca9578824c056731 diff --git a/src/lib/gadgets/bitwise.ts b/src/lib/gadgets/bitwise.ts index d4fc7ff5f..bd4b65f77 100644 --- a/src/lib/gadgets/bitwise.ts +++ b/src/lib/gadgets/bitwise.ts @@ -276,8 +276,10 @@ function rot( ); // Compute next row rangeCheck64(shifted); - // Compute following row - rangeCheck64(excess); + // note: range-checking `shifted` and `field` is enough. + // * excess < 2^rot follows from the bound check and the rotation equation in the gate + // * rotated < 2^64 follows from rotated = excess + shifted (because shifted has to be a multiple of 2^rot) + // for a proof, see https://github.com/o1-labs/o1js/pull/1201 return [rotated, excess, shifted]; } diff --git a/src/lib/gadgets/bitwise.unit-test.ts b/src/lib/gadgets/bitwise.unit-test.ts index 6fa914a79..73d908af1 100644 --- a/src/lib/gadgets/bitwise.unit-test.ts +++ b/src/lib/gadgets/bitwise.unit-test.ts @@ -1,6 +1,6 @@ import { ZkProgram } from '../proof_system.js'; import { - equivalent, + equivalentProvable as equivalent, equivalentAsync, field, fieldWithRng, @@ -228,7 +228,7 @@ constraintSystem( ifNotAllConstant(contains(xorChain(64))) ); -let rotChain: GateType[] = ['Rot64', 'RangeCheck0', 'RangeCheck0']; +let rotChain: GateType[] = ['Rot64', 'RangeCheck0']; let isJustRotate = ifNotAllConstant( and(contains(rotChain), withoutGenerics(equals(rotChain))) ); diff --git a/tests/vk-regression/plain-constraint-system.ts b/tests/vk-regression/plain-constraint-system.ts index 875135e2c..b5d0c1f44 100644 --- a/tests/vk-regression/plain-constraint-system.ts +++ b/tests/vk-regression/plain-constraint-system.ts @@ -36,6 +36,7 @@ const GroupCS = constraintSystem('Group Primitive', { const BitwiseCS = constraintSystem('Bitwise Primitive', { rot() { let a = Provable.witness(Field, () => new Field(12)); + Gadgets.rangeCheck64(a); // `rotate()` doesn't do this Gadgets.rotate(a, 2, 'left'); Gadgets.rotate(a, 2, 'right'); Gadgets.rotate(a, 4, 'left'); diff --git a/tests/vk-regression/vk-regression.json b/tests/vk-regression/vk-regression.json index 03974dc49..f60540c9f 100644 --- a/tests/vk-regression/vk-regression.json +++ b/tests/vk-regression/vk-regression.json @@ -169,8 +169,8 @@ "digest": "Bitwise Primitive", "methods": { "rot": { - "rows": 13, - "digest": "2c0dadbba96fd7ddb9adb7d643425ce3" + "rows": 10, + "digest": "c38703de755b10edf77bf24269089274" }, "xor": { "rows": 15, @@ -185,12 +185,12 @@ "digest": "b12ad7e8a3fd28b765e059357dbe9e44" }, "leftShift": { - "rows": 7, - "digest": "66de39ad3dd5807f760341ec85a6cc41" + "rows": 5, + "digest": "451f550bf73fecf53c9be82367572cb8" }, "rightShift": { - "rows": 7, - "digest": "a32264f2d4c3092f30d600fa9506385b" + "rows": 5, + "digest": "d0793d4a326d480eaa015902dc34bc39" }, "and": { "rows": 19,