runtime: Factor out `DurableNoncePartial` finishing logic and add tests
This commit is contained in:
parent
841c7a0f71
commit
8df2a4bac0
|
@ -359,40 +359,9 @@ impl Accounts {
|
||||||
|
|
||||||
// Update hash_age_kind with fee-subtracted accounts
|
// Update hash_age_kind with fee-subtracted accounts
|
||||||
let hash_age_kind = if let Some(hash_age_kind) = hash_age_kind {
|
let hash_age_kind = if let Some(hash_age_kind) = hash_age_kind {
|
||||||
match hash_age_kind {
|
match hash_age_kind.finish_partial(tx.message(), &accounts) {
|
||||||
HashAgeKind::Extant => Some(HashAgeKind::Extant),
|
Ok(hash_age_kind) => Some(hash_age_kind),
|
||||||
HashAgeKind::DurableNoncePartial(pubkey, account) => {
|
Err(e) => return (Err(e), Some(hash_age_kind)),
|
||||||
let fee_payer = tx
|
|
||||||
.message()
|
|
||||||
.account_keys
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|(i, k)| Self::is_non_loader_key(tx.message(), k, *i))
|
|
||||||
.map(|(i, k)| (*k, accounts[i].clone()));
|
|
||||||
if let Some((fee_pubkey, fee_account)) = fee_payer {
|
|
||||||
if fee_pubkey == pubkey {
|
|
||||||
Some(HashAgeKind::DurableNonceFull(
|
|
||||||
pubkey,
|
|
||||||
fee_account,
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Some(HashAgeKind::DurableNonceFull(
|
|
||||||
pubkey,
|
|
||||||
account,
|
|
||||||
Some(fee_account),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
Err(TransactionError::AccountNotFound),
|
|
||||||
Some(HashAgeKind::DurableNoncePartial(pubkey, account)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HashAgeKind::DurableNonceFull(_, _, _) => {
|
|
||||||
panic!("update: unexpected HashAgeKind variant")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -815,7 +784,7 @@ impl Accounts {
|
||||||
self.accounts_db.add_root(slot)
|
self.accounts_db.add_root(slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_non_loader_key(message: &Message, key: &Pubkey, key_index: usize) -> bool {
|
pub fn is_non_loader_key(message: &Message, key: &Pubkey, key_index: usize) -> bool {
|
||||||
!message.program_ids().contains(&key) || message.is_key_passed_to_program(key_index)
|
!message.program_ids().contains(&key) || message.is_key_passed_to_program(key_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -471,6 +471,36 @@ impl HashAgeKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn finish_partial(&self, message: &Message, accounts: &[Account]) -> Result<Self> {
|
||||||
|
match self {
|
||||||
|
HashAgeKind::Extant => Ok(HashAgeKind::Extant),
|
||||||
|
HashAgeKind::DurableNoncePartial(pubkey, account) => {
|
||||||
|
let fee_payer = message
|
||||||
|
.account_keys
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(i, k)| Accounts::is_non_loader_key(message, k, *i))
|
||||||
|
.and_then(|(i, k)| accounts.get(i).cloned().map(|a| (*k, a)));
|
||||||
|
if let Some((fee_pubkey, fee_account)) = fee_payer {
|
||||||
|
if fee_pubkey == *pubkey {
|
||||||
|
Ok(HashAgeKind::DurableNonceFull(*pubkey, fee_account, None))
|
||||||
|
} else {
|
||||||
|
Ok(HashAgeKind::DurableNonceFull(
|
||||||
|
*pubkey,
|
||||||
|
account.clone(),
|
||||||
|
Some(fee_account),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(TransactionError::AccountNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashAgeKind::DurableNonceFull(_, _, _) => {
|
||||||
|
panic!("update: unexpected HashAgeKind variant")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bank's common fields shared by all supported snapshot versions for deserialization.
|
// Bank's common fields shared by all supported snapshot versions for deserialization.
|
||||||
|
@ -4548,7 +4578,7 @@ pub(crate) mod tests {
|
||||||
poh_config::PohConfig,
|
poh_config::PohConfig,
|
||||||
process_instruction::InvokeContext,
|
process_instruction::InvokeContext,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
signature::{Keypair, Signer},
|
signature::{keypair_from_seed, Keypair, Signer},
|
||||||
system_instruction::{self, SystemError},
|
system_instruction::{self, SystemError},
|
||||||
system_program,
|
system_program,
|
||||||
sysvar::{fees::Fees, rewards::Rewards},
|
sysvar::{fees::Fees, rewards::Rewards},
|
||||||
|
@ -4620,6 +4650,77 @@ pub(crate) mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "update: unexpected HashAgeKind variant")]
|
||||||
|
fn test_hash_age_kind_finish_partial_full_panics() {
|
||||||
|
drop(
|
||||||
|
HashAgeKind::DurableNonceFull(Pubkey::default(), Account::default(), None)
|
||||||
|
.finish_partial(&Message::default(), &[]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_hash_age_kind_finish_partial() {
|
||||||
|
let nonce_authority = keypair_from_seed(&[0; 32]).unwrap();
|
||||||
|
let nonce_address = nonce_authority.pubkey();
|
||||||
|
let from = keypair_from_seed(&[1; 32]).unwrap();
|
||||||
|
let from_address = from.pubkey();
|
||||||
|
let to_address = Pubkey::new_unique();
|
||||||
|
let instructions = vec![
|
||||||
|
system_instruction::advance_nonce_account(&nonce_address, &nonce_authority.pubkey()),
|
||||||
|
system_instruction::transfer(&from_address, &to_address, 42),
|
||||||
|
];
|
||||||
|
let message = Message::new(&instructions, Some(&from_address));
|
||||||
|
|
||||||
|
let from_account = Account::new(1, 0, &Pubkey::default());
|
||||||
|
let nonce_account = Account::new(2, 0, &Pubkey::default());
|
||||||
|
let to_account = Account::new(3, 0, &Pubkey::default());
|
||||||
|
let recent_blockhashes_sysvar_account = Account::new(4, 0, &Pubkey::default());
|
||||||
|
let accounts = [
|
||||||
|
from_account.clone(),
|
||||||
|
nonce_account.clone(),
|
||||||
|
to_account.clone(),
|
||||||
|
recent_blockhashes_sysvar_account.clone(),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
HashAgeKind::Extant.finish_partial(&message, &accounts),
|
||||||
|
Ok(HashAgeKind::Extant)
|
||||||
|
);
|
||||||
|
|
||||||
|
let hash_age_kind = HashAgeKind::DurableNoncePartial(nonce_address, nonce_account.clone());
|
||||||
|
assert_eq!(
|
||||||
|
hash_age_kind.finish_partial(&message, &accounts),
|
||||||
|
Ok(HashAgeKind::DurableNonceFull(
|
||||||
|
nonce_address,
|
||||||
|
nonce_account.clone(),
|
||||||
|
Some(from_account.clone())
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
hash_age_kind.finish_partial(&message, &[]),
|
||||||
|
Err(TransactionError::AccountNotFound),
|
||||||
|
);
|
||||||
|
|
||||||
|
let message = Message::new(&instructions, Some(&nonce_address));
|
||||||
|
let accounts = [
|
||||||
|
nonce_account.clone(),
|
||||||
|
from_account,
|
||||||
|
to_account,
|
||||||
|
recent_blockhashes_sysvar_account,
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
hash_age_kind.finish_partial(&message, &accounts),
|
||||||
|
Ok(HashAgeKind::DurableNonceFull(
|
||||||
|
nonce_address,
|
||||||
|
nonce_account,
|
||||||
|
None
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bank_unix_timestamp_from_genesis() {
|
fn test_bank_unix_timestamp_from_genesis() {
|
||||||
let (genesis_config, _mint_keypair) = create_genesis_config(1);
|
let (genesis_config, _mint_keypair) = create_genesis_config(1);
|
||||||
|
|
Loading…
Reference in New Issue