revm_precompile/bls12_381_const.rs
1//! Constants specifying the precompile addresses for each precompile in EIP-2537
2
3use crate::u64_to_address;
4use primitives::Address;
5
6/// G1 add precompile address
7pub const G1_ADD_ADDRESS: Address = u64_to_address(0x0b);
8/// G1 msm precompile address
9pub const G1_MSM_ADDRESS: Address = u64_to_address(0x0c);
10/// G2 add precompile address
11pub const G2_ADD_ADDRESS: Address = u64_to_address(0x0d);
12/// G2 msm precompile address
13pub const G2_MSM_ADDRESS: Address = u64_to_address(0x0e);
14/// Pairing precompile address
15pub const PAIRING_ADDRESS: Address = u64_to_address(0x0f);
16/// Map fp to g1 precompile address
17pub const MAP_FP_TO_G1_ADDRESS: Address = u64_to_address(0x10);
18/// Map fp2 to g2 precompile address
19pub const MAP_FP2_TO_G2_ADDRESS: Address = u64_to_address(0x11);
20
21/// G1_ADD_BASE_GAS_FEE specifies the amount of gas needed
22/// to perform the G1_ADD precompile.
23pub const G1_ADD_BASE_GAS_FEE: u64 = 375;
24/// G1_MSM_BASE_GAS_FEE specifies the base amount of gas needed to
25/// perform the G1_MSM precompile.
26///
27/// The cost to do an MSM is determined by the formula:
28/// (k * G1_MSM_BASE_GAS_FEE * DISCOUNT\[k\]) // MSM_MULTIPLIER
29/// where k is the number of point-scalar pairs.
30///
31/// Note: If one wants to do a G1 scalar multiplication, they would call
32/// this precompile with a single point and a scalar.
33pub const G1_MSM_BASE_GAS_FEE: u64 = 12000;
34/// MSM_MULTIPLIER specifies the division constant that is used to determine the
35/// gas needed to compute an MSM.
36///
37/// The cost to do an MSM is determined by the formula:
38/// (k * MSM_BASE_GAS_FEE * DISCOUNT\[k\]) // MSM_MULTIPLIER
39/// where k is the number of point-scalar pairs.
40///
41/// Note: If `k` is more than the size of the discount table, then
42/// the last value in the discount table is chosen.
43pub const MSM_MULTIPLIER: u64 = 1000;
44/// MAP_FP_TO_G1_BASE_GAS_FEE specifies the amount of gas needed
45/// to perform the MAP_FP_TO_G1 precompile.
46pub const MAP_FP_TO_G1_BASE_GAS_FEE: u64 = 5500;
47/// MAP_FP2_TO_G2_BASE_GAS_FEE specifies the amount of gas needed
48/// to perform the MAP_FP2_TO_G2 precompile.
49pub const MAP_FP2_TO_G2_BASE_GAS_FEE: u64 = 23800;
50/// G2_ADD_BASE_GAS_FEE specifies the amount of gas needed
51/// to perform the G2_ADD precompile.
52pub const G2_ADD_BASE_GAS_FEE: u64 = 600;
53/// G2_MSM_BASE_GAS_FEE specifies the base amount of gas needed to
54/// perform the G2_MSM precompile.
55///
56/// The cost to do an MSM is determined by the formula:
57/// (k * G2_MSM_BASE_GAS_FEE * DISCOUNT\[k\]) // MSM_MULTIPLIER
58/// where k is the number of point-scalar pairs.
59///
60/// Note: If one wants to do a G2 scalar multiplication, they would call
61/// this precompile with a single point and a scalar.
62pub const G2_MSM_BASE_GAS_FEE: u64 = 22500;
63/// PAIRING_OFFSET_BASE specifies the y-intercept for the linear expression to determine
64/// the amount of gas needed to perform a pairing.
65///
66/// The cost to do a pairing is determined by the formula:
67/// cost = PAIRING_MULTIPLIER_BASE * number_of_pairs + PAIRING_OFFSET_BASE
68pub const PAIRING_OFFSET_BASE: u64 = 37700;
69/// PAIRING_MULTIPLIER_BASE specifies the slope/gradient for the linear expression to determine
70/// the amount of gas needed to perform a pairing.
71///
72/// The cost to do a pairing is determined by the formula:
73/// PAIRING_MULTIPLIER_BASE * number_of_pairs + PAIRING_OFFSET_BASE
74pub const PAIRING_MULTIPLIER_BASE: u64 = 32600;
75
76/// Discounts table for G1 MSM as a vector of pairs `[k, discount]`.
77pub static DISCOUNT_TABLE_G1_MSM: [u16; 128] = [
78 1000, 949, 848, 797, 764, 750, 738, 728, 719, 712, 705, 698, 692, 687, 682, 677, 673, 669, 665,
79 661, 658, 654, 651, 648, 645, 642, 640, 637, 635, 632, 630, 627, 625, 623, 621, 619, 617, 615,
80 613, 611, 609, 608, 606, 604, 603, 601, 599, 598, 596, 595, 593, 592, 591, 589, 588, 586, 585,
81 584, 582, 581, 580, 579, 577, 576, 575, 574, 573, 572, 570, 569, 568, 567, 566, 565, 564, 563,
82 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 547, 546, 545,
83 544, 543, 542, 541, 540, 540, 539, 538, 537, 536, 536, 535, 534, 533, 532, 532, 531, 530, 529,
84 528, 528, 527, 526, 525, 525, 524, 523, 522, 522, 521, 520, 520, 519,
85];
86/// Discounts table for G2 MSM as a vector of pairs `[k, discount]`:
87pub static DISCOUNT_TABLE_G2_MSM: [u16; 128] = [
88 1000, 1000, 923, 884, 855, 832, 812, 796, 782, 770, 759, 749, 740, 732, 724, 717, 711, 704,
89 699, 693, 688, 683, 679, 674, 670, 666, 663, 659, 655, 652, 649, 646, 643, 640, 637, 634, 632,
90 629, 627, 624, 622, 620, 618, 615, 613, 611, 609, 607, 606, 604, 602, 600, 598, 597, 595, 593,
91 592, 590, 589, 587, 586, 584, 583, 582, 580, 579, 578, 576, 575, 574, 573, 571, 570, 569, 568,
92 567, 566, 565, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 552, 551, 550, 549,
93 548, 547, 546, 545, 545, 544, 543, 542, 541, 541, 540, 539, 538, 537, 537, 536, 535, 535, 534,
94 533, 532, 532, 531, 530, 530, 529, 528, 528, 527, 526, 526, 525, 524, 524,
95];
96
97// Constants related to the bls12-381 precompile inputs and outputs
98
99/// FP_LENGTH specifies the number of bytes needed to represent an
100/// Fp element. This is an element in the base field of BLS12-381.
101///
102/// Note: The base field is used to define G1 and G2 elements.
103pub const FP_LENGTH: usize = 48;
104/// PADDED_FP_LENGTH specifies the number of bytes that the EVM will use
105/// to represent an Fp element according to EIP-2537.
106///
107/// Note: We only need FP_LENGTH number of bytes to represent it,
108/// but we pad the byte representation to be 32 byte aligned as specified in EIP 2537.
109pub const PADDED_FP_LENGTH: usize = 64;
110
111/// G1_LENGTH specifies the number of bytes needed to represent a G1 element.
112///
113/// Note: A G1 element contains 2 Fp elements.
114pub const G1_LENGTH: usize = 2 * FP_LENGTH;
115/// PADDED_G1_LENGTH specifies the number of bytes that the EVM will use to represent
116/// a G1 element according to padding rules specified in EIP-2537.
117pub const PADDED_G1_LENGTH: usize = 2 * PADDED_FP_LENGTH;
118
119/// PADDED_FP2_LENGTH specifies the number of bytes that the EVM will use to represent
120/// a Fp^2 element according to the padding rules specified in EIP-2537.
121///
122/// Note: This is the quadratic extension of Fp, and by definition
123/// means we need 2 Fp elements.
124pub const PADDED_FP2_LENGTH: usize = 2 * PADDED_FP_LENGTH;
125
126/// SCALAR_LENGTH specifies the number of bytes needed to represent an Fr element.
127/// This is an element in the scalar field of BLS12-381.
128///
129/// Note: Since it is already 32 byte aligned, there is no padded version of this constant.
130pub const SCALAR_LENGTH: usize = 32;
131/// SCALAR_LENGTH_BITS specifies the number of bits needed to represent an Fr element.
132/// This is an element in the scalar field of BLS12-381.
133pub const SCALAR_LENGTH_BITS: usize = SCALAR_LENGTH * 8;
134
135/// G1_ADD_INPUT_LENGTH specifies the number of bytes that the input to G1ADD
136/// must use.
137///
138/// Note: The input to the G1 addition precompile is 2 G1 elements.
139pub const G1_ADD_INPUT_LENGTH: usize = 2 * PADDED_G1_LENGTH;
140/// G1_MSM_INPUT_LENGTH specifies the number of bytes that each MSM input pair should have.
141///
142/// Note: An MSM pair is a G1 element and a scalar. The input to the MSM precompile will have `n`
143/// of these pairs.
144pub const G1_MSM_INPUT_LENGTH: usize = PADDED_G1_LENGTH + SCALAR_LENGTH;
145
146/// PADDED_G2_LENGTH specifies the number of bytes that the EVM will use to represent
147/// a G2 element.
148///
149/// Note: A G2 element can be represented using 2 Fp^2 elements.
150pub const PADDED_G2_LENGTH: usize = 2 * PADDED_FP2_LENGTH;
151
152/// G2_ADD_INPUT_LENGTH specifies the number of bytes that the input to G2ADD
153/// must occupy.
154///
155/// Note: The input to the G2 addition precompile is 2 G2 elements.
156pub const G2_ADD_INPUT_LENGTH: usize = 2 * PADDED_G2_LENGTH;
157/// G2_MSM_INPUT_LENGTH specifies the number of bytes that each MSM input pair should have.
158///
159/// Note: An MSM pair is a G2 element and a scalar. The input to the MSM will have `n`
160/// of these pairs.
161pub const G2_MSM_INPUT_LENGTH: usize = PADDED_G2_LENGTH + SCALAR_LENGTH;
162
163/// PAIRING_INPUT_LENGTH specifies the number of bytes that each Pairing input pair should have.
164///
165/// Note: An Pairing input-pair is a G2 element and a G1 element. The input to the Pairing will have `n`
166/// of these pairs.
167pub const PAIRING_INPUT_LENGTH: usize = PADDED_G1_LENGTH + PADDED_G2_LENGTH;
168
169/// FP_PAD_BY specifies the number of bytes that an FP_ELEMENT is padded by to make it 32 byte aligned.
170///
171/// Note: This should be equal to PADDED_FP_LENGTH - FP_LENGTH.
172pub const FP_PAD_BY: usize = 16;
173
174#[test]
175fn check_discount_table_invariant_holds() {
176 // Currently EIP-2537 specifies the cost for a G1/G2 scalar multiplication in two places
177 // in two different ways.
178 //
179 // First it explicitly says that G1 Multiplication costs 12000 Gas and G2 Multiplication costs 22500.
180 //
181 // Then it implies the above constants for G1_MSM and G2_MSM via the MSM formula:
182 // MSM_COST = k * MSM_BASE_GAS_FEE * DISCOUNT[k-1] // MSM_MULTIPLIER
183 //
184 // Note that when the MSM has only one point-scalar pair (scalar multiplication), we get:
185 // MSM_COST = MSM_BASE_GAS_FEE * DISCOUNT[0] // MSM_MULTIPLIER
186 // (This is because k==1)
187 //
188 // The 0th entry in the discount table for G1_MSM and G2_MSM is equal to MSM_MULTIPLIER
189 // so for k==1, MSM_COST = MSM_BASE_GAS_FEE
190 //
191 // For G1, MSM_BASE_GAS_FEE matches 12000 and for G2 MSM_BASE_GAS_FEE matches 22500.
192 //
193 // In this test, we check that this invariant does not change by asserting that the first value
194 // in the discount table is equal to the MULTIPLIER.
195 assert_eq!(DISCOUNT_TABLE_G1_MSM[0], MSM_MULTIPLIER as u16);
196 assert_eq!(DISCOUNT_TABLE_G2_MSM[0], MSM_MULTIPLIER as u16);
197 // Note: We could also more robustly check this by defining the G1/G2 Scalar multiplication constants
198 // from the EIP and checking that they equal to the value computed by `msm_required_gas` when k==1
199}