Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc.cpp
Go to the documentation of this file.
5
6namespace bb::avm2::simulation {
7
8namespace {
9
10class InternalEccException : public std::runtime_error {
11 public:
12 using std::runtime_error::runtime_error; // Inherit the constructor.
13};
14
15} // namespace
16
31{
32 // Check if points are on the curve. These will throw an unexpected exception if they fail.
33 BB_ASSERT(p.on_curve(), "Point p is not on the curve");
34 BB_ASSERT(q.on_curve(), "Point q is not on the curve");
35
36 EmbeddedCurvePoint result = p + q;
37 add_events.emit({ .p = p, .q = q, .result = result });
38 return result;
39}
40
56{
57 // This is bad - the scalar mul circuit assumes that the point is on the curve.
58 // This will throw an unexpected exception if it fails.
59 BB_ASSERT(point.on_curve(), "Point must be on the curve for scalar multiplication");
60
61 // FF bit size == 254.
62 auto intermediate_states = std::vector<ScalarMulIntermediateState>(254);
63 // Emits ToRadixEvent, see #[TO_RADIX] in scalar_mul.pil.
64 auto bits = to_radix.to_le_bits(scalar, 254).first;
65
66 // First iteration does conditional assignment instead of addition. Note: in circuit we perform reverse aggregation,
67 // so the corresponding constraints for below are gated by 'end'.
68
69 // See 'Temp Computation' section in scalar_mul.pil.
70 EmbeddedCurvePoint temp = point;
71 bool bit = bits[0];
72
73 // See 'Result Computation' section in scalar_mul.pil.
75 intermediate_states[0] = { result, temp, bit };
76
77 for (size_t i = 1; i < 254; i++) {
78 bit = bits[i];
79 // Emits EccAddEvent, see #[DOUBLE] in scalar_mul.pil.
80 temp = add(temp, temp);
81 if (bit) {
82 // Emits EccAddEvent, see #[ADD] in scalar_mul.pil.
83 result = add(result, temp);
84 }
85 intermediate_states[i] = { result, temp, bit };
86 }
88 { .point = point, .scalar = scalar, .intermediate_states = std::move(intermediate_states), .result = result });
89 return result;
90}
91
107 const EmbeddedCurvePoint& p,
108 const EmbeddedCurvePoint& q,
110{
111 uint32_t execution_clk = execution_id_manager.get_execution_id();
112 uint16_t space_id = memory.get_space_id();
113
114 try {
115 // The resulting EmbeddedCurvePoint is (x, y), stored at dst_address and dst_address + 1 respectively.
116 // Therefore, the maximum address that needs to be written to is dst_address + 1.
117 uint64_t max_write_address = static_cast<uint64_t>(dst_address) + 1;
118 // Emits GreaterThanEvent, see #[CHECK_DST_ADDR_IN_RANGE] in ecc_mem.pil.
119 if (gt.gt(max_write_address, AVM_HIGHEST_MEM_ADDRESS)) {
120 throw InternalEccException("dst address out of range");
121 }
122
123 if (!p.on_curve() || !q.on_curve()) {
124 throw InternalEccException("One of the points is not on the curve");
125 }
126
127 // Emits EccAddEvent, see #[INPUT_OUTPUT_ECC_ADD] in ecc_mem.pil.
128 EmbeddedCurvePoint result = add(p, q); // Cannot throw since we have checked on_curve().
129
130 // Emits MemoryEvents, see #[WRITE_MEM_i] for i = 0, 1 in ecc_mem.pil.
131 memory.set(dst_address, MemoryValue::from<FF>(result.x()));
132 memory.set(dst_address + 1, MemoryValue::from<FF>(result.y()));
133
134 add_memory_events.emit({ .execution_clk = execution_clk,
135 .space_id = space_id,
136 .p = p,
137 .q = q,
138 .result = result,
139 .dst_address = dst_address });
140 } catch (const InternalEccException& e) {
141 // Note this point is technically infinity, but we are treating it as 'empty' to corresponds
142 // to default values the circuit will assign. Since we have caught an InternalEccException,
143 // we have an error which the circuit should recognise and assign sel_should_exec == 0, so res will not be
144 // treated as inf.
146 add_memory_events.emit({ .execution_clk = execution_clk,
147 .space_id = space_id,
148 .p = p,
149 .q = q,
150 .result = res,
151 .dst_address = dst_address });
152 throw EccException("Add failed: " + std::string(e.what()));
153 }
154}
155
156} // namespace bb::avm2::simulation
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define AVM_HIGHEST_MEM_ADDRESS
constexpr const BaseField & x() const noexcept
constexpr const BaseField & y() const noexcept
constexpr bool on_curve() const noexcept
EventEmitterInterface< ScalarMulEvent > & scalar_mul_events
Definition ecc.hpp:40
EmbeddedCurvePoint add(const EmbeddedCurvePoint &p, const EmbeddedCurvePoint &q) override
Adds Grumpkin curve points P and Q and emits an EccAddEvent. Corresponds to the non-memory aware subt...
Definition ecc.cpp:30
EmbeddedCurvePoint scalar_mul(const EmbeddedCurvePoint &point, const FF &scalar) override
Performs scalar multiplication of an FF value with a Grumpkin curve point using the double and add al...
Definition ecc.cpp:55
EventEmitterInterface< EccAddMemoryEvent > & add_memory_events
Definition ecc.hpp:41
ExecutionIdManagerInterface & execution_id_manager
Definition ecc.hpp:44
EventEmitterInterface< EccAddEvent > & add_events
Definition ecc.hpp:39
virtual uint32_t get_execution_id() const =0
AVM range check gadget for witness generation.
AvmFlavorSettings::FF FF
Definition field.hpp:10
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
uint32_t MemoryAddress
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13