Skip to content

Commit a6ffbca

Browse files
committed
chore: apply to cpp
1 parent 9bfe331 commit a6ffbca

File tree

1 file changed

+115
-67
lines changed

1 file changed

+115
-67
lines changed

barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_optimized_contract.hpp

Lines changed: 115 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -454,19 +454,22 @@ contract HonkVerifier is IVerifier {
454454
uint256 internal constant EC_Q_SIGN = QL_EVAL_LOC;
455455
uint256 internal constant EC_Q_IS_DOUBLE = QM_EVAL_LOC;
456456
457-
// -1/2 mod p
458457
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
459458
/* CONSTANTS */
460459
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
461-
uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
462460
uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; // -(-17)
463461
464462
// Auxiliary relation constants
463+
// In the Non Native Field Arithmetic Relation, large field elements are broken up into 4 LIMBs of 68 `LIMB_SIZE` bits each.
465464
uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68
466-
uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14
467465
468-
// Poseidon internal constants
466+
// In the Delta Range Check Relation, there is a range checking relation that can validate 14-bit range checks with only 1
467+
// extra relation in the execution trace.
468+
// For large range checks, we decompose them into a collection of 14-bit range checks.
469+
uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14
469470
471+
// Poseidon2 internal constants
472+
// https://github.com/HorizenLabs/poseidon2/blob/main/poseidon2_rust_params.sage - derivation code
470473
uint256 internal constant POS_INTERNAL_MATRIX_D_0 =
471474
0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7;
472475
uint256 internal constant POS_INTERNAL_MATRIX_D_1 =
@@ -478,6 +481,7 @@ contract HonkVerifier is IVerifier {
478481
479482
// Constants inspecting proof components
480483
uint256 internal constant NUMBER_OF_UNSHIFTED_ENTITIES = 36;
484+
// Shifted columns are columes that are duplicates of existing columns but right-shifted by 1
481485
uint256 internal constant NUMBER_OF_SHIFTED_ENTITIES = 5;
482486
uint256 internal constant TOTAL_NUMBER_OF_ENTITIES = 41;
483487
@@ -487,9 +491,15 @@ contract HonkVerifier is IVerifier {
487491
uint256 internal constant G1_LOCATION = 0x60;
488492
uint256 internal constant G1_Y_LOCATION = 0x80;
489493
uint256 internal constant SCALAR_LOCATION = 0xa0;
494+
490495
uint256 internal constant LOWER_128_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
491496
497+
// Group order
498+
uint256 internal constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order
499+
492500
// Field order constants
501+
// -1/2 mod p
502+
uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
493503
uint256 internal constant P = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
494504
uint256 internal constant P_SUB_1 = 21888242871839275222246405745257275088548364400416034343698204186575808495616;
495505
uint256 internal constant P_SUB_2 = 21888242871839275222246405745257275088548364400416034343698204186575808495615;
@@ -499,6 +509,24 @@ contract HonkVerifier is IVerifier {
499509
uint256 internal constant P_SUB_6 = 21888242871839275222246405745257275088548364400416034343698204186575808495611;
500510
uint256 internal constant P_SUB_7 = 21888242871839275222246405745257275088548364400416034343698204186575808495610;
501511
512+
// Barycentric evaluation constants
513+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_0 =
514+
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51;
515+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_1 =
516+
0x00000000000000000000000000000000000000000000000000000000000002d0;
517+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_2 =
518+
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11;
519+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_3 =
520+
0x0000000000000000000000000000000000000000000000000000000000000090;
521+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_4 =
522+
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71;
523+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_5 =
524+
0x00000000000000000000000000000000000000000000000000000000000000f0;
525+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_6 =
526+
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31;
527+
uint256 internal constant BARYCENTRIC_LAGRANGE_DENOMINATOR_7 =
528+
0x00000000000000000000000000000000000000000000000000000000000013b0;
529+
502530
// Constants for computing public input delta
503531
uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28;
504532
@@ -512,19 +540,22 @@ contract HonkVerifier is IVerifier {
512540
uint256 internal constant MODEXP_FAILED_SELECTOR = 0xf442f1632;
513541
uint256 internal constant PROOF_POINT_NOT_ON_CURVE_SELECTOR = 0x661e012dec;
514542
515-
// TOOD: maybe verify vk points are on curve in constructor
516543
constructor() {}
517544
518-
function verify(bytes calldata, bytes32[] calldata) public override view returns (bool) {
545+
function verify(bytes calldata, /*proof*/ bytes32[] calldata /*public_inputs*/ )
546+
public
547+
view
548+
override
549+
returns (bool)
550+
{
519551
// Load the proof from calldata in one large chunk
520552
assembly {
521-
// Inline the verification key code here for the meantime
522-
// will be in it's own library
523-
// Note the split committments here will make a difference to costs in the end
524553
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
525554
/* LOAD VERIFCATION KEY */
526555
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
527556
// Write the verification key into memory
557+
//
558+
// Although defined at the top of the file, it is used towards the end of the algorithm when batching in the commitment scheme.
528559
function loadVk() {
529560
mstore(Q_L_X_LOC, {{ Q_L_X_LOC }})
530561
mstore(Q_L_Y_LOC, {{ Q_L_Y_LOC }})
@@ -584,8 +615,8 @@ contract HonkVerifier is IVerifier {
584615
mstore(LAGRANGE_LAST_Y_LOC, {{ LAGRANGE_LAST_Y_LOC }})
585616
}
586617
587-
// Prime field order
588-
let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617
618+
// Prime field order - placing on the stack
619+
let p := P
589620
590621
{
591622
let proof_ptr := add(calldataload(0x04), 0x24)
@@ -596,14 +627,8 @@ contract HonkVerifier is IVerifier {
596627
/*
597628
* Proof points (affine coordinates) in the proof are in the following format, where offset is
598629
* the offset in the entire proof until the first bit of the x coordinate
599-
* offset + 0x00: x - lower bits
600-
* offset + 0x20: x - higher bits
601-
* offset + 0x40: y - lower bits
602-
* offset + 0x60: y - higher bits
603-
*
604-
* Proof points are in this extended format at the moment as the proofs are optimised for
605-
* consumption by recursive verifiers
606-
* In the future, it is expect that these proofs will be shortened to be 64 bytes
630+
* offset + 0x00: x
631+
* offset + 0x20: y
607632
*/
608633
609634
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
@@ -746,25 +771,34 @@ contract HonkVerifier is IVerifier {
746771
let prev := mload(sub(gate_off, 0x20))
747772
748773
mstore(gate_off, mulmod(prev, prev, p))
749-
750774
gate_off := add(gate_off, 0x20)
751775
}
752776
777+
// Sumcheck Univariate challenges
778+
// The algebraic relations of the Honk protocol are max degree-7.
779+
// To prove satifiability, we multiply the relation by a random (POW) polynomial. We do this as we want all of our relations
780+
// 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)
781+
//
782+
// As a result, in every round of sumcheck, the prover sends an degree-8 univariate polynomial.
783+
// The sumcheck univariate challenge produces a challenge for each round of sumcheck, hashing the prev_challenge with
784+
// a hash of the degree 8 univariate polynomial provided by the prover.
785+
//
786+
// 8 points are sent as it is enough to uniquely identify the polynomial
753787
let read_off := SUMCHECK_UNIVARIATE_0_0_LOC
754788
let write_off := SUM_U_CHALLENGE_0
755789
for {} lt(read_off, QM_EVAL_LOC) {} {
756790
// Increase by 20 * batched relation length (8)
757-
// 20 * 8 = 160 (0xa0)
758-
791+
// 0x20 * 0x8 = 0x100
759792
mcopy(0x20, read_off, 0x100)
760793
761-
// Hash 0xa0 + 20 (prev hash) = 0xc0
794+
// Hash 0x100 + 0x20 (prev hash) = 0x120
762795
prev_challenge := mod(keccak256(0x00, 0x120), p)
763796
mstore(0x00, prev_challenge)
764797
765798
let sumcheck_u_challenge := and(prev_challenge, LOWER_128_MASK)
766799
mstore(write_off, sumcheck_u_challenge)
767800
801+
// Progress read / write pointers
768802
read_off := add(read_off, 0x100)
769803
write_off := add(write_off, 0x20)
770804
}
@@ -786,7 +820,7 @@ contract HonkVerifier is IVerifier {
786820
// - QRANGE
787821
// - QELLIPTIC
788822
// - QMEMORY
789-
// - QNNF
823+
// - QNNF (NNF = Non Native Field)
790824
// - QPOSEIDON2_EXTERNAL
791825
// - QPOSEIDON2_INTERNAL
792826
// - SIGMA1
@@ -895,7 +929,13 @@ contract HonkVerifier is IVerifier {
895929
* The above equation enforces that for each cell in the trace, if the id and sigma pair are equal, then the
896930
* witness value in that cell is equal.
897931
*
898-
* We extra terms to add to this product that correspond to public input values
932+
* We extra terms to add to this product that correspond to public input values.
933+
*
934+
* The values of id_i and σ_i polynomials are related to a generalized PLONK permutation argument, in the original paper, there
935+
* were no id_i polynomials.
936+
*
937+
* These are required under the multilinear setting as we cannot use cosets of the roots of unity to represent unique sets, rather
938+
* 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.
899939
*
900940
*/
901941
{
@@ -986,48 +1026,62 @@ contract HonkVerifier is IVerifier {
9861026
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
9871027
/* SUMCHECK */
9881028
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
1029+
//
1030+
// Sumcheck is used to prove that every relation 0 on each row of the witness.
1031+
//
1032+
// Given each of the columns of our trace is a multilinear polynomial 𝑃1,…,𝑃𝑁∈𝔽[𝑋0,…,𝑋𝑑−1]. We run sumcheck over the polynomial
1033+
//
1034+
// 𝐹̃ (𝑋0,…,𝑋𝑑−1)=𝑝𝑜𝑤𝛽(𝑋0,…,𝑋𝑑−1)⋅𝐹(𝑃1(𝑋0,…,𝑋𝑑−1),…,𝑃𝑁(𝑋0,…,𝑋𝑑−1))
1035+
//
1036+
// The Pow polynomial is a random polynomial that allows us to ceritify that the relations sum to 0 on each row of the witness,
1037+
// rather than the entire sum just targeting 0.
1038+
//
1039+
// 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....)
1040+
//
1041+
// We start with a LOG_N variate multilinear polynomial, each round fixes a variable to a challenge value.
1042+
// Each round the prover sends a round univariate poly, since the degree of our honk relations is 7 + the pow polynomial the prover
1043+
// sends a degree-8 univariate on each round.
1044+
// This is sent efficiently by sending 8 values, enough to represent a unique polynomial.
1045+
// Barycentric evaluation is used to evaluate the polynomial at any point on the domain, given these 8 unique points.
1046+
//
1047+
// In the sumcheck protocol, the target sum for each round is the sum of the round univariate evaluated on 0 and 1.
1048+
// 𝜎𝑖=?𝑆̃ 𝑖(0)+𝑆̃ 𝑖(1)
1049+
// This is efficiently checked as S(0) and S(1) are sent by the prover as values of the round univariate.
1050+
//
1051+
// We compute the next challenge by evaluating the round univariate at a random challenge value.
1052+
// 𝜎𝑖+1←𝑆̃ 𝑖(𝑢𝑖)
1053+
// This evaluation is performed via barycentric evaluation.
1054+
//
1055+
// Once we have reduced the multilinear polynomials into single dimensional polys, we check the entire sumcheck relation matches the target sum.
1056+
//
1057+
// Below this is composed of 8 relations:
1058+
// 1. Arithmetic relation - constrains arithmetic
1059+
// 2. Permutaiton Relation - efficiently encodes copy constraints
1060+
// 3. Log Derivative Lookup Relation - used for lookup operations
1061+
// 4. Delta Range Relation - used for efficient range checks
1062+
// 5. Memory Relation - used for efficient memory operations
1063+
// 6. NNF Relation - used for efficient Non Native Field operations
1064+
// 7. Poseidon2 External Relation - used for efficient in-circuit hashing
1065+
// 8. Poseidon2 Internal Relation - used for efficient in-circuit hashing
1066+
//
1067+
// These are batched together and evaluated at the same time using the alpha challenges.
1068+
//
9891069
{
9901070
// We write the barycentric domain values into memory
9911071
// These are written once per program execution, and reused across all
9921072
// sumcheck rounds
993-
mstore(
994-
BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC,
995-
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51
996-
)
997-
mstore(
998-
BARYCENTRIC_LAGRANGE_DENOMINATOR_1_LOC,
999-
0x00000000000000000000000000000000000000000000000000000000000002d0
1000-
)
1001-
mstore(
1002-
BARYCENTRIC_LAGRANGE_DENOMINATOR_2_LOC,
1003-
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff11
1004-
)
1005-
mstore(
1006-
BARYCENTRIC_LAGRANGE_DENOMINATOR_3_LOC,
1007-
0x0000000000000000000000000000000000000000000000000000000000000090
1008-
)
1009-
mstore(
1010-
BARYCENTRIC_LAGRANGE_DENOMINATOR_4_LOC,
1011-
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffff71
1012-
)
1013-
mstore(
1014-
BARYCENTRIC_LAGRANGE_DENOMINATOR_5_LOC,
1015-
0x00000000000000000000000000000000000000000000000000000000000000f0
1016-
)
1017-
mstore(
1018-
BARYCENTRIC_LAGRANGE_DENOMINATOR_6_LOC,
1019-
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31
1020-
)
1021-
mstore(
1022-
BARYCENTRIC_LAGRANGE_DENOMINATOR_7_LOC,
1023-
0x00000000000000000000000000000000000000000000000000000000000013b0
1024-
)
1073+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_0_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_0)
1074+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_1_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_1)
1075+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_2_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_2)
1076+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_3_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_3)
1077+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_4_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_4)
1078+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_5_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_5)
1079+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_6_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_6)
1080+
mstore(BARYCENTRIC_LAGRANGE_DENOMINATOR_7_LOC, BARYCENTRIC_LAGRANGE_DENOMINATOR_7)
10251081
10261082
// Compute the target sums for each round of sumcheck
10271083
{
10281084
// This requires the barycentric inverses to be computed for each round
1029-
// TODO: PROSE
1030-
10311085
// Write all of the non inverted barycentric denominators into memory
10321086
let accumulator := 1
10331087
let temp := LATER_SCRATCH_SPACE
@@ -1698,8 +1752,7 @@ contract HonkVerifier is IVerifier {
16981752
let record_delta := addmod(mload(W4_SHIFT_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p)
16991753
17001754
// index_is_monotonically_increasing = index_delta * (index_delta - 1)
1701-
let index_is_monotonically_increasing :=
1702-
mulmod(index_delta, addmod(index_delta, P_SUB_1, p), p)
1755+
let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, P_SUB_1, p), p)
17031756
17041757
// adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta)
17051758
let adjacent_values_match_if_adjacent_indices_match :=
@@ -2229,11 +2282,6 @@ contract HonkVerifier is IVerifier {
22292282
let off := POWERS_OF_EVALUATION_CHALLENGE_0_LOC
22302283
mstore(off, cache)
22312284
2232-
////////////////////////////////////////////
2233-
////////////////////////////////////////////
2234-
// TODO: remove pointer???
2235-
////////////////////////////////////////////
2236-
////////////////////////////////////////////
22372285
for { let i := 1 } lt(i, LOG_N) { i := add(i, 1) } {
22382286
off := add(off, 0x20)
22392287
cache := mulmod(cache, cache, p)
@@ -2707,7 +2755,7 @@ contract HonkVerifier is IVerifier {
27072755
}
27082756
27092757
let precomp_success_flag := 1
2710-
let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order
2758+
let q := Q // EC group order
27112759
{
27122760
// The initial accumulator = 1 * shplonk_q
27132761
// WORKTODO(md): we can ignore this accumulation as we are multiplying by 1,

0 commit comments

Comments
 (0)