Credit-Only Accounts: Cache account balance for thread-safe load/store (#4691)
* Implement CreditOnlyLocks * Update credit-only atomic on account load * Update credit-only atomic after bank.freeze_lock; store credits if all credit-only lock references are dropped * Commit credit-only credits on bank freeze * Update core to CreditAccountLocks * Impl credit-only in System Transfer * Rework CreditAccountLocks, test, and fix bugs * Review comments: Pass CreditAccountLocks by reference; Tighten up insert block * Only store credits on completed slot * Check balance in bench_exchange funding to ensure commit_credits has completed * Add is_debitable info to KeyedAccount meta to pass into programs * Reinstate CreditOnlyLocks check on lock_account * Rework CreditAccountLocks to remove strong_count usage * Add multi-threaded credit-only locks test * Improve RwLocks usage * Review comments: panic if bad things happen; tighter code * Assert lock_accounts race does not happen * Revert panic if bad things happen; not a bad thing
This commit is contained in:
@ -78,6 +78,7 @@ pub type LamportCredit = u64;
|
||||
#[derive(Debug)]
|
||||
pub struct KeyedAccount<'a> {
|
||||
is_signer: bool, // Transaction was signed by this account's key
|
||||
is_debitable: bool,
|
||||
key: &'a Pubkey,
|
||||
pub account: &'a mut Account,
|
||||
}
|
||||
@ -95,10 +96,28 @@ impl<'a> KeyedAccount<'a> {
|
||||
self.key
|
||||
}
|
||||
|
||||
pub fn is_debitable(&self) -> bool {
|
||||
self.is_debitable
|
||||
}
|
||||
|
||||
pub fn new(key: &'a Pubkey, is_signer: bool, account: &'a mut Account) -> KeyedAccount<'a> {
|
||||
KeyedAccount {
|
||||
key,
|
||||
is_signer,
|
||||
is_debitable: true,
|
||||
key,
|
||||
account,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_credit_only(
|
||||
key: &'a Pubkey,
|
||||
is_signer: bool,
|
||||
account: &'a mut Account,
|
||||
) -> KeyedAccount<'a> {
|
||||
KeyedAccount {
|
||||
is_signer,
|
||||
is_debitable: false,
|
||||
key,
|
||||
account,
|
||||
}
|
||||
}
|
||||
@ -108,6 +127,7 @@ impl<'a> From<(&'a Pubkey, &'a mut Account)> for KeyedAccount<'a> {
|
||||
fn from((key, account): (&'a Pubkey, &'a mut Account)) -> Self {
|
||||
KeyedAccount {
|
||||
is_signer: false,
|
||||
is_debitable: true,
|
||||
key,
|
||||
account,
|
||||
}
|
||||
@ -118,6 +138,7 @@ impl<'a> From<&'a mut (Pubkey, Account)> for KeyedAccount<'a> {
|
||||
fn from((key, account): &'a mut (Pubkey, Account)) -> Self {
|
||||
KeyedAccount {
|
||||
is_signer: false,
|
||||
is_debitable: true,
|
||||
key,
|
||||
account,
|
||||
}
|
||||
@ -127,3 +148,15 @@ impl<'a> From<&'a mut (Pubkey, Account)> for KeyedAccount<'a> {
|
||||
pub fn create_keyed_accounts(accounts: &mut [(Pubkey, Account)]) -> Vec<KeyedAccount> {
|
||||
accounts.iter_mut().map(Into::into).collect()
|
||||
}
|
||||
|
||||
pub fn create_keyed_credit_only_accounts(accounts: &mut [(Pubkey, Account)]) -> Vec<KeyedAccount> {
|
||||
accounts
|
||||
.iter_mut()
|
||||
.map(|(key, account)| KeyedAccount {
|
||||
is_signer: false,
|
||||
is_debitable: false,
|
||||
key,
|
||||
account,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ pub fn assign(from_pubkey: &Pubkey, program_id: &Pubkey) -> Instruction {
|
||||
pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*from_pubkey, true),
|
||||
AccountMeta::new(*to_pubkey, false),
|
||||
AccountMeta::new_credit_only(*to_pubkey, false),
|
||||
];
|
||||
Instruction::new(
|
||||
system_program::id(),
|
||||
|
Reference in New Issue
Block a user