revm_precompile/bls12_381/
g2.rs
1use super::utils::{fp_from_bendian, fp_to_bytes, remove_padding, FP_LENGTH, PADDED_FP_LENGTH};
2use crate::primitives::{Bytes, PrecompileError};
3use blst::{blst_fp2, blst_p2_affine, blst_p2_affine_in_g2, blst_p2_affine_on_curve};
4
5pub(super) const G2_INPUT_ITEM_LENGTH: usize = 256;
7
8const G2_OUTPUT_LENGTH: usize = 256;
10
11pub(super) fn encode_g2_point(input: &blst_p2_affine) -> Bytes {
13 let mut out = vec![0u8; G2_OUTPUT_LENGTH];
14 fp_to_bytes(&mut out[..PADDED_FP_LENGTH], &input.x.fp[0]);
15 fp_to_bytes(
16 &mut out[PADDED_FP_LENGTH..2 * PADDED_FP_LENGTH],
17 &input.x.fp[1],
18 );
19 fp_to_bytes(
20 &mut out[2 * PADDED_FP_LENGTH..3 * PADDED_FP_LENGTH],
21 &input.y.fp[0],
22 );
23 fp_to_bytes(
24 &mut out[3 * PADDED_FP_LENGTH..4 * PADDED_FP_LENGTH],
25 &input.y.fp[1],
26 );
27 out.into()
28}
29
30pub(super) fn decode_and_check_g2(
32 x1: &[u8; 48],
33 x2: &[u8; 48],
34 y1: &[u8; 48],
35 y2: &[u8; 48],
36) -> Result<blst_p2_affine, PrecompileError> {
37 Ok(blst_p2_affine {
38 x: check_canonical_fp2(x1, x2)?,
39 y: check_canonical_fp2(y1, y2)?,
40 })
41}
42
43pub(super) fn check_canonical_fp2(
46 input_1: &[u8; 48],
47 input_2: &[u8; 48],
48) -> Result<blst_fp2, PrecompileError> {
49 let fp_1 = fp_from_bendian(input_1)?;
50 let fp_2 = fp_from_bendian(input_2)?;
51
52 let fp2 = blst_fp2 { fp: [fp_1, fp_2] };
53
54 Ok(fp2)
55}
56
57pub(super) fn extract_g2_input(
61 input: &[u8],
62 subgroup_check: bool,
63) -> Result<blst_p2_affine, PrecompileError> {
64 if input.len() != G2_INPUT_ITEM_LENGTH {
65 return Err(PrecompileError::Other(format!(
66 "Input should be {G2_INPUT_ITEM_LENGTH} bytes, was {}",
67 input.len()
68 )));
69 }
70
71 let mut input_fps = [&[0; FP_LENGTH]; 4];
72 for i in 0..4 {
73 input_fps[i] = remove_padding(&input[i * PADDED_FP_LENGTH..(i + 1) * PADDED_FP_LENGTH])?;
74 }
75
76 let out = decode_and_check_g2(input_fps[0], input_fps[1], input_fps[2], input_fps[3])?;
77
78 if subgroup_check {
79 if unsafe { !blst_p2_affine_in_g2(&out) } {
92 return Err(PrecompileError::Other("Element not in G2".to_string()));
93 }
94 } else {
95 if unsafe { !blst_p2_affine_on_curve(&out) } {
108 return Err(PrecompileError::Other(
109 "Element not on G2 curve".to_string(),
110 ));
111 }
112 }
113
114 Ok(out)
115}