1use melstructs::{CoinID, CoinValue, StakeDoc, TxHash};
2use novasmt::{dense::DenseMerkleTree, Database, InMemoryCas};
3use stdcode::StdcodeSerializeExt;
4use tmelcrypt::{Ed25519PK, Hashable};
5
6#[derive(Clone, Debug)]
8pub struct StakeSet {
9 stakes: imbl::HashMap<TxHash, StakeDoc>,
10}
11
12impl StakeSet {
13 pub fn new(stakes: impl Iterator<Item = (TxHash, StakeDoc)>) -> Self {
15 Self {
16 stakes: stakes.collect(),
17 }
18 }
19
20 pub fn iter(&self) -> impl Iterator<Item = (&TxHash, &StakeDoc)> {
22 self.stakes.iter()
23 }
24
25 pub fn add_stake(&mut self, txhash: TxHash, stake: StakeDoc) {
27 self.stakes.insert(txhash, stake);
28 }
29
30 pub fn get_stake(&self, txhash: TxHash) -> Option<StakeDoc> {
32 self.stakes.get(&txhash).cloned()
33 }
34
35 pub fn is_frozen(&self, coin: CoinID) -> bool {
37 self.stakes.contains_key(&coin.txhash) && coin.index == 0
38 }
39
40 pub fn votes(&self, epoch: u64, key: Ed25519PK) -> u128 {
42 self.stakes
43 .values()
44 .filter(|v| v.e_start <= epoch && v.e_post_end > epoch && v.pubkey == key)
45 .map(|v| v.syms_staked.0)
46 .sum()
47 }
48
49 pub fn total_votes(&self, epoch: u64) -> u128 {
51 self.stakes
52 .values()
53 .filter(|v| v.e_start <= epoch && v.e_post_end > epoch)
54 .map(|v| v.syms_staked.0)
55 .sum()
56 }
57
58 pub fn unlock_old(&mut self, epoch: u64) {
60 self.stakes.retain(|_, v| v.e_post_end >= epoch);
61 }
62
63 pub fn pre_tip911(&self) -> novasmt::Tree<InMemoryCas> {
65 let mut tree = Database::new(InMemoryCas::default())
66 .get_tree([0u8; 32])
67 .unwrap();
68 for (k, v) in self.stakes.iter() {
69 tree.insert(k.stdcode().hash().0, &v.stdcode());
70 }
71 tree
72 }
73
74 pub fn post_tip911(&self, epoch: u64) -> Tip911 {
76 let mut stakes: Vec<(TxHash, StakeDoc)> = self.stakes.clone().into_iter().collect();
77 stakes.sort_unstable_by_key(|s| s.0);
79 stakes.sort_by_key(|s| s.1.syms_staked);
81 Tip911 {
82 current_total: self.total_votes(epoch).into(),
83 next_total: self.total_votes(epoch + 1).into(),
84 stakes,
85 }
86 }
87}
88
89#[derive(Clone, Debug)]
90pub struct Tip911 {
91 pub current_total: CoinValue,
93 pub next_total: CoinValue,
95 pub stakes: Vec<(TxHash, StakeDoc)>,
97}
98
99impl Tip911 {
100 pub fn calculate_merkle(&self) -> DenseMerkleTree {
102 let upto_vec: Vec<Vec<u8>> = (0..self.stakes.len())
103 .map(|k| {
104 (
105 self.current_total,
106 self.next_total,
107 self.stakes[..=k].to_vec(),
108 )
109 .stdcode()
110 })
111 .collect();
112 DenseMerkleTree::new(&upto_vec)
113 }
114}