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::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress};
5
6/// SHA-256 precompile
7pub const SHA256: PrecompileWithAddress =
8    PrecompileWithAddress(crate::u64_to_address(2), sha256_run);
9
10/// RIPEMD-160 precompile
11pub const RIPEMD160: PrecompileWithAddress =
12    PrecompileWithAddress(crate::u64_to_address(3), ripemd160_run);
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: &[u8], gas_limit: u64) -> PrecompileResult {
21    let cost = calc_linear_cost_u32(input.len(), 60, 12);
22    if cost > gas_limit {
23        Err(PrecompileError::OutOfGas)
24    } else {
25        let output = crypto().sha256(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: &[u8], gas_limit: u64) -> PrecompileResult {
37    let gas_used = calc_linear_cost_u32(input.len(), 600, 120);
38    if gas_used > gas_limit {
39        Err(PrecompileError::OutOfGas)
40    } else {
41        let output = crypto().ripemd160(input);
42        Ok(PrecompileOutput::new(gas_used, output.to_vec().into()))
43    }
44}