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