pchain_runtime/execution/
protocol.rs1use std::collections::HashMap;
9
10use pchain_types::cryptography::PublicAddress;
11use pchain_world_state::{
12 keys::AppKey,
13 network::{
14 constants::NETWORK_ADDRESS,
15 network_account::{NetworkAccount, NetworkAccountStorage},
16 pool::Pool,
17 stake::StakeValue,
18 },
19 states::AccountStorageState,
20 storage::WorldStateStorage,
21};
22
23use crate::{
24 formulas::{pool_reward, stake_reward}, read_write_set::ReadWriteSet, BlockProposalStats, ValidatorChanges,
25};
26
27use super::state::ExecutionState;
28
29pub(crate) fn next_epoch<S>(mut state: ExecutionState<S>) -> (ExecutionState<S>, ValidatorChanges)
31where
32 S: WorldStateStorage + Send + Sync + Clone,
33{
34 let block_performance = state.bd.validator_performance.clone().unwrap();
35
36 let new_validator_set = {
37 let acc_state = state.ws.account_storage_state(NETWORK_ADDRESS).unwrap();
38 let mut state = NetworkAccountWorldState::new(&mut state, acc_state);
39
40 let mut pools_in_vp = Vec::new();
41 let mut stakes_of_vp = HashMap::<PublicAddress, Vec<StakeValue>>::new();
42 let mut auto_stakes: Vec<(PublicAddress, PublicAddress, u64)> = Vec::new();
43
44 let current_epoch = NetworkAccount::new(&mut state).current_epoch();
47 let pool_length = NetworkAccount::vp(&mut state).length();
48 for i in 0..pool_length {
49 let mut vp = NetworkAccount::vp(&mut state);
50 let pool = vp.pool_at(i).unwrap();
51 pools_in_vp.push(Pool {
52 operator: pool.operator().unwrap(),
53 commission_rate: pool.commission_rate().unwrap(),
54 power: pool.power().map_or(0, |power| power),
55 operator_stake: pool.operator_stake().and_then(|opt_stake| opt_stake),
56 });
57 }
58
59 for pool in &pools_in_vp {
60 let pool_operator = pool.operator;
61 let pool_power = pool.power;
62 let pool_operator_own_stake = pool.operator_stake.map_or(0, |s| s.power);
63 let commission_rate = pool.commission_rate;
64 let stats = block_performance
65 .stats
66 .get(&pool_operator)
67 .map_or(BlockProposalStats::new(0), |stat| stat.clone());
68 let pool_reward = pool_reward(
69 current_epoch,
70 pool_power,
71 stats.num_of_proposed_blocks,
72 block_performance.blocks_per_epoch / pool_length,
73 );
74
75 let mut total_stakes = pool_operator_own_stake;
77 let mut vp_stakes = Vec::new();
78 let mut vp = NetworkAccount::vp(&mut state);
79 if let Some(mut vp_pool) = vp.pool(pool_operator) {
80 let stakes = vp_pool.delegated_stakes();
81 let stakes_length = stakes.length();
82 for j in 0..stakes_length {
83 let stake = stakes.get(j).unwrap();
84 total_stakes = total_stakes.saturating_add(stake.power);
85 vp_stakes.push(stake);
86 }
87 }
88 let mut total_commission_fee: u64 = 0;
90 let mut stakers_to_reward = Vec::new();
91 if pool_reward > 0 {
92 for stake in &vp_stakes {
93 let (stake_reward, commission_fee) =
94 stake_reward(pool_reward, commission_rate, stake.power, total_stakes);
95 stakers_to_reward.push((stake.owner, stake_reward));
96 total_commission_fee = total_commission_fee.saturating_add(commission_fee);
97 }
98 }
99 stakes_of_vp.insert(pool_operator, vp_stakes);
100
101 for (stake_owner, reward) in stakers_to_reward {
102 let mut stake_owner_deposit =
103 NetworkAccount::deposits(&mut state, pool_operator, stake_owner);
104 if let Some(balance) = stake_owner_deposit.balance() {
105 stake_owner_deposit.set_balance(balance.saturating_add(reward));
106 }
107
108 if stake_owner_deposit.auto_stake_rewards() == Some(true) {
110 auto_stakes.push((pool_operator, stake_owner, reward));
111 }
112 }
113
114 if pool_reward > 0 {
116 let (pool_operator_stake_reward, _) =
117 stake_reward(pool_reward, 0, pool_operator_own_stake, total_stakes);
118 let mut operator_deposits =
119 NetworkAccount::deposits(&mut state, pool_operator, pool_operator);
120 let pool_operator_total_reward =
121 pool_operator_stake_reward.saturating_add(total_commission_fee);
122 match operator_deposits.balance() {
123 Some(balance) => {
124 operator_deposits
125 .set_balance(balance.saturating_add(pool_operator_total_reward));
126 }
127 None => {
128 operator_deposits.set_balance(pool_operator_total_reward);
130 operator_deposits.set_auto_stake_rewards(false);
131 }
132 }
133
134 if operator_deposits.auto_stake_rewards() == Some(true) {
136 auto_stakes.push((pool_operator, pool_operator, pool_operator_total_reward));
137 }
138 }
139 }
140
141 for (operator, owner, increase_amount) in auto_stakes {
143 let mut pool = NetworkAccount::pools(&mut state, operator);
144 if !pool.exists() {
145 continue;
146 }
147 let pool_power = pool.power().unwrap_or(0);
148 let stake_power = if operator == owner {
149 match pool.operator_stake() {
150 Some(Some(stake)) => Some(stake.power),
151 _ => None,
152 }
153 } else {
154 pool.delegated_stakes()
155 .get_by(&owner)
156 .map(|stake| stake.power)
157 };
158 let _ = super::staking::increase_stake_power(
159 &mut state,
160 operator,
161 pool_power,
162 owner,
163 stake_power,
164 increase_amount,
165 false,
166 );
167 }
168
169 NetworkAccount::pvp(&mut state).clear();
171 for pool in &pools_in_vp {
172 let delegated_stakes = stakes_of_vp.remove(&pool.operator).unwrap();
173 let _ = NetworkAccount::pvp(&mut state).push(pool.clone(), delegated_stakes);
174 }
175
176 let mut next_validator_set = Vec::new();
178 NetworkAccount::vp(&mut state).clear();
179 let pool_length = NetworkAccount::nvp(&mut state).length();
180 for i in 0..pool_length {
181 let pool = NetworkAccount::nvp(&mut state).get(i).unwrap();
182 let pool_operator = pool.operator;
183 let mut pool = NetworkAccount::pools(&mut state, pool_operator);
184
185 let pool_to_vs = Pool {
186 operator: pool.operator().unwrap(),
187 commission_rate: pool.commission_rate().unwrap(),
188 power: pool.power().unwrap(),
189 operator_stake: pool.operator_stake().unwrap(),
190 };
191 next_validator_set.push((pool_to_vs.operator, pool_to_vs.power));
192
193 let delegated_stakes = pool.delegated_stakes().unordered_values();
194
195 let _ = NetworkAccount::vp(&mut state).push(pool_to_vs, delegated_stakes);
196 }
197
198 NetworkAccount::new(&mut state).set_current_epoch(current_epoch + 1);
200
201 let new_validator_set: Vec<(PublicAddress, u64)> = next_validator_set
203 .iter()
204 .filter_map(|(new_p, new_power)| {
205 if !pools_in_vp
206 .iter()
207 .any(|old_p| old_p.operator == *new_p && old_p.power == *new_power)
208 {
209 Some((*new_p, *new_power))
210 } else {
211 None
212 }
213 })
214 .collect();
215 let remove_validator_set = pools_in_vp
216 .iter()
217 .filter_map(|old_p| {
218 if !next_validator_set
219 .iter()
220 .any(|new_p| new_p.0 == old_p.operator)
221 {
222 Some(old_p.operator)
223 } else {
224 None
225 }
226 })
227 .collect();
228
229 ValidatorChanges {
230 new_validator_set,
231 remove_validator_set,
232 }
233 };
234
235 (state, new_validator_set)
237}
238
239pub(crate) struct NetworkAccountWorldState<'a, S>
245where
246 S: WorldStateStorage + Send + Sync + Clone,
247{
248 account_storage_state: AccountStorageState<S>,
249 rw_set: &'a mut ReadWriteSet<S>,
250}
251
252impl<'a, S> NetworkAccountWorldState<'a, S>
253where
254 S: WorldStateStorage + Send + Sync + Clone,
255{
256 pub(crate) fn new(
257 state: &'a mut ExecutionState<S>,
258 account_storage_state: AccountStorageState<S>,
259 ) -> Self {
260 Self {
261 account_storage_state,
262 rw_set: &mut state.ctx.rw_set,
263 }
264 }
265}
266
267impl<'a, S> NetworkAccountStorage for NetworkAccountWorldState<'a, S>
268where
269 S: WorldStateStorage + Send + Sync + Clone,
270{
271 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
272 self.rw_set.app_data_from_account_storage_state(
273 &self.account_storage_state,
274 AppKey::new(key.to_vec()),
275 )
276 }
277
278 fn contains(&self, key: &[u8]) -> bool {
279 self.rw_set.contains_app_data_from_account_storage_state(
280 &self.account_storage_state,
281 AppKey::new(key.to_vec()),
282 )
283 }
284
285 fn set(&mut self, key: &[u8], value: Vec<u8>) {
286 let address = self.account_storage_state.address();
287 self.rw_set
288 .set_app_data_uncharged(address, AppKey::new(key.to_vec()), value);
289 }
290
291 fn delete(&mut self, key: &[u8]) {
292 let address = self.account_storage_state.address();
293 self.rw_set
294 .set_app_data_uncharged(address, AppKey::new(key.to_vec()), Vec::new());
295 }
296}