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}