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