aztec_core/abi/
selectors.rs1use ark_ff::{BigInteger, PrimeField};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt;
4
5use super::types::{abi_type_signature, AbiParameter};
6use crate::hash::poseidon2_hash_bytes;
7use crate::types::Fr;
8use crate::Error;
9
10fn strip_0x(s: &str) -> &str {
11 s.strip_prefix("0x").unwrap_or(s)
12}
13
14fn decode_selector_hex(s: &str) -> Result<[u8; 4], Error> {
15 let raw = strip_0x(s);
16 if raw.len() > 8 {
17 return Err(Error::InvalidData(
18 "function selector must fit in 4 bytes".to_owned(),
19 ));
20 }
21 let padded = format!("{raw:0>8}");
22 let bytes = hex::decode(padded).map_err(|e| Error::InvalidData(e.to_string()))?;
23 let mut out = [0u8; 4];
24 out.copy_from_slice(&bytes);
25 Ok(out)
26}
27
28fn field_to_selector_bytes(field: Fr) -> [u8; 4] {
29 let raw = field.0.into_bigint().to_bytes_be();
30 let mut padded = [0u8; 32];
31 padded[32 - raw.len()..].copy_from_slice(&raw);
32 let mut out = [0u8; 4];
33 out.copy_from_slice(&padded[28..]);
34 out
35}
36
37fn selector_bytes_to_field(bytes: [u8; 4]) -> Fr {
38 Fr::from(u64::from(u32::from_be_bytes(bytes)))
39}
40
41fn selector_from_signature(signature: &str) -> [u8; 4] {
42 let hash = poseidon2_hash_bytes(signature.as_bytes());
43 field_to_selector_bytes(hash)
44}
45
46#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
48pub struct FunctionSelector(pub [u8; 4]);
49
50impl FunctionSelector {
51 pub fn from_hex(value: &str) -> Result<Self, Error> {
53 Ok(Self(decode_selector_hex(value)?))
54 }
55
56 pub fn from_field(field: Fr) -> Self {
58 Self(field_to_selector_bytes(field))
59 }
60
61 pub fn from_signature(signature: &str) -> Self {
72 Self(selector_from_signature(signature))
73 }
74
75 pub fn from_name_and_parameters(name: &str, params: &[AbiParameter]) -> Self {
80 let param_sigs: Vec<String> = params.iter().map(|p| abi_type_signature(&p.typ)).collect();
81 let sig = format!("{}({})", name, param_sigs.join(","));
82 Self::from_signature(&sig)
83 }
84
85 pub fn to_field(self) -> Fr {
87 selector_bytes_to_field(self.0)
88 }
89}
90
91impl fmt::Display for FunctionSelector {
92 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93 write!(f, "0x{}", hex::encode(self.0))
94 }
95}
96
97impl Serialize for FunctionSelector {
98 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
99 where
100 S: Serializer,
101 {
102 serializer.serialize_str(&self.to_string())
103 }
104}
105
106impl<'de> Deserialize<'de> for FunctionSelector {
107 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108 where
109 D: Deserializer<'de>,
110 {
111 let s = String::deserialize(deserializer)?;
112 Self::from_hex(&s).map_err(serde::de::Error::custom)
113 }
114}
115
116#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
118pub struct AuthorizationSelector(pub [u8; 4]);
119
120impl AuthorizationSelector {
121 pub fn from_hex(value: &str) -> Result<Self, Error> {
123 Ok(Self(decode_selector_hex(value)?))
124 }
125
126 pub fn from_field(field: Fr) -> Self {
128 Self(field_to_selector_bytes(field))
129 }
130
131 pub fn from_signature(signature: &str) -> Self {
133 Self(selector_from_signature(signature))
134 }
135
136 pub fn to_field(self) -> Fr {
138 selector_bytes_to_field(self.0)
139 }
140}
141
142impl fmt::Display for AuthorizationSelector {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "0x{}", hex::encode(self.0))
145 }
146}
147
148impl Serialize for AuthorizationSelector {
149 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
150 where
151 S: Serializer,
152 {
153 serializer.serialize_str(&self.to_string())
154 }
155}
156
157impl<'de> Deserialize<'de> for AuthorizationSelector {
158 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
159 where
160 D: Deserializer<'de>,
161 {
162 let s = String::deserialize(deserializer)?;
163 Self::from_hex(&s).map_err(serde::de::Error::custom)
164 }
165}
166
167#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
169pub struct EventSelector(pub Fr);
170
171#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
176pub struct NoteSelector(pub u8);
177
178impl NoteSelector {
179 pub const MAX_VALUE: u8 = 127;
181
182 pub fn new(value: u8) -> Result<Self, Error> {
184 if value > Self::MAX_VALUE {
185 return Err(Error::InvalidData(format!(
186 "note selector must fit in 7 bits (got {})",
187 value
188 )));
189 }
190 Ok(Self(value))
191 }
192
193 pub fn empty() -> Self {
195 Self(0)
196 }
197
198 pub fn from_field(field: Fr) -> Result<Self, Error> {
200 let val = field.to_usize();
201 if val > Self::MAX_VALUE as usize {
202 return Err(Error::InvalidData(format!(
203 "note selector must fit in 7 bits (got {})",
204 val
205 )));
206 }
207 Ok(Self(val as u8))
208 }
209
210 pub fn to_field(self) -> Fr {
212 Fr::from(self.0 as u64)
213 }
214
215 pub fn from_hex(value: &str) -> Result<Self, Error> {
217 let raw = value.strip_prefix("0x").unwrap_or(value);
218 let val = u8::from_str_radix(raw, 16).map_err(|e| Error::InvalidData(e.to_string()))?;
219 Self::new(val)
220 }
221}
222
223impl fmt::Display for NoteSelector {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 write!(f, "0x{:02x}", self.0)
226 }
227}
228
229impl Serialize for NoteSelector {
230 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
231 where
232 S: Serializer,
233 {
234 serializer.serialize_u8(self.0)
235 }
236}
237
238impl<'de> Deserialize<'de> for NoteSelector {
239 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
240 where
241 D: Deserializer<'de>,
242 {
243 let val = u8::deserialize(deserializer)?;
244 Self::new(val).map_err(serde::de::Error::custom)
245 }
246}