barretenberg
Loading...
Searching...
No Matches
transcript_builder.hpp
1#pragma once
2
3#include "./eccvm_builder_types.hpp"
4
5namespace proof_system {
6
7template <typename Flavor> class ECCVMTranscriptBuilder {
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
15 bool accumulator_empty = false;
16 bool q_add = false;
17 bool q_mul = false;
18 bool q_eq = false;
19 bool q_reset_accumulator = false;
20 bool msm_transition = false;
21 uint32_t pc = 0;
22 uint32_t msm_count = 0;
23 FF base_x = 0;
24 FF base_y = 0;
25 uint256_t z1 = 0;
26 uint256_t z2 = 0;
27 bool z1_zero = false;
28 bool z2_zero = false;
29 uint32_t opcode = 0;
30 FF accumulator_x = 0;
31 FF accumulator_y = 0;
32 FF msm_output_x = 0;
33 FF msm_output_y = 0;
34 FF collision_check = 0;
35 };
36 struct VMState {
37 uint32_t pc = 0;
38 uint32_t count = 0;
39 AffineElement accumulator = CycleGroup::affine_point_at_infinity;
40 AffineElement msm_accumulator = CycleGroup::affine_point_at_infinity;
41 bool is_accumulator_empty = true;
42 };
43 struct Opcode {
44 bool add;
45 bool mul;
46 bool eq;
47 bool reset;
48 [[nodiscard]] uint32_t value() const
49 {
50 auto res = static_cast<uint32_t>(add);
51 res += res;
52 res += static_cast<uint32_t>(mul);
53 res += res;
54 res += static_cast<uint32_t>(eq);
55 res += res;
56 res += static_cast<uint32_t>(reset);
57 return res;
58 }
59 };
60 static std::vector<TranscriptState> compute_transcript_state(
61 const std::vector<proof_system_eccvm::VMOperation<CycleGroup>>& vm_operations,
62 const uint32_t total_number_of_muls)
63 {
64 std::vector<TranscriptState> transcript_state;
65 VMState state{
66 .pc = total_number_of_muls,
67 .count = 0,
68 .accumulator = CycleGroup::affine_point_at_infinity,
69 .msm_accumulator = CycleGroup::affine_point_at_infinity,
70 .is_accumulator_empty = true,
71 };
72 VMState updated_state;
73
74 // add an empty row. 1st row all zeroes because of our shiftable polynomials
75 transcript_state.emplace_back(TranscriptState{});
76 for (size_t i = 0; i < vm_operations.size(); ++i) {
77 TranscriptState row;
78 const proof_system_eccvm::VMOperation<CycleGroup>& entry = vm_operations[i];
79
80 const bool is_mul = entry.mul;
81 const bool z1_zero = (entry.mul) ? entry.z1 == 0 : true;
82 const bool z2_zero = (entry.mul) ? entry.z2 == 0 : true;
83 const uint32_t num_muls = is_mul ? (static_cast<uint32_t>(!z1_zero) + static_cast<uint32_t>(!z2_zero)) : 0;
84
85 updated_state = state;
86
87 if (entry.reset) {
88 updated_state.is_accumulator_empty = true;
89 updated_state.msm_accumulator = CycleGroup::affine_point_at_infinity;
90 }
91 updated_state.pc = state.pc - num_muls;
92
93 bool last_row = i == (vm_operations.size() - 1);
94 // msm transition = current row is doing a lookup to validate output = msm output
95 // i.e. next row is not part of MSM and current row is part of MSM
96 // or next row is irrelevent and current row is a straight MUL
97 bool next_not_msm = last_row ? true : !vm_operations[i + 1].mul;
98
99 bool msm_transition = entry.mul && next_not_msm;
100
101 // we reset the count in updated state if we are not accumulating and not doing an msm
102 bool current_msm = entry.mul;
103 bool current_ongoing_msm = entry.mul && !next_not_msm;
104 updated_state.count = current_ongoing_msm ? state.count + num_muls : 0;
105
106 if (current_msm) {
107 const auto P = typename CycleGroup::element(entry.base_point);
108 const auto R = typename CycleGroup::element(state.msm_accumulator);
109 updated_state.msm_accumulator = R + P * entry.mul_scalar_full;
110 }
111
112 if (entry.mul && next_not_msm) {
113 if (state.is_accumulator_empty) {
114 updated_state.accumulator = updated_state.msm_accumulator;
115 } else {
116 const auto R = typename CycleGroup::element(state.accumulator);
117 updated_state.accumulator = R + updated_state.msm_accumulator;
118 }
119 updated_state.is_accumulator_empty = false;
120 }
121
122 bool add_accumulate = entry.add;
123 if (add_accumulate) {
124 if (state.is_accumulator_empty) {
125
126 updated_state.accumulator = entry.base_point;
127 } else {
128 updated_state.accumulator = typename CycleGroup::element(state.accumulator) + entry.base_point;
129 }
130 updated_state.is_accumulator_empty = false;
131 }
132 row.accumulator_empty = state.is_accumulator_empty;
133 row.q_add = entry.add;
134 row.q_mul = entry.mul;
135 row.q_eq = entry.eq;
136 row.q_reset_accumulator = entry.reset;
137 row.msm_transition = msm_transition;
138 row.pc = state.pc;
139 row.msm_count = state.count;
140 row.base_x = (entry.add || entry.mul || entry.eq) ? entry.base_point.x : 0;
141 row.base_y = (entry.add || entry.mul || entry.eq) ? entry.base_point.y : 0;
142 row.z1 = (entry.mul) ? entry.z1 : 0;
143 row.z2 = (entry.mul) ? entry.z2 : 0;
144 row.z1_zero = z1_zero;
145 row.z2_zero = z2_zero;
146 row.opcode = Opcode{ .add = entry.add, .mul = entry.mul, .eq = entry.eq, .reset = entry.reset }.value();
147 row.accumulator_x = (state.accumulator.is_point_at_infinity()) ? 0 : state.accumulator.x;
148 row.accumulator_y = (state.accumulator.is_point_at_infinity()) ? 0 : state.accumulator.y;
149 row.msm_output_x =
150 msm_transition
151 ? (updated_state.msm_accumulator.is_point_at_infinity() ? 0 : updated_state.msm_accumulator.x)
152 : 0;
153 row.msm_output_y =
154 msm_transition
155 ? (updated_state.msm_accumulator.is_point_at_infinity() ? 0 : updated_state.msm_accumulator.y)
156 : 0;
157
158 if (entry.mul && next_not_msm && !row.accumulator_empty) {
159 ASSERT((row.msm_output_x != row.accumulator_x) &&
160 "eccvm: attempting msm. Result point x-coordinate matches accumulator x-coordinate.");
161 state.msm_accumulator = CycleGroup::affine_point_at_infinity;
162 row.collision_check = (row.msm_output_x - row.accumulator_x).invert();
163 } else if (entry.add && !row.accumulator_empty) {
164 ASSERT((row.base_x != row.accumulator_x) &&
165 "eccvm: attempting to add points with matching x-coordinates");
166 row.collision_check = (row.base_x - row.accumulator_x).invert();
167 }
168
169 state = updated_state;
170
171 if (entry.mul && next_not_msm) {
172 state.msm_accumulator = CycleGroup::affine_point_at_infinity;
173 }
174 transcript_state.emplace_back(row);
175 }
176
177 TranscriptState final_row;
178 final_row.pc = updated_state.pc;
179 final_row.accumulator_x = (updated_state.accumulator.is_point_at_infinity()) ? 0 : updated_state.accumulator.x;
180 final_row.accumulator_y = (updated_state.accumulator.is_point_at_infinity()) ? 0 : updated_state.accumulator.y;
181 final_row.accumulator_empty = updated_state.is_accumulator_empty;
182
183 transcript_state.push_back(final_row);
184 return transcript_state;
185 }
186};
187} // namespace proof_system
Definition: uint256.hpp:25
Definition: transcript_builder.hpp:7
Definition: transcript_builder.hpp:43
Definition: transcript_builder.hpp:14
Definition: transcript_builder.hpp:36
Definition: eccvm_builder_types.hpp:15