Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cd ..
# - 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
# Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0

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

function compress_and_upload {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ auto& engine = numeric::get_debug_randomness();

using Params = crypto::Poseidon2Bn254ScalarFieldParams;
using Builder = UltraCircuitBuilder;
using Permutation = stdlib::Poseidon2Permutation<Params, Builder>;
using Permutation = stdlib::Poseidon2Permutation<Builder>;
using field_t = stdlib::field_t<Builder>;
using witness_t = stdlib::witness_t<Builder>;
using _curve = stdlib::bn254<Builder>;
Expand Down Expand Up @@ -70,7 +70,7 @@ void test_poseidon2s_circuit(size_t num_inputs = 5)
for (auto& elem : inputs) {
elem.fix_witness();
}
[[maybe_unused]] auto result = stdlib::poseidon2<Builder>::hash(builder, inputs);
[[maybe_unused]] auto result = stdlib::poseidon2<Builder>::hash(inputs);
auto graph = StaticAnalyzer(builder);
auto connected_components = graph.find_connected_components();
EXPECT_EQ(connected_components.size(), 1);
Expand Down Expand Up @@ -104,7 +104,7 @@ void test_poseidon2s_hash_repeated_pairs(size_t num_inputs = 5)
std::unordered_set<uint32_t> outputs{ left.witness_index };
// num_inputs - 1 iterations since the first hash hashes two elements
for (size_t i = 0; i < num_inputs - 1; ++i) {
left = stdlib::poseidon2<Builder>::hash(builder, { left, right });
left = stdlib::poseidon2<Builder>::hash({ left, right });
outputs.insert(left.witness_index + 1);
outputs.insert(left.witness_index + 2);
outputs.insert(left.witness_index + 3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,13 @@ void process_ROM_operations(Builder& builder,
// For a ROM table, constant read should be optimized out:
// The rom_table won't work with a constant read because the table may not be initialized
ASSERT(op.index.q_l != 0);
// We create a new witness w to avoid issues with non-valid witness assignements:
// if witness are not assigned, then w will be zero and table[w] will work
fr w_value = 0;
if (has_valid_witness_assignments) {
// If witness are assigned, we use the correct value for w
w_value = index.get_value();

// In case of invalid witness assignment, we set the value of index value to zero to not hit out of bound in
// ROM table
if (!has_valid_witness_assignments) {
builder.set_variable(index.witness_index, 0);
}
field_ct w = field_ct::from_witness(&builder, w_value);
value.assert_equal(table[w]);
w.assert_equal(index);
value.assert_equal(table[index]);
}
}

Expand All @@ -144,12 +141,11 @@ void process_RAM_operations(Builder& builder,
for (auto& op : constraint.trace) {
field_ct value = poly_to_field_ct(op.value, builder);
field_ct index = poly_to_field_ct(op.index, builder);

// We create a new witness w to avoid issues with non-valid witness assignements.
// If witness are not assigned, then index will be zero and table[index] won't hit bounds check.
fr index_value = has_valid_witness_assignments ? index.get_value() : 0;
// Create new witness and ensure equal to index.
field_ct::from_witness(&builder, index_value).assert_equal(index);
// In case of invalid witness assignment, we set the value of index value to zero to not hit out of bound in
// RAM table
if (!has_valid_witness_assignments) {
builder.set_variable(index.witness_index, 0);
}

if (op.access_type == 0) {
value.assert_equal(table.read(index));
Expand Down Expand Up @@ -179,14 +175,12 @@ void process_call_data_operations(Builder& builder,
BB_ASSERT_EQ(op.access_type, 0);
field_ct value = poly_to_field_ct(op.value, builder);
field_ct index = poly_to_field_ct(op.index, builder);
fr w_value = 0;
if (has_valid_witness_assignments) {
// If witness are assigned, we use the correct value for w
w_value = index.get_value();
// In case of invalid witness assignment, we set the value of index value to zero to not hit out of bound in
// calldata-array
if (!has_valid_witness_assignments) {
builder.set_variable(index.witness_index, 0);
}
field_ct w = field_ct::from_witness(&builder, w_value);
value.assert_equal(calldata_array[w]);
w.assert_equal(index);
value.assert_equal(calldata_array[index]);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ using namespace bb;
template <typename Builder> void create_poseidon2_permutations(Builder& builder, const Poseidon2Constraint& constraint)
{
using field_ct = stdlib::field_t<Builder>;
using Poseidon2Params = crypto::Poseidon2Bn254ScalarFieldParams;
using State = std::array<field_ct, Poseidon2Params::t>;
using State = stdlib::Poseidon2Permutation<Builder>::State;

BB_ASSERT_EQ(constraint.state.size(), 4U);
BB_ASSERT_EQ(constraint.result.size(), 4U);
Expand All @@ -29,19 +28,9 @@ template <typename Builder> void create_poseidon2_permutations(Builder& builder,
state[i] = to_field_ct(constraint.state[i], builder);
}
State output_state;
output_state = stdlib::Poseidon2Permutation<Poseidon2Params, Builder>::permutation(&builder, state);
output_state = stdlib::Poseidon2Permutation<Builder>::permutation(&builder, state);
for (size_t i = 0; i < output_state.size(); ++i) {
poly_triple assert_equal{
.a = output_state[i].normalize().witness_index,
.b = constraint.result[i],
.c = 0,
.q_m = 0,
.q_l = 1,
.q_r = -1,
.q_o = 0,
.q_c = 0,
};
builder.create_poly_gate(assert_equal);
output_state[i].assert_equal(field_ct::from_witness_index(&builder, constraint.result[i]));
}
}

Expand Down
4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/flavor/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,9 @@ class StdlibVerificationKey_ : public PrecomputedCommitments {
* @param builder
* @return FF
*/
FF hash(Builder& builder)
FF hash()
{
FF vk_hash = stdlib::poseidon2<Builder>::hash(builder, to_field_elements());
FF vk_hash = stdlib::poseidon2<Builder>::hash(to_field_elements());
return vk_hash;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ TYPED_TEST(StdlibVerificationKeyTests, VKHashingConsistency)
}
FF vk_hash_1 = transcript.hash_independent_buffer();
// Second method of hashing: using hash().
FF vk_hash_2 = vk.hash(outer_builder);
FF vk_hash_2 = vk.hash();
EXPECT_EQ(vk_hash_1.get_value(), vk_hash_2.get_value());
// Third method of hashing: using hash_through_transcript.
if constexpr (!IsAnyOf<Flavor, TranslatorRecursiveFlavor, ECCVMRecursiveFlavor>) {
Expand Down
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ template <class Fr, size_t domain_end, size_t domain_start = 0, size_t skip_coun
return result;
}

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

// Compute Lagrange coefficients of a given quadratic polynomial represented in monomial basis.
template <bool has_a0_plus_a1> Univariate(UnivariateCoefficientBasis<Fr, 3, has_a0_plus_a1> monomial)
{
static_assert(domain_start == 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,99 +29,134 @@ template <typename FF_> class Poseidon2ExternalRelationImpl {
}

/**
* @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of
* @brief Expression for the poseidon2 external round relation, based on \f$ E_i \f$ in Section 6 of
* https://eprint.iacr.org/2023/323.pdf.
* @details This relation is defined as C(in(X)...) :=
* q_poseidon2_external * ( (v1 - w_1_shift) + \alpha * (v2 - w_2_shift) +
* \alpha^2 * (v3 - w_3_shift) + \alpha^3 * (v4 - w_4_shift) ) = 0 where:
* u1 := (w_1 + q_1)^5
* u2 := (w_2 + q_2)^5
* u3 := (w_3 + q_3)^5
* u4 := (w_4 + q_4)^5
* t0 := u1 + u2 (1, 1, 0, 0)
* t1 := u3 + u4 (0, 0, 1, 1)
* t2 := 2 * u2 + t1 = 2 * u2 + u3 + u4 (0, 2, 1, 1)
* t3 := 2 * u4 + t0 = u1 + u2 + 2 * u4 (1, 1, 0, 2)
* v4 := 4 * t1 + t3 = u1 + u2 + 4 * u3 + 6 * u4 (1, 1, 4, 6)
* v2 := 4 * t0 + t2 = 4 * u1 + 6 * u2 + u3 + u4 (4, 6, 1, 1)
* v1 := t3 + v2 = 5 * u1 + 7 * u2 + 1 * u3 + 3 * u4 (5, 7, 1, 3)
* v3 := t2 + v4 (1, 3, 5, 7)
* @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
* external round computes \f$ \mathbf{v} = M_E \cdot \mathbf{u}^{\top}\f$, where \f$M_E\f$ is the external round
* matrix defined as follows:
*
* \f[
* M_E =
* \begin{bmatrix}
* 5 & 7 & 1 & 3 \\
* 4 & 6 & 1 & 1 \\
* 1 & 3 & 5 & 7 \\
* 1 & 1 & 4 & 6
* \end{bmatrix}
* \f]
*
* i.e.
* \f{align}{
* v_1 &= 5u_1 + 7u_2 + u_3 + 3u_4 \\
* v_2 &= 4u_1 + 6u_2 + u_3 + u_4 \\
* v_3 &= u_1 + 3u_2 + 5u_3 + 7u_4 \\
* v_4 &= u_1 + u_2 + 4u_3 + 6u_4
* \f}
*
* The relation enforces \f$ v_k = w_{k,shift}\f$ for \f$ k \in \{1,2,3,4\}\f$.
* Concretely, the relation is encoded as four independent constraints multiplied by the
* \f$\text{q_poseidon2_external}\f$ selector and the scaling factor \f$\hat{g}\f$ arising from the
* `GateSeparatorPolynomial`. These contributions are added to the corresponding univariate accumulator \f$ A_i
* \f$:
* \f{align}{
* A_1 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_1 - w_{1,\text{shift}}\big) \cdot \hat{g} \\
* A_2 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_1 - w_{1,\text{shift}}\big) \cdot \hat{g} \\
* A_3 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_3 - w_{3,\text{shift}}\big) \cdot \hat{g} \\
* A_4 &\;\mathrel{+}= \text{q_poseidon2_internal}\cdot \big(v_4 - w_{4,\text{shift}}\big) \cdot \hat{g}
* \f}
* At the end of each Sumcheck Round, the subrelation accumulators are aggregated with independent challenges
* \f$\alpha_{i} = \alpha_{i, \text{Poseidon2Ext}}\f$ taken from the array of `SubrelationSeparators`
* \f[
* \alpha_{0} A_1 +
* \alpha_{1} A_2 +
* \alpha_{2} A_3 +
* \alpha_{3} A_4
* \f]
* and multiplied by the linear factor of the `GateSeparatorPolynomial`.
*
* @param evals a tuple of tuples of univariate accumulators, the subtuple corresponding to this relation consists
* of \f$ [A_0, A_1, A_2, A_3]\f$ , such that
* \f$ \deg(A_i) = \text{SUBRELATION_PARTIAL_LENGTHS}[i] - 1 \f$.
* @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
* \f$d-k-1\f$-dimensional hypercube, given by an array containing the restrictions of the prover polynomials
* \f$ P_i(u_{<k}, X_k, i_{>k}) \f$.
* @param parameters Not used in this relation
* @param scaling_factor scaling term coming from `GateSeparatorPolynomial`.
*
* @param evals transformed to `evals + C(in(X)...)*scaling_factor`
* @param in an std::array containing the fully extended Univariate edges.
* @param parameters contains beta, gamma, and public_input_delta, ....
* @param scaling_factor optional term to scale the evaluation before adding to evals.
*/
template <typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
void static accumulate(ContainerOverSubrelations& evals,
const AllEntities& in,
const Parameters&,
const FF& scaling_factor)
{
// Univariates of degree 6 represented in Lagrange basis
using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>;
// Low-degree univariates represented in monomial basis
using CoefficientAccumulator = typename Accumulator::CoefficientAccumulator;
auto w_l = CoefficientAccumulator(in.w_l);
auto w_r = CoefficientAccumulator(in.w_r);
auto w_o = CoefficientAccumulator(in.w_o);
auto w_4 = CoefficientAccumulator(in.w_4);
auto w_l_shift = CoefficientAccumulator(in.w_l_shift);
auto w_r_shift = CoefficientAccumulator(in.w_r_shift);
auto w_o_shift = CoefficientAccumulator(in.w_o_shift);
auto w_4_shift = CoefficientAccumulator(in.w_4_shift);
auto q_l = CoefficientAccumulator(in.q_l);
auto q_r = CoefficientAccumulator(in.q_r);
auto q_o = CoefficientAccumulator(in.q_o);
auto q_4 = CoefficientAccumulator(in.q_4);
auto q_poseidon2_external = CoefficientAccumulator(in.q_poseidon2_external);

// Current state
const auto w_1 = CoefficientAccumulator(in.w_l);
const auto w_2 = CoefficientAccumulator(in.w_r);
const auto w_3 = CoefficientAccumulator(in.w_o);
const auto w_4 = CoefficientAccumulator(in.w_4);
// Expected state, contained in the next row
const auto w_1_shift = CoefficientAccumulator(in.w_l_shift);
const auto w_2_shift = CoefficientAccumulator(in.w_r_shift);
const auto w_3_shift = CoefficientAccumulator(in.w_o_shift);
const auto w_4_shift = CoefficientAccumulator(in.w_4_shift);
// i-th external round constants
const auto c_1 = CoefficientAccumulator(in.q_l);
const auto c_2 = CoefficientAccumulator(in.q_r);
const auto c_3 = CoefficientAccumulator(in.q_o);
const auto c_4 = CoefficientAccumulator(in.q_4);
// Poseidon2 external relation selector
const auto q_poseidon2_external = CoefficientAccumulator(in.q_poseidon2_external);

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

auto sbox = [](const Accumulator& x) {
auto t2 = x.sqr(); // x^2
auto t4 = t2.sqr(); // x^4
return t4 * x; // x^5
};
// apply s-box round
auto u1 = s1.sqr();
u1 = u1.sqr();
u1 *= s1;
auto u2 = s2.sqr();
u2 = u2.sqr();
u2 *= s2;
auto u3 = s3.sqr();
u3 = u3.sqr();
u3 *= s3;
auto u4 = s4.sqr();
u4 = u4.sqr();
u4 *= s4;

// matrix mul v = M_E * u with 14 additions
auto u1 = sbox(Accumulator(w_1 + c_1));
auto u2 = sbox(Accumulator(w_2 + c_2));
auto u3 = sbox(Accumulator(w_3 + c_3));
auto u4 = sbox(Accumulator(w_4 + c_4));
// Matrix mul v = M_E * u with 14 additions.
// Precompute common summands.
auto t0 = u1 + u2; // u_1 + u_2
auto t1 = u3 + u4; // u_3 + u_4
auto t2 = u2 + u2; // 2u_2
t2 += t1; // 2u_2 + u_3 + u_4
auto t3 = u4 + u4; // 2u_4
t3 += t0; // u_1 + u_2 + 2u_4

// Row 4: u_1 + u_2 + 4u_3 + 6u_4
auto v4 = t1 + t1;
v4 += v4;
v4 += t3; // u_1 + u_2 + 4u_3 + 6u_4
v4 += t3;

// Row 2: 4u_1 + 6u_2 + u_3 + u_4
auto v2 = t0 + t0;
v2 += v2;
v2 += t2; // 4u_1 + 6u_2 + u_3 + u_4
auto v1 = t3 + v2; // 5u_1 + 7u_2 + u_3 + 3u_4
auto v3 = t2 + v4; // u_1 + 3u_2 + 5u_3 + 7u_4
v2 += t2;
// Row 1: 5u_1 + 7u_2 + u_3 + 3u_4
auto v1 = t3 + v2;

// Row 3: u_1 + 3u_2 + 5u_3 + 7u_4
auto v3 = t2 + v4;

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

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

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

tmp = q_pos_by_scaling * (v4 - Accumulator(w_4_shift));
std::get<3>(evals) += tmp;
std::get<3>(evals) += q_pos_by_scaling * (v4 - Accumulator(w_4_shift));
};
};

Expand Down
Loading
Loading