pallet_evm_precompile_simple/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
19#![warn(unused_crate_dependencies)]
20
21extern crate alloc;
22
23use alloc::vec::Vec;
24use core::cmp::min;
25
26use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure};
27
28pub struct Identity;
30
31impl LinearCostPrecompile for Identity {
32 const BASE: u64 = 15;
33 const WORD: u64 = 3;
34
35 fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec<u8>), PrecompileFailure> {
36 Ok((ExitSucceed::Returned, input.to_vec()))
37 }
38}
39
40pub struct ECRecover;
42
43impl LinearCostPrecompile for ECRecover {
44 const BASE: u64 = 3000;
45 const WORD: u64 = 0;
46
47 fn execute(i: &[u8], _: u64) -> Result<(ExitSucceed, Vec<u8>), PrecompileFailure> {
48 let mut input = [0u8; 128];
49 input[..min(i.len(), 128)].copy_from_slice(&i[..min(i.len(), 128)]);
50
51 let mut msg = [0u8; 32];
52 let mut sig = [0u8; 65];
53
54 msg[0..32].copy_from_slice(&input[0..32]);
55 sig[0..32].copy_from_slice(&input[64..96]); sig[32..64].copy_from_slice(&input[96..128]); sig[64] = input[63]; if input[32..63] != [0u8; 31] || ![27, 28].contains(&input[63]) {
62 return Ok((ExitSucceed::Returned, [0u8; 0].to_vec()));
63 }
64
65 let result = match sp_io::crypto::secp256k1_ecdsa_recover(&sig, &msg) {
66 Ok(pubkey) => {
67 let mut address = sp_io::hashing::keccak_256(&pubkey);
68 address[0..12].copy_from_slice(&[0u8; 12]);
69 address.to_vec()
70 }
71 Err(_) => [0u8; 0].to_vec(),
72 };
73
74 Ok((ExitSucceed::Returned, result))
75 }
76}
77
78pub struct Ripemd160;
80
81impl LinearCostPrecompile for Ripemd160 {
82 const BASE: u64 = 600;
83 const WORD: u64 = 120;
84
85 fn execute(input: &[u8], _cost: u64) -> Result<(ExitSucceed, Vec<u8>), PrecompileFailure> {
86 use ripemd::Digest;
87
88 let mut ret = [0u8; 32];
89 ret[12..32].copy_from_slice(&ripemd::Ripemd160::digest(input));
90 Ok((ExitSucceed::Returned, ret.to_vec()))
91 }
92}
93
94pub struct Sha256;
96
97impl LinearCostPrecompile for Sha256 {
98 const BASE: u64 = 60;
99 const WORD: u64 = 12;
100
101 fn execute(input: &[u8], _cost: u64) -> Result<(ExitSucceed, Vec<u8>), PrecompileFailure> {
102 let ret = sp_io::hashing::sha2_256(input);
103 Ok((ExitSucceed::Returned, ret.to_vec()))
104 }
105}
106
107pub struct ECRecoverPublicKey;
110
111impl LinearCostPrecompile for ECRecoverPublicKey {
112 const BASE: u64 = 3000;
113 const WORD: u64 = 0;
114
115 fn execute(i: &[u8], _: u64) -> Result<(ExitSucceed, Vec<u8>), PrecompileFailure> {
116 let mut input = [0u8; 128];
117 input[..min(i.len(), 128)].copy_from_slice(&i[..min(i.len(), 128)]);
118
119 let mut msg = [0u8; 32];
120 let mut sig = [0u8; 65];
121
122 msg[0..32].copy_from_slice(&input[0..32]);
123 sig[0..32].copy_from_slice(&input[64..96]);
124 sig[32..64].copy_from_slice(&input[96..128]);
125 sig[64] = input[63];
126
127 let pubkey = sp_io::crypto::secp256k1_ecdsa_recover(&sig, &msg).map_err(|_| {
128 PrecompileFailure::Error {
129 exit_status: ExitError::Other("Public key recover failed".into()),
130 }
131 })?;
132
133 Ok((ExitSucceed::Returned, pubkey.to_vec()))
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use pallet_evm_test_vector_support::test_precompile_test_vectors;
141
142 #[test]
144 fn process_consensus_tests_for_ecrecover() -> Result<(), String> {
145 test_precompile_test_vectors::<ECRecover>("../testdata/ecRecover.json")?;
146 Ok(())
147 }
148
149 #[test]
150 fn process_consensus_tests_for_sha256() -> Result<(), String> {
151 test_precompile_test_vectors::<Sha256>("../testdata/common_sha256.json")?;
152 Ok(())
153 }
154
155 #[test]
156 fn process_consensus_tests_for_ripemd160() -> Result<(), String> {
157 test_precompile_test_vectors::<Ripemd160>("../testdata/common_ripemd.json")?;
158 Ok(())
159 }
160}