1use crate::idl::BLSDomainSeparator;
2use solana_alt_bn128_bls::{BLSError, G1Point, PrivKey as BLSPrivKey, Sha256Normalized};
3use solana_program::{hash::hashv, pubkey::Pubkey};
4
5#[cfg(feature = "transactions")]
6pub type X25519PubKey = x25519_dalek::PublicKey;
7#[cfg(feature = "transactions")]
8pub type X25519PrivKey = x25519_dalek::StaticSecret;
9
10pub const MAX_REALLOC_SIZE_PER_IX: usize = 10240; pub const MAX_SOL_ACCOUNT_SIZE_BYTES: usize = 10485760; pub const METADATA_SIZE_RAW_CIRCUIT_ACC: usize = 9;
18
19pub const MAX_RECOVERY_PEERS: usize = 100;
21
22pub const MIN_RECOVERY_PEERS: usize = 4;
24
25pub const MAX_RAW_CIRCUIT_BYTES_PER_ACC: usize =
27 MAX_SOL_ACCOUNT_SIZE_BYTES - METADATA_SIZE_RAW_CIRCUIT_ACC;
28
29pub(crate) fn sha256(vals: &[&[u8]]) -> [u8; 32] {
30 hashv(vals).to_bytes()
31}
32
33pub fn generate_bls_pop_signature(
38 bls_privkey: &BLSPrivKey,
39 bls_pubkey_bytes: &[u8; 64],
40 operator_pubkey: &Pubkey,
41) -> Result<[u8; 64], BLSError> {
42 let pop_message = [
43 &[BLSDomainSeparator::PoP as u8][..],
44 operator_pubkey.as_ref(),
45 bls_pubkey_bytes.as_ref(),
46 ]
47 .concat();
48
49 let signature: G1Point = bls_privkey.sign::<Sha256Normalized, _>(&pop_message)?;
50 Ok(signature.0)
51}
52
53pub fn parse_bls_keypair(keypair_str: &str) -> Result<BLSPrivKey, BLSError> {
54 let key_array =
55 parse_byte_array::<32>(keypair_str).map_err(|_| BLSError::SerializationError)?;
56 Ok(BLSPrivKey(key_array))
57}
58
59pub fn parse_byte_array<const N: usize>(bytes_str: &str) -> Result<[u8; N], String> {
64 let bytes_str = bytes_str.trim();
65 if !bytes_str.starts_with('[') || !bytes_str.ends_with(']') {
66 return Err("Invalid byte array format".to_string());
67 }
68 let inner = &bytes_str[1..bytes_str.len() - 1];
69 let bytes: Vec<u8> = inner
70 .split(',')
71 .map(|s| s.trim().parse::<u8>())
72 .collect::<Result<Vec<u8>, _>>()
73 .map_err(|_| "Failed to parse byte array".to_string())?;
74 let byte_array: [u8; N] = bytes
75 .try_into()
76 .map_err(|_| "Failed to parse byte array".to_string())?;
77 Ok(byte_array)
78}
79
80pub fn serialize_bls_keypair(keypair: &BLSPrivKey) -> String {
81 format!("{:?}", keypair.0)
82}
83
84#[cfg(feature = "transactions")]
85pub fn serialize_x25519_keypair(keypair: &X25519PrivKey) -> Result<String, serde_json::Error> {
86 serde_json::to_string(&keypair.as_bytes())
87}
88
89#[cfg(feature = "transactions")]
90pub fn parse_x25519_keypair(keypair_str: &str) -> Result<X25519PrivKey, serde_json::Error> {
91 serde_json::from_str(keypair_str)
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_bls_keypair_round_trip() {
100 let original = BLSPrivKey([
102 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
103 25, 26, 27, 28, 29, 30, 31, 32,
104 ]);
105
106 let serialized = serialize_bls_keypair(&original);
108
109 let parsed = parse_bls_keypair(&serialized).expect("Failed to parse serialized keypair");
111
112 assert_eq!(original.0, parsed.0);
114 }
115
116 #[test]
117 fn test_bls_keypair_serialize_format() {
118 let keypair = BLSPrivKey([
119 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
120 25, 26, 27, 28, 29, 30, 31, 32,
121 ]);
122 let serialized = serialize_bls_keypair(&keypair);
123
124 assert!(serialized.starts_with('['));
126 assert!(serialized.ends_with(']'));
127 assert!(serialized.contains(", "));
128 }
129
130 #[test]
131 fn test_bls_keypair_parse_valid() {
132 let input = "[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]";
133 let parsed = parse_bls_keypair(input).expect("Failed to parse valid keypair");
134
135 assert_eq!(parsed.0[0], 1);
136 assert_eq!(parsed.0[31], 32);
137 }
138
139 #[test]
140 fn test_bls_keypair_parse_with_whitespace() {
141 let input = " [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] ";
142 let parsed = parse_bls_keypair(input).expect("Failed to parse keypair with whitespace");
143
144 assert_eq!(parsed.0[0], 1);
145 assert_eq!(parsed.0[31], 32);
146 }
147
148 #[test]
149 fn test_bls_keypair_parse_invalid_format() {
150 let inputs = vec!["not an array", "[1, 2, 3", "1, 2, 3]", "{1, 2, 3}", ""];
151
152 for input in inputs {
153 assert!(
154 parse_bls_keypair(input).is_err(),
155 "Should fail for input: {}",
156 input
157 );
158 }
159 }
160
161 #[test]
162 fn test_bls_keypair_parse_wrong_length() {
163 let input = "[1, 2, 3]";
165 assert!(parse_bls_keypair(input).is_err());
166
167 let input = "[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]";
169 assert!(parse_bls_keypair(input).is_err());
170 }
171
172 #[test]
173 fn test_bls_keypair_parse_invalid_numbers() {
174 let input = "[1, 2, abc, 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]";
176 assert!(parse_bls_keypair(input).is_err());
177
178 let input = "[256, 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]";
180 assert!(parse_bls_keypair(input).is_err());
181 }
182}