ethereum.berlin.vm.precompiled_contracts.alt_bn128ethereum.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 | if len(data) != 64: |
59 | raise InvalidParameter("Input should be 64 bytes long") |
60 | |
61 | x_bytes = buffer_read(data, U256(0), U256(32)) |
62 | x = int(U256.from_be_bytes(x_bytes)) |
63 | y_bytes = buffer_read(data, U256(32), U256(32)) |
64 | y = int(U256.from_be_bytes(y_bytes)) |
65 | |
66 | if x >= field_modulus: |
67 | raise InvalidParameter("Invalid field element") |
68 | if y >= field_modulus: |
69 | raise InvalidParameter("Invalid field element") |
70 | |
71 | z = 1 |
72 | if x == 0 and y == 0: |
73 | z = 0 |
74 | |
75 | point = (FQ(x), FQ(y), FQ(z)) |
76 | |
77 | # Check if the point is on the curve |
78 | if not is_on_curve(point, b): |
79 | raise InvalidParameter("Point is not on curve") |
80 | |
81 | 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]:
85 | """ |
---|---|
86 | Decode 128 bytes to a G2 point. |
87 |
|
88 | Parameters |
89 | ---------- |
90 | data : |
91 | The bytes data to decode. |
92 |
|
93 | Returns |
94 | ------- |
95 | point : Point2D |
96 | A point on the curve. |
97 |
|
98 | Raises |
99 | ------ |
100 | InvalidParameter |
101 | Either a field element is invalid or the point is not on the curve. |
102 | """ |
103 | if len(data) != 128: |
104 | raise InvalidParameter("G2 should be 128 bytes long") |
105 | |
106 | x0_bytes = buffer_read(data, U256(0), U256(32)) |
107 | x0 = int(U256.from_be_bytes(x0_bytes)) |
108 | x1_bytes = buffer_read(data, U256(32), U256(32)) |
109 | x1 = int(U256.from_be_bytes(x1_bytes)) |
110 | |
111 | y0_bytes = buffer_read(data, U256(64), U256(32)) |
112 | y0 = int(U256.from_be_bytes(y0_bytes)) |
113 | y1_bytes = buffer_read(data, U256(96), U256(32)) |
114 | y1 = int(U256.from_be_bytes(y1_bytes)) |
115 | |
116 | if x0 >= field_modulus or x1 >= field_modulus: |
117 | raise InvalidParameter("Invalid field element") |
118 | if y0 >= field_modulus or y1 >= field_modulus: |
119 | raise InvalidParameter("Invalid field element") |
120 | |
121 | x = FQ2((x1, x0)) |
122 | y = FQ2((y1, y0)) |
123 | |
124 | z = (1, 0) |
125 | if x == FQ2((0, 0)) and y == FQ2((0, 0)): |
126 | z = (0, 0) |
127 | |
128 | point = (x, y, FQ2(z)) |
129 | |
130 | # Check if the point is on the curve |
131 | if not is_on_curve(point, b2): |
132 | raise InvalidParameter("Point is not on curve") |
133 | |
134 | return point |
alt_bn128_add
The ALT_BN128 addition precompiled contract.
Parameters
evm : The current EVM frame.
def alt_bn128_add(evm: Evm) -> None:
138 | """ |
---|---|
139 | The ALT_BN128 addition precompiled contract. |
140 |
|
141 | Parameters |
142 | ---------- |
143 | evm : |
144 | The current EVM frame. |
145 | """ |
146 | data = evm.message.data |
147 | |
148 | # GAS |
149 | charge_gas(evm, Uint(150)) |
150 | |
151 | # OPERATION |
152 | try: |
153 | p0 = bytes_to_g1(buffer_read(data, U256(0), U256(64))) |
154 | p1 = bytes_to_g1(buffer_read(data, U256(64), U256(64))) |
155 | except InvalidParameter as e: |
156 | raise OutOfGasError from e |
157 | |
158 | p = add(p0, p1) |
159 | x, y = normalize(p) |
160 | |
161 | 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:
165 | """ |
---|---|
166 | The ALT_BN128 multiplication precompiled contract. |
167 |
|
168 | Parameters |
169 | ---------- |
170 | evm : |
171 | The current EVM frame. |
172 | """ |
173 | data = evm.message.data |
174 | |
175 | # GAS |
176 | charge_gas(evm, Uint(6000)) |
177 | |
178 | # OPERATION |
179 | try: |
180 | p0 = bytes_to_g1(buffer_read(data, U256(0), U256(64))) |
181 | except InvalidParameter as e: |
182 | raise OutOfGasError from e |
183 | n = int(U256.from_be_bytes(buffer_read(data, U256(64), U256(32)))) |
184 | |
185 | p = multiply(p0, n) |
186 | x, y = normalize(p) |
187 | |
188 | 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:
192 | """ |
---|---|
193 | The ALT_BN128 pairing check precompiled contract. |
194 |
|
195 | Parameters |
196 | ---------- |
197 | evm : |
198 | The current EVM frame. |
199 | """ |
200 | data = evm.message.data |
201 | |
202 | # GAS |
203 | charge_gas(evm, Uint(34000 * (len(data) // 192) + 45000)) |
204 | |
205 | # OPERATION |
206 | if len(data) % 192 != 0: |
207 | raise OutOfGasError |
208 | result = FQ12.one() |
209 | for i in range(len(data) // 192): |
210 | try: |
211 | p = bytes_to_g1(buffer_read(data, U256(192 * i), U256(64))) |
212 | q = bytes_to_g2(buffer_read(data, U256(192 * i + 64), U256(128))) |
213 | except InvalidParameter as e: |
214 | raise OutOfGasError from e |
215 | if not is_inf(multiply(p, curve_order)): |
216 | raise OutOfGasError |
217 | if not is_inf(multiply(q, curve_order)): |
218 | raise OutOfGasError |
219 |
|
220 | result *= pairing(q, p) |
221 | |
222 | if result == FQ12.one(): |
223 | evm.output = U256(1).to_be_bytes32() |
224 | else: |
225 | evm.output = U256(0).to_be_bytes32() |