use primitive_types::U256;
pub use zkevm_opcode_defs::system_params::{
ECRECOVER_INNER_FUNCTION_PRECOMPILE_ADDRESS, KECCAK256_ROUND_FUNCTION_PRECOMPILE_ADDRESS,
SECP256R1_VERIFY_PRECOMPILE_ADDRESS, SHA256_ROUND_FUNCTION_PRECOMPILE_ADDRESS,
};
use zksync_vm2_interface::CycleStats;
pub use self::legacy::LegacyPrecompiles;
use crate::heap::Heap;
mod legacy;
#[derive(Debug, Clone)]
pub struct PrecompileMemoryReader<'a, const IN_WORDS: bool = false> {
heap: &'a Heap,
offset: u32,
len: u32,
}
impl<'a> PrecompileMemoryReader<'a> {
pub(crate) fn new(heap: &'a Heap, offset: u32, len: u32) -> Self {
Self { heap, offset, len }
}
pub fn assume_offset_in_words(self) -> PrecompileMemoryReader<'a, true> {
PrecompileMemoryReader {
heap: self.heap,
offset: self.offset * 32,
len: self.len * 32,
}
}
}
impl<const IN_WORDS: bool> Iterator for PrecompileMemoryReader<'_, IN_WORDS> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
if self.len == 0 {
return None;
}
let output = self.heap.read_byte(self.offset);
self.offset += 1;
self.len -= 1;
Some(output)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len as usize, Some(self.len as usize))
}
}
impl ExactSizeIterator for PrecompileMemoryReader<'_> {
fn len(&self) -> usize {
self.len as usize
}
}
#[derive(Debug, Default)]
pub struct PrecompileOutput {
pub(crate) buffer: [U256; 2],
pub(crate) len: u32,
pub(crate) cycle_stats: Option<CycleStats>,
}
impl PrecompileOutput {
#[must_use]
pub fn with_cycle_stats(mut self, stats: CycleStats) -> Self {
self.cycle_stats = Some(stats);
self
}
}
impl From<U256> for PrecompileOutput {
fn from(value: U256) -> Self {
Self {
buffer: [value, U256::zero()],
len: 1,
cycle_stats: None,
}
}
}
impl From<[U256; 2]> for PrecompileOutput {
fn from(value: [U256; 2]) -> Self {
Self {
buffer: value,
len: 2,
cycle_stats: None,
}
}
}
pub trait Precompiles {
fn call_precompile(
&self,
address_low: u16,
memory: PrecompileMemoryReader<'_>,
aux_input: u64,
) -> PrecompileOutput;
}