op_revm/
precompiles.rs

1//! Contains Optimism specific precompiles.
2use crate::OpSpecId;
3use revm::{
4    context::Cfg,
5    context_interface::ContextTr,
6    handler::{EthPrecompiles, PrecompileProvider},
7    interpreter::{CallInputs, InterpreterResult},
8    precompile::{
9        self, bn254, secp256r1, Precompile, PrecompileError, PrecompileId, PrecompileResult,
10        Precompiles,
11    },
12    primitives::{hardfork::SpecId, Address, OnceLock},
13};
14use std::{boxed::Box, string::String};
15
16/// Optimism precompile provider
17#[derive(Debug, Clone)]
18pub struct OpPrecompiles {
19    /// Inner precompile provider is same as Ethereums.
20    inner: EthPrecompiles,
21    /// Spec id of the precompile provider.
22    spec: OpSpecId,
23}
24
25impl OpPrecompiles {
26    /// Create a new precompile provider with the given OpSpec.
27    #[inline]
28    pub fn new_with_spec(spec: OpSpecId) -> Self {
29        let precompiles = match spec {
30            spec @ (OpSpecId::BEDROCK
31            | OpSpecId::REGOLITH
32            | OpSpecId::CANYON
33            | OpSpecId::ECOTONE) => Precompiles::new(spec.into_eth_spec().into()),
34            OpSpecId::FJORD => fjord(),
35            OpSpecId::GRANITE | OpSpecId::HOLOCENE => granite(),
36            OpSpecId::ISTHMUS => isthmus(),
37            OpSpecId::INTEROP | OpSpecId::OSAKA | OpSpecId::JOVIAN => jovian(),
38        };
39
40        Self {
41            inner: EthPrecompiles {
42                precompiles,
43                spec: SpecId::default(),
44            },
45            spec,
46        }
47    }
48
49    /// Precompiles getter.
50    #[inline]
51    pub fn precompiles(&self) -> &'static Precompiles {
52        self.inner.precompiles
53    }
54}
55
56/// Returns precompiles for Fjord spec.
57pub fn fjord() -> &'static Precompiles {
58    static INSTANCE: OnceLock<Precompiles> = OnceLock::new();
59    INSTANCE.get_or_init(|| {
60        let mut precompiles = Precompiles::cancun().clone();
61        // RIP-7212: secp256r1 P256verify
62        precompiles.extend([secp256r1::P256VERIFY]);
63        precompiles
64    })
65}
66
67/// Returns precompiles for Granite spec.
68pub fn granite() -> &'static Precompiles {
69    static INSTANCE: OnceLock<Precompiles> = OnceLock::new();
70    INSTANCE.get_or_init(|| {
71        let mut precompiles = fjord().clone();
72        // Restrict bn254Pairing input size
73        precompiles.extend([bn254_pair::GRANITE]);
74        precompiles
75    })
76}
77
78/// Returns precompiles for isthumus spec.
79pub fn isthmus() -> &'static Precompiles {
80    static INSTANCE: OnceLock<Precompiles> = OnceLock::new();
81    INSTANCE.get_or_init(|| {
82        let mut precompiles = granite().clone();
83        // Prague bls12 precompiles
84        precompiles.extend(precompile::bls12_381::precompiles());
85        // Isthmus bls12 precompile modifications
86        precompiles.extend([
87            bls12_381::ISTHMUS_G1_MSM,
88            bls12_381::ISTHMUS_G2_MSM,
89            bls12_381::ISTHMUS_PAIRING,
90        ]);
91        precompiles
92    })
93}
94
95/// Returns precompiles for jovian spec.
96pub fn jovian() -> &'static Precompiles {
97    static INSTANCE: OnceLock<Precompiles> = OnceLock::new();
98    INSTANCE.get_or_init(|| {
99        let mut precompiles = isthmus().clone();
100
101        let mut to_remove = Precompiles::default();
102        to_remove.extend([
103            bn254::pair::ISTANBUL,
104            bls12_381::ISTHMUS_G1_MSM,
105            bls12_381::ISTHMUS_G2_MSM,
106            bls12_381::ISTHMUS_PAIRING,
107        ]);
108
109        // Replace the 4 variable-input precompiles with Jovian versions (reduced limits)
110        precompiles.difference(&to_remove);
111
112        precompiles.extend([
113            bn254_pair::JOVIAN,
114            bls12_381::JOVIAN_G1_MSM,
115            bls12_381::JOVIAN_G2_MSM,
116            bls12_381::JOVIAN_PAIRING,
117        ]);
118
119        precompiles
120    })
121}
122
123impl<CTX> PrecompileProvider<CTX> for OpPrecompiles
124where
125    CTX: ContextTr<Cfg: Cfg<Spec = OpSpecId>>,
126{
127    type Output = InterpreterResult;
128
129    #[inline]
130    fn set_spec(&mut self, spec: <CTX::Cfg as Cfg>::Spec) -> bool {
131        if spec == self.spec {
132            return false;
133        }
134        *self = Self::new_with_spec(spec);
135        true
136    }
137
138    #[inline]
139    fn run(
140        &mut self,
141        context: &mut CTX,
142        inputs: &CallInputs,
143    ) -> Result<Option<Self::Output>, String> {
144        self.inner.run(context, inputs)
145    }
146
147    #[inline]
148    fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
149        self.inner.warm_addresses()
150    }
151
152    #[inline]
153    fn contains(&self, address: &Address) -> bool {
154        self.inner.contains(address)
155    }
156}
157
158impl Default for OpPrecompiles {
159    fn default() -> Self {
160        Self::new_with_spec(OpSpecId::JOVIAN)
161    }
162}
163
164/// Bn254 pair precompile.
165pub mod bn254_pair {
166    use super::*;
167
168    /// Max input size for the bn254 pair precompile.
169    pub const GRANITE_MAX_INPUT_SIZE: usize = 112687;
170    /// Bn254 pair precompile.
171    pub const GRANITE: Precompile = Precompile::new(
172        PrecompileId::Bn254Pairing,
173        bn254::pair::ADDRESS,
174        run_pair_granite,
175    );
176
177    /// Run the bn254 pair precompile with Optimism input limit.
178    pub fn run_pair_granite(input: &[u8], gas_limit: u64) -> PrecompileResult {
179        if input.len() > GRANITE_MAX_INPUT_SIZE {
180            return Err(PrecompileError::Bn254PairLength);
181        }
182        bn254::run_pair(
183            input,
184            bn254::pair::ISTANBUL_PAIR_PER_POINT,
185            bn254::pair::ISTANBUL_PAIR_BASE,
186            gas_limit,
187        )
188    }
189
190    /// Max input size for the bn254 pair precompile.
191    pub const JOVIAN_MAX_INPUT_SIZE: usize = 81_984;
192    /// Bn254 pair precompile.
193    pub const JOVIAN: Precompile = Precompile::new(
194        PrecompileId::Bn254Pairing,
195        bn254::pair::ADDRESS,
196        run_pair_jovian,
197    );
198
199    /// Run the bn254 pair precompile with Optimism input limit.
200    pub fn run_pair_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult {
201        if input.len() > JOVIAN_MAX_INPUT_SIZE {
202            return Err(PrecompileError::Bn254PairLength);
203        }
204        bn254::run_pair(
205            input,
206            bn254::pair::ISTANBUL_PAIR_PER_POINT,
207            bn254::pair::ISTANBUL_PAIR_BASE,
208            gas_limit,
209        )
210    }
211}
212
213/// Bls12_381 precompile.
214pub mod bls12_381 {
215    use super::*;
216    use revm::precompile::bls12_381_const::{G1_MSM_ADDRESS, G2_MSM_ADDRESS, PAIRING_ADDRESS};
217
218    /// Max input size for the g1 msm precompile.
219    pub const ISTHMUS_G1_MSM_MAX_INPUT_SIZE: usize = 513760;
220
221    /// The maximum input size for the BLS12-381 g1 msm operation after the Jovian Hardfork.
222    pub const JOVIAN_G1_MSM_MAX_INPUT_SIZE: usize = 288_960;
223
224    /// Max input size for the g2 msm precompile.
225    pub const ISTHMUS_G2_MSM_MAX_INPUT_SIZE: usize = 488448;
226
227    /// Max input size for the g2 msm precompile after the Jovian Hardfork.
228    pub const JOVIAN_G2_MSM_MAX_INPUT_SIZE: usize = 278_784;
229
230    /// Max input size for the pairing precompile.
231    pub const ISTHMUS_PAIRING_MAX_INPUT_SIZE: usize = 235008;
232
233    /// Max input size for the pairing precompile after the Jovian Hardfork.
234    pub const JOVIAN_PAIRING_MAX_INPUT_SIZE: usize = 156_672;
235
236    /// G1 msm precompile.
237    pub const ISTHMUS_G1_MSM: Precompile =
238        Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, run_g1_msm_isthmus);
239    /// G2 msm precompile.
240    pub const ISTHMUS_G2_MSM: Precompile =
241        Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, run_g2_msm_isthmus);
242    /// Pairing precompile.
243    pub const ISTHMUS_PAIRING: Precompile = Precompile::new(
244        PrecompileId::Bls12Pairing,
245        PAIRING_ADDRESS,
246        run_pair_isthmus,
247    );
248
249    /// G1 msm precompile after the Jovian Hardfork.
250    pub const JOVIAN_G1_MSM: Precompile =
251        Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, run_g1_msm_jovian);
252    /// G2 msm precompile after the Jovian Hardfork.
253    pub const JOVIAN_G2_MSM: Precompile =
254        Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, run_g2_msm_jovian);
255    /// Pairing precompile after the Jovian Hardfork.
256    pub const JOVIAN_PAIRING: Precompile =
257        Precompile::new(PrecompileId::Bls12Pairing, PAIRING_ADDRESS, run_pair_jovian);
258
259    /// Run the g1 msm precompile with Optimism input limit.
260    pub fn run_g1_msm_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult {
261        if input.len() > ISTHMUS_G1_MSM_MAX_INPUT_SIZE {
262            return Err(PrecompileError::Other(
263                "G1MSM input length too long for OP Stack input size limitation after the Isthmus Hardfork".into(),
264            ));
265        }
266        precompile::bls12_381::g1_msm::g1_msm(input, gas_limit)
267    }
268
269    /// Run the g1 msm precompile with Optimism input limit.
270    pub fn run_g1_msm_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult {
271        if input.len() > JOVIAN_G1_MSM_MAX_INPUT_SIZE {
272            return Err(PrecompileError::Other(
273                "G1MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".into(),
274            ));
275        }
276        precompile::bls12_381::g1_msm::g1_msm(input, gas_limit)
277    }
278
279    /// Run the g2 msm precompile with Optimism input limit.
280    pub fn run_g2_msm_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult {
281        if input.len() > ISTHMUS_G2_MSM_MAX_INPUT_SIZE {
282            return Err(PrecompileError::Other(
283                "G2MSM input length too long for OP Stack input size limitation".into(),
284            ));
285        }
286        precompile::bls12_381::g2_msm::g2_msm(input, gas_limit)
287    }
288
289    /// Run the g2 msm precompile with Optimism input limit after the Jovian Hardfork.
290    pub fn run_g2_msm_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult {
291        if input.len() > JOVIAN_G2_MSM_MAX_INPUT_SIZE {
292            return Err(PrecompileError::Other(
293                "G2MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".into(),
294            ));
295        }
296        precompile::bls12_381::g2_msm::g2_msm(input, gas_limit)
297    }
298
299    /// Run the pairing precompile with Optimism input limit.
300    pub fn run_pair_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult {
301        if input.len() > ISTHMUS_PAIRING_MAX_INPUT_SIZE {
302            return Err(PrecompileError::Other(
303                "Pairing input length too long for OP Stack input size limitation".into(),
304            ));
305        }
306        precompile::bls12_381::pairing::pairing(input, gas_limit)
307    }
308
309    /// Run the pairing precompile with Optimism input limit after the Jovian Hardfork.
310    pub fn run_pair_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult {
311        if input.len() > JOVIAN_PAIRING_MAX_INPUT_SIZE {
312            return Err(PrecompileError::Other(
313                "Pairing input length too long for OP Stack input size limitation after the Jovian Hardfork".into(),
314            ));
315        }
316        precompile::bls12_381::pairing::pairing(input, gas_limit)
317    }
318}
319
320#[cfg(test)]
321mod tests {
322    use crate::precompiles::bls12_381::{
323        run_g1_msm_isthmus, run_g1_msm_jovian, run_g2_msm_isthmus, run_g2_msm_jovian,
324        ISTHMUS_G1_MSM_MAX_INPUT_SIZE, ISTHMUS_G2_MSM_MAX_INPUT_SIZE,
325        ISTHMUS_PAIRING_MAX_INPUT_SIZE, JOVIAN_G1_MSM_MAX_INPUT_SIZE, JOVIAN_G2_MSM_MAX_INPUT_SIZE,
326        JOVIAN_PAIRING_MAX_INPUT_SIZE,
327    };
328
329    use super::*;
330    use revm::{
331        precompile::{bls12_381_const, PrecompileError},
332        primitives::{hex, Bytes},
333    };
334    use std::vec;
335
336    #[test]
337    fn test_bn254_pair() {
338        let input = hex::decode(
339            "\
340      1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\
341      3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\
342      209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\
343      04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\
344      2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\
345      120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\
346      111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\
347      2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\
348      198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\
349      1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\
350      090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\
351      12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
352        )
353        .unwrap();
354        let expected =
355            hex::decode("0000000000000000000000000000000000000000000000000000000000000001")
356                .unwrap();
357        let outcome = bn254_pair::run_pair_granite(&input, 260_000).unwrap();
358        assert_eq!(outcome.bytes, expected);
359
360        // Invalid input length
361        let input = hex::decode(
362            "\
363          1111111111111111111111111111111111111111111111111111111111111111\
364          1111111111111111111111111111111111111111111111111111111111111111\
365          111111111111111111111111111111\
366      ",
367        )
368        .unwrap();
369
370        let res = bn254_pair::run_pair_granite(&input, 260_000);
371        assert!(matches!(res, Err(PrecompileError::Bn254PairLength)));
372
373        // Valid input length shorter than 112687
374        let input = vec![1u8; 586 * bn254::PAIR_ELEMENT_LEN];
375        let res = bn254_pair::run_pair_granite(&input, 260_000);
376        assert!(matches!(res, Err(PrecompileError::OutOfGas)));
377
378        // Input length longer than 112687
379        let input = vec![1u8; 587 * bn254::PAIR_ELEMENT_LEN];
380        let res = bn254_pair::run_pair_granite(&input, 260_000);
381        assert!(matches!(res, Err(PrecompileError::Bn254PairLength)));
382    }
383
384    #[test]
385    fn test_accelerated_bn254_pairing_jovian() {
386        const TEST_INPUT: [u8; 384] = hex!(
387            "2cf44499d5d27bb186308b7af7af02ac5bc9eeb6a3d147c186b21fb1b76e18da2c0f001f52110ccfe69108924926e45f0b0c868df0e7bde1fe16d3242dc715f61fb19bb476f6b9e44e2a32234da8212f61cd63919354bc06aef31e3cfaff3ebc22606845ff186793914e03e21df544c34ffe2f2f3504de8a79d9159eca2d98d92bd368e28381e8eccb5fa81fc26cf3f048eea9abfdd85d7ed3ab3698d63e4f902fe02e47887507adf0ff1743cbac6ba291e66f59be6bd763950bb16041a0a85e000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd451971ff0471b09fa93caaf13cbf443c1aede09cc4328f5a62aad45f40ec133eb4091058a3141822985733cbdddfed0fd8d6c104e9e9eff40bf5abfef9ab163bc72a23af9a5ce2ba2796c1f4e453a370eb0af8c212d9dc9acd8fc02c2e907baea223a8eb0b0996252cb548a4487da97b02422ebc0e834613f954de6c7e0afdc1fc"
388        );
389        const EXPECTED_OUTPUT: [u8; 32] =
390            hex!("0000000000000000000000000000000000000000000000000000000000000001");
391
392        let res = bn254_pair::run_pair_jovian(TEST_INPUT.as_ref(), u64::MAX);
393        assert!(matches!(res, Ok(outcome) if **outcome.bytes == EXPECTED_OUTPUT));
394    }
395
396    #[test]
397    fn test_accelerated_bn254_pairing_bad_input_len_jovian() {
398        let input = [0u8; bn254_pair::JOVIAN_MAX_INPUT_SIZE + 1];
399        let res = bn254_pair::run_pair_jovian(&input, u64::MAX);
400        assert!(matches!(res, Err(PrecompileError::Bn254PairLength)));
401    }
402
403    #[test]
404    fn test_get_jovian_precompile_with_bad_input_len() {
405        let precompiles = OpPrecompiles::new_with_spec(OpSpecId::JOVIAN);
406        let bn254_pair_precompile = precompiles
407            .precompiles()
408            .get(&bn254::pair::ADDRESS)
409            .unwrap();
410
411        let mut bad_input_len = bn254_pair::JOVIAN_MAX_INPUT_SIZE + 1;
412        assert!(bad_input_len < bn254_pair::GRANITE_MAX_INPUT_SIZE);
413        let input = vec![0u8; bad_input_len];
414
415        let res = bn254_pair_precompile.execute(&input, u64::MAX);
416        assert!(matches!(res, Err(PrecompileError::Bn254PairLength)));
417
418        let bls12_381_g1_msm_precompile = precompiles
419            .precompiles()
420            .get(&bls12_381_const::G1_MSM_ADDRESS)
421            .unwrap();
422        bad_input_len = bls12_381::JOVIAN_G1_MSM_MAX_INPUT_SIZE + 1;
423        assert!(bad_input_len < bls12_381::ISTHMUS_G1_MSM_MAX_INPUT_SIZE);
424        let input = vec![0u8; bad_input_len];
425        let res = bls12_381_g1_msm_precompile.execute(&input, u64::MAX);
426        assert!(
427            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
428        );
429
430        let bls12_381_g2_msm_precompile = precompiles
431            .precompiles()
432            .get(&bls12_381_const::G2_MSM_ADDRESS)
433            .unwrap();
434        bad_input_len = bls12_381::JOVIAN_G2_MSM_MAX_INPUT_SIZE + 1;
435        assert!(bad_input_len < bls12_381::ISTHMUS_G2_MSM_MAX_INPUT_SIZE);
436        let input = vec![0u8; bad_input_len];
437        let res = bls12_381_g2_msm_precompile.execute(&input, u64::MAX);
438        assert!(
439            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
440        );
441
442        let bls12_381_pairing_precompile = precompiles
443            .precompiles()
444            .get(&bls12_381_const::PAIRING_ADDRESS)
445            .unwrap();
446        bad_input_len = bls12_381::JOVIAN_PAIRING_MAX_INPUT_SIZE + 1;
447        assert!(bad_input_len < bls12_381::ISTHMUS_PAIRING_MAX_INPUT_SIZE);
448        let input = vec![0u8; bad_input_len];
449        let res = bls12_381_pairing_precompile.execute(&input, u64::MAX);
450        assert!(
451            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
452        );
453    }
454
455    #[test]
456    fn test_cancun_precompiles_in_fjord() {
457        // additional to cancun, fjord has p256verify
458        assert_eq!(fjord().difference(Precompiles::cancun()).len(), 1)
459    }
460
461    #[test]
462    fn test_cancun_precompiles_in_granite() {
463        // granite has p256verify (fjord)
464        // granite has modification of cancun's bn254 pair (doesn't count as new precompile)
465        assert_eq!(granite().difference(Precompiles::cancun()).len(), 1)
466    }
467
468    #[test]
469    fn test_prague_precompiles_in_isthmus() {
470        let new_prague_precompiles = Precompiles::prague().difference(Precompiles::cancun());
471
472        // isthmus contains all precompiles that were new in prague, without modifications
473        assert!(new_prague_precompiles.difference(isthmus()).is_empty())
474    }
475
476    #[test]
477    fn test_prague_precompiles_in_jovian() {
478        let new_prague_precompiles = Precompiles::prague().difference(Precompiles::cancun());
479
480        // jovian contains all precompiles that were new in prague, without modifications
481        assert!(new_prague_precompiles.difference(jovian()).is_empty())
482    }
483
484    /// All the addresses of the precompiles in isthmus should be in jovian
485    #[test]
486    fn test_isthmus_precompiles_in_jovian() {
487        let new_isthmus_precompiles = isthmus().difference(Precompiles::cancun());
488
489        // jovian contains all precompiles that were new in isthmus, without modifications
490        assert!(new_isthmus_precompiles.difference(jovian()).is_empty())
491    }
492
493    #[test]
494    fn test_default_precompiles_is_latest() {
495        let latest = OpPrecompiles::new_with_spec(OpSpecId::default())
496            .inner
497            .precompiles;
498        let default = OpPrecompiles::default().inner.precompiles;
499        assert_eq!(latest.len(), default.len());
500
501        let intersection = default.intersection(latest);
502        assert_eq!(intersection.len(), latest.len())
503    }
504
505    #[test]
506    fn test_g1_isthmus_max_size() {
507        let oversized_input = vec![0u8; ISTHMUS_G1_MSM_MAX_INPUT_SIZE + 1];
508        let input = Bytes::from(oversized_input);
509
510        let res = run_g1_msm_isthmus(&input, 260_000);
511
512        assert!(
513            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
514        );
515    }
516
517    #[test]
518    fn test_g1_jovian_max_size() {
519        let oversized_input = vec![0u8; JOVIAN_G1_MSM_MAX_INPUT_SIZE + 1];
520        let input = Bytes::from(oversized_input);
521
522        let res = run_g1_msm_jovian(&input, u64::MAX);
523
524        assert!(
525            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
526        );
527    }
528    #[test]
529    fn test_g2_isthmus_max_size() {
530        let oversized_input = vec![0u8; ISTHMUS_G2_MSM_MAX_INPUT_SIZE + 1];
531        let input = Bytes::from(oversized_input);
532
533        let res = run_g2_msm_isthmus(&input, 260_000);
534
535        assert!(
536            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
537        );
538    }
539    #[test]
540    fn test_g2_jovian_max_size() {
541        let oversized_input = vec![0u8; JOVIAN_G2_MSM_MAX_INPUT_SIZE + 1];
542        let input = Bytes::from(oversized_input);
543
544        let res = run_g2_msm_jovian(&input, u64::MAX);
545
546        assert!(
547            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
548        );
549    }
550    #[test]
551    fn test_pair_isthmus_max_size() {
552        let oversized_input = vec![0u8; ISTHMUS_PAIRING_MAX_INPUT_SIZE + 1];
553        let input = Bytes::from(oversized_input);
554
555        let res = bls12_381::run_pair_isthmus(&input, 260_000);
556
557        assert!(
558            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
559        );
560    }
561    #[test]
562    fn test_pair_jovian_max_size() {
563        let oversized_input = vec![0u8; JOVIAN_PAIRING_MAX_INPUT_SIZE + 1];
564        let input = Bytes::from(oversized_input);
565
566        let res = bls12_381::run_pair_jovian(&input, u64::MAX);
567
568        assert!(
569            matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long"))
570        );
571    }
572}