Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
poseidon2.circuit.failure.test.cpp
Go to the documentation of this file.
4
5#include <gtest/gtest.h>
6
7using namespace bb;
8
9class Poseidon2FailureTests : public ::testing::Test {
10 public:
15 using FF = Flavor::FF;
20
21 void modify_selector(auto& selector)
22 {
23 size_t start_idx = selector.start_index();
24 size_t end_idx = selector.end_index();
25
26 // Flip the first non-zero selector value.
27 for (size_t idx = start_idx; idx < end_idx; idx++) {
28 if (selector.at(idx) == 1) {
29 selector.at(idx) = 0;
30 break;
31 }
32 }
33 }
34
35 void modify_witness(const auto& selector, auto& witness)
36 {
37 size_t start_idx = selector.start_index();
38 size_t end_idx = selector.end_index();
39
40 size_t selector_enabled_idx{ 0 };
41 // Find the first row index where the selector is enabled.
42 for (size_t idx = start_idx; idx < end_idx; idx++) {
43 if (selector.at(idx) == 1) {
44 selector_enabled_idx = idx;
45 break;
46 }
47 }
48 // Modify the witness
49 witness.at(selector_enabled_idx) += 1;
50 }
51 void tamper_with_shifts(const auto& selector, auto& witness, bool external)
52 {
53 size_t start_idx = selector.start_index();
54 size_t end_idx = selector.end_index();
55
56 size_t selector_enabled_idx{ 0 };
57
58 for (size_t idx = start_idx; idx < end_idx; idx++) {
59 if (selector.at(idx) == 1) {
60 selector_enabled_idx = idx;
61 break;
62 }
63 }
64 const size_t round_size = external ? 4 : 56;
65 size_t shift_idx = selector_enabled_idx + round_size;
66 // The selector must be zero at the row corresponding to the shift.
67 EXPECT_EQ(selector.at(shift_idx), 0);
68 // Modify the witness value. As Poseidon2ExternalRelation is comparing this value to the result of applying the
69 // S-box and M_E to the previous row, this must lead to a sumcheck failure.
70 witness.at(shift_idx) += 1;
71 }
72
74 {
76 random_input.fix_witness();
77 [[maybe_unused]] auto hash = stdlib::poseidon2<Builder>::hash({ random_input });
78 }
79
80 void prove_and_verify(const std::shared_ptr<ProverInstance>& prover_instance, bool expected_result)
81 {
82 const size_t virtual_log_n = Flavor::VIRTUAL_LOG_N;
83
84 // Random subrelation separators are needed here to make sure that the sumcheck is failing because of the wrong
85 // Poseidon2 selector/witness values.
86 SubrelationSeparators subrelation_separators{};
87 for (auto& alpha : subrelation_separators) {
88 alpha = FF::random_element();
89 }
90
91 std::vector<FF> gate_challenges(virtual_log_n);
92
93 // Random gate challenges ensure that relations are satisfied at every point of the hypercube
94 for (auto& beta : gate_challenges) {
95 beta = FF::random_element();
96 }
97
98 RelationParameters relation_parameters;
99
100 for (auto& rel_param : relation_parameters.get_to_fold()) {
101 rel_param = FF::random_element();
102 }
103 auto prover_transcript = std::make_shared<Transcript>();
104
105 SumcheckProver sumcheck_prover(prover_instance->dyadic_size(),
106 prover_instance->polynomials,
107 prover_transcript,
108 subrelation_separators,
109 gate_challenges,
110 relation_parameters,
111 virtual_log_n);
112 auto proof = sumcheck_prover.prove();
113
114 auto verifier_transcript = std::make_shared<Transcript>();
115 verifier_transcript->load_proof(prover_transcript->export_proof());
116
117 SumcheckVerifier verifier(verifier_transcript, subrelation_separators, virtual_log_n);
118 auto result = verifier.verify(relation_parameters, gate_challenges, std::vector<FF>(virtual_log_n, 1));
119 EXPECT_EQ(result.verified, expected_result);
120 };
121};
122
123TEST_F(Poseidon2FailureTests, WrongSelectorValues)
124{
126
127 // Construct a circuit that hashes a single witness field element.
128 hash_single_input(builder);
129
130 // Convert circuit to polynomials.
131 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
132 {
133 // Disable Poseidon2 External selector in the first active row
134 modify_selector(prover_instance->polynomials.q_poseidon2_external);
135
136 // Run sumcheck on the invalidated data
137 prove_and_verify(prover_instance, false);
138 }
139 {
140 // Disable Poseidon2 Internal selector in the first active row
141 modify_selector(prover_instance->polynomials.q_poseidon2_internal);
142
143 // Run sumcheck on the invalidated data
144 prove_and_verify(prover_instance, false);
145 }
146}
147
148TEST_F(Poseidon2FailureTests, WrongWitnessValues)
149{
151
152 hash_single_input(builder);
153
154 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
155 {
156 modify_witness(prover_instance->polynomials.q_poseidon2_external, prover_instance->polynomials.w_l);
157 prove_and_verify(prover_instance, false);
158 }
159 {
160 modify_witness(prover_instance->polynomials.q_poseidon2_internal, prover_instance->polynomials.w_r);
161 prove_and_verify(prover_instance, false);
162 }
163}
164
165TEST_F(Poseidon2FailureTests, TamperingWithShifts)
166{
168
169 hash_single_input(builder);
170
171 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
172 {
173 bool external_round = true;
174 tamper_with_shifts(
175 prover_instance->polynomials.q_poseidon2_external, prover_instance->polynomials.w_l, external_round);
176 prove_and_verify(prover_instance, false);
177 }
178
179 {
180 bool external_round = false;
181 tamper_with_shifts(
182 prover_instance->polynomials.q_poseidon2_internal, prover_instance->polynomials.w_l, external_round);
183 prove_and_verify(prover_instance, false);
184 }
185}
void tamper_with_shifts(const auto &selector, auto &witness, bool external)
void modify_witness(const auto &selector, auto &witness)
Flavor::SubrelationSeparators SubrelationSeparators
void prove_and_verify(const std::shared_ptr< ProverInstance > &prover_instance, bool expected_result)
SumcheckVerifier< Flavor > SumcheckVerifier
SumcheckProver< Flavor > SumcheckProver
A ProverInstance is normally constructed from a finalized circuit and it contains all the information...
SumcheckOutput< Flavor > prove()
Non-ZK version: Compute round univariate, place it in transcript, compute challenge,...
Definition sumcheck.hpp:246
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
Extract round univariate, check sum, generate challenge, compute next target sum.....
Definition sumcheck.hpp:771
Derived class that defines proof structure for Ultra proofs, as well as supporting functions.
Curve::ScalarField FF
std::array< FF, NUM_SUBRELATIONS - 1 > SubrelationSeparators
UltraCircuitBuilder CircuitBuilder
static constexpr size_t VIRTUAL_LOG_N
Transcript_< FrCodec, crypto::Poseidon2< crypto::Poseidon2Bn254ScalarFieldParams > > Transcript
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
AluTraceBuilder builder
Definition alu.test.cpp:123
bool expected_result
void hash(State &state) noexcept
Entry point for Barretenberg command-line interface.
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:188
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
RefArray< T, NUM_TO_FOLD > get_to_fold()
static field random_element(numeric::RNG *engine=nullptr) noexcept