Rework spl_token_v2_self_transfer_fix to avoid any SPL Token downtime (#15306)
(cherry picked from commit 2e7aebf0bb
)
Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
@ -4785,13 +4785,31 @@ impl Bank {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply_spl_token_v2_self_transfer_fix(&mut self) {
|
fn apply_spl_token_v2_self_transfer_fix(&mut self) {
|
||||||
if let Some(mut account) = self.get_account(&inline_spl_token_v2_0::id()) {
|
if let Some(old_account) = self.get_account(&inline_spl_token_v2_0::id()) {
|
||||||
self.capitalization.fetch_sub(account.lamports, Relaxed);
|
if let Some(new_account) =
|
||||||
account.lamports = 0;
|
self.get_account(&inline_spl_token_v2_0::new_token_program::id())
|
||||||
self.store_account(&inline_spl_token_v2_0::id(), &account);
|
{
|
||||||
|
datapoint_info!(
|
||||||
|
"bank-apply_spl_token_v2_self_transfer_fix",
|
||||||
|
("slot", self.slot, i64),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Burn lamports in the old token account
|
||||||
|
self.capitalization.fetch_sub(old_account.lamports, Relaxed);
|
||||||
|
|
||||||
|
// Transfer new token account to old token account
|
||||||
|
self.store_account(&inline_spl_token_v2_0::id(), &new_account);
|
||||||
|
|
||||||
|
// Clear new token account
|
||||||
|
self.store_account(
|
||||||
|
&inline_spl_token_v2_0::new_token_program::id(),
|
||||||
|
&Account::default(),
|
||||||
|
);
|
||||||
|
|
||||||
self.remove_executor(&inline_spl_token_v2_0::id());
|
self.remove_executor(&inline_spl_token_v2_0::id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn adjust_capitalization_for_existing_specially_retained_accounts(&self) {
|
fn adjust_capitalization_for_existing_specially_retained_accounts(&self) {
|
||||||
use solana_sdk::{bpf_loader, bpf_loader_deprecated, secp256k1_program};
|
use solana_sdk::{bpf_loader, bpf_loader_deprecated, secp256k1_program};
|
||||||
@ -11080,7 +11098,7 @@ pub(crate) mod tests {
|
|||||||
let (genesis_config, _mint_keypair) = create_genesis_config(0);
|
let (genesis_config, _mint_keypair) = create_genesis_config(0);
|
||||||
let mut bank = Bank::new(&genesis_config);
|
let mut bank = Bank::new(&genesis_config);
|
||||||
|
|
||||||
// Setup a simulated account
|
// Setup original token account
|
||||||
bank.store_account_and_update_capitalization(
|
bank.store_account_and_update_capitalization(
|
||||||
&inline_spl_token_v2_0::id(),
|
&inline_spl_token_v2_0::id(),
|
||||||
&Account {
|
&Account {
|
||||||
@ -11089,12 +11107,40 @@ pub(crate) mod tests {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
assert_eq!(bank.get_balance(&inline_spl_token_v2_0::id()), 100);
|
assert_eq!(bank.get_balance(&inline_spl_token_v2_0::id()), 100);
|
||||||
|
|
||||||
|
// Setup new token account
|
||||||
|
let new_token_account = Account {
|
||||||
|
lamports: 123,
|
||||||
|
data: vec![1, 2, 3],
|
||||||
|
executable: true,
|
||||||
|
..Account::default()
|
||||||
|
};
|
||||||
|
bank.store_account_and_update_capitalization(
|
||||||
|
&inline_spl_token_v2_0::new_token_program::id(),
|
||||||
|
&new_token_account,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
bank.get_balance(&inline_spl_token_v2_0::new_token_program::id()),
|
||||||
|
123
|
||||||
|
);
|
||||||
|
|
||||||
let original_capitalization = bank.capitalization();
|
let original_capitalization = bank.capitalization();
|
||||||
|
|
||||||
bank.apply_spl_token_v2_self_transfer_fix();
|
bank.apply_spl_token_v2_self_transfer_fix();
|
||||||
|
|
||||||
// Account is now empty, and the account lamports were burnt
|
// New token account is now empty
|
||||||
assert_eq!(bank.get_balance(&inline_spl_token_v2_0::id()), 0);
|
assert_eq!(
|
||||||
|
bank.get_balance(&inline_spl_token_v2_0::new_token_program::id()),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Old token account holds the new token account
|
||||||
|
assert_eq!(
|
||||||
|
bank.get_account(&inline_spl_token_v2_0::id()),
|
||||||
|
Some(new_token_account)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Lamports in the old token account were burnt
|
||||||
assert_eq!(bank.capitalization(), original_capitalization - 100);
|
assert_eq!(bank.capitalization(), original_capitalization - 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
// Partial SPL Token v2.0.x declarations inlined to avoid an external dependency on the spl-token crate
|
// Partial SPL Token v2.0.x declarations inlined to avoid an external dependency on the spl-token crate
|
||||||
solana_sdk::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
solana_sdk::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
|
||||||
|
|
||||||
|
pub(crate) mod new_token_program {
|
||||||
|
solana_sdk::declare_id!("t31zsgDmRntje65uXV3LrnWaJtJJpMd4LyJxq2R2VrU");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
spl_token::state::Account {
|
spl_token::state::Account {
|
||||||
mint: Pubkey,
|
mint: Pubkey,
|
||||||
|
Reference in New Issue
Block a user