1use alloy_primitives::{B256, Keccak256, U256};
5#[cfg(feature = "rkyv")]
6use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
7#[cfg(feature = "serde")]
8use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
9
10use crate::errors::PreimageOracleError;
11
12#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
14#[repr(u8)]
15#[cfg_attr(
16 feature = "rkyv",
17 derive(Archive, RkyvSerialize, RkyvDeserialize),
18 rkyv(derive(Eq, PartialEq, Ord, PartialOrd, Hash))
19)]
20#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
21pub enum PreimageKeyType {
22 Local = 1,
25 #[default]
28 Keccak256 = 2,
29 GlobalGeneric = 3,
31 Sha256 = 4,
34 Blob = 5,
38 Precompile = 6,
42}
43
44impl TryFrom<u8> for PreimageKeyType {
45 type Error = PreimageOracleError;
46
47 fn try_from(value: u8) -> Result<Self, Self::Error> {
48 let key_type = match value {
49 1 => Self::Local,
50 2 => Self::Keccak256,
51 3 => Self::GlobalGeneric,
52 4 => Self::Sha256,
53 5 => Self::Blob,
54 6 => Self::Precompile,
55 _ => return Err(PreimageOracleError::InvalidPreimageKey),
56 };
57 Ok(key_type)
58 }
59}
60
61#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
70#[cfg_attr(
71 feature = "rkyv",
72 derive(Archive, RkyvSerialize, RkyvDeserialize),
73 rkyv(derive(Eq, PartialEq, Ord, PartialOrd, Hash))
74)]
75#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
76pub struct PreimageKey {
77 data: [u8; 31],
78 key_type: PreimageKeyType,
79}
80
81impl PreimageKey {
82 pub fn new(key: [u8; 32], key_type: PreimageKeyType) -> Self {
85 let mut data = [0u8; 31];
86 data.copy_from_slice(&key[1..]);
87 Self { data, key_type }
88 }
89
90 pub fn new_local(local_ident: u64) -> Self {
93 let mut data = [0u8; 31];
94 data[23..].copy_from_slice(&local_ident.to_be_bytes());
95 Self { data, key_type: PreimageKeyType::Local }
96 }
97
98 pub fn new_keccak256(digest: [u8; 32]) -> Self {
101 Self::new(digest, PreimageKeyType::Keccak256)
102 }
103
104 pub fn new_precompile(precompile_addr: [u8; 20], input: &[u8]) -> Self {
108 let mut data = [0u8; 31];
109
110 let mut hasher = Keccak256::new();
111 hasher.update(precompile_addr);
112 hasher.update(input);
113
114 data.copy_from_slice(&hasher.finalize()[1..]);
115 Self { data, key_type: PreimageKeyType::Precompile }
116 }
117
118 pub const fn key_type(&self) -> PreimageKeyType {
120 self.key_type
121 }
122
123 pub const fn key_value(&self) -> U256 {
125 U256::from_be_slice(self.data.as_slice())
126 }
127}
128
129impl From<PreimageKey> for [u8; 32] {
130 fn from(key: PreimageKey) -> Self {
131 let mut rendered_key = [0u8; 32];
132 rendered_key[0] = key.key_type as u8;
133 rendered_key[1..].copy_from_slice(&key.data);
134 rendered_key
135 }
136}
137
138impl From<PreimageKey> for B256 {
139 fn from(value: PreimageKey) -> Self {
140 let raw: [u8; 32] = value.into();
141 Self::from(raw)
142 }
143}
144
145impl TryFrom<[u8; 32]> for PreimageKey {
146 type Error = PreimageOracleError;
147
148 fn try_from(value: [u8; 32]) -> Result<Self, Self::Error> {
149 let key_type = PreimageKeyType::try_from(value[0])?;
150 Ok(Self::new(value, key_type))
151 }
152}
153
154impl core::fmt::Display for PreimageKey {
155 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
156 let raw: [u8; 32] = (*self).into();
157 write!(f, "{}", B256::from(raw))
158 }
159}
160
161#[cfg(test)]
162mod test {
163 use super::*;
164
165 #[test]
166 fn test_preimage_key_from_u8() {
167 assert_eq!(PreimageKeyType::try_from(1).unwrap(), PreimageKeyType::Local);
168 assert_eq!(PreimageKeyType::try_from(2).unwrap(), PreimageKeyType::Keccak256);
169 assert_eq!(PreimageKeyType::try_from(3).unwrap(), PreimageKeyType::GlobalGeneric);
170 assert_eq!(PreimageKeyType::try_from(4).unwrap(), PreimageKeyType::Sha256);
171 assert_eq!(PreimageKeyType::try_from(5).unwrap(), PreimageKeyType::Blob);
172 assert_eq!(PreimageKeyType::try_from(6).unwrap(), PreimageKeyType::Precompile);
173 assert!(PreimageKeyType::try_from(0).is_err());
174 assert!(PreimageKeyType::try_from(7).is_err());
175 }
176
177 #[test]
178 fn test_preimage_key_new_local() {
179 let key = PreimageKey::new_local(0xFFu64);
180 assert_eq!(key.key_type(), PreimageKeyType::Local);
181 assert_eq!(key.key_value(), U256::from(0xFFu64));
182 }
183
184 #[test]
185 fn test_preimage_key_value() {
186 let key = PreimageKey::new([0xFFu8; 32], PreimageKeyType::Local);
187 assert_eq!(
188 key.key_value(),
189 alloy_primitives::uint!(
190 452312848583266388373324160190187140051835877600158453279131187530910662655_U256
191 )
192 );
193 }
194
195 #[test]
196 fn test_preimage_key_roundtrip_b256() {
197 let key = PreimageKey::new([0xFFu8; 32], PreimageKeyType::Local);
198 let b256: B256 = key.into();
199 let key2 = PreimageKey::try_from(<[u8; 32]>::from(b256)).unwrap();
200 assert_eq!(key, key2);
201 }
202
203 #[test]
204 fn test_preimage_key_display() {
205 let key = PreimageKey::new([0xFFu8; 32], PreimageKeyType::Local);
206 assert_eq!(
207 key.to_string(),
208 "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
209 );
210 }
211
212 #[test]
213 fn test_preimage_keys() {
214 let types = [
215 PreimageKeyType::Local,
216 PreimageKeyType::Keccak256,
217 PreimageKeyType::GlobalGeneric,
218 PreimageKeyType::Sha256,
219 PreimageKeyType::Blob,
220 PreimageKeyType::Precompile,
221 ];
222
223 for key_type in types {
224 let key = PreimageKey::new([0xFFu8; 32], key_type);
225 assert_eq!(key.key_type(), key_type);
226
227 let mut rendered_key = [0xFFu8; 32];
228 rendered_key[0] = key_type as u8;
229 let actual: [u8; 32] = key.into();
230 assert_eq!(actual, rendered_key);
231 }
232 }
233}