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