diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 720d9038edc8e1..f304656abe8c89 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -10,9 +10,9 @@ use solana_rbpf::{memory_region::MemoryRegion, EbpfVm}; use solana_sdk::{ account::KeyedAccount, entrypoint::SUCCESS, - instruction::InstructionError, loader_instruction::LoaderInstruction, program_utils::DecodeError, + program_error::ProgramError, program_utils::{is_executable, limited_deserialize, next_keyed_account}, pubkey::Pubkey, sysvar::rent, @@ -75,7 +75,7 @@ pub fn serialize_parameters( program_id: &Pubkey, keyed_accounts: &[KeyedAccount], data: &[u8], -) -> Result, InstructionError> { +) -> Result, ProgramError> { assert_eq!(32, mem::size_of::()); let mut v: Vec = Vec::new(); @@ -108,7 +108,7 @@ pub fn serialize_parameters( pub fn deserialize_parameters( keyed_accounts: &[KeyedAccount], buffer: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { assert_eq!(32, mem::size_of::()); let mut start = mem::size_of::(); // number of accounts @@ -139,12 +139,12 @@ pub fn process_instruction( program_id: &Pubkey, keyed_accounts: &[KeyedAccount], instruction_data: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { solana_logger::setup_with_default("solana=info"); if keyed_accounts.is_empty() { warn!("No account keys"); - return Err(InstructionError::NotEnoughAccountKeys); + return Err(ProgramError::NotEnoughAccountKeys); } if is_executable(keyed_accounts)? { @@ -166,7 +166,7 @@ pub fn process_instruction( match vm.execute_program(parameter_bytes.as_slice(), &[], &[heap_region]) { Ok(status) => { if status != SUCCESS { - let error: InstructionError = status.into(); + let error: ProgramError = status.into(); warn!("BPF program failed: {:?}", error); return Err(error); } @@ -185,14 +185,14 @@ pub fn process_instruction( let program = next_keyed_account(&mut keyed_accounts_iter)?; if program.signer_key().is_none() { warn!("key[0] did not sign the transaction"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } let offset = offset as usize; let len = bytes.len(); trace!("Write: offset={} length={}", offset, len); if program.data_len()? < offset + len { warn!("Write overflow: {} < {}", program.data_len()?, offset + len); - return Err(InstructionError::AccountDataTooSmall); + return Err(ProgramError::AccountDataTooSmall); } program.try_account_ref_mut()?.data[offset..offset + len].copy_from_slice(&bytes); } @@ -203,12 +203,12 @@ pub fn process_instruction( if program.signer_key().is_none() { warn!("key[0] did not sign the transaction"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } if let Err(e) = check_elf(&program.try_account_ref()?.data) { warn!("Invalid ELF: {}", e); - return Err(InstructionError::InvalidAccountData); + return Err(ProgramError::InvalidAccountData); } rent::verify_rent_exemption(&program, &rent)?; @@ -259,13 +259,13 @@ mod tests { // Case: Empty keyed accounts assert_eq!( - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), process_instruction(&program_id, &vec![], &instruction_data) ); // Case: Not signed assert_eq!( - Err(InstructionError::MissingRequiredSignature), + Err(ProgramError::MissingRequiredSignature), process_instruction(&program_id, &keyed_accounts, &instruction_data) ); @@ -285,7 +285,7 @@ mod tests { let mut keyed_accounts = vec![KeyedAccount::new(&program_key, true, &program_account)]; keyed_accounts[0].account.borrow_mut().data = vec![0; 5]; assert_eq!( - Err(InstructionError::AccountDataTooSmall), + Err(ProgramError::AccountDataTooSmall), process_instruction(&program_id, &keyed_accounts, &instruction_data) ); } @@ -306,7 +306,7 @@ mod tests { // Case: Empty keyed accounts assert_eq!( - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), process_instruction(&program_id, &vec![], &instruction_data) ); @@ -315,7 +315,7 @@ mod tests { // Case: Not signed assert_eq!( - Err(InstructionError::MissingRequiredSignature), + Err(ProgramError::MissingRequiredSignature), process_instruction(&program_id, &keyed_accounts, &instruction_data) ); @@ -339,7 +339,7 @@ mod tests { KeyedAccount::new(&rent_key, false, &rent_account), ]; assert_eq!( - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), process_instruction(&program_id, &keyed_accounts, &instruction_data) ); } @@ -363,7 +363,7 @@ mod tests { // Case: Empty keyed accounts assert_eq!( - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), process_instruction(&program_id, &vec![], &vec![]) ); @@ -376,7 +376,7 @@ mod tests { // Case: Account not executable keyed_accounts[0].account.borrow_mut().executable = false; assert_eq!( - Err(InstructionError::InvalidInstructionData), + Err(ProgramError::InvalidInstructionData), process_instruction(&program_id, &keyed_accounts, &vec![]) ); keyed_accounts[0].account.borrow_mut().executable = true; diff --git a/programs/config/src/config_processor.rs b/programs/config/src/config_processor.rs index e18db222db76b5..633bc46ae3fdaa 100644 --- a/programs/config/src/config_processor.rs +++ b/programs/config/src/config_processor.rs @@ -4,7 +4,7 @@ use crate::ConfigKeys; use bincode::deserialize; use log::*; use solana_sdk::account::KeyedAccount; -use solana_sdk::instruction::InstructionError; +use solana_sdk::program_error::ProgramError; use solana_sdk::program_utils::{limited_deserialize, next_keyed_account}; use solana_sdk::pubkey::Pubkey; @@ -12,7 +12,7 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &[KeyedAccount], data: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let key_list: ConfigKeys = limited_deserialize(data)?; let keyed_accounts_iter = &mut keyed_accounts.iter(); let config_keyed_account = &mut next_keyed_account(keyed_accounts_iter)?; @@ -25,7 +25,7 @@ pub fn process_instruction( config_account.data.len(), err ); - InstructionError::InvalidAccountData + ProgramError::InvalidAccountData })? }; let current_signer_keys: Vec = current_data @@ -40,7 +40,7 @@ pub fn process_instruction( // or when no signers specified in Config data if config_keyed_account.signer_key().is_none() { error!("account[0].signer_key().is_none()"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } } @@ -51,19 +51,19 @@ pub fn process_instruction( let signer_account = keyed_accounts_iter.next(); if signer_account.is_none() { error!("account {:?} is not in account list", signer); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } let signer_key = signer_account.unwrap().signer_key(); if signer_key.is_none() { error!("account {:?} signer_key().is_none()", signer); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } if signer_key.unwrap() != signer { error!( "account[{:?}].signer_key() does not match Config data)", counter + 1 ); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } // If Config account is already initialized, update signatures must match Config data if !current_data.keys.is_empty() @@ -73,11 +73,11 @@ pub fn process_instruction( .is_none() { error!("account {:?} is not in stored signer list", signer); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } } else if config_keyed_account.signer_key().is_none() { error!("account[0].signer_key().is_none()"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } } @@ -88,12 +88,12 @@ pub fn process_instruction( counter, current_signer_keys.len() ); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } if config_keyed_account.data_len()? < data.len() { error!("instruction data too large"); - return Err(InstructionError::InvalidInstructionData); + return Err(ProgramError::InvalidInstructionData); } config_keyed_account.try_account_ref_mut()?.data[..data.len()].copy_from_slice(&data); @@ -215,7 +215,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::InvalidInstructionData) + Err(ProgramError::InvalidInstructionData) ); } @@ -233,7 +233,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); } @@ -290,7 +290,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); } @@ -316,7 +316,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // Config-data pubkey not a signer @@ -327,7 +327,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); } @@ -395,7 +395,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // Attempt update with incorrect signatures @@ -414,7 +414,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); } @@ -477,7 +477,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instruction.data), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); } @@ -491,7 +491,7 @@ mod tests { let keyed_accounts = create_keyed_is_signer_accounts(&accounts); assert_eq!( process_instruction(&id(), &keyed_accounts, &instructions[1].data), - Err(InstructionError::NotEnoughAccountKeys) + Err(ProgramError::NotEnoughAccountKeys) ); } } diff --git a/programs/stake/src/config.rs b/programs/stake/src/config.rs index d79b779b790950..5c949e8436ed50 100644 --- a/programs/stake/src/config.rs +++ b/programs/stake/src/config.rs @@ -6,7 +6,7 @@ use solana_config_program::{create_config_account, get_config_data, ConfigState} use solana_sdk::{ account::{Account, KeyedAccount}, genesis_config::GenesisConfig, - instruction::InstructionError, + program_error::ProgramError, }; // stake config ID @@ -63,11 +63,11 @@ pub fn create_account(lamports: u64, config: &Config) -> Account { create_config_account(vec![], config, lamports) } -pub fn from_keyed_account(account: &KeyedAccount) -> Result { +pub fn from_keyed_account(account: &KeyedAccount) -> Result { if !check_id(account.unsigned_key()) { - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } - Config::from(&*account.try_account_ref()?).ok_or(InstructionError::InvalidArgument) + Config::from(&*account.try_account_ref()?).ok_or(ProgramError::InvalidArgument) } #[cfg(test)] @@ -82,7 +82,7 @@ mod tests { assert_eq!(Config::from(&account.borrow()), Some(Config::default())); assert_eq!( from_keyed_account(&KeyedAccount::new(&Pubkey::default(), false, &mut account)), - Err(InstructionError::InvalidArgument) + Err(ProgramError::InvalidArgument) ); } } diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 13ebde7f05eb00..98d82caa88e942 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -7,7 +7,8 @@ use num_derive::{FromPrimitive, ToPrimitive}; use serde_derive::{Deserialize, Serialize}; use solana_sdk::{ account::{get_signers, KeyedAccount}, - instruction::{AccountMeta, Instruction, InstructionError, WithSigner}, + instruction::{AccountMeta, Instruction, WithSigner}, + program_error::ProgramError, program_utils::{limited_deserialize, next_keyed_account, DecodeError}, pubkey::Pubkey, system_instruction, @@ -371,7 +372,7 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &[KeyedAccount], data: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { solana_logger::setup(); trace!("process_instruction: {:?}", data); @@ -440,7 +441,7 @@ mod tests { RefCell::new(Account::default()) } - fn process_instruction(instruction: &Instruction) -> Result<(), InstructionError> { + fn process_instruction(instruction: &Instruction) -> Result<(), ProgramError> { let accounts: Vec<_> = instruction .accounts .iter() @@ -480,7 +481,7 @@ mod tests { &Authorized::default(), &Lockup::default() )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&authorize( @@ -489,7 +490,7 @@ mod tests { &Pubkey::default(), StakeAuthorize::Staker )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction( @@ -500,7 +501,7 @@ mod tests { &Pubkey::default() )[2] ), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction( @@ -513,7 +514,7 @@ mod tests { "seed" )[1] ), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&delegate_stake( @@ -521,7 +522,7 @@ mod tests { &Pubkey::default(), &Pubkey::default() )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&withdraw( @@ -530,11 +531,11 @@ mod tests { &Pubkey::new_rand(), 100 )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&deactivate_stake(&Pubkey::default(), &Pubkey::default())), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&set_lockup( @@ -542,7 +543,7 @@ mod tests { &Lockup::default(), &Pubkey::default() )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); } @@ -561,7 +562,7 @@ mod tests { )) .unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); // no account for rent @@ -579,7 +580,7 @@ mod tests { )) .unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); // rent fails to deserialize @@ -596,7 +597,7 @@ mod tests { )) .unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); // fails to deserialize stake state @@ -617,7 +618,7 @@ mod tests { )) .unwrap(), ), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); // gets the first check in delegate, wrong number of accounts @@ -631,7 +632,7 @@ mod tests { ),], &serialize(&StakeInstruction::DelegateStake).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); // gets the sub-check for number of args @@ -645,7 +646,7 @@ mod tests { )], &serialize(&StakeInstruction::DelegateStake).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); // gets the check non-deserialize-able account in delegate_stake @@ -675,7 +676,7 @@ mod tests { ], &serialize(&StakeInstruction::DelegateStake).unwrap(), ), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); // Tests 3rd keyed account is of correct type (Clock instead of rewards) in withdraw @@ -701,7 +702,7 @@ mod tests { ], &serialize(&StakeInstruction::Withdraw(42)).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); // Tests correct number of accounts are provided in withdraw @@ -715,7 +716,7 @@ mod tests { )], &serialize(&StakeInstruction::Withdraw(42)).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); // Tests 2nd keyed account is of correct type (Clock instead of rewards) in deactivate @@ -732,7 +733,7 @@ mod tests { ], &serialize(&StakeInstruction::Deactivate).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); // Tests correct number of accounts are provided in deactivate @@ -742,18 +743,18 @@ mod tests { &[], &serialize(&StakeInstruction::Deactivate).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } #[test] fn test_custom_error_decode() { use num_traits::FromPrimitive; - fn pretty_err(err: InstructionError) -> String + fn pretty_err(err: ProgramError) -> String where T: 'static + std::error::Error + DecodeError + FromPrimitive, { - if let InstructionError::CustomError(code) = err { + if let ProgramError::CustomError(code) = err { let specific_error: T = T::decode_custom_error_to_enum(code).unwrap(); format!( "{:?}: {}::{:?} - {}", diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 53304c2bc98662..585d2d2286595e 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -9,7 +9,7 @@ use solana_sdk::{ account::{Account, KeyedAccount}, account_utils::{State, StateMut}, clock::{Clock, Epoch, UnixTimestamp}, - instruction::InstructionError, + program_error::ProgramError, pubkey::Pubkey, rent::Rent, stake_history::{StakeHistory, StakeHistoryEntry}, @@ -122,9 +122,9 @@ impl Meta { &mut self, lockup: &Lockup, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { if !signers.contains(&self.lockup.custodian) { - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } self.lockup = *lockup; Ok(()) @@ -136,7 +136,7 @@ impl Meta { stake_authorize: StakeAuthorize, signers: &HashSet, clock: &Clock, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { // verify that lockup has expired or that the authorization // is *also* signed by the custodian if self.lockup.is_in_force(clock, signers) { @@ -326,11 +326,11 @@ impl Authorized { &self, signers: &HashSet, stake_authorize: StakeAuthorize, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { match stake_authorize { StakeAuthorize::Staker if signers.contains(&self.staker) => Ok(()), StakeAuthorize::Withdrawer if signers.contains(&self.withdrawer) => Ok(()), - _ => Err(InstructionError::MissingRequiredSignature), + _ => Err(ProgramError::MissingRequiredSignature), } } @@ -339,7 +339,7 @@ impl Authorized { signers: &HashSet, new_authorized: &Pubkey, stake_authorize: StakeAuthorize, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { self.check(signers, stake_authorize)?; match stake_authorize { StakeAuthorize::Staker => self.staker = *new_authorized, @@ -497,14 +497,14 @@ pub trait StakeAccount { authorized: &Authorized, lockup: &Lockup, rent: &Rent, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; fn authorize( &self, authority: &Pubkey, stake_authorize: StakeAuthorize, signers: &HashSet, clock: &Clock, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; fn delegate( &self, vote_account: &KeyedAccount, @@ -512,19 +512,15 @@ pub trait StakeAccount { stake_history: &StakeHistory, config: &Config, signers: &HashSet, - ) -> Result<(), InstructionError>; - fn deactivate(&self, clock: &Clock, signers: &HashSet) -> Result<(), InstructionError>; - fn set_lockup( - &self, - lockup: &Lockup, - signers: &HashSet, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; + fn deactivate(&self, clock: &Clock, signers: &HashSet) -> Result<(), ProgramError>; + fn set_lockup(&self, lockup: &Lockup, signers: &HashSet) -> Result<(), ProgramError>; fn split( &self, lamports: u64, split_stake: &KeyedAccount, signers: &HashSet, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; fn withdraw( &self, lamports: u64, @@ -532,7 +528,7 @@ pub trait StakeAccount { clock: &Clock, stake_history: &StakeHistory, signers: &HashSet, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; } impl<'a> StakeAccount for KeyedAccount<'a> { @@ -541,7 +537,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { authorized: &Authorized, lockup: &Lockup, rent: &Rent, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { if let StakeState::Uninitialized = self.state()? { let rent_exempt_reserve = rent.minimum_balance(self.data_len()?); @@ -552,10 +548,10 @@ impl<'a> StakeAccount for KeyedAccount<'a> { lockup: *lockup, })) } else { - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) } } else { - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) } } @@ -568,7 +564,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { stake_authorize: StakeAuthorize, signers: &HashSet, clock: &Clock, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { match self.state()? { StakeState::Stake(mut meta, stake) => { meta.authorize(authority, stake_authorize, signers, clock)?; @@ -578,7 +574,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { meta.authorize(authority, stake_authorize, signers, clock)?; self.set_state(&StakeState::Initialized(meta)) } - _ => Err(InstructionError::InvalidAccountData), + _ => Err(ProgramError::InvalidAccountData), } } fn delegate( @@ -588,7 +584,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { stake_history: &StakeHistory, config: &Config, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { match self.state()? { StakeState::Initialized(meta) => { meta.authorized.check(signers, StakeAuthorize::Staker)?; @@ -612,24 +608,20 @@ impl<'a> StakeAccount for KeyedAccount<'a> { )?; self.set_state(&StakeState::Stake(meta, stake)) } - _ => Err(InstructionError::InvalidAccountData), + _ => Err(ProgramError::InvalidAccountData), } } - fn deactivate(&self, clock: &Clock, signers: &HashSet) -> Result<(), InstructionError> { + fn deactivate(&self, clock: &Clock, signers: &HashSet) -> Result<(), ProgramError> { if let StakeState::Stake(meta, mut stake) = self.state()? { meta.authorized.check(signers, StakeAuthorize::Staker)?; stake.deactivate(clock.epoch)?; self.set_state(&StakeState::Stake(meta, stake)) } else { - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) } } - fn set_lockup( - &self, - lockup: &Lockup, - signers: &HashSet, - ) -> Result<(), InstructionError> { + fn set_lockup(&self, lockup: &Lockup, signers: &HashSet) -> Result<(), ProgramError> { match self.state()? { StakeState::Initialized(mut meta) => { meta.set_lockup(lockup, signers)?; @@ -639,7 +631,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { meta.set_lockup(lockup, signers)?; self.set_state(&StakeState::Stake(meta, stake)) } - _ => Err(InstructionError::InvalidAccountData), + _ => Err(ProgramError::InvalidAccountData), } } @@ -648,11 +640,11 @@ impl<'a> StakeAccount for KeyedAccount<'a> { lamports: u64, split: &KeyedAccount, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { if let StakeState::Uninitialized = split.state()? { // verify enough account lamports if lamports > self.lamports()? { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } match self.state()? { @@ -664,7 +656,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { // verify enough lamports left in previous stake and not full withdrawal || (lamports + meta.rent_exempt_reserve > self.lamports()? && lamports != self.lamports()?) { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } // split the stake, subtract rent_exempt_balance unless // the destination account already has those lamports @@ -686,24 +678,24 @@ impl<'a> StakeAccount for KeyedAccount<'a> { // verify enough lamports left in previous stake || (lamports + meta.rent_exempt_reserve > self.lamports()? && lamports != self.lamports()?) { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } split.set_state(&StakeState::Initialized(meta))?; } StakeState::Uninitialized => { if !signers.contains(&self.unsigned_key()) { - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } } - _ => return Err(InstructionError::InvalidAccountData), + _ => return Err(ProgramError::InvalidAccountData), } split.try_account_ref_mut()?.lamports += lamports; self.try_account_ref_mut()?.lamports -= lamports; Ok(()) } else { - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) } } @@ -714,7 +706,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { clock: &Clock, stake_history: &StakeHistory, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let (lockup, reserve, is_staked) = match self.state()? { StakeState::Stake(meta, stake) => { meta.authorized.check(signers, StakeAuthorize::Withdrawer)?; @@ -737,11 +729,11 @@ impl<'a> StakeAccount for KeyedAccount<'a> { } StakeState::Uninitialized => { if !signers.contains(&self.unsigned_key()) { - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } (Lockup::default(), 0, false) // no lockup, no restrictions } - _ => return Err(InstructionError::InvalidAccountData), + _ => return Err(ProgramError::InvalidAccountData), }; // verify that lockup has expired or that the withdrawal is signed by @@ -754,14 +746,14 @@ impl<'a> StakeAccount for KeyedAccount<'a> { if is_staked // line coverage for branch coverage && lamports + reserve > self.lamports()? { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } if lamports != self.lamports()? // not a full withdrawal && lamports + reserve > self.lamports()? { assert!(!is_staked); - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } self.try_account_ref_mut()?.lamports -= lamports; @@ -776,7 +768,7 @@ pub fn redeem_rewards( vote_account: &mut Account, point_value: f64, stake_history: Option<&StakeHistory>, -) -> Result<(u64, u64), InstructionError> { +) -> Result<(u64, u64), ProgramError> { if let StakeState::Stake(meta, mut stake) = stake_account.state()? { let vote_state = vote_account.state()?; @@ -793,7 +785,7 @@ pub fn redeem_rewards( Err(StakeError::NoCreditsToRedeem.into()) } } else { - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) } } @@ -920,7 +912,7 @@ mod tests { assert_eq!( meta.authorize(&staker, StakeAuthorize::Staker, &signers, &clock), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); signers.insert(staker); assert_eq!( @@ -1029,7 +1021,7 @@ mod tests { &Config::default(), &signers, ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // signed keyed account @@ -1458,7 +1450,7 @@ mod tests { ..Rent::free() }, ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // this one works, as is uninit @@ -1497,7 +1489,7 @@ mod tests { &Lockup::default(), &Rent::free() ), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); } @@ -1523,7 +1515,7 @@ mod tests { let signers = vec![stake_pubkey].into_iter().collect(); assert_eq!( stake_keyed_account.deactivate(&clock, &signers), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); // Staking @@ -1551,7 +1543,7 @@ mod tests { let stake_keyed_account = KeyedAccount::new(&stake_pubkey, false, &stake_account); assert_eq!( stake_keyed_account.deactivate(&clock, &HashSet::default()), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // Deactivate after staking @@ -1581,7 +1573,7 @@ mod tests { let stake_keyed_account = KeyedAccount::new(&stake_pubkey, false, &stake_account); assert_eq!( stake_keyed_account.set_lockup(&Lockup::default(), &HashSet::default(),), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); // initalize the stake @@ -1600,7 +1592,7 @@ mod tests { assert_eq!( stake_keyed_account.set_lockup(&Lockup::default(), &HashSet::default(),), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); assert_eq!( @@ -1645,7 +1637,7 @@ mod tests { }, &HashSet::default(), ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); assert_eq!( stake_keyed_account.set_lockup( @@ -1688,7 +1680,7 @@ mod tests { &StakeHistory::default(), &HashSet::default(), ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // signed keyed account and uninitialized should work @@ -1736,7 +1728,7 @@ mod tests { &StakeHistory::default(), &signers, ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // Stake some lamports (available lamports for withdrawals will reduce to zero) @@ -1789,7 +1781,7 @@ mod tests { &StakeHistory::default(), &signers ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // deactivate the stake before withdrawal @@ -1807,7 +1799,7 @@ mod tests { &StakeHistory::default(), &signers ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // Try to withdraw all lamports @@ -1889,7 +1881,7 @@ mod tests { &stake_history, &signers, ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); } @@ -1918,7 +1910,7 @@ mod tests { &StakeHistory::default(), &signers, ), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); } @@ -2136,7 +2128,7 @@ mod tests { &signers, &Clock::default() ), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); } @@ -2197,7 +2189,7 @@ mod tests { &signers, &Clock::default() ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); let signers0 = vec![stake_pubkey0].into_iter().collect(); @@ -2245,7 +2237,7 @@ mod tests { &StakeHistory::default(), &signers, // old signer ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // Test a successful action by the currently authorized withdrawer @@ -2294,7 +2286,7 @@ mod tests { &split_stake_keyed_account, &HashSet::default() // no signers ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // this should work @@ -2336,7 +2328,7 @@ mod tests { KeyedAccount::new(&split_stake_pubkey, true, &split_stake_account); assert_eq!( stake_keyed_account.split(stake_lamports / 2, &split_stake_keyed_account, &signers), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); } impl Stake { @@ -2435,7 +2427,7 @@ mod tests { &split_stake_keyed_account, &signers ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // doesn't leave enough for initial stake @@ -2445,7 +2437,7 @@ mod tests { &split_stake_keyed_account, &signers ), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // split account already has way enough lamports @@ -2522,7 +2514,7 @@ mod tests { // split more than available fails assert_eq!( stake_keyed_account.split(stake_lamports + 1, &split_stake_keyed_account, &signers), - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) ); // should work @@ -2836,7 +2828,7 @@ mod tests { &Config::default(), &other_signers, ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); let new_signers = vec![new_staker_pubkey].into_iter().collect(); diff --git a/programs/storage/src/storage_contract.rs b/programs/storage/src/storage_contract.rs index 92b08409562916..d4974508e3b9f9 100644 --- a/programs/storage/src/storage_contract.rs +++ b/programs/storage/src/storage_contract.rs @@ -7,7 +7,7 @@ use solana_sdk::{ account_utils::StateMut, clock::Epoch, hash::Hash, - instruction::InstructionError, + program_error::ProgramError, pubkey::Pubkey, signature::Signature, sysvar, @@ -137,7 +137,7 @@ impl<'a> StorageAccount<'a> { &mut self, owner: Pubkey, account_type: StorageAccountType, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let storage_contract = &mut self.account.state()?; if let StorageContract::Uninitialized = storage_contract { *storage_contract = match account_type { @@ -157,7 +157,7 @@ impl<'a> StorageAccount<'a> { }; self.account.set_state(storage_contract) } else { - Err(InstructionError::AccountAlreadyInitialized) + Err(ProgramError::AccountAlreadyInitialized) } } @@ -168,7 +168,7 @@ impl<'a> StorageAccount<'a> { signature: Signature, blockhash: Hash, clock: sysvar::clock::Clock, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let mut storage_contract = &mut self.account.state()?; if let StorageContract::ArchiverStorage { proofs, @@ -194,7 +194,7 @@ impl<'a> StorageAccount<'a> { if segment_index >= current_segment { // attempt to submit proof for unconfirmed segment - return Err(InstructionError::CustomError( + return Err(ProgramError::CustomError( StorageError::InvalidSegment as u32, )); } @@ -207,7 +207,7 @@ impl<'a> StorageAccount<'a> { // TODO check that this blockhash is valid and recent // if !is_valid(&blockhash) { // // proof isn't using a recent blockhash - // return Err(InstructionError::CustomError(InvalidBlockhash as u32)); + // return Err(ProgramError::CustomError(InvalidBlockhash as u32)); // } let proof = Proof { @@ -220,13 +220,13 @@ impl<'a> StorageAccount<'a> { let segment_proofs = proofs.entry(current_segment).or_default(); if segment_proofs.contains(&proof) { // do not accept duplicate proofs - return Err(InstructionError::CustomError( + return Err(ProgramError::CustomError( StorageError::DuplicateProof as u32, )); } if segment_proofs.len() >= MAX_PROOFS_PER_SEGMENT { // do not accept more than MAX_PROOFS_PER_SEGMENT - return Err(InstructionError::CustomError( + return Err(ProgramError::CustomError( StorageError::ProofLimitReached as u32, )); } @@ -234,7 +234,7 @@ impl<'a> StorageAccount<'a> { segment_proofs.push(proof); self.account.set_state(storage_contract) } else { - Err(InstructionError::InvalidArgument) + Err(ProgramError::InvalidArgument) } } @@ -243,7 +243,7 @@ impl<'a> StorageAccount<'a> { hash: Hash, segment: u64, clock: sysvar::clock::Clock, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let mut storage_contract = &mut self.account.state()?; if let StorageContract::ValidatorStorage { segment: state_segment, @@ -255,7 +255,7 @@ impl<'a> StorageAccount<'a> { { debug!("advertise new segment: {} orig: {}", segment, clock.segment); if segment < *state_segment || segment > clock.segment { - return Err(InstructionError::CustomError( + return Err(ProgramError::CustomError( StorageError::InvalidSegment as u32, )); } @@ -270,7 +270,7 @@ impl<'a> StorageAccount<'a> { credits.current_epoch += total_validations; self.account.set_state(storage_contract) } else { - Err(InstructionError::InvalidArgument) + Err(ProgramError::InvalidArgument) } } @@ -281,7 +281,7 @@ impl<'a> StorageAccount<'a> { segment_index: u64, proofs_per_account: Vec>, archiver_accounts: &mut [StorageAccount], - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let mut storage_contract = &mut self.account.state()?; if let StorageContract::ValidatorStorage { segment: state_segment, @@ -290,7 +290,7 @@ impl<'a> StorageAccount<'a> { } = &mut storage_contract { if segment_index > *state_segment { - return Err(InstructionError::CustomError( + return Err(ProgramError::CustomError( StorageError::InvalidSegment as u32, )); } @@ -329,7 +329,7 @@ impl<'a> StorageAccount<'a> { if accounts.len() != proofs_per_account.len() { // don't have all the accounts to validate the proofs_per_account against - return Err(InstructionError::CustomError( + return Err(ProgramError::CustomError( StorageError::InvalidProofMask as u32, )); } @@ -360,7 +360,7 @@ impl<'a> StorageAccount<'a> { self.account.set_state(storage_contract) } else { - Err(InstructionError::InvalidArgument) + Err(ProgramError::InvalidArgument) } } @@ -370,7 +370,7 @@ impl<'a> StorageAccount<'a> { clock: sysvar::clock::Clock, rewards: sysvar::rewards::Rewards, owner: &mut StorageAccount, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let mut storage_contract = &mut self.account.state()?; if let StorageContract::ValidatorStorage { @@ -380,9 +380,7 @@ impl<'a> StorageAccount<'a> { } = &mut storage_contract { if owner.id != *account_owner { - return Err(InstructionError::CustomError( - StorageError::InvalidOwner as u32, - )); + return Err(ProgramError::CustomError(StorageError::InvalidOwner as u32)); } credits.update_epoch(clock.epoch); @@ -397,9 +395,7 @@ impl<'a> StorageAccount<'a> { } = &mut storage_contract { if owner.id != *account_owner { - return Err(InstructionError::CustomError( - StorageError::InvalidOwner as u32, - )); + return Err(ProgramError::CustomError(StorageError::InvalidOwner as u32)); } credits.update_epoch(clock.epoch); let (num_validations, _total_proofs) = count_valid_proofs(&validations); @@ -409,7 +405,7 @@ impl<'a> StorageAccount<'a> { self.account.set_state(storage_contract) } else { - Err(InstructionError::InvalidArgument) + Err(ProgramError::InvalidArgument) } } } @@ -419,10 +415,10 @@ fn check_redeemable( storage_point_value: f64, rewards_pool: &KeyedAccount, owner: &mut StorageAccount, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let rewards = (credits.redeemable as f64 * storage_point_value) as u64; if rewards_pool.lamports()? < rewards { - Err(InstructionError::CustomError( + Err(ProgramError::CustomError( StorageError::RewardPoolDepleted as u32, )) } else { @@ -447,7 +443,7 @@ fn store_validation_result( storage_account: &mut StorageAccount, segment: u64, proof_mask: &[ProofStatus], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let mut storage_contract = storage_account.account.state()?; match &mut storage_contract { StorageContract::ArchiverStorage { @@ -457,11 +453,11 @@ fn store_validation_result( .. } => { if !proofs.contains_key(&segment) { - return Err(InstructionError::InvalidAccountData); + return Err(ProgramError::InvalidAccountData); } if proofs.get(&segment).unwrap().len() != proof_mask.len() { - return Err(InstructionError::InvalidAccountData); + return Err(ProgramError::InvalidAccountData); } let (recorded_validations, _) = count_valid_proofs(&validations); @@ -473,7 +469,7 @@ fn store_validation_result( credits.update_epoch(clock.epoch); credits.current_epoch += total_validations - recorded_validations; } - _ => return Err(InstructionError::InvalidAccountData), + _ => return Err(ProgramError::InvalidAccountData), } storage_account.account.set_state(&storage_contract) } @@ -629,7 +625,7 @@ mod tests { keyed_pool_account.account.borrow_mut().lamports = 0; assert_eq!( check_redeemable(&mut credits, 1.0, &keyed_pool_account, &mut owner), - Err(InstructionError::CustomError( + Err(ProgramError::CustomError( StorageError::RewardPoolDepleted as u32, )) ); diff --git a/programs/storage/src/storage_processor.rs b/programs/storage/src/storage_processor.rs index c0be6124eb26ce..74dfaaa210bce4 100644 --- a/programs/storage/src/storage_processor.rs +++ b/programs/storage/src/storage_processor.rs @@ -4,7 +4,7 @@ use crate::{storage_contract::StorageAccount, storage_instruction::StorageInstruction}; use solana_sdk::{ account::KeyedAccount, - instruction::InstructionError, + program_error::ProgramError, program_utils::limited_deserialize, pubkey::Pubkey, sysvar::{clock::Clock, rewards::Rewards, Sysvar}, @@ -14,7 +14,7 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &[KeyedAccount], data: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { solana_logger::setup(); let (me, rest) = keyed_accounts.split_at(1); @@ -28,7 +28,7 @@ pub fn process_instruction( account_type, } => { if !rest.is_empty() { - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } storage_account.initialize_storage(owner, account_type) } @@ -40,7 +40,7 @@ pub fn process_instruction( } => { if me_unsigned || rest.len() != 1 { // This instruction must be signed by `me` - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } let clock = Clock::from_keyed_account(&rest[0])?; storage_account.submit_mining_proof( @@ -54,14 +54,14 @@ pub fn process_instruction( StorageInstruction::AdvertiseStorageRecentBlockhash { hash, segment } => { if me_unsigned || rest.len() != 1 { // This instruction must be signed by `me` - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } let clock = Clock::from_keyed_account(&rest[0])?; storage_account.advertise_storage_recent_blockhash(hash, segment, clock) } StorageInstruction::ClaimStorageReward => { if rest.len() != 4 { - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } let (clock, rest) = rest.split_at(1); let (rewards, rest) = rest.split_at(1); @@ -76,20 +76,20 @@ pub fn process_instruction( } StorageInstruction::ProofValidation { segment, proofs } => { if rest.is_empty() { - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } let (clock, rest) = rest.split_at(1); if me_unsigned || rest.is_empty() { // This instruction must be signed by `me` and `rest` cannot be empty - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } let me_id = storage_account.id; let clock = Clock::from_keyed_account(&clock[0])?; let mut rest = rest .iter() .map(|keyed_account| Ok((keyed_account, keyed_account.try_account_ref_mut()?))) - .collect::, InstructionError>>()?; + .collect::, ProgramError>>()?; let mut rest = rest .iter_mut() .map(|(keyed_account, account_ref)| { @@ -116,7 +116,7 @@ mod tests { account::{create_keyed_accounts, Account, KeyedAccount}, clock::DEFAULT_SLOTS_PER_SEGMENT, hash::Hash, - instruction::{Instruction, InstructionError}, + instruction::{Instruction, ProgramError}, signature::Signature, sysvar::{ clock::{self, Clock}, @@ -128,7 +128,7 @@ mod tests { fn test_instruction( ix: &Instruction, program_accounts: &[Account], - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let program_accounts: Vec<_> = program_accounts .iter() .map(|account| RefCell::new(account.clone())) @@ -205,7 +205,7 @@ mod tests { assert_eq!( process_instruction(&id(), &keyed_accounts, &ix.data), - Err(InstructionError::InvalidAccountData) + Err(ProgramError::InvalidAccountData) ); } diff --git a/programs/vote/src/vote_instruction.rs b/programs/vote/src/vote_instruction.rs index fe18ba2648a199..c02966d418965f 100644 --- a/programs/vote/src/vote_instruction.rs +++ b/programs/vote/src/vote_instruction.rs @@ -11,7 +11,8 @@ use serde_derive::{Deserialize, Serialize}; use solana_metrics::datapoint_debug; use solana_sdk::{ account::{get_signers, KeyedAccount}, - instruction::{AccountMeta, Instruction, InstructionError, WithSigner}, + instruction::{AccountMeta, Instruction, WithSigner}, + program_error::ProgramError, program_utils::{limited_deserialize, next_keyed_account, DecodeError}, pubkey::Pubkey, system_instruction, @@ -178,7 +179,7 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &[KeyedAccount], data: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { solana_logger::setup_with_default("solana=info"); trace!("process_instruction: {:?}", data); @@ -236,11 +237,11 @@ mod tests { fn test_vote_process_instruction_decode_bail() { assert_eq!( super::process_instruction(&Pubkey::default(), &[], &[],), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } - fn process_instruction(instruction: &Instruction) -> Result<(), InstructionError> { + fn process_instruction(instruction: &Instruction) -> Result<(), ProgramError> { let mut accounts: Vec<_> = instruction .accounts .iter() @@ -281,7 +282,7 @@ mod tests { ); assert_eq!( process_instruction(&instructions[1]), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&vote( @@ -289,7 +290,7 @@ mod tests { &Pubkey::default(), Vote::default(), )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&authorize( @@ -298,7 +299,7 @@ mod tests { &Pubkey::default(), VoteAuthorize::Voter, )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( process_instruction(&update_node( @@ -306,7 +307,7 @@ mod tests { &Pubkey::default(), &Pubkey::default(), )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); assert_eq!( @@ -316,7 +317,7 @@ mod tests { 0, &Pubkey::default() )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); } @@ -331,11 +332,11 @@ mod tests { #[test] fn test_custom_error_decode() { use num_traits::FromPrimitive; - fn pretty_err(err: InstructionError) -> String + fn pretty_err(err: ProgramError) -> String where T: 'static + std::error::Error + DecodeError + FromPrimitive, { - if let InstructionError::CustomError(code) = err { + if let ProgramError::CustomError(code) = err { let specific_error: T = T::decode_custom_error_to_enum(code).unwrap(); format!( "{:?}: {}::{:?} - {}", diff --git a/programs/vote/src/vote_state.rs b/programs/vote/src/vote_state.rs index 323dfc05a563c4..51a5bcdb8eebce 100644 --- a/programs/vote/src/vote_state.rs +++ b/programs/vote/src/vote_state.rs @@ -10,7 +10,7 @@ use solana_sdk::{ account_utils::State, clock::{Epoch, Slot, UnixTimestamp}, hash::Hash, - instruction::InstructionError, + program_error::ProgramError, pubkey::Pubkey, rent::Rent, slot_hashes::SlotHash, @@ -195,14 +195,14 @@ impl VoteState { Self::serialize(self, &mut account.data).ok() } - pub fn deserialize(input: &[u8]) -> Result { - deserialize(input).map_err(|_| InstructionError::InvalidAccountData) + pub fn deserialize(input: &[u8]) -> Result { + deserialize(input).map_err(|_| ProgramError::InvalidAccountData) } - pub fn serialize(&self, output: &mut [u8]) -> Result<(), InstructionError> { + pub fn serialize(&self, output: &mut [u8]) -> Result<(), ProgramError> { serialize_into(output, self).map_err(|err| match *err { - ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall, - _ => InstructionError::GenericError, + ErrorKind::SizeLimit => ProgramError::AccountDataTooSmall, + _ => ProgramError::SerializationFailed, }) } @@ -433,7 +433,7 @@ pub fn authorize( vote_authorize: VoteAuthorize, signers: &HashSet, clock: &Clock, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let mut vote_state: VoteState = vote_account.state()?; // current authorized signer must say "yay" @@ -468,7 +468,7 @@ pub fn update_node( vote_account: &KeyedAccount, node_pubkey: &Pubkey, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let mut vote_state: VoteState = vote_account.state()?; // current authorized voter must say "yay" @@ -482,11 +482,11 @@ pub fn update_node( fn verify_authorized_signer( authorized: &Pubkey, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { if signers.contains(authorized) { Ok(()) } else { - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) } } @@ -496,13 +496,13 @@ pub fn withdraw( lamports: u64, to_account: &KeyedAccount, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let vote_state: VoteState = vote_account.state()?; verify_authorized_signer(&vote_state.authorized_withdrawer, signers)?; if vote_account.lamports()? < lamports { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } vote_account.try_account_ref_mut()?.lamports -= lamports; to_account.try_account_ref_mut()?.lamports += lamports; @@ -516,11 +516,11 @@ pub fn initialize_account( vote_account: &KeyedAccount, vote_init: &VoteInit, clock: &Clock, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let vote_state: VoteState = vote_account.state()?; if vote_state.authorized_voter != Pubkey::default() { - return Err(InstructionError::AccountAlreadyInitialized); + return Err(ProgramError::AccountAlreadyInitialized); } vote_account.set_state(&VoteState::new(vote_init, clock)) } @@ -531,11 +531,11 @@ pub fn process_vote( clock: &Clock, vote: &Vote, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let mut vote_state: VoteState = vote_account.state()?; if vote_state.authorized_voter == Pubkey::default() { - return Err(InstructionError::UninitializedAccount); + return Err(ProgramError::UninitializedAccount); } verify_authorized_signer(&vote_state.authorized_voter, signers)?; @@ -635,7 +635,7 @@ mod tests { }, &Clock::default(), ); - assert_eq!(res, Err(InstructionError::AccountAlreadyInitialized)); + assert_eq!(res, Err(ProgramError::AccountAlreadyInitialized)); } fn create_test_account() -> (Pubkey, RefCell) { @@ -657,7 +657,7 @@ mod tests { vote: &Vote, slot_hashes: &[SlotHash], epoch: Epoch, - ) -> Result { + ) -> Result { let keyed_accounts = &[KeyedAccount::new(&vote_pubkey, true, vote_account)]; let signers = get_signers(keyed_accounts); process_vote( @@ -678,7 +678,7 @@ mod tests { vote_pubkey: &Pubkey, vote_account: &RefCell, vote: &Vote, - ) -> Result { + ) -> Result { simulate_process_vote( vote_pubkey, vote_account, @@ -764,7 +764,7 @@ mod tests { let keyed_accounts = &[KeyedAccount::new(&vote_pubkey, false, &vote_account)]; let signers = get_signers(keyed_accounts); let res = update_node(&keyed_accounts[0], &node_pubkey, &signers); - assert_eq!(res, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(res, Err(ProgramError::MissingRequiredSignature)); let vote_state: VoteState = vote_account.borrow().state().unwrap(); assert!(vote_state.node_pubkey != node_pubkey); @@ -791,7 +791,7 @@ mod tests { &vote, &signers, ); - assert_eq!(res, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(res, Err(ProgramError::MissingRequiredSignature)); // signed let keyed_accounts = &[KeyedAccount::new(&vote_pubkey, true, &vote_account)]; @@ -819,7 +819,7 @@ mod tests { ..Clock::default() }, ); - assert_eq!(res, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(res, Err(ProgramError::MissingRequiredSignature)); let keyed_accounts = &[KeyedAccount::new(&vote_pubkey, true, &vote_account)]; let signers = get_signers(keyed_accounts); @@ -901,7 +901,7 @@ mod tests { &vote, &signers, ); - assert_eq!(res, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(res, Err(ProgramError::MissingRequiredSignature)); // signed by authorized voter let authorized_voter_account = RefCell::new(Account::default()); @@ -931,7 +931,7 @@ mod tests { &vote_account, &Vote::new(vec![1], Hash::default()), ); - assert_eq!(res, Err(InstructionError::UninitializedAccount)); + assert_eq!(res, Err(ProgramError::UninitializedAccount)); } #[test] @@ -1259,7 +1259,7 @@ mod tests { ), &signers, ); - assert_eq!(res, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(res, Err(ProgramError::MissingRequiredSignature)); // insufficient funds let keyed_accounts = &[KeyedAccount::new(&vote_pubkey, true, &vote_account)]; @@ -1274,7 +1274,7 @@ mod tests { ), &signers, ); - assert_eq!(res, Err(InstructionError::InsufficientFunds)); + assert_eq!(res, Err(ProgramError::InsufficientFunds)); // all good let to_account = RefCell::new(Account::default()); diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index 515906d00640c8..a5eed85597bae1 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -7,6 +7,7 @@ use solana_sdk::{ entrypoint_native, instruction::{CompiledInstruction, InstructionError}, message::Message, + program_error::ProgramError, pubkey::Pubkey, system_program, transaction::TransactionError, @@ -123,7 +124,7 @@ pub fn verify_account_changes( Ok(()) } -pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), InstructionError>; +pub type ProcessInstruction = fn(&Pubkey, &[KeyedAccount], &[u8]) -> Result<(), ProgramError>; pub type SymbolCache = RwLock, Symbol>>; @@ -168,7 +169,7 @@ impl MessageProcessor { instruction: &CompiledInstruction, executable_accounts: &[(Pubkey, RefCell)], program_accounts: &[Rc>], - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let program_id = instruction.program_id(&message.account_keys); let mut keyed_accounts = create_keyed_readonly_accounts(executable_accounts); let mut keyed_accounts2: Vec<_> = instruction @@ -279,7 +280,11 @@ impl MessageProcessor { // Sum total lamports before instruction processing let pre_total = Self::sum_account_lamports(program_accounts); - self.process_instruction(message, instruction, executable_accounts, program_accounts)?; + if let Err(err) = + self.process_instruction(message, instruction, executable_accounts, program_accounts) + { + return Err(InstructionError::ProgramError(err)); + } // Verify all accounts have zero outstanding refs Self::verify_account_references(executable_accounts, program_accounts)?; diff --git a/runtime/src/native_loader.rs b/runtime/src/native_loader.rs index 3406281cecee1e..9e31d99eb6899b 100644 --- a/runtime/src/native_loader.rs +++ b/runtime/src/native_loader.rs @@ -7,8 +7,12 @@ use libloading::os::windows::*; use log::*; use num_derive::{FromPrimitive, ToPrimitive}; use solana_sdk::{ +<<<<<<< HEAD account::KeyedAccount, entrypoint_native, instruction::InstructionError, program_utils::DecodeError, pubkey::Pubkey, +======= + account::KeyedAccount, entrypoint_native, program_error::ProgramError, pubkey::Pubkey, +>>>>>>> Rreturn ProgramError from programs }; use std::{env, path::PathBuf, str}; use thiserror::Error; @@ -84,7 +88,7 @@ pub fn invoke_entrypoint( keyed_accounts: &[KeyedAccount], instruction_data: &[u8], symbol_cache: &SymbolCache, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { // dispatch it let (names, params) = keyed_accounts.split_at(1); let name_vec = &names[0].try_account_ref()?.data; diff --git a/runtime/src/system_instruction_processor.rs b/runtime/src/system_instruction_processor.rs index 61bad42969efa5..7043ec58bf467e 100644 --- a/runtime/src/system_instruction_processor.rs +++ b/runtime/src/system_instruction_processor.rs @@ -2,8 +2,8 @@ use log::*; use solana_sdk::{ account::{get_signers, Account, KeyedAccount}, account_utils::StateMut, - instruction::InstructionError, nonce_state::{NonceAccount, NonceState}, + program_error::ProgramError, program_utils::{limited_deserialize, next_keyed_account}, pubkey::Pubkey, system_instruction::{ @@ -33,7 +33,7 @@ impl Address { fn create( address: &Pubkey, with_seed: Option<(&Pubkey, &str, &Pubkey)>, - ) -> Result { + ) -> Result { let base = if let Some((base, seed, program_id)) = with_seed { // re-derive the address, must match the supplied address if *address != create_address_with_seed(base, seed, program_id)? { @@ -56,10 +56,10 @@ fn allocate( address: &Address, space: u64, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { if !address.is_signer(signers) { debug!("Allocate: must carry signature of `to`"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } // if it looks like the `to` account is already in use, bail @@ -90,7 +90,7 @@ fn assign( address: &Address, program_id: &Pubkey, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { // no work to do, just return if account.owner == *program_id { return Ok(()); @@ -98,7 +98,7 @@ fn assign( if !address.is_signer(&signers) { debug!("Assign: account must sign"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } // guard against sysvars being made @@ -117,7 +117,7 @@ fn allocate_and_assign( space: u64, program_id: &Pubkey, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { allocate(to, to_address, space, signers)?; assign(to, to_address, program_id, signers) } @@ -130,24 +130,24 @@ fn create_account( space: u64, program_id: &Pubkey, signers: &HashSet, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { allocate_and_assign(to, to_address, space, program_id, signers)?; transfer(from, to, lamports) } -fn transfer(from: &KeyedAccount, to: &mut Account, lamports: u64) -> Result<(), InstructionError> { +fn transfer(from: &KeyedAccount, to: &mut Account, lamports: u64) -> Result<(), ProgramError> { if lamports == 0 { return Ok(()); } if from.signer_key().is_none() { debug!("Transfer: from must sign"); - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } if !from.data_is_empty()? { debug!("Transfer: `from` must not carry data"); - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } if lamports > from.lamports()? { debug!( @@ -167,7 +167,7 @@ pub fn process_instruction( _program_id: &Pubkey, keyed_accounts: &[KeyedAccount], instruction_data: &[u8], -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let instruction = limited_deserialize(instruction_data)?; trace!("process_instruction: {:?}", instruction); @@ -326,7 +326,7 @@ mod tests { client::SyncClient, genesis_config::create_genesis_config, hash::{hash, Hash}, - instruction::{AccountMeta, Instruction, InstructionError}, + instruction::{AccountMeta, Instruction, ProgramError}, message::Message, nonce_state, signature::{Keypair, KeypairUtil}, @@ -458,7 +458,7 @@ mod tests { &new_program_owner, &HashSet::new(), ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); assert_eq!(from_account.borrow().lamports, 100); assert_eq!(to_account, Account::default()); @@ -645,7 +645,7 @@ mod tests { &new_program_owner, &[owned_key].iter().cloned().collect::>(), ); - assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(result, Err(ProgramError::MissingRequiredSignature)); // Haven't signed to account let mut owned_account = Account::new(0, 0, &Pubkey::default()); @@ -658,7 +658,7 @@ mod tests { &new_program_owner, &[from].iter().cloned().collect::>(), ); - assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(result, Err(ProgramError::MissingRequiredSignature)); // support creation/assignment with zero lamports (ephemeral account) let mut owned_account = Account::new(0, 0, &Pubkey::default()); @@ -761,7 +761,7 @@ mod tests { &Pubkey::new_rand(), &signers ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); } @@ -779,7 +779,7 @@ mod tests { &new_program_owner, &HashSet::new() ), - Err(InstructionError::MissingRequiredSignature) + Err(ProgramError::MissingRequiredSignature) ); // no change, no signature needed assert_eq!( @@ -832,7 +832,7 @@ mod tests { }; let data = serialize(&instruction).unwrap(); let result = process_instruction(&system_program::id(), &[], &data); - assert_eq!(result, Err(InstructionError::NotEnoughAccountKeys)); + assert_eq!(result, Err(ProgramError::NotEnoughAccountKeys)); let from = Pubkey::new_rand(); let from_account = Account::new_ref(100, 0, &system_program::id()); @@ -844,7 +844,7 @@ mod tests { &[KeyedAccount::new(&from, true, &from_account)], &data, ); - assert_eq!(result, Err(InstructionError::NotEnoughAccountKeys)); + assert_eq!(result, Err(ProgramError::NotEnoughAccountKeys)); } #[test] @@ -894,7 +894,7 @@ mod tests { &mut to_account, 50, ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ) } @@ -997,13 +997,13 @@ mod tests { .send_instruction(&mallory_keypair, malicious_instruction) .unwrap_err() .unwrap(), - TransactionError::InstructionError(0, InstructionError::MissingRequiredSignature) + TransactionError::ProgramError(0, ProgramError::MissingRequiredSignature) ); assert_eq!(bank_client.get_balance(&alice_pubkey).unwrap(), 50); assert_eq!(bank_client.get_balance(&mallory_pubkey).unwrap(), 50); } - fn process_nonce_instruction(instruction: &Instruction) -> Result<(), InstructionError> { + fn process_nonce_instruction(instruction: &Instruction) -> Result<(), ProgramError> { let accounts: Vec<_> = instruction .accounts .iter() @@ -1039,7 +1039,7 @@ mod tests { &Pubkey::default(), &Pubkey::default() )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); } @@ -1051,7 +1051,7 @@ mod tests { &[], &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap() ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } @@ -1067,7 +1067,7 @@ mod tests { ),], &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } @@ -1086,7 +1086,7 @@ mod tests { ], &serialize(&SystemInstruction::AdvanceNonceAccount).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); } @@ -1138,7 +1138,7 @@ mod tests { &Pubkey::default(), 1, )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); } @@ -1150,7 +1150,7 @@ mod tests { &[], &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } @@ -1166,7 +1166,7 @@ mod tests { ),], &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } @@ -1186,7 +1186,7 @@ mod tests { ], &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); } @@ -1211,7 +1211,7 @@ mod tests { ], &serialize(&SystemInstruction::WithdrawNonceAccount(42)).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); } @@ -1248,7 +1248,7 @@ mod tests { &[], &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } @@ -1264,7 +1264,7 @@ mod tests { ),], &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(), ), - Err(InstructionError::NotEnoughAccountKeys), + Err(ProgramError::NotEnoughAccountKeys), ); } @@ -1287,7 +1287,7 @@ mod tests { ], &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); } @@ -1311,7 +1311,7 @@ mod tests { ], &serialize(&SystemInstruction::InitializeNonceAccount(Pubkey::default())).unwrap(), ), - Err(InstructionError::InvalidArgument), + Err(ProgramError::InvalidArgument), ); } @@ -1374,7 +1374,7 @@ mod tests { &Pubkey::default(), &Pubkey::default(), )), - Err(InstructionError::InvalidAccountData), + Err(ProgramError::InvalidAccountData), ); } diff --git a/sdk/src/account.rs b/sdk/src/account.rs index f10db11550df7e..f62a662afd0645 100644 --- a/sdk/src/account.rs +++ b/sdk/src/account.rs @@ -1,6 +1,6 @@ use crate::{ hash::Hash, - instruction::InstructionError, + program_error::ProgramError, {clock::Epoch, pubkey::Pubkey}, }; use std::{ @@ -163,43 +163,43 @@ impl<'a> KeyedAccount<'a> { self.is_writable } - pub fn lamports(&self) -> Result { + pub fn lamports(&self) -> Result { Ok(self.try_borrow()?.lamports) } - pub fn data_len(&self) -> Result { + pub fn data_len(&self) -> Result { Ok(self.try_borrow()?.data.len()) } - pub fn data_is_empty(&self) -> Result { + pub fn data_is_empty(&self) -> Result { Ok(self.try_borrow()?.data.is_empty()) } - pub fn owner(&self) -> Result { + pub fn owner(&self) -> Result { Ok(self.try_borrow()?.owner) } - pub fn executable(&self) -> Result { + pub fn executable(&self) -> Result { Ok(self.try_borrow()?.executable) } - pub fn try_account_ref(&'a self) -> Result, InstructionError> { + pub fn try_account_ref(&'a self) -> Result, ProgramError> { self.try_borrow() } - pub fn try_account_ref_mut(&'a self) -> Result, InstructionError> { + pub fn try_account_ref_mut(&'a self) -> Result, ProgramError> { self.try_borrow_mut() } - fn try_borrow(&self) -> Result, InstructionError> { + fn try_borrow(&self) -> Result, ProgramError> { self.account .try_borrow() - .map_err(|_| InstructionError::AccountBorrowFailed) + .map_err(|_| ProgramError::AccountBorrowFailed) } - fn try_borrow_mut(&self) -> Result, InstructionError> { + fn try_borrow_mut(&self) -> Result, ProgramError> { self.account .try_borrow_mut() - .map_err(|_| InstructionError::AccountBorrowFailed) + .map_err(|_| ProgramError::AccountBorrowFailed) } pub fn new(key: &'a Pubkey, is_signer: bool, account: &'a RefCell) -> Self { diff --git a/sdk/src/account_utils.rs b/sdk/src/account_utils.rs index 7b97dde5b53155..813be9b959146d 100644 --- a/sdk/src/account_utils.rs +++ b/sdk/src/account_utils.rs @@ -1,32 +1,32 @@ //! useful extras for Account state use crate::{ account::{Account, KeyedAccount}, - instruction::InstructionError, + program_error::ProgramError, }; use bincode::ErrorKind; /// Convenience trait to covert bincode errors to instruction errors. pub trait StateMut { - fn state(&self) -> Result; - fn set_state(&mut self, state: &T) -> Result<(), InstructionError>; + fn state(&self) -> Result; + fn set_state(&mut self, state: &T) -> Result<(), ProgramError>; } pub trait State { - fn state(&self) -> Result; - fn set_state(&self, state: &T) -> Result<(), InstructionError>; + fn state(&self) -> Result; + fn set_state(&self, state: &T) -> Result<(), ProgramError>; } impl StateMut for Account where T: serde::Serialize + serde::de::DeserializeOwned, { - fn state(&self) -> Result { + fn state(&self) -> Result { self.deserialize_data() - .map_err(|_| InstructionError::InvalidAccountData) + .map_err(|_| ProgramError::InvalidAccountData) } - fn set_state(&mut self, state: &T) -> Result<(), InstructionError> { + fn set_state(&mut self, state: &T) -> Result<(), ProgramError> { self.serialize_data(state).map_err(|err| match *err { - ErrorKind::SizeLimit => InstructionError::AccountDataTooSmall, - _ => InstructionError::GenericError, + ErrorKind::SizeLimit => ProgramError::AccountDataTooSmall, + _ => ProgramError::SerializationFailed, }) } } @@ -35,10 +35,10 @@ impl<'a, T> State for KeyedAccount<'a> where T: serde::Serialize + serde::de::DeserializeOwned, { - fn state(&self) -> Result { + fn state(&self) -> Result { self.try_account_ref()?.state() } - fn set_state(&self, state: &T) -> Result<(), InstructionError> { + fn set_state(&self, state: &T) -> Result<(), ProgramError> { self.try_account_ref_mut()?.set_state(state) } } @@ -53,7 +53,7 @@ mod tests { let state = 42u64; assert!(Account::default().set_state(&state).is_err()); - let res = Account::default().state() as Result; + let res = Account::default().state() as Result; assert!(res.is_err()); let mut account = Account::new(0, std::mem::size_of::(), &Pubkey::default()); diff --git a/sdk/src/entrypoint_native.rs b/sdk/src/entrypoint_native.rs index d559886a3ccc2e..ef2bc5f11b4f6c 100644 --- a/sdk/src/entrypoint_native.rs +++ b/sdk/src/entrypoint_native.rs @@ -1,13 +1,13 @@ //! @brief Solana Native program entry point -use crate::{account::KeyedAccount, instruction::InstructionError, pubkey::Pubkey}; +use crate::{account::KeyedAccount, program_error::ProgramError, pubkey::Pubkey}; // Prototype of a native program entry point pub type Entrypoint = unsafe extern "C" fn( program_id: &Pubkey, keyed_accounts: &[KeyedAccount], instruction_data: &[u8], -) -> Result<(), InstructionError>; +) -> Result<(), ProgramError>; /// Convenience macro to declare a native program /// @@ -23,7 +23,7 @@ pub type Entrypoint = unsafe extern "C" fn( /// # // rather than in the statement position which isn't allowed. /// # mod item_wrapper { /// use solana_sdk::account::KeyedAccount; -/// use solana_sdk::instruction::InstructionError; +/// use solana_sdk::instruction::ProgramError; /// use solana_sdk::pubkey::Pubkey; /// use solana_sdk::declare_program; /// @@ -31,7 +31,7 @@ pub type Entrypoint = unsafe extern "C" fn( /// program_id: &Pubkey, /// keyed_accounts: &[KeyedAccount], /// instruction_data: &[u8], -/// ) -> Result<(), InstructionError> { +/// ) -> Result<(), ProgramError> { /// // Process an instruction /// Ok(()) /// } @@ -54,7 +54,7 @@ pub type Entrypoint = unsafe extern "C" fn( /// # // rather than in the statement position which isn't allowed. /// # mod item_wrapper { /// use solana_sdk::account::KeyedAccount; -/// use solana_sdk::instruction::InstructionError; +/// use solana_sdk::instruction::ProgramError; /// use solana_sdk::pubkey::Pubkey; /// use solana_sdk::declare_program; /// @@ -62,7 +62,7 @@ pub type Entrypoint = unsafe extern "C" fn( /// program_id: &Pubkey, /// keyed_accounts: &[KeyedAccount], /// instruction_data: &[u8], -/// ) -> Result<(), InstructionError> { +/// ) -> Result<(), ProgramError> { /// // Process an instruction /// Ok(()) /// } @@ -94,7 +94,7 @@ macro_rules! declare_program( program_id: &$crate::pubkey::Pubkey, keyed_accounts: &[$crate::account::KeyedAccount], instruction_data: &[u8], - ) -> Result<(), $crate::instruction::InstructionError> { + ) -> Result<(), $crate::program_error::ProgramError> { $entrypoint(program_id, keyed_accounts, instruction_data) } ) diff --git a/sdk/src/instruction.rs b/sdk/src/instruction.rs index 247dc17d498abd..50a390c1eba347 100644 --- a/sdk/src/instruction.rs +++ b/sdk/src/instruction.rs @@ -1,6 +1,8 @@ //! Defines a composable Instruction type and a memory-efficient CompiledInstruction. -use crate::{pubkey::Pubkey, short_vec, system_instruction::SystemError}; +use crate::{ + program_error::ProgramError, pubkey::Pubkey, short_vec, system_instruction::SystemError, +}; use bincode::serialize; use serde::Serialize; @@ -11,33 +13,6 @@ pub enum InstructionError { /// The program instruction returned an error GenericError, - /// The arguments provided to a program instruction where invalid - InvalidArgument, - - /// An instruction's data contents was invalid - InvalidInstructionData, - - /// An account's data contents was invalid - InvalidAccountData, - - /// An account's data was too small - AccountDataTooSmall, - - /// An account's balance was too small to complete the instruction - InsufficientFunds, - - /// The account did not have the expected program id - IncorrectProgramId, - - /// A signature was required but not found - MissingRequiredSignature, - - /// An initialize instruction was sent to an account that has already been initialized. - AccountAlreadyInitialized, - - /// An attempt to operate on an account that hasn't been initialized. - UninitializedAccount, - /// Program's instruction lamport balance does not equal the balance after the instruction UnbalancedInstruction, @@ -66,9 +41,6 @@ pub enum InstructionError { /// Rent_epoch account changed, but shouldn't have RentEpochModified, - /// The instruction expected additional account keys - NotEnoughAccountKeys, - /// A non-system program changed the size of the account data AccountDataSizeChanged, @@ -86,14 +58,10 @@ pub enum InstructionError { /// the runtime cannot determine which changes to pick or how to merge them if both are modified DuplicateAccountOutOfSync, - /// The return value from the program was invalid. Valid errors are either a defined builtin - /// error value or a user-defined error in the lower 32 bits. - InvalidError, - /// Allows on-chain programs to implement program-specific error types and see them returned /// by the Solana runtime. A program-specific error may be any type that is represented as /// or serialized to a u32 integer. - CustomError(u32), + ProgramError(ProgramError), } impl InstructionError { diff --git a/sdk/src/nonce_state.rs b/sdk/src/nonce_state.rs index 5c9a100b3b8c16..e8026c609de104 100644 --- a/sdk/src/nonce_state.rs +++ b/sdk/src/nonce_state.rs @@ -2,7 +2,7 @@ use crate::{ account::{Account, KeyedAccount}, account_utils::State, hash::Hash, - instruction::InstructionError, + program_error::ProgramError, pubkey::Pubkey, system_instruction::NonceError, system_program, @@ -48,7 +48,7 @@ pub trait NonceAccount { &self, recent_blockhashes: &RecentBlockhashes, signers: &HashSet, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; fn withdraw_nonce_account( &self, lamports: u64, @@ -56,18 +56,18 @@ pub trait NonceAccount { recent_blockhashes: &RecentBlockhashes, rent: &Rent, signers: &HashSet, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; fn initialize_nonce_account( &self, nonce_authority: &Pubkey, recent_blockhashes: &RecentBlockhashes, rent: &Rent, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; fn authorize_nonce_account( &self, nonce_authority: &Pubkey, signers: &HashSet, - ) -> Result<(), InstructionError>; + ) -> Result<(), ProgramError>; } impl<'a> NonceAccount for KeyedAccount<'a> { @@ -75,7 +75,7 @@ impl<'a> NonceAccount for KeyedAccount<'a> { &self, recent_blockhashes: &RecentBlockhashes, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { if recent_blockhashes.is_empty() { return Err(NonceError::NoRecentBlockhashes.into()); } @@ -83,7 +83,7 @@ impl<'a> NonceAccount for KeyedAccount<'a> { let meta = match self.state()? { NonceState::Initialized(meta, ref hash) => { if !signers.contains(&meta.nonce_authority) { - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } if *hash == recent_blockhashes[0] { return Err(NonceError::NotExpired.into()); @@ -103,11 +103,11 @@ impl<'a> NonceAccount for KeyedAccount<'a> { recent_blockhashes: &RecentBlockhashes, rent: &Rent, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { let signer = match self.state()? { NonceState::Uninitialized => { if lamports > self.lamports()? { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } *self.unsigned_key() } @@ -119,7 +119,7 @@ impl<'a> NonceAccount for KeyedAccount<'a> { } else { let min_balance = rent.minimum_balance(self.data_len()?); if lamports + min_balance > self.lamports()? { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } } meta.nonce_authority @@ -127,7 +127,7 @@ impl<'a> NonceAccount for KeyedAccount<'a> { }; if !signers.contains(&signer) { - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } self.try_account_ref_mut()?.lamports -= lamports; @@ -141,7 +141,7 @@ impl<'a> NonceAccount for KeyedAccount<'a> { nonce_authority: &Pubkey, recent_blockhashes: &RecentBlockhashes, rent: &Rent, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { if recent_blockhashes.is_empty() { return Err(NonceError::NoRecentBlockhashes.into()); } @@ -150,7 +150,7 @@ impl<'a> NonceAccount for KeyedAccount<'a> { NonceState::Uninitialized => { let min_balance = rent.minimum_balance(self.data_len()?); if self.lamports()? < min_balance { - return Err(InstructionError::InsufficientFunds); + return Err(ProgramError::InsufficientFunds); } Meta::new(nonce_authority) } @@ -164,11 +164,11 @@ impl<'a> NonceAccount for KeyedAccount<'a> { &self, nonce_authority: &Pubkey, signers: &HashSet, - ) -> Result<(), InstructionError> { + ) -> Result<(), ProgramError> { match self.state()? { NonceState::Initialized(meta, nonce) => { if !signers.contains(&meta.nonce_authority) { - return Err(InstructionError::MissingRequiredSignature); + return Err(ProgramError::MissingRequiredSignature); } self.set_state(&NonceState::Initialized(Meta::new(nonce_authority), nonce)) } @@ -309,7 +309,7 @@ mod test { let signers = HashSet::new(); let recent_blockhashes = create_test_recent_blockhashes(0); let result = nonce_account.advance_nonce_account(&recent_blockhashes, &signers); - assert_eq!(result, Err(InstructionError::MissingRequiredSignature),); + assert_eq!(result, Err(ProgramError::MissingRequiredSignature),); }) } @@ -412,7 +412,7 @@ mod test { .initialize_nonce_account(&authorized, &recent_blockhashes, &rent) .unwrap(); let result = nonce_account.advance_nonce_account(&recent_blockhashes, &signers); - assert_eq!(result, Err(InstructionError::MissingRequiredSignature),); + assert_eq!(result, Err(ProgramError::MissingRequiredSignature),); }); }); } @@ -477,7 +477,7 @@ mod test { &rent, &signers, ); - assert_eq!(result, Err(InstructionError::MissingRequiredSignature),); + assert_eq!(result, Err(ProgramError::MissingRequiredSignature),); }) }) } @@ -504,7 +504,7 @@ mod test { &rent, &signers, ); - assert_eq!(result, Err(InstructionError::InsufficientFunds)); + assert_eq!(result, Err(ProgramError::InsufficientFunds)); }) }) } @@ -671,7 +671,7 @@ mod test { &rent, &signers, ); - assert_eq!(result, Err(InstructionError::InsufficientFunds)); + assert_eq!(result, Err(ProgramError::InsufficientFunds)); }) }) } @@ -701,7 +701,7 @@ mod test { &rent, &signers, ); - assert_eq!(result, Err(InstructionError::InsufficientFunds)); + assert_eq!(result, Err(ProgramError::InsufficientFunds)); }) }) } @@ -780,7 +780,7 @@ mod test { let authorized = keyed_account.unsigned_key().clone(); let result = keyed_account.initialize_nonce_account(&authorized, &recent_blockhashes, &rent); - assert_eq!(result, Err(InstructionError::InsufficientFunds)); + assert_eq!(result, Err(ProgramError::InsufficientFunds)); }) } @@ -840,7 +840,7 @@ mod test { .initialize_nonce_account(&authorized, &recent_blockhashes, &rent) .unwrap(); let result = nonce_account.authorize_nonce_account(&Pubkey::default(), &signers); - assert_eq!(result, Err(InstructionError::MissingRequiredSignature)); + assert_eq!(result, Err(ProgramError::MissingRequiredSignature)); }) } } diff --git a/sdk/src/program_error.rs b/sdk/src/program_error.rs index 435f803d98cd73..70560532909ab8 100644 --- a/sdk/src/program_error.rs +++ b/sdk/src/program_error.rs @@ -1,4 +1,4 @@ -use crate::{instruction::InstructionError, program_utils::DecodeError}; +use crate::program_utils::DecodeError; use num_traits::{FromPrimitive, ToPrimitive}; use thiserror::Error; @@ -37,6 +37,10 @@ pub enum ProgramError { NotEnoughAccountKeys, #[error("Failed to borrow a reference to account data, already borrowed")] AccountBorrowFailed, + #[error("Failed to serialize into acount data")] + SerializationFailed, + #[error("Invalid program error")] + Invalid, } pub trait PrintProgramError { @@ -69,6 +73,8 @@ impl PrintProgramError for ProgramError { ProgramError::UninitializedAccount => info!("Error: UninitializedAccount"), ProgramError::NotEnoughAccountKeys => info!("Error: NotEnoughAccountKeys"), ProgramError::AccountBorrowFailed => info!("Error: AccountBorrowFailed"), + ProgramError::SerializationFailed => info!("Error: SerializationFailed"), + ProgramError::Invalid => info!("Error: Invalid program error"), } } } @@ -93,6 +99,8 @@ const ACCOUNT_ALREADY_INITIALIZED: u64 = to_builtin!(9); const UNINITIALIZED_ACCOUNT: u64 = to_builtin!(10); const NOT_ENOUGH_ACCOUNT_KEYS: u64 = to_builtin!(11); const ACCOUNT_BORROW_FAILED: u64 = to_builtin!(12); +const SERIALIATION_FAILED: u64 = to_builtin!(13); +const INVALID: u64 = to_builtin!(14); impl From for u64 { fn from(error: ProgramError) -> Self { @@ -108,6 +116,8 @@ impl From for u64 { ProgramError::UninitializedAccount => UNINITIALIZED_ACCOUNT, ProgramError::NotEnoughAccountKeys => NOT_ENOUGH_ACCOUNT_KEYS, ProgramError::AccountBorrowFailed => ACCOUNT_BORROW_FAILED, + ProgramError::SerializationFailed => SERIALIATION_FAILED, + ProgramError::Invalid => INVALID, ProgramError::CustomError(error) => { if error == 0 { CUSTOM_ZERO @@ -119,31 +129,33 @@ impl From for u64 { } } -impl From for InstructionError +impl From for ProgramError where T: ToPrimitive, { fn from(error: T) -> Self { let error = error.to_u64().unwrap_or(0xbad_c0de); match error { - CUSTOM_ZERO => InstructionError::CustomError(0), - INVALID_ARGUMENT => InstructionError::InvalidArgument, - INVALID_INSTRUCTION_DATA => InstructionError::InvalidInstructionData, - INVALID_ACCOUNT_DATA => InstructionError::InvalidAccountData, - ACCOUNT_DATA_TOO_SMALL => InstructionError::AccountDataTooSmall, - INSUFFICIENT_FUNDS => InstructionError::InsufficientFunds, - INCORRECT_PROGRAM_ID => InstructionError::IncorrectProgramId, - MISSING_REQUIRED_SIGNATURES => InstructionError::MissingRequiredSignature, - ACCOUNT_ALREADY_INITIALIZED => InstructionError::AccountAlreadyInitialized, - UNINITIALIZED_ACCOUNT => InstructionError::UninitializedAccount, - NOT_ENOUGH_ACCOUNT_KEYS => InstructionError::NotEnoughAccountKeys, - ACCOUNT_BORROW_FAILED => InstructionError::AccountBorrowFailed, + CUSTOM_ZERO => ProgramError::CustomError(0), + INVALID_ARGUMENT => ProgramError::InvalidArgument, + INVALID_INSTRUCTION_DATA => ProgramError::InvalidInstructionData, + INVALID_ACCOUNT_DATA => ProgramError::InvalidAccountData, + ACCOUNT_DATA_TOO_SMALL => ProgramError::AccountDataTooSmall, + INSUFFICIENT_FUNDS => ProgramError::InsufficientFunds, + INCORRECT_PROGRAM_ID => ProgramError::IncorrectProgramId, + MISSING_REQUIRED_SIGNATURES => ProgramError::MissingRequiredSignature, + ACCOUNT_ALREADY_INITIALIZED => ProgramError::AccountAlreadyInitialized, + UNINITIALIZED_ACCOUNT => ProgramError::UninitializedAccount, + NOT_ENOUGH_ACCOUNT_KEYS => ProgramError::NotEnoughAccountKeys, + ACCOUNT_BORROW_FAILED => ProgramError::AccountBorrowFailed, + SERIALIATION_FAILED => ProgramError::SerializationFailed, + INVALID => ProgramError::Invalid, _ => { // A valid custom error has no bits set in the upper 32 if error >> BUILTIN_BIT_SHIFT == 0 { - InstructionError::CustomError(error as u32) + ProgramError::CustomError(error as u32) } else { - InstructionError::InvalidError + ProgramError::Invalid } } } diff --git a/sdk/src/program_utils.rs b/sdk/src/program_utils.rs index 4c380343c5dbc4..0a3c107014d40f 100644 --- a/sdk/src/program_utils.rs +++ b/sdk/src/program_utils.rs @@ -1,14 +1,11 @@ -use crate::{ - account::KeyedAccount, account_info::AccountInfo, instruction::InstructionError, - program_error::ProgramError, -}; +use crate::{account::KeyedAccount, account_info::AccountInfo, program_error::ProgramError}; use num_traits::FromPrimitive; /// Return the next KeyedAccount or a NotEnoughAccountKeys error pub fn next_keyed_account<'a, 'b, I: Iterator>>( iter: &mut I, -) -> Result { - iter.next().ok_or(InstructionError::NotEnoughAccountKeys) +) -> Result { + iter.next().ok_or(ProgramError::NotEnoughAccountKeys) } /// Return the next AccountInfo or a NotEnoughAccountKeys error @@ -20,13 +17,13 @@ pub fn next_account_info<'a, 'b, I: Iterator>>( /// Return true if the first keyed_account is executable, used to determine if /// the loader should call a program's 'main' -pub fn is_executable(keyed_accounts: &[KeyedAccount]) -> Result { +pub fn is_executable(keyed_accounts: &[KeyedAccount]) -> Result { Ok(!keyed_accounts.is_empty() && keyed_accounts[0].executable()?) } /// Deserialize with a limit based the maximum amount of data a program can expect to get. /// This function should be used in place of direct deserialization to help prevent OOM errors -pub fn limited_deserialize(instruction_data: &[u8]) -> Result +pub fn limited_deserialize(instruction_data: &[u8]) -> Result where T: serde::de::DeserializeOwned, { @@ -34,7 +31,7 @@ where bincode::config() .limit(limit) .deserialize(instruction_data) - .map_err(|_| InstructionError::InvalidInstructionData) + .map_err(|_| ProgramError::InvalidInstructionData) } /// Allows customer errors to be decoded back to their original enum diff --git a/sdk/src/sysvar/mod.rs b/sdk/src/sysvar/mod.rs index 75a1177c368fc3..b2cadfd02cdfcc 100644 --- a/sdk/src/sysvar/mod.rs +++ b/sdk/src/sysvar/mod.rs @@ -3,7 +3,6 @@ use crate::{ account::{Account, KeyedAccount}, account_info::AccountInfo, - instruction::InstructionError, program_error::ProgramError, pubkey::Pubkey, }; @@ -77,12 +76,11 @@ pub trait Sysvar: fn to_account_info(&self, account_info: &mut AccountInfo) -> Option<()> { bincode::serialize_into(&mut account_info.data.borrow_mut()[..], self).ok() } - fn from_keyed_account(keyed_account: &KeyedAccount) -> Result { + fn from_keyed_account(keyed_account: &KeyedAccount) -> Result { if !Self::check_id(keyed_account.unsigned_key()) { - return Err(InstructionError::InvalidArgument); + return Err(ProgramError::InvalidArgument); } - Self::from_account(&*keyed_account.try_account_ref()?) - .ok_or(InstructionError::InvalidArgument) + Self::from_account(&*keyed_account.try_account_ref()?).ok_or(ProgramError::InvalidArgument) } fn create_account(&self, lamports: u64) -> Account { let data_len = Self::size_of().max(bincode::serialized_size(self).unwrap() as usize); diff --git a/sdk/src/sysvar/rent.rs b/sdk/src/sysvar/rent.rs index ff005762d9402b..4f722b06e8a592 100644 --- a/sdk/src/sysvar/rent.rs +++ b/sdk/src/sysvar/rent.rs @@ -4,7 +4,7 @@ pub use crate::rent::Rent; use crate::{ account::{Account, KeyedAccount}, - instruction::InstructionError, + program_error::ProgramError, sysvar::Sysvar, }; @@ -19,10 +19,10 @@ pub fn create_account(lamports: u64, rent: &Rent) -> Account { pub fn verify_rent_exemption( keyed_account: &KeyedAccount, rent_sysvar_account: &KeyedAccount, -) -> Result<(), InstructionError> { +) -> Result<(), ProgramError> { let rent = Rent::from_keyed_account(rent_sysvar_account)?; if !rent.is_exempt(keyed_account.lamports()?, keyed_account.data_len()?) { - Err(InstructionError::InsufficientFunds) + Err(ProgramError::InsufficientFunds) } else { Ok(()) }