Add next_keyed_account() to instruction_processor_utils (#6309)
* Cleanup KeyedArguments traversal * Better error message * Fix clippy warning * Rename next_arg to next_keyed_account * Fix clippy warning * Shorter
This commit is contained in:
		@@ -10,6 +10,7 @@ use solana_config_api::get_config_data;
 | 
				
			|||||||
use solana_sdk::{
 | 
					use solana_sdk::{
 | 
				
			||||||
    account::{Account, KeyedAccount},
 | 
					    account::{Account, KeyedAccount},
 | 
				
			||||||
    instruction::InstructionError,
 | 
					    instruction::InstructionError,
 | 
				
			||||||
 | 
					    instruction_processor_utils::next_keyed_account,
 | 
				
			||||||
    pubkey::Pubkey,
 | 
					    pubkey::Pubkey,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -58,6 +59,7 @@ pub fn process_instruction(
 | 
				
			|||||||
    keyed_accounts: &mut [KeyedAccount],
 | 
					    keyed_accounts: &mut [KeyedAccount],
 | 
				
			||||||
    data: &[u8],
 | 
					    data: &[u8],
 | 
				
			||||||
) -> Result<(), InstructionError> {
 | 
					) -> Result<(), InstructionError> {
 | 
				
			||||||
 | 
					    let keyed_accounts_iter = &mut keyed_accounts.iter_mut();
 | 
				
			||||||
    let instruction = deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)?;
 | 
					    let instruction = deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match instruction {
 | 
					    match instruction {
 | 
				
			||||||
@@ -68,10 +70,7 @@ pub fn process_instruction(
 | 
				
			|||||||
            date_pubkey,
 | 
					            date_pubkey,
 | 
				
			||||||
            total_lamports,
 | 
					            total_lamports,
 | 
				
			||||||
        } => {
 | 
					        } => {
 | 
				
			||||||
            let contract_keyed_account = match keyed_accounts {
 | 
					            let contract_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                [ka0] => ka0,
 | 
					 | 
				
			||||||
                _ => return Err(InstructionError::InvalidArgument),
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            let contract_account = &mut contract_keyed_account.account;
 | 
					            let contract_account = &mut contract_keyed_account.account;
 | 
				
			||||||
            let vest_state = VestState {
 | 
					            let vest_state = VestState {
 | 
				
			||||||
                terminator_pubkey,
 | 
					                terminator_pubkey,
 | 
				
			||||||
@@ -84,10 +83,8 @@ pub fn process_instruction(
 | 
				
			|||||||
            vest_state.serialize(&mut contract_account.data)
 | 
					            vest_state.serialize(&mut contract_account.data)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        VestInstruction::SetPayee(payee_pubkey) => {
 | 
					        VestInstruction::SetPayee(payee_pubkey) => {
 | 
				
			||||||
            let (contract_keyed_account, old_payee_keyed_account) = match keyed_accounts {
 | 
					            let contract_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                [ka0, ka1] => (ka0, ka1),
 | 
					            let old_payee_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                _ => return Err(InstructionError::InvalidArgument),
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            let contract_account = &mut contract_keyed_account.account;
 | 
					            let contract_account = &mut contract_keyed_account.account;
 | 
				
			||||||
            let mut vest_state = VestState::deserialize(&contract_account.data)?;
 | 
					            let mut vest_state = VestState::deserialize(&contract_account.data)?;
 | 
				
			||||||
            parse_signed_account(old_payee_keyed_account, &vest_state.payee_pubkey)?;
 | 
					            parse_signed_account(old_payee_keyed_account, &vest_state.payee_pubkey)?;
 | 
				
			||||||
@@ -95,11 +92,9 @@ pub fn process_instruction(
 | 
				
			|||||||
            vest_state.serialize(&mut contract_account.data)
 | 
					            vest_state.serialize(&mut contract_account.data)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        VestInstruction::RedeemTokens => {
 | 
					        VestInstruction::RedeemTokens => {
 | 
				
			||||||
            let (contract_keyed_account, date_keyed_account, payee_keyed_account) =
 | 
					            let contract_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                match keyed_accounts {
 | 
					            let date_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                    [ka0, ka1, ka2] => (ka0, ka1, ka2),
 | 
					            let payee_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                    _ => return Err(InstructionError::InvalidArgument),
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
            let contract_account = &mut contract_keyed_account.account;
 | 
					            let contract_account = &mut contract_keyed_account.account;
 | 
				
			||||||
            let mut vest_state = VestState::deserialize(&contract_account.data)?;
 | 
					            let mut vest_state = VestState::deserialize(&contract_account.data)?;
 | 
				
			||||||
            let current_date = parse_date_account(date_keyed_account, &vest_state.date_pubkey)?;
 | 
					            let current_date = parse_date_account(date_keyed_account, &vest_state.date_pubkey)?;
 | 
				
			||||||
@@ -109,12 +104,9 @@ pub fn process_instruction(
 | 
				
			|||||||
            vest_state.serialize(&mut contract_account.data)
 | 
					            vest_state.serialize(&mut contract_account.data)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        VestInstruction::Terminate => {
 | 
					        VestInstruction::Terminate => {
 | 
				
			||||||
            let (contract_keyed_account, terminator_keyed_account, payee_keyed_account) =
 | 
					            let contract_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                match keyed_accounts {
 | 
					            let terminator_keyed_account = next_keyed_account(keyed_accounts_iter)?;
 | 
				
			||||||
                    [ka0, ka1] => (ka0, ka1, None),
 | 
					            let payee_keyed_account = keyed_accounts_iter.next();
 | 
				
			||||||
                    [ka0, ka1, ka2] => (ka0, ka1, Some(ka2)),
 | 
					 | 
				
			||||||
                    _ => return Err(InstructionError::InvalidArgument),
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
            let contract_account = &mut contract_keyed_account.account;
 | 
					            let contract_account = &mut contract_keyed_account.account;
 | 
				
			||||||
            let mut vest_state = VestState::deserialize(&contract_account.data)?;
 | 
					            let mut vest_state = VestState::deserialize(&contract_account.data)?;
 | 
				
			||||||
            let terminator_account =
 | 
					            let terminator_account =
 | 
				
			||||||
@@ -335,7 +327,7 @@ mod tests {
 | 
				
			|||||||
                .send_message(&[&alice_keypair], message)
 | 
					                .send_message(&[&alice_keypair], message)
 | 
				
			||||||
                .unwrap_err()
 | 
					                .unwrap_err()
 | 
				
			||||||
                .unwrap(),
 | 
					                .unwrap(),
 | 
				
			||||||
            TransactionError::InstructionError(1, InstructionError::InvalidArgument)
 | 
					            TransactionError::InstructionError(1, InstructionError::NotEnoughAccountKeys)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,6 +67,9 @@ pub enum InstructionError {
 | 
				
			|||||||
    /// Rent_epoch account changed, but shouldn't have
 | 
					    /// Rent_epoch account changed, but shouldn't have
 | 
				
			||||||
    RentEpochModified,
 | 
					    RentEpochModified,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// The instruction expected additional account keys
 | 
				
			||||||
 | 
					    NotEnoughAccountKeys,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// CustomError allows on-chain programs to implement program-specific error types and see
 | 
					    /// CustomError allows on-chain programs to implement program-specific error types and see
 | 
				
			||||||
    /// them returned by the Solana runtime. A CustomError may be any type that is represented
 | 
					    /// them returned by the Solana runtime. A CustomError may be any type that is represented
 | 
				
			||||||
    /// as or serialized to a u32 integer.
 | 
					    /// as or serialized to a u32 integer.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,11 @@ where
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Return the next KeyedAccount or a NotEnoughAccountKeys instruction error
 | 
				
			||||||
 | 
					pub fn next_keyed_account<I: Iterator>(iter: &mut I) -> Result<I::Item, InstructionError> {
 | 
				
			||||||
 | 
					    iter.next().ok_or(InstructionError::NotEnoughAccountKeys)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait DecodeError<E> {
 | 
					pub trait DecodeError<E> {
 | 
				
			||||||
    fn decode_custom_error_to_enum(custom: u32) -> Option<E>
 | 
					    fn decode_custom_error_to_enum(custom: u32) -> Option<E>
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user