Don't repack if not needed (#355)
This commit is contained in:
parent
64a9e151e0
commit
815cca3cb8
|
@ -69,19 +69,13 @@ impl State {
|
||||||
pub fn token_account_deserialize(
|
pub fn token_account_deserialize(
|
||||||
info: &AccountInfo,
|
info: &AccountInfo,
|
||||||
) -> Result<spl_token::state::Account, Error> {
|
) -> 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)
|
.map_err(|_| Error::ExpectedAccount)
|
||||||
// Ok(*spl_token::state::unpack(&mut info.data.borrow_mut())
|
|
||||||
// .map_err(|_| Error::ExpectedAccount)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes a spl_token `Mint`.
|
/// Deserializes a spl_token `Mint`.
|
||||||
pub fn mint_deserialize(info: &AccountInfo) -> Result<spl_token::state::Mint, Error> {
|
pub fn mint_deserialize(info: &AccountInfo) -> Result<spl_token::state::Mint, Error> {
|
||||||
spl_token::state::Mint::unpack_from_slice(&info.data.borrow_mut())
|
spl_token::state::Mint::unpack(&info.data.borrow_mut()).map_err(|_| Error::ExpectedAccount)
|
||||||
.map_err(|_| Error::ExpectedAccount)
|
|
||||||
|
|
||||||
// Ok(*spl_token::state::unpack(&mut info.data.borrow_mut())
|
|
||||||
// .map_err(|_| Error::ExpectedToken)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the authority id by generating a program address.
|
/// 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,
|
account::Account, account_info::create_is_signer_account_infos, instruction::Instruction,
|
||||||
};
|
};
|
||||||
use spl_token::{
|
use spl_token::{
|
||||||
instruction::{initialize_account, initialize_mint},
|
instruction::{initialize_account, initialize_mint, mint_to},
|
||||||
processor::Processor as SplProcessor,
|
processor::Processor as SplProcessor,
|
||||||
state::{Account as SplAccount, Mint as SplMint},
|
state::{Account as SplAccount, Mint as SplMint},
|
||||||
};
|
};
|
||||||
|
@ -575,24 +569,26 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut authority_account = Account::default();
|
let mut authority_account = Account::default();
|
||||||
do_process_instruction(
|
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,
|
&program_id,
|
||||||
&token_key,
|
&token_key,
|
||||||
Some(&account_key),
|
&account_key,
|
||||||
Some(&authority_key),
|
authority_key,
|
||||||
|
&[],
|
||||||
amount,
|
amount,
|
||||||
2,
|
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
if amount == 0 {
|
vec![
|
||||||
vec![&mut token_account, &mut authority_account]
|
&mut token_account,
|
||||||
} else {
|
&mut account_account,
|
||||||
vec![
|
&mut authority_account,
|
||||||
&mut token_account,
|
],
|
||||||
&mut account_account,
|
|
||||||
&mut authority_account,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,28 @@ pub trait Pack: Sealed {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError>;
|
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`
|
/// Borrow `Self` from `input` for the duration of the call to `f`, but first check that `Self`
|
||||||
/// is initialized
|
/// is initialized
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
|
@ -29,9 +51,9 @@ pub trait Pack: Sealed {
|
||||||
F: FnMut(&mut Self) -> Result<U, ProgramError>,
|
F: FnMut(&mut Self) -> Result<U, ProgramError>,
|
||||||
Self: IsInitialized,
|
Self: IsInitialized,
|
||||||
{
|
{
|
||||||
let mut t = unpack(input)?;
|
let mut t = Self::unpack(input)?;
|
||||||
let u = f(&mut t)?;
|
let u = f(&mut t)?;
|
||||||
pack(t, input)?;
|
Self::pack(t, input)?;
|
||||||
Ok(u)
|
Ok(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,35 +64,19 @@ pub trait Pack: Sealed {
|
||||||
where
|
where
|
||||||
F: FnMut(&mut Self) -> Result<U, ProgramError>,
|
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)?;
|
let u = f(&mut t)?;
|
||||||
pack(t, input)?;
|
Self::pack(t, input)?;
|
||||||
Ok(u)
|
Ok(u)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn pack<T: Pack>(src: T, dst: &mut [u8]) -> Result<(), ProgramError> {
|
/// Pack into slice
|
||||||
if dst.len() < T::LEN {
|
fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> {
|
||||||
println!("dlen {:?} tlen {:?}", dst.len(), T::LEN);
|
if dst.len() < Self::LEN {
|
||||||
return Err(ProgramError::InvalidAccountData);
|
println!("dlen {:?} tlen {:?}", dst.len(), Self::LEN);
|
||||||
}
|
return Err(ProgramError::InvalidAccountData);
|
||||||
src.pack_into_slice(dst);
|
}
|
||||||
Ok(())
|
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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)?)
|
|
||||||
}
|
|
||||||
|
|
|
@ -75,8 +75,7 @@ impl Processor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if *mint_info.key != crate::native_mint::id() {
|
if *mint_info.key != crate::native_mint::id() {
|
||||||
let mut mint_info_data = mint_info.data.borrow_mut();
|
let _ = Mint::unpack(&mint_info.data.borrow_mut())
|
||||||
Mint::unpack_mut(&mut mint_info_data, &mut |_| Ok(()))
|
|
||||||
.map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
|
.map_err(|_| Into::<ProgramError>::into(TokenError::InvalidMint))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,18 +176,15 @@ impl Processor {
|
||||||
return Err(TokenError::AccountFrozen.into());
|
return Err(TokenError::AccountFrozen.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((mint_account_info, expected_decimals)) = expected_mint_info {
|
if let Some((mint_info, expected_decimals)) = expected_mint_info {
|
||||||
if source_account.mint != *mint_account_info.key {
|
if source_account.mint != *mint_info.key {
|
||||||
return Err(TokenError::MintMismatch.into());
|
return Err(TokenError::MintMismatch.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mint_info_data = mint_account_info.data.borrow_mut();
|
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
|
||||||
Mint::unpack_mut(&mut mint_info_data, &mut |mint: &mut Mint| {
|
if expected_decimals != mint.decimals {
|
||||||
if expected_decimals != mint.decimals {
|
return Err(TokenError::MintDecimalsMismatch.into());
|
||||||
return Err(TokenError::MintDecimalsMismatch.into());
|
}
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match source_account.delegate {
|
match source_account.delegate {
|
||||||
|
@ -268,18 +264,15 @@ impl Processor {
|
||||||
return Err(TokenError::AccountFrozen.into());
|
return Err(TokenError::AccountFrozen.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((mint_account_info, expected_decimals)) = expected_mint_info {
|
if let Some((mint_info, expected_decimals)) = expected_mint_info {
|
||||||
if source_account.mint != *mint_account_info.key {
|
if source_account.mint != *mint_info.key {
|
||||||
return Err(TokenError::MintMismatch.into());
|
return Err(TokenError::MintMismatch.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mint_info_data = mint_account_info.data.borrow_mut();
|
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
|
||||||
Mint::unpack_mut(&mut mint_info_data, &mut |mint: &mut Mint| {
|
if expected_decimals != mint.decimals {
|
||||||
if expected_decimals != mint.decimals {
|
return Err(TokenError::MintDecimalsMismatch.into());
|
||||||
return Err(TokenError::MintDecimalsMismatch.into());
|
}
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::validate_owner(
|
Self::validate_owner(
|
||||||
|
@ -442,8 +435,8 @@ impl Processor {
|
||||||
return Err(TokenError::MintMismatch.into());
|
return Err(TokenError::MintMismatch.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mint_info_data = mint_info.data.borrow_mut();
|
let mut mint_data = mint_info.data.borrow_mut();
|
||||||
Mint::unpack_mut(&mut mint_info_data, &mut |mint: &mut Mint| {
|
Mint::unpack_mut(&mut mint_data, &mut |mint: &mut Mint| {
|
||||||
if let Some(expected_decimals) = expected_decimals {
|
if let Some(expected_decimals) = expected_decimals {
|
||||||
if expected_decimals != mint.decimals {
|
if expected_decimals != mint.decimals {
|
||||||
return Err(TokenError::MintDecimalsMismatch.into());
|
return Err(TokenError::MintDecimalsMismatch.into());
|
||||||
|
@ -612,19 +605,16 @@ impl Processor {
|
||||||
return Err(TokenError::InvalidState.into());
|
return Err(TokenError::InvalidState.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mint_data = mint_info.data.borrow_mut();
|
let mint = Mint::unpack(&mint_info.data.borrow_mut())?;
|
||||||
Mint::unpack_mut(
|
match mint.freeze_authority {
|
||||||
&mut mint_data,
|
COption::Some(authority) => Self::validate_owner(
|
||||||
&mut |mint: &mut Mint| match mint.freeze_authority {
|
program_id,
|
||||||
COption::Some(authority) => Self::validate_owner(
|
&authority,
|
||||||
program_id,
|
authority_info,
|
||||||
&authority,
|
account_info_iter.as_slice(),
|
||||||
authority_info,
|
),
|
||||||
account_info_iter.as_slice(),
|
COption::None => Err(TokenError::MintCannotFreeze.into()),
|
||||||
),
|
}?;
|
||||||
COption::None => Err(TokenError::MintCannotFreeze.into()),
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
source_account.state = if freeze {
|
source_account.state = if freeze {
|
||||||
AccountState::Frozen
|
AccountState::Frozen
|
||||||
|
@ -1497,7 +1487,7 @@ mod tests {
|
||||||
vec![&mut mint_account, &mut account_account, &mut owner_account],
|
vec![&mut mint_account, &mut account_account, &mut owner_account],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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| {
|
Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| {
|
||||||
assert_eq!(account.amount, 42);
|
assert_eq!(account.amount, 42);
|
||||||
Ok(())
|
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| {
|
Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| {
|
||||||
assert_eq!(account.amount, 42);
|
assert_eq!(account.amount, 42);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1544,7 +1534,7 @@ mod tests {
|
||||||
vec![&mut mint_account, &mut account_account, &mut owner_account],
|
vec![&mut mint_account, &mut account_account, &mut owner_account],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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| {
|
Account::unpack_unchecked_mut(&mut account_account.data, &mut |account: &mut Account| {
|
||||||
assert_eq!(account.amount, 84);
|
assert_eq!(account.amount, 84);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in New Issue