Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
blake_util.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
10
12
13using namespace bb::plookup;
14
15// constants
17
18constexpr uint8_t MSG_SCHEDULE_BLAKE3[7][16] = {
19 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8 },
20 { 3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1 }, { 10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6 },
21 { 12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4 }, { 9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7 },
22 { 11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13 },
23};
24
25constexpr uint8_t MSG_SCHEDULE_BLAKE2[10][16] = {
26 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
27 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
28 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
29 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
30 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
31};
32
39template <typename Builder> field_t<Builder> add_normalize(const field_t<Builder>& a, const field_t<Builder>& b)
40{
43
44 Builder* ctx = a.get_context() ? a.get_context() : b.get_context();
45
46 uint256_t sum = a.get_value() + b.get_value();
47
48 uint256_t normalized_sum = static_cast<uint32_t>(sum.data[0]);
49
50 if (a.is_constant() && b.is_constant()) {
51 return field_pt(ctx, normalized_sum);
52 }
53
54 field_pt overflow = witness_pt(ctx, fr((sum - normalized_sum) >> 32));
55
56 // The overflow here could be of 2 bits because we allow that much overflow in the Blake rounds.
57 overflow.create_range_constraint(3);
58
59 // a + b - (overflow * 2^{32})
60 field_pt result = a.add_two(b, overflow * field_pt(ctx, -fr((uint64_t)(1ULL << 32ULL))));
61
62 return result;
63}
64
111template <typename Builder>
113 size_t a,
114 size_t b,
115 size_t c,
116 size_t d,
119{
121
122 // For simplicity, state[a] is written as `a' in comments.
123 // a = a + b + x
124 state[a] = state[a].add_two(state[b], x);
125
126 // d = (d ^ a).ror(16)
127 // Get the lookup accumulator where `lookup_1[ColumnIdx::C3][0]` contains the
128 // XORed and rotated (by 16) value scaled by 2^{-16}.
129 const auto lookup_1 = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR_ROTATE_16, state[d], state[a], true);
130 // Compute the scaling factor 2^{32-16} = 2^{16} to get the correct rotated value.
131 field_pt scaling_factor_1 = (1 << (32 - 16));
132 // Multiply by the scaling factor to get the final rotated value.
133 state[d] = lookup_1[ColumnIdx::C3][0] * scaling_factor_1;
134
135 // c = c + d
136 state[c] = state[c] + state[d];
137
138 // b = (b ^ c).ror(12)
139 // Does not require a special XOR_ROTATE_12 table since we can get the correct value
140 // by combining values from BLAKE_XOR table itself.
141 // Let u = s_0 + 2^6 * s_1 + 2^{12} * s_2 + 2^{18} * s_3 + 2^{24} * s_4 + 2^{30} * s_5
142 // be a 32-bit output of XOR, split into slices s_0, s_1, s_2, s_3, s_4 (6-bits each) and s_5 (5-bit).
143 // We want to compute ROTATE_12(u) = s_2 + 2^6 * s_3 + 2^{12} * s_4 + 2^{18} * s_5 + 2^{20} * s_0 + 2^{26} * s_1.
144 // The BLAKE_XOR table gives:
145 // lookup_2[ColumnIdx::C3][0] = s_0 + 2^6 * s_1 + 2^{12} * s_2 + 2^{18} * s_3 + 2^{24} * s_4 + 2^{30} * s_5 = u.
146 // lookup_2[ColumnIdx::C3][2] = s_2 + 2^6 * s_3 + 2^{12} * s_4 + 2^{18} * s_5 (i.e., u without s_0 and s_1).
147 // Thus, we can compute ROTATE_12(u) as:
148 // ROTATE_12(u) = lookup_2[ColumnIdx::C3][2] + (lookup_2[ColumnIdx::C3][0] - 2^{12} * lookup_2[ColumnIdx::C3][2]) *
149 // 2^{20}.
150
151 // Get the lookup accumulator for BLAKE_XOR table where lookup_2[ColumnIdx::C3][0] = u.
152 const auto lookup_2 = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR, state[b], state[c], true);
153 // lookup_2[ColumnIdx::C3][2] = s_2 + 2^6 * s_3 + 2^{12} * s_4 + 2^{18} * s_5 (i.e., u without s_0 and s_1).
154 field_pt lookup_output = lookup_2[ColumnIdx::C3][2];
155 // Compute 2^{12} * lookup_2[ColumnIdx::C3][2].
156 field_pt t2_term = field_pt(1 << 12) * lookup_2[ColumnIdx::C3][2];
157 // Compute the final rotated value as described for ROTATE_12(u) above.
158 lookup_output += (lookup_2[ColumnIdx::C3][0] - t2_term) * field_pt(1 << 20);
159 state[b] = lookup_output;
160
161 // a = a + b + y
162 state[a] = add_normalize(state[a], state[b] + y);
163
164 // d = (d ^ a).ror(8)
165 // Get the lookup accumulator where `lookup_3[ColumnIdx::C3][0]` contains the
166 // XORed and rotated (by 8) value scaled by 2^{-24}.
167 const auto lookup_3 = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR_ROTATE_8, state[d], state[a], true);
168 // Compute the scaling factor 2^{32-8} = 2^{24} to get the correct rotated value.
169 field_pt scaling_factor_3 = (1 << (32 - 8));
170 // Multiply by the scaling factor to get the final rotated value.
171 state[d] = lookup_3[ColumnIdx::C3][0] * scaling_factor_3;
172
173 // c = c + d
174 state[c] = add_normalize(state[c], state[d]);
175
176 // b = (b ^ c).ror(7)
177 // Get the lookup accumulator where `lookup_4[ColumnIdx::C3][0]` contains the
178 // XORed and rotated (by 7) value scaled by 2^{-25}.
179 const auto lookup_4 = plookup_read<Builder>::get_lookup_accumulators(BLAKE_XOR_ROTATE_7, state[b], state[c], true);
180 // Compute the scaling factor 2^{32-7} = 2^{25} to get the correct rotated value.
181 field_pt scaling_factor_4 = (1 << (32 - 7));
182 // Multiply by the scaling factor to get the final rotated value.
183 state[b] = lookup_4[ColumnIdx::C3][0] * scaling_factor_4;
184}
185
186/*
187 * This is the round function used in Blake2s and Blake3s for Ultra.
188 * Inputs: - 16-word state
189 * - 16-word msg
190 * - round number
191 * - which_blake to choose Blake2 or Blake3 (false -> Blake2)
192 */
193template <typename Builder>
196 size_t round,
197 const bool which_blake = false)
198{
199 // Select the message schedule based on the round.
200 const uint8_t* schedule = which_blake ? MSG_SCHEDULE_BLAKE3[round] : MSG_SCHEDULE_BLAKE2[round];
201
202 // Mix the columns.
203 g<Builder>(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]);
204 g<Builder>(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]);
205 g<Builder>(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]);
206 g<Builder>(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]);
207
208 // Mix the rows.
209 g<Builder>(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]);
210 g<Builder>(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]);
211 g<Builder>(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]);
212 g<Builder>(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]);
213}
214
215} // namespace bb::stdlib::blake_util
void create_range_constraint(size_t num_bits, std::string const &msg="field_t::range_constraint") const
Let x = *this.normalize(), constrain x.v < 2^{num_bits}.
Definition field.cpp:909
field_t add_two(const field_t &add_b, const field_t &add_c) const
Efficiently compute (this + a + b) using big_mul gate.
Definition field.cpp:575
static plookup::ReadData< field_pt > get_lookup_accumulators(const plookup::MultiTableId id, const field_pt &key_a, const field_pt &key_b=0, const bool is_2_to_1_lookup=false)
Definition plookup.cpp:19
FF a
FF b
stdlib::witness_t< bb::UltraCircuitBuilder > witness_pt
stdlib::field_t< UltraCircuitBuilder > field_pt
@ BLAKE_XOR_ROTATE_16
Definition types.hpp:113
@ BLAKE_XOR_ROTATE_7
Definition types.hpp:115
@ BLAKE_XOR_ROTATE_8
Definition types.hpp:114
constexpr uint8_t MSG_SCHEDULE_BLAKE2[10][16]
field_t< Builder > add_normalize(const field_t< Builder > &a, const field_t< Builder > &b)
constexpr uint8_t MSG_SCHEDULE_BLAKE3[7][16]
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)
void g(field_t< Builder > state[BLAKE_STATE_SIZE], size_t a, size_t b, size_t c, size_t d, field_t< Builder > x, field_t< Builder > y)
field< Bn254FrParams > fr
Definition fr.hpp:174
Inner sum(Cont< Inner, Args... > const &in)
Definition container.hpp:70