ethereum.prague.vm.precompiled_contracts.bls12_381.bls12_381_g1

Ethereum Virtual Machine (EVM) BLS12 381 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. contents:: Table of Contents :backlinks: none :local:

Introduction

Implementation of pre-compiles in G1 (curve over base prime field).

LENGTH_PER_PAIR

41
LENGTH_PER_PAIR = 160

bls12_g1_add

The bls12_381 G1 point addition precompile.

Parameters

evm : The current EVM frame.

Raises

InvalidParameter If the input length is invalid.

def bls12_g1_add(evm: Evm) -> None:
45
    """
46
    The bls12_381 G1 point addition precompile.
47
48
    Parameters
49
    ----------
50
    evm :
51
        The current EVM frame.
52
53
    Raises
54
    ------
55
    InvalidParameter
56
        If the input length is invalid.
57
    """
58
    data = evm.message.data
59
    if len(data) != 256:
60
        raise InvalidParameter("Invalid Input Length")
61
62
    # GAS
63
    charge_gas(evm, Uint(GAS_BLS_G1_ADD))
64
65
    # OPERATION
66
    p1 = bytes_to_g1(buffer_read(data, U256(0), U256(128)))
67
    p2 = bytes_to_g1(buffer_read(data, U256(128), U256(128)))
68
69
    result = bls12_add(p1, p2)
70
71
    evm.output = g1_to_bytes(result)

bls12_g1_msm

The bls12_381 G1 multi-scalar multiplication precompile. Note: This uses the naive approach to multi-scalar multiplication which is not suitably optimized for production clients. Clients are required to implement a more efficient algorithm such as the Pippenger algorithm.

Parameters

evm : The current EVM frame.

Raises

InvalidParameter If the input length is invalid.

def bls12_g1_msm(evm: Evm) -> None:
75
    """
76
    The bls12_381 G1 multi-scalar multiplication precompile.
77
    Note: This uses the naive approach to multi-scalar multiplication
78
    which is not suitably optimized for production clients. Clients are
79
    required to implement a more efficient algorithm such as the Pippenger
80
    algorithm.
81
82
    Parameters
83
    ----------
84
    evm :
85
        The current EVM frame.
86
87
    Raises
88
    ------
89
    InvalidParameter
90
        If the input length is invalid.
91
    """
92
    data = evm.message.data
93
    if len(data) == 0 or len(data) % LENGTH_PER_PAIR != 0:
94
        raise InvalidParameter("Invalid Input Length")
95
96
    # GAS
97
    k = len(data) // LENGTH_PER_PAIR
98
    if k <= 128:
99
        discount = Uint(G1_K_DISCOUNT[k - 1])
100
    else:
101
        discount = Uint(G1_MAX_DISCOUNT)
102
103
    gas_cost = Uint(k) * GAS_BLS_G1_MUL * discount // MULTIPLIER
104
    charge_gas(evm, gas_cost)
105
106
    # OPERATION
107
    for i in range(k):
108
        start_index = i * LENGTH_PER_PAIR
109
        end_index = start_index + LENGTH_PER_PAIR
110
111
        p, m = decode_g1_scalar_pair(data[start_index:end_index])
112
        product = bls12_multiply(p, m)
113
114
        if i == 0:
115
            result = product
116
        else:
117
            result = bls12_add(result, product)
118
119
    evm.output = g1_to_bytes(result)

bls12_map_fp_to_g1

Precompile to map field element to G1.

Parameters

evm : The current EVM frame.

Raises

InvalidParameter If the input length is invalid.

def bls12_map_fp_to_g1(evm: Evm) -> None:
123
    """
124
    Precompile to map field element to G1.
125
126
    Parameters
127
    ----------
128
    evm :
129
        The current EVM frame.
130
131
    Raises
132
    ------
133
    InvalidParameter
134
        If the input length is invalid.
135
    """
136
    data = evm.message.data
137
    if len(data) != 64:
138
        raise InvalidParameter("Invalid Input Length")
139
140
    # GAS
141
    charge_gas(evm, Uint(GAS_BLS_G1_MAP))
142
143
    # OPERATION
144
    fp = int.from_bytes(data, "big")
145
    if fp >= FQ.field_modulus:
146
        raise InvalidParameter("coordinate >= field modulus")
147
148
    g1_optimized_3d = clear_cofactor_G1(map_to_curve_G1(FQ(fp)))
149
    evm.output = g1_to_bytes(g1_optimized_3d)