Skip to content

Commit

Permalink
Track reserved account keys in bank (#769)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstarry authored Apr 13, 2024
1 parent 45e0939 commit cb13b39
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
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 @@ -7952,6 +7952,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

0 comments on commit cb13b39

Please sign in to comment.