1use std::cell::RefCell;
2use std::collections::VecDeque;
3use std::time::Duration;
4
5use ahash::AHashMap;
6use tokio::sync::mpsc::Sender;
7
8pub type Currency = u64;
9
10pub type Timestamp = u64;
12pub type SaitoSignature = [u8; 64];
13pub type SaitoPublicKey = [u8; 33];
14pub type SaitoPrivateKey = [u8; 32];
15pub type SaitoHash = [u8; 32];
16pub type BlockHash = SaitoHash;
17
18pub type ForkId = SaitoHash;
19pub const UTXO_KEY_LENGTH: usize = 59;
21pub type SaitoUTXOSetKey = [u8; UTXO_KEY_LENGTH];
22pub type UtxoSet = AHashMap<SaitoUTXOSetKey, bool>;
23pub type PeerIndex = u64;
24pub type BlockId = u64;
25
26pub const CHANNEL_SAFE_BUFFER: usize = 16;
27
28pub const NOLAN_PER_SAITO: Currency = 100_000_000;
29
30pub const PROJECT_PUBLIC_KEY: &str = "q6TTBeSStCLXEPoS5TUVAxNiGGnRDZQenpvAXXAfTmtA";
31
32pub const MAX_TOKEN_SUPPLY: Currency = 7_000_000_000 * NOLAN_PER_SAITO;
44pub const MIN_GOLDEN_TICKETS_NUMERATOR: u64 = 2;
46pub const MIN_GOLDEN_TICKETS_DENOMINATOR: u64 = 6;
48
49pub const BLOCK_FILE_EXTENSION: &str = ".sai";
50pub const STAT_BIN_COUNT: usize = 3;
51
52pub const PEER_RECONNECT_WAIT_PERIOD: Timestamp = Duration::from_secs(10).as_millis() as Timestamp;
53pub const WS_KEEP_ALIVE_PERIOD: Timestamp = Duration::from_secs(10).as_millis() as Timestamp;
54
55pub const LOCK_ORDER_NETWORK_CONTROLLER: u8 = 1;
66pub const LOCK_ORDER_SOCKETS: u8 = 2;
67pub const LOCK_ORDER_CONFIGS: u8 = 3;
68pub const LOCK_ORDER_BLOCKCHAIN: u8 = 4;
69pub const LOCK_ORDER_MEMPOOL: u8 = 5;
70pub const LOCK_ORDER_PEERS: u8 = 6;
71pub const LOCK_ORDER_WALLET: u8 = 7;
72
73thread_local! {
74 pub static LOCK_ORDER: RefCell<VecDeque<u8>> = RefCell::new(VecDeque::default());
75}
76
77#[macro_export]
78macro_rules! iterate {
79 ($collection:expr, $min:expr) => {{
80 #[cfg(feature = "with-rayon")]
81 {
82 $collection.par_iter().with_min_len($min)
83 }
84
85 #[cfg(not(feature = "with-rayon"))]
86 {
87 $collection.iter()
88 }
89 }};
90}
91
92#[macro_export]
93macro_rules! iterate_mut {
94 ($collection:expr) => {{
95 #[cfg(feature = "with-rayon")]
96 {
97 $collection.par_iter_mut()
98 }
99
100 #[cfg(not(feature = "with-rayon"))]
101 {
102 $collection.iter_mut()
103 }
104 }};
105}
106
107#[macro_export]
108macro_rules! drain {
109 ($collection:expr, $min:expr) => {{
110 #[cfg(feature = "with-rayon")]
111 {
112 $collection.par_drain(..).with_min_len($min)
113 }
114
115 #[cfg(not(feature = "with-rayon"))]
116 {
117 $collection.drain(..)
118 }
119 }};
120}
121
122#[derive(Clone, Debug)]
123pub struct StatVariable {
124 pub total: u64,
125 pub count_since_last_stat: u64,
126 pub last_stat_at: Timestamp,
127 pub bins: VecDeque<(u64, Timestamp)>,
128 pub avg: f64,
129 pub max_avg: f64,
130 pub min_avg: f64,
131 pub name: String,
132 pub sender: Sender<String>,
133}
134
135impl StatVariable {
136 pub fn new(name: String, bin_count: usize, sender: Sender<String>) -> StatVariable {
137 StatVariable {
138 total: 0,
139 count_since_last_stat: 0,
140 last_stat_at: 0,
141 bins: VecDeque::with_capacity(bin_count),
142 avg: 0.0,
143 max_avg: 0.0,
144 min_avg: f64::MAX,
145 name,
146 sender,
147 }
148 }
149 pub fn increment(&mut self) {
150 {
151 self.total += 1;
152 self.count_since_last_stat += 1;
153 }
154 }
155 pub fn increment_by(&mut self, amount: u64) {
156 {
157 self.total += amount;
158 self.count_since_last_stat += amount;
159 }
160 }
161 pub async fn calculate_stats(&mut self, current_time_in_ms: Timestamp) {
162 let time_elapsed_in_ms = current_time_in_ms - self.last_stat_at;
163 self.last_stat_at = current_time_in_ms;
164 if self.bins.len() == self.bins.capacity() - 1 {
165 self.bins.pop_front();
166 }
167 self.bins
168 .push_back((self.count_since_last_stat, time_elapsed_in_ms));
169 self.count_since_last_stat = 0;
170
171 let mut total = 0;
172 let mut total_time_in_ms = 0;
173 for (count, time) in self.bins.iter() {
174 total += *count;
175 total_time_in_ms += *time;
176 }
177
178 self.avg = (1_000.0 * total as f64) / total_time_in_ms as f64;
179 if self.avg > self.max_avg {
180 self.max_avg = self.avg;
181 }
182 if self.avg < self.min_avg {
183 self.min_avg = self.avg;
184 }
185 self.sender
186 .send(self.print(current_time_in_ms))
187 .await
188 .expect("failed sending stat update");
189 }
190 pub fn format_timestamp(timestamp: Timestamp) -> String {
191 chrono::DateTime::from_timestamp_millis(timestamp as i64)
192 .unwrap()
193 .to_string()
194 }
195 fn print(&self, current_time_in_ms: Timestamp) -> String {
196 format!(
197 "{} - {} - total : {:?}, current_rate : {:.2}, max_rate : {:.2}, min_rate : {:.2}",
199 Self::format_timestamp(current_time_in_ms),
200 format!("{:width$}", self.name, width = 40),
201 self.total,
202 self.avg,
203 self.max_avg,
204 self.min_avg
205 )
206 }
207}
208
209pub trait PrintForLog<T: TryFrom<Vec<u8>>> {
210 fn to_base58(&self) -> String;
211 fn to_hex(&self) -> String;
212 fn from_hex(str: &str) -> Result<T, String>;
213
214 fn from_base58(str: &str) -> Result<T, String>;
215}
216
217#[macro_export]
218macro_rules! impl_print {
219 ($st:ident) => {
220 impl PrintForLog<$st> for $st {
221 fn to_base58(&self) -> String {
222 bs58::encode(self).into_string()
223 }
224
225 fn to_hex(&self) -> String {
226 hex::encode(self)
227 }
228
229 fn from_hex(str: &str) -> Result<$st, String> {
230 let result = hex::decode(str);
231 if result.is_err() {
232 return Err(format!(
233 "couldn't convert string : {:?} to hex type. {:?}",
234 str,
235 result.err().unwrap()
236 ));
237 }
238 let result = result.unwrap();
239 let result = result.try_into();
240 if result.is_err() {
241 return Err(format!(
242 "couldn't convert : {:?} with length : {:?} to hex type. {:?}",
243 str,
244 str.len(),
245 result.err().unwrap()
246 ));
247 }
248 Ok(result.unwrap())
249 }
250 fn from_base58(str: &str) -> Result<$st, String> {
251 let result = bs58::decode(str).into_vec();
252 if result.is_err() {
253 return Err(format!(
254 "couldn't convert string : {:?} to base58. {:?}",
255 str,
256 result.err().unwrap()
257 ));
258 }
259 let result = result.unwrap();
260 let result = result.try_into();
261 if result.is_err() {
262 return Err(format!(
263 "couldn't convert : {:?} with length : {:?} to base58. {:?}",
264 str,
265 str.len(),
266 result.err().unwrap()
267 ));
268 }
269 Ok(result.unwrap())
270 }
271 }
272 };
273}
274impl_print!(SaitoHash);
275impl_print!(SaitoPublicKey);
276impl_print!(SaitoSignature);
277impl_print!(SaitoUTXOSetKey);