2021-12-06 09:45:33 -08:00
|
|
|
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,
|
2021-12-12 12:57:18 -08:00
|
|
|
|
2022-03-13 08:58:57 -07:00
|
|
|
/// Transaction would exceed account data limit within the block
|
|
|
|
#[error("Transaction would exceed account data limit within the block")]
|
|
|
|
WouldExceedAccountDataBlockLimit,
|
2022-01-03 22:25:23 -08:00
|
|
|
|
|
|
|
/// Transaction locked too many accounts
|
|
|
|
#[error("Transaction locked too many accounts")]
|
|
|
|
TooManyAccountLocks,
|
2022-01-06 19:59:09 -08:00
|
|
|
|
|
|
|
/// Address lookup table not found
|
|
|
|
#[error("Transaction loads an address table account that doesn't exist")]
|
|
|
|
AddressLookupTableNotFound,
|
|
|
|
|
|
|
|
/// Attempted to lookup addresses from an account owned by the wrong program
|
|
|
|
#[error("Transaction loads an address table account with an invalid owner")]
|
|
|
|
InvalidAddressLookupTableOwner,
|
|
|
|
|
|
|
|
/// Attempted to lookup addresses from an invalid account
|
|
|
|
#[error("Transaction loads an address table account with invalid data")]
|
|
|
|
InvalidAddressLookupTableData,
|
|
|
|
|
|
|
|
/// Address table lookup uses an invalid index
|
|
|
|
#[error("Transaction address table lookup uses an invalid index")]
|
|
|
|
InvalidAddressLookupTableIndex,
|
2022-01-11 10:32:25 -08:00
|
|
|
|
|
|
|
/// Transaction leaves an account with a lower balance than rent-exempt minimum
|
2022-03-15 20:41:16 -07:00
|
|
|
#[error("Transaction leaves an account with a lower balance than rent-exempt minimum")]
|
2022-01-11 10:32:25 -08:00
|
|
|
InvalidRentPayingAccount,
|
2022-01-12 21:27:19 -08:00
|
|
|
|
|
|
|
/// Transaction would exceed max Vote Cost Limit
|
|
|
|
#[error("Transaction would exceed max Vote Cost Limit")]
|
|
|
|
WouldExceedMaxVoteCostLimit,
|
2022-03-13 08:58:57 -07:00
|
|
|
|
|
|
|
/// Transaction would exceed total account data limit
|
|
|
|
#[error("Transaction would exceed total account data limit")]
|
|
|
|
WouldExceedAccountDataTotalLimit,
|
2022-05-12 11:07:36 -07:00
|
|
|
|
|
|
|
/// Transaction contains a duplicate instruction that is not allowed
|
|
|
|
#[error("Transaction contains a duplicate instruction ({0}) that is not allowed")]
|
|
|
|
DuplicateInstruction(u8),
|
2021-12-06 09:45:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SanitizeError> for TransactionError {
|
|
|
|
fn from(_: SanitizeError) -> Self {
|
|
|
|
Self::SanitizeFailure
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<SanitizeMessageError> for TransactionError {
|
2022-01-03 22:25:23 -08:00
|
|
|
fn from(_err: SanitizeMessageError) -> Self {
|
|
|
|
Self::SanitizeFailure
|
2021-12-06 09:45:33 -08:00
|
|
|
}
|
|
|
|
}
|