Skip to main content

snap_coin/full_node/
node_state.rs

1use serde::{Deserialize, Serialize};
2use std::{
3    collections::{HashMap, VecDeque},
4    net::SocketAddr,
5    sync::Arc,
6};
7use tokio::sync::{
8    Mutex, RwLock, broadcast,
9    watch::{self, Ref},
10};
11
12use crate::{
13    core::{
14        block::Block,
15        difficulty::calculate_live_transaction_difficulty,
16        transaction::{Transaction, TransactionId},
17    },
18    crypto::Hash,
19    full_node::mempool::MemPool,
20    node::peer::PeerHandle,
21};
22
23pub type SharedNodeState = Arc<NodeState>;
24
25pub struct NodeState {
26    pub connected_peers: RwLock<HashMap<SocketAddr, PeerHandle>>,
27    pub mempool: MemPool,
28    pub is_syncing: RwLock<bool>,
29    pub chain_events: broadcast::Sender<ChainEvent>,
30    pub adding_block: Mutex<()>,
31    last_seen_block_reader: watch::Receiver<Hash>,
32    last_seen_block_writer: watch::Sender<Hash>,
33    last_seen_transactions_reader: watch::Receiver<VecDeque<TransactionId>>,
34    last_seen_transactions_writer: watch::Sender<VecDeque<TransactionId>>,
35}
36
37impl NodeState {
38    pub fn new_empty() -> SharedNodeState {
39        let (last_seen_block_writer, last_seen_block_reader) =
40            watch::channel(Hash::new_from_buf([0u8; 32]));
41        let (last_seen_transactions_writer, last_seen_transactions_reader) =
42            watch::channel(VecDeque::new());
43
44        Arc::new(NodeState {
45            connected_peers: RwLock::new(HashMap::new()),
46            mempool: MemPool::new(),
47            is_syncing: RwLock::new(false),
48            chain_events: broadcast::channel(64).0,
49            adding_block: Mutex::new(()),
50            last_seen_block_reader,
51            last_seen_block_writer,
52            last_seen_transactions_reader,
53            last_seen_transactions_writer,
54        })
55    }
56
57    /// Get the latest seen block
58    pub fn last_seen_block(&self) -> Hash {
59        self.last_seen_block_reader.borrow().clone()
60    }
61
62    /// Set a new last seen block
63    pub fn set_last_seen_block(&self, hash: Hash) {
64        let _ = self.last_seen_block_writer.send(hash);
65    }
66
67    /// Get the latest seen transactions
68    pub fn last_seen_transactions(&self) -> Ref<'_, VecDeque<TransactionId>> {
69        self.last_seen_transactions_reader.borrow()
70    }
71
72    /// Add a new last seen transaction, removing the oldest if >500
73    pub fn add_last_seen_transaction(&self, tx_id: TransactionId) {
74        let mut transactions: VecDeque<TransactionId> =
75            self.last_seen_transactions_reader.borrow().clone();
76
77        // Avoid duplicates
78        if !transactions.contains(&tx_id) {
79            transactions.push_back(tx_id);
80
81            // Keep only the latest 500 transactions
82            if transactions.len() > 500 {
83                transactions.pop_front(); // remove oldest
84            }
85
86            let _ = self.last_seen_transactions_writer.send(transactions);
87        }
88    }
89
90    pub async fn get_live_transaction_difficulty(
91        &self,
92        transaction_difficulty: [u8; 32],
93    ) -> [u8; 32] {
94        calculate_live_transaction_difficulty(
95            &transaction_difficulty,
96            self.mempool.mempool_size().await,
97        )
98    }
99}
100
101#[derive(Serialize, Deserialize, Clone)]
102pub enum ChainEvent {
103    Block { block: Block },
104    Transaction { transaction: Transaction },
105    TransactionExpiration { transaction: TransactionId },
106}