diff --git a/modules/accounts_state/src/rewards.rs b/modules/accounts_state/src/rewards.rs index 6daaaa0d..484ad119 100644 --- a/modules/accounts_state/src/rewards.rs +++ b/modules/accounts_state/src/rewards.rs @@ -14,7 +14,7 @@ use std::sync::Arc; use tracing::{debug, info, warn}; /// Type of reward being given -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum RewardType { Leader, Member, @@ -34,7 +34,7 @@ pub struct RewardDetail { } /// Result of a rewards calculation -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct RewardsResult { /// Epoch these rewards were earned in (when blocks produced) pub epoch: u64, diff --git a/modules/accounts_state/src/state.rs b/modules/accounts_state/src/state.rs index db15508d..85034d35 100644 --- a/modules/accounts_state/src/state.rs +++ b/modules/accounts_state/src/state.rs @@ -1,6 +1,6 @@ //! Acropolis AccountsState: State storage use crate::monetary::calculate_monetary_change; -use crate::rewards::{calculate_rewards, RewardsResult}; +use crate::rewards::{calculate_rewards, RewardType, RewardsResult}; use crate::snapshot::Snapshot; use crate::verifier::Verifier; use acropolis_common::queries::accounts::OptimalPoolSizing; @@ -657,36 +657,52 @@ impl State { // If rewards have been calculated, save the results if let Some(task) = task.take() { - if let Ok(Ok(reward_result)) = task.await { - // Collect rewards to stake addresses reward deltas - for rewards in reward_result.rewards.values() { - reward_deltas.extend( - rewards - .iter() - .map(|reward| StakeRewardDelta { - stake_address: reward.account.clone(), - delta: reward.amount as i64, - }) - .collect::>(), - ); - } - - // Verify them - verifier.verify_rewards(reward_result.epoch, &reward_result); - + if let Ok(Ok(rewards_result)) = task.await { // Pay the rewards let mut stake_addresses = self.stake_addresses.lock().unwrap(); - for (_, rewards) in reward_result.rewards { + let mut filtered_rewards_result = rewards_result.clone(); + for (spo, rewards) in rewards_result.rewards { for reward in rewards { - stake_addresses.add_to_reward(&reward.account, reward.amount); + if stake_addresses.is_registered(&reward.account) { + stake_addresses.add_to_reward(&reward.account, reward.amount); + reward_deltas.push(StakeRewardDelta { + stake_address: reward.account.clone(), + delta: reward.amount as i64, + }); + } else { + warn!( + "Reward account {} deregistered - paying reward {} to treasury", + reward.account, reward.amount + ); + self.pots.treasury += reward.amount; + + // Remove from filtered version for comparison and result + if let Some(rewards) = filtered_rewards_result.rewards.get_mut(&spo) { + rewards.retain(|r| r.account != reward.account); + } + + if let Some((_, spor)) = filtered_rewards_result + .spo_rewards + .iter_mut() + .find(|(fspo, _)| *fspo == spo) + { + spor.total_rewards -= reward.amount; + if reward.rtype == RewardType::Leader { + spor.operator_rewards -= reward.amount; + } + } + } } } + // Verify them + verifier.verify_rewards(&filtered_rewards_result); + // save SPO rewards - spo_rewards = reward_result.spo_rewards.into_iter().collect(); + spo_rewards = filtered_rewards_result.spo_rewards.clone(); // Adjust the reserves for next time with amount actually paid - self.pots.reserves -= reward_result.total_paid; + self.pots.reserves -= rewards_result.total_paid; } }; diff --git a/modules/accounts_state/src/verifier.rs b/modules/accounts_state/src/verifier.rs index f34924af..4f4784d4 100644 --- a/modules/accounts_state/src/verifier.rs +++ b/modules/accounts_state/src/verifier.rs @@ -119,7 +119,8 @@ impl Verifier { } /// Verify rewards, logging any errors - pub fn verify_rewards(&self, epoch: u64, rewards: &RewardsResult) { + pub fn verify_rewards(&self, rewards: &RewardsResult) { + let epoch = rewards.epoch; if let Some(template) = &self.rewards_file_template { let path = template.replace("{}", &epoch.to_string());