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