Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
Add PubkeyError for ProgramError (#10748)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackcmay authored Jun 23, 2020
1 parent 685beca commit db4a18a
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 4 deletions.
3 changes: 3 additions & 0 deletions programs/bpf/c/src/error_handling/error_handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ extern uint64_t entrypoint(const uint8_t *input) {
case(6):
sol_log("return unknown builtin");
return TO_BUILTIN(50);
case(9):
sol_log("return pubkey error");
return MAX_SEED_LENGTH_EXCEEDED;
default:
sol_log("Unrecognized command");
return ERROR_INVALID_INSTRUCTION_DATA;
Expand Down
6 changes: 5 additions & 1 deletion programs/bpf/rust/error_handling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use solana_sdk::{
entrypoint::ProgramResult,
info,
program_error::{PrintProgramError, ProgramError},
pubkey::Pubkey,
pubkey::{Pubkey, PubkeyError},
};
use thiserror::Error;

Expand Down Expand Up @@ -73,6 +73,10 @@ fn process_instruction(
assert_eq!(*data, *data2);
Ok(())
}
9 => {
info!("return pubkey error");
Err(PubkeyError::MaxSeedLengthExceeded.into())
}
_ => {
info!("Unsupported");
Err(ProgramError::InvalidInstructionData)
Expand Down
8 changes: 8 additions & 0 deletions programs/bpf/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ mod bpf {
result.unwrap_err().unwrap(),
TransactionError::InstructionError(0, InstructionError::InvalidInstructionData)
);

let instruction = Instruction::new(program_id, &9u8, account_metas.clone());
let result = bank_client.send_instruction(&mint_keypair, instruction);
assert_eq!(
result.unwrap_err().unwrap(),
TransactionError::InstructionError(0, InstructionError::MaxSeedLengthExceeded)
);

}
}

Expand Down
3 changes: 2 additions & 1 deletion sdk/bpf/c/inc/solana_sdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ static_assert(sizeof(uint64_t) == 8);
#define ERROR_NOT_ENOUGH_ACCOUNT_KEYS TO_BUILTIN(11)
/** Note: Not applicable to program written in C */
#define ERROR_ACCOUNT_BORROW_FAILED TO_BUILTIN(12)
/** The length of the seed is too long for address generation */
#define MAX_SEED_LENGTH_EXCEEDED TO_BUILTIN(13)

/**
* Boolean type
Expand All @@ -129,7 +131,6 @@ void sol_log_(const char *, uint64_t);
void sol_log_64_(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
#define sol_log_64 sol_log_64_


/**
* Size of Public key in bytes
*/
Expand Down
4 changes: 4 additions & 0 deletions sdk/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ pub enum InstructionError {
/// Cross-program invocation reentrancy not allowed for this instruction
#[error("Cross-program invocation reentrancy not allowed for this instruction")]
ReentrancyNotAllowed,

/// Length of the seed is too long for address generation
#[error("Length of the seed is too long for address generation")]
MaxSeedLengthExceeded,
}

impl InstructionError {
Expand Down
18 changes: 17 additions & 1 deletion sdk/src/program_error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{decode_error::DecodeError, instruction::InstructionError};
use crate::{decode_error::DecodeError, instruction::InstructionError, pubkey::PubkeyError};
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::TryFrom;
use thiserror::Error;
Expand Down Expand Up @@ -38,6 +38,8 @@ pub enum ProgramError {
NotEnoughAccountKeys,
#[error("Failed to borrow a reference to account data, already borrowed")]
AccountBorrowFailed,
#[error("Length of the seed is too long for address generation")]
MaxSeedLengthExceeded,
}

pub trait PrintProgramError {
Expand Down Expand Up @@ -70,6 +72,7 @@ impl PrintProgramError for ProgramError {
Self::UninitializedAccount => info!("Error: UninitializedAccount"),
Self::NotEnoughAccountKeys => info!("Error: NotEnoughAccountKeys"),
Self::AccountBorrowFailed => info!("Error: AccountBorrowFailed"),
Self::MaxSeedLengthExceeded => info!("Error: MaxSeedLengthExceeded"),
}
}
}
Expand All @@ -94,6 +97,7 @@ 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 MAX_SEED_LENGTH_EXCEEDED: u64 = to_builtin!(13);

impl From<ProgramError> for u64 {
fn from(error: ProgramError) -> Self {
Expand All @@ -109,6 +113,7 @@ impl From<ProgramError> for u64 {
ProgramError::UninitializedAccount => UNINITIALIZED_ACCOUNT,
ProgramError::NotEnoughAccountKeys => NOT_ENOUGH_ACCOUNT_KEYS,
ProgramError::AccountBorrowFailed => ACCOUNT_BORROW_FAILED,
ProgramError::MaxSeedLengthExceeded => MAX_SEED_LENGTH_EXCEEDED,
ProgramError::Custom(error) => {
if error == 0 {
CUSTOM_ZERO
Expand All @@ -134,6 +139,7 @@ impl From<u64> for ProgramError {
UNINITIALIZED_ACCOUNT => ProgramError::UninitializedAccount,
NOT_ENOUGH_ACCOUNT_KEYS => ProgramError::NotEnoughAccountKeys,
ACCOUNT_BORROW_FAILED => ProgramError::AccountBorrowFailed,
MAX_SEED_LENGTH_EXCEEDED => ProgramError::MaxSeedLengthExceeded,
CUSTOM_ZERO => ProgramError::Custom(0),
_ => ProgramError::Custom(error as u32),
}
Expand All @@ -157,6 +163,7 @@ impl TryFrom<InstructionError> for ProgramError {
Self::Error::UninitializedAccount => Ok(Self::UninitializedAccount),
Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
_ => Err(error),
}
}
Expand All @@ -181,6 +188,7 @@ where
UNINITIALIZED_ACCOUNT => InstructionError::UninitializedAccount,
NOT_ENOUGH_ACCOUNT_KEYS => InstructionError::NotEnoughAccountKeys,
ACCOUNT_BORROW_FAILED => InstructionError::AccountBorrowFailed,
MAX_SEED_LENGTH_EXCEEDED => InstructionError::MaxSeedLengthExceeded,
_ => {
// A valid custom error has no bits set in the upper 32
if error >> BUILTIN_BIT_SHIFT == 0 {
Expand All @@ -192,3 +200,11 @@ where
}
}
}

impl From<PubkeyError> for ProgramError {
fn from(error: PubkeyError) -> Self {
match error {
PubkeyError::MaxSeedLengthExceeded => ProgramError::MaxSeedLengthExceeded,
}
}
}
3 changes: 2 additions & 1 deletion sdk/src/pubkey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ pub const MAX_SEED_LEN: usize = 32;

#[derive(Error, Debug, Serialize, Clone, PartialEq, FromPrimitive, ToPrimitive)]
pub enum PubkeyError {
#[error("length of requested seed is too long")]
/// Length of the seed is too long for address generation
#[error("Length of the seed is too long for address generation")]
MaxSeedLengthExceeded,
}
impl<T> DecodeError<T> for PubkeyError {
Expand Down

0 comments on commit db4a18a

Please sign in to comment.