3#include "../../primitives/curves/bn254.hpp"
4#include "../../primitives/memory/rom_table.hpp"
5#include "../../primitives/uint/uint.hpp"
6#include "barretenberg/crypto/pedersen_hash/pedersen.hpp"
7#include "barretenberg/ecc/curves/bn254/fq12.hpp"
8#include "barretenberg/ecc/curves/bn254/pairing.hpp"
9#include "barretenberg/plonk/proof_system/public_inputs/public_inputs.hpp"
10#include "barretenberg/plonk/proof_system/types/polynomial_manifest.hpp"
11#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp"
12#include "barretenberg/polynomials/evaluation_domain.hpp"
13#include "barretenberg/polynomials/polynomial_arithmetic.hpp"
14#include "barretenberg/srs/factories/crs_factory.hpp"
15#include "barretenberg/stdlib/hash/pedersen/pedersen.hpp"
18namespace proof_system::plonk::stdlib::recursion {
43 static_assert(bits_per_element <
uint256_t(barretenberg::fr::modulus).get_msb());
45 if (current_bit_counter != 0) {
86 size_t current_bit_counter = 0;
90 void add_element_with_existing_range_constraint(
const field_pt&
element,
const size_t num_bits)
111 ASSERT(context !=
nullptr);
113 size_t hi_bits = bits_per_element - current_bit_counter;
114 if (hi_bits >= num_bits) {
116 size_t new_bit_counter = current_bit_counter + num_bits;
118 const size_t leftovers = bits_per_element - new_bit_counter;
121 current_bit_counter = new_bit_counter;
122 if (current_bit_counter == bits_per_element) {
123 current_bit_counter = 0;
130 const size_t lo_bits = num_bits - hi_bits;
133 lo.create_range_constraint(lo_bits);
134 hi.create_range_constraint(hi_bits);
136 if (!
element.is_constant() || !lo.is_constant() || !hi.is_constant()) {
140 constexpr uint256_t modulus = barretenberg::fr::modulus;
141 constexpr size_t modulus_bits = modulus.get_msb();
144 if (num_bits >= modulus_bits) {
149 field_pt borrow = field_pt::from_witness(context, need_borrow);
153 context->create_new_range_constraint(borrow.get_witness_index(), 1,
"borrow");
155 context->create_range_constraint(borrow.get_witness_index(), 1,
"borrow");
159 field_t res_hi = (r_hi - hi) - borrow;
162 res_hi.create_range_constraint(modulus_bits + 1 - lo_bits);
163 res_lo.create_range_constraint(lo_bits);
165 current_bit_counter = (current_bit_counter + num_bits) % bits_per_element;
168 if (current_bit_counter == 0) {
189 domain.root = fields[0];
191 domain.root_inverse = domain.root.invert();
192 domain.domain = fields[1];
193 domain.domain_inverse = domain.domain.invert();
194 domain.generator = fields[2];
195 domain.generator_inverse = domain.generator.invert();
196 domain.size = domain.domain;
204 domain.root_inverse = domain.root.invert();
206 domain.domain_inverse = domain.domain.invert();
208 domain.generator_inverse = domain.generator.invert();
209 domain.size = domain.domain;
222 domain.size = domain.domain;
236 using Builder =
typename Curve::Builder;
238 static std::shared_ptr<verification_key> from_field_elements(
241 bool inner_proof_contains_recursive_proof =
false,
242 std::array<uint32_t, 16> recursive_proof_public_input_indices = {})
244 std::vector<fr> fields_raw;
245 std::shared_ptr<verification_key> key = std::make_shared<verification_key>();
252 key->num_public_inputs = fields[4];
256 key->contains_recursive_proof = inner_proof_contains_recursive_proof;
257 for (
size_t i = 0; i < 16; ++i) {
258 auto x = recursive_proof_public_input_indices[i];
259 key->recursive_proof_public_input_indices.emplace_back(x);
263 for (
const auto& descriptor : key->polynomial_manifest.get()) {
264 if (descriptor.source == PolynomialSource::SELECTOR || descriptor.source == PolynomialSource::PERMUTATION) {
266 const auto x_lo = fields[count++];
267 const auto x_hi = fields[count++];
268 const auto y_lo = fields[count++];
269 const auto y_hi = fields[count++];
270 const typename Curve::BaseField x(x_lo, x_hi);
271 const typename Curve::BaseField y(y_lo, y_hi);
272 const typename Curve::Group
element(x, y);
274 key->commitments.insert({ std::string(descriptor.commitment_label),
element });
287 const std::shared_ptr<plonk::verification_key>& input_key)
289 std::shared_ptr<verification_key> key = std::make_shared<verification_key>();
292 key->reference_string = input_key->reference_string;
293 key->polynomial_manifest = input_key->polynomial_manifest;
299 key->contains_recursive_proof = input_key->contains_recursive_proof;
300 key->recursive_proof_public_input_indices = input_key->recursive_proof_public_input_indices;
301 for (
const auto& [tag, value] : input_key->commitments) {
307 const typename Curve::BaseField x = Curve::BaseField::from_witness(ctx, value.x);
308 const typename Curve::BaseField y = Curve::BaseField::from_witness(ctx, value.y);
309 key->commitments.insert({ tag,
typename Curve::Group(x, y) });
315 static std::shared_ptr<verification_key> from_constants(
Builder* ctx,
316 const std::shared_ptr<plonk::verification_key>& input_key)
318 std::shared_ptr<verification_key> key = std::make_shared<verification_key>();
321 key->num_public_inputs =
field_t<Builder>(ctx, input_key->num_public_inputs);
322 key->contains_recursive_proof = input_key->contains_recursive_proof;
323 key->recursive_proof_public_input_indices = input_key->recursive_proof_public_input_indices;
327 for (
const auto& [tag, value] : input_key->commitments) {
328 key->commitments.insert({ tag,
typename Curve::Group(value) });
331 key->reference_string = input_key->reference_string;
332 key->polynomial_manifest = input_key->polynomial_manifest;
337 void validate_key_is_in_set(
const std::vector<std::shared_ptr<plonk::verification_key>>& keys_in_set)
339 const auto circuit_key_compressed = hash();
344 std::vector<field_t<Builder>> compressed_keys;
345 for (
size_t i = 0; i < keys_in_set.size(); ++i) {
347 compressed_keys.emplace_back(compressed);
348 if (compressed == circuit_key_compressed.get_value()) {
355 "verification_key::validate_key_is_in_set failed - input key is not in the provided set!");
357 rom_table<Builder> key_table(compressed_keys);
359 const auto output_key = key_table[key_index];
360 output_key.assert_equal(circuit_key_compressed);
362 bool_t<Builder> is_valid(
false);
363 for (
const auto& key : keys_in_set) {
365 is_valid = is_valid || (circuit_key_compressed == compressed);
368 is_valid.assert_equal(
true);
375 PedersenPreimageBuilder<Builder> preimage_buffer(context);
379 domain.generator.create_range_constraint(16,
"domain.generator");
380 domain.domain.create_range_constraint(32,
"domain.generator");
381 num_public_inputs.create_range_constraint(32,
"num_public_inputs");
382 preimage_buffer.add_element_with_existing_range_constraint(circuit_type, 8);
383 preimage_buffer.add_element_with_existing_range_constraint(domain.generator, 16);
384 preimage_buffer.add_element_with_existing_range_constraint(domain.domain, 32);
385 preimage_buffer.add_element_with_existing_range_constraint(num_public_inputs, 32);
386 constexpr size_t limb_bits = Curve::BaseField::NUM_LIMB_BITS;
387 constexpr size_t last_limb_bits = 256 - (limb_bits * 3);
388 for (
const auto& [tag, selector] : commitments) {
389 const auto& x = selector.x;
390 const auto& y = selector.y;
391 preimage_buffer.add_element_with_existing_range_constraint(y.binary_basis_limbs[3].element, last_limb_bits);
392 preimage_buffer.add_element_with_existing_range_constraint(y.binary_basis_limbs[2].element, limb_bits);
393 preimage_buffer.add_element_with_existing_range_constraint(y.binary_basis_limbs[1].element, limb_bits);
394 preimage_buffer.add_element_with_existing_range_constraint(y.binary_basis_limbs[0].element, limb_bits);
395 preimage_buffer.add_element_with_existing_range_constraint(x.binary_basis_limbs[3].element, last_limb_bits);
396 preimage_buffer.add_element_with_existing_range_constraint(x.binary_basis_limbs[2].element, limb_bits);
397 preimage_buffer.add_element_with_existing_range_constraint(x.binary_basis_limbs[1].element, limb_bits);
398 preimage_buffer.add_element_with_existing_range_constraint(x.binary_basis_limbs[0].element, limb_bits);
400 preimage_buffer.add_element(domain.root);
405 static barretenberg::fr hash_native(
const std::shared_ptr<plonk::verification_key>& key,
406 const size_t hash_index = 0)
408 std::vector<uint8_t> preimage_data;
410 preimage_data.push_back(
static_cast<uint8_t
>(Builder::CIRCUIT_TYPE));
412 const uint256_t domain = key->domain.domain;
413 const uint256_t generator = key->domain.generator;
414 const uint256_t num_public_inputs = key->num_public_inputs;
417 ASSERT(generator < (
uint256_t(1) << 16));
418 ASSERT(num_public_inputs < (
uint256_t(1) << 32));
420 write(preimage_data,
static_cast<uint16_t
>(
uint256_t(key->domain.generator)));
421 write(preimage_data,
static_cast<uint32_t
>(
uint256_t(key->domain.domain)));
422 write(preimage_data,
static_cast<uint32_t
>(key->num_public_inputs));
423 for (
const auto& [tag, selector] : key->commitments) {
424 write(preimage_data, selector.y);
425 write(preimage_data, selector.x);
428 write(preimage_data, key->domain.root);
440 std::map<std::string, typename Curve::Group> commitments;
444 std::shared_ptr<barretenberg::srs::factories::VerifierCrs<curve::BN254>> reference_string;
446 PolynomialManifest polynomial_manifest;
448 bool contains_recursive_proof =
false;
449 std::vector<uint32_t> recursive_proof_public_input_indices;
450 size_t program_width = 4;
static Fq hash_buffer(const std::vector< uint8_t > &input, GeneratorContext context={})
Given an arbitrary length of bytes, convert them to fields and hash the result using the default gene...
Definition: pedersen.cpp:69
Definition: uint256.hpp:25
constexpr uint256_t slice(uint64_t start, uint64_t end) const
Definition: uint256_impl.hpp:157
Definition: standard_circuit_builder.hpp:12
Definition: polynomial_manifest.hpp:142
Definition: biggroup.hpp:22
static field_t accumulate(const std::vector< field_t > &to_add)
Definition: field.cpp:936
void assert_equal(const field_t &rhs, std::string const &msg="field_t::assert_equal") const
Constrain that this field is equal to the given field.
Definition: field.cpp:749
stdlib class that evaluates in-circuit pedersen hashes, consistent with behavior in crypto::pedersen_...
Definition: pedersen.hpp:18
Definition: witness.hpp:10
Contains all the headers required to adequately compile the types defined in circuit_builders_fwd....
Definition: circuit_builders.hpp:11
Constructs a packed buffer of field elements to be fed into a Pedersen hash function Goal is to conca...
Definition: verification_key.hpp:31
std::vector< field_pt > preimage_data
preimage_data is a bit-array where bits_per_element number of bits are packed into a single field ele...
Definition: verification_key.hpp:77
void slice_element(const field_pt &element, const size_t num_bits)
Populate preimage_data with element whose size is known to be num_bits. preimage_data is treated as a...
Definition: verification_key.hpp:109
std::vector< field_pt > work_element
work_element represents the leading element to be added into preimage_data. Vector is composed of fie...
Definition: verification_key.hpp:84
Definition: verification_key.hpp:185
Definition: verification_key.hpp:235
static std::shared_ptr< verification_key > from_witness(Builder *ctx, const std::shared_ptr< plonk::verification_key > &input_key)
Converts a 'native' verification key into a standard library type, instantiating the input_key parame...
Definition: verification_key.hpp:286