sui_core/accumulators/
unsettled_object_withdrawals.rs1use std::{
5 collections::{BTreeMap, BTreeSet},
6 sync::Arc,
7};
8
9use parking_lot::RwLock;
10use sui_types::{accumulator_root::AccumulatorObjId, base_types::SequenceNumber};
11
12use crate::accumulators::object_funds_checker::metrics::ObjectFundsCheckerMetrics;
13
14pub struct UnsettledObjectWithdrawals {
15 inner: RwLock<Inner>,
16 metrics: Arc<ObjectFundsCheckerMetrics>,
17}
18
19#[derive(Default)]
20struct Inner {
21 unsettled_withdraws: BTreeMap<AccumulatorObjId, BTreeMap<SequenceNumber, u128>>,
27 unsettled_accounts: BTreeMap<SequenceNumber, BTreeSet<AccumulatorObjId>>,
32}
33
34impl UnsettledObjectWithdrawals {
35 pub fn new(metrics: Arc<ObjectFundsCheckerMetrics>) -> Self {
36 Self {
37 inner: RwLock::new(Inner::default()),
38 metrics,
39 }
40 }
41
42 pub(crate) fn get_unsettled_object_withdraw(
44 &self,
45 account: &AccumulatorObjId,
46 accumulator_version: SequenceNumber,
47 ) -> u128 {
48 self.inner
49 .read()
50 .unsettled_withdraws
51 .get(account)
52 .and_then(|withdraws| withdraws.get(&accumulator_version))
53 .copied()
54 .unwrap_or_default()
55 }
56
57 pub(crate) fn record_unsettled_withdraws<'a>(
61 &self,
62 withdraws: impl Iterator<Item = (&'a AccumulatorObjId, &'a u128)>,
63 accumulator_version: SequenceNumber,
64 ) {
65 let mut inner = self.inner.write();
66 for (account, amount) in withdraws {
67 let entry = inner
68 .unsettled_withdraws
69 .entry(*account)
70 .or_default()
71 .entry(accumulator_version)
72 .or_default();
73 *entry = entry.checked_add(*amount).unwrap();
74 inner
75 .unsettled_accounts
76 .entry(accumulator_version)
77 .or_default()
78 .insert(*account);
79 }
80 self.update_unsettled_metrics(&inner);
81 }
82
83 fn update_unsettled_metrics(&self, inner: &Inner) {
84 self.metrics
85 .unsettled_accounts
86 .set(inner.unsettled_withdraws.len() as i64);
87 self.metrics
88 .unsettled_versions
89 .set(inner.unsettled_accounts.len() as i64);
90 }
91
92 pub fn commit_accumulator_versions(&self, committed_accumulator_versions: Vec<SequenceNumber>) {
95 let mut inner = self.inner.write();
96 for accumulator_version in committed_accumulator_versions {
97 let accounts = inner
98 .unsettled_accounts
99 .remove(&accumulator_version)
100 .unwrap_or_default();
101 for account in accounts {
102 if let Some(withdraws) = inner.unsettled_withdraws.get_mut(&account) {
103 withdraws.remove(&accumulator_version);
104 if withdraws.is_empty() {
105 inner.unsettled_withdraws.remove(&account);
106 }
107 }
108 }
109 }
110 self.update_unsettled_metrics(&inner);
111 }
112
113 #[cfg(test)]
114 pub fn is_empty(&self) -> bool {
115 let inner = self.inner.read();
116 inner.unsettled_withdraws.is_empty() && inner.unsettled_accounts.is_empty()
117 }
118}