ethereum.forks.constantinople.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(500)) | 
| 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(40000)) | 
| 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(80000 * (len(data) // 192) + 100000)) | 
| 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() |