Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Populate partitioned-rewards PDA during calculation #34624

Merged

Conversation

CriesofCarrots
Copy link
Contributor

@CriesofCarrots CriesofCarrots commented Jan 2, 2024

Problem

When the partitioned rewards feature is activated, the only way to find the rewards for a specific address will be to iterate through blocks at the beginning of each epoch. This is because we do not persist information about how the rewards were partitioned; in fact, we don't even persist how many blocks the rewards distribution spans, so there is no way to predict how long it will take to find an address. This is not reasonable for stake-account users.

Summary of Changes

When partitioned rewards are calculated, populate a PDA (address seeded by the epoch number) that stores the partition data needed to create an EpochRewardsHasher to performantly identify which partition a particular stake address' distribution is in: number of partitions, parent bank's hash, and the hasher kind.

@CriesofCarrots CriesofCarrots force-pushed the partitioned-rewards-pda branch from ce4421f to 2c9db16 Compare January 2, 2024 19:53
@jstarry jstarry self-requested a review January 10, 2024 00:54
@CriesofCarrots CriesofCarrots force-pushed the partitioned-rewards-pda branch 2 times, most recently from fcfd1de to ae79075 Compare January 11, 2024 07:11
Copy link

codecov bot commented Jan 11, 2024

Codecov Report

Attention: 18 lines in your changes are missing coverage. Please review.

Comparison is base (e31a45a) 81.7% compared to head (58df173) 81.8%.
Report is 4 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff            @@
##           master   #34624    +/-   ##
========================================
  Coverage    81.7%    81.8%            
========================================
  Files         823      824     +1     
  Lines      222865   223077   +212     
========================================
+ Hits       182279   182506   +227     
+ Misses      40586    40571    -15     

@CriesofCarrots CriesofCarrots force-pushed the partitioned-rewards-pda branch from ae79075 to 5881f7b Compare January 11, 2024 18:21
@CriesofCarrots CriesofCarrots marked this pull request as ready for review January 11, 2024 18:22
HaoranYi
HaoranYi previously approved these changes Jan 11, 2024
Copy link
Contributor

@HaoranYi HaoranYi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

Copy link
Contributor

@t-nelson t-nelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly lgtm. one nit, one q

@@ -3579,6 +3594,30 @@ impl Bank {
self.log_epoch_rewards_sysvar("update");
}

/// Create the persistent PDA containing the epoch-rewards data
fn create_epoch_rewards_partition_list_account(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn create_epoch_rewards_partition_list_account(
fn create_epoch_rewards_partition_metadata_account(

or

Suggested change
fn create_epoch_rewards_partition_list_account(
fn create_epoch_rewards_partition_receipt_account(

we kinda rugged the name dropping the commitment list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, sorry! I thought I fixed all of these. Maybe I rebased badly the last time. Fix pushed.

&solana_sdk::stake::program::id(),
)
.unwrap();
self.store_account_and_update_capitalization(&address, &new_account);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does this work if an account already exists at the given address? like some smart ass sends it some sol in advance

Copy link
Contributor Author

@CriesofCarrots CriesofCarrots Jan 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the method:

solana/runtime/src/bank.rs

Lines 6497 to 6581 in 22fcffe

fn store_account_and_update_capitalization(
&self,
pubkey: &Pubkey,
new_account: &AccountSharedData,
) {
let old_account_data_size =
if let Some(old_account) = self.get_account_with_fixed_root(pubkey) {
match new_account.lamports().cmp(&old_account.lamports()) {
std::cmp::Ordering::Greater => {
let increased = new_account.lamports() - old_account.lamports();
trace!(
"store_account_and_update_capitalization: increased: {} {}",
pubkey,
increased
);
self.capitalization.fetch_add(increased, Relaxed);
}
std::cmp::Ordering::Less => {
let decreased = old_account.lamports() - new_account.lamports();
trace!(
"store_account_and_update_capitalization: decreased: {} {}",
pubkey,
decreased
);
self.capitalization.fetch_sub(decreased, Relaxed);
}
std::cmp::Ordering::Equal => {}
}
old_account.data().len()
} else {
trace!(
"store_account_and_update_capitalization: created: {} {}",
pubkey,
new_account.lamports()
);
self.capitalization
.fetch_add(new_account.lamports(), Relaxed);
0
};
self.store_account(pubkey, new_account);
self.calculate_and_update_accounts_data_size_delta_off_chain(
old_account_data_size,
new_account.data().len(),
);
}
fn withdraw(&self, pubkey: &Pubkey, lamports: u64) -> Result<()> {
match self.get_account_with_fixed_root(pubkey) {
Some(mut account) => {
let min_balance = match get_system_account_kind(&account) {
Some(SystemAccountKind::Nonce) => self
.rent_collector
.rent
.minimum_balance(nonce::State::size()),
_ => 0,
};
lamports
.checked_add(min_balance)
.filter(|required_balance| *required_balance <= account.lamports())
.ok_or(TransactionError::InsufficientFundsForFee)?;
account
.checked_sub_lamports(lamports)
.map_err(|_| TransactionError::InsufficientFundsForFee)?;
self.store_account(pubkey, &account);
Ok(())
}
None => Err(TransactionError::AccountNotFound),
}
}
pub fn accounts(&self) -> Arc<Accounts> {
self.rc.accounts.clone()
}
fn finish_init(
&mut self,
genesis_config: &GenesisConfig,
additional_builtins: Option<&[BuiltinPrototype]>,
debug_do_not_add_builtins: bool,
) {
self.rewards_pool_pubkeys =
Arc::new(genesis_config.rewards_pools.keys().cloned().collect());

If there are more lamports than needed in the existing account, the excess are burned. If less, they are created/supplemented to the new account balance.
It's the same thing other sysvars use.

Copy link
Contributor

@t-nelson t-nelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@CriesofCarrots CriesofCarrots merged commit 4385ed1 into solana-labs:master Jan 12, 2024
29 checks passed
@jstarry
Copy link
Contributor

jstarry commented Jan 17, 2024

@CriesofCarrots can you write up a SIMD so that the firedancer team is aware of this runtime change?

@CriesofCarrots
Copy link
Contributor Author

@CriesofCarrots can you write up a SIMD so that the firedancer team is aware of this runtime change?

Thank you for the nudge! Yes, I will.

CriesofCarrots pushed a commit to CriesofCarrots/solana that referenced this pull request Feb 5, 2024
CriesofCarrots pushed a commit that referenced this pull request Feb 6, 2024
mergify bot pushed a commit that referenced this pull request Feb 6, 2024
This reverts commit 4385ed1.

(cherry picked from commit 57bbd33)

# Conflicts:
#	runtime/src/bank.rs
CriesofCarrots pushed a commit that referenced this pull request Feb 7, 2024
This reverts commit 4385ed1.

(cherry picked from commit 57bbd33)

# Conflicts:
#	runtime/src/bank.rs
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants