Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track reserved account keys in bank #769

Merged
merged 1 commit into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ use {
rent::RentDue,
rent_collector::{CollectedInfo, RentCollector, RENT_EXEMPT_RENT_EPOCH},
rent_debits::RentDebits,
reserved_account_keys::ReservedAccountKeys,
reward_info::RewardInfo,
saturating_add_assign,
signature::{Keypair, Signature},
Expand Down Expand Up @@ -563,6 +564,7 @@ impl PartialEq for Bank {
transaction_log_collector_config: _,
transaction_log_collector: _,
feature_set: _,
reserved_account_keys: _,
drop_callback: _,
freeze_started: _,
vote_only_bank: _,
Expand Down Expand Up @@ -783,6 +785,9 @@ pub struct Bank {

pub feature_set: Arc<FeatureSet>,

/// Set of reserved account keys that cannot be write locked
reserved_account_keys: Arc<ReservedAccountKeys>,

/// callback function only to be called when dropping and should only be called once
pub drop_callback: RwLock<OptionalDropCallback>,

Expand Down Expand Up @@ -929,6 +934,7 @@ impl Bank {
),
transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
feature_set: Arc::<FeatureSet>::default(),
reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
drop_callback: RwLock::new(OptionalDropCallback(None)),
freeze_started: AtomicBool::default(),
vote_only_bank: false,
Expand Down Expand Up @@ -1179,6 +1185,7 @@ impl Bank {
transaction_log_collector_config,
transaction_log_collector: Arc::new(RwLock::new(TransactionLogCollector::default())),
feature_set: Arc::clone(&feature_set),
reserved_account_keys: parent.reserved_account_keys.clone(),
drop_callback: RwLock::new(OptionalDropCallback(
parent
.drop_callback
Expand Down Expand Up @@ -1639,6 +1646,7 @@ impl Bank {
),
transaction_log_collector: Arc::<RwLock<TransactionLogCollector>>::default(),
feature_set: Arc::<FeatureSet>::default(),
reserved_account_keys: Arc::<ReservedAccountKeys>::default(),
drop_callback: RwLock::new(OptionalDropCallback(None)),
freeze_started: AtomicBool::new(fields.hash != Hash::default()),
vote_only_bank: false,
Expand Down Expand Up @@ -6502,6 +6510,12 @@ impl Bank {
}
}

/// Get a set of all actively reserved account keys that are not allowed to
/// be write-locked during transaction processing.
pub fn get_reserved_account_keys(&self) -> &HashSet<Pubkey> {
&self.reserved_account_keys.active
}

// This is called from snapshot restore AND for each epoch boundary
// The entire code path herein must be idempotent
fn apply_feature_activations(
Expand Down Expand Up @@ -6532,6 +6546,13 @@ impl Bank {
}
}

// Update active set of reserved account keys which are not allowed to be write locked
self.reserved_account_keys = {
let mut reserved_keys = ReservedAccountKeys::clone(&self.reserved_account_keys);
reserved_keys.update_active_set(&self.feature_set);
Arc::new(reserved_keys)
};

if new_feature_activations.contains(&feature_set::pico_inflation::id()) {
*self.inflation.write().unwrap() = Inflation::pico();
self.fee_rate_governor.burn_percent = 50; // 50% fee burn
Expand Down
26 changes: 26 additions & 0 deletions runtime/src/bank/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7907,6 +7907,32 @@ fn test_compute_active_feature_set() {
assert!(feature_set.is_active(&test_feature));
}

#[test]
fn test_reserved_account_keys() {
let bank0 = create_simple_test_arc_bank(100_000).0;
let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
bank.feature_set = Arc::new(FeatureSet::default());

assert_eq!(
bank.get_reserved_account_keys().len(),
20,
"before activating the new feature, bank should already have active reserved keys"
);

// Activate `add_new_reserved_account_keys` feature
bank.store_account(
&feature_set::add_new_reserved_account_keys::id(),
&feature::create_account(&Feature::default(), 42),
);
bank.apply_feature_activations(ApplyFeatureActivationsCaller::NewFromParent, true);

assert_eq!(
bank.get_reserved_account_keys().len(),
29,
"after activating the new feature, bank should have new active reserved keys"
);
}

#[test]
fn test_program_replacement() {
let mut bank = create_simple_test_bank(0);
Expand Down
10 changes: 10 additions & 0 deletions sdk/src/reserved_account_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ mod zk_token_proof_program {
solana_sdk::declare_id!("ZkTokenProof1111111111111111111111111111111");
}

// ReservedAccountKeys is not serialized into or deserialized from bank
// snapshots but the bank requires this trait to be implemented anyways.
#[cfg(RUSTC_WITH_SPECIALIZATION)]
impl ::solana_frozen_abi::abi_example::AbiExample for ReservedAccountKeys {
fn example() -> Self {
// ReservedAccountKeys is not Serialize so just rely on Default.
ReservedAccountKeys::default()
}
}

/// `ReservedAccountKeys` holds the set of currently active/inactive
/// account keys that are reserved by the protocol and may not be write-locked
/// during transaction processing.
Expand Down
Loading