Skip to content

Commit e0c3050

Browse files
authored
Merge branch 'main' into improve_memory_load
2 parents d6cac17 + c59033d commit e0c3050

File tree

2 files changed

+44
-28
lines changed

2 files changed

+44
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Perf
44

5+
### 2025-08-20
6+
57
### 2025-08-22
68

79
- Improve Memory::load_range by returning a Bytes directly, avoding a vec allocation [#4098](https://github.com/lambdaclass/ethrex/pull/4098)
@@ -14,6 +16,8 @@
1416

1517
- Improve blobbasefee opcode [#4092](https://github.com/lambdaclass/ethrex/pull/4092)
1618

19+
- Make precompiles use a constant table [#4097](https://github.com/lambdaclass/ethrex/pull/4097)
20+
1721
### 2025-08-19
1822

1923
- Improve addmod and mulmod opcode performance [#4072](https://github.com/lambdaclass/ethrex/pull/4072)

crates/vm/levm/src/precompiles.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -194,41 +194,53 @@ pub fn is_precompile(address: &Address, fork: Fork) -> bool {
194194
PRECOMPILES.contains(address) || PRECOMPILES_POST_CANCUN.contains(address)
195195
}
196196

197+
#[expect(clippy::as_conversions, clippy::indexing_slicing)]
197198
pub fn execute_precompile(
198199
address: Address,
199200
calldata: &Bytes,
200201
gas_remaining: &mut u64,
201202
) -> Result<Bytes, VMError> {
202-
let result = match address {
203-
address if address == ECRECOVER_ADDRESS => ecrecover(calldata, gas_remaining)?,
204-
address if address == IDENTITY_ADDRESS => identity(calldata, gas_remaining)?,
205-
address if address == SHA2_256_ADDRESS => sha2_256(calldata, gas_remaining)?,
206-
address if address == RIPEMD_160_ADDRESS => ripemd_160(calldata, gas_remaining)?,
207-
address if address == MODEXP_ADDRESS => modexp(calldata, gas_remaining)?,
208-
address if address == ECADD_ADDRESS => ecadd(calldata, gas_remaining)?,
209-
address if address == ECMUL_ADDRESS => ecmul(calldata, gas_remaining)?,
210-
address if address == ECPAIRING_ADDRESS => ecpairing(calldata, gas_remaining)?,
211-
address if address == BLAKE2F_ADDRESS => blake2f(calldata, gas_remaining)?,
212-
address if address == POINT_EVALUATION_ADDRESS => {
213-
point_evaluation(calldata, gas_remaining)?
214-
}
215-
address if address == BLS12_G1ADD_ADDRESS => bls12_g1add(calldata, gas_remaining)?,
216-
address if address == BLS12_G1MSM_ADDRESS => bls12_g1msm(calldata, gas_remaining)?,
217-
address if address == BLS12_G2ADD_ADDRESS => bls12_g2add(calldata, gas_remaining)?,
218-
address if address == BLS12_G2MSM_ADDRESS => bls12_g2msm(calldata, gas_remaining)?,
219-
address if address == BLS12_PAIRING_CHECK_ADDRESS => {
220-
bls12_pairing_check(calldata, gas_remaining)?
221-
}
222-
address if address == BLS12_MAP_FP_TO_G1_ADDRESS => {
223-
bls12_map_fp_to_g1(calldata, gas_remaining)?
224-
}
225-
address if address == BLS12_MAP_FP2_TO_G2_ADDRESS => {
226-
bls12_map_fp2_tp_g2(calldata, gas_remaining)?
227-
}
228-
_ => return Err(InternalError::InvalidPrecompileAddress.into()),
203+
type PrecompileFn = fn(&Bytes, &mut u64) -> Result<Bytes, VMError>;
204+
205+
const PRECOMPILES: [Option<PrecompileFn>; 18] = const {
206+
let mut precompiles = [const { None }; 18];
207+
precompiles[ECRECOVER_ADDRESS.0[19] as usize] = Some(ecrecover as PrecompileFn);
208+
precompiles[IDENTITY_ADDRESS.0[19] as usize] = Some(identity as PrecompileFn);
209+
precompiles[SHA2_256_ADDRESS.0[19] as usize] = Some(sha2_256 as PrecompileFn);
210+
precompiles[RIPEMD_160_ADDRESS.0[19] as usize] = Some(ripemd_160 as PrecompileFn);
211+
precompiles[MODEXP_ADDRESS.0[19] as usize] = Some(modexp as PrecompileFn);
212+
precompiles[ECADD_ADDRESS.0[19] as usize] = Some(ecadd as PrecompileFn);
213+
precompiles[ECMUL_ADDRESS.0[19] as usize] = Some(ecmul as PrecompileFn);
214+
precompiles[ECPAIRING_ADDRESS.0[19] as usize] = Some(ecpairing as PrecompileFn);
215+
precompiles[BLAKE2F_ADDRESS.0[19] as usize] = Some(blake2f as PrecompileFn);
216+
precompiles[POINT_EVALUATION_ADDRESS.0[19] as usize] =
217+
Some(point_evaluation as PrecompileFn);
218+
precompiles[BLS12_G1ADD_ADDRESS.0[19] as usize] = Some(bls12_g1add as PrecompileFn);
219+
precompiles[BLS12_G1MSM_ADDRESS.0[19] as usize] = Some(bls12_g1msm as PrecompileFn);
220+
precompiles[BLS12_G2ADD_ADDRESS.0[19] as usize] = Some(bls12_g2add as PrecompileFn);
221+
precompiles[BLS12_G2MSM_ADDRESS.0[19] as usize] = Some(bls12_g2msm as PrecompileFn);
222+
precompiles[BLS12_PAIRING_CHECK_ADDRESS.0[19] as usize] =
223+
Some(bls12_pairing_check as PrecompileFn);
224+
precompiles[BLS12_MAP_FP_TO_G1_ADDRESS.0[19] as usize] =
225+
Some(bls12_map_fp_to_g1 as PrecompileFn);
226+
precompiles[BLS12_MAP_FP2_TO_G2_ADDRESS.0[19] as usize] =
227+
Some(bls12_map_fp2_tp_g2 as PrecompileFn);
228+
229+
precompiles
229230
};
230231

231-
Ok(result)
232+
if address[0..18] != [0u8; 18] {
233+
return Err(VMError::Internal(InternalError::InvalidPrecompileAddress));
234+
}
235+
let index = u16::from_be_bytes([address[18], address[19]]) as usize;
236+
237+
let precompile = PRECOMPILES
238+
.get(index)
239+
.copied()
240+
.flatten()
241+
.ok_or(VMError::Internal(InternalError::InvalidPrecompileAddress))?;
242+
243+
precompile(calldata, gas_remaining)
232244
}
233245

234246
/// Consumes gas and if it's higher than the gas limit returns an error.

0 commit comments

Comments
 (0)