1use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub struct Hash(pub [u8; 32]);
15
16impl Hash {
17 pub fn new(bytes: [u8; 32]) -> Self {
19 Self(bytes)
20 }
21
22 pub fn as_bytes(&self) -> &[u8] {
24 &self.0
25 }
26
27 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
31 if bytes.len() == 32 {
32 let mut arr = [0u8; 32];
33 arr.copy_from_slice(bytes);
34 Some(Self(arr))
35 } else {
36 None
37 }
38 }
39
40 pub fn zero() -> Self {
42 Self([0u8; 32])
43 }
44
45 pub fn combine(&self, other: &Hash) -> Self {
50 use sha2::{Digest, Sha256};
51 let mut hasher = Sha256::new();
52 hasher.update(self.0);
53 hasher.update(other.0);
54 let result = hasher.finalize();
55 Self(result.into())
56 }
57}
58
59impl fmt::Display for Hash {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 write!(f, "{}", hex::encode(self.0))
62 }
63}
64
65impl From<[u8; 32]> for Hash {
66 fn from(bytes: [u8; 32]) -> Self {
67 Self(bytes)
68 }
69}
70
71impl Default for Hash {
72 fn default() -> Self {
73 Self::zero()
74 }
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
82pub struct Address(pub [u8; 32]);
83
84impl Address {
85 pub fn new(bytes: [u8; 32]) -> Self {
87 Self(bytes)
88 }
89
90 pub fn as_bytes(&self) -> &[u8] {
92 &self.0
93 }
94
95 pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
99 if bytes.len() == 32 {
100 let mut arr = [0u8; 32];
101 arr.copy_from_slice(bytes);
102 Some(Self(arr))
103 } else {
104 None
105 }
106 }
107
108 pub fn zero() -> Self {
110 Self([0u8; 32])
111 }
112
113 pub fn to_base58(&self) -> String {
115 bs58::encode(&self.0).into_string()
116 }
117
118 pub fn from_base58(s: &str) -> Result<Self, bs58::decode::Error> {
120 let bytes = bs58::decode(s).into_vec()?;
121 Self::from_bytes(&bytes).ok_or(bs58::decode::Error::BufferTooSmall)
122 }
123
124 pub fn is_valid_hex(s: &str) -> bool {
128 let s = s.strip_prefix("0x").unwrap_or(s);
129 s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())
130 }
131
132 pub fn from_hex(s: &str) -> Result<Self, crate::error::TenzroError> {
138 Self::from_hex_checksummed(s)
139 }
140
141 pub fn from_hex_checksummed(s: &str) -> Result<Self, crate::error::TenzroError> {
146 let s = s.strip_prefix("0x").unwrap_or(s);
147
148 if s.len() == 40 {
150 let bytes = hex::decode(s).map_err(|e| crate::error::TenzroError::InvalidAddress(format!("Invalid hex: {}", e)))?;
152
153 use sha3::{Digest, Keccak256};
155 let mut hasher = Keccak256::new();
156 hasher.update(s.to_lowercase().as_bytes());
157 let hash = hasher.finalize();
158
159 for (i, c) in s.chars().enumerate() {
161 if c.is_alphabetic() {
162 let hash_byte = hash[i / 2];
163 let hash_nibble = if i % 2 == 0 {
164 hash_byte >> 4
165 } else {
166 hash_byte & 0x0f
167 };
168
169 let should_be_uppercase = hash_nibble >= 8;
170 if c.is_uppercase() != should_be_uppercase {
171 return Err(crate::error::TenzroError::InvalidAddress("Invalid EIP-55 checksum".to_string()));
172 }
173 }
174 }
175
176 let mut addr = [0u8; 32];
178 addr[12..].copy_from_slice(&bytes);
179 Ok(Self(addr))
180 } else if s.len() == 64 {
181 let bytes = hex::decode(s).map_err(|e| crate::error::TenzroError::InvalidAddress(format!("Invalid hex: {}", e)))?;
183 let mut addr = [0u8; 32];
184 addr.copy_from_slice(&bytes);
185 Ok(Self(addr))
186 } else {
187 Err(crate::error::TenzroError::InvalidAddress(format!("Invalid address length: expected 40 or 64 hex chars, got {}", s.len())))
188 }
189 }
190}
191
192impl fmt::Display for Address {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 write!(f, "{}", self.to_base58())
195 }
196}
197
198impl From<[u8; 32]> for Address {
199 fn from(bytes: [u8; 32]) -> Self {
200 Self(bytes)
201 }
202}
203
204impl Default for Address {
205 fn default() -> Self {
206 Self::zero()
207 }
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
218#[derive(Default)]
219pub struct Signature {
220 #[serde(deserialize_with = "crate::validation::bounded_signature_bytes")]
222 pub bytes: Vec<u8>,
223 #[serde(deserialize_with = "crate::validation::bounded_public_key_bytes")]
225 pub public_key: Vec<u8>,
226}
227
228impl Signature {
229 pub fn new(bytes: Vec<u8>, public_key: Vec<u8>) -> Self {
231 Self { bytes, public_key }
232 }
233}
234
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
240pub struct BlockHeight(pub u64);
241
242impl BlockHeight {
243 pub fn new(height: u64) -> Self {
245 Self(height)
246 }
247
248 pub fn genesis() -> Self {
250 Self(0)
251 }
252
253 pub fn next(self) -> Self {
255 Self(self.0 + 1)
256 }
257
258 pub fn prev(self) -> Option<Self> {
260 if self.0 > 0 {
261 Some(Self(self.0 - 1))
262 } else {
263 None
264 }
265 }
266}
267
268impl fmt::Display for BlockHeight {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 write!(f, "{}", self.0)
271 }
272}
273
274impl From<u64> for BlockHeight {
275 fn from(height: u64) -> Self {
276 Self(height)
277 }
278}
279
280impl Default for BlockHeight {
281 fn default() -> Self {
282 Self::genesis()
283 }
284}
285
286impl BlockHeight {
287 pub fn as_u64(&self) -> u64 {
289 self.0
290 }
291}
292
293impl std::ops::Add<u64> for BlockHeight {
294 type Output = Self;
295
296 fn add(self, rhs: u64) -> Self::Output {
297 Self(self.0 + rhs)
298 }
299}
300
301impl std::ops::Sub<u64> for BlockHeight {
302 type Output = Self;
303
304 fn sub(self, rhs: u64) -> Self::Output {
305 Self(self.0.saturating_sub(rhs))
306 }
307}
308
309#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
314pub struct Nonce(pub u64);
315
316impl Nonce {
317 pub fn new(value: u64) -> Self {
319 Self(value)
320 }
321
322 pub fn initial() -> Self {
324 Self(0)
325 }
326
327 pub fn next(self) -> Self {
329 Self(self.0 + 1)
330 }
331}
332
333impl fmt::Display for Nonce {
334 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335 write!(f, "{}", self.0)
336 }
337}
338
339impl From<u64> for Nonce {
340 fn from(value: u64) -> Self {
341 Self(value)
342 }
343}
344
345#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
349#[derive(Default)]
350pub struct Timestamp(pub i64);
351
352
353impl Timestamp {
354 pub fn new(millis: i64) -> Self {
356 Self(millis)
357 }
358
359 pub fn now() -> Self {
361 Self(chrono::Utc::now().timestamp_millis())
362 }
363
364 pub fn as_millis(&self) -> i64 {
366 self.0
367 }
368
369 pub fn as_secs(&self) -> i64 {
371 self.0 / 1000
372 }
373}
374
375impl From<Timestamp> for std::time::SystemTime {
376 fn from(ts: Timestamp) -> Self {
377 std::time::UNIX_EPOCH + std::time::Duration::from_millis(ts.0 as u64)
378 }
379}
380
381impl fmt::Display for Timestamp {
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 write!(f, "{}", self.0)
384 }
385}
386
387impl From<i64> for Timestamp {
388 fn from(millis: i64) -> Self {
389 Self(millis)
390 }
391}
392
393#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
400pub struct ChainId(pub u64);
401
402impl<'de> Deserialize<'de> for ChainId {
403 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
404 where
405 D: serde::Deserializer<'de>,
406 {
407 let value = u64::deserialize(deserializer)?;
408 let chain = ChainId(value);
409 crate::validation::validate_chain_id(chain).map_err(serde::de::Error::custom)?;
410 Ok(chain)
411 }
412}
413
414impl ChainId {
415 pub const MAINNET: Self = Self(1);
417
418 pub const TESTNET: Self = Self(1337);
420
421 pub const DEVNET: Self = Self(31337);
423
424 pub fn new(id: u64) -> Self {
428 Self(id)
429 }
430
431 pub fn try_new(id: u64) -> Result<Self, crate::error::TenzroError> {
437 let chain = Self(id);
438 crate::validation::validate_chain_id(chain)?;
439 Ok(chain)
440 }
441
442 pub fn mainnet() -> Self {
444 Self::MAINNET
445 }
446
447 pub fn testnet() -> Self {
449 Self::TESTNET
450 }
451
452 pub fn devnet() -> Self {
454 Self::DEVNET
455 }
456
457 pub fn as_u64(&self) -> u64 {
459 self.0
460 }
461
462 pub fn is_valid(&self) -> bool {
466 crate::validation::validate_chain_id(*self).is_ok()
467 }
468}
469
470impl fmt::Display for ChainId {
471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 write!(f, "{}", self.0)
473 }
474}
475
476impl From<u64> for ChainId {
477 fn from(id: u64) -> Self {
478 Self(id)
479 }
480}
481
482pub mod u128_serde {
501 use serde::de::{self, Visitor};
502 use serde::{Deserializer, Serializer};
503 use std::fmt;
504
505 pub fn serialize<S: Serializer>(value: &u128, serializer: S) -> Result<S::Ok, S::Error> {
506 if *value <= u64::MAX as u128 {
507 serializer.serialize_u64(*value as u64)
508 } else {
509 serializer.serialize_str(&value.to_string())
510 }
511 }
512
513 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u128, D::Error> {
514 struct U128Visitor;
515
516 impl<'de> Visitor<'de> for U128Visitor {
517 type Value = u128;
518
519 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
520 f.write_str("a non-negative integer or decimal string fitting in u128")
521 }
522
523 fn visit_u64<E: de::Error>(self, v: u64) -> Result<u128, E> {
524 Ok(v as u128)
525 }
526
527 fn visit_u128<E: de::Error>(self, v: u128) -> Result<u128, E> {
528 Ok(v)
529 }
530
531 fn visit_i64<E: de::Error>(self, v: i64) -> Result<u128, E> {
532 if v < 0 {
533 Err(E::custom(format!("negative integer {v} is not a valid u128")))
534 } else {
535 Ok(v as u128)
536 }
537 }
538
539 fn visit_i128<E: de::Error>(self, v: i128) -> Result<u128, E> {
540 if v < 0 {
541 Err(E::custom(format!("negative integer {v} is not a valid u128")))
542 } else {
543 Ok(v as u128)
544 }
545 }
546
547 fn visit_str<E: de::Error>(self, s: &str) -> Result<u128, E> {
548 s.parse::<u128>()
549 .map_err(|e| E::custom(format!("invalid u128 string {s:?}: {e}")))
550 }
551
552 fn visit_string<E: de::Error>(self, s: String) -> Result<u128, E> {
553 self.visit_str(&s)
554 }
555 }
556
557 deserializer.deserialize_any(U128Visitor)
558 }
559}
560
561pub mod u128_serde_opt {
568 use serde::de::{self, Visitor};
569 use serde::{Deserializer, Serializer};
570 use std::fmt;
571
572 pub fn serialize<S: Serializer>(
573 value: &Option<u128>,
574 serializer: S,
575 ) -> Result<S::Ok, S::Error> {
576 match value {
577 None => serializer.serialize_none(),
578 Some(v) if *v <= u64::MAX as u128 => serializer.serialize_u64(*v as u64),
579 Some(v) => serializer.serialize_str(&v.to_string()),
580 }
581 }
582
583 pub fn deserialize<'de, D: Deserializer<'de>>(
584 deserializer: D,
585 ) -> Result<Option<u128>, D::Error> {
586 struct OptU128Visitor;
587
588 impl<'de> Visitor<'de> for OptU128Visitor {
589 type Value = Option<u128>;
590
591 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
592 f.write_str("null, a non-negative integer, or a decimal string fitting in u128")
593 }
594
595 fn visit_unit<E: de::Error>(self) -> Result<Option<u128>, E> {
596 Ok(None)
597 }
598
599 fn visit_none<E: de::Error>(self) -> Result<Option<u128>, E> {
600 Ok(None)
601 }
602
603 fn visit_some<D2: Deserializer<'de>>(
604 self,
605 deserializer: D2,
606 ) -> Result<Option<u128>, D2::Error> {
607 super::u128_serde::deserialize(deserializer).map(Some)
608 }
609
610 fn visit_u64<E: de::Error>(self, v: u64) -> Result<Option<u128>, E> {
611 Ok(Some(v as u128))
612 }
613
614 fn visit_u128<E: de::Error>(self, v: u128) -> Result<Option<u128>, E> {
615 Ok(Some(v))
616 }
617
618 fn visit_i64<E: de::Error>(self, v: i64) -> Result<Option<u128>, E> {
619 if v < 0 {
620 Err(E::custom(format!("negative integer {v} is not a valid u128")))
621 } else {
622 Ok(Some(v as u128))
623 }
624 }
625
626 fn visit_i128<E: de::Error>(self, v: i128) -> Result<Option<u128>, E> {
627 if v < 0 {
628 Err(E::custom(format!("negative integer {v} is not a valid u128")))
629 } else {
630 Ok(Some(v as u128))
631 }
632 }
633
634 fn visit_str<E: de::Error>(self, s: &str) -> Result<Option<u128>, E> {
635 s.parse::<u128>()
636 .map(Some)
637 .map_err(|e| E::custom(format!("invalid u128 string {s:?}: {e}")))
638 }
639
640 fn visit_string<E: de::Error>(self, s: String) -> Result<Option<u128>, E> {
641 self.visit_str(&s)
642 }
643 }
644
645 deserializer.deserialize_any(OptU128Visitor)
646 }
647}
648
649#[cfg(test)]
650mod u128_serde_tests {
651 use serde::{Deserialize, Serialize};
652
653 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
654 struct Wrap {
655 #[serde(with = "super::u128_serde")]
656 v: u128,
657 }
658
659 #[test]
660 fn round_trips_small_value_as_number() {
661 let w = Wrap { v: 42 };
662 let json = serde_json::to_string(&w).unwrap();
663 assert_eq!(json, r#"{"v":42}"#);
664 let back: Wrap = serde_json::from_str(&json).unwrap();
665 assert_eq!(back, w);
666 }
667
668 #[test]
669 fn round_trips_large_value_as_string() {
670 let w = Wrap { v: 5_000_000_000_000_000_000_000u128 };
671 let json = serde_json::to_string(&w).unwrap();
672 assert_eq!(json, r#"{"v":"5000000000000000000000"}"#);
673 let back: Wrap = serde_json::from_str(&json).unwrap();
674 assert_eq!(back, w);
675 }
676
677 #[test]
678 fn deserializes_large_raw_number() {
679 let json = r#"{"v":5000000000000000000000}"#;
681 let back: Wrap = serde_json::from_str(json).unwrap();
682 assert_eq!(back.v, 5_000_000_000_000_000_000_000u128);
683 }
684
685 #[test]
686 fn deserializes_string_at_u64_boundary() {
687 let json = r#"{"v":"18446744073709551616"}"#; let back: Wrap = serde_json::from_str(json).unwrap();
689 assert_eq!(back.v, (u64::MAX as u128) + 1);
690 }
691
692 #[test]
693 fn rejects_negative_string() {
694 let json = r#"{"v":"-1"}"#;
695 assert!(serde_json::from_str::<Wrap>(json).is_err());
696 }
697
698 #[test]
699 fn rejects_negative_number() {
700 let json = r#"{"v":-1}"#;
701 assert!(serde_json::from_str::<Wrap>(json).is_err());
702 }
703}