Skip to main content

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