ethereum.forks.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
40 | 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:
44 | """ |
---|---|
45 | The bls12_381 G1 point addition precompile. |
46 |
|
47 | Parameters |
48 | ---------- |
49 | evm : |
50 | The current EVM frame. |
51 |
|
52 | Raises |
53 | ------ |
54 | InvalidParameter |
55 | If the input length is invalid. |
56 |
|
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 | """ |
93 | data = evm.message.data |
94 | if len(data) == 0 or len(data) % LENGTH_PER_PAIR != 0: |
95 | raise InvalidParameter("Invalid Input Length") |
96 | |
97 | # GAS |
98 | k = len(data) // LENGTH_PER_PAIR |
99 | if k <= 128: |
100 | discount = Uint(G1_K_DISCOUNT[k - 1]) |
101 | else: |
102 | discount = Uint(G1_MAX_DISCOUNT) |
103 | |
104 | gas_cost = Uint(k) * GAS_BLS_G1_MUL * discount // MULTIPLIER |
105 | charge_gas(evm, gas_cost) |
106 | |
107 | # OPERATION |
108 | for i in range(k): |
109 | start_index = i * LENGTH_PER_PAIR |
110 | end_index = start_index + LENGTH_PER_PAIR |
111 |
|
112 | p, m = decode_g1_scalar_pair(data[start_index:end_index]) |
113 | product = bls12_multiply(p, m) |
114 |
|
115 | if i == 0: |
116 | result = product |
117 | else: |
118 | result = bls12_add(result, product) |
119 | |
120 | 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:
124 | """ |
---|---|
125 | Precompile to map field element to G1. |
126 |
|
127 | Parameters |
128 | ---------- |
129 | evm : |
130 | The current EVM frame. |
131 |
|
132 | Raises |
133 | ------ |
134 | InvalidParameter |
135 | If the input length is invalid. |
136 |
|
137 | """ |
138 | data = evm.message.data |
139 | if len(data) != 64: |
140 | raise InvalidParameter("Invalid Input Length") |
141 | |
142 | # GAS |
143 | charge_gas(evm, Uint(GAS_BLS_G1_MAP)) |
144 | |
145 | # OPERATION |
146 | fp = int.from_bytes(data, "big") |
147 | if fp >= FQ.field_modulus: |
148 | raise InvalidParameter("coordinate >= field modulus") |
149 | |
150 | g1_optimized_3d = clear_cofactor_G1(map_to_curve_G1(FQ(fp))) |
151 | evm.output = g1_to_bytes(g1_optimized_3d) |