Skip to content

Commit 9bfe331

Browse files
committed
fix: apply review feedback
1 parent 26cbe44 commit 9bfe331

File tree

1 file changed

+115
-68
lines changed

1 file changed

+115
-68
lines changed

barretenberg/sol/src/honk/optimised/blake-opt.sol

Lines changed: 115 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)