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()