Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
sponge.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
9#include <array>
10#include <cstddef>
11#include <cstdint>
12#include <span>
13
16
17namespace bb::stdlib {
18
24template <typename Builder> class FieldSponge {
25 private:
27 static constexpr size_t t = crypto::Poseidon2Bn254ScalarFieldParams::t; // = 4
28 static constexpr size_t capacity = 1;
29 static constexpr size_t rate = t - capacity; // = 3
30
32
33 // sponge state. t = rate + capacity. capacity = 1 field element (~256 bits)
35
36 // cached elements that have been absorbed.
38 size_t cache_size = 0;
40
41 FieldSponge(Builder* builder_, size_t in_len)
42 : builder(builder_)
43 {
44 // Add the domain separation to the initial state.
45 field_t iv(static_cast<uint256_t>(in_len) << 64);
47 state[rate] = iv;
48 }
49
51 {
52 // Add the cache into sponge state
53 for (size_t i = 0; i < rate; ++i) {
54 state[i] += cache[i];
55 }
56
57 // Apply Poseidon2 permutation
59
60 // Reset the cache
61 cache = {};
62 }
63
64 void absorb(const field_t& input)
65 {
66 if (cache_size == rate) {
67 // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache
69 cache[0] = input;
70 cache_size = 1;
71 } else {
72 // If we're absorbing, and the cache is not full, add the input into the cache
73 cache[cache_size] = input;
74 cache_size += 1;
75 }
76 }
77
79 {
80
82
83 return state[0];
84 }
85
86 public:
94 {
95 // Ensure that all inputs belong to the same circuit and extract a pointer to the circuit object.
96 Builder* builder = validate_context<Builder>(input);
97
98 // Ensure that the pointer is not a `nullptr`
100
101 // Initialize the sponge state. Input length is used for domain separation.
102 const size_t in_len = input.size();
103 FieldSponge sponge(builder, in_len);
104
105 // Absorb inputs in blocks of size r = 3. Make sure that all inputs are witneesses.
106 for (size_t i = 0; i < in_len; ++i) {
107 BB_ASSERT_EQ(input[i].is_constant(), false, "Sponge inputs should not be stdlib constants.");
108 sponge.absorb(input[i]);
109 }
110
111 // Perform final duplex call. At this point, cache contains `m = in_len % 3` input elements and 3 - m constant
112 // zeroes served as padding.
113 field_t output = sponge.squeeze();
114
115 // The final state consists of 4 elements, we only use the first element, which means that the remaining
116 // 3 witnesses are only used in a single gate.
117 for (const auto& elem : sponge.state) {
118 builder->update_used_witnesses(elem.witness_index);
119 }
120 return output;
121 }
122};
123} // namespace bb::stdlib
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:88
#define ASSERT(expression,...)
Definition assert.hpp:77
Implements the circuit form of a cryptographic sponge over prime fields.
Definition sponge.hpp:24
static constexpr size_t rate
Definition sponge.hpp:29
FieldSponge(Builder *builder_, size_t in_len)
Definition sponge.hpp:41
std::array< field_t, t > state
Definition sponge.hpp:34
void absorb(const field_t &input)
Definition sponge.hpp:64
static constexpr size_t t
Definition sponge.hpp:27
std::array< field_t, rate > cache
Definition sponge.hpp:37
static field_t hash_internal(std::span< const field_t > input)
Use the sponge to hash an input vector.
Definition sponge.hpp:93
static constexpr size_t capacity
Definition sponge.hpp:28
Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323.
static State permutation(Builder *builder, const State &input)
Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323.
void convert_constant_to_fixed_witness(Builder *ctx)
Definition field.hpp:422
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13