1use bincode::{Decode, Encode};
2use ed25519_dalek::SigningKey;
3use ed25519_dalek::ed25519::Error;
4use ed25519_dalek::ed25519::signature::SignerMut;
5use ed25519_dalek::{Signature as DalekSignature, VerifyingKey};
6use num_bigint::BigUint;
7use randomx_rs::{RandomXCache, RandomXDataset, RandomXFlag, RandomXVM};
8use serde::{Deserialize, Serialize};
9use std::cell::RefCell;
10use std::fmt;
11use std::ops::Deref;
12use std::sync::OnceLock;
13use std::sync::atomic::{AtomicBool, Ordering};
14
15use keys::{Private, Public};
16
17pub mod keys;
19
20pub mod merkle_tree;
22
23pub mod address_inclusion_filter;
25
26pub const RANDOMX_SEED: &[u8] = b"snap-coin-testnet";
27
28#[derive(Clone)]
30struct SharedDataset(RandomXDataset);
31
32unsafe impl Sync for SharedDataset {}
34unsafe impl Send for SharedDataset {}
35
36static DATASET: OnceLock<SharedDataset> = OnceLock::new();
37static IS_LIGHT_MODE: AtomicBool = AtomicBool::new(true);
38
39pub fn randomx_use_full_mode() {
42 IS_LIGHT_MODE.store(false, Ordering::SeqCst);
43}
44
45fn get_dataset() -> RandomXDataset {
47 let dataset = DATASET.get_or_init(|| {
48 println!("Creating RandomX dataset...");
49 let flags = RandomXFlag::FLAG_FULL_MEM | RandomXFlag::FLAG_JIT;
50
51 let cache =
52 RandomXCache::new(flags, RANDOMX_SEED).expect("Failed to create RandomX cache");
53
54 let dataset =
55 RandomXDataset::new(flags, cache, 0).expect("Failed to create RandomX dataset");
56
57 let shared_dataset = SharedDataset(dataset);
58 println!("RandomX dataset created!");
59 shared_dataset
60 });
61 dataset.clone().0
62}
63
64thread_local! {
66 static THREAD_VM: RefCell<RandomXVM> = RefCell::new({
67 if IS_LIGHT_MODE.load(Ordering::SeqCst) {
68 let flags = RandomXFlag::FLAG_JIT;
69 let cache = RandomXCache::new(flags, RANDOMX_SEED).expect("Failed to create RandomX cache (light mode)");
70 RandomXVM::new(flags, Some(cache), None)
71 .expect("Failed to create RandomX VM (light mode)")
72 } else {
73 let flags = RandomXFlag::FLAG_FULL_MEM | RandomXFlag::FLAG_JIT;
74 let dataset = get_dataset();
75 RandomXVM::new(flags, None, Some(dataset.clone()))
76 .expect("Failed to create RandomX VM (full mode)")
77 }
78 });
79}
80
81pub fn randomx_hash(input: &[u8]) -> [u8; 32] {
82 THREAD_VM.with(|vm_cell| {
83 let vm = vm_cell.borrow_mut();
84 let hash_vec = vm.calculate_hash(input).expect("RandomX hashing failed");
85 hash_vec.try_into().expect("Hash must be 32 bytes")
86 })
87}
88
89#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, std::hash::Hash)]
92pub struct Hash([u8; 32]);
93
94impl Hash {
95 pub fn new(data: &[u8]) -> Self {
98 Hash(randomx_hash(data))
99 }
100
101 pub const fn new_from_buf(hash_buf: [u8; 32]) -> Self {
103 Hash(hash_buf)
104 }
105
106 pub fn compare_with_data(&self, other_data: &[u8]) -> bool {
108 let computed = randomx_hash(other_data);
109 computed == self.0
110 }
111
112 pub fn new_from_base36(s: &str) -> Option<Self> {
114 let big_int = BigUint::parse_bytes(s.as_bytes(), 36)?;
116 let mut buf = big_int.to_bytes_be();
117
118 if buf.len() > 32 {
120 return None;
121 } else if buf.len() < 32 {
122 let mut padded = vec![0u8; 32 - buf.len()];
124 padded.extend(buf);
125 buf = padded;
126 }
127
128 let buf: [u8; 32] = buf.try_into().ok()?;
130
131 Some(Hash(buf))
132 }
133
134 pub fn dump_base36(&self) -> String {
135 let big_int = BigUint::from_bytes_be(&self.0);
136 big_int.to_str_radix(36)
137 }
138
139 pub fn dump_buf(&self) -> [u8; 32] {
140 self.0
141 }
142}
143
144impl Serialize for Hash {
145 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
146 where
147 S: serde::Serializer,
148 {
149 serializer.serialize_str(&self.dump_base36())
150 }
151}
152
153impl<'de> Deserialize<'de> for Hash {
154 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155 where
156 D: serde::Deserializer<'de>,
157 {
158 let s = String::deserialize(deserializer)?;
159 Self::new_from_base36(&s).ok_or_else(|| serde::de::Error::custom("Invalid base36 hash"))
160 }
161}
162
163impl Deref for Hash {
164 type Target = [u8; 32];
165 fn deref(&self) -> &Self::Target {
166 &self.0
167 }
168}
169
170impl fmt::Debug for Hash {
171 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172 write!(f, "Hash: {}", self.dump_base36())
173 }
174}
175
176#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, Hash)]
178pub struct Signature([u8; 64]);
179
180impl Signature {
181 pub fn new_signature(private: &mut Private, data: &[u8]) -> Self {
183 let mut key = SigningKey::from_bytes(private.dump_buf());
184 let signature = key.sign(data);
185 Signature(signature.to_bytes()) }
187
188 pub fn new_from_buf(signature: &[u8; 64]) -> Self {
190 Signature(signature.clone())
191 }
192
193 pub fn validate_with_public(&self, public: &Public, data: &[u8]) -> Result<bool, Error> {
195 let key = VerifyingKey::from_bytes(public.dump_buf())?;
196 Ok(key
197 .verify_strict(data, &DalekSignature::from_bytes(&self.0))
198 .is_ok())
199 }
200
201 pub fn validate_with_private(&self, private: &Private, data: &[u8]) -> Result<bool, Error> {
203 let key = SigningKey::from_bytes(private.dump_buf());
204 Ok(key
205 .verify_strict(data, &DalekSignature::from_bytes(&self.0))
206 .is_ok())
207 }
208
209 pub fn new_from_base36(s: &str) -> Option<Self> {
211 let big_int = BigUint::parse_bytes(s.as_bytes(), 36)?;
213 let mut buf = big_int.to_bytes_be();
214
215 if buf.len() > 64 {
217 return None;
218 } else if buf.len() < 64 {
219 let mut padded = vec![0u8; 64 - buf.len()];
221 padded.extend(buf);
222 buf = padded;
223 }
224
225 let buf: [u8; 64] = buf.try_into().ok()?;
227
228 Some(Self(buf))
229 }
230
231 pub fn dump_base36(&self) -> String {
232 let big_int = BigUint::from_bytes_be(&self.0);
233 big_int.to_str_radix(36)
234 }
235
236 pub fn dump_buf(&self) -> [u8; 64] {
237 self.0
238 }
239}
240
241impl Serialize for Signature {
242 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243 where
244 S: serde::Serializer,
245 {
246 serializer.serialize_str(&self.dump_base36())
247 }
248}
249
250impl<'de> Deserialize<'de> for Signature {
251 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
252 where
253 D: serde::Deserializer<'de>,
254 {
255 let s = String::deserialize(deserializer)?;
256 Self::new_from_base36(&s)
257 .ok_or_else(|| serde::de::Error::custom("Invalid base36 signature"))
258 }
259}
260
261impl Deref for Signature {
262 type Target = [u8; 64]; fn deref(&self) -> &Self::Target {
264 &self.0
265 }
266}
267
268impl fmt::Debug for Signature {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 write!(f, "Signature: {}", self.dump_base36())
271 }
272}