Skip to content

Commit 062ed4e

Browse files
authored
chore: assert poseidon hashes only witnesses (#16341)
Closes AztecProtocol/barretenberg#1413. Adds assert to sponge that ensures we only hash witnesses. Removes unused hash_buffer functions from poseidon2.
1 parent 70fc9a2 commit 062ed4e

7 files changed

Lines changed: 4 additions & 164 deletions

File tree

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

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -83,37 +83,6 @@ void test_poseidon2s_circuit(size_t num_inputs = 5)
8383
}
8484
}
8585

86-
/**
87-
* @brief Test graph description for poseidon2 hash with byte array input
88-
*
89-
* The result should be one connected component, and only output variables must be in one gate
90-
*
91-
* @param num_inputs Number of random bytes to generate
92-
*/
93-
void test_poseidon2s_hash_byte_array(size_t num_inputs = 5)
94-
{
95-
Builder builder;
96-
97-
std::vector<uint8_t> input;
98-
input.reserve(num_inputs);
99-
for (size_t i = 0; i < num_inputs; ++i) {
100-
input.push_back(engine.get_random_uint8());
101-
}
102-
103-
byte_array_ct circuit_input(&builder, input);
104-
auto result = stdlib::poseidon2<Builder>::hash_buffer(builder, circuit_input);
105-
auto graph = StaticAnalyzer(builder);
106-
auto connected_components = graph.find_connected_components();
107-
EXPECT_EQ(connected_components.size(), 1);
108-
auto variables_in_one_gate = graph.show_variables_in_one_gate(builder);
109-
std::unordered_set<uint32_t> outputs{
110-
result.witness_index, result.witness_index + 1, result.witness_index + 2, result.witness_index + 3
111-
};
112-
for (const auto& elem : variables_in_one_gate) {
113-
EXPECT_EQ(outputs.contains(elem), true);
114-
}
115-
}
116-
11786
/**
11887
* @brief Test graph description for repeated poseidon2 hash operations
11988
*
@@ -234,16 +203,6 @@ TEST(boomerang_poseidon2s, test_graph_for_poseidon2s_for_one_input_size)
234203
test_poseidon2s_circuit();
235204
}
236205

237-
/**
238-
* @brief Test graph for poseidon2s hash with byte arrays of varying sizes
239-
*/
240-
TEST(boomerang_poseidon2s, test_graph_for_poseidon2s_hash_byte_array)
241-
{
242-
for (size_t num_inputs = 6; num_inputs < 100; num_inputs++) {
243-
test_poseidon2s_hash_byte_array(num_inputs);
244-
}
245-
}
246-
247206
/**
248207
* @brief Test graph for poseidon2s with repeated hash operations
249208
*/

barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.cpp

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,5 @@ typename Poseidon2<Params>::FF Poseidon2<Params>::hash(const std::vector<typenam
1616
return Sponge::hash_internal(input);
1717
}
1818

19-
/**
20-
* @brief Hashes vector of bytes by chunking it into 31 byte field elements and calling hash()
21-
* @details Slice function cuts out the required number of bytes from the byte vector
22-
*/
23-
template <typename Params>
24-
typename Poseidon2<Params>::FF Poseidon2<Params>::hash_buffer(const std::vector<uint8_t>& input)
25-
{
26-
const size_t num_bytes = input.size();
27-
const size_t bytes_per_element = 31;
28-
size_t num_elements = static_cast<size_t>(num_bytes % bytes_per_element != 0) + (num_bytes / bytes_per_element);
29-
30-
const auto slice = [](const std::vector<uint8_t>& data, const size_t start, const size_t slice_size) {
31-
uint256_t result(0);
32-
for (size_t i = 0; i < slice_size; ++i) {
33-
result = (result << uint256_t(8));
34-
result += uint256_t(data[i + start]);
35-
}
36-
return FF(result);
37-
};
38-
39-
std::vector<FF> converted;
40-
for (size_t i = 0; i < num_elements - 1; ++i) {
41-
size_t bytes_to_slice = bytes_per_element;
42-
FF element = slice(input, i * bytes_per_element, bytes_to_slice);
43-
converted.emplace_back(element);
44-
}
45-
size_t bytes_to_slice = num_bytes - ((num_elements - 1) * bytes_per_element);
46-
FF element = slice(input, (num_elements - 1) * bytes_per_element, bytes_to_slice);
47-
converted.emplace_back(element);
48-
49-
return hash(converted);
50-
}
51-
5219
template class Poseidon2<Poseidon2Bn254ScalarFieldParams>;
5320
} // namespace bb::crypto

barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ template <typename Params> class Poseidon2 {
2323
* @brief Hashes a vector of field elements
2424
*/
2525
static FF hash(const std::vector<FF>& input);
26-
/**
27-
* @brief Hashes vector of bytes by chunking it into 31 byte field elements and calling hash()
28-
* @details Slice function cuts out the required number of bytes from the byte vector
29-
*/
30-
static FF hash_buffer(const std::vector<uint8_t>& input);
3126
};
3227

3328
extern template class Poseidon2<Poseidon2Bn254ScalarFieldParams>;

barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.test.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,3 @@ TEST(Poseidon2, HashConsistencyCheck)
4545

4646
EXPECT_EQ(result, expected);
4747
}
48-
49-
TEST(Poseidon2, HashBufferConsistencyCheck)
50-
{
51-
// 31 byte inputs because hash_buffer slicing is only injective with 31 bytes, as it slices 31 bytes for each field
52-
// element
53-
fr a(std::string("00000b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));
54-
55-
// takes field element and converts it to 32 bytes
56-
auto input_vec = to_buffer(a);
57-
bb::fr result1 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash_buffer(input_vec);
58-
input_vec.erase(input_vec.begin()); // erase first byte since we want 31 bytes
59-
fr result2 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash_buffer(input_vec);
60-
61-
std::vector<fr> input{ a };
62-
auto expected = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(input);
63-
64-
EXPECT_NE(result1, expected);
65-
EXPECT_EQ(result2, expected);
66-
}

barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2.cpp

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,6 @@ template <typename C> field_t<C> poseidon2<C>::hash(C& builder, const std::vecto
2323
return Sponge::hash_internal(builder, inputs);
2424
}
2525

26-
/**
27-
* @brief Hash a byte_array.
28-
*/
29-
template <typename C> field_t<C> poseidon2<C>::hash_buffer(C& builder, const stdlib::byte_array<C>& input)
30-
{
31-
const size_t num_bytes = input.size();
32-
const size_t bytes_per_element = 31; // 31 bytes in a fr element
33-
size_t num_elements = static_cast<size_t>(num_bytes % bytes_per_element != 0) + (num_bytes / bytes_per_element);
34-
35-
std::vector<field_ct> elements;
36-
for (size_t i = 0; i < num_elements; ++i) {
37-
size_t bytes_to_slice = 0;
38-
if (i == num_elements - 1) {
39-
bytes_to_slice = num_bytes - (i * bytes_per_element);
40-
} else {
41-
bytes_to_slice = bytes_per_element;
42-
}
43-
auto element = static_cast<field_ct>(input.slice(i * bytes_per_element, bytes_to_slice));
44-
elements.emplace_back(element);
45-
}
46-
return hash(builder, elements);
47-
}
4826
template class poseidon2<bb::MegaCircuitBuilder>;
4927
template class poseidon2<bb::UltraCircuitBuilder>;
5028

barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2.test.cpp

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -77,33 +77,6 @@ template <typename Builder> class StdlibPoseidon2 : public testing::Test {
7777
bool result = CircuitChecker::check(builder);
7878
EXPECT_EQ(result, true);
7979
}
80-
/**
81-
* @brief Call poseidon2 hash_buffer on a vector of bytes
82-
*
83-
* @param num_input_bytes
84-
*/
85-
static void test_hash_byte_array(size_t num_input_bytes)
86-
{
87-
Builder builder;
88-
89-
std::vector<uint8_t> input;
90-
input.reserve(num_input_bytes);
91-
for (size_t i = 0; i < num_input_bytes; ++i) {
92-
input.push_back(engine.get_random_uint8());
93-
}
94-
95-
fr expected = native_poseidon2::hash_buffer(input);
96-
97-
byte_array_ct circuit_input(&builder, input);
98-
auto result = poseidon2::hash_buffer(builder, circuit_input);
99-
100-
EXPECT_EQ(result.get_value(), expected);
101-
102-
info("num gates = ", builder.get_estimated_num_finalized_gates());
103-
104-
bool proof_result = CircuitChecker::check(builder);
105-
EXPECT_EQ(proof_result, true);
106-
}
10780

10881
static void test_hash_zeros(size_t num_inputs)
10982
{
@@ -140,13 +113,9 @@ template <typename Builder> class StdlibPoseidon2 : public testing::Test {
140113
}
141114
}
142115

143-
fr expected = native_poseidon2::hash(inputs);
144-
auto result = poseidon2::hash(builder, witness_inputs);
145-
146-
EXPECT_EQ(result.get_value(), expected);
147-
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1413): Investigate why this fails. Sees like we
148-
// don't allow poseidon2 to take in constants.
149-
EXPECT_FALSE(CircuitChecker::check(builder));
116+
native_poseidon2::hash(inputs);
117+
EXPECT_THROW_OR_ABORT(poseidon2::hash(builder, witness_inputs),
118+
".*Sponge inputs should not be stdlib constants.*");
150119
}
151120
};
152121

@@ -174,16 +143,6 @@ TYPED_TEST(StdlibPoseidon2, TestHashRepeatedPairs)
174143
TestFixture::test_hash_repeated_pairs(256);
175144
}
176145

177-
TYPED_TEST(StdlibPoseidon2, TestHashByteArraySmall)
178-
{
179-
TestFixture::test_hash_byte_array(351);
180-
};
181-
182-
TYPED_TEST(StdlibPoseidon2, TestHashByteArrayLarge)
183-
{
184-
TestFixture::test_hash_byte_array(31000);
185-
};
186-
187146
TYPED_TEST(StdlibPoseidon2, TestHashConstants)
188147
{
189148
TestFixture::test_hash_constants();

barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/sponge/sponge.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ template <size_t rate, size_t capacity, size_t t, typename Permutation, typename
155155
FieldSponge sponge(builder, iv);
156156

157157
for (size_t i = 0; i < in_len; ++i) {
158+
BB_ASSERT_EQ(input[i].witness_index == IS_CONSTANT, false, "Sponge inputs should not be stdlib constants.");
158159
sponge.absorb(input[i]);
159160
}
160161

0 commit comments

Comments
 (0)