Add missing ProgramError to InstructionError mappings (#16231)
* Add missing ProgramError to InstructionError mappings * add note * Clarify process of adding new program error
This commit is contained in:
parent
708bbcb001
commit
83b9a046d1
|
@ -31,13 +31,14 @@ use solana_sdk::{
|
||||||
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
||||||
clock::Clock,
|
clock::Clock,
|
||||||
entrypoint::SUCCESS,
|
entrypoint::SUCCESS,
|
||||||
feature_set::upgradeable_close_instruction,
|
feature_set::{add_missing_program_error_mappings, upgradeable_close_instruction},
|
||||||
ic_logger_msg, ic_msg,
|
ic_logger_msg, ic_msg,
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
keyed_account::{from_keyed_account, keyed_account_at_index},
|
keyed_account::{from_keyed_account, keyed_account_at_index},
|
||||||
loader_instruction::LoaderInstruction,
|
loader_instruction::LoaderInstruction,
|
||||||
loader_upgradeable_instruction::UpgradeableLoaderInstruction,
|
loader_upgradeable_instruction::UpgradeableLoaderInstruction,
|
||||||
process_instruction::{stable_log, ComputeMeter, Executor, InvokeContext},
|
process_instruction::{stable_log, ComputeMeter, Executor, InvokeContext},
|
||||||
|
program_error::{ACCOUNT_NOT_RENT_EXEMPT, BORSH_IO_ERROR},
|
||||||
program_utils::limited_deserialize,
|
program_utils::limited_deserialize,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
|
@ -750,6 +751,8 @@ impl Executor for BpfExecutor {
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let logger = invoke_context.get_logger();
|
let logger = invoke_context.get_logger();
|
||||||
let invoke_depth = invoke_context.invoke_depth();
|
let invoke_depth = invoke_context.invoke_depth();
|
||||||
|
let add_missing_program_error_mappings =
|
||||||
|
invoke_context.is_feature_active(&add_missing_program_error_mappings::id());
|
||||||
|
|
||||||
invoke_context.remove_first_keyed_account()?;
|
invoke_context.remove_first_keyed_account()?;
|
||||||
|
|
||||||
|
@ -803,7 +806,14 @@ impl Executor for BpfExecutor {
|
||||||
match result {
|
match result {
|
||||||
Ok(status) => {
|
Ok(status) => {
|
||||||
if status != SUCCESS {
|
if status != SUCCESS {
|
||||||
let error: InstructionError = status.into();
|
let error: InstructionError = if !add_missing_program_error_mappings
|
||||||
|
&& (status == ACCOUNT_NOT_RENT_EXEMPT || status == BORSH_IO_ERROR)
|
||||||
|
{
|
||||||
|
// map originally missing error mappings to InvalidError
|
||||||
|
InstructionError::InvalidError
|
||||||
|
} else {
|
||||||
|
status.into()
|
||||||
|
};
|
||||||
stable_log::program_failure(&logger, program_id, &error);
|
stable_log::program_failure(&logger, program_id, &error);
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,8 @@ pub enum InstructionError {
|
||||||
/// Unsupported sysvar
|
/// Unsupported sysvar
|
||||||
#[error("Unsupported sysvar")]
|
#[error("Unsupported sysvar")]
|
||||||
UnsupportedSysvar,
|
UnsupportedSysvar,
|
||||||
|
// Note: For any new error added here an equivilent ProgramError and it's
|
||||||
|
// conversions must also be added
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
|
|
|
@ -111,6 +111,11 @@ pub const INVALID_SEEDS: u64 = to_builtin!(14);
|
||||||
pub const BORSH_IO_ERROR: u64 = to_builtin!(15);
|
pub const BORSH_IO_ERROR: u64 = to_builtin!(15);
|
||||||
pub const ACCOUNT_NOT_RENT_EXEMPT: u64 = to_builtin!(16);
|
pub const ACCOUNT_NOT_RENT_EXEMPT: u64 = to_builtin!(16);
|
||||||
pub const UNSUPPORTED_SYSVAR: u64 = to_builtin!(17);
|
pub const UNSUPPORTED_SYSVAR: u64 = to_builtin!(17);
|
||||||
|
// Warning: Any new program errors added here must also be:
|
||||||
|
// - Added to the below conversions
|
||||||
|
// - Added as an equivilent to InstructionError
|
||||||
|
// - Be featureized in the BPF loader to return `InstructionError::InvalidError`
|
||||||
|
// until the feature is activated
|
||||||
|
|
||||||
impl From<ProgramError> for u64 {
|
impl From<ProgramError> for u64 {
|
||||||
fn from(error: ProgramError) -> Self {
|
fn from(error: ProgramError) -> Self {
|
||||||
|
@ -131,7 +136,6 @@ impl From<ProgramError> for u64 {
|
||||||
ProgramError::BorshIoError(_) => BORSH_IO_ERROR,
|
ProgramError::BorshIoError(_) => BORSH_IO_ERROR,
|
||||||
ProgramError::AccountNotRentExempt => ACCOUNT_NOT_RENT_EXEMPT,
|
ProgramError::AccountNotRentExempt => ACCOUNT_NOT_RENT_EXEMPT,
|
||||||
ProgramError::UnsupportedSysvar => UNSUPPORTED_SYSVAR,
|
ProgramError::UnsupportedSysvar => UNSUPPORTED_SYSVAR,
|
||||||
|
|
||||||
ProgramError::Custom(error) => {
|
ProgramError::Custom(error) => {
|
||||||
if error == 0 {
|
if error == 0 {
|
||||||
CUSTOM_ZERO
|
CUSTOM_ZERO
|
||||||
|
@ -146,22 +150,24 @@ impl From<ProgramError> for u64 {
|
||||||
impl From<u64> for ProgramError {
|
impl From<u64> for ProgramError {
|
||||||
fn from(error: u64) -> Self {
|
fn from(error: u64) -> Self {
|
||||||
match error {
|
match error {
|
||||||
INVALID_ARGUMENT => ProgramError::InvalidArgument,
|
CUSTOM_ZERO => Self::Custom(0),
|
||||||
INVALID_INSTRUCTION_DATA => ProgramError::InvalidInstructionData,
|
INVALID_ARGUMENT => Self::InvalidArgument,
|
||||||
INVALID_ACCOUNT_DATA => ProgramError::InvalidAccountData,
|
INVALID_INSTRUCTION_DATA => Self::InvalidInstructionData,
|
||||||
ACCOUNT_DATA_TOO_SMALL => ProgramError::AccountDataTooSmall,
|
INVALID_ACCOUNT_DATA => Self::InvalidAccountData,
|
||||||
INSUFFICIENT_FUNDS => ProgramError::InsufficientFunds,
|
ACCOUNT_DATA_TOO_SMALL => Self::AccountDataTooSmall,
|
||||||
INCORRECT_PROGRAM_ID => ProgramError::IncorrectProgramId,
|
INSUFFICIENT_FUNDS => Self::InsufficientFunds,
|
||||||
MISSING_REQUIRED_SIGNATURES => ProgramError::MissingRequiredSignature,
|
INCORRECT_PROGRAM_ID => Self::IncorrectProgramId,
|
||||||
ACCOUNT_ALREADY_INITIALIZED => ProgramError::AccountAlreadyInitialized,
|
MISSING_REQUIRED_SIGNATURES => Self::MissingRequiredSignature,
|
||||||
UNINITIALIZED_ACCOUNT => ProgramError::UninitializedAccount,
|
ACCOUNT_ALREADY_INITIALIZED => Self::AccountAlreadyInitialized,
|
||||||
NOT_ENOUGH_ACCOUNT_KEYS => ProgramError::NotEnoughAccountKeys,
|
UNINITIALIZED_ACCOUNT => Self::UninitializedAccount,
|
||||||
ACCOUNT_BORROW_FAILED => ProgramError::AccountBorrowFailed,
|
NOT_ENOUGH_ACCOUNT_KEYS => Self::NotEnoughAccountKeys,
|
||||||
MAX_SEED_LENGTH_EXCEEDED => ProgramError::MaxSeedLengthExceeded,
|
ACCOUNT_BORROW_FAILED => Self::AccountBorrowFailed,
|
||||||
INVALID_SEEDS => ProgramError::InvalidSeeds,
|
MAX_SEED_LENGTH_EXCEEDED => Self::MaxSeedLengthExceeded,
|
||||||
UNSUPPORTED_SYSVAR => ProgramError::UnsupportedSysvar,
|
INVALID_SEEDS => Self::InvalidSeeds,
|
||||||
CUSTOM_ZERO => ProgramError::Custom(0),
|
BORSH_IO_ERROR => Self::BorshIoError("Unkown".to_string()),
|
||||||
_ => ProgramError::Custom(error as u32),
|
ACCOUNT_NOT_RENT_EXEMPT => Self::AccountNotRentExempt,
|
||||||
|
UNSUPPORTED_SYSVAR => Self::UnsupportedSysvar,
|
||||||
|
_ => Self::Custom(error as u32),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,6 +190,7 @@ impl TryFrom<InstructionError> for ProgramError {
|
||||||
Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
|
Self::Error::NotEnoughAccountKeys => Ok(Self::NotEnoughAccountKeys),
|
||||||
Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
|
Self::Error::AccountBorrowFailed => Ok(Self::AccountBorrowFailed),
|
||||||
Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
|
Self::Error::MaxSeedLengthExceeded => Ok(Self::MaxSeedLengthExceeded),
|
||||||
|
Self::Error::InvalidSeeds => Ok(Self::InvalidSeeds),
|
||||||
Self::Error::BorshIoError(err) => Ok(Self::BorshIoError(err)),
|
Self::Error::BorshIoError(err) => Ok(Self::BorshIoError(err)),
|
||||||
Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
|
Self::Error::AccountNotRentExempt => Ok(Self::AccountNotRentExempt),
|
||||||
Self::Error::UnsupportedSysvar => Ok(Self::UnsupportedSysvar),
|
Self::Error::UnsupportedSysvar => Ok(Self::UnsupportedSysvar),
|
||||||
|
@ -199,25 +206,27 @@ where
|
||||||
fn from(error: T) -> Self {
|
fn from(error: T) -> Self {
|
||||||
let error = error.to_u64().unwrap_or(0xbad_c0de);
|
let error = error.to_u64().unwrap_or(0xbad_c0de);
|
||||||
match error {
|
match error {
|
||||||
CUSTOM_ZERO => InstructionError::Custom(0),
|
CUSTOM_ZERO => Self::Custom(0),
|
||||||
INVALID_ARGUMENT => InstructionError::InvalidArgument,
|
INVALID_ARGUMENT => Self::InvalidArgument,
|
||||||
INVALID_INSTRUCTION_DATA => InstructionError::InvalidInstructionData,
|
INVALID_INSTRUCTION_DATA => Self::InvalidInstructionData,
|
||||||
INVALID_ACCOUNT_DATA => InstructionError::InvalidAccountData,
|
INVALID_ACCOUNT_DATA => Self::InvalidAccountData,
|
||||||
ACCOUNT_DATA_TOO_SMALL => InstructionError::AccountDataTooSmall,
|
ACCOUNT_DATA_TOO_SMALL => Self::AccountDataTooSmall,
|
||||||
INSUFFICIENT_FUNDS => InstructionError::InsufficientFunds,
|
INSUFFICIENT_FUNDS => Self::InsufficientFunds,
|
||||||
INCORRECT_PROGRAM_ID => InstructionError::IncorrectProgramId,
|
INCORRECT_PROGRAM_ID => Self::IncorrectProgramId,
|
||||||
MISSING_REQUIRED_SIGNATURES => InstructionError::MissingRequiredSignature,
|
MISSING_REQUIRED_SIGNATURES => Self::MissingRequiredSignature,
|
||||||
ACCOUNT_ALREADY_INITIALIZED => InstructionError::AccountAlreadyInitialized,
|
ACCOUNT_ALREADY_INITIALIZED => Self::AccountAlreadyInitialized,
|
||||||
UNINITIALIZED_ACCOUNT => InstructionError::UninitializedAccount,
|
UNINITIALIZED_ACCOUNT => Self::UninitializedAccount,
|
||||||
NOT_ENOUGH_ACCOUNT_KEYS => InstructionError::NotEnoughAccountKeys,
|
NOT_ENOUGH_ACCOUNT_KEYS => Self::NotEnoughAccountKeys,
|
||||||
ACCOUNT_BORROW_FAILED => InstructionError::AccountBorrowFailed,
|
ACCOUNT_BORROW_FAILED => Self::AccountBorrowFailed,
|
||||||
MAX_SEED_LENGTH_EXCEEDED => InstructionError::MaxSeedLengthExceeded,
|
MAX_SEED_LENGTH_EXCEEDED => Self::MaxSeedLengthExceeded,
|
||||||
INVALID_SEEDS => InstructionError::InvalidSeeds,
|
INVALID_SEEDS => Self::InvalidSeeds,
|
||||||
UNSUPPORTED_SYSVAR => InstructionError::UnsupportedSysvar,
|
BORSH_IO_ERROR => Self::BorshIoError("Unkown".to_string()),
|
||||||
|
ACCOUNT_NOT_RENT_EXEMPT => Self::AccountNotRentExempt,
|
||||||
|
UNSUPPORTED_SYSVAR => Self::UnsupportedSysvar,
|
||||||
_ => {
|
_ => {
|
||||||
// A valid custom error has no bits set in the upper 32
|
// A valid custom error has no bits set in the upper 32
|
||||||
if error >> BUILTIN_BIT_SHIFT == 0 {
|
if error >> BUILTIN_BIT_SHIFT == 0 {
|
||||||
InstructionError::Custom(error as u32)
|
Self::Custom(error as u32)
|
||||||
} else {
|
} else {
|
||||||
Self::InvalidError
|
Self::InvalidError
|
||||||
}
|
}
|
||||||
|
@ -229,14 +238,14 @@ where
|
||||||
impl From<PubkeyError> for ProgramError {
|
impl From<PubkeyError> for ProgramError {
|
||||||
fn from(error: PubkeyError) -> Self {
|
fn from(error: PubkeyError) -> Self {
|
||||||
match error {
|
match error {
|
||||||
PubkeyError::MaxSeedLengthExceeded => ProgramError::MaxSeedLengthExceeded,
|
PubkeyError::MaxSeedLengthExceeded => Self::MaxSeedLengthExceeded,
|
||||||
PubkeyError::InvalidSeeds => ProgramError::InvalidSeeds,
|
PubkeyError::InvalidSeeds => Self::InvalidSeeds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BorshIoError> for ProgramError {
|
impl From<BorshIoError> for ProgramError {
|
||||||
fn from(error: BorshIoError) -> Self {
|
fn from(error: BorshIoError) -> Self {
|
||||||
ProgramError::BorshIoError(format!("{}", error))
|
Self::BorshIoError(format!("{}", error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,10 @@ pub mod memory_ops_syscalls {
|
||||||
solana_sdk::declare_id!("ENQi37wsVhTvFz2gUiZAAbqFEWGN2jwFsqdEDTE8A4MU");
|
solana_sdk::declare_id!("ENQi37wsVhTvFz2gUiZAAbqFEWGN2jwFsqdEDTE8A4MU");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod add_missing_program_error_mappings {
|
||||||
|
solana_sdk::declare_id!("3QEUpjhgPEt92nz3Mqf6pABkHPGCQwSvKtyGMq4SuQyL");
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Map of feature identifiers to user-visible description
|
/// Map of feature identifiers to user-visible description
|
||||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||||
|
@ -174,6 +178,7 @@ lazy_static! {
|
||||||
(keccak256_syscall_enabled::id(), "keccak256 syscall"),
|
(keccak256_syscall_enabled::id(), "keccak256 syscall"),
|
||||||
(stake_program_v4::id(), "solana_stake_program v4"),
|
(stake_program_v4::id(), "solana_stake_program v4"),
|
||||||
(memory_ops_syscalls::id(), "add syscalls for memory operations"),
|
(memory_ops_syscalls::id(), "add syscalls for memory operations"),
|
||||||
|
(add_missing_program_error_mappings::id(), "add missing program error mappings"),
|
||||||
/*************** ADD NEW FEATURES HERE ***************/
|
/*************** ADD NEW FEATURES HERE ***************/
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Reference in New Issue