Simple cap by including sysvars and native programs (#13884)
* Simpler cap by including sysvars and native programs * Fix tests * Add comment * revert some unrelated code * Update test_bank_update_sysvar_account for cap. * Test cap. for add_native_program using new helper * Improve the cap adjustment with new tests * Fix typo... * Adjust test for improved code coverage * Rename simpler_capitalization => simple_capitalization * More rename and bonus commenting
This commit is contained in:
@ -98,7 +98,10 @@ fn main() {
|
|||||||
} else {
|
} else {
|
||||||
let mut pubkeys: Vec<Pubkey> = vec![];
|
let mut pubkeys: Vec<Pubkey> = vec![];
|
||||||
let mut time = Measure::start("hash");
|
let mut time = Measure::start("hash");
|
||||||
let hash = accounts.accounts_db.update_accounts_hash(0, &ancestors).0;
|
let hash = accounts
|
||||||
|
.accounts_db
|
||||||
|
.update_accounts_hash(0, &ancestors, true)
|
||||||
|
.0;
|
||||||
time.stop();
|
time.stop();
|
||||||
println!("hash: {} {}", hash, time);
|
println!("hash: {} {}", hash, time);
|
||||||
create_test_accounts(&accounts, &mut pubkeys, 1, 0);
|
create_test_accounts(&accounts, &mut pubkeys, 1, 0);
|
||||||
|
@ -1217,6 +1217,13 @@ fn main() {
|
|||||||
.help("Enable stake program v2 (several inflation-related staking \
|
.help("Enable stake program v2 (several inflation-related staking \
|
||||||
bugs are feature-gated behind this)"),
|
bugs are feature-gated behind this)"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("enable_simple_capitalization")
|
||||||
|
.required(false)
|
||||||
|
.long("enable-simple-capitalization")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Enable simple capitalization to test hardcoded cap adjustments"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("recalculate_capitalization")
|
Arg::with_name("recalculate_capitalization")
|
||||||
.required(false)
|
.required(false)
|
||||||
@ -2115,11 +2122,47 @@ fn main() {
|
|||||||
.lazy_rent_collection
|
.lazy_rent_collection
|
||||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
|
||||||
if arg_matches.is_present("enable_stake_program_v2") {
|
|
||||||
let feature_account_balance = std::cmp::max(
|
let feature_account_balance = std::cmp::max(
|
||||||
genesis_config.rent.minimum_balance(Feature::size_of()),
|
genesis_config.rent.minimum_balance(Feature::size_of()),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
if arg_matches.is_present("enable_simple_capitalization") {
|
||||||
|
if base_bank
|
||||||
|
.get_account(&feature_set::simple_capitalization::id())
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
base_bank.store_account(
|
||||||
|
&feature_set::simple_capitalization::id(),
|
||||||
|
&feature::create_account(
|
||||||
|
&Feature { activated_at: None },
|
||||||
|
feature_account_balance,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if base_bank
|
||||||
|
.get_account(&feature_set::cumulative_rent_related_fixes::id())
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
// steal some lamports from the pretty old feature not to affect
|
||||||
|
// capitalizaion, which doesn't affect inflation behavior!
|
||||||
|
base_bank.store_account(
|
||||||
|
&feature_set::cumulative_rent_related_fixes::id(),
|
||||||
|
&Account::default(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let old_cap = base_bank.set_capitalization();
|
||||||
|
let new_cap = base_bank.capitalization();
|
||||||
|
warn!(
|
||||||
|
"Skewing capitalization a bit to enable simple capitalization as \
|
||||||
|
requested: increasing {} from {} to {}",
|
||||||
|
feature_account_balance, old_cap, new_cap,
|
||||||
|
);
|
||||||
|
assert_eq!(old_cap + feature_account_balance, new_cap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Already simple_capitalization is activated (or scheduled)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if arg_matches.is_present("enable_stake_program_v2") {
|
||||||
let mut force_enabled_count = 0;
|
let mut force_enabled_count = 0;
|
||||||
if base_bank
|
if base_bank
|
||||||
.get_account(&feature_set::stake_program_v2::id())
|
.get_account(&feature_set::stake_program_v2::id())
|
||||||
|
@ -94,8 +94,12 @@ fn test_accounts_hash_bank_hash(bencher: &mut Bencher) {
|
|||||||
let slot = 0;
|
let slot = 0;
|
||||||
create_test_accounts(&accounts, &mut pubkeys, num_accounts, slot);
|
create_test_accounts(&accounts, &mut pubkeys, num_accounts, slot);
|
||||||
let ancestors = vec![(0, 0)].into_iter().collect();
|
let ancestors = vec![(0, 0)].into_iter().collect();
|
||||||
let (_, total_lamports) = accounts.accounts_db.update_accounts_hash(0, &ancestors);
|
let (_, total_lamports) = accounts
|
||||||
bencher.iter(|| assert!(accounts.verify_bank_hash_and_lamports(0, &ancestors, total_lamports)));
|
.accounts_db
|
||||||
|
.update_accounts_hash(0, &ancestors, true);
|
||||||
|
bencher.iter(|| {
|
||||||
|
assert!(accounts.verify_bank_hash_and_lamports(0, &ancestors, total_lamports, true))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
@ -109,7 +113,9 @@ fn test_update_accounts_hash(bencher: &mut Bencher) {
|
|||||||
create_test_accounts(&accounts, &mut pubkeys, 50_000, 0);
|
create_test_accounts(&accounts, &mut pubkeys, 50_000, 0);
|
||||||
let ancestors = vec![(0, 0)].into_iter().collect();
|
let ancestors = vec![(0, 0)].into_iter().collect();
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
accounts.accounts_db.update_accounts_hash(0, &ancestors);
|
accounts
|
||||||
|
.accounts_db
|
||||||
|
.update_accounts_hash(0, &ancestors, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,7 +460,11 @@ impl Accounts {
|
|||||||
accounts_balances
|
accounts_balances
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_capitalization(&self, ancestors: &Ancestors) -> u64 {
|
pub fn calculate_capitalization(
|
||||||
|
&self,
|
||||||
|
ancestors: &Ancestors,
|
||||||
|
simple_capitalization_enabled: bool,
|
||||||
|
) -> u64 {
|
||||||
let balances =
|
let balances =
|
||||||
self.load_all_unchecked(ancestors)
|
self.load_all_unchecked(ancestors)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -469,6 +473,7 @@ impl Accounts {
|
|||||||
account.lamports,
|
account.lamports,
|
||||||
&account.owner,
|
&account.owner,
|
||||||
account.executable,
|
account.executable,
|
||||||
|
simple_capitalization_enabled,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -481,11 +486,14 @@ impl Accounts {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
ancestors: &Ancestors,
|
ancestors: &Ancestors,
|
||||||
total_lamports: u64,
|
total_lamports: u64,
|
||||||
|
simple_capitalization_enabled: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Err(err) =
|
if let Err(err) = self.accounts_db.verify_bank_hash_and_lamports(
|
||||||
self.accounts_db
|
slot,
|
||||||
.verify_bank_hash_and_lamports(slot, ancestors, total_lamports)
|
ancestors,
|
||||||
{
|
total_lamports,
|
||||||
|
simple_capitalization_enabled,
|
||||||
|
) {
|
||||||
warn!("verify_bank_hash failed: {:?}", err);
|
warn!("verify_bank_hash failed: {:?}", err);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
@ -2246,7 +2246,12 @@ impl AccountsDB {
|
|||||||
lamports: u64,
|
lamports: u64,
|
||||||
owner: &Pubkey,
|
owner: &Pubkey,
|
||||||
executable: bool,
|
executable: bool,
|
||||||
|
simple_capitalization_enabled: bool,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
|
if simple_capitalization_enabled {
|
||||||
|
return lamports;
|
||||||
|
}
|
||||||
|
|
||||||
let is_specially_retained = (solana_sdk::native_loader::check_id(owner) && executable)
|
let is_specially_retained = (solana_sdk::native_loader::check_id(owner) && executable)
|
||||||
|| solana_sdk::sysvar::check_id(owner);
|
|| solana_sdk::sysvar::check_id(owner);
|
||||||
|
|
||||||
@ -2265,6 +2270,7 @@ impl AccountsDB {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
ancestors: &Ancestors,
|
ancestors: &Ancestors,
|
||||||
check_hash: bool,
|
check_hash: bool,
|
||||||
|
simple_capitalization_enabled: bool,
|
||||||
) -> Result<(Hash, u64), BankHashVerificationError> {
|
) -> Result<(Hash, u64), BankHashVerificationError> {
|
||||||
use BankHashVerificationError::*;
|
use BankHashVerificationError::*;
|
||||||
let mut scan = Measure::start("scan");
|
let mut scan = Measure::start("scan");
|
||||||
@ -2295,6 +2301,7 @@ impl AccountsDB {
|
|||||||
account_info.lamports,
|
account_info.lamports,
|
||||||
&account.account_meta.owner,
|
&account.account_meta.owner,
|
||||||
account.account_meta.executable,
|
account.account_meta.executable,
|
||||||
|
simple_capitalization_enabled,
|
||||||
);
|
);
|
||||||
|
|
||||||
if check_hash {
|
if check_hash {
|
||||||
@ -2353,9 +2360,14 @@ impl AccountsDB {
|
|||||||
bank_hash_info.snapshot_hash
|
bank_hash_info.snapshot_hash
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_accounts_hash(&self, slot: Slot, ancestors: &Ancestors) -> (Hash, u64) {
|
pub fn update_accounts_hash(
|
||||||
|
&self,
|
||||||
|
slot: Slot,
|
||||||
|
ancestors: &Ancestors,
|
||||||
|
simple_capitalization_enabled: bool,
|
||||||
|
) -> (Hash, u64) {
|
||||||
let (hash, total_lamports) = self
|
let (hash, total_lamports) = self
|
||||||
.calculate_accounts_hash(slot, ancestors, false)
|
.calculate_accounts_hash(slot, ancestors, false, simple_capitalization_enabled)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut bank_hashes = self.bank_hashes.write().unwrap();
|
let mut bank_hashes = self.bank_hashes.write().unwrap();
|
||||||
let mut bank_hash_info = bank_hashes.get_mut(&slot).unwrap();
|
let mut bank_hash_info = bank_hashes.get_mut(&slot).unwrap();
|
||||||
@ -2368,11 +2380,12 @@ impl AccountsDB {
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
ancestors: &Ancestors,
|
ancestors: &Ancestors,
|
||||||
total_lamports: u64,
|
total_lamports: u64,
|
||||||
|
simple_capitalization_enabled: bool,
|
||||||
) -> Result<(), BankHashVerificationError> {
|
) -> Result<(), BankHashVerificationError> {
|
||||||
use BankHashVerificationError::*;
|
use BankHashVerificationError::*;
|
||||||
|
|
||||||
let (calculated_hash, calculated_lamports) =
|
let (calculated_hash, calculated_lamports) =
|
||||||
self.calculate_accounts_hash(slot, ancestors, true)?;
|
self.calculate_accounts_hash(slot, ancestors, true, simple_capitalization_enabled)?;
|
||||||
|
|
||||||
if calculated_lamports != total_lamports {
|
if calculated_lamports != total_lamports {
|
||||||
warn!(
|
warn!(
|
||||||
@ -4015,8 +4028,8 @@ pub mod tests {
|
|||||||
|
|
||||||
let ancestors = linear_ancestors(latest_slot);
|
let ancestors = linear_ancestors(latest_slot);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
daccounts.update_accounts_hash(latest_slot, &ancestors),
|
daccounts.update_accounts_hash(latest_slot, &ancestors, true),
|
||||||
accounts.update_accounts_hash(latest_slot, &ancestors)
|
accounts.update_accounts_hash(latest_slot, &ancestors, true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4169,12 +4182,12 @@ pub mod tests {
|
|||||||
|
|
||||||
let ancestors = linear_ancestors(current_slot);
|
let ancestors = linear_ancestors(current_slot);
|
||||||
info!("ancestors: {:?}", ancestors);
|
info!("ancestors: {:?}", ancestors);
|
||||||
let hash = accounts.update_accounts_hash(current_slot, &ancestors);
|
let hash = accounts.update_accounts_hash(current_slot, &ancestors, true);
|
||||||
|
|
||||||
accounts.clean_accounts(None);
|
accounts.clean_accounts(None);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
accounts.update_accounts_hash(current_slot, &ancestors),
|
accounts.update_accounts_hash(current_slot, &ancestors, true),
|
||||||
hash
|
hash
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -4291,7 +4304,7 @@ pub mod tests {
|
|||||||
accounts.add_root(current_slot);
|
accounts.add_root(current_slot);
|
||||||
|
|
||||||
accounts.print_accounts_stats("pre_f");
|
accounts.print_accounts_stats("pre_f");
|
||||||
accounts.update_accounts_hash(4, &HashMap::default());
|
accounts.update_accounts_hash(4, &HashMap::default(), true);
|
||||||
|
|
||||||
let accounts = f(accounts, current_slot);
|
let accounts = f(accounts, current_slot);
|
||||||
|
|
||||||
@ -4303,7 +4316,7 @@ pub mod tests {
|
|||||||
assert_load_account(&accounts, current_slot, dummy_pubkey, dummy_lamport);
|
assert_load_account(&accounts, current_slot, dummy_pubkey, dummy_lamport);
|
||||||
|
|
||||||
accounts
|
accounts
|
||||||
.verify_bank_hash_and_lamports(4, &HashMap::default(), 1222)
|
.verify_bank_hash_and_lamports(4, &HashMap::default(), 1222, true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4700,15 +4713,15 @@ pub mod tests {
|
|||||||
|
|
||||||
db.store(some_slot, &[(&key, &account)]);
|
db.store(some_slot, &[(&key, &account)]);
|
||||||
db.add_root(some_slot);
|
db.add_root(some_slot);
|
||||||
db.update_accounts_hash(some_slot, &ancestors);
|
db.update_accounts_hash(some_slot, &ancestors, true);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1, true),
|
||||||
Ok(_)
|
Ok(_)
|
||||||
);
|
);
|
||||||
|
|
||||||
db.bank_hashes.write().unwrap().remove(&some_slot).unwrap();
|
db.bank_hashes.write().unwrap().remove(&some_slot).unwrap();
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1, true),
|
||||||
Err(MissingBankHash)
|
Err(MissingBankHash)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -4723,7 +4736,7 @@ pub mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(some_slot, bank_hash_info);
|
.insert(some_slot, bank_hash_info);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1, true),
|
||||||
Err(MismatchedBankHash)
|
Err(MismatchedBankHash)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -4742,9 +4755,9 @@ pub mod tests {
|
|||||||
|
|
||||||
db.store(some_slot, &[(&key, &account)]);
|
db.store(some_slot, &[(&key, &account)]);
|
||||||
db.add_root(some_slot);
|
db.add_root(some_slot);
|
||||||
db.update_accounts_hash(some_slot, &ancestors);
|
db.update_accounts_hash(some_slot, &ancestors, true);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1, true),
|
||||||
Ok(_)
|
Ok(_)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -4756,15 +4769,19 @@ pub mod tests {
|
|||||||
&solana_sdk::native_loader::create_loadable_account("foo", 1),
|
&solana_sdk::native_loader::create_loadable_account("foo", 1),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
db.update_accounts_hash(some_slot, &ancestors);
|
db.update_accounts_hash(some_slot, &ancestors, true);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1, false),
|
||||||
|
Ok(_)
|
||||||
|
);
|
||||||
|
assert_matches!(
|
||||||
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 2, true),
|
||||||
Ok(_)
|
Ok(_)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 10),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 10, true),
|
||||||
Err(MismatchedTotalLamports(expected, actual)) if expected == 1 && actual == 10
|
Err(MismatchedTotalLamports(expected, actual)) if expected == 2 && actual == 10
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4781,9 +4798,9 @@ pub mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(some_slot, BankHashInfo::default());
|
.insert(some_slot, BankHashInfo::default());
|
||||||
db.add_root(some_slot);
|
db.add_root(some_slot);
|
||||||
db.update_accounts_hash(some_slot, &ancestors);
|
db.update_accounts_hash(some_slot, &ancestors, true);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 0),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 0, true),
|
||||||
Ok(_)
|
Ok(_)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -4808,7 +4825,7 @@ pub mod tests {
|
|||||||
db.store_accounts_default(some_slot, accounts, &[some_hash]);
|
db.store_accounts_default(some_slot, accounts, &[some_hash]);
|
||||||
db.add_root(some_slot);
|
db.add_root(some_slot);
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1),
|
db.verify_bank_hash_and_lamports(some_slot, &ancestors, 1, true),
|
||||||
Err(MismatchedAccountHash)
|
Err(MismatchedAccountHash)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -5284,14 +5301,14 @@ pub mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let no_ancestors = HashMap::default();
|
let no_ancestors = HashMap::default();
|
||||||
accounts.update_accounts_hash(current_slot, &no_ancestors);
|
accounts.update_accounts_hash(current_slot, &no_ancestors, true);
|
||||||
accounts
|
accounts
|
||||||
.verify_bank_hash_and_lamports(current_slot, &no_ancestors, 22300)
|
.verify_bank_hash_and_lamports(current_slot, &no_ancestors, 22300, true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let accounts = reconstruct_accounts_db_via_serialization(&accounts, current_slot);
|
let accounts = reconstruct_accounts_db_via_serialization(&accounts, current_slot);
|
||||||
accounts
|
accounts
|
||||||
.verify_bank_hash_and_lamports(current_slot, &no_ancestors, 22300)
|
.verify_bank_hash_and_lamports(current_slot, &no_ancestors, 22300, true)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// repeating should be no-op
|
// repeating should be no-op
|
||||||
@ -5488,7 +5505,7 @@ pub mod tests {
|
|||||||
fn test_account_balance_for_capitalization_normal() {
|
fn test_account_balance_for_capitalization_normal() {
|
||||||
// system accounts
|
// system accounts
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
AccountsDB::account_balance_for_capitalization(10, &Pubkey::default(), false),
|
AccountsDB::account_balance_for_capitalization(10, &Pubkey::default(), false, true),
|
||||||
10
|
10
|
||||||
);
|
);
|
||||||
// any random program data accounts
|
// any random program data accounts
|
||||||
@ -5496,7 +5513,17 @@ pub mod tests {
|
|||||||
AccountsDB::account_balance_for_capitalization(
|
AccountsDB::account_balance_for_capitalization(
|
||||||
10,
|
10,
|
||||||
&solana_sdk::pubkey::new_rand(),
|
&solana_sdk::pubkey::new_rand(),
|
||||||
false
|
false,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
10
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AccountsDB::account_balance_for_capitalization(
|
||||||
|
10,
|
||||||
|
&solana_sdk::pubkey::new_rand(),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
10
|
10
|
||||||
);
|
);
|
||||||
@ -5512,16 +5539,40 @@ pub mod tests {
|
|||||||
AccountsDB::account_balance_for_capitalization(
|
AccountsDB::account_balance_for_capitalization(
|
||||||
normal_sysvar.lamports,
|
normal_sysvar.lamports,
|
||||||
&normal_sysvar.owner,
|
&normal_sysvar.owner,
|
||||||
normal_sysvar.executable
|
normal_sysvar.executable,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AccountsDB::account_balance_for_capitalization(
|
||||||
|
normal_sysvar.lamports,
|
||||||
|
&normal_sysvar.owner,
|
||||||
|
normal_sysvar.executable,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
// currently transactions can send any lamports to sysvars although this is not sensible.
|
// currently transactions can send any lamports to sysvars although this is not sensible.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
AccountsDB::account_balance_for_capitalization(10, &solana_sdk::sysvar::id(), false),
|
AccountsDB::account_balance_for_capitalization(
|
||||||
|
10,
|
||||||
|
&solana_sdk::sysvar::id(),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
),
|
||||||
9
|
9
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AccountsDB::account_balance_for_capitalization(
|
||||||
|
10,
|
||||||
|
&solana_sdk::sysvar::id(),
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
10
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -5531,20 +5582,40 @@ pub mod tests {
|
|||||||
AccountsDB::account_balance_for_capitalization(
|
AccountsDB::account_balance_for_capitalization(
|
||||||
normal_native_program.lamports,
|
normal_native_program.lamports,
|
||||||
&normal_native_program.owner,
|
&normal_native_program.owner,
|
||||||
normal_native_program.executable
|
normal_native_program.executable,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AccountsDB::account_balance_for_capitalization(
|
||||||
|
normal_native_program.lamports,
|
||||||
|
&normal_native_program.owner,
|
||||||
|
normal_native_program.executable,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
// test maliciously assigned bogus native loader account
|
// test maliciously assigned bogus native loader account
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
AccountsDB::account_balance_for_capitalization(
|
AccountsDB::account_balance_for_capitalization(
|
||||||
1,
|
1,
|
||||||
&solana_sdk::native_loader::id(),
|
&solana_sdk::native_loader::id(),
|
||||||
false
|
false,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
1
|
1
|
||||||
)
|
);
|
||||||
|
assert_eq!(
|
||||||
|
AccountsDB::account_balance_for_capitalization(
|
||||||
|
1,
|
||||||
|
&solana_sdk::native_loader::id(),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1272,7 +1272,12 @@ impl Bank {
|
|||||||
{
|
{
|
||||||
let old_account = self.get_sysvar_account(pubkey);
|
let old_account = self.get_sysvar_account(pubkey);
|
||||||
let new_account = updater(&old_account);
|
let new_account = updater(&old_account);
|
||||||
|
|
||||||
|
if !self.simple_capitalization_enabled() {
|
||||||
self.store_account(pubkey, &new_account);
|
self.store_account(pubkey, &new_account);
|
||||||
|
} else {
|
||||||
|
self.store_account_and_update_capitalization(pubkey, &new_account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inherit_specially_retained_account_balance(&self, old_account: &Option<Account>) -> u64 {
|
fn inherit_specially_retained_account_balance(&self, old_account: &Option<Account>) -> u64 {
|
||||||
@ -2020,7 +2025,6 @@ impl Bank {
|
|||||||
// Bootstrap validator collects fees until `new_from_parent` is called.
|
// Bootstrap validator collects fees until `new_from_parent` is called.
|
||||||
self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
|
self.fee_rate_governor = genesis_config.fee_rate_governor.clone();
|
||||||
self.fee_calculator = self.fee_rate_governor.create_fee_calculator();
|
self.fee_calculator = self.fee_rate_governor.create_fee_calculator();
|
||||||
self.update_fees();
|
|
||||||
|
|
||||||
for (pubkey, account) in genesis_config.accounts.iter() {
|
for (pubkey, account) in genesis_config.accounts.iter() {
|
||||||
if self.get_account(&pubkey).is_some() {
|
if self.get_account(&pubkey).is_some() {
|
||||||
@ -2029,6 +2033,9 @@ impl Bank {
|
|||||||
self.store_account(pubkey, account);
|
self.store_account(pubkey, account);
|
||||||
self.capitalization.fetch_add(account.lamports, Relaxed);
|
self.capitalization.fetch_add(account.lamports, Relaxed);
|
||||||
}
|
}
|
||||||
|
// updating sysvars (the fees sysvar in this case) now depends on feature activations in
|
||||||
|
// genesis_config.accounts above
|
||||||
|
self.update_fees();
|
||||||
|
|
||||||
for (pubkey, account) in genesis_config.rewards_pools.iter() {
|
for (pubkey, account) in genesis_config.rewards_pools.iter() {
|
||||||
if self.get_account(&pubkey).is_some() {
|
if self.get_account(&pubkey).is_some() {
|
||||||
@ -2148,7 +2155,11 @@ impl Bank {
|
|||||||
name,
|
name,
|
||||||
self.inherit_specially_retained_account_balance(&existing_genuine_program),
|
self.inherit_specially_retained_account_balance(&existing_genuine_program),
|
||||||
);
|
);
|
||||||
|
if !self.simple_capitalization_enabled() {
|
||||||
self.store_account(&program_id, &account);
|
self.store_account(&program_id, &account);
|
||||||
|
} else {
|
||||||
|
self.store_account_and_update_capitalization(&program_id, &account);
|
||||||
|
}
|
||||||
|
|
||||||
debug!("Added native program {} under {:?}", name, program_id);
|
debug!("Added native program {} under {:?}", name, program_id);
|
||||||
}
|
}
|
||||||
@ -3765,7 +3776,6 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn store_account_and_update_capitalization(&self, pubkey: &Pubkey, new_account: &Account) {
|
fn store_account_and_update_capitalization(&self, pubkey: &Pubkey, new_account: &Account) {
|
||||||
if let Some(old_account) = self.get_account(&pubkey) {
|
if let Some(old_account) = self.get_account(&pubkey) {
|
||||||
match new_account.lamports.cmp(&old_account.lamports) {
|
match new_account.lamports.cmp(&old_account.lamports) {
|
||||||
@ -4071,6 +4081,7 @@ impl Bank {
|
|||||||
self.slot(),
|
self.slot(),
|
||||||
&self.ancestors,
|
&self.ancestors,
|
||||||
self.capitalization(),
|
self.capitalization(),
|
||||||
|
self.simple_capitalization_enabled(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4101,7 +4112,9 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_capitalization(&self) -> u64 {
|
pub fn calculate_capitalization(&self) -> u64 {
|
||||||
self.rc.accounts.calculate_capitalization(&self.ancestors)
|
self.rc
|
||||||
|
.accounts
|
||||||
|
.calculate_capitalization(&self.ancestors, self.simple_capitalization_enabled())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_and_verify_capitalization(&self) -> bool {
|
pub fn calculate_and_verify_capitalization(&self) -> bool {
|
||||||
@ -4132,11 +4145,11 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_accounts_hash(&self) -> Hash {
|
pub fn update_accounts_hash(&self) -> Hash {
|
||||||
let (hash, total_lamports) = self
|
let (hash, total_lamports) = self.rc.accounts.accounts_db.update_accounts_hash(
|
||||||
.rc
|
self.slot(),
|
||||||
.accounts
|
&self.ancestors,
|
||||||
.accounts_db
|
self.simple_capitalization_enabled(),
|
||||||
.update_accounts_hash(self.slot(), &self.ancestors);
|
);
|
||||||
assert_eq!(total_lamports, self.capitalization());
|
assert_eq!(total_lamports, self.capitalization());
|
||||||
hash
|
hash
|
||||||
}
|
}
|
||||||
@ -4445,6 +4458,28 @@ impl Bank {
|
|||||||
.is_active(&feature_set::stake_program_v2::id())
|
.is_active(&feature_set::stake_program_v2::id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn simple_capitalization_enabled(&self) -> bool {
|
||||||
|
self.simple_capitalization_enabled_at_genesis()
|
||||||
|
|| self
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::simple_capitalization::id())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simple_capitalization_enabled_at_genesis(&self) -> bool {
|
||||||
|
// genesis builtin initialization codepath is called even before the initial
|
||||||
|
// feature activation, so we need to peek this flag at very early bank
|
||||||
|
// initialization phase for the development genesis case
|
||||||
|
if let Some(account) = self.get_account(&feature_set::simple_capitalization::id()) {
|
||||||
|
if let Some(feature) = feature::from_account(&account) {
|
||||||
|
if feature.activated_at == Some(0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
// This is called from snapshot restore AND for each epoch boundary
|
// This is called from snapshot restore AND for each epoch boundary
|
||||||
// The entire code path herein must be idempotent
|
// The entire code path herein must be idempotent
|
||||||
fn apply_feature_activations(&mut self, init_finish_or_warp: bool) {
|
fn apply_feature_activations(&mut self, init_finish_or_warp: bool) {
|
||||||
@ -4476,6 +4511,10 @@ impl Bank {
|
|||||||
self.rewrite_stakes();
|
self.rewrite_stakes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if new_feature_activations.contains(&feature_set::simple_capitalization::id()) {
|
||||||
|
self.adjust_capitalization_for_existing_specially_retained_accounts();
|
||||||
|
}
|
||||||
|
|
||||||
self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations);
|
self.ensure_feature_builtins(init_finish_or_warp, &new_feature_activations);
|
||||||
self.reconfigure_token2_native_mint();
|
self.reconfigure_token2_native_mint();
|
||||||
self.ensure_no_storage_rewards_pool();
|
self.ensure_no_storage_rewards_pool();
|
||||||
@ -4560,6 +4599,39 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn adjust_capitalization_for_existing_specially_retained_accounts(&self) {
|
||||||
|
use solana_sdk::{bpf_loader, bpf_loader_deprecated, secp256k1_program};
|
||||||
|
let mut existing_sysvar_account_count = 8;
|
||||||
|
let mut existing_native_program_account_count = 4;
|
||||||
|
|
||||||
|
if self.get_account(&sysvar::rewards::id()).is_some() {
|
||||||
|
existing_sysvar_account_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.get_account(&bpf_loader::id()).is_some() {
|
||||||
|
existing_native_program_account_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.get_account(&bpf_loader_deprecated::id()).is_some() {
|
||||||
|
existing_native_program_account_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.get_account(&secp256k1_program::id()).is_some() {
|
||||||
|
existing_native_program_account_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Adjusted capitalization for existing {} sysvars and {} native programs from {}",
|
||||||
|
existing_sysvar_account_count,
|
||||||
|
existing_native_program_account_count,
|
||||||
|
self.capitalization()
|
||||||
|
);
|
||||||
|
self.capitalization.fetch_add(
|
||||||
|
existing_sysvar_account_count + existing_native_program_account_count,
|
||||||
|
Relaxed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn reconfigure_token2_native_mint(&mut self) {
|
fn reconfigure_token2_native_mint(&mut self) {
|
||||||
let reconfigure_token2_native_mint = match self.cluster_type() {
|
let reconfigure_token2_native_mint = match self.cluster_type() {
|
||||||
ClusterType::Development => true,
|
ClusterType::Development => true,
|
||||||
@ -5223,6 +5295,19 @@ pub(crate) mod tests {
|
|||||||
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_capitalization_diff_with_new_bank(
|
||||||
|
bank: &Bank,
|
||||||
|
updater: impl Fn() -> Bank,
|
||||||
|
asserter: impl Fn(u64, u64),
|
||||||
|
) -> Bank {
|
||||||
|
let old = bank.capitalization();
|
||||||
|
let bank = updater();
|
||||||
|
let new = bank.capitalization();
|
||||||
|
asserter(old, new);
|
||||||
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
bank
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_store_account_and_update_capitalization_missing() {
|
fn test_store_account_and_update_capitalization_missing() {
|
||||||
let (genesis_config, _mint_keypair) = create_genesis_config(0);
|
let (genesis_config, _mint_keypair) = create_genesis_config(0);
|
||||||
@ -5425,6 +5510,7 @@ pub(crate) mod tests {
|
|||||||
burn_percent: 10,
|
burn_percent: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
genesis_config.disable_cap_altering_features_for_preciseness();
|
||||||
let mut bank = Bank::new(&genesis_config);
|
let mut bank = Bank::new(&genesis_config);
|
||||||
// Enable rent collection
|
// Enable rent collection
|
||||||
bank.rent_collector.epoch = 5;
|
bank.rent_collector.epoch = 5;
|
||||||
@ -6416,6 +6502,11 @@ pub(crate) mod tests {
|
|||||||
.map(|(slot, _)| *slot)
|
.map(|(slot, _)| *slot)
|
||||||
.collect::<Vec<Slot>>()
|
.collect::<Vec<Slot>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_slot_in_next_epoch(&self) -> Slot {
|
||||||
|
self.epoch_schedule()
|
||||||
|
.get_first_slot_in_epoch(self.epoch() + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -7121,6 +7212,7 @@ pub(crate) mod tests {
|
|||||||
let (expected_fee_collected, expected_fee_burned) =
|
let (expected_fee_collected, expected_fee_burned) =
|
||||||
genesis_config.fee_rate_governor.burn(expected_fee_paid);
|
genesis_config.fee_rate_governor.burn(expected_fee_paid);
|
||||||
|
|
||||||
|
genesis_config.disable_cap_altering_features_for_preciseness();
|
||||||
let mut bank = Bank::new(&genesis_config);
|
let mut bank = Bank::new(&genesis_config);
|
||||||
|
|
||||||
let capitalization = bank.capitalization();
|
let capitalization = bank.capitalization();
|
||||||
@ -7919,18 +8011,22 @@ pub(crate) mod tests {
|
|||||||
assert_eq!(None, bank3.get_account_modified_since_parent(&pubkey));
|
assert_eq!(None, bank3.get_account_modified_since_parent(&pubkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn do_test_bank_update_sysvar_account(simple_capitalization_enabled: bool) {
|
||||||
fn test_bank_update_sysvar_account() {
|
|
||||||
use sysvar::clock::Clock;
|
use sysvar::clock::Clock;
|
||||||
|
|
||||||
let dummy_clock_id = solana_sdk::pubkey::new_rand();
|
let dummy_clock_id = solana_sdk::pubkey::new_rand();
|
||||||
let (genesis_config, _mint_keypair) = create_genesis_config(500);
|
let (mut genesis_config, _mint_keypair) = create_genesis_config(500);
|
||||||
|
|
||||||
let expected_previous_slot = 3;
|
let expected_previous_slot = 3;
|
||||||
let expected_next_slot = expected_previous_slot + 1;
|
let expected_next_slot = expected_previous_slot + 1;
|
||||||
|
|
||||||
// First, initialize the clock sysvar
|
// First, initialize the clock sysvar
|
||||||
|
if simple_capitalization_enabled {
|
||||||
|
activate_all_features(&mut genesis_config);
|
||||||
|
}
|
||||||
let bank1 = Arc::new(Bank::new(&genesis_config));
|
let bank1 = Arc::new(Bank::new(&genesis_config));
|
||||||
|
assert_eq!(bank1.calculate_capitalization(), bank1.capitalization());
|
||||||
|
|
||||||
assert_capitalization_diff(
|
assert_capitalization_diff(
|
||||||
&bank1,
|
&bank1,
|
||||||
|| {
|
|| {
|
||||||
@ -7952,7 +8048,12 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|old, new| {
|
|old, new| {
|
||||||
|
// only if simple_capitalization_enabled, cap should increment
|
||||||
|
if simple_capitalization_enabled {
|
||||||
|
assert_eq!(old + 1, new);
|
||||||
|
} else {
|
||||||
assert_eq!(old, new);
|
assert_eq!(old, new);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -8040,6 +8141,16 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bank_update_sysvar_account_with_simple_capitalization_disabled() {
|
||||||
|
do_test_bank_update_sysvar_account(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bank_update_sysvar_account_with_simple_capitalization_enabled() {
|
||||||
|
do_test_bank_update_sysvar_account(true);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bank_epoch_vote_accounts() {
|
fn test_bank_epoch_vote_accounts() {
|
||||||
let leader_pubkey = solana_sdk::pubkey::new_rand();
|
let leader_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
@ -10101,9 +10212,11 @@ pub(crate) mod tests {
|
|||||||
assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
|
assert_eq!(bank.get_account_modified_slot(&loader_id).unwrap().1, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn do_test_add_native_program(simple_capitalization_enabled: bool) {
|
||||||
fn test_add_native_program_no_overwrite() {
|
let (mut genesis_config, _mint_keypair) = create_genesis_config(100_000);
|
||||||
let (genesis_config, _mint_keypair) = create_genesis_config(100_000);
|
if simple_capitalization_enabled {
|
||||||
|
activate_all_features(&mut genesis_config);
|
||||||
|
}
|
||||||
|
|
||||||
let slot = 123;
|
let slot = 123;
|
||||||
let program_id = solana_sdk::pubkey::new_rand();
|
let program_id = solana_sdk::pubkey::new_rand();
|
||||||
@ -10119,7 +10232,11 @@ pub(crate) mod tests {
|
|||||||
&bank,
|
&bank,
|
||||||
|| bank.add_native_program("mock_program", &program_id, false),
|
|| bank.add_native_program("mock_program", &program_id, false),
|
||||||
|old, new| {
|
|old, new| {
|
||||||
|
if simple_capitalization_enabled {
|
||||||
|
assert_eq!(old + 1, new);
|
||||||
|
} else {
|
||||||
assert_eq!(old, new);
|
assert_eq!(old, new);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -10162,6 +10279,16 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_native_program_with_simple_capitalization_disabled() {
|
||||||
|
do_test_add_native_program(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_native_program_with_simple_capitalization_enabled() {
|
||||||
|
do_test_add_native_program(true);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_native_program_inherited_cap_while_replacing() {
|
fn test_add_native_program_inherited_cap_while_replacing() {
|
||||||
let (genesis_config, mint_keypair) = create_genesis_config(100_000);
|
let (genesis_config, mint_keypair) = create_genesis_config(100_000);
|
||||||
@ -10323,6 +10450,7 @@ pub(crate) mod tests {
|
|||||||
reward_pubkey,
|
reward_pubkey,
|
||||||
Account::new(u64::MAX, 0, &solana_sdk::pubkey::new_rand()),
|
Account::new(u64::MAX, 0, &solana_sdk::pubkey::new_rand()),
|
||||||
);
|
);
|
||||||
|
genesis_config.disable_cap_altering_features_for_preciseness();
|
||||||
let bank0 = Bank::new(&genesis_config);
|
let bank0 = Bank::new(&genesis_config);
|
||||||
// because capitalization has been reset with bogus capitalization calculation allowing overflows,
|
// because capitalization has been reset with bogus capitalization calculation allowing overflows,
|
||||||
// deliberately substract 1 lamport to simulate it
|
// deliberately substract 1 lamport to simulate it
|
||||||
@ -10743,6 +10871,113 @@ pub(crate) mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_capitalization_adjustment_minimum_genesis_set() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let (mut genesis_config, _mint_keypair) = create_genesis_config(0);
|
||||||
|
let feature_balance =
|
||||||
|
std::cmp::max(genesis_config.rent.minimum_balance(Feature::size_of()), 1);
|
||||||
|
|
||||||
|
// inhibit deprecated rewards sysvar creation altogether
|
||||||
|
genesis_config.accounts.insert(
|
||||||
|
feature_set::deprecate_rewards_sysvar::id(),
|
||||||
|
feature::create_account(
|
||||||
|
&Feature {
|
||||||
|
activated_at: Some(0),
|
||||||
|
},
|
||||||
|
feature_balance,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
let bank0 = Bank::new(&genesis_config);
|
||||||
|
let bank1 = Arc::new(new_from_parent(&Arc::new(bank0)));
|
||||||
|
|
||||||
|
// schedule activation of simple capitalization
|
||||||
|
bank1.store_account_and_update_capitalization(
|
||||||
|
&feature_set::simple_capitalization::id(),
|
||||||
|
&feature::create_account(&Feature { activated_at: None }, feature_balance),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 12 is minimum adjusted cap increase in adjust_capitalization_for_existing_specially_retained_accounts
|
||||||
|
assert_capitalization_diff_with_new_bank(
|
||||||
|
&bank1,
|
||||||
|
|| Bank::new_from_parent(&bank1, &Pubkey::default(), bank1.first_slot_in_next_epoch()),
|
||||||
|
|old, new| assert_eq!(old + 12, new),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_capitalization_adjustment_full_set() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let (mut genesis_config, _mint_keypair) = create_genesis_config(0);
|
||||||
|
let feature_balance =
|
||||||
|
std::cmp::max(genesis_config.rent.minimum_balance(Feature::size_of()), 1);
|
||||||
|
|
||||||
|
// activate all features but simple capitalization
|
||||||
|
activate_all_features(&mut genesis_config);
|
||||||
|
genesis_config
|
||||||
|
.accounts
|
||||||
|
.remove(&feature_set::simple_capitalization::id());
|
||||||
|
// intentionally create deprecated rewards sysvar creation
|
||||||
|
genesis_config
|
||||||
|
.accounts
|
||||||
|
.remove(&feature_set::deprecate_rewards_sysvar::id());
|
||||||
|
|
||||||
|
// intentionally create bogus native programs
|
||||||
|
fn mock_process_instruction(
|
||||||
|
_program_id: &Pubkey,
|
||||||
|
_keyed_accounts: &[KeyedAccount],
|
||||||
|
_data: &[u8],
|
||||||
|
_invoke_context: &mut dyn InvokeContext,
|
||||||
|
) -> std::result::Result<(), solana_sdk::instruction::InstructionError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
let builtins = Builtins {
|
||||||
|
genesis_builtins: vec![
|
||||||
|
Builtin::new(
|
||||||
|
"mock bpf",
|
||||||
|
solana_sdk::bpf_loader::id(),
|
||||||
|
mock_process_instruction,
|
||||||
|
),
|
||||||
|
Builtin::new(
|
||||||
|
"mock bpf",
|
||||||
|
solana_sdk::bpf_loader_deprecated::id(),
|
||||||
|
mock_process_instruction,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
feature_builtins: (vec![]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let bank0 = Arc::new(Bank::new_with_paths(
|
||||||
|
&genesis_config,
|
||||||
|
Vec::new(),
|
||||||
|
&[],
|
||||||
|
None,
|
||||||
|
Some(&builtins),
|
||||||
|
));
|
||||||
|
// move to next epoch to create now deprecated rewards sysvar intentionally
|
||||||
|
let bank1 = Arc::new(Bank::new_from_parent(
|
||||||
|
&bank0,
|
||||||
|
&Pubkey::default(),
|
||||||
|
bank0.first_slot_in_next_epoch(),
|
||||||
|
));
|
||||||
|
|
||||||
|
// schedule activation of simple capitalization
|
||||||
|
bank1.store_account_and_update_capitalization(
|
||||||
|
&feature_set::simple_capitalization::id(),
|
||||||
|
&feature::create_account(&Feature { activated_at: None }, feature_balance),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 16 is maximum adjusted cap increase in adjust_capitalization_for_existing_specially_retained_accounts
|
||||||
|
assert_capitalization_diff_with_new_bank(
|
||||||
|
&bank1,
|
||||||
|
|| Bank::new_from_parent(&bank1, &Pubkey::default(), bank1.first_slot_in_next_epoch()),
|
||||||
|
|old, new| assert_eq!(old + 16, new),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_timestamp_bounding_feature() {
|
fn test_timestamp_bounding_feature() {
|
||||||
let leader_pubkey = solana_sdk::pubkey::new_rand();
|
let leader_pubkey = solana_sdk::pubkey::new_rand();
|
||||||
|
@ -98,6 +98,10 @@ pub mod filter_stake_delegation_accounts {
|
|||||||
solana_sdk::declare_id!("GE7fRxmW46K6EmCD9AMZSbnaJ2e3LfqCZzdHi9hmYAgi");
|
solana_sdk::declare_id!("GE7fRxmW46K6EmCD9AMZSbnaJ2e3LfqCZzdHi9hmYAgi");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod simple_capitalization {
|
||||||
|
solana_sdk::declare_id!("9r69RnnxABmpcPFfj1yhg4n9YFR2MNaLdKJCC6v3Speb");
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Map of feature identifiers to user-visible description
|
/// Map of feature identifiers to user-visible description
|
||||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||||
@ -124,6 +128,7 @@ lazy_static! {
|
|||||||
(stake_program_v2::id(), "solana_stake_program v2"),
|
(stake_program_v2::id(), "solana_stake_program v2"),
|
||||||
(rewrite_stake::id(), "rewrite stake"),
|
(rewrite_stake::id(), "rewrite stake"),
|
||||||
(filter_stake_delegation_accounts::id(), "filter stake_delegation_accounts #14062"),
|
(filter_stake_delegation_accounts::id(), "filter stake_delegation_accounts #14062"),
|
||||||
|
(simple_capitalization::id(), "simple capitalization"),
|
||||||
/*************** ADD NEW FEATURES HERE ***************/
|
/*************** ADD NEW FEATURES HERE ***************/
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -149,6 +149,11 @@ impl GenesisConfig {
|
|||||||
hash(&serialized)
|
hash(&serialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn disable_cap_altering_features_for_preciseness(&mut self) {
|
||||||
|
self.accounts
|
||||||
|
.remove(&crate::feature_set::simple_capitalization::id());
|
||||||
|
}
|
||||||
|
|
||||||
fn genesis_filename(ledger_path: &Path) -> PathBuf {
|
fn genesis_filename(ledger_path: &Path) -> PathBuf {
|
||||||
Path::new(ledger_path).join("genesis.bin")
|
Path::new(ledger_path).join("genesis.bin")
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user