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
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 SubrelationSeparator subrelation_separator = FF::random_element();
87
88 std::vector<FF> gate_challenges(virtual_log_n);
89
90 // Random gate challenges ensure that relations are satisfied at every point of the hypercube
91 for (auto& beta : gate_challenges) {
92 beta = FF::random_element();
93 }
94
95 RelationParameters relation_parameters;
96
97 for (auto& rel_param : relation_parameters.get_to_fold()) {
98 rel_param = FF::random_element();
99 }
100 auto prover_transcript = std::make_shared<Transcript>();
101
102 SumcheckProver sumcheck_prover(prover_instance->dyadic_size(),
103 prover_instance->polynomials,
104 prover_transcript,
105 subrelation_separator,
106 gate_challenges,
107 relation_parameters,
108 virtual_log_n);
109 auto proof = sumcheck_prover.prove();
110
111 auto verifier_transcript = std::make_shared<Transcript>(prover_transcript->export_proof());
112
113 SumcheckVerifier verifier(verifier_transcript, subrelation_separator, virtual_log_n);
114 auto result = verifier.verify(relation_parameters, gate_challenges, std::vector<FF>(virtual_log_n, 1));
115 EXPECT_EQ(result.verified, expected_result);
116 };
117};
118
119TEST_F(Poseidon2FailureTests, WrongSelectorValues)
120{
122
123 // Construct a circuit that hashes a single witness field element.
124 hash_single_input(builder);
125
126 // Convert circuit to polynomials.
127 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
128 {
129 // Disable Poseidon2 External selector in the first active row
130 modify_selector(prover_instance->polynomials.q_poseidon2_external);
131
132 // Run sumcheck on the invalidated data
133 prove_and_verify(prover_instance, false);
134 }
135 {
136 // Disable Poseidon2 Internal selector in the first active row
137 modify_selector(prover_instance->polynomials.q_poseidon2_internal);
138
139 // Run sumcheck on the invalidated data
140 prove_and_verify(prover_instance, false);
141 }
142}
143
144TEST_F(Poseidon2FailureTests, WrongWitnessValues)
145{
147
148 hash_single_input(builder);
149
150 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
151 {
152 modify_witness(prover_instance->polynomials.q_poseidon2_external, prover_instance->polynomials.w_l);
153 prove_and_verify(prover_instance, false);
154 }
155 {
156 modify_witness(prover_instance->polynomials.q_poseidon2_internal, prover_instance->polynomials.w_r);
157 prove_and_verify(prover_instance, false);
158 }
159}
160
161TEST_F(Poseidon2FailureTests, TamperingWithShifts)
162{
164
165 hash_single_input(builder);
166
167 auto prover_instance = std::make_shared<ProverInstance_<Flavor>>(builder);
168 {
169 bool external_round = true;
170 tamper_with_shifts(
171 prover_instance->polynomials.q_poseidon2_external, prover_instance->polynomials.w_l, external_round);
172 prove_and_verify(prover_instance, false);
173 }
174
175 {
176 bool external_round = false;
177 tamper_with_shifts(
178 prover_instance->polynomials.q_poseidon2_internal, prover_instance->polynomials.w_l, external_round);
179 prove_and_verify(prover_instance, false);
180 }
181}
void tamper_with_shifts(const auto &selector, auto &witness, bool external)
void modify_witness(const auto &selector, auto &witness)
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:398
SumcheckOutput< Flavor > verify(const bb::RelationParameters< FF > &relation_parameters, const std::vector< FF > &gate_challenges, const std::vector< FF > &padding_indicator_array)
The Sumcheck verification method. First it extracts round univariate, checks sum (the sumcheck univar...
Definition sumcheck.hpp:844
Derived class that defines proof structure for Ultra proofs, as well as supporting functions.
Curve::ScalarField FF
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:124
bool expected_result
void hash(State &state) noexcept
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
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