Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
blake3s.cpp
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#include "blake3s.hpp"
10
11namespace bb::stdlib {
12
13using namespace blake_util;
14
15/*
16 * Core Blake3s functions. These are similar to that of Blake2s except for a few
17 * constant parameters and fewer rounds.
18 *
19 */
20template <typename Builder>
22 const field_t<Builder> cv[8],
23 const byte_array<Builder>& block,
24 uint8_t block_len,
25 uint8_t flags)
26{
27 field_ct block_words[BLAKE3_STATE_SIZE];
28 for (size_t i = 0; i < BLAKE3_STATE_SIZE; ++i) {
29 block_words[i] = field_ct(block.slice(i * 4, 4).reverse());
30 }
31
32 state[0] = cv[0];
33 state[1] = cv[1];
34 state[2] = cv[2];
35 state[3] = cv[3];
36 state[4] = cv[4];
37 state[5] = cv[5];
38 state[6] = cv[6];
39 state[7] = cv[7];
40 state[8] = field_ct(block.get_context(), uint256_t(IV[0]));
41 state[9] = field_ct(block.get_context(), uint256_t(IV[1]));
42 state[10] = field_ct(block.get_context(), uint256_t(IV[2]));
43 state[11] = field_ct(block.get_context(), uint256_t(IV[3]));
44 state[12] = field_ct(block.get_context(), 0);
45 state[13] = field_ct(block.get_context(), 0);
46 state[14] = field_ct(block.get_context(), uint256_t(block_len));
47 state[15] = field_ct(block.get_context(), uint256_t(flags));
48
49 for (size_t idx = 0; idx < 7; idx++) {
50 round_fn(state, block_words, idx, true);
51 }
52}
53
54template <typename Builder>
56 const byte_array<Builder>& block,
57 uint8_t block_len,
58 uint8_t flags)
59{
60 field_ct state[BLAKE3_STATE_SIZE];
61 compress_pre(state, cv, block, block_len, flags);
62
70 for (size_t i = 0; i < (BLAKE3_STATE_SIZE >> 1); i++) {
71 const auto lookup = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR, state[i], state[i + 8], true);
72 cv[i] = lookup[ColumnIdx::C3][0];
73 }
74}
75
76template <typename Builder>
78 const byte_array<Builder>& block,
79 uint8_t block_len,
80 uint8_t flags,
82{
83 field_ct state[BLAKE3_STATE_SIZE];
84
85 compress_pre(state, cv, block, block_len, flags);
86
91 for (size_t i = 0; i < (BLAKE3_STATE_SIZE >> 1); i++) {
92 const auto lookup_1 = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR, state[i], state[i + 8], true);
93 byte_array<Builder> out_bytes_1(lookup_1[ColumnIdx::C3][0], 4);
94 out.write_at(out_bytes_1.reverse(), i * 4);
95
96 const auto lookup_2 = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR, state[i + 8], cv[i], true);
97 byte_array<Builder> out_bytes_2(lookup_2[ColumnIdx::C3][0], 4);
98 out.write_at(out_bytes_2.reverse(), (i + 8) * 4);
99 }
100}
101
102template <typename Builder>
104 const byte_array<Builder>& block,
105 uint8_t block_len,
106 uint8_t flags)
107{
108 output_t ret;
109 for (size_t i = 0; i < (BLAKE3_OUT_LEN >> 2); ++i) {
110 ret.input_cv[i] = input_cv[i];
111 }
112
113 ret.block = byte_array_ct(block.get_context(), BLAKE3_BLOCK_LEN);
114 for (size_t i = 0; i < BLAKE3_BLOCK_LEN; i++) {
115 ret.block[i] = block[i];
116 }
117 ret.block_len = block_len;
118 ret.flags = flags;
119 return ret;
120}
121
122/*
123 * Blake3s wrapper functions.
124 *
125 */
126template <typename Builder> void Blake3s<Builder>::hasher_init(blake3_hasher* self)
127{
128 for (size_t i = 0; i < (BLAKE3_KEY_LEN >> 2); ++i) {
129 self->key[i] = field_ct(uint256_t(IV[i]));
130 self->cv[i] = field_ct(uint256_t(IV[i]));
131 }
132 self->buf = byte_array_ct(self->context, BLAKE3_BLOCK_LEN);
133 for (size_t i = 0; i < BLAKE3_BLOCK_LEN; i++) {
134 self->buf[i] = field_t<Builder>(self->context, 0);
135 }
136 self->buf_len = 0;
137 self->blocks_compressed = 0;
138 self->flags = 0;
139}
140
141template <typename Builder>
142void Blake3s<Builder>::hasher_update(blake3_hasher* self, const byte_array<Builder>& input, size_t input_len)
143{
144 if (input_len == 0) {
145 return;
146 }
147
148 size_t start_counter = 0;
149 while (input_len > BLAKE3_BLOCK_LEN) {
150 compress_in_place(self->cv,
151 input.slice(start_counter, BLAKE3_BLOCK_LEN),
152 BLAKE3_BLOCK_LEN,
153 self->flags | maybe_start_flag(self));
154 self->blocks_compressed = static_cast<uint8_t>(self->blocks_compressed + 1);
155 start_counter += BLAKE3_BLOCK_LEN;
156 input_len -= BLAKE3_BLOCK_LEN;
157 }
158
159 size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len);
160 if (take > input_len) {
161 take = input_len;
162 }
163 for (size_t i = 0; i < take; i++) {
164 self->buf[self->buf_len + i] = input[i + start_counter];
165 }
166
167 self->buf_len = static_cast<uint8_t>(self->buf_len + (uint8_t)take);
168 input_len -= take;
169}
170
171template <typename Builder> void Blake3s<Builder>::hasher_finalize(const blake3_hasher* self, byte_array<Builder>& out)
172{
173 uint8_t block_flags = self->flags | maybe_start_flag(self) | CHUNK_END;
174 output_t output = make_output(self->cv, self->buf, self->buf_len, block_flags);
175
176 byte_array_ct wide_buf(out.get_context(), BLAKE3_BLOCK_LEN);
177 compress_xof(output.input_cv, output.block, output.block_len, output.flags | ROOT, wide_buf);
178 for (size_t i = 0; i < BLAKE3_OUT_LEN; i++) {
179 out[i] = wide_buf[i];
180 }
181}
182
183template <typename Builder> byte_array<Builder> Blake3s<Builder>::hash(const byte_array<Builder>& input)
184{
185 ASSERT(input.size() <= BLAKE3_CHUNK_LEN,
186 "Barretenberg does not support blake3s with input lengths greater than 1024 bytes.");
187
188 blake3_hasher hasher = {};
189 hasher.context = input.get_context();
190 hasher_init(&hasher);
191 hasher_update(&hasher, input, input.size());
192 byte_array_ct result(input.get_context(), BLAKE3_OUT_LEN);
193 hasher_finalize(&hasher, result);
194 return result;
195}
196
197template class Blake3s<UltraCircuitBuilder>;
198template class Blake3s<MegaCircuitBuilder>;
199} // namespace bb::stdlib
#define ASSERT(expression,...)
Definition assert.hpp:49
static void hasher_init(blake3_hasher *self)
Definition blake3s.cpp:126
static byte_array_ct hash(const byte_array_ct &input)
Definition blake3s.cpp:183
static void compress_in_place(field_t< Builder > cv[8], const byte_array_ct &block, uint8_t block_len, uint8_t flags)
Definition blake3s.cpp:55
static void compress_xof(const field_t< Builder > cv[8], const byte_array_ct &block, uint8_t block_len, uint8_t flags, byte_array_ct &out)
Definition blake3s.cpp:77
static void compress_pre(field_t< Builder > state[BLAKE3_STATE_SIZE], const field_t< Builder > cv[8], const byte_array_ct &block, uint8_t block_len, uint8_t flags)
Definition blake3s.cpp:21
static void hasher_finalize(const blake3_hasher *self, byte_array_ct &out)
Definition blake3s.cpp:171
static output_t make_output(const field_t< Builder > input_cv[8], const byte_array_ct &block, uint8_t block_len, uint8_t flags)
Definition blake3s.cpp:103
static void hasher_update(blake3_hasher *self, const byte_array_ct &input, size_t input_len)
Definition blake3s.cpp:142
Represents a dynamic array of bytes in-circuit.
byte_array slice(size_t offset) const
Slice bytes from the byte array starting at offset. Does not add any constraints.
byte_array reverse() const
Reverse the bytes in the byte array.
byte_array & write_at(byte_array const &other, size_t index)
Overwrites this byte_array starting at index with the contents of other. Asserts that the write does ...
size_t size() const
Builder * get_context() const
stdlib::field_t< Builder > field_ct
stdlib::byte_array< Builder > byte_array_ct
void round_fn(field_t< Builder > state[BLAKE_STATE_SIZE], field_t< Builder > msg[BLAKE_STATE_SIZE], size_t round, const bool which_blake=false)
byte_array< Builder > buf
Definition blake3s.hpp:43
field_t< Builder > cv[8]
Definition blake3s.hpp:42
field_t< Builder > key[8]
Definition blake3s.hpp:41
byte_array< Builder > block
Definition blake3s.hpp:52
field_t< Builder > input_cv[8]
Definition blake3s.hpp:51