diff --git a/runtime/src/runtime.rs b/runtime/src/runtime.rs index 06f2ff49ea..db2962e45d 100644 --- a/runtime/src/runtime.rs +++ b/runtime/src/runtime.rs @@ -1,4 +1,5 @@ use crate::native_loader; +use crate::system_program::SystemError; use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount}; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; @@ -26,7 +27,9 @@ pub enum InstructionError { impl InstructionError { pub fn new_result_with_negative_lamports() -> Self { - InstructionError::ProgramError(ProgramError::ResultWithNegativeLamports) + let serialized_error = + bincode::serialize(&SystemError::ResultWithNegativeLamports).unwrap(); + InstructionError::ProgramError(ProgramError::CustomError(serialized_error)) } } diff --git a/runtime/src/system_program.rs b/runtime/src/system_program.rs index eced0db5bb..8702c5c01d 100644 --- a/runtime/src/system_program.rs +++ b/runtime/src/system_program.rs @@ -11,7 +11,7 @@ const FROM_ACCOUNT_INDEX: usize = 0; const TO_ACCOUNT_INDEX: usize = 1; #[derive(Serialize, Debug, Clone, PartialEq)] -enum SystemError { +pub enum SystemError { AccountAlreadyInUse, ResultWithNegativeLamports, SourceNotSystemAccount, @@ -55,20 +55,17 @@ fn create_system_account( fn assign_account_to_program( keyed_accounts: &mut [KeyedAccount], program_id: &Pubkey, -) -> Result<(), ProgramError> { - if !system_program::check_id(&keyed_accounts[FROM_ACCOUNT_INDEX].account.owner) { - Err(ProgramError::AssignOfUnownedAccount)?; - } +) -> Result<(), SystemError> { keyed_accounts[FROM_ACCOUNT_INDEX].account.owner = *program_id; Ok(()) } -fn move_lamports(keyed_accounts: &mut [KeyedAccount], lamports: u64) -> Result<(), ProgramError> { +fn move_lamports(keyed_accounts: &mut [KeyedAccount], lamports: u64) -> Result<(), SystemError> { if lamports > keyed_accounts[FROM_ACCOUNT_INDEX].account.lamports { info!( "Move: insufficient lamports ({}, need {})", keyed_accounts[FROM_ACCOUNT_INDEX].account.lamports, lamports ); - Err(ProgramError::ResultWithNegativeLamports)?; + Err(SystemError::ResultWithNegativeLamports)?; } keyed_accounts[FROM_ACCOUNT_INDEX].account.lamports -= lamports; keyed_accounts[TO_ACCOUNT_INDEX].account.lamports += lamports; @@ -81,8 +78,8 @@ pub fn entrypoint( data: &[u8], _tick_height: u64, ) -> Result<(), ProgramError> { - if let Ok(syscall) = bincode::deserialize(data) { - trace!("process_instruction: {:?}", syscall); + if let Ok(instruction) = bincode::deserialize(data) { + trace!("process_instruction: {:?}", instruction); trace!("keyed_accounts: {:?}", keyed_accounts); // All system instructions require that accounts_keys[0] be a signer @@ -91,24 +88,21 @@ pub fn entrypoint( Err(ProgramError::InvalidArgument)?; } - match syscall { + match instruction { SystemInstruction::CreateAccount { lamports, space, program_id, - } => create_system_account(keyed_accounts, lamports, space, &program_id).map_err(|e| { - match e { - SystemError::ResultWithNegativeLamports => { - ProgramError::ResultWithNegativeLamports - } - e => ProgramError::CustomError(serialize(&e).unwrap()), - } - }), + } => create_system_account(keyed_accounts, lamports, space, &program_id), SystemInstruction::Assign { program_id } => { + if !system_program::check_id(&keyed_accounts[FROM_ACCOUNT_INDEX].account.owner) { + Err(ProgramError::AssignOfUnownedAccount)?; + } assign_account_to_program(keyed_accounts, &program_id) } SystemInstruction::Move { lamports } => move_lamports(keyed_accounts, lamports), } + .map_err(|e| ProgramError::CustomError(serialize(&e).unwrap())) } else { info!("Invalid transaction instruction userdata: {:?}", data); Err(ProgramError::InvalidUserdata) @@ -246,7 +240,11 @@ mod tests { // Attempt to assign account not owned by system program let another_program_owner = Pubkey::new(&[8; 32]); keyed_accounts = [KeyedAccount::new(&from, true, &mut from_account)]; - let result = assign_account_to_program(&mut keyed_accounts, &another_program_owner); + let instruction = SystemInstruction::Assign { + program_id: another_program_owner, + }; + let data = serialize(&instruction).unwrap(); + let result = entrypoint(&system_program::id(), &mut keyed_accounts, &data, 0); assert_eq!(result, Err(ProgramError::AssignOfUnownedAccount)); assert_eq!(from_account.owner, new_program_owner); } @@ -273,7 +271,7 @@ mod tests { KeyedAccount::new(&to, false, &mut to_account), ]; let result = move_lamports(&mut keyed_accounts, 100); - assert_eq!(result, Err(ProgramError::ResultWithNegativeLamports)); + assert_eq!(result, Err(SystemError::ResultWithNegativeLamports)); assert_eq!(from_account.lamports, 50); assert_eq!(to_account.lamports, 51); } diff --git a/sdk/src/native_program.rs b/sdk/src/native_program.rs index e088f36081..cdbd96f93a 100644 --- a/sdk/src/native_program.rs +++ b/sdk/src/native_program.rs @@ -11,11 +11,6 @@ pub enum ProgramError { /// The arguments provided to a program instruction where invalid InvalidArgument, - /// An instruction resulted in an account with a negative balance - /// The difference from InsufficientFundsForFee is that the transaction was executed by the - /// contract - ResultWithNegativeLamports, - /// An account's userdata contents was invalid InvalidUserdata,