revm_precompile/bls12_381/
utils.rs1use crate::bls12_381_const::{
3 FP_LENGTH, FP_PAD_BY, G1_LENGTH, PADDED_FP_LENGTH, PADDED_G1_LENGTH, PADDED_G2_LENGTH,
4};
5use crate::PrecompileError;
6
7pub(super) fn remove_fp_padding(input: &[u8]) -> Result<&[u8; FP_LENGTH], PrecompileError> {
9 if input.len() != PADDED_FP_LENGTH {
10 return Err(PrecompileError::Bls12381FpPaddingLength);
11 }
12 let (padding, unpadded) = input.split_at(FP_PAD_BY);
13 if !padding.iter().all(|&x| x == 0) {
14 return Err(PrecompileError::Bls12381FpPaddingInvalid);
15 }
16 Ok(unpadded.try_into().unwrap())
17}
18pub(super) fn remove_g1_padding(input: &[u8]) -> Result<[&[u8; FP_LENGTH]; 2], PrecompileError> {
21 if input.len() != PADDED_G1_LENGTH {
22 return Err(PrecompileError::Bls12381G1PaddingLength);
23 }
24
25 let x = remove_fp_padding(&input[..PADDED_FP_LENGTH])?;
26 let y = remove_fp_padding(&input[PADDED_FP_LENGTH..PADDED_G1_LENGTH])?;
27 Ok([x, y])
28}
29
30pub(super) fn remove_g2_padding(input: &[u8]) -> Result<[&[u8; FP_LENGTH]; 4], PrecompileError> {
33 if input.len() != PADDED_G2_LENGTH {
34 return Err(PrecompileError::Bls12381G2PaddingLength);
35 }
36
37 let mut input_fps = [&[0; FP_LENGTH]; 4];
38 for i in 0..4 {
39 input_fps[i] = remove_fp_padding(&input[i * PADDED_FP_LENGTH..(i + 1) * PADDED_FP_LENGTH])?;
40 }
41 Ok(input_fps)
42}
43
44pub(super) fn pad_g1_point(unpadded: &[u8]) -> [u8; PADDED_G1_LENGTH] {
49 assert_eq!(
50 unpadded.len(),
51 G1_LENGTH,
52 "Invalid unpadded G1 point length"
53 );
54
55 let mut padded = [0u8; PADDED_G1_LENGTH];
56
57 for i in 0..2 {
59 padded[i * PADDED_FP_LENGTH + FP_PAD_BY..(i + 1) * PADDED_FP_LENGTH]
60 .copy_from_slice(&unpadded[i * FP_LENGTH..(i + 1) * FP_LENGTH]);
61 }
62
63 padded
64}
65
66pub(super) fn pad_g2_point(unpadded: &[u8]) -> [u8; PADDED_G2_LENGTH] {
71 assert_eq!(
72 unpadded.len(),
73 4 * FP_LENGTH,
74 "Invalid unpadded G2 point length"
75 );
76
77 let mut padded = [0u8; PADDED_G2_LENGTH];
78
79 for i in 0..4 {
81 padded[i * PADDED_FP_LENGTH + FP_PAD_BY..(i + 1) * PADDED_FP_LENGTH]
82 .copy_from_slice(&unpadded[i * FP_LENGTH..(i + 1) * FP_LENGTH]);
83 }
84
85 padded
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_pad_g1_point_roundtrip() {
94 let mut unpadded = [0u8; G1_LENGTH];
96 for (i, byte) in unpadded.iter_mut().enumerate() {
97 *byte = (i * 2 + 1) as u8;
98 }
99
100 let padded = pad_g1_point(&unpadded);
102
103 let result = remove_g1_padding(&padded).unwrap();
105
106 assert_eq!(result[0], &unpadded[0..FP_LENGTH]);
108 assert_eq!(result[1], &unpadded[FP_LENGTH..G1_LENGTH]);
109 }
110
111 #[test]
112 fn test_pad_g2_point_roundtrip() {
113 let mut unpadded = [0u8; 4 * FP_LENGTH];
115 for (i, byte) in unpadded.iter_mut().enumerate() {
116 *byte = (i * 2 + 1) as u8;
117 }
118
119 let padded = pad_g2_point(&unpadded);
121
122 let result = remove_g2_padding(&padded).unwrap();
124
125 assert_eq!(result[0], &unpadded[0..FP_LENGTH]);
127 assert_eq!(result[1], &unpadded[FP_LENGTH..2 * FP_LENGTH]);
128 assert_eq!(result[2], &unpadded[2 * FP_LENGTH..3 * FP_LENGTH]);
129 assert_eq!(result[3], &unpadded[3 * FP_LENGTH..4 * FP_LENGTH]);
130 }
131}