revm_precompile/
hash.rs

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