Skip to content

Commit f84ce60

Browse files
authored
feat: merge-train/barretenberg (#16805)
BEGIN_COMMIT_OVERRIDE chore: databus internal audit - small cleanups and tests coverage (#16703) chore: `stdlib::poseidon2` internal audit (#16534) END_COMMIT_OVERRIDE
2 parents e353048 + e6f9e87 commit f84ce60

23 files changed

+1039
-475
lines changed

barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ cd ..
1414
# - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz
1515
# Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0
1616

17-
pinned_short_hash="f2981f9f"
17+
pinned_short_hash="ec9b5be3"
1818
pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz"
1919

2020
function compress_and_upload {

barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_poseidon2s_permutation.test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ auto& engine = numeric::get_debug_randomness();
2020

2121
using Params = crypto::Poseidon2Bn254ScalarFieldParams;
2222
using Builder = UltraCircuitBuilder;
23-
using Permutation = stdlib::Poseidon2Permutation<Params, Builder>;
23+
using Permutation = stdlib::Poseidon2Permutation<Builder>;
2424
using field_t = stdlib::field_t<Builder>;
2525
using witness_t = stdlib::witness_t<Builder>;
2626
using _curve = stdlib::bn254<Builder>;
@@ -70,7 +70,7 @@ void test_poseidon2s_circuit(size_t num_inputs = 5)
7070
for (auto& elem : inputs) {
7171
elem.fix_witness();
7272
}
73-
[[maybe_unused]] auto result = stdlib::poseidon2<Builder>::hash(builder, inputs);
73+
[[maybe_unused]] auto result = stdlib::poseidon2<Builder>::hash(inputs);
7474
auto graph = StaticAnalyzer(builder);
7575
auto connected_components = graph.find_connected_components();
7676
EXPECT_EQ(connected_components.size(), 1);
@@ -104,7 +104,7 @@ void test_poseidon2s_hash_repeated_pairs(size_t num_inputs = 5)
104104
std::unordered_set<uint32_t> outputs{ left.witness_index };
105105
// num_inputs - 1 iterations since the first hash hashes two elements
106106
for (size_t i = 0; i < num_inputs - 1; ++i) {
107-
left = stdlib::poseidon2<Builder>::hash(builder, { left, right });
107+
left = stdlib::poseidon2<Builder>::hash({ left, right });
108108
outputs.insert(left.witness_index + 1);
109109
outputs.insert(left.witness_index + 2);
110110
outputs.insert(left.witness_index + 3);

barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,13 @@ void process_ROM_operations(Builder& builder,
118118
// For a ROM table, constant read should be optimized out:
119119
// The rom_table won't work with a constant read because the table may not be initialized
120120
ASSERT(op.index.q_l != 0);
121-
// We create a new witness w to avoid issues with non-valid witness assignements:
122-
// if witness are not assigned, then w will be zero and table[w] will work
123-
fr w_value = 0;
124-
if (has_valid_witness_assignments) {
125-
// If witness are assigned, we use the correct value for w
126-
w_value = index.get_value();
121+
122+
// In case of invalid witness assignment, we set the value of index value to zero to not hit out of bound in
123+
// ROM table
124+
if (!has_valid_witness_assignments) {
125+
builder.set_variable(index.witness_index, 0);
127126
}
128-
field_ct w = field_ct::from_witness(&builder, w_value);
129-
value.assert_equal(table[w]);
130-
w.assert_equal(index);
127+
value.assert_equal(table[index]);
131128
}
132129
}
133130

@@ -144,12 +141,11 @@ void process_RAM_operations(Builder& builder,
144141
for (auto& op : constraint.trace) {
145142
field_ct value = poly_to_field_ct(op.value, builder);
146143
field_ct index = poly_to_field_ct(op.index, builder);
147-
148-
// We create a new witness w to avoid issues with non-valid witness assignements.
149-
// If witness are not assigned, then index will be zero and table[index] won't hit bounds check.
150-
fr index_value = has_valid_witness_assignments ? index.get_value() : 0;
151-
// Create new witness and ensure equal to index.
152-
field_ct::from_witness(&builder, index_value).assert_equal(index);
144+
// In case of invalid witness assignment, we set the value of index value to zero to not hit out of bound in
145+
// RAM table
146+
if (!has_valid_witness_assignments) {
147+
builder.set_variable(index.witness_index, 0);
148+
}
153149

154150
if (op.access_type == 0) {
155151
value.assert_equal(table.read(index));
@@ -179,14 +175,12 @@ void process_call_data_operations(Builder& builder,
179175
BB_ASSERT_EQ(op.access_type, 0);
180176
field_ct value = poly_to_field_ct(op.value, builder);
181177
field_ct index = poly_to_field_ct(op.index, builder);
182-
fr w_value = 0;
183-
if (has_valid_witness_assignments) {
184-
// If witness are assigned, we use the correct value for w
185-
w_value = index.get_value();
178+
// In case of invalid witness assignment, we set the value of index value to zero to not hit out of bound in
179+
// calldata-array
180+
if (!has_valid_witness_assignments) {
181+
builder.set_variable(index.witness_index, 0);
186182
}
187-
field_ct w = field_ct::from_witness(&builder, w_value);
188-
value.assert_equal(calldata_array[w]);
189-
w.assert_equal(index);
183+
value.assert_equal(calldata_array[index]);
190184
}
191185
};
192186

barretenberg/cpp/src/barretenberg/dsl/acir_format/poseidon2_constraint.cpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ using namespace bb;
1717
template <typename Builder> void create_poseidon2_permutations(Builder& builder, const Poseidon2Constraint& constraint)
1818
{
1919
using field_ct = stdlib::field_t<Builder>;
20-
using Poseidon2Params = crypto::Poseidon2Bn254ScalarFieldParams;
21-
using State = std::array<field_ct, Poseidon2Params::t>;
20+
using State = stdlib::Poseidon2Permutation<Builder>::State;
2221

2322
BB_ASSERT_EQ(constraint.state.size(), 4U);
2423
BB_ASSERT_EQ(constraint.result.size(), 4U);
@@ -29,19 +28,9 @@ template <typename Builder> void create_poseidon2_permutations(Builder& builder,
2928
state[i] = to_field_ct(constraint.state[i], builder);
3029
}
3130
State output_state;
32-
output_state = stdlib::Poseidon2Permutation<Poseidon2Params, Builder>::permutation(&builder, state);
31+
output_state = stdlib::Poseidon2Permutation<Builder>::permutation(&builder, state);
3332
for (size_t i = 0; i < output_state.size(); ++i) {
34-
poly_triple assert_equal{
35-
.a = output_state[i].normalize().witness_index,
36-
.b = constraint.result[i],
37-
.c = 0,
38-
.q_m = 0,
39-
.q_l = 1,
40-
.q_r = -1,
41-
.q_o = 0,
42-
.q_c = 0,
43-
};
44-
builder.create_poly_gate(assert_equal);
33+
output_state[i].assert_equal(field_ct::from_witness_index(&builder, constraint.result[i]));
4534
}
4635
}
4736

barretenberg/cpp/src/barretenberg/flavor/flavor.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,9 @@ class StdlibVerificationKey_ : public PrecomputedCommitments {
356356
* @param builder
357357
* @return FF
358358
*/
359-
FF hash(Builder& builder)
359+
FF hash()
360360
{
361-
FF vk_hash = stdlib::poseidon2<Builder>::hash(builder, to_field_elements());
361+
FF vk_hash = stdlib::poseidon2<Builder>::hash(to_field_elements());
362362
return vk_hash;
363363
}
364364

barretenberg/cpp/src/barretenberg/flavor/stdlib_verification_key.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ TYPED_TEST(StdlibVerificationKeyTests, VKHashingConsistency)
7979
}
8080
FF vk_hash_1 = transcript.hash_independent_buffer();
8181
// Second method of hashing: using hash().
82-
FF vk_hash_2 = vk.hash(outer_builder);
82+
FF vk_hash_2 = vk.hash();
8383
EXPECT_EQ(vk_hash_1.get_value(), vk_hash_2.get_value());
8484
// Third method of hashing: using hash_through_transcript.
8585
if constexpr (!IsAnyOf<Flavor, TranslatorRecursiveFlavor, ECCVMRecursiveFlavor>) {

barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ template <class Fr, size_t domain_end, size_t domain_start = 0, size_t skip_coun
6969
return result;
7070
}
7171

72+
// Compute Lagrange coefficients of a given linear polynomial represented in monomial basis.
7273
template <bool has_a0_plus_a1> Univariate(UnivariateCoefficientBasis<Fr, 2, has_a0_plus_a1> monomial)
7374
{
7475
static_assert(domain_start == 0);
@@ -86,6 +87,7 @@ template <class Fr, size_t domain_end, size_t domain_start = 0, size_t skip_coun
8687
}
8788
}
8889

90+
// Compute Lagrange coefficients of a given quadratic polynomial represented in monomial basis.
8991
template <bool has_a0_plus_a1> Univariate(UnivariateCoefficientBasis<Fr, 3, has_a0_plus_a1> monomial)
9092
{
9193
static_assert(domain_start == 0);

barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp

Lines changed: 98 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -29,99 +29,134 @@ template <typename FF_> class Poseidon2ExternalRelationImpl {
2929
}
3030

3131
/**
32-
* @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of
32+
* @brief Expression for the poseidon2 external round relation, based on \f$ E_i \f$ in Section 6 of
3333
* https://eprint.iacr.org/2023/323.pdf.
34-
* @details This relation is defined as C(in(X)...) :=
35-
* q_poseidon2_external * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) +
36-
* \alpha^2 * (v3 - w_3_shift) + \alpha^3 * (v4 - w_4_shift) ) = 0 where:
37-
* u1 := (w_1 + q_1)^5
38-
* u2 := (w_2 + q_2)^5
39-
* u3 := (w_3 + q_3)^5
40-
* u4 := (w_4 + q_4)^5
41-
* t0 := u1 + u2 (1, 1, 0, 0)
42-
* t1 := u3 + u4 (0, 0, 1, 1)
43-
* t2 := 2 * u2 + t1 = 2 * u2 + u3 + u4 (0, 2, 1, 1)
44-
* t3 := 2 * u4 + t0 = u1 + u2 + 2 * u4 (1, 1, 0, 2)
45-
* v4 := 4 * t1 + t3 = u1 + u2 + 4 * u3 + 6 * u4 (1, 1, 4, 6)
46-
* v2 := 4 * t0 + t2 = 4 * u1 + 6 * u2 + u3 + u4 (4, 6, 1, 1)
47-
* v1 := t3 + v2 = 5 * u1 + 7 * u2 + 1 * u3 + 3 * u4 (5, 7, 1, 3)
48-
* v3 := t2 + v4 (1, 3, 5, 7)
34+
* @details For state \f$ \mathbf{u} = (u_1, u_2, u_3, u_4)\f$ with \f$ u_i = \big(w_i + c_i^{(i)}\big)^5 \f$, the
35+
* external round computes \f$ \mathbf{v} = M_E \cdot \mathbf{u}^{\top}\f$, where \f$M_E\f$ is the external round
36+
* matrix defined as follows:
37+
*
38+
* \f[
39+
* M_E =
40+
* \begin{bmatrix}
41+
* 5 & 7 & 1 & 3 \\
42+
* 4 & 6 & 1 & 1 \\
43+
* 1 & 3 & 5 & 7 \\
44+
* 1 & 1 & 4 & 6
45+
* \end{bmatrix}
46+
* \f]
47+
*
48+
* i.e.
49+
* \f{align}{
50+
* v_1 &= 5u_1 + 7u_2 + u_3 + 3u_4 \\
51+
* v_2 &= 4u_1 + 6u_2 + u_3 + u_4 \\
52+
* v_3 &= u_1 + 3u_2 + 5u_3 + 7u_4 \\
53+
* v_4 &= u_1 + u_2 + 4u_3 + 6u_4
54+
* \f}
55+
*
56+
* The relation enforces \f$ v_k = w_{k,shift}\f$ for \f$ k \in \{1,2,3,4\}\f$.
57+
* Concretely, the relation is encoded as four independent constraints multiplied by the
58+
* \f$\text{q_poseidon2_external}\f$ selector and the scaling factor \f$\hat{g}\f$ arising from the
59+
* `GateSeparatorPolynomial`. These contributions are added to the corresponding univariate accumulator \f$ A_i
60+
* \f$:
61+
* \f{align}{
62+
* A_1 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_1 - w_{1,\text{shift}}\big) \cdot \hat{g} \\
63+
* A_2 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_1 - w_{1,\text{shift}}\big) \cdot \hat{g} \\
64+
* A_3 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_3 - w_{3,\text{shift}}\big) \cdot \hat{g} \\
65+
* A_4 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_4 - w_{4,\text{shift}}\big) \cdot \hat{g}
66+
* \f}
67+
* At the end of each Sumcheck Round, the subrelation accumulators are aggregated with independent challenges
68+
* \f$\alpha_{i} = \alpha_{i, \text{Poseidon2Ext}}\f$ taken from the array of `SubrelationSeparators`
69+
* \f[
70+
* \alpha_{0} A_1 +
71+
* \alpha_{1} A_2 +
72+
* \alpha_{2} A_3 +
73+
* \alpha_{3} A_4
74+
* \f]
75+
* and multiplied by the linear factor of the `GateSeparatorPolynomial`.
76+
*
77+
* @param evals a tuple of tuples of univariate accumulators, the subtuple corresponding to this relation consists
78+
* of \f$ [A_0, A_1, A_2, A_3]\f$ , such that
79+
* \f$ \deg(A_i) = \text{SUBRELATION_PARTIAL_LENGTHS}[i] - 1 \f$.
80+
* @param in In round \f$ k \f$ of Sumcheck at the point \f$i_{>k} = (i_{k+1}, \ldots, i_{d-1})\f$ on the
81+
* \f$d-k-1\f$-dimensional hypercube, given by an array containing the restrictions of the prover polynomials
82+
* \f$ P_i(u_{<k}, X_k, i_{>k}) \f$.
83+
* @param parameters Not used in this relation
84+
* @param scaling_factor scaling term coming from `GateSeparatorPolynomial`.
4985
*
50-
* @param evals transformed to `evals + C(in(X)...)*scaling_factor`
51-
* @param in an std::array containing the fully extended Univariate edges.
52-
* @param parameters contains beta, gamma, and public_input_delta, ....
53-
* @param scaling_factor optional term to scale the evaluation before adding to evals.
5486
*/
5587
template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
5688
void static accumulate(ContainerOverSubrelations& evals,
5789
const AllEntities& in,
5890
const Parameters&,
5991
const FF& scaling_factor)
6092
{
93+
// Univariates of degree 6 represented in Lagrange basis
6194
using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>;
95+
// Low-degree univariates represented in monomial basis
6296
using CoefficientAccumulator = typename Accumulator::CoefficientAccumulator;
63-
auto w_l = CoefficientAccumulator(in.w_l);
64-
auto w_r = CoefficientAccumulator(in.w_r);
65-
auto w_o = CoefficientAccumulator(in.w_o);
66-
auto w_4 = CoefficientAccumulator(in.w_4);
67-
auto w_l_shift = CoefficientAccumulator(in.w_l_shift);
68-
auto w_r_shift = CoefficientAccumulator(in.w_r_shift);
69-
auto w_o_shift = CoefficientAccumulator(in.w_o_shift);
70-
auto w_4_shift = CoefficientAccumulator(in.w_4_shift);
71-
auto q_l = CoefficientAccumulator(in.q_l);
72-
auto q_r = CoefficientAccumulator(in.q_r);
73-
auto q_o = CoefficientAccumulator(in.q_o);
74-
auto q_4 = CoefficientAccumulator(in.q_4);
75-
auto q_poseidon2_external = CoefficientAccumulator(in.q_poseidon2_external);
97+
98+
// Current state
99+
const auto w_1 = CoefficientAccumulator(in.w_l);
100+
const auto w_2 = CoefficientAccumulator(in.w_r);
101+
const auto w_3 = CoefficientAccumulator(in.w_o);
102+
const auto w_4 = CoefficientAccumulator(in.w_4);
103+
// Expected state, contained in the next row
104+
const auto w_1_shift = CoefficientAccumulator(in.w_l_shift);
105+
const auto w_2_shift = CoefficientAccumulator(in.w_r_shift);
106+
const auto w_3_shift = CoefficientAccumulator(in.w_o_shift);
107+
const auto w_4_shift = CoefficientAccumulator(in.w_4_shift);
108+
// i-th external round constants
109+
const auto c_1 = CoefficientAccumulator(in.q_l);
110+
const auto c_2 = CoefficientAccumulator(in.q_r);
111+
const auto c_3 = CoefficientAccumulator(in.q_o);
112+
const auto c_4 = CoefficientAccumulator(in.q_4);
113+
// Poseidon2 external relation selector
114+
const auto q_poseidon2_external = CoefficientAccumulator(in.q_poseidon2_external);
76115

77116
// add round constants which are loaded in selectors
78-
auto s1 = Accumulator(w_l + q_l);
79-
auto s2 = Accumulator(w_r + q_r);
80-
auto s3 = Accumulator(w_o + q_o);
81-
auto s4 = Accumulator(w_4 + q_4);
82117

118+
auto sbox = [](const Accumulator& x) {
119+
auto t2 = x.sqr(); // x^2
120+
auto t4 = t2.sqr(); // x^4
121+
return t4 * x; // x^5
122+
};
83123
// apply s-box round
84-
auto u1 = s1.sqr();
85-
u1 = u1.sqr();
86-
u1 *= s1;
87-
auto u2 = s2.sqr();
88-
u2 = u2.sqr();
89-
u2 *= s2;
90-
auto u3 = s3.sqr();
91-
u3 = u3.sqr();
92-
u3 *= s3;
93-
auto u4 = s4.sqr();
94-
u4 = u4.sqr();
95-
u4 *= s4;
96-
97-
// matrix mul v = M_E * u with 14 additions
124+
auto u1 = sbox(Accumulator(w_1 + c_1));
125+
auto u2 = sbox(Accumulator(w_2 + c_2));
126+
auto u3 = sbox(Accumulator(w_3 + c_3));
127+
auto u4 = sbox(Accumulator(w_4 + c_4));
128+
// Matrix mul v = M_E * u with 14 additions.
129+
// Precompute common summands.
98130
auto t0 = u1 + u2; // u_1 + u_2
99131
auto t1 = u3 + u4; // u_3 + u_4
100132
auto t2 = u2 + u2; // 2u_2
101133
t2 += t1; // 2u_2 + u_3 + u_4
102134
auto t3 = u4 + u4; // 2u_4
103135
t3 += t0; // u_1 + u_2 + 2u_4
136+
137+
// Row 4: u_1 + u_2 + 4u_3 + 6u_4
104138
auto v4 = t1 + t1;
105139
v4 += v4;
106-
v4 += t3; // u_1 + u_2 + 4u_3 + 6u_4
140+
v4 += t3;
141+
142+
// Row 2: 4u_1 + 6u_2 + u_3 + u_4
107143
auto v2 = t0 + t0;
108144
v2 += v2;
109-
v2 += t2; // 4u_1 + 6u_2 + u_3 + u_4
110-
auto v1 = t3 + v2; // 5u_1 + 7u_2 + u_3 + 3u_4
111-
auto v3 = t2 + v4; // u_1 + 3u_2 + 5u_3 + 7u_4
145+
v2 += t2;
146+
// Row 1: 5u_1 + 7u_2 + u_3 + 3u_4
147+
auto v1 = t3 + v2;
148+
149+
// Row 3: u_1 + 3u_2 + 5u_3 + 7u_4
150+
auto v3 = t2 + v4;
112151

113152
auto q_pos_by_scaling = Accumulator(q_poseidon2_external * scaling_factor);
114-
auto tmp = q_pos_by_scaling * (v1 - Accumulator(w_l_shift));
115-
std::get<0>(evals) += tmp;
153+
std::get<0>(evals) += q_pos_by_scaling * (v1 - Accumulator(w_1_shift));
116154

117-
tmp = q_pos_by_scaling * (v2 - Accumulator(w_r_shift));
118-
std::get<1>(evals) += tmp;
155+
std::get<1>(evals) += q_pos_by_scaling * (v2 - Accumulator(w_2_shift));
119156

120-
tmp = q_pos_by_scaling * (v3 - Accumulator(w_o_shift));
121-
std::get<2>(evals) += tmp;
157+
std::get<2>(evals) += q_pos_by_scaling * (v3 - Accumulator(w_3_shift));
122158

123-
tmp = q_pos_by_scaling * (v4 - Accumulator(w_4_shift));
124-
std::get<3>(evals) += tmp;
159+
std::get<3>(evals) += q_pos_by_scaling * (v4 - Accumulator(w_4_shift));
125160
};
126161
};
127162

0 commit comments

Comments
 (0)