@@ -909,7 +909,6 @@ contract BlakeOptHonkVerifier is IVerifier {
909909 /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
910910
911911 // Aliases for scratch space
912- // TODO: work out the stack scheduling for these
913912 uint256 internal constant CHALL_POW_LOC = 0x0 ;
914913 uint256 internal constant SUMCHECK_U_LOC = 0x20 ;
915914 uint256 internal constant GEMINI_A_LOC = 0x40 ;
@@ -933,19 +932,22 @@ contract BlakeOptHonkVerifier is IVerifier {
933932 uint256 internal constant EC_Q_SIGN = QL_EVAL_LOC;
934933 uint256 internal constant EC_Q_IS_DOUBLE = QM_EVAL_LOC;
935934
936- // -1/2 mod p
937935 /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
938936 /* CONSTANTS */
939937 /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
940- uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000 ;
941938 uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17 ; // -(-17)
942939
943940 // Auxiliary relation constants
941+ // In the Non Native Field Arithmetic Relation, large field elements are broken up into 4 LIMBs of 68 `LIMB_SIZE` bits each.
944942 uint256 internal constant LIMB_SIZE = 0x100000000000000000 ; // 2<<68
945- uint256 internal constant SUBLIMB_SHIFT = 0x4000 ; // 2<<14
946943
947- // Poseidon internal constants
944+ // In the Delta Range Check Relation, there is a range checking relation that can validate 14-bit range checks with only 1
945+ // extra relation in the execution trace.
946+ // For large range checks, we decompose them into a collection of 14-bit range checks.
947+ uint256 internal constant SUBLIMB_SHIFT = 0x4000 ; // 2<<14
948948
949+ // Poseidon2 internal constants
950+ // https://github.com/HorizenLabs/poseidon2/blob/main/poseidon2_rust_params.sage - derivation code
949951 uint256 internal constant POS_INTERNAL_MATRIX_D_0 =
950952 0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7 ;
951953 uint256 internal constant POS_INTERNAL_MATRIX_D_1 =
@@ -957,6 +959,7 @@ contract BlakeOptHonkVerifier is IVerifier {
957959
958960 // Constants inspecting proof components
959961 uint256 internal constant NUMBER_OF_UNSHIFTED_ENTITIES = 36 ;
962+ // Shifted columns are columes that are duplicates of existing columns but right-shifted by 1
960963 uint256 internal constant NUMBER_OF_SHIFTED_ENTITIES = 5 ;
961964 uint256 internal constant TOTAL_NUMBER_OF_ENTITIES = 41 ;
962965
@@ -966,9 +969,15 @@ contract BlakeOptHonkVerifier is IVerifier {
966969 uint256 internal constant G1_LOCATION = 0x60 ;
967970 uint256 internal constant G1_Y_LOCATION = 0x80 ;
968971 uint256 internal constant SCALAR_LOCATION = 0xa0 ;
972+
969973 uint256 internal constant LOWER_128_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ;
970974
975+ // Group order
976+ uint256 internal constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583 ; // EC group order
977+
971978 // Field order constants
979+ // -1/2 mod p
980+ uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000 ;
972981 uint256 internal constant P = 21888242871839275222246405745257275088548364400416034343698204186575808495617 ;
973982 uint256 internal constant P_SUB_1 = 21888242871839275222246405745257275088548364400416034343698204186575808495616 ;
974983 uint256 internal constant P_SUB_2 = 21888242871839275222246405745257275088548364400416034343698204186575808495615 ;
@@ -978,6 +987,24 @@ contract BlakeOptHonkVerifier is IVerifier {
978987 uint256 internal constant P_SUB_6 = 21888242871839275222246405745257275088548364400416034343698204186575808495611 ;
979988 uint256 internal constant P_SUB_7 = 21888242871839275222246405745257275088548364400416034343698204186575808495610 ;
980989
990+ // Barycentric evaluation constants
991+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_0 =
992+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51 ;
993+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_1 =
994+ 0x00000000000000000000000000000000000000000000000000000000000002d0 ;
995+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_2 =
996+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11 ;
997+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_3 =
998+ 0x0000000000000000000000000000000000000000000000000000000000000090 ;
999+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_4 =
1000+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71 ;
1001+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_5 =
1002+ 0x00000000000000000000000000000000000000000000000000000000000000f0 ;
1003+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_6 =
1004+ 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31 ;
1005+ uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_7 =
1006+ 0x00000000000000000000000000000000000000000000000000000000000013b0 ;
1007+
9811008 // Constants for computing public input delta
9821009 uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28 ;
9831010
@@ -991,19 +1018,22 @@ contract BlakeOptHonkVerifier is IVerifier {
9911018 uint256 internal constant MODEXP_FAILED_SELECTOR = 0xf442f1632 ;
9921019 uint256 internal constant PROOF_POINT_NOT_ON_CURVE_SELECTOR = 0x661e012dec ;
9931020
994- // TOOD: maybe verify vk points are on curve in constructor
9951021 constructor () {}
9961022
997- function verify (bytes calldata , bytes32 [] calldata ) public override view returns (bool ) {
1023+ function verify (bytes calldata , /*proof*/ bytes32 [] calldata /*public_inputs*/ )
1024+ public
1025+ view
1026+ override
1027+ returns (bool )
1028+ {
9981029 // Load the proof from calldata in one large chunk
9991030 assembly {
1000- // Inline the verification key code here for the meantime
1001- // will be in it's own library
1002- // Note the split committments here will make a difference to costs in the end
10031031 /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
10041032 /* LOAD VERIFCATION KEY */
10051033 /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
10061034 // Write the verification key into memory
1035+ //
1036+ // Although defined at the top of the file, it is used towards the end of the algorithm when batching in the commitment scheme.
10071037 function loadVk () {
10081038 mstore (Q_L_X_LOC, 0x1638b2ed58e539359cbb8efff0c6772b16bfe763ff7d1accf8b7fcfe8a075d5d )
10091039 mstore (Q_L_Y_LOC, 0x2ddbcd8955a1df6ee2906cd36e4ef311e1961ec5fda0ca087aaca85c577de5cc )
@@ -1063,8 +1093,8 @@ contract BlakeOptHonkVerifier is IVerifier {
10631093 mstore (LAGRANGE_LAST_Y_LOC, 0x0653455f179c7df626a5b79bf2694c5ceaf36de7f007a4cfa251305b68b50775 )
10641094 }
10651095
1066- // Prime field order
1067- let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617
1096+ // Prime field order - placing on the stack
1097+ let p := P
10681098
10691099 {
10701100 let proof_ptr := add (calldataload (0x04 ), 0x24 )
@@ -1075,14 +1105,8 @@ contract BlakeOptHonkVerifier is IVerifier {
10751105 /*
10761106 * Proof points (affine coordinates) in the proof are in the following format, where offset is
10771107 * the offset in the entire proof until the first bit of the x coordinate
1078- * offset + 0x00: x - lower bits
1079- * offset + 0x20: x - higher bits
1080- * offset + 0x40: y - lower bits
1081- * offset + 0x60: y - higher bits
1082- *
1083- * Proof points are in this extended format at the moment as the proofs are optimised for
1084- * consumption by recursive verifiers
1085- * In the future, it is expect that these proofs will be shortened to be 64 bytes
1108+ * offset + 0x00: x
1109+ * offset + 0x20: y
10861110 */
10871111
10881112 /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
@@ -1225,25 +1249,34 @@ contract BlakeOptHonkVerifier is IVerifier {
12251249 let prev := mload (sub (gate_off, 0x20 ))
12261250
12271251 mstore (gate_off, mulmod (prev, prev, p))
1228-
12291252 gate_off := add (gate_off, 0x20 )
12301253 }
12311254
1255+ // Sumcheck Univariate challenges
1256+ // The algebraic relations of the Honk protocol are max degree-7.
1257+ // To prove satifiability, we multiply the relation by a random (POW) polynomial. We do this as we want all of our relations
1258+ // to be zero on every row - not for the sum of the relations to be zero. (Which is all sumcheck can do without this modification)
1259+ //
1260+ // As a result, in every round of sumcheck, the prover sends an degree-8 univariate polynomial.
1261+ // The sumcheck univariate challenge produces a challenge for each round of sumcheck, hashing the prev_challenge with
1262+ // a hash of the degree 8 univariate polynomial provided by the prover.
1263+ //
1264+ // 8 points are sent as it is enough to uniquely identify the polynomial
12321265 let read_off := SUMCHECK_UNIVARIATE_0_0_LOC
12331266 let write_off := SUM_U_CHALLENGE_0
12341267 for {} lt (read_off, QM_EVAL_LOC) {} {
12351268 // Increase by 20 * batched relation length (8)
1236- // 20 * 8 = 160 (0xa0)
1237-
1269+ // 0x20 * 0x8 = 0x100
12381270 mcopy (0x20 , read_off, 0x100 )
12391271
1240- // Hash 0xa0 + 20 (prev hash) = 0xc0
1272+ // Hash 0x100 + 0x20 (prev hash) = 0x120
12411273 prev_challenge := mod (keccak256 (0x00 , 0x120 ), p)
12421274 mstore (0x00 , prev_challenge)
12431275
12441276 let sumcheck_u_challenge := and (prev_challenge, LOWER_128_MASK)
12451277 mstore (write_off, sumcheck_u_challenge)
12461278
1279+ // Progress read / write pointers
12471280 read_off := add (read_off, 0x100 )
12481281 write_off := add (write_off, 0x20 )
12491282 }
@@ -1265,7 +1298,7 @@ contract BlakeOptHonkVerifier is IVerifier {
12651298 // - QRANGE
12661299 // - QELLIPTIC
12671300 // - QMEMORY
1268- // - QNNF
1301+ // - QNNF (NNF = Non Native Field)
12691302 // - QPOSEIDON2_EXTERNAL
12701303 // - QPOSEIDON2_INTERNAL
12711304 // - SIGMA1
@@ -1374,7 +1407,13 @@ contract BlakeOptHonkVerifier is IVerifier {
13741407 * The above equation enforces that for each cell in the trace, if the id and sigma pair are equal, then the
13751408 * witness value in that cell is equal.
13761409 *
1377- * We extra terms to add to this product that correspond to public input values
1410+ * We extra terms to add to this product that correspond to public input values.
1411+ *
1412+ * The values of id_i and σ_i polynomials are related to a generalized PLONK permutation argument, in the original paper, there
1413+ * were no id_i polynomials.
1414+ *
1415+ * These are required under the multilinear setting as we cannot use cosets of the roots of unity to represent unique sets, rather
1416+ * we just use polynomials that include unique values. In implementation, id_0 can be {0 .. n} and id_1 can be {n .. 2n} and so forth.
13781417 *
13791418 */
13801419 {
@@ -1465,48 +1504,62 @@ contract BlakeOptHonkVerifier is IVerifier {
14651504 /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
14661505 /* SUMCHECK */
14671506 /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
1507+ //
1508+ // Sumcheck is used to prove that every relation 0 on each row of the witness.
1509+ //
1510+ // Given each of the columns of our trace is a multilinear polynomial 𝑃1,…,𝑃𝑁∈𝔽[𝑋0,…,𝑋𝑑−1]. We run sumcheck over the polynomial
1511+ //
1512+ // 𝐹̃ (𝑋0,…,𝑋𝑑−1)=𝑝𝑜𝑤𝛽(𝑋0,…,𝑋𝑑−1)⋅𝐹(𝑃1(𝑋0,…,𝑋𝑑−1),…,𝑃𝑁(𝑋0,…,𝑋𝑑−1))
1513+ //
1514+ // The Pow polynomial is a random polynomial that allows us to ceritify that the relations sum to 0 on each row of the witness,
1515+ // rather than the entire sum just targeting 0.
1516+ //
1517+ // Each polynomial P in our implementation are the polys in the proof and the verification key. (W_1, W_2, W_3, W_4, Z_PERM, etc....)
1518+ //
1519+ // We start with a LOG_N variate multilinear polynomial, each round fixes a variable to a challenge value.
1520+ // Each round the prover sends a round univariate poly, since the degree of our honk relations is 7 + the pow polynomial the prover
1521+ // sends a degree-8 univariate on each round.
1522+ // This is sent efficiently by sending 8 values, enough to represent a unique polynomial.
1523+ // Barycentric evaluation is used to evaluate the polynomial at any point on the domain, given these 8 unique points.
1524+ //
1525+ // In the sumcheck protocol, the target sum for each round is the sum of the round univariate evaluated on 0 and 1.
1526+ // 𝜎𝑖=?𝑆̃ 𝑖(0)+𝑆̃ 𝑖(1)
1527+ // This is efficiently checked as S(0) and S(1) are sent by the prover as values of the round univariate.
1528+ //
1529+ // We compute the next challenge by evaluating the round univariate at a random challenge value.
1530+ // 𝜎𝑖+1←𝑆̃ 𝑖(𝑢𝑖)
1531+ // This evaluation is performed via barycentric evaluation.
1532+ //
1533+ // Once we have reduced the multilinear polynomials into single dimensional polys, we check the entire sumcheck relation matches the target sum.
1534+ //
1535+ // Below this is composed of 8 relations:
1536+ // 1. Arithmetic relation - constrains arithmetic
1537+ // 2. Permutaiton Relation - efficiently encodes copy constraints
1538+ // 3. Log Derivative Lookup Relation - used for lookup operations
1539+ // 4. Delta Range Relation - used for efficient range checks
1540+ // 5. Memory Relation - used for efficient memory operations
1541+ // 6. NNF Relation - used for efficient Non Native Field operations
1542+ // 7. Poseidon2 External Relation - used for efficient in-circuit hashing
1543+ // 8. Poseidon2 Internal Relation - used for efficient in-circuit hashing
1544+ //
1545+ // These are batched together and evaluated at the same time using the alpha challenges.
1546+ //
14681547 {
14691548 // We write the barycentric domain values into memory
14701549 // These are written once per program execution, and reused across all
14711550 // sumcheck rounds
1472- mstore (
1473- BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC,
1474- 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51
1475- )
1476- mstore (
1477- BARYCENTRIC_LAGRANGE_DENOMINATOR_1_LOC,
1478- 0x00000000000000000000000000000000000000000000000000000000000002d0
1479- )
1480- mstore (
1481- BARYCENTRIC_LAGRANGE_DENOMINATOR_2_LOC,
1482- 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11
1483- )
1484- mstore (
1485- BARYCENTRIC_LAGRANGE_DENOMINATOR_3_LOC,
1486- 0x0000000000000000000000000000000000000000000000000000000000000090
1487- )
1488- mstore (
1489- BARYCENTRIC_LAGRANGE_DENOMINATOR_4_LOC,
1490- 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71
1491- )
1492- mstore (
1493- BARYCENTRIC_LAGRANGE_DENOMINATOR_5_LOC,
1494- 0x00000000000000000000000000000000000000000000000000000000000000f0
1495- )
1496- mstore (
1497- BARYCENTRIC_LAGRANGE_DENOMINATOR_6_LOC,
1498- 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31
1499- )
1500- mstore (
1501- BARYCENTRIC_LAGRANGE_DENOMINATOR_7_LOC,
1502- 0x00000000000000000000000000000000000000000000000000000000000013b0
1503- )
1551+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_0)
1552+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_1_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_1)
1553+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_2_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_2)
1554+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_3_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_3)
1555+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_4_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_4)
1556+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_5_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_5)
1557+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_6_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_6)
1558+ mstore (BARYCENTRIC_LAGRANGE_DENOMINATOR_7_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_7)
15041559
15051560 // Compute the target sums for each round of sumcheck
15061561 {
15071562 // This requires the barycentric inverses to be computed for each round
1508- // TODO: PROSE
1509-
15101563 // Write all of the non inverted barycentric denominators into memory
15111564 let accumulator := 1
15121565 let temp := LATER_SCRATCH_SPACE
@@ -2177,8 +2230,7 @@ contract BlakeOptHonkVerifier is IVerifier {
21772230 let record_delta := addmod (mload (W4_SHIFT_EVAL_LOC), sub (p, mload (W4_EVAL_LOC)), p)
21782231
21792232 // index_is_monotonically_increasing = index_delta * (index_delta - 1)
2180- let index_is_monotonically_increasing :=
2181- mulmod (index_delta, addmod (index_delta, P_SUB_1, p), p)
2233+ let index_is_monotonically_increasing := mulmod (index_delta, addmod (index_delta, P_SUB_1, p), p)
21822234
21832235 // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta)
21842236 let adjacent_values_match_if_adjacent_indices_match :=
@@ -2708,11 +2760,6 @@ contract BlakeOptHonkVerifier is IVerifier {
27082760 let off := POWERS_OF_EVALUATION_CHALLENGE_0_LOC
27092761 mstore (off, cache)
27102762
2711- ////////////////////////////////////////////
2712- ////////////////////////////////////////////
2713- // TODO: remove pointer???
2714- ////////////////////////////////////////////
2715- ////////////////////////////////////////////
27162763 for { let i := 1 } lt (i, LOG_N) { i := add (i, 1 ) } {
27172764 off := add (off, 0x20 )
27182765 cache := mulmod (cache, cache, p)
@@ -3599,7 +3646,7 @@ contract BlakeOptHonkVerifier is IVerifier {
35993646 }
36003647
36013648 let precomp_success_flag := 1
3602- let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order
3649+ let q := Q // EC group order
36033650 {
36043651 // The initial accumulator = 1 * shplonk_q
36053652 // WORKTODO(md): we can ignore this accumulation as we are multiplying by 1,
0 commit comments