Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc.cpp
Go to the documentation of this file.
6
7namespace bb::avm2::simulation {
8
9namespace {
10
11class InternalEccException : public std::runtime_error {
12 public:
13 using std::runtime_error::runtime_error; // Inherit the constructor.
14};
15
16} // namespace
17
18// This function assumes that the points p and q are on the curve. You should only
19// use this function internally if you can guarantee this. Otherwise it is called
20// via the opcode ECADD, see the overloaded function Ecc::add (which performs the curve check)
22{
23 // Check if points are on the curve. These will throw an unexpected exception if they fail.
24 BB_ASSERT(p.on_curve(), "Point p is not on the curve");
25 BB_ASSERT(q.on_curve(), "Point q is not on the curve");
26 // Check if the points are normalized (infinity points must be (0, 0, true))
27 if (p.is_infinity()) {
28 BB_ASSERT((p.x() == 0) && (p.y() == 0), "Point p is not normalized");
29 }
30 if (q.is_infinity()) {
31 BB_ASSERT((q.x() == 0) && (q.y() == 0), "Point q is not normalized");
32 }
33
34 EmbeddedCurvePoint result = p + q;
35 add_events.emit({ .p = p, .q = q, .result = result });
36 return result;
37}
38
39// This function assumes that the point is on the curve. As this should only be used internally,
40// it is treated as a catastrophic failure if the point is not on the curve.
42{
43 // This is bad - the scalar mul circuit assumes that the point is on the curve.
44 // This will throw an unexpected exception if it fails.
45 BB_ASSERT(point.on_curve(), "Point must be on the curve for scalar multiplication");
46
47 auto intermediate_states = std::vector<ScalarMulIntermediateState>(254);
48 auto bits = to_radix.to_le_bits(scalar, 254).first;
49
50 // Normalize input infinity point.
51 EmbeddedCurvePoint point_input = point.is_infinity() ? EmbeddedCurvePoint::infinity() : point;
52
53 // First iteration does conditional assignment instead of addition
54 EmbeddedCurvePoint temp = point_input;
55 bool bit = bits[0];
56
58 intermediate_states[0] = { result, temp, bit };
59
60 for (size_t i = 1; i < 254; i++) {
61 bit = bits[i];
62 temp = add(temp, temp);
63
64 if (bit) {
65 result = add(result, temp);
66 }
67 intermediate_states[i] = { result, temp, bit };
68 }
69 scalar_mul_events.emit({ .point = point_input,
70 .scalar = scalar,
71 .intermediate_states = std::move(intermediate_states),
72 .result = result });
73 return result;
74}
75
77 const EmbeddedCurvePoint& p,
78 const EmbeddedCurvePoint& q,
80{
81 uint32_t execution_clk = execution_id_manager.get_execution_id();
82 uint16_t space_id = memory.get_space_id();
83
84 try {
85 // The resulting EmbeddedCurvePoint is a triple of (x, y, is_infinity).
86 // The x and y coordinates are stored at dst_address and dst_address + 1 respectively,
87 // and the is_infinity flag is stored at dst_address + 2.
88 // Therefore, the maximum address that needs to be written to is dst_address + 2.
89 uint64_t max_write_address = static_cast<uint64_t>(dst_address) + 2;
90 if (gt.gt(max_write_address, AVM_HIGHEST_MEM_ADDRESS)) {
91 throw InternalEccException("dst address out of range");
92 }
93
94 if (!p.on_curve() || !q.on_curve()) {
95 throw InternalEccException("One of the points is not on the curve");
96 }
97
98 // Normalize input infinity points.
101
102 EmbeddedCurvePoint result = add(p_input, q_input); // Cannot throw.
103
104 memory.set(dst_address, MemoryValue::from<FF>(result.x()));
105 memory.set(dst_address + 1, MemoryValue::from<FF>(result.y()));
106 memory.set(dst_address + 2, MemoryValue::from<uint1_t>(result.is_infinity() ? 1 : 0));
107
108 add_memory_events.emit({ .execution_clk = execution_clk,
109 .space_id = space_id,
110 .p = p,
111 .q = q,
112 .result = result,
113 .dst_address = dst_address });
114 } catch (const InternalEccException& e) {
115 // Note this point is not on the curve, but corresponds
116 // to default values the circuit will assign.
117 EmbeddedCurvePoint res = EmbeddedCurvePoint(0, 0, false);
118 add_memory_events.emit({ .execution_clk = execution_clk,
119 .space_id = space_id,
120 .p = p,
121 .q = q,
122 .result = res,
123 .dst_address = dst_address });
124 throw EccException("Add failed: " + std::string(e.what()));
125 }
126}
127
128} // namespace bb::avm2::simulation
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define AVM_HIGHEST_MEM_ADDRESS
constexpr bool is_infinity() const noexcept
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
Definition ecc.cpp:21
EmbeddedCurvePoint scalar_mul(const EmbeddedCurvePoint &point, const FF &scalar) override
Definition ecc.cpp:41
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
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
uint32_t MemoryAddress
AvmFlavorSettings::FF FF
Definition field.hpp:10
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13