Maintain sysvar balances for consistent market cap. (#9936)
* Maintain sysvar balances for consistent market cap. * Unindent
This commit is contained in:
parent
f98bfda6f9
commit
00e45ec935
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue