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}