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