barretenberg
Loading...
Searching...
No Matches
precomputed_tables_builder.hpp
1#pragma once
2
3#include "./eccvm_builder_types.hpp"
4
5namespace proof_system {
6
7template <typename Flavor> class ECCVMPrecomputedTablesBuilder {
8 public:
9 using CycleGroup = typename Flavor::CycleGroup;
10 using FF = typename Flavor::FF;
11 using Element = typename CycleGroup::element;
12 using AffineElement = typename CycleGroup::affine_element;
13
14 static constexpr size_t NUM_WNAF_SLICES = proof_system_eccvm::NUM_WNAF_SLICES;
15 static constexpr size_t WNAF_SLICES_PER_ROW = proof_system_eccvm::WNAF_SLICES_PER_ROW;
16 static constexpr size_t WNAF_SLICE_BITS = proof_system_eccvm::WNAF_SLICE_BITS;
17
19 int s1 = 0;
20 int s2 = 0;
21 int s3 = 0;
22 int s4 = 0;
23 int s5 = 0;
24 int s6 = 0;
25 int s7 = 0;
26 int s8 = 0;
27 bool skew = false;
28 bool point_transition = false;
29 uint32_t pc = 0;
30 uint32_t round = 0;
31 uint256_t scalar_sum = 0;
32 AffineElement precompute_accumulator{ 0, 0 };
33 AffineElement precompute_double{ 0, 0 };
34 };
35
36 static std::vector<PrecomputeState> compute_precompute_state(
37 const std::vector<proof_system_eccvm::ScalarMul<CycleGroup>>& ecc_muls)
38 {
39 std::vector<PrecomputeState> precompute_state;
40
41 // start with empty row (shiftable polynomials must have 0 as first coefficient)
42 precompute_state.push_back(PrecomputeState{});
43 static constexpr size_t num_rows_per_scalar = NUM_WNAF_SLICES / WNAF_SLICES_PER_ROW;
44
45 // current impl doesn't work if not 4
46 static_assert(WNAF_SLICES_PER_ROW == 4);
47
48 for (const auto& entry : ecc_muls) {
49 const auto& slices = entry.wnaf_slices;
50 uint256_t scalar_sum = 0;
51
52 const Element point = entry.base_point;
53 const Element d2 = point.dbl();
54
55 for (size_t i = 0; i < num_rows_per_scalar; ++i) {
56 PrecomputeState row;
57 const int slice0 = slices[i * WNAF_SLICES_PER_ROW];
58 const int slice1 = slices[i * WNAF_SLICES_PER_ROW + 1];
59 const int slice2 = slices[i * WNAF_SLICES_PER_ROW + 2];
60 const int slice3 = slices[i * WNAF_SLICES_PER_ROW + 3];
61
62 const int slice0base2 = (slice0 + 15) / 2;
63 const int slice1base2 = (slice1 + 15) / 2;
64 const int slice2base2 = (slice2 + 15) / 2;
65 const int slice3base2 = (slice3 + 15) / 2;
66
67 // convert into 2-bit chunks
68 row.s1 = slice0base2 >> 2;
69 row.s2 = slice0base2 & 3;
70 row.s3 = slice1base2 >> 2;
71 row.s4 = slice1base2 & 3;
72 row.s5 = slice2base2 >> 2;
73 row.s6 = slice2base2 & 3;
74 row.s7 = slice3base2 >> 2;
75 row.s8 = slice3base2 & 3;
76 bool last_row = (i == num_rows_per_scalar - 1);
77
78 row.skew = last_row ? entry.wnaf_skew : false;
79
80 row.scalar_sum = scalar_sum;
81
82 // N.B. we apply a constraint that requires slice1 to be positive for the 1st row of each scalar sum.
83 // This ensures we do not have WNAF representations of negative values
84 const int row_chunk = slice3 + slice2 * (1 << 4) + slice1 * (1 << 8) + slice0 * (1 << 12);
85
86 bool chunk_negative = row_chunk < 0;
87
88 scalar_sum = scalar_sum << (WNAF_SLICE_BITS * WNAF_SLICES_PER_ROW);
89 if (chunk_negative) {
90 scalar_sum -= static_cast<uint64_t>(-row_chunk);
91 } else {
92 scalar_sum += static_cast<uint64_t>(row_chunk);
93 }
94 row.round = static_cast<uint32_t>(i);
95 row.point_transition = last_row;
96 row.pc = entry.pc;
97
98 if (last_row) {
99 ASSERT(scalar_sum - entry.wnaf_skew == entry.scalar);
100 }
101
102 row.precompute_double = d2;
103 // fill accumulator in reverse order i.e. first row = 15[P], then 13[P], ..., 1[P]
104 row.precompute_accumulator = entry.precomputed_table[proof_system_eccvm::POINT_TABLE_SIZE - 1 - i];
105 precompute_state.emplace_back(row);
106 }
107 }
108 return precompute_state;
109 }
110};
111} // namespace proof_system
Definition: uint256.hpp:25
Definition: precomputed_tables_builder.hpp:7
Definition: precomputed_tables_builder.hpp:18
Definition: eccvm_builder_types.hpp:36