kaspa_consensus_core/
subnets.rs1use std::fmt::{Debug, Display, Formatter};
2use std::str::{self, FromStr};
3
4use borsh::{BorshDeserialize, BorshSerialize};
5use kaspa_utils::hex::{FromHex, ToHex};
6use kaspa_utils::{serde_impl_deser_fixed_bytes_ref, serde_impl_ser_fixed_bytes_ref};
7use thiserror::Error;
8
9pub const SUBNETWORK_ID_SIZE: usize = 20;
11
12#[derive(Clone, Default, Eq, PartialEq, Ord, PartialOrd, Hash, BorshSerialize, BorshDeserialize)]
14pub struct SubnetworkId([u8; SUBNETWORK_ID_SIZE]);
15
16impl Debug for SubnetworkId {
17 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("SubnetworkId").field("", &self.to_hex()).finish()
19 }
20}
21
22serde_impl_ser_fixed_bytes_ref!(SubnetworkId, SUBNETWORK_ID_SIZE);
23serde_impl_deser_fixed_bytes_ref!(SubnetworkId, SUBNETWORK_ID_SIZE);
24
25impl AsRef<[u8; SUBNETWORK_ID_SIZE]> for SubnetworkId {
26 fn as_ref(&self) -> &[u8; SUBNETWORK_ID_SIZE] {
27 &self.0
28 }
29}
30
31impl AsRef<[u8]> for SubnetworkId {
32 fn as_ref(&self) -> &[u8] {
33 &self.0
34 }
35}
36
37impl From<[u8; SUBNETWORK_ID_SIZE]> for SubnetworkId {
38 fn from(value: [u8; SUBNETWORK_ID_SIZE]) -> Self {
39 Self::from_bytes(value)
40 }
41}
42
43impl SubnetworkId {
44 pub const fn from_byte(b: u8) -> SubnetworkId {
45 let mut bytes = [0u8; SUBNETWORK_ID_SIZE];
46 bytes[0] = b;
47 SubnetworkId(bytes)
48 }
49
50 pub const fn from_bytes(bytes: [u8; SUBNETWORK_ID_SIZE]) -> SubnetworkId {
51 SubnetworkId(bytes)
52 }
53
54 #[inline]
58 pub fn is_builtin(&self) -> bool {
59 *self == SUBNETWORK_ID_COINBASE || *self == SUBNETWORK_ID_REGISTRY
60 }
61
62 #[inline]
64 pub fn is_native(&self) -> bool {
65 *self == SUBNETWORK_ID_NATIVE
66 }
67
68 #[inline]
70 pub fn is_builtin_or_native(&self) -> bool {
71 self.is_native() || self.is_builtin()
72 }
73}
74
75#[derive(Error, Debug, Clone)]
76pub enum SubnetworkConversionError {
77 #[error(transparent)]
78 SliceError(#[from] std::array::TryFromSliceError),
79
80 #[error(transparent)]
81 HexError(#[from] faster_hex::Error),
82}
83
84impl TryFrom<&[u8]> for SubnetworkId {
85 type Error = SubnetworkConversionError;
86
87 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
88 let bytes = <[u8; SUBNETWORK_ID_SIZE]>::try_from(value)?;
89 Ok(Self(bytes))
90 }
91}
92
93impl Display for SubnetworkId {
94 #[inline]
95 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96 let mut hex = [0u8; SUBNETWORK_ID_SIZE * 2];
97 faster_hex::hex_encode(&self.0, &mut hex).expect("The output is exactly twice the size of the input");
98 f.write_str(str::from_utf8(&hex).expect("hex is always valid UTF-8"))
99 }
100}
101
102impl ToHex for SubnetworkId {
103 fn to_hex(&self) -> String {
104 let mut hex = [0u8; SUBNETWORK_ID_SIZE * 2];
105 faster_hex::hex_encode(&self.0, &mut hex).expect("The output is exactly twice the size of the input");
106 str::from_utf8(&hex).expect("hex is always valid UTF-8").to_string()
107 }
108}
109
110impl FromStr for SubnetworkId {
111 type Err = SubnetworkConversionError;
112
113 #[inline]
114 fn from_str(hex_str: &str) -> Result<Self, Self::Err> {
115 let mut bytes = [0u8; SUBNETWORK_ID_SIZE];
116 faster_hex::hex_decode(hex_str.as_bytes(), &mut bytes)?;
117 Ok(Self(bytes))
118 }
119}
120
121impl FromHex for SubnetworkId {
122 type Error = SubnetworkConversionError;
123 fn from_hex(hex_str: &str) -> Result<Self, Self::Error> {
124 let mut bytes = [0u8; SUBNETWORK_ID_SIZE];
125 faster_hex::hex_decode(hex_str.as_bytes(), &mut bytes)?;
126 Ok(Self(bytes))
127 }
128}
129
130pub const SUBNETWORK_ID_NATIVE: SubnetworkId = SubnetworkId::from_byte(0);
132
133pub const SUBNETWORK_ID_COINBASE: SubnetworkId = SubnetworkId::from_byte(1);
135
136pub const SUBNETWORK_ID_REGISTRY: SubnetworkId = SubnetworkId::from_byte(2);