(cherry picked from commit 3dab1e711d
)
Co-authored-by: Justin Starry <justin@solana.com>
This commit is contained in:
@ -234,7 +234,7 @@ impl ExecuteTimings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BankStatusCache = StatusCache<Result<()>>;
|
type BankStatusCache = StatusCache<Result<()>>;
|
||||||
#[frozen_abi(digest = "7bCDimGo11ajw6ZHViBBu8KPfoDZBcwSnumWCU8MMuwr")]
|
#[frozen_abi(digest = "32EjVUc6shHHVPpsnBAVfyBziMgyFzH8qxisLwmwwdS1")]
|
||||||
pub type BankSlotDelta = SlotDelta<Result<()>>;
|
pub type BankSlotDelta = SlotDelta<Result<()>>;
|
||||||
type TransactionAccountRefCells = Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>;
|
type TransactionAccountRefCells = Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>;
|
||||||
|
|
||||||
|
121
sdk/src/transaction/error.rs
Normal file
121
sdk/src/transaction/error.rs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
instruction::InstructionError, message::SanitizeMessageError, sanitize::SanitizeError,
|
||||||
|
},
|
||||||
|
serde::Serialize,
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Reasons a transaction might be rejected.
|
||||||
|
#[derive(
|
||||||
|
Error, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample, AbiEnumVisitor,
|
||||||
|
)]
|
||||||
|
pub enum TransactionError {
|
||||||
|
/// An account is already being processed in another transaction in a way
|
||||||
|
/// that does not support parallelism
|
||||||
|
#[error("Account in use")]
|
||||||
|
AccountInUse,
|
||||||
|
|
||||||
|
/// A `Pubkey` appears twice in the transaction's `account_keys`. Instructions can reference
|
||||||
|
/// `Pubkey`s more than once but the message must contain a list with no duplicate keys
|
||||||
|
#[error("Account loaded twice")]
|
||||||
|
AccountLoadedTwice,
|
||||||
|
|
||||||
|
/// Attempt to debit an account but found no record of a prior credit.
|
||||||
|
#[error("Attempt to debit an account but found no record of a prior credit.")]
|
||||||
|
AccountNotFound,
|
||||||
|
|
||||||
|
/// Attempt to load a program that does not exist
|
||||||
|
#[error("Attempt to load a program that does not exist")]
|
||||||
|
ProgramAccountNotFound,
|
||||||
|
|
||||||
|
/// The from `Pubkey` does not have sufficient balance to pay the fee to schedule the transaction
|
||||||
|
#[error("Insufficient funds for fee")]
|
||||||
|
InsufficientFundsForFee,
|
||||||
|
|
||||||
|
/// This account may not be used to pay transaction fees
|
||||||
|
#[error("This account may not be used to pay transaction fees")]
|
||||||
|
InvalidAccountForFee,
|
||||||
|
|
||||||
|
/// The bank has seen this transaction before. This can occur under normal operation
|
||||||
|
/// when a UDP packet is duplicated, as a user error from a client not updating
|
||||||
|
/// its `recent_blockhash`, or as a double-spend attack.
|
||||||
|
#[error("This transaction has already been processed")]
|
||||||
|
AlreadyProcessed,
|
||||||
|
|
||||||
|
/// The bank has not seen the given `recent_blockhash` or the transaction is too old and
|
||||||
|
/// the `recent_blockhash` has been discarded.
|
||||||
|
#[error("Blockhash not found")]
|
||||||
|
BlockhashNotFound,
|
||||||
|
|
||||||
|
/// An error occurred while processing an instruction. The first element of the tuple
|
||||||
|
/// indicates the instruction index in which the error occurred.
|
||||||
|
#[error("Error processing Instruction {0}: {1}")]
|
||||||
|
InstructionError(u8, InstructionError),
|
||||||
|
|
||||||
|
/// Loader call chain is too deep
|
||||||
|
#[error("Loader call chain is too deep")]
|
||||||
|
CallChainTooDeep,
|
||||||
|
|
||||||
|
/// Transaction requires a fee but has no signature present
|
||||||
|
#[error("Transaction requires a fee but has no signature present")]
|
||||||
|
MissingSignatureForFee,
|
||||||
|
|
||||||
|
/// Transaction contains an invalid account reference
|
||||||
|
#[error("Transaction contains an invalid account reference")]
|
||||||
|
InvalidAccountIndex,
|
||||||
|
|
||||||
|
/// Transaction did not pass signature verification
|
||||||
|
#[error("Transaction did not pass signature verification")]
|
||||||
|
SignatureFailure,
|
||||||
|
|
||||||
|
/// This program may not be used for executing instructions
|
||||||
|
#[error("This program may not be used for executing instructions")]
|
||||||
|
InvalidProgramForExecution,
|
||||||
|
|
||||||
|
/// Transaction failed to sanitize accounts offsets correctly
|
||||||
|
/// implies that account locks are not taken for this TX, and should
|
||||||
|
/// not be unlocked.
|
||||||
|
#[error("Transaction failed to sanitize accounts offsets correctly")]
|
||||||
|
SanitizeFailure,
|
||||||
|
|
||||||
|
#[error("Transactions are currently disabled due to cluster maintenance")]
|
||||||
|
ClusterMaintenance,
|
||||||
|
|
||||||
|
/// Transaction processing left an account with an outstanding borrowed reference
|
||||||
|
#[error("Transaction processing left an account with an outstanding borrowed reference")]
|
||||||
|
AccountBorrowOutstanding,
|
||||||
|
|
||||||
|
/// Transaction would exceed max Block Cost Limit
|
||||||
|
#[error("Transaction would exceed max Block Cost Limit")]
|
||||||
|
WouldExceedMaxBlockCostLimit,
|
||||||
|
|
||||||
|
/// Transaction version is unsupported
|
||||||
|
#[error("Transaction version is unsupported")]
|
||||||
|
UnsupportedVersion,
|
||||||
|
|
||||||
|
/// Transaction loads a writable account that cannot be written
|
||||||
|
#[error("Transaction loads a writable account that cannot be written")]
|
||||||
|
InvalidWritableAccount,
|
||||||
|
|
||||||
|
/// Transaction would exceed max account limit within the block
|
||||||
|
#[error("Transaction would exceed max account limit within the block")]
|
||||||
|
WouldExceedMaxAccountCostLimit,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SanitizeError> for TransactionError {
|
||||||
|
fn from(_: SanitizeError) -> Self {
|
||||||
|
Self::SanitizeFailure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SanitizeMessageError> for TransactionError {
|
||||||
|
fn from(err: SanitizeMessageError) -> Self {
|
||||||
|
match err {
|
||||||
|
SanitizeMessageError::IndexOutOfBounds
|
||||||
|
| SanitizeMessageError::ValueOutOfBounds
|
||||||
|
| SanitizeMessageError::InvalidValue => Self::SanitizeFailure,
|
||||||
|
SanitizeMessageError::DuplicateAccountKey => Self::AccountLoadedTwice,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,8 @@
|
|||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::{CompiledInstruction, Instruction, InstructionError},
|
instruction::{CompiledInstruction, Instruction},
|
||||||
message::{Message, SanitizeMessageError},
|
message::Message,
|
||||||
nonce::NONCED_TX_MARKER_IX_INDEX,
|
nonce::NONCED_TX_MARKER_IX_INDEX,
|
||||||
precompiles::verify_if_precompile,
|
precompiles::verify_if_precompile,
|
||||||
program_utils::limited_deserialize,
|
program_utils::limited_deserialize,
|
||||||
@ -20,110 +20,13 @@ use {
|
|||||||
solana_program::{system_instruction::SystemInstruction, system_program},
|
solana_program::{system_instruction::SystemInstruction, system_program},
|
||||||
solana_sdk::feature_set,
|
solana_sdk::feature_set,
|
||||||
std::{result, sync::Arc},
|
std::{result, sync::Arc},
|
||||||
thiserror::Error,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod error;
|
||||||
mod sanitized;
|
mod sanitized;
|
||||||
mod versioned;
|
mod versioned;
|
||||||
|
|
||||||
pub use {sanitized::*, versioned::*};
|
pub use {error::*, sanitized::*, versioned::*};
|
||||||
|
|
||||||
/// Reasons a transaction might be rejected.
|
|
||||||
#[derive(
|
|
||||||
Error, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample, AbiEnumVisitor,
|
|
||||||
)]
|
|
||||||
pub enum TransactionError {
|
|
||||||
/// An account is already being processed in another transaction in a way
|
|
||||||
/// that does not support parallelism
|
|
||||||
#[error("Account in use")]
|
|
||||||
AccountInUse,
|
|
||||||
|
|
||||||
/// A `Pubkey` appears twice in the transaction's `account_keys`. Instructions can reference
|
|
||||||
/// `Pubkey`s more than once but the message must contain a list with no duplicate keys
|
|
||||||
#[error("Account loaded twice")]
|
|
||||||
AccountLoadedTwice,
|
|
||||||
|
|
||||||
/// Attempt to debit an account but found no record of a prior credit.
|
|
||||||
#[error("Attempt to debit an account but found no record of a prior credit.")]
|
|
||||||
AccountNotFound,
|
|
||||||
|
|
||||||
/// Attempt to load a program that does not exist
|
|
||||||
#[error("Attempt to load a program that does not exist")]
|
|
||||||
ProgramAccountNotFound,
|
|
||||||
|
|
||||||
/// The from `Pubkey` does not have sufficient balance to pay the fee to schedule the transaction
|
|
||||||
#[error("Insufficient funds for fee")]
|
|
||||||
InsufficientFundsForFee,
|
|
||||||
|
|
||||||
/// This account may not be used to pay transaction fees
|
|
||||||
#[error("This account may not be used to pay transaction fees")]
|
|
||||||
InvalidAccountForFee,
|
|
||||||
|
|
||||||
/// The bank has seen this transaction before. This can occur under normal operation
|
|
||||||
/// when a UDP packet is duplicated, as a user error from a client not updating
|
|
||||||
/// its `recent_blockhash`, or as a double-spend attack.
|
|
||||||
#[error("This transaction has already been processed")]
|
|
||||||
AlreadyProcessed,
|
|
||||||
|
|
||||||
/// The bank has not seen the given `recent_blockhash` or the transaction is too old and
|
|
||||||
/// the `recent_blockhash` has been discarded.
|
|
||||||
#[error("Blockhash not found")]
|
|
||||||
BlockhashNotFound,
|
|
||||||
|
|
||||||
/// An error occurred while processing an instruction. The first element of the tuple
|
|
||||||
/// indicates the instruction index in which the error occurred.
|
|
||||||
#[error("Error processing Instruction {0}: {1}")]
|
|
||||||
InstructionError(u8, InstructionError),
|
|
||||||
|
|
||||||
/// Loader call chain is too deep
|
|
||||||
#[error("Loader call chain is too deep")]
|
|
||||||
CallChainTooDeep,
|
|
||||||
|
|
||||||
/// Transaction requires a fee but has no signature present
|
|
||||||
#[error("Transaction requires a fee but has no signature present")]
|
|
||||||
MissingSignatureForFee,
|
|
||||||
|
|
||||||
/// Transaction contains an invalid account reference
|
|
||||||
#[error("Transaction contains an invalid account reference")]
|
|
||||||
InvalidAccountIndex,
|
|
||||||
|
|
||||||
/// Transaction did not pass signature verification
|
|
||||||
#[error("Transaction did not pass signature verification")]
|
|
||||||
SignatureFailure,
|
|
||||||
|
|
||||||
/// This program may not be used for executing instructions
|
|
||||||
#[error("This program may not be used for executing instructions")]
|
|
||||||
InvalidProgramForExecution,
|
|
||||||
|
|
||||||
/// Transaction failed to sanitize accounts offsets correctly
|
|
||||||
/// implies that account locks are not taken for this TX, and should
|
|
||||||
/// not be unlocked.
|
|
||||||
#[error("Transaction failed to sanitize accounts offsets correctly")]
|
|
||||||
SanitizeFailure,
|
|
||||||
|
|
||||||
#[error("Transactions are currently disabled due to cluster maintenance")]
|
|
||||||
ClusterMaintenance,
|
|
||||||
|
|
||||||
/// Transaction processing left an account with an outstanding borrowed reference
|
|
||||||
#[error("Transaction processing left an account with an outstanding borrowed reference")]
|
|
||||||
AccountBorrowOutstanding,
|
|
||||||
|
|
||||||
/// Transaction would exceed max Block Cost Limit
|
|
||||||
#[error("Transaction would exceed max Block Cost Limit")]
|
|
||||||
WouldExceedMaxBlockCostLimit,
|
|
||||||
|
|
||||||
/// Transaction version is unsupported
|
|
||||||
#[error("Transaction version is unsupported")]
|
|
||||||
UnsupportedVersion,
|
|
||||||
|
|
||||||
/// Transaction loads a writable account that cannot be written
|
|
||||||
#[error("Transaction loads a writable account that cannot be written")]
|
|
||||||
InvalidWritableAccount,
|
|
||||||
|
|
||||||
/// Transaction would exceed max account limit within the block
|
|
||||||
#[error("Transaction would exceed max account limit within the block")]
|
|
||||||
WouldExceedMaxAccountCostLimit,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
pub enum TransactionVerificationMode {
|
pub enum TransactionVerificationMode {
|
||||||
@ -134,23 +37,6 @@ pub enum TransactionVerificationMode {
|
|||||||
|
|
||||||
pub type Result<T> = result::Result<T, TransactionError>;
|
pub type Result<T> = result::Result<T, TransactionError>;
|
||||||
|
|
||||||
impl From<SanitizeError> for TransactionError {
|
|
||||||
fn from(_: SanitizeError) -> Self {
|
|
||||||
Self::SanitizeFailure
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<SanitizeMessageError> for TransactionError {
|
|
||||||
fn from(err: SanitizeMessageError) -> Self {
|
|
||||||
match err {
|
|
||||||
SanitizeMessageError::IndexOutOfBounds
|
|
||||||
| SanitizeMessageError::ValueOutOfBounds
|
|
||||||
| SanitizeMessageError::InvalidValue => Self::SanitizeFailure,
|
|
||||||
SanitizeMessageError::DuplicateAccountKey => Self::AccountLoadedTwice,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An atomic transaction
|
/// An atomic transaction
|
||||||
#[frozen_abi(digest = "FZtncnS1Xk8ghHfKiXE5oGiUbw2wJhmfXQuNgQR3K6Mc")]
|
#[frozen_abi(digest = "FZtncnS1Xk8ghHfKiXE5oGiUbw2wJhmfXQuNgQR3K6Mc")]
|
||||||
#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, AbiExample)]
|
#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, AbiExample)]
|
||||||
|
Reference in New Issue
Block a user