Don't repack if not needed (#355)

This commit is contained in:
Jack May 2020-08-28 12:03:10 -07:00 committed by GitHub
parent 64a9e151e0
commit 815cca3cb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 88 deletions

View File

@ -69,19 +69,13 @@ impl State {
pub fn token_account_deserialize(
info: &AccountInfo,
) -> Result<spl_token::state::Account, Error> {
spl_token::state::Account::unpack_from_slice(&info.data.borrow_mut())
spl_token::state::Account::unpack(&info.data.borrow_mut())
.map_err(|_| Error::ExpectedAccount)
// Ok(*spl_token::state::unpack(&mut info.data.borrow_mut())
// .map_err(|_| Error::ExpectedAccount)?)
}
/// Deserializes a spl_token `Mint`.
pub fn mint_deserialize(info: &AccountInfo) -> Result<spl_token::state::Mint, Error> {
spl_token::state::Mint::unpack_from_slice(&info.data.borrow_mut())
.map_err(|_| Error::ExpectedAccount)
// Ok(*spl_token::state::unpack(&mut info.data.borrow_mut())
// .map_err(|_| Error::ExpectedToken)?)
spl_token::state::Mint::unpack(&info.data.borrow_mut()).map_err(|_| Error::ExpectedAccount)
}
/// Calculates the authority id by generating a program address.
@ -523,7 +517,7 @@ mod tests {
account::Account, account_info::create_is_signer_account_infos, instruction::Instruction,
};
use spl_token::{
instruction::{initialize_account, initialize_mint},
instruction::{initialize_account, initialize_mint, mint_to},
processor::Processor as SplProcessor,
state::{Account as SplAccount, Mint as SplMint},
};
@ -575,24 +569,26 @@ mod tests {
.unwrap();
let mut authority_account = Account::default();
do_process_instruction(
initialize_mint(
initialize_mint(&program_id, &token_key, authority_key, None, 2).unwrap(),
vec![&mut token_account, &mut authority_account],
)
.unwrap();
do_process_instruction(
mint_to(
&program_id,
&token_key,
Some(&account_key),
Some(&authority_key),
&account_key,
authority_key,
&[],
amount,
2,
)
.unwrap(),
if amount == 0 {
vec![&mut token_account, &mut authority_account]
} else {
vec![
&mut token_account,
&mut account_account,
&mut authority_account,
]
},
vec![
&mut token_account,
&mut account_account,
&mut authority_account,
],
)
.unwrap();

View File

@ -21,6 +21,28 @@ pub trait Pack: Sealed {
#[doc(hidden)]
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError>;
/// Unpack from slice and check if initialized
fn unpack(input: &[u8]) -> Result<Self, ProgramError>
where
Self: IsInitialized,
{
let value = Self::unpack_unchecked(input)?;
if value.is_initialized() {
Ok(value)
} else {
Err(TokenError::UninitializedState.into())
}
}
/// Unpack from slice without checking if initialized
fn unpack_unchecked(input: &[u8]) -> Result<Self, ProgramError> {
if input.len() < Self::LEN {
println!("ilen {:?} tlen {:?}", input.len(), Self::LEN);
return Err(ProgramError::InvalidAccountData);
}
Ok(Self::unpack_from_slice(input)?)
}
/// Borrow `Self` from `input` for the duration of the call to `f`, but first check that `Self`
/// is initialized
#[inline(never)]
@ -29,9 +51,9 @@ pub trait Pack: Sealed {
F: FnMut(&mut Self) -> Result<U, ProgramError>,
Self: IsInitialized,
{
let mut t = unpack(input)?;
let mut t = Self::unpack(input)?;
let u = f(&mut t)?;
pack(t, input)?;
Self::pack(t, input)?;
Ok(u)
}
@ -42,35 +64,19 @@ pub trait Pack: Sealed {
where
F: FnMut(&mut Self) -> Result<U, ProgramError>,
{
let mut t = unpack_unchecked(input)?;
let mut t = Self::unpack_unchecked(input)?;
let u = f(&mut t)?;
pack(t, input)?;
Self::pack(t, input)?;
Ok(u)
}
}
fn pack<T: Pack>(src: T, dst: &mut [u8]) -> Result<(), ProgramError> {
if dst.len() < T::LEN {
println!("dlen {:?} tlen {:?}", dst.len(), T::LEN);
return Err(ProgramError::InvalidAccountData);
}
src.pack_into_slice(dst);
Ok(())
}
fn unpack<T: Pack + IsInitialized>(input: &[u8]) -> Result<T, ProgramError> {
let value: T = unpack_unchecked(input)?;
if value.is_initialized() {
Ok(value)
} else {
Err(TokenError::UninitializedState.into())
/// Pack into slice
fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> {
if dst.len() < Self::LEN {
println!("dlen {:?} tlen {:?}", dst.len(), Self::LEN);
return Err(ProgramError::InvalidAccountData);
}
src.pack_into_slice(dst);
Ok(())
}
}
fn unpack_unchecked<T: Pack>(input: &[u8]) -> Result<T, ProgramError> {
if input.len() < T::LEN {
println!("ilen {:?} tlen {:?}", input.len(), T::LEN);
return Err(ProgramError::InvalidAccountData);
}
Ok(T::unpack_from_slice(input)?)
}

View File

@ -75,8 +75,7 @@ impl Processor {
}
if *mint_info.key != crate::native_mint::id() {
let mut mint_info_data = mint_info.data.borrow_mut();
Mint::unpack_mut(&mut mint_info_data, &mut |_| Ok(()))
let _ = Mint::unpack(&mint_info.data.borrow_mut())
.map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
}
@ -177,18 +176,15 @@ impl Processor {
return Err(TokenError::AccountFrozen.into());
}
if let Some((mint_account_info, expected_decimals)) = expected_mint_info {
if source_account.mint != *mint_account_info.key {
if let Some((mint_info, expected_decimals)) = expected_mint_info {
if source_account.mint != *mint_info.key {
return Err(TokenError::MintMismatch.into());
}
let mut mint_info_data = mint_account_info.data.borrow_mut();
Mint::unpack_mut(&mut mint_info_data, &mut |mint: &mut Mint| {
if expected_decimals != mint.decimals {
return Err(TokenError::MintDecimalsMismatch.into());
}
Ok(())
})?;
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
if expected_decimals != mint.decimals {
return Err(TokenError::MintDecimalsMismatch.into());
}
}
match source_account.delegate {
@ -268,18 +264,15 @@ impl Processor {
return Err(TokenError::AccountFrozen.into());
}
if let Some((mint_account_info, expected_decimals)) = expected_mint_info {
if source_account.mint != *mint_account_info.key {
if let Some((mint_info, expected_decimals)) = expected_mint_info {
if source_account.mint != *mint_info.key {
return Err(TokenError::MintMismatch.into());
}
let mut mint_info_data = mint_account_info.data.borrow_mut();
Mint::unpack_mut(&mut mint_info_data, &mut |mint: &mut Mint| {
if expected_decimals != mint.decimals {
return Err(TokenError::MintDecimalsMismatch.into());
}
Ok(())
})?;
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
if expected_decimals != mint.decimals {
return Err(TokenError::MintDecimalsMismatch.into());
}
}
Self::validate_owner(
@ -442,8 +435,8 @@ impl Processor {
return Err(TokenError::MintMismatch.into());
}
let mut mint_info_data = mint_info.data.borrow_mut();
Mint::unpack_mut(&mut mint_info_data, &mut |mint: &mut Mint| {
let mut mint_data = mint_info.data.borrow_mut();
Mint::unpack_mut(&mut mint_data, &mut |mint: &mut Mint| {
if let Some(expected_decimals) = expected_decimals {
if expected_decimals != mint.decimals {
return Err(TokenError::MintDecimalsMismatch.into());
@ -612,19 +605,16 @@ impl Processor {
return Err(TokenError::InvalidState.into());
}
let mut mint_data = mint_info.data.borrow_mut();
Mint::unpack_mut(
&mut mint_data,
&mut |mint: &mut Mint| match mint.freeze_authority {
COption::Some(authority) => Self::validate_owner(
program_id,
&authority,
authority_info,
account_info_iter.as_slice(),
),
COption::None => Err(TokenError::MintCannotFreeze.into()),
},
)?;
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
match mint.freeze_authority {
COption::Some(authority) => Self::validate_owner(
program_id,
&authority,
authority_info,
account_info_iter.as_slice(),
),
COption::None => Err(TokenError::MintCannotFreeze.into()),
}?;
source_account.state = if freeze {
AccountState::Frozen
@ -1497,7 +1487,7 @@ mod tests {
vec![&mut mint_account, &mut account_account, &mut owner_account],
)
.unwrap();
Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |_| Ok(())).unwrap();
let _ = Mint::unpack(&mut mint_account.data).unwrap();
Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| {
assert_eq!(account.amount, 42);
Ok(())
@ -1522,7 +1512,7 @@ mod tests {
)
);
Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |_| Ok(())).unwrap();
let _ = Mint::unpack(&mut mint_account.data).unwrap();
Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| {
assert_eq!(account.amount, 42);
Ok(())
@ -1544,7 +1534,7 @@ mod tests {
vec![&mut mint_account, &mut account_account, &mut owner_account],
)
.unwrap();
Mint::unpack_unchecked_mut(&mut mint_account.data, &mut |_| Ok(())).unwrap();
let _ = Mint::unpack(&mut mint_account.data).unwrap();
Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| {
assert_eq!(account.amount, 84);
Ok(())