barretenberg
Loading...
Searching...
No Matches
permutation.hpp
1#pragma once
2#include "barretenberg/common/slab_allocator.hpp"
3#include "barretenberg/common/throw_or_abort.hpp"
4#include "barretenberg/numeric/bitop/get_msb.hpp"
5#include "barretenberg/polynomials/iterate_over_domain.hpp"
6#include "barretenberg/polynomials/polynomial.hpp"
7
8namespace proof_system::plonk {
9
11 uint32_t subgroup_index = 0;
12 uint8_t column_index = 0;
13 bool is_public_input = false;
14 bool is_tag = false;
15};
16
21template <typename program_settings>
23 const std::vector<uint32_t>& permutation,
24 const barretenberg::evaluation_domain& small_domain)
25{
26 std::vector<permutation_subgroup_element> subgroup_elements;
27 for (const auto& permutation_element : permutation) {
28 uint32_t index = permutation_element & (uint32_t)0xffffffU;
29 uint32_t column = permutation_element >> 30U;
30 subgroup_elements.emplace_back(permutation_subgroup_element{ index, (uint8_t)column, false, false });
31 }
32 compute_permutation_lagrange_base_single<program_settings>(output, subgroup_elements, small_domain);
33}
34
44template <typename program_settings>
46 const std::vector<permutation_subgroup_element>& permutation,
47 const barretenberg::evaluation_domain& small_domain)
48{
49 if (output.size() < permutation.size()) {
50 throw_or_abort("Permutation polynomial size is insufficient to store permutations.");
51 }
52 // permutation encoding:
53 // low 28 bits defines the location in witness polynomial
54 // upper 2 bits defines the witness polynomial:
55 // 0 = left
56 // 1 = right
57 // 2 = output
58 ASSERT(small_domain.log2_size > 1);
59 const barretenberg::fr* roots = small_domain.get_round_roots()[small_domain.log2_size - 2];
60 const size_t root_size = small_domain.size >> 1UL;
61 const size_t log2_root_size = static_cast<size_t>(numeric::get_msb(root_size));
62
63 ITERATE_OVER_DOMAIN_START(small_domain);
64
65 // `permutation[i]` will specify the 'index' that this wire value will map to.
66 // Here, 'index' refers to an element of our subgroup H.
67 // We can almost use `permutation[i]` to directly index our `roots` array, which contains our subgroup elements.
68 // We first have to accommodate for the fact that `roots` only contains *half* of our subgroup elements. This is
69 // because ω^{n/2} = -ω and we don't want to perform redundant work computing roots of unity.
70
71 size_t raw_idx = permutation[i].subgroup_index;
72
73 // Step 1: is `raw_idx` >= (n / 2)? if so, we will need to index `-roots[raw_idx - subgroup_size / 2]` instead
74 // of `roots[raw_idx]`
75 const bool negative_idx = raw_idx >= root_size;
76
77 // Step 2: compute the index of the subgroup element we'll be accessing.
78 // To avoid a conditional branch, we can subtract `negative_idx << log2_root_size` from `raw_idx`.
79 // Here, `log2_root_size = numeric::get_msb(subgroup_size / 2)` (we know our subgroup size will be a power of 2,
80 // so we lose no precision here)
81 const size_t idx = raw_idx - (static_cast<size_t>(negative_idx) << log2_root_size);
82
83 // Call `conditionally_subtract_double_modulus`, using `negative_idx` as our predicate.
84 // Our roots of unity table is partially 'overloaded' - we either store the root `w`, or `modulus + w`
85 // So to ensure we correctly compute `modulus - w`, we need to compute `2 * modulus - w`
86 // The output will similarly be overloaded (containing either 2 * modulus - w, or modulus - w)
87 output[i] = roots[idx].conditionally_subtract_from_double_modulus(static_cast<uint64_t>(negative_idx));
88
89 // Finally, if our permutation maps to an index in either the right wire vector, or the output wire vector, we
90 // need to multiply our result by one of two quadratic non-residues. (This ensures that mapping into the left
91 // wires gives unique values that are not repeated in the right or output wire permutations) (ditto for right
92 // wire and output wire mappings)
93
94 if (permutation[i].is_public_input) {
95 // As per the paper which modifies plonk to include the public inputs in a permutation argument, the permutation
96 // `σ` is modified to `σ'`, where `σ'` maps all public inputs to a set of l distinct ζ elements which are
97 // disjoint from H ∪ k1·H ∪ k2·H.
98 output[i] *= barretenberg::fr::external_coset_generator();
99 } else if (permutation[i].is_tag) {
100 output[i] *= barretenberg::fr::tag_coset_generator();
101 } else {
102 {
103 const uint32_t column_index = permutation[i].column_index;
104 if (column_index > 0) {
105 output[i] *= barretenberg::fr::coset_generator(column_index - 1);
106 }
107 }
108 }
109 ITERATE_OVER_DOMAIN_END;
110}
111} // namespace proof_system::plonk
Definition: widget.bench.cpp:13
void compute_permutation_lagrange_base_single(barretenberg::polynomial &output, const std::vector< uint32_t > &permutation, const barretenberg::evaluation_domain &small_domain)
Definition: permutation.hpp:22