ethereum.forks.london.vm.precompiled_contracts.alt_bn128
Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS.
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Implementation of the ALT_BN128 precompiled contracts.
bytes_to_g1
Decode 64 bytes to a point on the curve.
Parameters
data : The bytes data to decode.
Returns
point : Point3D A point on the curve.
Raises
InvalidParameter Either a field element is invalid or the point is not on the curve.
def bytes_to_g1(data: Bytes) -> Point3D[FQ]:
40 | """ |
---|---|
41 | Decode 64 bytes to a point on the curve. |
42 |
|
43 | Parameters |
44 | ---------- |
45 | data : |
46 | The bytes data to decode. |
47 |
|
48 | Returns |
49 | ------- |
50 | point : Point3D |
51 | A point on the curve. |
52 |
|
53 | Raises |
54 | ------ |
55 | InvalidParameter |
56 | Either a field element is invalid or the point is not on the curve. |
57 |
|
58 | """ |
59 | if len(data) != 64: |
60 | raise InvalidParameter("Input should be 64 bytes long") |
61 | |
62 | x_bytes = buffer_read(data, U256(0), U256(32)) |
63 | x = int(U256.from_be_bytes(x_bytes)) |
64 | y_bytes = buffer_read(data, U256(32), U256(32)) |
65 | y = int(U256.from_be_bytes(y_bytes)) |
66 | |
67 | if x >= field_modulus: |
68 | raise InvalidParameter("Invalid field element") |
69 | if y >= field_modulus: |
70 | raise InvalidParameter("Invalid field element") |
71 | |
72 | z = 1 |
73 | if x == 0 and y == 0: |
74 | z = 0 |
75 | |
76 | point = (FQ(x), FQ(y), FQ(z)) |
77 | |
78 | # Check if the point is on the curve |
79 | if not is_on_curve(point, b): |
80 | raise InvalidParameter("Point is not on curve") |
81 | |
82 | return point |
bytes_to_g2
Decode 128 bytes to a G2 point.
Parameters
data : The bytes data to decode.
Returns
point : Point2D A point on the curve.
Raises
InvalidParameter Either a field element is invalid or the point is not on the curve.
def bytes_to_g2(data: Bytes) -> Point3D[FQ2]:
86 | """ |
---|---|
87 | Decode 128 bytes to a G2 point. |
88 |
|
89 | Parameters |
90 | ---------- |
91 | data : |
92 | The bytes data to decode. |
93 |
|
94 | Returns |
95 | ------- |
96 | point : Point2D |
97 | A point on the curve. |
98 |
|
99 | Raises |
100 | ------ |
101 | InvalidParameter |
102 | Either a field element is invalid or the point is not on the curve. |
103 |
|
104 | """ |
105 | if len(data) != 128: |
106 | raise InvalidParameter("G2 should be 128 bytes long") |
107 | |
108 | x0_bytes = buffer_read(data, U256(0), U256(32)) |
109 | x0 = int(U256.from_be_bytes(x0_bytes)) |
110 | x1_bytes = buffer_read(data, U256(32), U256(32)) |
111 | x1 = int(U256.from_be_bytes(x1_bytes)) |
112 | |
113 | y0_bytes = buffer_read(data, U256(64), U256(32)) |
114 | y0 = int(U256.from_be_bytes(y0_bytes)) |
115 | y1_bytes = buffer_read(data, U256(96), U256(32)) |
116 | y1 = int(U256.from_be_bytes(y1_bytes)) |
117 | |
118 | if x0 >= field_modulus or x1 >= field_modulus: |
119 | raise InvalidParameter("Invalid field element") |
120 | if y0 >= field_modulus or y1 >= field_modulus: |
121 | raise InvalidParameter("Invalid field element") |
122 | |
123 | x = FQ2((x1, x0)) |
124 | y = FQ2((y1, y0)) |
125 | |
126 | z = (1, 0) |
127 | if x == FQ2((0, 0)) and y == FQ2((0, 0)): |
128 | z = (0, 0) |
129 | |
130 | point = (x, y, FQ2(z)) |
131 | |
132 | # Check if the point is on the curve |
133 | if not is_on_curve(point, b2): |
134 | raise InvalidParameter("Point is not on curve") |
135 | |
136 | return point |
alt_bn128_add
The ALT_BN128 addition precompiled contract.
Parameters
evm : The current EVM frame.
def alt_bn128_add(evm: Evm) -> None:
140 | """ |
---|---|
141 | The ALT_BN128 addition precompiled contract. |
142 |
|
143 | Parameters |
144 | ---------- |
145 | evm : |
146 | The current EVM frame. |
147 |
|
148 | """ |
149 | data = evm.message.data |
150 | |
151 | # GAS |
152 | charge_gas(evm, Uint(150)) |
153 | |
154 | # OPERATION |
155 | try: |
156 | p0 = bytes_to_g1(buffer_read(data, U256(0), U256(64))) |
157 | p1 = bytes_to_g1(buffer_read(data, U256(64), U256(64))) |
158 | except InvalidParameter as e: |
159 | raise OutOfGasError from e |
160 | |
161 | p = add(p0, p1) |
162 | x, y = normalize(p) |
163 | |
164 | evm.output = Uint(x).to_be_bytes32() + Uint(y).to_be_bytes32() |
alt_bn128_mul
The ALT_BN128 multiplication precompiled contract.
Parameters
evm : The current EVM frame.
def alt_bn128_mul(evm: Evm) -> None:
168 | """ |
---|---|
169 | The ALT_BN128 multiplication precompiled contract. |
170 |
|
171 | Parameters |
172 | ---------- |
173 | evm : |
174 | The current EVM frame. |
175 |
|
176 | """ |
177 | data = evm.message.data |
178 | |
179 | # GAS |
180 | charge_gas(evm, Uint(6000)) |
181 | |
182 | # OPERATION |
183 | try: |
184 | p0 = bytes_to_g1(buffer_read(data, U256(0), U256(64))) |
185 | except InvalidParameter as e: |
186 | raise OutOfGasError from e |
187 | n = int(U256.from_be_bytes(buffer_read(data, U256(64), U256(32)))) |
188 | |
189 | p = multiply(p0, n) |
190 | x, y = normalize(p) |
191 | |
192 | evm.output = Uint(x).to_be_bytes32() + Uint(y).to_be_bytes32() |
alt_bn128_pairing_check
The ALT_BN128 pairing check precompiled contract.
Parameters
evm : The current EVM frame.
def alt_bn128_pairing_check(evm: Evm) -> None:
196 | """ |
---|---|
197 | The ALT_BN128 pairing check precompiled contract. |
198 |
|
199 | Parameters |
200 | ---------- |
201 | evm : |
202 | The current EVM frame. |
203 |
|
204 | """ |
205 | data = evm.message.data |
206 | |
207 | # GAS |
208 | charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) |
209 | |
210 | # OPERATION |
211 | if len(data) % 192 != 0: |
212 | raise OutOfGasError |
213 | result = FQ12.one() |
214 | for i in range(len(data) // 192): |
215 | try: |
216 | p = bytes_to_g1(buffer_read(data, U256(192 * i), U256(64))) |
217 | q = bytes_to_g2(buffer_read(data, U256(192 * i + 64), U256(128))) |
218 | except InvalidParameter as e: |
219 | raise OutOfGasError from e |
220 | if not is_inf(multiply(p, curve_order)): |
221 | raise OutOfGasError |
222 | if not is_inf(multiply(q, curve_order)): |
223 | raise OutOfGasError |
224 |
|
225 | result *= pairing(q, p) |
226 | |
227 | if result == FQ12.one(): |
228 | evm.output = U256(1).to_be_bytes32() |
229 | else: |
230 | evm.output = U256(0).to_be_bytes32() |