/ console / network / src / helpers / object.rs
object.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  use crate::prelude::*;
 20  
 21  use anyhow::Result;
 22  use bech32::{self, FromBase32, ToBase32};
 23  use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
 24  use std::borrow::Borrow;
 25  
 26  pub trait Bech32Object<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send>:
 27      From<T>
 28      + Deref<Target = T>
 29      + Clone
 30      + Debug
 31      + Display
 32      + ToBytes
 33      + FromBytes
 34      + PartialEq
 35      + Eq
 36      + Serialize
 37      + DeserializeOwned
 38      + Sync
 39      + Send
 40  {
 41      fn prefix() -> String;
 42  }
 43  
 44  /// Converts a string of 4 characters into a `u32` for a human-readable prefix in Bech32.
 45  #[macro_export]
 46  macro_rules! hrp4 {
 47      ( $persona: expr ) => {{
 48          $crate::const_assert!($persona.len() == 4);
 49          let p = $persona.as_bytes();
 50          u32::from_le_bytes([p[0], p[1], p[2], p[3]])
 51      }};
 52  }
 53  
 54  #[derive(Clone, PartialEq, Eq, Hash)]
 55  pub struct AlphaObject<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32>(T);
 56  
 57  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Bech32Object<T>
 58      for AlphaObject<T, PREFIX>
 59  {
 60      #[inline]
 61      fn prefix() -> String {
 62          String::from_utf8(PREFIX.to_le_bytes().to_vec()).expect("Failed to convert prefix to string")
 63      }
 64  }
 65  
 66  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> From<T>
 67      for AlphaObject<T, PREFIX>
 68  {
 69      #[inline]
 70      fn from(data: T) -> Self {
 71          Self(data)
 72      }
 73  }
 74  
 75  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> FromBytes
 76      for AlphaObject<T, PREFIX>
 77  {
 78      /// Reads data into a buffer.
 79      #[inline]
 80      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
 81          Ok(Self(FromBytes::read_le(&mut reader)?))
 82      }
 83  }
 84  
 85  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> ToBytes
 86      for AlphaObject<T, PREFIX>
 87  {
 88      /// Writes the data to a buffer.
 89      #[inline]
 90      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
 91          self.0.write_le(&mut writer)
 92      }
 93  }
 94  
 95  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> FromStr
 96      for AlphaObject<T, PREFIX>
 97  {
 98      type Err = Error;
 99  
100      /// Reads in a bech32m string.
101      #[inline]
102      fn from_str(string: &str) -> Result<Self, Self::Err> {
103          let (hrp, data, variant) = bech32::decode(string)?;
104          if hrp.as_bytes() != PREFIX.to_le_bytes() {
105              bail!("Invalid prefix for a bech32m hash: {hrp}")
106          };
107          if data.is_empty() {
108              bail!("Bech32m hash data is empty")
109          }
110          if variant != bech32::Variant::Bech32m {
111              bail!("Hash is not a bech32m hash")
112          }
113          Ok(Self::read_le(&*Vec::from_base32(&data)?)?)
114      }
115  }
116  
117  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Display
118      for AlphaObject<T, PREFIX>
119  {
120      #[inline]
121      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
122          bech32::encode_to_fmt(
123              f,
124              &Self::prefix(),
125              self.0.to_bytes_le().expect("Failed to write data as bytes").to_base32(),
126              bech32::Variant::Bech32m,
127          )
128          .expect("Failed to encode in bech32m")
129      }
130  }
131  
132  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Debug
133      for AlphaObject<T, PREFIX>
134  {
135      #[inline]
136      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
137          write!(f, "AlphaObject {{ hrp: {:?}, data: {:?} }}", &Self::prefix(), self.0)
138      }
139  }
140  
141  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Serialize
142      for AlphaObject<T, PREFIX>
143  {
144      #[inline]
145      fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
146          match serializer.is_human_readable() {
147              true => serializer.collect_str(self),
148              false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
149          }
150      }
151  }
152  
153  impl<'de, T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Deserialize<'de>
154      for AlphaObject<T, PREFIX>
155  {
156      #[inline]
157      fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
158          match deserializer.is_human_readable() {
159              true => FromStr::from_str(&String::deserialize(deserializer)?).map_err(de::Error::custom),
160              false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, &Self::prefix()),
161          }
162      }
163  }
164  
165  impl<T: Default + Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Default
166      for AlphaObject<T, PREFIX>
167  {
168      fn default() -> Self {
169          Self(T::default())
170      }
171  }
172  
173  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Deref
174      for AlphaObject<T, PREFIX>
175  {
176      type Target = T;
177  
178      #[inline]
179      fn deref(&self) -> &Self::Target {
180          &self.0
181      }
182  }
183  
184  impl<T: Clone + Debug + ToBytes + FromBytes + PartialEq + Eq + Sync + Send, const PREFIX: u32> Borrow<T>
185      for AlphaObject<T, PREFIX>
186  {
187      #[inline]
188      fn borrow(&self) -> &T {
189          &self.0
190      }
191  }