v1.0: Maintain sysvar balances for consistent market cap. (#9937)

* Maintain sysvar balances for consistent market cap.

* Back-port fun and gating adjustments

* Add comment

* Adjust test
This commit is contained in:
Ryo Onodera
2020-05-09 01:19:03 +09:00
committed by GitHub
parent 4999fa6263
commit a7b0fcc21e
3 changed files with 172 additions and 18 deletions

View File

@@ -1071,7 +1071,7 @@ impl AccountsDB {
pub fn include_owner_in_hash(slot: Slot) -> bool {
// Account hashing updated to include owner activates at this slot on the mainnet-beta
slot >= 11_000_000
slot >= 12_500_000
}
pub fn hash_account_data(

View File

@@ -72,6 +72,8 @@ pub const MAX_SNAPSHOT_DATA_FILE_SIZE: u64 = 32 * 1024 * 1024 * 1024; // 32 GiB
pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5;
const SYSVAR_BALANCE_ACTIVATION_EPOCH: Epoch = 25;
type BankStatusCache = StatusCache<Result<()>>;
pub type BankSlotDelta = SlotDelta<Result<()>>;
type TransactionAccountRefCells = Vec<Rc<RefCell<Account>>>;
@@ -556,8 +558,17 @@ impl Bank {
self.store_account(pubkey, &new_account);
}
fn inherit_sysvar_account_balance(&self, old_account: &Option<Account>) -> u64 {
// Corrent sysvar account balance maintenance activates at this epoch on the mainnet-beta
if self.epoch() >= SYSVAR_BALANCE_ACTIVATION_EPOCH {
old_account.as_ref().map(|a| a.lamports).unwrap_or(1)
} else {
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),
@@ -565,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))
});
}
@@ -576,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))
});
}
@@ -587,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))
});
}
@@ -622,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,
)
});
}
@@ -644,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(),
)
});
}
@@ -680,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);
@@ -747,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,
)
});
}
@@ -1896,12 +1926,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!(
@@ -3484,6 +3515,45 @@ 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_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), 1);
let bank = Arc::new(Bank::new_from_parent(
&bank,
&Pubkey::default(),
genesis_config
.epoch_schedule
.get_first_slot_in_epoch(SYSVAR_BALANCE_ACTIVATION_EPOCH),
));
let normal_pubkey = Pubkey::new_rand();
bank.transfer(6000, &mint_keypair, &normal_pubkey).unwrap();
bank.transfer(6000, &mint_keypair, &sysvar_pubkey).unwrap();
assert_eq!(bank.get_balance(&normal_pubkey), 3561);
assert_eq!(bank.get_balance(&sysvar_pubkey), 6001);
let bank = Arc::new(new_from_parent(&bank));
assert_eq!(bank.get_balance(&normal_pubkey), 3561);
assert_eq!(bank.get_balance(&sysvar_pubkey), 6001);
}
#[test]
fn test_bank_deposit() {
let (genesis_config, _mint_keypair) = create_genesis_config(100);