1#![cfg_attr(not(test), no_std)]
26
27extern crate alloc;
28
29use alloc::string::String;
30use alloc::vec::Vec;
31
32pub mod caller;
33pub mod guest;
34#[cfg(feature = "smt")]
35pub mod merkle_utils;
36pub mod secp256k1;
37pub mod utils;
38
39use caller::ExecutionContext;
40pub use hyli_model::*;
42
43pub use hyli_model::utils as hyli_model_utils;
44
45#[cfg(feature = "tracing")]
46pub use tracing;
47
48#[cfg(feature = "tracing")]
50#[macro_export]
51macro_rules! info {
52 ($($arg:tt)*) => {
53 $crate::tracing::info!($($arg)*);
54 }
55}
56
57#[cfg(feature = "tracing")]
59#[macro_export]
60macro_rules! error {
61 ($($arg:tt)*) => {
62 $crate::tracing::error!($($arg)*);
63 }
64}
65
66#[cfg(all(not(feature = "tracing"), feature = "risc0"))]
68#[macro_export]
69macro_rules! info {
70 ($($arg:tt)*) => {
71 risc0_zkvm::guest::env::log(&format!($($arg)*));
72 }
73}
74
75#[cfg(all(not(feature = "tracing"), not(feature = "risc0")))]
76#[macro_export]
77macro_rules! info {
78 ($($arg:tt)*) => {
79 #[cfg(test)]
81 println!($($arg)*);
82 }
83}
84
85#[cfg(all(not(feature = "tracing"), feature = "risc0"))]
87#[macro_export]
88macro_rules! error {
89 ($($arg:tt)*) => {
90 risc0_zkvm::guest::env::log(&format!($($arg)*));
91 }
92}
93
94#[cfg(all(not(feature = "tracing"), not(feature = "risc0")))]
95#[macro_export]
96macro_rules! error {
97 ($($arg:tt)*) => {
98 #[cfg(test)]
100 println!($($arg)*);
101 }
102}
103
104pub type RunResult = Result<(Vec<u8>, ExecutionContext, Vec<OnchainEffect>), String>;
105
106pub trait ZkContract {
157 fn execute(&mut self, calldata: &Calldata) -> RunResult;
161
162 fn commit(&self) -> StateCommitment;
163
164 fn initialize(&mut self) -> Result<(), String> {
167 Ok(())
168 }
169}
170
171pub trait TransactionalZkContract
172where
173 Self: ZkContract,
174{
175 type State;
176 fn initial_state(&self) -> Self::State;
177
178 fn revert(&mut self, initial_state: Self::State);
179
180 fn on_success(&mut self) -> StateCommitment {
181 self.commit()
182 }
183}
184
185pub trait FullStateRevert {}
186
187impl<T> TransactionalZkContract for T
188where
189 T: FullStateRevert,
190 Self: Sized + Clone + ZkContract,
191{
192 type State = Self;
193
194 fn initial_state(&self) -> Self::State {
195 self.clone()
196 }
197
198 fn revert(&mut self, initial_state: Self::State) {
199 *self = initial_state;
200 }
201}
202
203pub const fn to_u8_array(val: &[u32; 8]) -> [u8; 32] {
204 [
205 (val[0] & 0xFF) as u8,
206 ((val[0] >> 8) & 0xFF) as u8,
207 ((val[0] >> 16) & 0xFF) as u8,
208 ((val[0] >> 24) & 0xFF) as u8,
209 (val[1] & 0xFF) as u8,
210 ((val[1] >> 8) & 0xFF) as u8,
211 ((val[1] >> 16) & 0xFF) as u8,
212 ((val[1] >> 24) & 0xFF) as u8,
213 (val[2] & 0xFF) as u8,
214 ((val[2] >> 8) & 0xFF) as u8,
215 ((val[2] >> 16) & 0xFF) as u8,
216 ((val[2] >> 24) & 0xFF) as u8,
217 (val[3] & 0xFF) as u8,
218 ((val[3] >> 8) & 0xFF) as u8,
219 ((val[3] >> 16) & 0xFF) as u8,
220 ((val[3] >> 24) & 0xFF) as u8,
221 (val[4] & 0xFF) as u8,
222 ((val[4] >> 8) & 0xFF) as u8,
223 ((val[4] >> 16) & 0xFF) as u8,
224 ((val[4] >> 24) & 0xFF) as u8,
225 (val[5] & 0xFF) as u8,
226 ((val[5] >> 8) & 0xFF) as u8,
227 ((val[5] >> 16) & 0xFF) as u8,
228 ((val[5] >> 24) & 0xFF) as u8,
229 (val[6] & 0xFF) as u8,
230 ((val[6] >> 8) & 0xFF) as u8,
231 ((val[6] >> 16) & 0xFF) as u8,
232 ((val[6] >> 24) & 0xFF) as u8,
233 (val[7] & 0xFF) as u8,
234 ((val[7] >> 8) & 0xFF) as u8,
235 ((val[7] >> 16) & 0xFF) as u8,
236 ((val[7] >> 24) & 0xFF) as u8,
237 ]
238}
239
240const fn byte_to_u8(byte: u8) -> u8 {
241 match byte {
242 b'0'..=b'9' => byte - b'0',
243 b'a'..=b'f' => byte - b'a' + 10,
244 b'A'..=b'F' => byte - b'A' + 10,
245 _ => 0,
246 }
247}
248
249#[allow(
250 clippy::indexing_slicing,
251 reason = "const block, shouldn't be used at runtime."
252)]
253pub const fn str_to_u8(s: &str) -> [u8; 32] {
254 let mut bytes = [0u8; 32];
255 let chrs = s.as_bytes();
256 let mut i = 0;
257 while i < 32 {
258 bytes[i] = (byte_to_u8(chrs[i * 2]) << 4) | byte_to_u8(chrs[i * 2 + 1]);
259 i += 1;
260 }
261 bytes
262}
263
264#[cfg(test)]
265mod tests {
266 use super::*;
267 use alloc::{format, string::ToString, vec};
268
269 #[test]
270 fn test_identity_from_string() {
271 let identity_str = "test_identity".to_string();
272 let identity = Identity::from(identity_str.clone());
273 assert_eq!(identity.0, identity_str);
274 }
275
276 #[test]
277 fn test_identity_from_str() {
278 let identity_str = "test_identity";
279 let identity = Identity::from(identity_str);
280 assert_eq!(identity.0, identity_str.to_string());
281 }
282
283 #[test]
284 fn test_txhash_from_string() {
285 let txhash_str = "746573745f747868617368".to_string();
286 let txhash = TxHash::from_hex(&txhash_str).expect("txhash hex");
287 assert_eq!(txhash.0, b"test_txhash".to_vec());
288 }
289
290 #[test]
291 fn test_txhash_from_str() {
292 let txhash_str = "746573745f747868617368";
293 let txhash = TxHash::from_hex(txhash_str).expect("txhash hex");
294 assert_eq!(txhash.0, b"test_txhash".to_vec());
295 }
296
297 #[test]
298 fn test_txhash_new() {
299 let txhash = TxHash::new(b"test_txhash".to_vec());
300 assert_eq!(txhash.0, b"test_txhash".to_vec());
301 }
302
303 #[test]
304 fn test_blobindex_from_u32() {
305 let index = 42;
306 let blob_index = BlobIndex::from(index);
307 assert_eq!(blob_index.0, index);
308 }
309
310 #[test]
311 fn test_txhash_display() {
312 let txhash_str = "746573745f747868617368";
313 let txhash = TxHash::from_hex(txhash_str).expect("txhash hex");
314 assert_eq!(format!("{txhash}"), txhash_str);
315 }
316
317 #[test]
318 fn test_blobindex_display() {
319 let index = 42;
320 let blob_index = BlobIndex::from(index);
321 assert_eq!(format!("{blob_index}"), index.to_string());
322 }
323
324 #[test]
325 fn test_state_commitment_encoding() {
326 let state_commitment = StateCommitment(vec![1, 2, 3, 4]);
327 let encoded = borsh::to_vec(&state_commitment).expect("Failed to encode StateCommitment");
328 let decoded: StateCommitment =
329 borsh::from_slice(&encoded).expect("Failed to decode StateCommitment");
330 assert_eq!(state_commitment, decoded);
331 }
332
333 #[test]
334 fn test_identity_encoding() {
335 let identity = Identity::new("test_identity");
336 let encoded = borsh::to_vec(&identity).expect("Failed to encode Identity");
337 let decoded: Identity = borsh::from_slice(&encoded).expect("Failed to decode Identity");
338 assert_eq!(identity, decoded);
339 }
340
341 #[test]
342 fn test_txhash_encoding() {
343 let txhash = TxHash::from_hex("746573745f747868617368").expect("txhash hex");
344 let encoded = borsh::to_vec(&txhash).expect("Failed to encode TxHash");
345 let decoded: TxHash = borsh::from_slice(&encoded).expect("Failed to decode TxHash");
346 assert_eq!(txhash, decoded);
347 }
348
349 #[test]
350 fn test_blobindex_encoding() {
351 let blob_index = BlobIndex(42);
352 let encoded = borsh::to_vec(&blob_index).expect("Failed to encode BlobIndex");
353 let decoded: BlobIndex = borsh::from_slice(&encoded).expect("Failed to decode BlobIndex");
354 assert_eq!(blob_index, decoded);
355 }
356
357 #[test]
358 fn test_blobdata_encoding() {
359 let blob_data = BlobData(vec![1, 2, 3, 4]);
360 let encoded = borsh::to_vec(&blob_data).expect("Failed to encode BlobData");
361 let decoded: BlobData = borsh::from_slice(&encoded).expect("Failed to decode BlobData");
362 assert_eq!(blob_data, decoded);
363 }
364}