1use std::io::Write;
13use std::str::FromStr;
14
15use ethereum_types::{Address, H256, H512, U256};
16use ripemd::{Digest, Ripemd160};
17use sha2::Sha256;
18
19use crate::common;
20use crate::err;
21
22pub trait PrecompiledContract: Send + Sync {
24 fn required_gas(&self, input: &[u8]) -> u64;
26
27 fn run(&self, input: &[u8]) -> Result<Vec<u8>, err::Error>;
29}
30
31pub fn get(address: Address) -> Box<dyn PrecompiledContract> {
33 match U256::from_big_endian(H256::from(address).as_bytes()).low_u64() {
34 0x01 => Box::new(EcRecover {}) as Box<dyn PrecompiledContract>,
35 0x02 => Box::new(SHA256Hash {}) as Box<dyn PrecompiledContract>,
36 0x03 => Box::new(RIPEMD160Hash {}) as Box<dyn PrecompiledContract>,
37 0x04 => Box::new(DataCopy {}) as Box<dyn PrecompiledContract>,
38 0x05 => Box::new(BigModExp {}) as Box<dyn PrecompiledContract>,
39 0x06 => Box::new(Bn256Add {}) as Box<dyn PrecompiledContract>,
40 0x07 => Box::new(Bn256ScalarMul {}) as Box<dyn PrecompiledContract>,
41 0x08 => Box::new(Bn256Pairing {}) as Box<dyn PrecompiledContract>,
42 _ => unimplemented!(),
43 }
44}
45
46pub fn contains(address: &Address) -> bool {
48 let i = U256::from_big_endian(H256::from(*address).as_bytes());
49 i <= U256::from(8) && !i.is_zero()
50}
51
52const G_ECRECOVER: u64 = 3000; const G_SHA256_BASE: u64 = 60; const G_SHA256_PER_WORD: u64 = 12; const G_RIPEMD160_BASE: u64 = 600; const G_RIPEMD160_PER_WORD: u64 = 120; const G_IDENTITY_BASE: u64 = 15; const G_IDENTITY_PER_WORD: u64 = 3; const G_MOD_EXP_QUADCOEFF_DIV: u64 = 20; const G_BN256_ADD: u64 = 500; const G_BN256_SCALAR_MUL: u64 = 40000; const G_BN256_PARING_BASE: u64 = 100_000; const G_BN256_PARING_PER_POINT: u64 = 80000; fn is_signature_valid(r: &H256, s: &H256, v: u8) -> bool {
67 v <= 1
68 && *r < H256::from_str("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap()
69 && *r >= H256::from_low_u64_le(1)
70 && *s < H256::from_str("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap()
71 && *s >= H256::from_low_u64_le(1)
72}
73
74fn recover(input: &[u8], hash: &[u8], bit: u8) -> Result<H512, secp256k1::Error> {
76 let signature = secp256k1::Signature::parse_standard_slice(&input[64..128])?;
77 let message = secp256k1::Message::parse_slice(hash)?;
78 let recovery_id = secp256k1::RecoveryId::parse(bit)?;
79 let pub_key = secp256k1::recover(&message, &signature, &recovery_id)?;
80 let pub_key_ser = pub_key.serialize();
81 Ok(H512::from_slice(&pub_key_ser[1..65]))
82}
83
84pub struct EcRecover {}
86
87impl PrecompiledContract for EcRecover {
88 fn required_gas(&self, _: &[u8]) -> u64 {
89 G_ECRECOVER
90 }
91
92 fn run(&self, i: &[u8]) -> Result<Vec<u8>, err::Error> {
93 let len = std::cmp::min(i.len(), 128);
94
95 let mut input = [0; 128];
96 input[..len].copy_from_slice(&i[..len]);
97
98 let hash = H256::from_slice(&input[0..32]);
99 let v = H256::from_slice(&input[32..64]);
100 let r = H256::from_slice(&input[64..96]);
101 let s = H256::from_slice(&input[96..128]);
102
103 let bit = match v[31] {
104 27 | 28 if v.0[..31] == [0; 31] => v[31] - 27,
105 _ => {
106 return Ok(vec![]);
107 }
108 };
109 if !is_signature_valid(&r, &s, bit) {
110 return Ok(vec![]);
111 }
112 let mut output: Vec<u8> = Vec::new();
113 if let Ok(public) = recover(&input, hash.as_bytes(), bit) {
114 let data = common::hash::summary(&public.0);
115 output.write_all(&[0; 12])?;
116 output.write_all(&data[12..data.len()])?;
117 }
118 Ok(output)
119 }
120}
121
122pub struct SHA256Hash {}
124
125impl PrecompiledContract for SHA256Hash {
126 fn required_gas(&self, i: &[u8]) -> u64 {
129 (i.len() as u64 + 31) / 32 * G_SHA256_PER_WORD + G_SHA256_BASE
130 }
131
132 fn run(&self, i: &[u8]) -> Result<Vec<u8>, err::Error> {
133 let mut hasher = Sha256::new();
134 hasher.update(i);
135 let result = hasher.finalize();
136 let mut output: Vec<u8> = Vec::new();
137 output.write_all(&result).unwrap();
138 Ok(output)
139 }
140}
141
142pub struct RIPEMD160Hash {}
144
145impl PrecompiledContract for RIPEMD160Hash {
146 fn required_gas(&self, i: &[u8]) -> u64 {
149 (i.len() as u64 + 31) / 32 * G_RIPEMD160_PER_WORD + G_RIPEMD160_BASE
150 }
151
152 fn run(&self, i: &[u8]) -> Result<Vec<u8>, err::Error> {
153 let mut hasher = Ripemd160::new();
154 hasher.update(i);
155 let result = hasher.finalize();
156 let mut output: Vec<u8> = Vec::new();
157 output.write_all(&[0; 12]).unwrap();
158 output.write_all(&result).unwrap();
159 Ok(output)
160 }
161}
162
163pub struct DataCopy {}
164
165impl PrecompiledContract for DataCopy {
166 fn required_gas(&self, i: &[u8]) -> u64 {
169 (i.len() as u64 + 31) / 32 * G_IDENTITY_PER_WORD + G_IDENTITY_BASE
170 }
171
172 fn run(&self, i: &[u8]) -> Result<Vec<u8>, err::Error> {
173 Ok(i.into())
174 }
175}
176
177pub struct BigModExp {}
179
180impl PrecompiledContract for BigModExp {
181 fn required_gas(&self, _: &[u8]) -> u64 {
182 0
183 }
184
185 fn run(&self, _: &[u8]) -> Result<Vec<u8>, err::Error> {
186 Err(err::Error::Str("Not implemented!".into()))
187 }
188}
189
190pub struct Bn256Add {}
192
193impl PrecompiledContract for Bn256Add {
194 fn required_gas(&self, _: &[u8]) -> u64 {
195 G_BN256_ADD
196 }
197
198 fn run(&self, _: &[u8]) -> Result<Vec<u8>, err::Error> {
199 Err(err::Error::Str("Not implemented!".into()))
200 }
201}
202
203pub struct Bn256ScalarMul {}
205
206impl PrecompiledContract for Bn256ScalarMul {
207 fn required_gas(&self, _: &[u8]) -> u64 {
208 G_BN256_SCALAR_MUL
209 }
210
211 fn run(&self, _: &[u8]) -> Result<Vec<u8>, err::Error> {
212 Err(err::Error::Str("Not implemented!".into()))
213 }
214}
215
216pub struct Bn256Pairing {}
218
219impl PrecompiledContract for Bn256Pairing {
220 fn required_gas(&self, i: &[u8]) -> u64 {
221 G_BN256_PARING_BASE + (i.len() as u64 / 192 * G_BN256_PARING_PER_POINT)
222 }
223
224 fn run(&self, _: &[u8]) -> Result<Vec<u8>, err::Error> {
225 Err(err::Error::Str("Not implemented!".into()))
226 }
227}