mithril_common/entities/
cardano_stake_distribution.rs1use serde::{Deserialize, Serialize};
2use sha2::{Digest, Sha256};
3
4use super::{Epoch, StakeDistribution};
5
6#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
8pub struct CardanoStakeDistribution {
9 pub hash: String,
11
12 pub epoch: Epoch,
14
15 pub stake_distribution: StakeDistribution,
17}
18
19impl CardanoStakeDistribution {
20 pub fn new(epoch: Epoch, stake_distribution: StakeDistribution) -> CardanoStakeDistribution {
22 let mut cardano_stake_distribution = CardanoStakeDistribution {
23 hash: "".to_string(),
24 epoch,
25 stake_distribution,
26 };
27 cardano_stake_distribution.hash = cardano_stake_distribution.compute_hash();
28
29 cardano_stake_distribution
30 }
31
32 fn compute_hash(&self) -> String {
34 let mut hasher = Sha256::new();
35 hasher.update(self.epoch.to_be_bytes());
36 self.stake_distribution.iter().for_each(|(k, v)| {
37 hasher.update(k.as_bytes());
38 hasher.update(v.to_be_bytes());
39 });
40
41 hex::encode(hasher.finalize())
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn test_compute_hash() {
51 assert_eq!(
52 "7144dda132aa4fe758df8da5f85a774cef602ce85c8554baeeea006866710154",
53 CardanoStakeDistribution::new(
54 Epoch(1),
55 StakeDistribution::from([("pool-1".to_string(), 100), ("pool-2".to_string(), 200)])
56 )
57 .compute_hash()
58 );
59 }
60
61 #[test]
62 fn compute_hash_returns_same_hash_with_same_cardano_stake_distribution() {
63 let epoch = Epoch(1);
64
65 assert_eq!(
66 CardanoStakeDistribution::new(
67 epoch,
68 StakeDistribution::from([("pool-1".to_string(), 100), ("pool-2".to_string(), 200)])
69 )
70 .compute_hash(),
71 CardanoStakeDistribution::new(
72 epoch,
73 StakeDistribution::from([("pool-1".to_string(), 100), ("pool-2".to_string(), 200)])
74 )
75 .compute_hash()
76 );
77 }
78
79 #[test]
80 fn compute_hash_returns_same_hash_whatever_the_stake_distribution_order() {
81 let epoch = Epoch(1);
82
83 assert_eq!(
84 CardanoStakeDistribution::new(
85 epoch,
86 StakeDistribution::from([("pool-1".to_string(), 100), ("pool-2".to_string(), 200)])
87 )
88 .compute_hash(),
89 CardanoStakeDistribution::new(
90 epoch,
91 StakeDistribution::from([("pool-2".to_string(), 200), ("pool-1".to_string(), 100)])
92 )
93 .compute_hash()
94 );
95 }
96
97 #[test]
98 fn compute_hash_returns_different_hash_with_different_epoch() {
99 assert_ne!(
100 CardanoStakeDistribution::new(
101 Epoch(1),
102 StakeDistribution::from([("pool-1".to_string(), 100)])
103 )
104 .compute_hash(),
105 CardanoStakeDistribution::new(
106 Epoch(2),
107 StakeDistribution::from([("pool-1".to_string(), 100)])
108 )
109 .compute_hash()
110 );
111 }
112
113 #[test]
114 fn compute_hash_returns_different_hash_with_different_stake_distribution_pool_id() {
115 let epoch = Epoch(1);
116
117 assert_ne!(
118 CardanoStakeDistribution::new(
119 epoch,
120 StakeDistribution::from([("pool-1".to_string(), 100)])
121 )
122 .compute_hash(),
123 CardanoStakeDistribution::new(
124 epoch,
125 StakeDistribution::from([("pool-2".to_string(), 100)])
126 )
127 .compute_hash()
128 );
129 }
130
131 #[test]
132 fn compute_hash_returns_different_hash_with_different_stake_distribution_stakes() {
133 let epoch = Epoch(1);
134
135 assert_ne!(
136 CardanoStakeDistribution::new(
137 epoch,
138 StakeDistribution::from([("pool-1".to_string(), 100)])
139 )
140 .compute_hash(),
141 CardanoStakeDistribution::new(
142 epoch,
143 StakeDistribution::from([("pool-1".to_string(), 150)])
144 )
145 .compute_hash()
146 );
147 }
148
149 #[test]
150 fn compute_hash_returns_different_hash_with_different_stake_distribution_size() {
151 let epoch = Epoch(1);
152
153 assert_ne!(
154 CardanoStakeDistribution::new(
155 epoch,
156 StakeDistribution::from([("pool-1".to_string(), 100)])
157 )
158 .compute_hash(),
159 CardanoStakeDistribution::new(
160 epoch,
161 StakeDistribution::from([("pool-1".to_string(), 100), ("pool-2".to_string(), 150)])
162 )
163 .compute_hash()
164 );
165 }
166}