pchain_runtime/execution/
protocol.rs

1/*
2    Copyright © 2023, ParallelChain Lab
3    Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
4*/
5
6//! Implementation of executing [Protocol Commands](https://github.com/parallelchain-io/parallelchain-protocol/blob/master/Runtime.md#protocol-commands).
7
8use 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
29/// Execution of [pchain_types::blockchain::Command::NextEpoch]
30pub(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        // 1. Reward each Stake in VS
45        // 1.1 calculate total reward
46        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            // 1.2 Calculate total stakes of this pool
76            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            // 1.3 Distribute pool rewards to stakers
89            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                // auto stake rewards for stakers
109                if stake_owner_deposit.auto_stake_rewards() == Some(true) {
110                    auto_stakes.push((pool_operator, stake_owner, reward));
111                }
112            }
113
114            // 1.4 Reward Pool's own stakes
115            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                        // create deposit if not exist
129                        operator_deposits.set_balance(pool_operator_total_reward);
130                        operator_deposits.set_auto_stake_rewards(false);
131                    }
132                }
133
134                // auto stake rewards for operators
135                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        // Auto Stake to NVP
142        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        // 2. Replace PVS with VS
170        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        // 3. Replace VS with NVS
177        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        // 4. Bump up Current Epoch by 1.
199        NetworkAccount::new(&mut state).set_current_epoch(current_epoch + 1);
200
201        // 5. Update validator set
202        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    // There is no Gas consumption as we use NetworkAccountWorldState for accessing the world state
236    (state, new_validator_set)
237}
238
239/// NetworkAccountWorldState is specific to accessing storage of an Account Storage State.
240/// It stores account storage state and use it for subsequent Read / Writes operations.
241/// Write opertions would store to read write set.
242/// Different with [state::ExecutionState] which also implements Trait [NetworkAccountStorage],
243/// it does not charge gas for opertaions.
244pub(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}