gringron_servers/common/
stats.rs

1// Copyright 2021 The GrinGron Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Server stat collection types, to be used by tests, logging or GUI/TUI
16//! to collect information about server status
17
18use crate::util::RwLock;
19use std::sync::Arc;
20use std::time::SystemTime;
21
22use crate::core::core::hash::Hash;
23use crate::core::ser::ProtocolVersion;
24
25use chrono::prelude::*;
26
27use crate::chain::SyncStatus;
28use crate::p2p;
29use crate::p2p::Capabilities;
30use gringron_core::pow::Difficulty;
31
32/// Server state info collection struct, to be passed around into internals
33/// and populated when required
34#[derive(Clone)]
35pub struct ServerStateInfo {
36	/// Stratum stats
37	pub stratum_stats: Arc<RwLock<StratumStats>>,
38}
39
40impl Default for ServerStateInfo {
41	fn default() -> ServerStateInfo {
42		ServerStateInfo {
43			stratum_stats: Arc::new(RwLock::new(StratumStats::default())),
44		}
45	}
46}
47/// Simpler thread-unaware version of above to be populated and returned to
48/// consumers might be interested in, such as test results or UI
49#[derive(Debug, Clone)]
50pub struct ServerStats {
51	/// Number of peers
52	pub peer_count: u32,
53	/// Chain head
54	pub chain_stats: ChainStats,
55	/// Header head (may differ from chain head)
56	pub header_stats: ChainStats,
57	/// Whether we're currently syncing
58	pub sync_status: SyncStatus,
59	/// Handle to current stratum server stats
60	pub stratum_stats: StratumStats,
61	/// Peer stats
62	pub peer_stats: Vec<PeerStats>,
63	/// Difficulty calculation statistics
64	pub diff_stats: DiffStats,
65	/// Transaction pool statistics
66	pub tx_stats: Option<TxStats>,
67	/// Disk usage in GB
68	pub disk_usage_gb: String,
69}
70
71/// Chain Statistics
72#[derive(Clone, Serialize, Debug)]
73pub struct ChainStats {
74	/// Height of the tip (max height of the fork)
75	pub height: u64,
76	/// Last block pushed to the fork
77	pub last_block_h: Hash,
78	/// Total difficulty accumulated on that fork
79	pub total_difficulty: Difficulty,
80	/// Timestamp of highest block or header
81	pub latest_timestamp: DateTime<Utc>,
82}
83/// Transaction Statistics
84#[derive(Clone, Serialize, Debug)]
85pub struct TxStats {
86	/// Number of transactions in the transaction pool
87	pub tx_pool_size: usize,
88	/// Number of transaction kernels in the transaction pool
89	pub tx_pool_kernels: usize,
90	/// Number of transactions in the stem pool
91	pub stem_pool_size: usize,
92	/// Number of transaction kernels in the stem pool
93	pub stem_pool_kernels: usize,
94}
95/// Struct to return relevant information about stratum workers
96#[derive(Clone, Serialize, Debug)]
97pub struct WorkerStats {
98	/// Unique ID for this worker
99	pub id: String,
100	/// whether stratum worker is currently connected
101	pub is_connected: bool,
102	/// Timestamp of most recent communication with this worker
103	pub last_seen: SystemTime,
104	/// which block height it starts mining
105	pub initial_block_height: u64,
106	/// pow difficulty this worker is using
107	pub pow_difficulty: u64,
108	/// number of valid shares submitted
109	pub num_accepted: u64,
110	/// number of invalid shares submitted
111	pub num_rejected: u64,
112	/// number of shares submitted too late
113	pub num_stale: u64,
114	/// number of valid blocks found
115	pub num_blocks_found: u64,
116}
117
118/// Struct to return relevant information about the stratum server
119#[derive(Clone, Serialize, Debug)]
120pub struct StratumStats {
121	/// whether stratum server is enabled
122	pub is_enabled: bool,
123	/// whether stratum server is running
124	pub is_running: bool,
125	/// Number of connected workers
126	pub num_workers: usize,
127	/// what block height we're mining at
128	pub block_height: u64,
129	/// current network difficulty we're working on
130	pub network_difficulty: u64,
131	/// cuckoo size of last share submitted
132	pub edge_bits: u16,
133	/// Number of blocks found by all workers
134	pub blocks_found: u16,
135	/// current network Hashrate (for edge_bits)
136	pub network_hashrate: f64,
137	/// The minimum acceptable share difficulty to request from miners
138	pub minimum_share_difficulty: u64,
139	/// Individual worker status
140	pub worker_stats: Vec<WorkerStats>,
141}
142
143/// Stats on the last WINDOW blocks and the difficulty calculation
144#[derive(Debug, Clone)]
145pub struct DiffStats {
146	/// latest height
147	pub height: u64,
148	/// Last WINDOW block data
149	pub last_blocks: Vec<DiffBlock>,
150	/// Average block time for last WINDOW blocks
151	pub average_block_time: u64,
152	/// Average WINDOW difficulty
153	pub average_difficulty: u64,
154	/// WINDOW size
155	pub window_size: u64,
156}
157
158/// Last n blocks for difficulty calculation purposes
159#[derive(Clone, Debug)]
160pub struct DiffBlock {
161	/// Block height (can be negative for a new chain)
162	pub block_height: i64,
163	/// Block hash (may be synthetic for a new chain)
164	pub block_hash: Hash,
165	/// Block network difficulty
166	pub difficulty: u64,
167	/// Time block was found (epoch seconds)
168	pub time: u64,
169	/// Duration since previous block (epoch seconds)
170	pub duration: u64,
171	/// secondary scaling
172	pub secondary_scaling: u32,
173	/// is secondary
174	pub is_secondary: bool,
175}
176
177/// Struct to return relevant information about peers
178#[derive(Clone, Debug)]
179pub struct PeerStats {
180	/// Current state of peer
181	pub state: String,
182	/// Address
183	pub addr: String,
184	/// version running
185	pub version: ProtocolVersion,
186	/// Peer user agent string.
187	pub user_agent: String,
188	/// difficulty reported by peer
189	pub total_difficulty: u64,
190	/// height reported by peer on ping
191	pub height: u64,
192	/// direction
193	pub direction: String,
194	/// Last time we saw a ping/pong from this peer.
195	pub last_seen: DateTime<Utc>,
196	/// Number of bytes we've sent to the peer.
197	pub sent_bytes_per_sec: u64,
198	/// Number of bytes we've received from the peer.
199	pub received_bytes_per_sec: u64,
200	/// Peer advertised capability flags.
201	pub capabilities: Capabilities,
202}
203
204impl PartialEq for PeerStats {
205	fn eq(&self, other: &PeerStats) -> bool {
206		*self.addr == other.addr
207	}
208}
209
210impl PartialEq for WorkerStats {
211	fn eq(&self, other: &WorkerStats) -> bool {
212		*self.id == other.id
213	}
214}
215
216impl PartialEq for DiffBlock {
217	fn eq(&self, other: &DiffBlock) -> bool {
218		self.block_height == other.block_height
219	}
220}
221
222impl PeerStats {
223	/// Convert from a peer directly
224	pub fn from_peer(peer: &p2p::Peer) -> PeerStats {
225		// State
226		let state = if peer.is_banned() {
227			"Banned"
228		} else if peer.is_connected() {
229			"Connected"
230		} else {
231			"Disconnected"
232		};
233		let addr = peer.info.addr.to_string();
234		let direction = match peer.info.direction {
235			p2p::types::Direction::Inbound => "Inbound",
236			p2p::types::Direction::Outbound => "Outbound",
237		};
238		PeerStats {
239			state: state.to_string(),
240			addr: addr,
241			version: peer.info.version,
242			user_agent: peer.info.user_agent.clone(),
243			total_difficulty: peer.info.total_difficulty().to_num(),
244			height: peer.info.height(),
245			direction: direction.to_string(),
246			last_seen: peer.info.last_seen(),
247			sent_bytes_per_sec: peer.tracker().sent_bytes.read().bytes_per_min() / 60,
248			received_bytes_per_sec: peer.tracker().received_bytes.read().bytes_per_min() / 60,
249			capabilities: peer.info.capabilities,
250		}
251	}
252}
253
254impl Default for WorkerStats {
255	fn default() -> WorkerStats {
256		WorkerStats {
257			id: String::from("unknown"),
258			is_connected: false,
259			last_seen: SystemTime::now(),
260			initial_block_height: 0,
261			pow_difficulty: 0,
262			num_accepted: 0,
263			num_rejected: 0,
264			num_stale: 0,
265			num_blocks_found: 0,
266		}
267	}
268}
269
270impl Default for StratumStats {
271	fn default() -> StratumStats {
272		StratumStats {
273			is_enabled: false,
274			is_running: false,
275			num_workers: 0,
276			block_height: 0,
277			network_difficulty: 0,
278			edge_bits: 32,
279			blocks_found: 0,
280			network_hashrate: 0.0,
281			minimum_share_difficulty: 1,
282			worker_stats: Vec::new(),
283		}
284	}
285}