|
|
@@ -43,7 +43,7 @@
|
|
|
use {
|
|
|
crate::{
|
|
|
decode_error::DecodeError,
|
|
|
- instruction::{AccountMeta, Instruction, InstructionError},
|
|
|
+ instruction::{AccountMeta, Instruction},
|
|
|
nonce,
|
|
|
pubkey::Pubkey,
|
|
|
system_program,
|
|
|
@@ -81,101 +81,6 @@ impl<T> DecodeError<T> for SystemError {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#[derive(Error, Debug, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
|
|
-pub enum NonceError {
|
|
|
- #[error("recent blockhash list is empty")]
|
|
|
- NoRecentBlockhashes,
|
|
|
- #[error("stored nonce is still in recent_blockhashes")]
|
|
|
- NotExpired,
|
|
|
- #[error("specified nonce does not match stored nonce")]
|
|
|
- UnexpectedValue,
|
|
|
- #[error("cannot handle request in current account state")]
|
|
|
- BadAccountState,
|
|
|
-}
|
|
|
-
|
|
|
-impl<E> DecodeError<E> for NonceError {
|
|
|
- fn type_of() -> &'static str {
|
|
|
- "NonceError"
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Error, Debug, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
|
|
-enum NonceErrorAdapter {
|
|
|
- #[error("recent blockhash list is empty")]
|
|
|
- NoRecentBlockhashes,
|
|
|
- #[error("stored nonce is still in recent_blockhashes")]
|
|
|
- NotExpired,
|
|
|
- #[error("specified nonce does not match stored nonce")]
|
|
|
- UnexpectedValue,
|
|
|
- #[error("cannot handle request in current account state")]
|
|
|
- BadAccountState,
|
|
|
-}
|
|
|
-
|
|
|
-impl<E> DecodeError<E> for NonceErrorAdapter {
|
|
|
- fn type_of() -> &'static str {
|
|
|
- "NonceErrorAdapter"
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl From<NonceErrorAdapter> for NonceError {
|
|
|
- fn from(e: NonceErrorAdapter) -> Self {
|
|
|
- match e {
|
|
|
- NonceErrorAdapter::NoRecentBlockhashes => NonceError::NoRecentBlockhashes,
|
|
|
- NonceErrorAdapter::NotExpired => NonceError::NotExpired,
|
|
|
- NonceErrorAdapter::UnexpectedValue => NonceError::UnexpectedValue,
|
|
|
- NonceErrorAdapter::BadAccountState => NonceError::BadAccountState,
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub fn nonce_to_instruction_error(error: NonceError, use_system_variant: bool) -> InstructionError {
|
|
|
- if use_system_variant {
|
|
|
- match error {
|
|
|
- NonceError::NoRecentBlockhashes => SystemError::NonceNoRecentBlockhashes.into(),
|
|
|
- NonceError::NotExpired => SystemError::NonceBlockhashNotExpired.into(),
|
|
|
- NonceError::UnexpectedValue => SystemError::NonceUnexpectedBlockhashValue.into(),
|
|
|
- NonceError::BadAccountState => InstructionError::InvalidAccountData,
|
|
|
- }
|
|
|
- } else {
|
|
|
- match error {
|
|
|
- NonceError::NoRecentBlockhashes => NonceErrorAdapter::NoRecentBlockhashes.into(),
|
|
|
- NonceError::NotExpired => NonceErrorAdapter::NotExpired.into(),
|
|
|
- NonceError::UnexpectedValue => NonceErrorAdapter::UnexpectedValue.into(),
|
|
|
- NonceError::BadAccountState => NonceErrorAdapter::BadAccountState.into(),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub fn instruction_to_nonce_error(
|
|
|
- error: &InstructionError,
|
|
|
- use_system_variant: bool,
|
|
|
-) -> Option<NonceError> {
|
|
|
- if use_system_variant {
|
|
|
- match error {
|
|
|
- InstructionError::Custom(discriminant) => {
|
|
|
- match SystemError::decode_custom_error_to_enum(*discriminant) {
|
|
|
- Some(SystemError::NonceNoRecentBlockhashes) => {
|
|
|
- Some(NonceError::NoRecentBlockhashes)
|
|
|
- }
|
|
|
- Some(SystemError::NonceBlockhashNotExpired) => Some(NonceError::NotExpired),
|
|
|
- Some(SystemError::NonceUnexpectedBlockhashValue) => {
|
|
|
- Some(NonceError::UnexpectedValue)
|
|
|
- }
|
|
|
- _ => None,
|
|
|
- }
|
|
|
- }
|
|
|
- InstructionError::InvalidAccountData => Some(NonceError::BadAccountState),
|
|
|
- _ => None,
|
|
|
- }
|
|
|
- } else if let InstructionError::Custom(discriminant) = error {
|
|
|
- let maybe: Option<NonceErrorAdapter> =
|
|
|
- NonceErrorAdapter::decode_custom_error_to_enum(*discriminant);
|
|
|
- maybe.map(NonceError::from)
|
|
|
- } else {
|
|
|
- None
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/// Maximum permitted size of account data (10 MiB).
|
|
|
pub const MAX_PERMITTED_DATA_LENGTH: u64 = 10 * 1024 * 1024;
|
|
|
|
|
|
@@ -1867,11 +1772,7 @@ pub fn upgrade_nonce_account(nonce_pubkey: Pubkey) -> Instruction {
|
|
|
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
- use {
|
|
|
- super::*,
|
|
|
- crate::instruction::{Instruction, InstructionError},
|
|
|
- num_traits::ToPrimitive,
|
|
|
- };
|
|
|
+ use {super::*, crate::instruction::Instruction};
|
|
|
|
|
|
fn get_keys(instruction: &Instruction) -> Vec<Pubkey> {
|
|
|
instruction.accounts.iter().map(|x| x.pubkey).collect()
|
|
|
@@ -1903,165 +1804,4 @@ mod tests {
|
|
|
assert!(pubkeys.contains(&from_pubkey));
|
|
|
assert!(pubkeys.contains(&nonce_pubkey));
|
|
|
}
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn test_nonce_error_decode() {
|
|
|
- use num_traits::FromPrimitive;
|
|
|
- fn pretty_err<T>(err: InstructionError) -> String
|
|
|
- where
|
|
|
- T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
|
|
- {
|
|
|
- if let InstructionError::Custom(code) = err {
|
|
|
- let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
|
|
- format!(
|
|
|
- "{:?}: {}::{:?} - {}",
|
|
|
- err,
|
|
|
- T::type_of(),
|
|
|
- specific_error,
|
|
|
- specific_error,
|
|
|
- )
|
|
|
- } else {
|
|
|
- "".to_string()
|
|
|
- }
|
|
|
- }
|
|
|
- assert_eq!(
|
|
|
- "Custom(0): NonceError::NoRecentBlockhashes - recent blockhash list is empty",
|
|
|
- pretty_err::<NonceError>(NonceError::NoRecentBlockhashes.into())
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- "Custom(1): NonceError::NotExpired - stored nonce is still in recent_blockhashes",
|
|
|
- pretty_err::<NonceError>(NonceError::NotExpired.into())
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- "Custom(2): NonceError::UnexpectedValue - specified nonce does not match stored nonce",
|
|
|
- pretty_err::<NonceError>(NonceError::UnexpectedValue.into())
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- "Custom(3): NonceError::BadAccountState - cannot handle request in current account state",
|
|
|
- pretty_err::<NonceError>(NonceError::BadAccountState.into())
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn test_nonce_to_instruction_error() {
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::NoRecentBlockhashes, false),
|
|
|
- NonceError::NoRecentBlockhashes.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::NotExpired, false),
|
|
|
- NonceError::NotExpired.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::UnexpectedValue, false),
|
|
|
- NonceError::UnexpectedValue.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::BadAccountState, false),
|
|
|
- NonceError::BadAccountState.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::NoRecentBlockhashes, true),
|
|
|
- SystemError::NonceNoRecentBlockhashes.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::NotExpired, true),
|
|
|
- SystemError::NonceBlockhashNotExpired.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::UnexpectedValue, true),
|
|
|
- SystemError::NonceUnexpectedBlockhashValue.into(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- nonce_to_instruction_error(NonceError::BadAccountState, true),
|
|
|
- InstructionError::InvalidAccountData,
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn test_instruction_to_nonce_error() {
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(NonceErrorAdapter::NoRecentBlockhashes.to_u32().unwrap(),),
|
|
|
- false,
|
|
|
- ),
|
|
|
- Some(NonceError::NoRecentBlockhashes),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(NonceErrorAdapter::NotExpired.to_u32().unwrap(),),
|
|
|
- false,
|
|
|
- ),
|
|
|
- Some(NonceError::NotExpired),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(NonceErrorAdapter::UnexpectedValue.to_u32().unwrap(),),
|
|
|
- false,
|
|
|
- ),
|
|
|
- Some(NonceError::UnexpectedValue),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(NonceErrorAdapter::BadAccountState.to_u32().unwrap(),),
|
|
|
- false,
|
|
|
- ),
|
|
|
- Some(NonceError::BadAccountState),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(&InstructionError::Custom(u32::MAX), false),
|
|
|
- None,
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(SystemError::NonceNoRecentBlockhashes.to_u32().unwrap(),),
|
|
|
- true,
|
|
|
- ),
|
|
|
- Some(NonceError::NoRecentBlockhashes),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(SystemError::NonceBlockhashNotExpired.to_u32().unwrap(),),
|
|
|
- true,
|
|
|
- ),
|
|
|
- Some(NonceError::NotExpired),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(
|
|
|
- &InstructionError::Custom(
|
|
|
- SystemError::NonceUnexpectedBlockhashValue.to_u32().unwrap(),
|
|
|
- ),
|
|
|
- true,
|
|
|
- ),
|
|
|
- Some(NonceError::UnexpectedValue),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(&InstructionError::InvalidAccountData, true),
|
|
|
- Some(NonceError::BadAccountState),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- instruction_to_nonce_error(&InstructionError::Custom(u32::MAX), true),
|
|
|
- None,
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn test_nonce_error_adapter_compat() {
|
|
|
- assert_eq!(
|
|
|
- NonceError::NoRecentBlockhashes.to_u32(),
|
|
|
- NonceErrorAdapter::NoRecentBlockhashes.to_u32(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- NonceError::NotExpired.to_u32(),
|
|
|
- NonceErrorAdapter::NotExpired.to_u32(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- NonceError::UnexpectedValue.to_u32(),
|
|
|
- NonceErrorAdapter::UnexpectedValue.to_u32(),
|
|
|
- );
|
|
|
- assert_eq!(
|
|
|
- NonceError::BadAccountState.to_u32(),
|
|
|
- NonceErrorAdapter::BadAccountState.to_u32(),
|
|
|
- );
|
|
|
- }
|
|
|
}
|