1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
use std::borrow::Cow;
use std::fmt;
use crate::{Precompile, PrecompileSpecId};
/// Precompile with address and function.
/// Unique precompile identifier.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum PrecompileId {
/// Elliptic curve digital signature algorithm (ECDSA) public key recovery function.
EcRec,
/// SHA2-256 hash function.
Sha256,
/// RIPEMD-160 hash function.
Ripemd160,
/// Identity precompile.
Identity,
/// Arbitrary-precision exponentiation under modulo.
ModExp,
/// Point addition (ADD) on the elliptic curve 'alt_bn128'.
Bn254Add,
/// Scalar multiplication (MUL) on the elliptic curve 'alt_bn128'.
Bn254Mul,
/// Bilinear function on groups on the elliptic curve 'alt_bn128'.
Bn254Pairing,
/// Compression function F used in the BLAKE2 cryptographic hashing algorithm.
Blake2F,
/// Verify p(z) = y given commitment that corresponds to the polynomial p(x) and a KZG proof. Also verify that the provided commitment matches the provided versioned_hash.
KzgPointEvaluation,
/// Point addition in G1 (curve over base prime field).
Bls12G1Add,
/// Multi-scalar-multiplication (MSM) in G1 (curve over base prime field).
Bls12G1Msm,
/// Point addition in G2 (curve over quadratic extension of the base prime field).
Bls12G2Add,
/// Multi-scalar-multiplication (MSM) in G2 (curve over quadratic extension of the base prime field).
Bls12G2Msm,
/// Pairing operations between a set of pairs of (G1, G2) points.
Bls12Pairing,
/// Base field element mapping into the G1 point.
Bls12MapFpToGp1,
/// Extension field element mapping into the G2 point.
Bls12MapFp2ToGp2,
/// ECDSA signature verification over the secp256r1 elliptic curve (also known as P-256 or prime256v1).
P256Verify,
/// Custom precompile identifier.
Custom(Cow<'static, str>),
}
impl PrecompileId {
/// Create new custom precompile ID.
pub fn custom<I>(id: I) -> Self
where
I: Into<Cow<'static, str>>,
{
Self::Custom(id.into())
}
/// Returns the name of the precompile as defined in EIP-7910.
pub fn name(&self) -> &str {
match self {
Self::EcRec => "ECREC",
Self::Sha256 => "SHA256",
Self::Ripemd160 => "RIPEMD160",
Self::Identity => "ID",
Self::ModExp => "MODEXP",
Self::Bn254Add => "BN254_ADD",
Self::Bn254Mul => "BN254_MUL",
Self::Bn254Pairing => "BN254_PAIRING",
Self::Blake2F => "BLAKE2F",
Self::KzgPointEvaluation => "KZG_POINT_EVALUATION",
Self::Bls12G1Add => "BLS12_G1ADD",
Self::Bls12G1Msm => "BLS12_G1MSM",
Self::Bls12G2Add => "BLS12_G2ADD",
Self::Bls12G2Msm => "BLS12_G2MSM",
Self::Bls12Pairing => "BLS12_PAIRING_CHECK",
Self::Bls12MapFpToGp1 => "BLS12_MAP_FP_TO_G1",
Self::Bls12MapFp2ToGp2 => "BLS12_MAP_FP2_TO_G2",
Self::P256Verify => "P256VERIFY",
Self::Custom(a) => a.as_ref(),
}
}
/// Returns the precompile function for the given spec.
///
/// If case of [`PrecompileId::Custom`] it will return [`None`].
///
/// For case where precompile was still not introduced in the spec,
/// it will return [`Some`] with fork closest to activation.
pub fn precompile(&self, spec: PrecompileSpecId) -> Option<Precompile> {
use PrecompileSpecId::*;
let precompile = match self {
Self::EcRec => crate::secp256k1::ECRECOVER,
Self::Sha256 => crate::hash::SHA256,
Self::Ripemd160 => crate::hash::RIPEMD160,
Self::Identity => crate::identity::FUN,
Self::ModExp => {
// ModExp changes gas calculation based on spec
if spec < BERLIN {
crate::modexp::BYZANTIUM
} else if spec < OSAKA {
crate::modexp::BERLIN
} else {
crate::modexp::OSAKA
}
}
Self::Bn254Add => {
// BN254 add - gas cost changes in Istanbul
if spec < ISTANBUL {
crate::bn254::add::BYZANTIUM
} else {
crate::bn254::add::ISTANBUL
}
}
Self::Bn254Mul => {
// BN254 mul - gas cost changes in Istanbul
if spec < ISTANBUL {
crate::bn254::mul::BYZANTIUM
} else {
crate::bn254::mul::ISTANBUL
}
}
Self::Bn254Pairing => {
// BN254 pairing - gas cost changes in Istanbul
if spec < ISTANBUL {
crate::bn254::pair::BYZANTIUM
} else {
crate::bn254::pair::ISTANBUL
}
}
Self::Blake2F => crate::blake2::FUN,
Self::KzgPointEvaluation => crate::kzg_point_evaluation::POINT_EVALUATION,
Self::Bls12G1Add => crate::bls12_381::g1_add::PRECOMPILE,
Self::Bls12G1Msm => crate::bls12_381::g1_msm::PRECOMPILE,
Self::Bls12G2Add => crate::bls12_381::g2_add::PRECOMPILE,
Self::Bls12G2Msm => crate::bls12_381::g2_msm::PRECOMPILE,
Self::Bls12Pairing => crate::bls12_381::pairing::PRECOMPILE,
Self::Bls12MapFpToGp1 => crate::bls12_381::map_fp_to_g1::PRECOMPILE,
Self::Bls12MapFp2ToGp2 => crate::bls12_381::map_fp2_to_g2::PRECOMPILE,
Self::P256Verify => {
// P256 verify - gas cost changes in Osaka
if spec < OSAKA {
crate::secp256r1::P256VERIFY
} else {
crate::secp256r1::P256VERIFY_OSAKA
}
}
Self::Custom(_) => return None,
};
Some(precompile)
}
}
impl fmt::Display for PrecompileId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}