2020-10-12 17:47:06 -07:00
|
|
|
//! Implementation defined RPC server errors
|
2021-03-26 20:26:06 -07:00
|
|
|
use {
|
2022-08-23 22:34:35 -07:00
|
|
|
crate::response::RpcSimulateTransactionResult,
|
2021-03-26 20:26:06 -07:00
|
|
|
jsonrpc_core::{Error, ErrorCode},
|
|
|
|
solana_sdk::clock::Slot,
|
2022-03-07 23:20:34 -08:00
|
|
|
solana_transaction_status::EncodeError,
|
2021-12-03 09:00:31 -08:00
|
|
|
thiserror::Error,
|
2021-03-26 20:26:06 -07:00
|
|
|
};
|
2020-05-11 14:47:40 -07:00
|
|
|
|
2022-06-30 13:08:10 -07:00
|
|
|
// Keep in sync with web3.js/src/errors.ts
|
2020-10-12 18:06:10 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP: i64 = -32001;
|
|
|
|
pub const JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE: i64 = -32002;
|
|
|
|
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE: i64 = -32003;
|
|
|
|
pub const JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE: i64 = -32004;
|
2021-02-12 23:07:04 -08:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY: i64 = -32005;
|
2020-10-12 18:06:10 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE: i64 = -32006;
|
2020-12-16 12:40:36 -08:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_SLOT_SKIPPED: i64 = -32007;
|
2021-01-14 21:45:11 -08:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_NO_SNAPSHOT: i64 = -32008;
|
2021-01-21 20:40:47 -08:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED: i64 = -32009;
|
2021-05-13 14:04:21 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX: i64 = -32010;
|
2021-05-26 12:27:41 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE: i64 = -32011;
|
2021-06-14 21:04:01 -07:00
|
|
|
pub const JSON_RPC_SCAN_ERROR: i64 = -32012;
|
2021-07-01 11:06:59 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_LEN_MISMATCH: i64 = -32013;
|
2021-10-27 12:11:27 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET: i64 = -32014;
|
2022-01-13 23:24:41 -08:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION: i64 = -32015;
|
2022-05-16 23:46:02 -07:00
|
|
|
pub const JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED: i64 = -32016;
|
2020-05-11 14:47:40 -07:00
|
|
|
|
2021-06-14 21:04:01 -07:00
|
|
|
#[derive(Error, Debug)]
|
2020-05-11 14:47:40 -07:00
|
|
|
pub enum RpcCustomError {
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("BlockCleanedUp")]
|
2020-05-11 14:47:40 -07:00
|
|
|
BlockCleanedUp {
|
|
|
|
slot: Slot,
|
|
|
|
first_available_block: Slot,
|
|
|
|
},
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("SendTransactionPreflightFailure")]
|
2020-05-29 23:16:35 -07:00
|
|
|
SendTransactionPreflightFailure {
|
|
|
|
message: String,
|
2020-09-15 22:30:04 -07:00
|
|
|
result: RpcSimulateTransactionResult,
|
2020-05-29 23:16:35 -07:00
|
|
|
},
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("TransactionSignatureVerificationFailure")]
|
2020-09-15 22:30:04 -07:00
|
|
|
TransactionSignatureVerificationFailure,
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("BlockNotAvailable")]
|
|
|
|
BlockNotAvailable { slot: Slot },
|
|
|
|
#[error("NodeUnhealthy")]
|
|
|
|
NodeUnhealthy { num_slots_behind: Option<Slot> },
|
|
|
|
#[error("TransactionPrecompileVerificationFailure")]
|
2020-09-27 22:29:00 -07:00
|
|
|
TransactionPrecompileVerificationFailure(solana_sdk::transaction::TransactionError),
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("SlotSkipped")]
|
|
|
|
SlotSkipped { slot: Slot },
|
|
|
|
#[error("NoSnapshot")]
|
2021-01-14 21:45:11 -08:00
|
|
|
NoSnapshot,
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("LongTermStorageSlotSkipped")]
|
|
|
|
LongTermStorageSlotSkipped { slot: Slot },
|
|
|
|
#[error("KeyExcludedFromSecondaryIndex")]
|
|
|
|
KeyExcludedFromSecondaryIndex { index_key: String },
|
|
|
|
#[error("TransactionHistoryNotAvailable")]
|
2021-05-26 12:27:41 -07:00
|
|
|
TransactionHistoryNotAvailable,
|
2021-06-14 21:04:01 -07:00
|
|
|
#[error("ScanError")]
|
|
|
|
ScanError { message: String },
|
2021-07-01 11:06:59 -07:00
|
|
|
#[error("TransactionSignatureLenMismatch")]
|
|
|
|
TransactionSignatureLenMismatch,
|
2021-10-27 12:11:27 -07:00
|
|
|
#[error("BlockStatusNotAvailableYet")]
|
|
|
|
BlockStatusNotAvailableYet { slot: Slot },
|
2022-01-13 23:24:41 -08:00
|
|
|
#[error("UnsupportedTransactionVersion")]
|
2022-03-07 23:20:34 -08:00
|
|
|
UnsupportedTransactionVersion(u8),
|
2022-05-16 23:46:02 -07:00
|
|
|
#[error("MinContextSlotNotReached")]
|
|
|
|
MinContextSlotNotReached { context_slot: Slot },
|
2020-05-11 14:47:40 -07:00
|
|
|
}
|
|
|
|
|
2021-01-14 21:45:11 -08:00
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
2021-01-17 20:23:14 -08:00
|
|
|
pub struct NodeUnhealthyErrorData {
|
|
|
|
pub num_slots_behind: Option<Slot>,
|
2021-01-14 21:45:11 -08:00
|
|
|
}
|
|
|
|
|
2022-05-16 23:46:02 -07:00
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
pub struct MinContextSlotNotReachedErrorData {
|
|
|
|
pub context_slot: Slot,
|
|
|
|
}
|
|
|
|
|
2022-03-07 23:20:34 -08:00
|
|
|
impl From<EncodeError> for RpcCustomError {
|
|
|
|
fn from(err: EncodeError) -> Self {
|
|
|
|
match err {
|
|
|
|
EncodeError::UnsupportedTransactionVersion(version) => {
|
|
|
|
Self::UnsupportedTransactionVersion(version)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 14:47:40 -07:00
|
|
|
impl From<RpcCustomError> for Error {
|
|
|
|
fn from(e: RpcCustomError) -> Self {
|
|
|
|
match e {
|
|
|
|
RpcCustomError::BlockCleanedUp {
|
|
|
|
slot,
|
|
|
|
first_available_block,
|
|
|
|
} => Self {
|
2020-10-12 18:06:10 -07:00
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_CLEANED_UP),
|
2020-05-11 14:47:40 -07:00
|
|
|
message: format!(
|
2022-12-06 06:30:06 -08:00
|
|
|
"Block {slot} cleaned up, does not exist on node. First available block: {first_available_block}",
|
2020-05-11 14:47:40 -07:00
|
|
|
),
|
|
|
|
data: None,
|
|
|
|
},
|
2020-09-15 22:30:04 -07:00
|
|
|
RpcCustomError::SendTransactionPreflightFailure { message, result } => Self {
|
2020-10-12 18:06:10 -07:00
|
|
|
code: ErrorCode::ServerError(
|
|
|
|
JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
|
|
|
|
),
|
2020-05-29 23:16:35 -07:00
|
|
|
message,
|
2020-09-15 22:30:04 -07:00
|
|
|
data: Some(serde_json::json!(result)),
|
2020-05-29 23:16:35 -07:00
|
|
|
},
|
2020-09-15 22:30:04 -07:00
|
|
|
RpcCustomError::TransactionSignatureVerificationFailure => Self {
|
2020-10-12 18:06:10 -07:00
|
|
|
code: ErrorCode::ServerError(
|
|
|
|
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE,
|
|
|
|
),
|
2020-09-15 22:30:04 -07:00
|
|
|
message: "Transaction signature verification failure".to_string(),
|
2020-07-29 19:06:16 -07:00
|
|
|
data: None,
|
|
|
|
},
|
2020-08-20 14:05:30 -07:00
|
|
|
RpcCustomError::BlockNotAvailable { slot } => Self {
|
2020-10-12 18:06:10 -07:00
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE),
|
2022-12-06 06:30:06 -08:00
|
|
|
message: format!("Block not available for slot {slot}"),
|
2020-08-20 14:05:30 -07:00
|
|
|
data: None,
|
|
|
|
},
|
2021-01-17 20:23:14 -08:00
|
|
|
RpcCustomError::NodeUnhealthy { num_slots_behind } => Self {
|
2021-02-12 23:07:04 -08:00
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY),
|
2021-01-17 20:23:14 -08:00
|
|
|
message: if let Some(num_slots_behind) = num_slots_behind {
|
2022-12-06 06:30:06 -08:00
|
|
|
format!("Node is behind by {num_slots_behind} slots")
|
2021-01-17 20:23:14 -08:00
|
|
|
} else {
|
|
|
|
"Node is unhealthy".to_string()
|
|
|
|
},
|
|
|
|
data: Some(serde_json::json!(NodeUnhealthyErrorData {
|
2021-01-14 21:45:11 -08:00
|
|
|
num_slots_behind
|
|
|
|
})),
|
2020-09-15 22:30:04 -07:00
|
|
|
},
|
2020-09-27 22:29:00 -07:00
|
|
|
RpcCustomError::TransactionPrecompileVerificationFailure(e) => Self {
|
2020-10-12 18:06:10 -07:00
|
|
|
code: ErrorCode::ServerError(
|
2023-01-04 11:46:13 -08:00
|
|
|
JSON_RPC_SERVER_ERROR_TRANSACTION_PRECOMPILE_VERIFICATION_FAILURE,
|
2020-10-12 18:06:10 -07:00
|
|
|
),
|
2022-12-06 06:30:06 -08:00
|
|
|
message: format!("Transaction precompile verification failure {e:?}"),
|
2020-09-27 22:29:00 -07:00
|
|
|
data: None,
|
|
|
|
},
|
2020-12-16 12:40:36 -08:00
|
|
|
RpcCustomError::SlotSkipped { slot } => Self {
|
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_SLOT_SKIPPED),
|
|
|
|
message: format!(
|
2022-12-06 06:30:06 -08:00
|
|
|
"Slot {slot} was skipped, or missing due to ledger jump to recent snapshot"
|
2020-12-16 12:40:36 -08:00
|
|
|
),
|
|
|
|
data: None,
|
|
|
|
},
|
2021-01-14 21:45:11 -08:00
|
|
|
RpcCustomError::NoSnapshot => Self {
|
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_NO_SNAPSHOT),
|
|
|
|
message: "No snapshot".to_string(),
|
|
|
|
data: None,
|
|
|
|
},
|
2021-01-21 20:40:47 -08:00
|
|
|
RpcCustomError::LongTermStorageSlotSkipped { slot } => Self {
|
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_LONG_TERM_STORAGE_SLOT_SKIPPED),
|
2022-12-06 06:30:06 -08:00
|
|
|
message: format!("Slot {slot} was skipped, or missing in long-term storage"),
|
2021-01-21 20:40:47 -08:00
|
|
|
data: None,
|
|
|
|
},
|
2021-05-13 14:04:21 -07:00
|
|
|
RpcCustomError::KeyExcludedFromSecondaryIndex { index_key } => Self {
|
|
|
|
code: ErrorCode::ServerError(
|
|
|
|
JSON_RPC_SERVER_ERROR_KEY_EXCLUDED_FROM_SECONDARY_INDEX,
|
|
|
|
),
|
|
|
|
message: format!(
|
2022-12-06 06:30:06 -08:00
|
|
|
"{index_key} excluded from account secondary indexes; \
|
|
|
|
this RPC method unavailable for key"
|
2021-05-13 14:04:21 -07:00
|
|
|
),
|
|
|
|
data: None,
|
|
|
|
},
|
2021-05-26 12:27:41 -07:00
|
|
|
RpcCustomError::TransactionHistoryNotAvailable => Self {
|
|
|
|
code: ErrorCode::ServerError(
|
|
|
|
JSON_RPC_SERVER_ERROR_TRANSACTION_HISTORY_NOT_AVAILABLE,
|
|
|
|
),
|
|
|
|
message: "Transaction history is not available from this node".to_string(),
|
|
|
|
data: None,
|
|
|
|
},
|
2021-06-14 21:04:01 -07:00
|
|
|
RpcCustomError::ScanError { message } => Self {
|
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SCAN_ERROR),
|
|
|
|
message,
|
|
|
|
data: None,
|
|
|
|
},
|
2021-07-01 11:06:59 -07:00
|
|
|
RpcCustomError::TransactionSignatureLenMismatch => Self {
|
|
|
|
code: ErrorCode::ServerError(
|
|
|
|
JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_LEN_MISMATCH,
|
|
|
|
),
|
|
|
|
message: "Transaction signature length mismatch".to_string(),
|
|
|
|
data: None,
|
|
|
|
},
|
2021-10-27 12:11:27 -07:00
|
|
|
RpcCustomError::BlockStatusNotAvailableYet { slot } => Self {
|
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_BLOCK_STATUS_NOT_AVAILABLE_YET),
|
2022-12-06 06:30:06 -08:00
|
|
|
message: format!("Block status not yet available for slot {slot}"),
|
2021-10-27 12:11:27 -07:00
|
|
|
data: None,
|
|
|
|
},
|
2022-03-07 23:20:34 -08:00
|
|
|
RpcCustomError::UnsupportedTransactionVersion(version) => Self {
|
2022-01-13 23:24:41 -08:00
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_UNSUPPORTED_TRANSACTION_VERSION),
|
2022-10-06 02:12:56 -07:00
|
|
|
message: format!(
|
2022-12-06 06:30:06 -08:00
|
|
|
"Transaction version ({version}) is not supported by the requesting client. \
|
2022-10-06 02:12:56 -07:00
|
|
|
Please try the request again with the following configuration parameter: \
|
2022-12-06 06:30:06 -08:00
|
|
|
\"maxSupportedTransactionVersion\": {version}"
|
2022-10-06 02:12:56 -07:00
|
|
|
),
|
2022-01-13 23:24:41 -08:00
|
|
|
data: None,
|
|
|
|
},
|
2022-05-16 23:46:02 -07:00
|
|
|
RpcCustomError::MinContextSlotNotReached { context_slot } => Self {
|
|
|
|
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_MIN_CONTEXT_SLOT_NOT_REACHED),
|
|
|
|
message: "Minimum context slot has not been reached".to_string(),
|
|
|
|
data: Some(serde_json::json!(MinContextSlotNotReachedErrorData {
|
|
|
|
context_slot,
|
|
|
|
})),
|
|
|
|
},
|
2020-05-11 14:47:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|