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 = RandomXCache::new(flags, RANDOMX_SEED).expect("Failed to create RandomX cache");
52
53 let dataset =
54 RandomXDataset::new(flags, cache, 0).expect("Failed to create RandomX dataset");
55
56 let shared_dataset = SharedDataset(dataset);
57 println!("RandomX dataset created!");
58 shared_dataset
59 });
60 dataset.clone().0
61}
62
63thread_local! {
65 static THREAD_VM: RefCell<RandomXVM> = RefCell::new({
66 if IS_LIGHT_MODE.load(Ordering::SeqCst) {
67 let flags = RandomXFlag::FLAG_JIT;
68 let cache = RandomXCache::new(flags, RANDOMX_SEED).expect("Failed to create RandomX cache (light mode)");
69 RandomXVM::new(flags, Some(cache), None)
70 .expect("Failed to create RandomX VM (light mode)")
71 } else {
72 let flags = RandomXFlag::FLAG_FULL_MEM | RandomXFlag::FLAG_JIT;
73 let dataset = get_dataset();
74 RandomXVM::new(flags, None, Some(dataset.clone()))
75 .expect("Failed to create RandomX VM (full mode)")
76 }
77 });
78}
79
80pub fn randomx_hash(input: &[u8]) -> [u8; 32] {
81 THREAD_VM.with(|vm_cell| {
82 let vm = vm_cell.borrow_mut();
83 let hash_vec = vm.calculate_hash(input).expect("RandomX hashing failed");
84 hash_vec.try_into().expect("Hash must be 32 bytes")
85 })
86}
87
88#[derive(Clone, Copy, PartialEq, Eq, Encode, Decode, std::hash::Hash)]
91pub struct Hash([u8; 32]);
92
93impl Hash {
94 pub fn new(data: &[u8]) -> Self {
97 Hash(randomx_hash(data))
98 }
99
100 pub const fn new_from_buf(hash_buf: [u8; 32]) -> Self {
102 Hash(hash_buf)
103 }
104
105 pub fn compare_with_data(&self, other_data: &[u8]) -> bool {
107 let computed = randomx_hash(other_data);
108 computed == self.0
109 }
110
111 pub fn new_from_base36(s: &str) -> Option<Self> {
113 let big_int = BigUint::parse_bytes(s.as_bytes(), 36)?;
115 let mut buf = big_int.to_bytes_be();
116
117 if buf.len() > 32 {
119 return None;
120 } else if buf.len() < 32 {
121 let mut padded = vec![0u8; 32 - buf.len()];
123 padded.extend(buf);
124 buf = padded;
125 }
126
127 let buf: [u8; 32] = buf.try_into().ok()?;
129
130 Some(Hash(buf))
131 }
132
133 pub fn dump_base36(&self) -> String {
134 let big_int = BigUint::from_bytes_be(&self.0);
135 big_int.to_str_radix(36)
136 }
137
138 pub fn dump_buf(&self) -> [u8; 32] {
139 self.0
140 }
141}
142
143impl Serialize for Hash {
144 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
145 where
146 S: serde::Serializer,
147 {
148 serializer.serialize_str(&self.dump_base36())
149 }
150}
151
152impl<'de> Deserialize<'de> for Hash {
153 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
154 where
155 D: serde::Deserializer<'de>,
156 {
157 let s = String::deserialize(deserializer)?;
158 Self::new_from_base36(&s).ok_or_else(|| serde::de::Error::custom("Invalid base36 hash"))
159 }
160}
161
162impl Deref for Hash {
163 type Target = [u8; 32];
164 fn deref(&self) -> &Self::Target {
165 &self.0
166 }
167}
168
169impl fmt::Debug for Hash {
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 write!(f, "Hash: {}", self.dump_base36())
172 }
173}
174
175#[derive(Clone, PartialEq, Eq, Encode, Decode, Copy, Hash)]
177pub struct Signature([u8; 64]);
178
179impl Signature {
180 pub fn new_signature(private: &mut Private, data: &[u8]) -> Self {
182 let mut key = SigningKey::from_bytes(private.dump_buf());
183 let signature = key.sign(data);
184 Signature(signature.to_bytes()) }
186
187 pub fn new_from_buf(signature: &[u8; 64]) -> Self {
189 Signature(signature.clone())
190 }
191
192 pub fn validate_with_public(&self, public: &Public, data: &[u8]) -> Result<bool, Error> {
194 let key = VerifyingKey::from_bytes(public.dump_buf())?;
195 Ok(key
196 .verify_strict(data, &DalekSignature::from_bytes(&self.0))
197 .is_ok())
198 }
199
200 pub fn validate_with_private(&self, private: &Private, data: &[u8]) -> Result<bool, Error> {
202 let key = SigningKey::from_bytes(private.dump_buf());
203 Ok(key
204 .verify_strict(data, &DalekSignature::from_bytes(&self.0))
205 .is_ok())
206 }
207
208 pub fn new_from_base36(s: &str) -> Option<Self> {
210 let big_int = BigUint::parse_bytes(s.as_bytes(), 36)?;
212 let mut buf = big_int.to_bytes_be();
213
214 if buf.len() > 64 {
216 return None;
217 } else if buf.len() < 64 {
218 let mut padded = vec![0u8; 64 - buf.len()];
220 padded.extend(buf);
221 buf = padded;
222 }
223
224 let buf: [u8; 64] = buf.try_into().ok()?;
226
227 Some(Self(buf))
228 }
229
230 pub fn dump_base36(&self) -> String {
231 let big_int = BigUint::from_bytes_be(&self.0);
232 big_int.to_str_radix(36)
233 }
234
235 pub fn dump_buf(&self) -> [u8; 64] {
236 self.0
237 }
238}
239
240impl Serialize for Signature {
241 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
242 where
243 S: serde::Serializer,
244 {
245 serializer.serialize_str(&self.dump_base36())
246 }
247}
248
249impl<'de> Deserialize<'de> for Signature {
250 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
251 where
252 D: serde::Deserializer<'de>,
253 {
254 let s = String::deserialize(deserializer)?;
255 Self::new_from_base36(&s)
256 .ok_or_else(|| serde::de::Error::custom("Invalid base36 signature"))
257 }
258}
259
260impl Deref for Signature {
261 type Target = [u8; 64]; fn deref(&self) -> &Self::Target {
263 &self.0
264 }
265}
266
267impl fmt::Debug for Signature {
268 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
269 write!(f, "Signature: {}", self.dump_base36())
270 }
271}