Tiny add_native_program bug fixes with cleanups (#14042)
* Tiny add_native_program bug fixes with cleanups * Fix typo
This commit is contained in:
parent
d33ab34d75
commit
164b7895b3
|
@ -4738,7 +4738,7 @@ pub mod tests {
|
||||||
some_slot,
|
some_slot,
|
||||||
&[(
|
&[(
|
||||||
&native_account_pubkey,
|
&native_account_pubkey,
|
||||||
&solana_sdk::native_loader::create_loadable_account("foo"),
|
&solana_sdk::native_loader::create_loadable_account("foo", 1),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
db.update_accounts_hash(some_slot, &ancestors);
|
db.update_accounts_hash(some_slot, &ancestors);
|
||||||
|
@ -5511,7 +5511,7 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_account_balance_for_capitalization_native_program() {
|
fn test_account_balance_for_capitalization_native_program() {
|
||||||
let normal_native_program = solana_sdk::native_loader::create_loadable_account("foo");
|
let normal_native_program = solana_sdk::native_loader::create_loadable_account("foo", 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
AccountsDB::account_balance_for_capitalization(
|
AccountsDB::account_balance_for_capitalization(
|
||||||
normal_native_program.lamports,
|
normal_native_program.lamports,
|
||||||
|
|
|
@ -1244,7 +1244,7 @@ impl Bank {
|
||||||
self.store_account(pubkey, &new_account);
|
self.store_account(pubkey, &new_account);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inherit_sysvar_account_balance(&self, old_account: &Option<Account>) -> u64 {
|
fn inherit_specially_retained_account_balance(&self, old_account: &Option<Account>) -> u64 {
|
||||||
old_account.as_ref().map(|a| a.lamports).unwrap_or(1)
|
old_account.as_ref().map(|a| a.lamports).unwrap_or(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1332,7 +1332,10 @@ impl Bank {
|
||||||
unix_timestamp,
|
unix_timestamp,
|
||||||
};
|
};
|
||||||
self.update_sysvar_account(&sysvar::clock::id(), |account| {
|
self.update_sysvar_account(&sysvar::clock::id(), |account| {
|
||||||
create_account(&clock, self.inherit_sysvar_account_balance(account))
|
create_account(
|
||||||
|
&clock,
|
||||||
|
self.inherit_specially_retained_account_balance(account),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,7 +1346,10 @@ impl Bank {
|
||||||
.map(|account| from_account::<SlotHistory>(&account).unwrap())
|
.map(|account| from_account::<SlotHistory>(&account).unwrap())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
slot_history.add(self.slot());
|
slot_history.add(self.slot());
|
||||||
create_account(&slot_history, self.inherit_sysvar_account_balance(account))
|
create_account(
|
||||||
|
&slot_history,
|
||||||
|
self.inherit_specially_retained_account_balance(account),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1354,7 +1360,10 @@ impl Bank {
|
||||||
.map(|account| from_account::<SlotHashes>(&account).unwrap())
|
.map(|account| from_account::<SlotHashes>(&account).unwrap())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
slot_hashes.add(self.parent_slot, self.parent_hash);
|
slot_hashes.add(self.parent_slot, self.parent_hash);
|
||||||
create_account(&slot_hashes, self.inherit_sysvar_account_balance(account))
|
create_account(
|
||||||
|
&slot_hashes,
|
||||||
|
self.inherit_specially_retained_account_balance(account),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,7 +1407,7 @@ impl Bank {
|
||||||
self.update_sysvar_account(&sysvar::fees::id(), |account| {
|
self.update_sysvar_account(&sysvar::fees::id(), |account| {
|
||||||
create_account(
|
create_account(
|
||||||
&sysvar::fees::Fees::new(&self.fee_calculator),
|
&sysvar::fees::Fees::new(&self.fee_calculator),
|
||||||
self.inherit_sysvar_account_balance(account),
|
self.inherit_specially_retained_account_balance(account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1407,7 +1416,7 @@ impl Bank {
|
||||||
self.update_sysvar_account(&sysvar::rent::id(), |account| {
|
self.update_sysvar_account(&sysvar::rent::id(), |account| {
|
||||||
create_account(
|
create_account(
|
||||||
&self.rent_collector.rent,
|
&self.rent_collector.rent,
|
||||||
self.inherit_sysvar_account_balance(account),
|
self.inherit_specially_retained_account_balance(account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1416,7 +1425,7 @@ impl Bank {
|
||||||
self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
|
self.update_sysvar_account(&sysvar::epoch_schedule::id(), |account| {
|
||||||
create_account(
|
create_account(
|
||||||
&self.epoch_schedule,
|
&self.epoch_schedule,
|
||||||
self.inherit_sysvar_account_balance(account),
|
self.inherit_specially_retained_account_balance(account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1429,7 +1438,7 @@ impl Bank {
|
||||||
self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
|
self.update_sysvar_account(&sysvar::stake_history::id(), |account| {
|
||||||
create_account::<sysvar::stake_history::StakeHistory>(
|
create_account::<sysvar::stake_history::StakeHistory>(
|
||||||
&self.stakes.read().unwrap().history(),
|
&self.stakes.read().unwrap().history(),
|
||||||
self.inherit_sysvar_account_balance(account),
|
self.inherit_specially_retained_account_balance(account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1548,7 +1557,7 @@ impl Bank {
|
||||||
self.update_sysvar_account(&sysvar::rewards::id(), |account| {
|
self.update_sysvar_account(&sysvar::rewards::id(), |account| {
|
||||||
create_account(
|
create_account(
|
||||||
&sysvar::rewards::Rewards::new(validator_point_value),
|
&sysvar::rewards::Rewards::new(validator_point_value),
|
||||||
self.inherit_sysvar_account_balance(account),
|
self.inherit_specially_retained_account_balance(account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1757,7 +1766,7 @@ impl Bank {
|
||||||
self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
|
self.update_sysvar_account(&sysvar::recent_blockhashes::id(), |account| {
|
||||||
let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
|
let recent_blockhash_iter = locked_blockhash_queue.get_recent_blockhashes();
|
||||||
recent_blockhashes_account::create_account_with_data(
|
recent_blockhashes_account::create_account_with_data(
|
||||||
self.inherit_sysvar_account_balance(account),
|
self.inherit_specially_retained_account_balance(account),
|
||||||
recent_blockhash_iter,
|
recent_blockhash_iter,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -2014,9 +2023,13 @@ impl Bank {
|
||||||
|
|
||||||
// NOTE: must hold idempotent for the same set of arguments
|
// NOTE: must hold idempotent for the same set of arguments
|
||||||
pub fn add_native_program(&self, name: &str, program_id: &Pubkey, must_replace: bool) {
|
pub fn add_native_program(&self, name: &str, program_id: &Pubkey, must_replace: bool) {
|
||||||
let mut existing_genuine_program = self.get_account(&program_id);
|
let existing_genuine_program = if let Some(mut account) = self.get_account(&program_id) {
|
||||||
if let Some(account) = &mut existing_genuine_program {
|
// it's very unlikely to be squatted at program_id as non-system account because of burden to
|
||||||
if !native_loader::check_id(&account.owner) {
|
// find victim's pubkey/hash. So, when account.owner is indeed native_loader's, it's
|
||||||
|
// safe to assume it's a genuine program.
|
||||||
|
if native_loader::check_id(&account.owner) {
|
||||||
|
Some(account)
|
||||||
|
} else {
|
||||||
// malicious account is pre-occupying at program_id
|
// malicious account is pre-occupying at program_id
|
||||||
// forcibly burn and purge it
|
// forcibly burn and purge it
|
||||||
|
|
||||||
|
@ -2026,13 +2039,16 @@ impl Bank {
|
||||||
// flush the Stakes cache
|
// flush the Stakes cache
|
||||||
account.lamports = 0;
|
account.lamports = 0;
|
||||||
self.store_account(&program_id, &account);
|
self.store_account(&program_id, &account);
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if must_replace {
|
if must_replace {
|
||||||
// updating native program
|
// updating native program
|
||||||
|
|
||||||
match existing_genuine_program {
|
match &existing_genuine_program {
|
||||||
None => panic!(
|
None => panic!(
|
||||||
"There is no account to replace with native program ({}, {}).",
|
"There is no account to replace with native program ({}, {}).",
|
||||||
name, program_id
|
name, program_id
|
||||||
|
@ -2048,7 +2064,7 @@ impl Bank {
|
||||||
} else {
|
} else {
|
||||||
// introducing native program
|
// introducing native program
|
||||||
|
|
||||||
match existing_genuine_program {
|
match &existing_genuine_program {
|
||||||
None => (), // continue to add account
|
None => (), // continue to add account
|
||||||
Some(_account) => {
|
Some(_account) => {
|
||||||
// nop; it seems that we already have account
|
// nop; it seems that we already have account
|
||||||
|
@ -2074,7 +2090,10 @@ impl Bank {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add a bogus executable native account, which will be loaded and ignored.
|
// Add a bogus executable native account, which will be loaded and ignored.
|
||||||
let account = native_loader::create_loadable_account(name);
|
let account = native_loader::create_loadable_account(
|
||||||
|
name,
|
||||||
|
self.inherit_specially_retained_account_balance(&existing_genuine_program),
|
||||||
|
);
|
||||||
self.store_account(&program_id, &account);
|
self.store_account(&program_id, &account);
|
||||||
|
|
||||||
debug!("Added native program {} under {:?}", name, program_id);
|
debug!("Added native program {} under {:?}", name, program_id);
|
||||||
|
@ -7022,6 +7041,8 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bank_tx_fee() {
|
fn test_bank_tx_fee() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
let arbitrary_transfer_amount = 42;
|
let arbitrary_transfer_amount = 42;
|
||||||
let mint = arbitrary_transfer_amount * 100;
|
let mint = arbitrary_transfer_amount * 100;
|
||||||
let leader = solana_sdk::pubkey::new_rand();
|
let leader = solana_sdk::pubkey::new_rand();
|
||||||
|
@ -7849,65 +7870,112 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
// First, initialize the clock sysvar
|
// First, initialize the clock sysvar
|
||||||
let bank1 = Arc::new(Bank::new(&genesis_config));
|
let bank1 = Arc::new(Bank::new(&genesis_config));
|
||||||
bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
assert_capitalization_diff(
|
||||||
assert!(optional_account.is_none());
|
&bank1,
|
||||||
|
|| {
|
||||||
|
bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
||||||
|
assert!(optional_account.is_none());
|
||||||
|
|
||||||
create_account(
|
create_account(
|
||||||
&Clock {
|
&Clock {
|
||||||
slot: expected_previous_slot,
|
slot: expected_previous_slot,
|
||||||
..Clock::default()
|
..Clock::default()
|
||||||
},
|
},
|
||||||
1,
|
bank1.inherit_specially_retained_account_balance(optional_account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let current_account = bank1.get_account(&dummy_clock_id).unwrap();
|
let current_account = bank1.get_account(&dummy_clock_id).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected_previous_slot,
|
expected_previous_slot,
|
||||||
from_account::<Clock>(¤t_account).unwrap().slot
|
from_account::<Clock>(¤t_account).unwrap().slot
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|old, new| {
|
||||||
|
assert_eq!(old, new);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_capitalization_diff(
|
||||||
|
&bank1,
|
||||||
|
|| {
|
||||||
|
bank1.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
||||||
|
assert!(optional_account.is_none());
|
||||||
|
|
||||||
|
create_account(
|
||||||
|
&Clock {
|
||||||
|
slot: expected_previous_slot,
|
||||||
|
..Clock::default()
|
||||||
|
},
|
||||||
|
bank1.inherit_specially_retained_account_balance(optional_account),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|old, new| {
|
||||||
|
// creating new sysvar twice in a slot shouldn't increment capitalization twice
|
||||||
|
assert_eq!(old, new);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Updating should increment the clock's slot
|
// Updating should increment the clock's slot
|
||||||
let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
|
let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 1));
|
||||||
bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
assert_capitalization_diff(
|
||||||
let slot = from_account::<Clock>(optional_account.as_ref().unwrap())
|
&bank2,
|
||||||
.unwrap()
|
|| {
|
||||||
.slot
|
bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
||||||
+ 1;
|
let slot = from_account::<Clock>(optional_account.as_ref().unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.slot
|
||||||
|
+ 1;
|
||||||
|
|
||||||
create_account(
|
create_account(
|
||||||
&Clock {
|
&Clock {
|
||||||
slot,
|
slot,
|
||||||
..Clock::default()
|
..Clock::default()
|
||||||
},
|
},
|
||||||
1,
|
bank2.inherit_specially_retained_account_balance(optional_account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let current_account = bank2.get_account(&dummy_clock_id).unwrap();
|
let current_account = bank2.get_account(&dummy_clock_id).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected_next_slot,
|
expected_next_slot,
|
||||||
from_account::<Clock>(¤t_account).unwrap().slot
|
from_account::<Clock>(¤t_account).unwrap().slot
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|old, new| {
|
||||||
|
// if existing, capitalization shouldn't change
|
||||||
|
assert_eq!(old, new);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Updating again should give bank1's sysvar to the closure not bank2's.
|
// Updating again should give bank1's sysvar to the closure not bank2's.
|
||||||
// Thus, assert with same expected_next_slot as previously
|
// Thus, assert with same expected_next_slot as previously
|
||||||
bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
assert_capitalization_diff(
|
||||||
let slot = from_account::<Clock>(optional_account.as_ref().unwrap())
|
&bank2,
|
||||||
.unwrap()
|
|| {
|
||||||
.slot
|
bank2.update_sysvar_account(&dummy_clock_id, |optional_account| {
|
||||||
+ 1;
|
let slot = from_account::<Clock>(optional_account.as_ref().unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.slot
|
||||||
|
+ 1;
|
||||||
|
|
||||||
create_account(
|
create_account(
|
||||||
&Clock {
|
&Clock {
|
||||||
slot,
|
slot,
|
||||||
..Clock::default()
|
..Clock::default()
|
||||||
},
|
},
|
||||||
1,
|
bank2.inherit_specially_retained_account_balance(optional_account),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let current_account = bank2.get_account(&dummy_clock_id).unwrap();
|
let current_account = bank2.get_account(&dummy_clock_id).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
expected_next_slot,
|
expected_next_slot,
|
||||||
from_account::<Clock>(¤t_account).unwrap().slot
|
from_account::<Clock>(¤t_account).unwrap().slot
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|old, new| {
|
||||||
|
// updating twice in a slot shouldn't increment capitalization twice
|
||||||
|
assert_eq!(old, new);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8523,13 +8591,34 @@ pub(crate) mod tests {
|
||||||
assert!(bank.stakes.read().unwrap().vote_accounts().is_empty());
|
assert!(bank.stakes.read().unwrap().vote_accounts().is_empty());
|
||||||
assert!(bank.stakes.read().unwrap().stake_delegations().is_empty());
|
assert!(bank.stakes.read().unwrap().stake_delegations().is_empty());
|
||||||
assert_eq!(bank.calculate_capitalization(), bank.capitalization());
|
assert_eq!(bank.calculate_capitalization(), bank.capitalization());
|
||||||
|
assert_eq!(
|
||||||
|
"mock_program1",
|
||||||
|
String::from_utf8_lossy(&bank.get_account(&vote_id).unwrap_or_default().data)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
"mock_program2",
|
||||||
|
String::from_utf8_lossy(&bank.get_account(&stake_id).unwrap_or_default().data)
|
||||||
|
);
|
||||||
|
|
||||||
// Re-adding builtin programs should be no-op
|
// Re-adding builtin programs should be no-op
|
||||||
|
bank.update_accounts_hash();
|
||||||
|
let old_hash = bank.get_accounts_hash();
|
||||||
bank.add_builtin("mock_program1", vote_id, mock_ix_processor);
|
bank.add_builtin("mock_program1", vote_id, mock_ix_processor);
|
||||||
bank.add_builtin("mock_program2", stake_id, mock_ix_processor);
|
bank.add_builtin("mock_program2", stake_id, mock_ix_processor);
|
||||||
|
bank.update_accounts_hash();
|
||||||
|
let new_hash = bank.get_accounts_hash();
|
||||||
|
assert_eq!(old_hash, new_hash);
|
||||||
assert!(bank.stakes.read().unwrap().vote_accounts().is_empty());
|
assert!(bank.stakes.read().unwrap().vote_accounts().is_empty());
|
||||||
assert!(bank.stakes.read().unwrap().stake_delegations().is_empty());
|
assert!(bank.stakes.read().unwrap().stake_delegations().is_empty());
|
||||||
assert_eq!(bank.calculate_capitalization(), bank.capitalization());
|
assert_eq!(bank.calculate_capitalization(), bank.capitalization());
|
||||||
|
assert_eq!(
|
||||||
|
"mock_program1",
|
||||||
|
String::from_utf8_lossy(&bank.get_account(&vote_id).unwrap_or_default().data)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
"mock_program2",
|
||||||
|
String::from_utf8_lossy(&bank.get_account(&stake_id).unwrap_or_default().data)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -9958,39 +10047,53 @@ pub(crate) mod tests {
|
||||||
let slot = 123;
|
let slot = 123;
|
||||||
let program_id = solana_sdk::pubkey::new_rand();
|
let program_id = solana_sdk::pubkey::new_rand();
|
||||||
|
|
||||||
let mut bank = Arc::new(Bank::new_from_parent(
|
let bank = Arc::new(Bank::new_from_parent(
|
||||||
&Arc::new(Bank::new(&genesis_config)),
|
&Arc::new(Bank::new(&genesis_config)),
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
slot,
|
slot,
|
||||||
));
|
));
|
||||||
assert_eq!(bank.get_account_modified_slot(&program_id), None);
|
assert_eq!(bank.get_account_modified_slot(&program_id), None);
|
||||||
|
|
||||||
Arc::get_mut(&mut bank)
|
assert_capitalization_diff(
|
||||||
.unwrap()
|
&bank,
|
||||||
.add_native_program("mock_program", &program_id, false);
|
|| bank.add_native_program("mock_program", &program_id, false),
|
||||||
|
|old, new| {
|
||||||
|
assert_eq!(old, new);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
|
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
|
||||||
|
|
||||||
let mut bank = Arc::new(new_from_parent(&bank));
|
let bank = Arc::new(new_from_parent(&bank));
|
||||||
Arc::get_mut(&mut bank)
|
assert_capitalization_diff(
|
||||||
.unwrap()
|
&bank,
|
||||||
.add_native_program("mock_program", &program_id, false);
|
|| bank.add_native_program("mock_program", &program_id, false),
|
||||||
|
|old, new| assert_eq!(old, new),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
|
assert_eq!(bank.get_account_modified_slot(&program_id).unwrap().1, slot);
|
||||||
|
|
||||||
let mut bank = Arc::new(new_from_parent(&bank));
|
let bank = Arc::new(new_from_parent(&bank));
|
||||||
// When replacing native_program, name must change to disambiguate from repeated
|
// When replacing native_program, name must change to disambiguate from repeated
|
||||||
// invocations.
|
// invocations.
|
||||||
Arc::get_mut(&mut bank)
|
assert_capitalization_diff(
|
||||||
.unwrap()
|
&bank,
|
||||||
.add_native_program("mock_program v2", &program_id, true);
|
|| bank.add_native_program("mock_program v2", &program_id, true),
|
||||||
|
|old, new| assert_eq!(old, new),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bank.get_account_modified_slot(&program_id).unwrap().1,
|
bank.get_account_modified_slot(&program_id).unwrap().1,
|
||||||
bank.slot()
|
bank.slot()
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut bank = Arc::new(new_from_parent(&bank));
|
let bank = Arc::new(new_from_parent(&bank));
|
||||||
Arc::get_mut(&mut bank)
|
assert_capitalization_diff(
|
||||||
.unwrap()
|
&bank,
|
||||||
.add_native_program("mock_program v2", &program_id, true);
|
|| bank.add_native_program("mock_program v2", &program_id, true),
|
||||||
|
|old, new| assert_eq!(old, new),
|
||||||
|
);
|
||||||
|
|
||||||
// replacing with same name shouldn't update account
|
// replacing with same name shouldn't update account
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
bank.get_account_modified_slot(&program_id).unwrap().1,
|
bank.get_account_modified_slot(&program_id).unwrap().1,
|
||||||
|
@ -9998,6 +10101,41 @@ pub(crate) mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_native_program_inherited_cap_while_replacing() {
|
||||||
|
let (genesis_config, mint_keypair) = create_genesis_config(100_000);
|
||||||
|
let bank = Bank::new(&genesis_config);
|
||||||
|
let program_id = solana_sdk::pubkey::new_rand();
|
||||||
|
|
||||||
|
bank.add_native_program("mock_program", &program_id, false);
|
||||||
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
|
||||||
|
// someone mess with program_id's balance
|
||||||
|
bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
|
||||||
|
assert_ne!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
bank.deposit(&program_id, 10);
|
||||||
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
|
||||||
|
bank.add_native_program("mock_program v2", &program_id, true);
|
||||||
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_native_program_squatted_while_not_replacing() {
|
||||||
|
let (genesis_config, mint_keypair) = create_genesis_config(100_000);
|
||||||
|
let bank = Bank::new(&genesis_config);
|
||||||
|
let program_id = solana_sdk::pubkey::new_rand();
|
||||||
|
|
||||||
|
// someone managed to squat at program_id!
|
||||||
|
bank.withdraw(&mint_keypair.pubkey(), 10).unwrap();
|
||||||
|
assert_ne!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
bank.deposit(&program_id, 10);
|
||||||
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
|
||||||
|
bank.add_native_program("mock_program", &program_id, false);
|
||||||
|
assert_eq!(bank.capitalization(), bank.calculate_capitalization());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(
|
#[should_panic(
|
||||||
expected = "Can't change frozen bank by adding not-existing new native \
|
expected = "Can't change frozen bank by adding not-existing new native \
|
||||||
|
|
|
@ -1317,7 +1317,7 @@ mod tests {
|
||||||
accounts.push(account);
|
accounts.push(account);
|
||||||
|
|
||||||
let mut loaders: Vec<Vec<(Pubkey, RefCell<Account>)>> = Vec::new();
|
let mut loaders: Vec<Vec<(Pubkey, RefCell<Account>)>> = Vec::new();
|
||||||
let account = RefCell::new(create_loadable_account("mock_system_program"));
|
let account = RefCell::new(create_loadable_account("mock_system_program", 1));
|
||||||
loaders.push(vec![(mock_system_program_id, account)]);
|
loaders.push(vec![(mock_system_program_id, account)]);
|
||||||
|
|
||||||
let executors = Rc::new(RefCell::new(Executors::default()));
|
let executors = Rc::new(RefCell::new(Executors::default()));
|
||||||
|
@ -1478,7 +1478,7 @@ mod tests {
|
||||||
accounts.push(account);
|
accounts.push(account);
|
||||||
|
|
||||||
let mut loaders: Vec<Vec<(Pubkey, RefCell<Account>)>> = Vec::new();
|
let mut loaders: Vec<Vec<(Pubkey, RefCell<Account>)>> = Vec::new();
|
||||||
let account = RefCell::new(create_loadable_account("mock_system_program"));
|
let account = RefCell::new(create_loadable_account("mock_system_program", 1));
|
||||||
loaders.push(vec![(mock_program_id, account)]);
|
loaders.push(vec![(mock_program_id, account)]);
|
||||||
|
|
||||||
let executors = Rc::new(RefCell::new(Executors::default()));
|
let executors = Rc::new(RefCell::new(Executors::default()));
|
||||||
|
|
|
@ -3,9 +3,9 @@ use crate::account::Account;
|
||||||
crate::declare_id!("NativeLoader1111111111111111111111111111111");
|
crate::declare_id!("NativeLoader1111111111111111111111111111111");
|
||||||
|
|
||||||
/// Create an executable account with the given shared object name.
|
/// Create an executable account with the given shared object name.
|
||||||
pub fn create_loadable_account(name: &str) -> Account {
|
pub fn create_loadable_account(name: &str, lamports: u64) -> Account {
|
||||||
Account {
|
Account {
|
||||||
lamports: 1,
|
lamports,
|
||||||
owner: id(),
|
owner: id(),
|
||||||
data: name.as_bytes().to_vec(),
|
data: name.as_bytes().to_vec(),
|
||||||
executable: true,
|
executable: true,
|
||||||
|
|
Loading…
Reference in New Issue