revm_precompile/hash.rs
1//! Hash precompiles, it contains SHA-256 and RIPEMD-160 hash precompiles
2//! More details in [`sha256_run`] and [`ripemd160_run`]
3use super::calc_linear_cost_u32;
4use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress};
5use sha2::Digest;
6
7/// SHA-256 precompile
8pub const SHA256: PrecompileWithAddress =
9 PrecompileWithAddress(crate::u64_to_address(2), sha256_run);
10
11/// RIPEMD-160 precompile
12pub const RIPEMD160: PrecompileWithAddress =
13 PrecompileWithAddress(crate::u64_to_address(3), ripemd160_run);
14
15/// Computes the SHA-256 hash of the input data
16///
17/// This function follows specifications defined in the following references:
18/// - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)
19/// - [Solidity Documentation on Mathematical and Cryptographic Functions](https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions)
20/// - [Address 0x02](https://etherscan.io/address/0000000000000000000000000000000000000002)
21pub fn sha256_run(input: &[u8], gas_limit: u64) -> PrecompileResult {
22 let cost = calc_linear_cost_u32(input.len(), 60, 12);
23 if cost > gas_limit {
24 Err(PrecompileError::OutOfGas)
25 } else {
26 let output = sha2::Sha256::digest(input);
27 Ok(PrecompileOutput::new(cost, output.to_vec().into()))
28 }
29}
30
31/// Computes the RIPEMD-160 hash of the input data
32///
33/// This function follows specifications defined in the following references:
34/// - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)
35/// - [Solidity Documentation on Mathematical and Cryptographic Functions](https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions)
36/// - [Address 03](https://etherscan.io/address/0000000000000000000000000000000000000003)
37pub fn ripemd160_run(input: &[u8], gas_limit: u64) -> PrecompileResult {
38 let gas_used = calc_linear_cost_u32(input.len(), 600, 120);
39 if gas_used > gas_limit {
40 Err(PrecompileError::OutOfGas)
41 } else {
42 let mut hasher = ripemd::Ripemd160::new();
43 hasher.update(input);
44
45 let mut output = [0u8; 32];
46 hasher.finalize_into((&mut output[12..]).into());
47 Ok(PrecompileOutput::new(gas_used, output.to_vec().into()))
48 }
49}