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
15
16namespace bb::crypto {
17
32template <typename FF, size_t rate, size_t capacity, size_t t, typename Permutation> class FieldSponge {
33 public:
41 enum Mode {
44 };
45
46 // sponge state. t = rate + capacity. capacity = 1 field element (~256 bits)
47 std::array<FF, t> state;
48
49 // cached elements that have been absorbed.
50 std::array<FF, rate> cache;
51 size_t cache_size = 0;
53
54 FieldSponge(FF domain_iv = 0)
55 {
56 for (size_t i = 0; i < rate; ++i) {
57 state[i] = 0;
58 }
59 state[rate] = domain_iv;
60 }
61
62 std::array<FF, rate> perform_duplex()
63 {
64 // zero-pad the cache
65 for (size_t i = cache_size; i < rate; ++i) {
66 cache[i] = 0;
67 }
68 // add the cache into sponge state
69 for (size_t i = 0; i < rate; ++i) {
70 state[i] += cache[i];
71 }
73 // return `rate` number of field elements from the sponge state.
74 std::array<FF, rate> output;
75 for (size_t i = 0; i < rate; ++i) {
76 output[i] = state[i];
77 }
78 return output;
79 }
80
81 void absorb(const FF& input)
82 {
83 if (mode == Mode::ABSORB && cache_size == rate) {
84 // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache
86 cache[0] = input;
87 cache_size = 1;
88 } else if (mode == Mode::ABSORB && cache_size < rate) {
89 // If we're absorbing, and the cache is not full, add the input into the cache
90 cache[cache_size] = input;
91 cache_size += 1;
92 } else if (mode == Mode::SQUEEZE) {
93 // If we're in squeeze mode, switch to absorb mode and add the input into the cache.
94 // N.B. I don't think this code path can be reached?!
95 cache[0] = input;
96 cache_size = 1;
98 }
99 }
100
102 {
103 if (mode == Mode::SQUEEZE && cache_size == 0) {
104 // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!
105 // Switch to absorb mode.
107 cache_size = 0;
108 }
109 if (mode == Mode::ABSORB) {
110 // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed
111 // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was
112 // matched
113 auto new_output_elements = perform_duplex();
115 for (size_t i = 0; i < rate; ++i) {
116 cache[i] = new_output_elements[i];
117 }
118 cache_size = rate;
119 }
120 // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.
121 FF result = cache[0];
122 for (size_t i = 1; i < cache_size; ++i) {
123 cache[i - 1] = cache[i];
124 }
125 cache_size -= 1;
126 cache[cache_size] = 0;
127 return result;
128 }
129
137 template <size_t out_len> static std::array<FF, out_len> hash_internal(std::span<const FF> input)
138 {
139 size_t in_len = input.size();
140 const uint256_t iv = (static_cast<uint256_t>(in_len) << 64) + out_len - 1;
141 return hash_internal<out_len>(input, iv);
142 }
143
144 template <size_t out_len> static std::array<FF, out_len> hash_internal(std::span<const FF> input, FF iv)
145 {
146 FieldSponge sponge(iv);
147
148 size_t in_len = input.size();
149 for (size_t i = 0; i < in_len; ++i) {
150 sponge.absorb(input[i]);
151 }
152
154 for (size_t i = 0; i < out_len; ++i) {
155 output[i] = sponge.squeeze();
156 }
157 return output;
158 }
159
160 static FF hash_internal(std::span<const FF> input) { return hash_internal<1>(input)[0]; }
161 static FF hash_internal(std::span<const FF> input, FF iv) { return hash_internal<1>(input, iv)[0]; }
162};
163} // namespace bb::crypto
Implements a cryptographic sponge over prime fields. Implements the sponge specification from the Com...
Definition sponge.hpp:32
FieldSponge(FF domain_iv=0)
Definition sponge.hpp:54
static FF hash_internal(std::span< const FF > input)
Definition sponge.hpp:160
void absorb(const FF &input)
Definition sponge.hpp:81
static std::array< FF, out_len > hash_internal(std::span< const FF > input, FF iv)
Definition sponge.hpp:144
std::array< FF, rate > perform_duplex()
Definition sponge.hpp:62
std::array< FF, rate > cache
Definition sponge.hpp:50
static std::array< FF, out_len > hash_internal(std::span< const FF > input)
Use the sponge to hash an input string.
Definition sponge.hpp:137
std::array< FF, t > state
Definition sponge.hpp:47
static FF hash_internal(std::span< const FF > input, FF iv)
Definition sponge.hpp:161
Mode
Defines what phase of the sponge algorithm we are in.
Definition sponge.hpp:41
static State permutation(Builder *builder, const State &input)
Circuit form of Poseidon2 permutation from https://eprint.iacr.org/2023/323.
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13