forked from bluealloy/revm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathg1_add.rs
53 lines (44 loc) · 2.11 KB
/
g1_add.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use super::g1::{encode_g1_point, extract_g1_input};
use crate::{u64_to_address, PrecompileWithAddress};
use crate::{PrecompileError, PrecompileOutput, PrecompileResult};
use blst::{
blst_p1, blst_p1_add_or_double_affine, blst_p1_affine, blst_p1_from_affine, blst_p1_to_affine,
};
use primitives::Bytes;
use crate::bls12_381::bls12_381_const::{G1_ADD_ADDRESS, G1_ADD_BASE_GAS_FEE, G1_ADD_INPUT_LENGTH,G1_INPUT_ITEM_LENGTH};
/// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile.
pub const PRECOMPILE: PrecompileWithAddress =
PrecompileWithAddress(u64_to_address(G1_ADD_ADDRESS), g1_add);
/// G1 addition call expects `256` bytes as an input that is interpreted as byte
/// concatenation of two G1 points (`128` bytes each).
/// Output is an encoding of addition operation result - single G1 point (`128`
/// bytes).
/// See also: <https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition>
pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult {
if G1_ADD_BASE_GAS_FEE > gas_limit {
return Err(PrecompileError::OutOfGas.into());
}
if input.len() != G1_ADD_INPUT_LENGTH {
return Err(PrecompileError::Other(format!(
"G1ADD input should be {G1_ADD_INPUT_LENGTH} bytes, was {}",
input.len()
))
.into());
}
// NB: There is no subgroup check for the G1 addition precompile.
//
// So we set the subgroup checks here to `false`
let a_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], false)?;
let b_aff = &extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..], false)?;
let mut b = blst_p1::default();
// SAFETY: `b` and `b_aff` are blst values.
unsafe { blst_p1_from_affine(&mut b, b_aff) };
let mut p = blst_p1::default();
// SAFETY: `p`, `b` and `a_aff` are blst values.
unsafe { blst_p1_add_or_double_affine(&mut p, &b, a_aff) };
let mut p_aff = blst_p1_affine::default();
// SAFETY: `p_aff` and `p`` are blst values.
unsafe { blst_p1_to_affine(&mut p_aff, &p) };
let out = encode_g1_point(&p_aff);
Ok(PrecompileOutput::new(G1_ADD_BASE_GAS_FEE, out))
}