revm_precompile/
hash.rs

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