Maintain sysvar balances for consistent market cap. (#9936)

* Maintain sysvar balances for consistent market cap.

* Unindent
This commit is contained in:
Ryo Onodera 2020-05-09 02:42:32 +09:00 committed by GitHub
parent f98bfda6f9
commit 00e45ec935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 140 additions and 17 deletions

View File

@ -778,6 +778,14 @@ fn main() {
.help("Include sysvars too"),
)
.arg(&max_genesis_archive_unpacked_size_arg)
).subcommand(
SubCommand::with_name("capitalization")
.about("Print capitalization (aka, total suppy)")
.arg(&no_snapshot_arg)
.arg(&account_paths_arg)
.arg(&halt_at_slot_arg)
.arg(&hard_forks_arg)
.arg(&max_genesis_archive_unpacked_size_arg)
).subcommand(
SubCommand::with_name("prune")
.about("Prune the ledger from a yaml file containing a list of slots to prune.")
@ -1112,6 +1120,76 @@ fn main() {
}
}
}
("capitalization", Some(arg_matches)) => {
let dev_halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok();
let process_options = ProcessOptions {
dev_halt_at_slot,
new_hard_forks: hardforks_of(arg_matches, "hard_forks"),
poh_verify: false,
..ProcessOptions::default()
};
let genesis_config = open_genesis_config_by(&ledger_path, arg_matches);
match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) {
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
let slot = bank_forks.working_bank().slot();
let bank = bank_forks.get(slot).unwrap_or_else(|| {
eprintln!("Error: Slot {} is not available", slot);
exit(1);
});
use solana_sdk::native_token::LAMPORTS_PER_SOL;
use std::fmt::{Display, Formatter, Result};
pub struct Sol(u64);
impl Display for Sol {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(
f,
"{}.{:09} SOL",
self.0 / LAMPORTS_PER_SOL,
self.0 % LAMPORTS_PER_SOL
)
}
}
let computed_capitalization: u64 = bank
.get_program_accounts(None)
.into_iter()
.filter_map(|(_pubkey, account)| {
if account.lamports == u64::max_value() {
return None;
}
let is_specially_retained =
solana_sdk::native_loader::check_id(&account.owner)
|| solana_sdk::sysvar::check_id(&account.owner);
if is_specially_retained {
// specially retained accounts are ensured to exist by
// alwaysing having a balance of 1 lamports, which is
// outside the capitalization calculation.
Some(account.lamports - 1)
} else {
Some(account.lamports)
}
})
.sum();
if bank.capitalization() != computed_capitalization {
panic!(
"Capitalization mismatch!?: {} != {}",
bank.capitalization(),
computed_capitalization
);
}
println!("Capitalization: {}", Sol(bank.capitalization()));
}
Err(err) => {
eprintln!("Failed to load ledger: {:?}", err);
exit(1);
}
}
}
("purge", Some(arg_matches)) => {
let start_slot = value_t_or_exit!(arg_matches, "start_slot", Slot);
let end_slot = value_t!(arg_matches, "end_slot", Slot);

View File

@ -563,8 +563,12 @@ impl Bank {
self.store_account(pubkey, &new_account);
}
fn inherit_sysvar_account_balance(&self, old_account: &Option<Account>) -> u64 {
old_account.as_ref().map(|a| a.lamports).unwrap_or(1)
}
fn update_clock(&self) {
self.update_sysvar_account(&sysvar::clock::id(), |_| {
self.update_sysvar_account(&sysvar::clock::id(), |account| {
sysvar::clock::Clock {
slot: self.slot,
segment: get_segment_from_slot(self.slot, self.slots_per_segment),
@ -572,7 +576,7 @@ impl Bank {
leader_schedule_epoch: self.epoch_schedule.get_leader_schedule_epoch(self.slot),
unix_timestamp: self.unix_timestamp(),
}
.create_account(1)
.create_account(self.inherit_sysvar_account_balance(account))
});
}
@ -583,7 +587,7 @@ impl Bank {
.map(|account| SlotHistory::from_account(&account).unwrap())
.unwrap_or_default();
slot_history.add(self.slot());
slot_history.create_account(1)
slot_history.create_account(self.inherit_sysvar_account_balance(account))
});
}
@ -594,7 +598,7 @@ impl Bank {
.map(|account| SlotHashes::from_account(&account).unwrap())
.unwrap_or_default();
slot_hashes.add(self.parent_slot, self.parent_hash);
slot_hashes.create_account(1)
slot_hashes.create_account(self.inherit_sysvar_account_balance(account))
});
}
@ -629,20 +633,29 @@ impl Bank {
}
fn update_fees(&self) {
self.update_sysvar_account(&sysvar::fees::id(), |_| {
sysvar::fees::create_account(1, &self.fee_calculator)
self.update_sysvar_account(&sysvar::fees::id(), |account| {
sysvar::fees::create_account(
self.inherit_sysvar_account_balance(account),
&self.fee_calculator,
)
});
}
fn update_rent(&self) {
self.update_sysvar_account(&sysvar::rent::id(), |_| {
sysvar::rent::create_account(1, &self.rent_collector.rent)
self.update_sysvar_account(&sysvar::rent::id(), |account| {
sysvar::rent::create_account(
self.inherit_sysvar_account_balance(account),
&self.rent_collector.rent,
)
});
}
fn update_epoch_schedule(&self) {
self.update_sysvar_account(&sysvar::epoch_schedule::id(), |_| {
sysvar::epoch_schedule::create_account(1, &self.epoch_schedule)
self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
sysvar::epoch_schedule::create_account(
self.inherit_sysvar_account_balance(account),
&self.epoch_schedule,
)
});
}
@ -651,8 +664,11 @@ impl Bank {
return;
}
// if I'm the first Bank in an epoch, ensure stake_history is updated
self.update_sysvar_account(&sysvar::stake_history::id(), |_| {
sysvar::stake_history::create_account(1, self.stakes.read().unwrap().history())
self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
sysvar::stake_history::create_account(
self.inherit_sysvar_account_balance(account),
self.stakes.read().unwrap().history(),
)
});
}
@ -687,8 +703,12 @@ impl Bank {
validator_rewards / validator_points as f64,
storage_rewards / storage_points as f64,
);
self.update_sysvar_account(&sysvar::rewards::id(), |_| {
sysvar::rewards::create_account(1, validator_point_value, storage_point_value)
self.update_sysvar_account(&sysvar::rewards::id(), |account| {
sysvar::rewards::create_account(
self.inherit_sysvar_account_balance(account),
validator_point_value,
storage_point_value,
)
});
let validator_rewards = self.pay_validator_rewards(validator_point_value);
@ -754,10 +774,13 @@ impl Bank {
}
pub fn update_recent_blockhashes(&self) {
self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |_| {
self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
let blockhash_queue = self.blockhash_queue.read().unwrap();
let recent_blockhash_iter = blockhash_queue.get_recent_blockhashes();
sysvar::recent_blockhashes::create_account_with_data(1, recent_blockhash_iter)
sysvar::recent_blockhashes::create_account_with_data(
self.inherit_sysvar_account_balance(account),
recent_blockhash_iter,
)
});
}
@ -1945,12 +1968,13 @@ impl Bank {
}
info!(
"bank frozen: {} hash: {} accounts_delta: {} signature_count: {} last_blockhash: {}",
"bank frozen: {} hash: {} accounts_delta: {} signature_count: {} last_blockhash: {} capitalization: {}",
self.slot(),
hash,
accounts_delta_hash.hash,
self.signature_count(),
self.last_blockhash(),
self.capitalization(),
);
info!(
@ -3558,6 +3582,27 @@ mod tests {
assert_eq!(bank.get_balance(&pubkey), 500);
}
#[test]
fn test_transfer_to_sysvar() {
solana_logger::setup();
let (genesis_config, mint_keypair) = create_genesis_config(10_000);
let bank = Arc::new(Bank::new(&genesis_config));
let normal_pubkey = Pubkey::new_rand();
let sysvar_pubkey = sysvar::clock::id();
assert_eq!(bank.get_balance(&normal_pubkey), 0);
assert_eq!(bank.get_balance(&sysvar_pubkey), 1);
bank.transfer(500, &mint_keypair, &normal_pubkey).unwrap();
bank.transfer(500, &mint_keypair, &sysvar_pubkey).unwrap();
assert_eq!(bank.get_balance(&normal_pubkey), 500);
assert_eq!(bank.get_balance(&sysvar_pubkey), 501);
let bank = Arc::new(new_from_parent(&bank));
assert_eq!(bank.get_balance(&normal_pubkey), 500);
assert_eq!(bank.get_balance(&sysvar_pubkey), 501);
}
#[test]
fn test_bank_deposit() {
let (genesis_config, _mint_keypair) = create_genesis_config(100);