node/watched_accounts/
watched_accounts_state.rs

1use std::collections::{BTreeMap, VecDeque};
2
3use mina_p2p_messages::v2::{
4    LedgerHash, MinaBaseAccountBinableArgStableV2, MinaBaseTransactionStatusStableV2,
5    MinaBaseUserCommandStableV2, NonZeroCurvePoint, StateHash, TransactionHash,
6};
7use serde::{Deserialize, Serialize};
8
9use crate::p2p::PeerId;
10
11#[derive(Serialize, Deserialize, Debug, Clone)]
12pub struct WatchedAccountBlockInfo {
13    pub level: u32,
14    pub hash: StateHash,
15    pub pred_hash: StateHash,
16    pub staged_ledger_hash: LedgerHash,
17}
18
19#[derive(Serialize, Deserialize, Debug, Clone)]
20pub struct Transaction {
21    pub hash: Option<TransactionHash>,
22    pub data: MinaBaseUserCommandStableV2,
23    pub status: MinaBaseTransactionStatusStableV2,
24}
25
26#[derive(Serialize, Deserialize, Debug, Clone)]
27pub enum WatchedAccountsLedgerInitialStateGetError {
28    PeerDisconnected,
29    // TransportError(P2pRpcOutgoingError),
30    P2pRpcError(mina_p2p_messages::core::Info),
31}
32
33#[derive(Serialize, Deserialize, Debug, Clone)]
34#[serde(tag = "state")]
35pub enum WatchedAccountLedgerInitialState {
36    Idle {
37        time: redux::Timestamp,
38    },
39    Pending {
40        time: redux::Timestamp,
41        block: WatchedAccountBlockInfo,
42        peer_id: PeerId,
43    },
44    Error {
45        time: redux::Timestamp,
46        error: WatchedAccountsLedgerInitialStateGetError,
47        peer_id: PeerId,
48    },
49    Success {
50        time: redux::Timestamp,
51        block: WatchedAccountBlockInfo,
52        data: Option<Box<MinaBaseAccountBinableArgStableV2>>,
53    },
54}
55
56impl WatchedAccountLedgerInitialState {
57    pub fn block(&self) -> Option<&WatchedAccountBlockInfo> {
58        match self {
59            Self::Pending { block, .. } => Some(block),
60            _ => None,
61        }
62    }
63
64    pub fn data(&self) -> Option<&MinaBaseAccountBinableArgStableV2> {
65        match self {
66            Self::Success { data, .. } => data.as_ref().map(AsRef::as_ref),
67            _ => None,
68        }
69    }
70
71    pub fn is_success(&self) -> bool {
72        matches!(self, Self::Success { .. })
73    }
74}
75
76#[derive(Serialize, Deserialize, Debug, Clone)]
77#[serde(tag = "state")]
78pub enum WatchedAccountBlockState {
79    /// Relevant transactions to the account has been included in the block.
80    TransactionsInBlockBody {
81        block: WatchedAccountBlockInfo,
82        /// Transactions included in the block ordered by nonce from low to high.
83        transactions: Vec<Transaction>,
84    },
85    /// Get account data from the ledger pending.
86    LedgerAccountGetPending {
87        block: WatchedAccountBlockInfo,
88        /// Transactions included in the block ordered by nonce from low to high.
89        transactions: Vec<Transaction>,
90    },
91    /// Get account data from the ledger success.
92    LedgerAccountGetSuccess {
93        block: WatchedAccountBlockInfo,
94        /// Transactions included in the block ordered by nonce from low to high.
95        transactions: Vec<Transaction>,
96        ledger_account: Box<MinaBaseAccountBinableArgStableV2>,
97    },
98}
99
100impl WatchedAccountBlockState {
101    pub fn block(&self) -> &WatchedAccountBlockInfo {
102        match self {
103            Self::TransactionsInBlockBody { block, .. } => block,
104            Self::LedgerAccountGetPending { block, .. } => block,
105            Self::LedgerAccountGetSuccess { block, .. } => block,
106        }
107    }
108
109    pub fn transactions(&self) -> &[Transaction] {
110        match self {
111            Self::TransactionsInBlockBody { transactions, .. } => transactions,
112            Self::LedgerAccountGetPending { transactions, .. } => transactions,
113            Self::LedgerAccountGetSuccess { transactions, .. } => transactions,
114        }
115    }
116
117    pub fn ledger_account(&self) -> Option<&MinaBaseAccountBinableArgStableV2> {
118        match self {
119            Self::TransactionsInBlockBody { .. } => None,
120            Self::LedgerAccountGetPending { .. } => None,
121            Self::LedgerAccountGetSuccess { ledger_account, .. } => Some(ledger_account),
122        }
123    }
124}
125
126#[derive(Serialize, Deserialize, Debug, Clone)]
127pub struct WatchedAccountState {
128    pub initial_state: WatchedAccountLedgerInitialState,
129
130    /// Blocks in which account updates has happened.
131    pub blocks: VecDeque<WatchedAccountBlockState>,
132    // /// Pending transactions which haven't been included in any blocks.
133    // pub pending_transactions: BTreeMap<txhash, tx>,
134}
135
136impl WatchedAccountState {
137    pub fn block_find_by_hash(&self, hash: &StateHash) -> Option<&WatchedAccountBlockState> {
138        self.blocks.iter().rev().find(|b| &b.block().hash == hash)
139    }
140
141    pub fn block_find_by_hash_mut(
142        &mut self,
143        hash: &StateHash,
144    ) -> Option<&mut WatchedAccountBlockState> {
145        self.blocks
146            .iter_mut()
147            .rev()
148            .find(|b| &b.block().hash == hash)
149    }
150}
151
152#[derive(Serialize, Deserialize, Debug, Clone, Default)]
153pub struct WatchedAccountsState {
154    list: BTreeMap<NonZeroCurvePoint, WatchedAccountState>,
155}
156
157impl WatchedAccountsState {
158    pub fn new() -> Self {
159        Self::default()
160    }
161
162    pub fn contains(&self, key: &NonZeroCurvePoint) -> bool {
163        self.list.contains_key(key)
164    }
165
166    pub fn get(&self, key: &NonZeroCurvePoint) -> Option<&WatchedAccountState> {
167        self.list.get(key)
168    }
169
170    pub fn get_mut(&mut self, key: &NonZeroCurvePoint) -> Option<&mut WatchedAccountState> {
171        self.list.get_mut(key)
172    }
173
174    pub fn insert(&mut self, key: NonZeroCurvePoint, value: WatchedAccountState) {
175        self.list.insert(key, value);
176    }
177
178    pub fn iter(
179        &self,
180    ) -> impl '_ + Iterator<Item = (&'_ NonZeroCurvePoint, &'_ WatchedAccountState)> {
181        self.list.iter()
182    }
183
184    pub fn accounts(&self) -> Vec<NonZeroCurvePoint> {
185        self.iter().map(|v| v.0.clone()).collect()
186    }
187}