unc_primitives/
errors.rs

1use crate::hash::CryptoHash;
2use crate::serialize::dec_format;
3use crate::types::{AccountId, Balance, EpochId, Gas, Nonce};
4use borsh::{BorshDeserialize, BorshSerialize};
5use std::fmt::{Debug, Display};
6use unc_crypto::PublicKey;
7use unc_primitives_core::types::{BlockHeight, ProtocolVersion};
8use unc_rpc_error_macro::RpcError;
9
10/// Error returned in the ExecutionOutcome in case of failure
11#[derive(
12    BorshSerialize,
13    BorshDeserialize,
14    Debug,
15    Clone,
16    PartialEq,
17    Eq,
18    RpcError,
19    serde::Deserialize,
20    serde::Serialize,
21)]
22pub enum TxExecutionError {
23    /// An error happened during Action execution
24    ActionError(ActionError),
25    /// An error happened during Transaction execution
26    InvalidTxError(InvalidTxError),
27}
28
29impl std::error::Error for TxExecutionError {}
30
31impl Display for TxExecutionError {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
33        match self {
34            TxExecutionError::ActionError(e) => write!(f, "{}", e),
35            TxExecutionError::InvalidTxError(e) => write!(f, "{}", e),
36        }
37    }
38}
39
40impl From<ActionError> for TxExecutionError {
41    fn from(error: ActionError) -> Self {
42        TxExecutionError::ActionError(error)
43    }
44}
45
46impl From<InvalidTxError> for TxExecutionError {
47    fn from(error: InvalidTxError) -> Self {
48        TxExecutionError::InvalidTxError(error)
49    }
50}
51
52/// Error returned from `Runtime::apply`
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub enum RuntimeError {
55    /// An unexpected integer overflow occurred. The likely issue is an invalid state or the transition.
56    UnexpectedIntegerOverflow,
57    /// An error happened during TX verification and account charging. It's likely the chunk is invalid.
58    /// and should be challenged.
59    InvalidTxError(InvalidTxError),
60    /// Unexpected error which is typically related to the node storage corruption.
61    /// It's possible the input state is invalid or malicious.
62    StorageError(StorageError),
63    /// An error happens if `check_balance` fails, which is likely an indication of an invalid state.
64    BalanceMismatchError(Box<BalanceMismatchError>),
65    /// The incoming receipt didn't pass the validation, it's likely a malicious behaviour.
66    ReceiptValidationError(ReceiptValidationError),
67    /// Error when accessing validator information. Happens inside epoch manager.
68    ValidatorError(EpochError),
69}
70
71impl std::fmt::Display for RuntimeError {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
73        f.write_str(&format!("{:?}", self))
74    }
75}
76
77impl std::error::Error for RuntimeError {}
78
79/// Contexts in which `StorageError::MissingTrieValue` error might occur.
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum MissingTrieValueContext {
82    /// Missing trie value when reading from TrieIterator.
83    TrieIterator,
84    /// Missing trie value when reading from TriePrefetchingStorage.
85    TriePrefetchingStorage,
86    /// Missing trie value when reading from TrieMemoryPartialStorage.
87    TrieMemoryPartialStorage,
88    /// Missing trie value when reading from TrieStorage.
89    TrieStorage,
90}
91
92/// Errors which may occur during working with trie storages, storing
93/// trie values (trie nodes and state values) by their hashes.
94#[derive(Debug, Clone, PartialEq, Eq)]
95pub enum StorageError {
96    /// Key-value db internal failure
97    StorageInternalError,
98    /// Requested trie value by its hash which is missing in storage.
99    MissingTrieValue(MissingTrieValueContext, CryptoHash),
100    /// Found trie node which shouldn't be part of state. Raised during
101    /// validation of state sync parts where incorrect node was passed.
102    /// TODO (#8997): consider including hash of trie node.
103    UnexpectedTrieValue,
104    /// Either invalid state or key-value db is corrupted.
105    /// For PartialStorage it cannot be corrupted.
106    /// Error message is unreliable and for debugging purposes only. It's also probably ok to
107    /// panic in every place that produces this error.
108    /// We can check if db is corrupted by verifying everything in the state trie.
109    StorageInconsistentState(String),
110    /// Flat storage error, meaning that it doesn't support some block anymore.
111    /// We guarantee that such block cannot become final, thus block processing
112    /// must resume normally.
113    FlatStorageBlockNotSupported(String),
114    /// In-memory trie could not be loaded for some reason.
115    MemTrieLoadingError(String),
116}
117
118impl std::fmt::Display for StorageError {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
120        f.write_str(&format!("{:?}", self))
121    }
122}
123
124impl std::error::Error for StorageError {}
125
126/// An error happened during TX execution
127#[derive(
128    BorshSerialize,
129    BorshDeserialize,
130    Debug,
131    Clone,
132    PartialEq,
133    Eq,
134    RpcError,
135    serde::Deserialize,
136    serde::Serialize,
137)]
138pub enum InvalidTxError {
139    /// Happens if a wrong AccessKey used or AccessKey has not enough permissions
140    InvalidAccessKeyError(InvalidAccessKeyError),
141    /// TX signer_id is not a valid [`AccountId`]
142    InvalidSignerId { signer_id: String },
143    /// TX signer_id is not found in a storage
144    SignerDoesNotExist { signer_id: AccountId },
145    /// Transaction nonce must be `account[access_key].nonce + 1`.
146    InvalidNonce { tx_nonce: Nonce, ak_nonce: Nonce },
147    /// Transaction nonce is larger than the upper bound given by the block height
148    NonceTooLarge { tx_nonce: Nonce, upper_bound: Nonce },
149    /// TX receiver_id is not a valid AccountId
150    InvalidReceiverId { receiver_id: String },
151    /// TX signature is not valid
152    InvalidSignature,
153    /// Account does not have enough balance to cover TX cost
154    NotEnoughBalance {
155        signer_id: AccountId,
156        #[serde(with = "dec_format")]
157        balance: Balance,
158        #[serde(with = "dec_format")]
159        cost: Balance,
160    },
161    /// Signer account doesn't have enough balance after transaction.
162    LackBalanceForState {
163        /// An account which doesn't have enough balance to cover storage.
164        signer_id: AccountId,
165        /// Required balance to cover the state.
166        #[serde(with = "dec_format")]
167        amount: Balance,
168    },
169    /// An integer overflow occurred during transaction cost estimation.
170    CostOverflow,
171    /// Transaction parent block hash doesn't belong to the current chain
172    InvalidChain,
173    /// Transaction has expired
174    Expired,
175    /// An error occurred while validating actions of a Transaction.
176    ActionsValidation(ActionsValidationError),
177    /// The size of serialized transaction exceeded the limit.
178    TransactionSizeExceeded { size: u64, limit: u64 },
179}
180
181impl std::error::Error for InvalidTxError {}
182
183#[derive(
184    BorshSerialize,
185    BorshDeserialize,
186    Debug,
187    Clone,
188    PartialEq,
189    Eq,
190    RpcError,
191    serde::Deserialize,
192    serde::Serialize,
193)]
194pub enum InvalidAccessKeyError {
195    /// The access key identified by the `public_key` doesn't exist for the account
196    AccessKeyNotFound { account_id: AccountId, public_key: Box<PublicKey> },
197    /// Transaction `receiver_id` doesn't match the access key receiver_id
198    ReceiverMismatch { tx_receiver: AccountId, ak_receiver: String },
199    /// Transaction method name isn't allowed by the access key
200    MethodNameMismatch { method_name: String },
201    /// Transaction requires a full permission access key.
202    RequiresFullAccess,
203    /// Access Key does not have enough allowance to cover transaction cost
204    NotEnoughAllowance {
205        account_id: AccountId,
206        public_key: Box<PublicKey>,
207        #[serde(with = "dec_format")]
208        allowance: Balance,
209        #[serde(with = "dec_format")]
210        cost: Balance,
211    },
212    /// Having a deposit with a function call action is not allowed with a function call access key.
213    DepositWithFunctionCall,
214}
215
216/// Describes the error for validating a list of actions.
217#[derive(
218    BorshSerialize,
219    BorshDeserialize,
220    Debug,
221    Clone,
222    PartialEq,
223    Eq,
224    RpcError,
225    serde::Serialize,
226    serde::Deserialize,
227)]
228pub enum ActionsValidationError {
229    /// The delete action must be a final aciton in transaction
230    DeleteActionMustBeFinal,
231    /// The total prepaid gas (for all given actions) exceeded the limit.
232    TotalPrepaidGasExceeded { total_prepaid_gas: Gas, limit: Gas },
233    /// The number of actions exceeded the given limit.
234    TotalNumberOfActionsExceeded { total_number_of_actions: u64, limit: u64 },
235    /// The total number of bytes of the method names exceeded the limit in a Add Key action.
236    AddKeyMethodNamesNumberOfBytesExceeded { total_number_of_bytes: u64, limit: u64 },
237    /// The length of some method name exceeded the limit in a Add Key action.
238    AddKeyMethodNameLengthExceeded { length: u64, limit: u64 },
239    /// Integer overflow during a compute.
240    IntegerOverflow,
241    /// Invalid account ID.
242    InvalidAccountId { account_id: String },
243    /// The size of the contract code exceeded the limit in a DeployContract action.
244    ContractSizeExceeded { size: u64, limit: u64 },
245    /// The length of the method name exceeded the limit in a Function Call action.
246    FunctionCallMethodNameLengthExceeded { length: u64, limit: u64 },
247    /// The length of the arguments exceeded the limit in a Function Call action.
248    FunctionCallArgumentsLengthExceeded { length: u64, limit: u64 },
249    /// An attempt to pledge with a public key that is not convertible to ristretto.
250    UnsuitablePledgingKey { public_key: Box<PublicKey> },
251    /// The attached amount of gas in a FunctionCall action has to be a positive number.
252    FunctionCallZeroAttachedGas,
253    /// There should be the only one DelegateAction
254    DelegateActionMustBeOnlyOne,
255    /// The transaction includes a feature that the current protocol version
256    /// does not support.
257    ///
258    /// Note: we stringify the protocol feature name instead of using
259    /// `ProtocolFeature` here because we don't want to leak the internals of
260    /// that type into observable borsh serialization.
261    UnsupportedProtocolFeature { protocol_feature: String, version: ProtocolVersion },
262
263    /// The actions only support rsa2048 keys
264    UnsuitableChallengingKey { public_key: Box<PublicKey> },
265}
266
267/// Describes the error for validating a receipt.
268#[derive(
269    BorshSerialize,
270    BorshDeserialize,
271    Debug,
272    Clone,
273    PartialEq,
274    Eq,
275    RpcError,
276    serde::Serialize,
277    serde::Deserialize,
278)]
279pub enum ReceiptValidationError {
280    /// The `predecessor_id` of a Receipt is not valid.
281    InvalidPredecessorId { account_id: String },
282    /// The `receiver_id` of a Receipt is not valid.
283    InvalidReceiverId { account_id: String },
284    /// The `signer_id` of an ActionReceipt is not valid.
285    InvalidSignerId { account_id: String },
286    /// The `receiver_id` of a DataReceiver within an ActionReceipt is not valid.
287    InvalidDataReceiverId { account_id: String },
288    /// The length of the returned data exceeded the limit in a DataReceipt.
289    ReturnedValueLengthExceeded { length: u64, limit: u64 },
290    /// The number of input data dependencies exceeds the limit in an ActionReceipt.
291    NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 },
292    /// An error occurred while validating actions of an ActionReceipt.
293    ActionsValidation(ActionsValidationError),
294}
295
296impl Display for ReceiptValidationError {
297    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
298        match self {
299            ReceiptValidationError::InvalidPredecessorId { account_id } => {
300                write!(f, "The predecessor_id `{}` of a Receipt is not valid.", account_id)
301            }
302            ReceiptValidationError::InvalidReceiverId { account_id } => {
303                write!(f, "The receiver_id `{}` of a Receipt is not valid.", account_id)
304            }
305            ReceiptValidationError::InvalidSignerId { account_id } => {
306                write!(f, "The signer_id `{}` of an ActionReceipt is not valid.", account_id)
307            }
308            ReceiptValidationError::InvalidDataReceiverId { account_id } => write!(
309                f,
310                "The receiver_id `{}` of a DataReceiver within an ActionReceipt is not valid.",
311                account_id
312            ),
313            ReceiptValidationError::ReturnedValueLengthExceeded { length, limit } => write!(
314                f,
315                "The length of the returned data {} exceeded the limit {} in a DataReceipt",
316                length, limit
317            ),
318            ReceiptValidationError::NumberInputDataDependenciesExceeded { number_of_input_data_dependencies, limit } => write!(
319                f,
320                "The number of input data dependencies {} exceeded the limit {} in an ActionReceipt",
321                number_of_input_data_dependencies, limit
322            ),
323            ReceiptValidationError::ActionsValidation(e) => write!(f, "{}", e),
324        }
325    }
326}
327
328impl std::error::Error for ReceiptValidationError {}
329
330impl Display for ActionsValidationError {
331    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
332        match self {
333            ActionsValidationError::DeleteActionMustBeFinal => {
334                write!(f, "The delete action must be the last action in transaction")
335            }
336            ActionsValidationError::TotalPrepaidGasExceeded { total_prepaid_gas, limit } => {
337                write!(f, "The total prepaid gas {} exceeds the limit {}", total_prepaid_gas, limit)
338            }
339            ActionsValidationError::TotalNumberOfActionsExceeded {total_number_of_actions, limit } => {
340                write!(
341                    f,
342                    "The total number of actions {} exceeds the limit {}",
343                    total_number_of_actions, limit
344                )
345            }
346            ActionsValidationError::AddKeyMethodNamesNumberOfBytesExceeded { total_number_of_bytes, limit } => write!(
347                f,
348                "The total number of bytes in allowed method names {} exceeds the maximum allowed number {} in a AddKey action",
349                total_number_of_bytes, limit
350            ),
351            ActionsValidationError::AddKeyMethodNameLengthExceeded { length, limit } => write!(
352                f,
353                "The length of some method name {} exceeds the maximum allowed length {} in a AddKey action",
354                length, limit
355            ),
356            ActionsValidationError::IntegerOverflow => write!(
357                f,
358                "Integer overflow during a compute",
359            ),
360            ActionsValidationError::InvalidAccountId { account_id } => write!(
361                f,
362                "Invalid account ID `{}`",
363                account_id
364            ),
365            ActionsValidationError::ContractSizeExceeded { size, limit } => write!(
366                f,
367                "The length of the contract size {} exceeds the maximum allowed size {} in a DeployContract action",
368                size, limit
369            ),
370            ActionsValidationError::FunctionCallMethodNameLengthExceeded { length, limit } => write!(
371                f,
372                "The length of the method name {} exceeds the maximum allowed length {} in a FunctionCall action",
373                length, limit
374            ),
375            ActionsValidationError::FunctionCallArgumentsLengthExceeded { length, limit } => write!(
376                f,
377                "The length of the arguments {} exceeds the maximum allowed length {} in a FunctionCall action",
378                length, limit
379            ),
380            ActionsValidationError::UnsuitablePledgingKey { public_key } => write!(
381                f,
382                "The staking key must be ristretto compatible ED25519 key. {} is provided instead.",
383                public_key,
384            ),
385            ActionsValidationError::FunctionCallZeroAttachedGas => write!(
386                f,
387                "The attached amount of gas in a FunctionCall action has to be a positive number",
388            ),
389            ActionsValidationError::DelegateActionMustBeOnlyOne => write!(
390                f,
391                "The actions can contain the ony one DelegateAction"
392            ),
393            ActionsValidationError::UnsupportedProtocolFeature { protocol_feature, version } => write!(
394                    f,
395                    "Transaction requires protocol feature {} / version {} which is not supported by the current protocol version",
396                    protocol_feature,
397                    version,
398            ),
399            ActionsValidationError::UnsuitableChallengingKey { public_key } => write!(
400                f,
401                "The challenging key must be RSA2048 keys. {} is provided instead.",
402                public_key,
403            ),
404        }
405    }
406}
407
408impl std::error::Error for ActionsValidationError {}
409
410/// An error happened during Action execution
411#[derive(
412    BorshSerialize,
413    BorshDeserialize,
414    Debug,
415    Clone,
416    PartialEq,
417    Eq,
418    RpcError,
419    serde::Deserialize,
420    serde::Serialize,
421)]
422pub struct ActionError {
423    /// Index of the failed action in the transaction.
424    /// Action index is not defined if ActionError.kind is `ActionErrorKind::LackBalanceForState`
425    pub index: Option<u64>,
426    /// The kind of ActionError happened
427    pub kind: ActionErrorKind,
428}
429
430impl std::error::Error for ActionError {}
431
432#[derive(
433    BorshSerialize,
434    BorshDeserialize,
435    Debug,
436    Clone,
437    PartialEq,
438    Eq,
439    RpcError,
440    serde::Deserialize,
441    serde::Serialize,
442)]
443pub enum ActionErrorKind {
444    /// Happens when CreateAccount action tries to create an account with account_id which is already exists in the storage
445    AccountAlreadyExists { account_id: AccountId },
446    /// Happens when TX receiver_id doesn't exist (but action is not Action::CreateAccount)
447    AccountDoesNotExist { account_id: AccountId },
448    /// A newly created account must be under a namespace of the creator account
449    CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId },
450    /// Administrative actions like `DeployContract`, `Pledge`, `AddKey`, `DeleteKey`. can be proceed only if sender=receiver
451    /// or the first TX action is a `CreateAccount` action
452    ActorNoPermission { account_id: AccountId, actor_id: AccountId },
453    /// Account tries to remove an access key that doesn't exist
454    DeleteKeyDoesNotExist { account_id: AccountId, public_key: Box<PublicKey> },
455    /// The public key is already used for an existing access key
456    AddKeyAlreadyExists { account_id: AccountId, public_key: Box<PublicKey> },
457    /// Account is staking and can not be deleted
458    DeleteAccountPledging { account_id: AccountId },
459    /// ActionReceipt can't be completed, because the remaining balance will not be enough to cover storage.
460    LackBalanceForState {
461        /// An account which needs balance
462        account_id: AccountId,
463        /// Balance required to complete an action.
464        #[serde(with = "dec_format")]
465        amount: Balance,
466    },
467    /// Account is not yet pledging, but tries to unpledge
468    TriesToUnpledge { account_id: AccountId },
469    /// The account doesn't have enough balance to increase the pledge.
470    TriesToPledge {
471        account_id: AccountId,
472        #[serde(with = "dec_format")]
473        pledge: Balance,
474        #[serde(with = "dec_format")]
475        pledging: Balance,
476        #[serde(with = "dec_format")]
477        balance: Balance,
478    },
479    InsufficientPledge {
480        account_id: AccountId,
481        #[serde(with = "dec_format")]
482        pledge: Balance,
483        #[serde(with = "dec_format")]
484        minimum_pledge: Balance,
485    },
486    /// An error occurred during a `FunctionCall` Action, parameter is debug message.
487    FunctionCallError(FunctionCallError),
488    /// Error occurs when a new `ActionReceipt` created by the `FunctionCall` action fails
489    /// receipt validation.
490    NewReceiptValidationError(ReceiptValidationError),
491    /// Error occurs when a `CreateAccount` action is called on a UNC-implicit or ETH-implicit account.
492    /// TODO: This error is named very poorly. A better name would be
493    /// `OnlyReservedCreationAllowed`.
494    OnlyImplicitAccountCreationAllowed { account_id: AccountId },
495    /// Delete account whose state is large is temporarily banned.
496    DeleteAccountWithLargeState { account_id: AccountId },
497    /// Signature does not match the provided actions and given signer public key.
498    DelegateActionInvalidSignature,
499    /// Receiver of the transaction doesn't match Sender of the delegate action
500    DelegateActionSenderDoesNotMatchTxReceiver { sender_id: AccountId, receiver_id: AccountId },
501    /// Delegate action has expired. `max_block_height` is less than actual block height.
502    DelegateActionExpired,
503    /// The given public key doesn't exist for Sender account
504    DelegateActionAccessKeyError(InvalidAccessKeyError),
505    /// DelegateAction nonce must be greater sender[public_key].nonce
506    DelegateActionInvalidNonce { delegate_nonce: Nonce, ak_nonce: Nonce },
507    /// DelegateAction nonce is larger than the upper bound given by the block height
508    DelegateActionNonceTooLarge { delegate_nonce: Nonce, upper_bound: Nonce },
509
510    /// The public key used for an  not existed  rsa key
511    RsaKeysNotFound { account_id: AccountId, public_key: Box<PublicKey> },
512}
513
514impl From<ActionErrorKind> for ActionError {
515    fn from(e: ActionErrorKind) -> ActionError {
516        ActionError { index: None, kind: e }
517    }
518}
519
520impl Display for InvalidTxError {
521    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
522        match self {
523            InvalidTxError::InvalidSignerId { signer_id } => {
524                write!(f, "Invalid signer account ID {:?} according to requirements", signer_id)
525            }
526            InvalidTxError::SignerDoesNotExist { signer_id } => {
527                write!(f, "Signer {:?} does not exist", signer_id)
528            }
529            InvalidTxError::InvalidAccessKeyError(access_key_error) => {
530                Display::fmt(&access_key_error, f)
531            }
532            InvalidTxError::InvalidNonce { tx_nonce, ak_nonce } => write!(
533                f,
534                "Transaction nonce {} must be larger than nonce of the used access key {}",
535                tx_nonce, ak_nonce
536            ),
537            InvalidTxError::InvalidReceiverId { receiver_id } => {
538                write!(f, "Invalid receiver account ID {:?} according to requirements", receiver_id)
539            }
540            InvalidTxError::InvalidSignature => {
541                write!(f, "Transaction is not signed with the given public key")
542            }
543            InvalidTxError::NotEnoughBalance { signer_id, balance, cost } => write!(
544                f,
545                "Sender {:?} does not have enough balance {} for operation costing {}",
546                signer_id, balance, cost
547            ),
548            InvalidTxError::LackBalanceForState { signer_id, amount } => {
549                write!(f, "Failed to execute, because the account {:?} wouldn't have enough balance to cover storage, required to have {} attoUNC more", signer_id, amount)
550            }
551            InvalidTxError::CostOverflow => {
552                write!(f, "Transaction gas or balance cost is too high")
553            }
554            InvalidTxError::InvalidChain => {
555                write!(f, "Transaction parent block hash doesn't belong to the current chain")
556            }
557            InvalidTxError::Expired => {
558                write!(f, "Transaction has expired")
559            }
560            InvalidTxError::ActionsValidation(error) => {
561                write!(f, "Transaction actions validation error: {}", error)
562            }
563            InvalidTxError::NonceTooLarge { tx_nonce, upper_bound } => {
564                write!(
565                    f,
566                    "Transaction nonce {} must be smaller than the access key nonce upper bound {}",
567                    tx_nonce, upper_bound
568                )
569            }
570            InvalidTxError::TransactionSizeExceeded { size, limit } => {
571                write!(f, "Size of serialized transaction {} exceeded the limit {}", size, limit)
572            }
573        }
574    }
575}
576
577impl From<InvalidAccessKeyError> for InvalidTxError {
578    fn from(error: InvalidAccessKeyError) -> Self {
579        InvalidTxError::InvalidAccessKeyError(error)
580    }
581}
582
583impl Display for InvalidAccessKeyError {
584    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
585        match self {
586            InvalidAccessKeyError::AccessKeyNotFound { account_id, public_key } => write!(
587                f,
588                "Signer {:?} doesn't have access key with the given public_key {}",
589                account_id, public_key
590            ),
591            InvalidAccessKeyError::ReceiverMismatch { tx_receiver, ak_receiver } => write!(
592                f,
593                "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}",
594                tx_receiver, ak_receiver
595            ),
596            InvalidAccessKeyError::MethodNameMismatch { method_name } => write!(
597                f,
598                "Transaction method name {:?} isn't allowed by the access key",
599                method_name
600            ),
601            InvalidAccessKeyError::RequiresFullAccess => {
602                write!(f, "Invalid access key type. Full-access keys are required for transactions that have multiple or non-function-call actions")
603            }
604            InvalidAccessKeyError::NotEnoughAllowance {
605                account_id,
606                public_key,
607                allowance,
608                cost,
609            } => write!(
610                f,
611                "Access Key {:?}:{} does not have enough balance {} for transaction costing {}",
612                account_id, public_key, allowance, cost
613            ),
614            InvalidAccessKeyError::DepositWithFunctionCall => {
615                write!(f, "Having a deposit with a function call action is not allowed with a function call access key.")
616            }
617        }
618    }
619}
620
621impl std::error::Error for InvalidAccessKeyError {}
622
623/// Happens when the input balance doesn't match the output balance in Runtime apply.
624#[derive(
625    BorshSerialize,
626    BorshDeserialize,
627    Debug,
628    Clone,
629    PartialEq,
630    Eq,
631    RpcError,
632    serde::Deserialize,
633    serde::Serialize,
634)]
635pub struct BalanceMismatchError {
636    // Input balances
637    #[serde(with = "dec_format")]
638    pub incoming_validator_rewards: Balance,
639    #[serde(with = "dec_format")]
640    pub initial_accounts_balance: Balance,
641    #[serde(with = "dec_format")]
642    pub incoming_receipts_balance: Balance,
643    #[serde(with = "dec_format")]
644    pub processed_delayed_receipts_balance: Balance,
645    #[serde(with = "dec_format")]
646    pub initial_postponed_receipts_balance: Balance,
647    // Output balances
648    #[serde(with = "dec_format")]
649    pub final_accounts_balance: Balance,
650    #[serde(with = "dec_format")]
651    pub outgoing_receipts_balance: Balance,
652    #[serde(with = "dec_format")]
653    pub new_delayed_receipts_balance: Balance,
654    #[serde(with = "dec_format")]
655    pub final_postponed_receipts_balance: Balance,
656    #[serde(with = "dec_format")]
657    pub tx_burnt_amount: Balance,
658    #[serde(with = "dec_format")]
659    pub slashed_burnt_amount: Balance,
660    #[serde(with = "dec_format")]
661    pub other_burnt_amount: Balance,
662}
663
664impl Display for BalanceMismatchError {
665    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
666        // Using saturating add to avoid overflow in display
667        let initial_balance = self
668            .incoming_validator_rewards
669            .saturating_add(self.initial_accounts_balance)
670            .saturating_add(self.incoming_receipts_balance)
671            .saturating_add(self.processed_delayed_receipts_balance)
672            .saturating_add(self.initial_postponed_receipts_balance);
673        let final_balance = self
674            .final_accounts_balance
675            .saturating_add(self.outgoing_receipts_balance)
676            .saturating_add(self.new_delayed_receipts_balance)
677            .saturating_add(self.final_postponed_receipts_balance)
678            .saturating_add(self.tx_burnt_amount)
679            .saturating_add(self.slashed_burnt_amount)
680            .saturating_add(self.other_burnt_amount);
681        write!(
682            f,
683            "Balance Mismatch Error. The input balance {} doesn't match output balance {}\n\
684             Inputs:\n\
685             \tIncoming validator rewards sum: {}\n\
686             \tInitial accounts balance sum: {}\n\
687             \tIncoming receipts balance sum: {}\n\
688             \tProcessed delayed receipts balance sum: {}\n\
689             \tInitial postponed receipts balance sum: {}\n\
690             Outputs:\n\
691             \tFinal accounts balance sum: {}\n\
692             \tOutgoing receipts balance sum: {}\n\
693             \tNew delayed receipts balance sum: {}\n\
694             \tFinal postponed receipts balance sum: {}\n\
695             \tTx fees burnt amount: {}\n\
696             \tSlashed amount: {}\n\
697             \tOther burnt amount: {}",
698            initial_balance,
699            final_balance,
700            self.incoming_validator_rewards,
701            self.initial_accounts_balance,
702            self.incoming_receipts_balance,
703            self.processed_delayed_receipts_balance,
704            self.initial_postponed_receipts_balance,
705            self.final_accounts_balance,
706            self.outgoing_receipts_balance,
707            self.new_delayed_receipts_balance,
708            self.final_postponed_receipts_balance,
709            self.tx_burnt_amount,
710            self.slashed_burnt_amount,
711            self.other_burnt_amount,
712        )
713    }
714}
715
716impl std::error::Error for BalanceMismatchError {}
717
718#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)]
719pub struct IntegerOverflowError;
720
721impl std::fmt::Display for IntegerOverflowError {
722    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
723        f.write_str(&format!("{:?}", self))
724    }
725}
726
727impl std::error::Error for IntegerOverflowError {}
728
729impl From<IntegerOverflowError> for InvalidTxError {
730    fn from(_: IntegerOverflowError) -> Self {
731        InvalidTxError::CostOverflow
732    }
733}
734
735impl From<IntegerOverflowError> for RuntimeError {
736    fn from(_: IntegerOverflowError) -> Self {
737        RuntimeError::UnexpectedIntegerOverflow
738    }
739}
740
741impl From<StorageError> for RuntimeError {
742    fn from(e: StorageError) -> Self {
743        RuntimeError::StorageError(e)
744    }
745}
746
747impl From<BalanceMismatchError> for RuntimeError {
748    fn from(e: BalanceMismatchError) -> Self {
749        RuntimeError::BalanceMismatchError(Box::new(e))
750    }
751}
752
753impl From<InvalidTxError> for RuntimeError {
754    fn from(e: InvalidTxError) -> Self {
755        RuntimeError::InvalidTxError(e)
756    }
757}
758
759impl From<EpochError> for RuntimeError {
760    fn from(e: EpochError) -> Self {
761        RuntimeError::ValidatorError(e)
762    }
763}
764
765impl Display for ActionError {
766    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
767        write!(f, "Action #{}: {}", self.index.unwrap_or_default(), self.kind)
768    }
769}
770
771impl Display for ActionErrorKind {
772    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
773        match self {
774            ActionErrorKind::AccountAlreadyExists { account_id } => {
775                write!(f, "Can't create a new account {:?}, because it already exists", account_id)
776            }
777            ActionErrorKind::AccountDoesNotExist { account_id } => write!(
778                f,
779                "Can't complete the action because account {:?} doesn't exist",
780                account_id
781            ),
782            ActionErrorKind::ActorNoPermission { actor_id, account_id } => write!(
783                f,
784                "Actor {:?} doesn't have permission to account {:?} to complete the action",
785                actor_id, account_id
786            ),
787            ActionErrorKind::LackBalanceForState { account_id, amount } => write!(
788                f,
789                "The account {} wouldn't have enough balance to cover storage, required to have {} attoUNC more",
790                account_id, amount
791            ),
792            ActionErrorKind::TriesToUnpledge { account_id } => {
793                write!(f, "Account {:?} is not yet pledging, but tries to unpledge", account_id)
794            }
795            ActionErrorKind::TriesToPledge { account_id, pledge, pledging, balance } => write!(
796                f,
797                "Account {:?} tries to pledge {}, but has pledging {} and only has {}",
798                account_id, pledge, pledging, balance
799            ),
800            ActionErrorKind::CreateAccountNotAllowed { account_id, predecessor_id } => write!(
801                f,
802                "A sub-account ID {:?} can't be created by account {:?}",
803                account_id, predecessor_id,
804            ),
805            ActionErrorKind::DeleteKeyDoesNotExist { account_id, .. } => write!(
806                f,
807                "Account {:?} tries to remove an access key that doesn't exist",
808                account_id
809            ),
810            ActionErrorKind::AddKeyAlreadyExists { public_key, .. } => write!(
811                f,
812                "The public key {:?} is already used for an existing access key",
813                public_key
814            ),
815            ActionErrorKind::DeleteAccountPledging{ account_id } => {
816                write!(f, "Account {:?} is staking and can not be deleted", account_id)
817            }
818            ActionErrorKind::FunctionCallError(s) => write!(f, "{:?}", s),
819            ActionErrorKind::NewReceiptValidationError(e) => {
820                write!(f, "An new action receipt created during a FunctionCall is not valid: {}", e)
821            }
822            ActionErrorKind::InsufficientPledge { account_id, pledge, minimum_pledge } => write!(f, "Account {} tries to pledge {} but minimum required pledge is {}", account_id, pledge, minimum_pledge),
823            ActionErrorKind::OnlyImplicitAccountCreationAllowed { account_id } => write!(f, "CreateAccount action is called on hex-characters account of length 64 {}", account_id),
824            ActionErrorKind::DeleteAccountWithLargeState { account_id } => write!(f, "The state of account {} is too large and therefore cannot be deleted", account_id),
825            ActionErrorKind::DelegateActionInvalidSignature => write!(f, "DelegateAction is not signed with the given public key"),
826            ActionErrorKind::DelegateActionSenderDoesNotMatchTxReceiver { sender_id, receiver_id } => write!(f, "Transaction receiver {} doesn't match DelegateAction sender {}", receiver_id, sender_id),
827            ActionErrorKind::DelegateActionExpired => write!(f, "DelegateAction has expired"),
828            ActionErrorKind::DelegateActionAccessKeyError(access_key_error) => Display::fmt(&access_key_error, f),
829            ActionErrorKind::DelegateActionInvalidNonce { delegate_nonce, ak_nonce } => write!(f, "DelegateAction nonce {} must be larger than nonce of the used access key {}", delegate_nonce, ak_nonce),
830            ActionErrorKind::DelegateActionNonceTooLarge { delegate_nonce, upper_bound } => write!(f, "DelegateAction nonce {} must be smaller than the access key nonce upper bound {}", delegate_nonce, upper_bound),
831            ActionErrorKind::RsaKeysNotFound { public_key, .. } => write!(
832                f,
833                "The public key {:?} is doesn't exist rsa key",
834                public_key
835            ),
836        }
837    }
838}
839#[derive(Eq, PartialEq, Clone)]
840pub enum BlockError {
841    /// Error calculating threshold from given pledges for given number of seats.
842    /// Only should happened if calling code doesn't check for integer value of pledge > number of seats.
843    ThresholdError {
844        pledge_sum: Balance,
845        num_seats: u64,
846    },
847    /// Requesting validators for an epoch that wasn't computed yet.
848    BlockOutOfBounds(CryptoHash),
849    /// Missing block hash in the storage (means there is some structural issue).
850    MissingBlock(CryptoHash),
851    /// Error due to IO (DB read/write, serialization, etc.).
852    IOErr(String),
853    /// Given account ID is not a validator in the given block height.
854    NotAValidator(AccountId, BlockHeight),
855    /// Error getting information for a shard
856    ShardingError(String),
857    NotEnoughValidators {
858        num_validators: u64,
859        num_shards: u64,
860    },
861    /// Error selecting validators for a chunk.
862    ChunkValidatorSelectionError(String),
863    /// ValidatorTotalPowerError
864    ValidatorTotalPowerError(String),
865    /// NoAvailableValidator
866    NoAvailableValidator(String),
867}
868
869impl std::error::Error for crate::errors::BlockError {}
870
871impl Display for crate::errors::BlockError {
872    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
873        match self {
874            crate::errors::BlockError::ThresholdError { pledge_sum, num_seats } => write!(
875                f,
876                "Total pledge {} must be higher than the number of seats {}",
877                pledge_sum, num_seats
878            ),
879            crate::errors::BlockError::BlockOutOfBounds(block_height) => {
880                write!(f, "Block {:?} is out of bounds", block_height)
881            }
882            crate::errors::BlockError::MissingBlock(hash) => write!(f, "Missing block {}", hash),
883            crate::errors::BlockError::IOErr(err) => write!(f, "IO: {}", err),
884            crate::errors::BlockError::NotAValidator(account_id, block_height) => {
885                write!(f, "{} is not a validator in epoch {:?}", account_id, block_height)
886            }
887            crate::errors::BlockError::ShardingError(err) => write!(f, "Sharding Error: {}", err),
888            crate::errors::BlockError::NotEnoughValidators { num_shards, num_validators } => {
889                write!(f, "There were not enough validator proposals to fill all shards. num_proposals: {}, num_shards: {}", num_validators, num_shards)
890            }
891            crate::errors::BlockError::ChunkValidatorSelectionError(err) => {
892                write!(f, "Error selecting validators for a chunk: {}", err)
893            }
894            crate::errors::BlockError::ValidatorTotalPowerError(err) => {
895                write!(f, "Error when computing total power: {}", err)
896            }
897            crate::errors::BlockError::NoAvailableValidator(err) => {
898                write!(f, "Error selecting produce: {}", err)
899            }
900        }
901    }
902}
903
904impl Debug for crate::errors::BlockError {
905    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
906        match self {
907            crate::errors::BlockError::ThresholdError { pledge_sum, num_seats } => {
908                write!(f, "ThresholdError({}, {})", pledge_sum, num_seats)
909            }
910            crate::errors::BlockError::BlockOutOfBounds(block_height) => {
911                write!(f, "EpochOutOfBounds({:?})", block_height)
912            }
913            crate::errors::BlockError::MissingBlock(hash) => write!(f, "MissingBlock({})", hash),
914            crate::errors::BlockError::IOErr(err) => write!(f, "IOErr({})", err),
915            crate::errors::BlockError::NotAValidator(account_id, block_height) => {
916                write!(f, "NotAValidator({}, {:?})", account_id, block_height)
917            }
918            crate::errors::BlockError::ShardingError(err) => write!(f, "ShardingError({})", err),
919            crate::errors::BlockError::NotEnoughValidators { num_shards, num_validators } => {
920                write!(f, "NotEnoughValidators({}, {})", num_validators, num_shards)
921            }
922            crate::errors::BlockError::ChunkValidatorSelectionError(err) => {
923                write!(f, "ChunkValidatorSelectionError({})", err)
924            }
925            crate::errors::BlockError::ValidatorTotalPowerError(err) => {
926                write!(f, "Error when computing total power: {}", err)
927            }
928            crate::errors::BlockError::NoAvailableValidator(err) => {
929                write!(f, "Error selecting produce: {}", err)
930            }
931        }
932    }
933}
934
935impl From<std::io::Error> for crate::errors::BlockError {
936    fn from(error: std::io::Error) -> Self {
937        crate::errors::BlockError::IOErr(error.to_string())
938    }
939}
940
941impl From<EpochError> for BlockError {
942    fn from(error: EpochError) -> Self {
943        match error {
944            EpochError::IOErr(..) => BlockError::IOErr(error.to_string()),
945            EpochError::ChunkValidatorSelectionError(..) => {
946                BlockError::ChunkValidatorSelectionError(error.to_string())
947            }
948            EpochError::EpochOutOfBounds(..) => BlockError::BlockOutOfBounds(CryptoHash::default()),
949            EpochError::MissingBlock(block_hash) => BlockError::MissingBlock(block_hash),
950            EpochError::NotAValidator(account_id, _hash) => {
951                BlockError::NotAValidator(account_id, 0)
952            }
953            EpochError::NotEnoughValidators { num_validators: x, num_shards: y } => {
954                BlockError::NotEnoughValidators { num_validators: x, num_shards: y }
955            }
956            EpochError::ShardingError(..) => BlockError::ShardingError(error.to_string()),
957            EpochError::ThresholdError { pledge_sum: pledge, num_seats: seats } => {
958                BlockError::ThresholdError { pledge_sum: pledge, num_seats: seats }
959            }
960        }
961    }
962}
963#[derive(Eq, PartialEq, Clone)]
964pub enum EpochError {
965    /// Error calculating threshold from given pledges for given number of seats.
966    /// Only should happened if calling code doesn't check for integer value of pledge > number of seats.
967    ThresholdError {
968        pledge_sum: Balance,
969        num_seats: u64,
970    },
971    /// Requesting validators for an epoch that wasn't computed yet.
972    EpochOutOfBounds(EpochId),
973    /// Missing block hash in the storage (means there is some structural issue).
974    MissingBlock(CryptoHash),
975    /// Error due to IO (DB read/write, serialization, etc.).
976    IOErr(String),
977    /// Given account ID is not a validator in the given epoch ID.
978    NotAValidator(AccountId, EpochId),
979    /// Error getting information for a shard
980    ShardingError(String),
981    NotEnoughValidators {
982        num_validators: u64,
983        num_shards: u64,
984    },
985    /// Error selecting validators for a chunk.
986    ChunkValidatorSelectionError(String),
987}
988
989impl std::error::Error for EpochError {}
990
991impl Display for EpochError {
992    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
993        match self {
994            EpochError::ThresholdError { pledge_sum, num_seats } => write!(
995                f,
996                "Total pledge {} must be higher than the number of seats {}",
997                pledge_sum, num_seats
998            ),
999            EpochError::EpochOutOfBounds(epoch_id) => {
1000                write!(f, "Epoch {:?} is out of bounds", epoch_id)
1001            }
1002            EpochError::MissingBlock(hash) => write!(f, "Missing block {}", hash),
1003            EpochError::IOErr(err) => write!(f, "IO: {}", err),
1004            EpochError::NotAValidator(account_id, epoch_id) => {
1005                write!(f, "{} is not a validator in epoch {:?}", account_id, epoch_id)
1006            }
1007            EpochError::ShardingError(err) => write!(f, "Sharding Error: {}", err),
1008            EpochError::NotEnoughValidators { num_shards, num_validators } => {
1009                write!(f, "There were not enough validator proposals to fill all shards. num_proposals: {}, num_shards: {}", num_validators, num_shards)
1010            }
1011            EpochError::ChunkValidatorSelectionError(err) => {
1012                write!(f, "Error selecting validators for a chunk: {}", err)
1013            }
1014        }
1015    }
1016}
1017
1018impl Debug for EpochError {
1019    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1020        match self {
1021            EpochError::ThresholdError { pledge_sum, num_seats } => {
1022                write!(f, "ThresholdError({}, {})", pledge_sum, num_seats)
1023            }
1024            EpochError::EpochOutOfBounds(epoch_id) => write!(f, "EpochOutOfBounds({:?})", epoch_id),
1025            EpochError::MissingBlock(hash) => write!(f, "MissingBlock({})", hash),
1026            EpochError::IOErr(err) => write!(f, "IOErr({})", err),
1027            EpochError::NotAValidator(account_id, epoch_id) => {
1028                write!(f, "NotAValidator({}, {:?})", account_id, epoch_id)
1029            }
1030            EpochError::ShardingError(err) => write!(f, "ShardingError({})", err),
1031            EpochError::NotEnoughValidators { num_shards, num_validators } => {
1032                write!(f, "NotEnoughValidators({}, {})", num_validators, num_shards)
1033            }
1034            EpochError::ChunkValidatorSelectionError(err) => {
1035                write!(f, "ChunkValidatorSelectionError({})", err)
1036            }
1037        }
1038    }
1039}
1040
1041impl From<std::io::Error> for EpochError {
1042    fn from(error: std::io::Error) -> Self {
1043        EpochError::IOErr(error.to_string())
1044    }
1045}
1046
1047impl From<BlockError> for EpochError {
1048    fn from(error: BlockError) -> Self {
1049        match error {
1050            BlockError::IOErr(..) => EpochError::IOErr(error.to_string()),
1051            BlockError::ChunkValidatorSelectionError(..) => {
1052                EpochError::ChunkValidatorSelectionError(error.to_string())
1053            }
1054            BlockError::BlockOutOfBounds(..) => EpochError::EpochOutOfBounds(EpochId::default()),
1055            BlockError::MissingBlock(block_hash) => EpochError::MissingBlock(block_hash),
1056            BlockError::NotAValidator(account_id, _block_height) => {
1057                EpochError::NotAValidator(account_id, EpochId::default())
1058            }
1059            BlockError::NotEnoughValidators { num_validators: x, num_shards: y } => {
1060                EpochError::NotEnoughValidators { num_validators: x, num_shards: y }
1061            }
1062            BlockError::ShardingError(..) => EpochError::ShardingError(error.to_string()),
1063            BlockError::ThresholdError { pledge_sum: pledge, num_seats: seats } => {
1064                EpochError::ThresholdError { pledge_sum: pledge, num_seats: seats }
1065            }
1066            BlockError::ValidatorTotalPowerError(..) => EpochError::IOErr(error.to_string()),
1067            BlockError::NoAvailableValidator(..) => EpochError::IOErr(error.to_string()),
1068        }
1069    }
1070}
1071
1072#[derive(
1073    Debug,
1074    Clone,
1075    PartialEq,
1076    Eq,
1077    BorshDeserialize,
1078    BorshSerialize,
1079    RpcError,
1080    serde::Deserialize,
1081    serde::Serialize,
1082)]
1083/// Error that can occur while preparing or executing Wasm smart-contract.
1084pub enum PrepareError {
1085    /// Error happened while serializing the module.
1086    Serialization,
1087    /// Error happened while deserializing the module.
1088    Deserialization,
1089    /// Internal memory declaration has been found in the module.
1090    InternalMemoryDeclared,
1091    /// Gas instrumentation failed.
1092    ///
1093    /// This most likely indicates the module isn't valid.
1094    GasInstrumentation,
1095    /// Stack instrumentation failed.
1096    ///
1097    /// This  most likely indicates the module isn't valid.
1098    StackHeightInstrumentation,
1099    /// Error happened during instantiation.
1100    ///
1101    /// This might indicate that `start` function trapped, or module isn't
1102    /// instantiable and/or unlinkable.
1103    Instantiate,
1104    /// Error creating memory.
1105    Memory,
1106    /// Contract contains too many functions.
1107    TooManyFunctions,
1108    /// Contract contains too many locals.
1109    TooManyLocals,
1110}
1111
1112/// A kind of a trap happened during execution of a binary
1113#[derive(
1114    Debug,
1115    Clone,
1116    PartialEq,
1117    Eq,
1118    BorshDeserialize,
1119    BorshSerialize,
1120    RpcError,
1121    serde::Deserialize,
1122    serde::Serialize,
1123    strum::IntoStaticStr,
1124)]
1125pub enum WasmTrap {
1126    /// An `unreachable` opcode was executed.
1127    Unreachable,
1128    /// Call indirect incorrect signature trap.
1129    IncorrectCallIndirectSignature,
1130    /// Memory out of bounds trap.
1131    MemoryOutOfBounds,
1132    /// Call indirect out of bounds trap.
1133    CallIndirectOOB,
1134    /// An arithmetic exception, e.g. divided by zero.
1135    IllegalArithmetic,
1136    /// Misaligned atomic access trap.
1137    MisalignedAtomicAccess,
1138    /// Indirect call to null.
1139    IndirectCallToNull,
1140    /// Stack overflow.
1141    StackOverflow,
1142    /// Generic trap.
1143    GenericTrap,
1144}
1145
1146#[derive(
1147    Debug,
1148    Clone,
1149    PartialEq,
1150    Eq,
1151    BorshDeserialize,
1152    BorshSerialize,
1153    RpcError,
1154    serde::Deserialize,
1155    serde::Serialize,
1156    strum::IntoStaticStr,
1157)]
1158pub enum HostError {
1159    /// String encoding is bad UTF-16 sequence
1160    BadUTF16,
1161    /// String encoding is bad UTF-8 sequence
1162    BadUTF8,
1163    /// Exceeded the prepaid gas
1164    GasExceeded,
1165    /// Exceeded the maximum amount of gas allowed to burn per contract
1166    GasLimitExceeded,
1167    /// Exceeded the account balance
1168    BalanceExceeded,
1169    /// Tried to call an empty method name
1170    EmptyMethodName,
1171    /// Smart contract panicked
1172    GuestPanic { panic_msg: String },
1173    /// IntegerOverflow happened during a contract execution
1174    IntegerOverflow,
1175    /// `promise_idx` does not correspond to existing promises
1176    InvalidPromiseIndex { promise_idx: u64 },
1177    /// Actions can only be appended to non-joint promise.
1178    CannotAppendActionToJointPromise,
1179    /// Returning joint promise is currently prohibited
1180    CannotReturnJointPromise,
1181    /// Accessed invalid promise result index
1182    InvalidPromiseResultIndex { result_idx: u64 },
1183    /// Accessed invalid register id
1184    InvalidRegisterId { register_id: u64 },
1185    /// Iterator `iterator_index` was invalidated after its creation by performing a mutable operation on trie
1186    IteratorWasInvalidated { iterator_index: u64 },
1187    /// Accessed memory outside the bounds
1188    MemoryAccessViolation,
1189    /// VM Logic returned an invalid receipt index
1190    InvalidReceiptIndex { receipt_index: u64 },
1191    /// Iterator index `iterator_index` does not exist
1192    InvalidIteratorIndex { iterator_index: u64 },
1193    /// VM Logic returned an invalid account id
1194    InvalidAccountId,
1195    /// VM Logic returned an invalid method name
1196    InvalidMethodName,
1197    /// VM Logic provided an invalid public key
1198    InvalidPublicKey,
1199    /// `method_name` is not allowed in view calls
1200    ProhibitedInView { method_name: String },
1201    /// The total number of logs will exceed the limit.
1202    NumberOfLogsExceeded { limit: u64 },
1203    /// The storage key length exceeded the limit.
1204    KeyLengthExceeded { length: u64, limit: u64 },
1205    /// The storage value length exceeded the limit.
1206    ValueLengthExceeded { length: u64, limit: u64 },
1207    /// The total log length exceeded the limit.
1208    TotalLogLengthExceeded { length: u64, limit: u64 },
1209    /// The maximum number of promises within a FunctionCall exceeded the limit.
1210    NumberPromisesExceeded { number_of_promises: u64, limit: u64 },
1211    /// The maximum number of input data dependencies exceeded the limit.
1212    NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 },
1213    /// The returned value length exceeded the limit.
1214    ReturnedValueLengthExceeded { length: u64, limit: u64 },
1215    /// The contract size for DeployContract action exceeded the limit.
1216    ContractSizeExceeded { size: u64, limit: u64 },
1217    /// The host function was deprecated.
1218    Deprecated { method_name: String },
1219    /// General errors for ECDSA recover.
1220    ECRecoverError { msg: String },
1221    /// Invalid input to alt_bn128 familiy of functions (e.g., point which isn't
1222    /// on the curve).
1223    AltBn128InvalidInput { msg: String },
1224    /// Invalid input to ed25519 signature verification function (e.g. signature cannot be
1225    /// derived from bytes).
1226    Ed25519VerifyInvalidInput { msg: String },
1227}
1228
1229#[derive(
1230    Debug,
1231    Clone,
1232    PartialEq,
1233    Eq,
1234    BorshDeserialize,
1235    BorshSerialize,
1236    RpcError,
1237    serde::Deserialize,
1238    serde::Serialize,
1239    strum::IntoStaticStr,
1240)]
1241pub enum MethodResolveError {
1242    MethodEmptyName,
1243    MethodNotFound,
1244    MethodInvalidSignature,
1245}
1246
1247#[derive(
1248    Debug,
1249    Clone,
1250    PartialEq,
1251    Eq,
1252    BorshDeserialize,
1253    BorshSerialize,
1254    RpcError,
1255    serde::Deserialize,
1256    serde::Serialize,
1257    strum::IntoStaticStr,
1258)]
1259pub enum CompilationError {
1260    CodeDoesNotExist {
1261        account_id: AccountId,
1262    },
1263    PrepareError(PrepareError),
1264    /// This is for defense in depth.
1265    /// We expect our runtime-independent preparation code to fully catch all invalid wasms,
1266    /// but, if it ever misses something we’ll emit this error
1267    WasmerCompileError {
1268        msg: String,
1269    },
1270}
1271
1272/// Serializable version of `unc-vm-runner::FunctionCallError`.
1273///
1274/// Must never reorder/remove elements, can only add new variants at the end (but do that very
1275/// carefully). It describes stable serialization format, and only used by serialization logic.
1276#[derive(
1277    Debug,
1278    Clone,
1279    PartialEq,
1280    Eq,
1281    BorshDeserialize,
1282    BorshSerialize,
1283    serde::Serialize,
1284    serde::Deserialize,
1285)]
1286pub enum FunctionCallError {
1287    /// Wasm compilation error
1288    CompilationError(CompilationError),
1289    /// Wasm binary env link error
1290    ///
1291    /// Note: this is only to deserialize old data, use execution error for new data
1292    LinkError {
1293        msg: String,
1294    },
1295    /// Import/export resolve error
1296    MethodResolveError(MethodResolveError),
1297    /// A trap happened during execution of a binary
1298    ///
1299    /// Note: this is only to deserialize old data, use execution error for new data
1300    WasmTrap(WasmTrap),
1301    WasmUnknownError,
1302    /// Note: this is only to deserialize old data, use execution error for new data
1303    HostError(HostError),
1304    // Unused, can be reused by a future error but must be exactly one error to keep ExecutionError
1305    // error borsh serialized at correct index
1306    _EVMError,
1307    ExecutionError(String),
1308}
1309
1310impl From<unc_vm_runner::logic::errors::MethodResolveError> for MethodResolveError {
1311    fn from(outer_err: unc_vm_runner::logic::errors::MethodResolveError) -> Self {
1312        use unc_vm_runner::logic::errors::MethodResolveError as MRE;
1313        match outer_err {
1314            MRE::MethodEmptyName => Self::MethodEmptyName,
1315            MRE::MethodNotFound => Self::MethodNotFound,
1316            MRE::MethodInvalidSignature => Self::MethodInvalidSignature,
1317        }
1318    }
1319}
1320
1321impl From<unc_vm_runner::logic::errors::PrepareError> for PrepareError {
1322    fn from(outer_err: unc_vm_runner::logic::errors::PrepareError) -> Self {
1323        use unc_vm_runner::logic::errors::PrepareError as PE;
1324        match outer_err {
1325            PE::Serialization => Self::Serialization,
1326            PE::Deserialization => Self::Deserialization,
1327            PE::InternalMemoryDeclared => Self::InternalMemoryDeclared,
1328            PE::GasInstrumentation => Self::GasInstrumentation,
1329            PE::StackHeightInstrumentation => Self::StackHeightInstrumentation,
1330            PE::Instantiate => Self::Instantiate,
1331            PE::Memory => Self::Memory,
1332            PE::TooManyFunctions => Self::TooManyFunctions,
1333            PE::TooManyLocals => Self::TooManyLocals,
1334        }
1335    }
1336}
1337
1338impl From<unc_vm_runner::logic::errors::CompilationError> for CompilationError {
1339    fn from(outer_err: unc_vm_runner::logic::errors::CompilationError) -> Self {
1340        use unc_vm_runner::logic::errors::CompilationError as CE;
1341        match outer_err {
1342            CE::CodeDoesNotExist { account_id } => Self::CodeDoesNotExist {
1343                account_id: account_id.parse().expect("account_id in error must be valid"),
1344            },
1345            CE::PrepareError(pe) => Self::PrepareError(pe.into()),
1346            CE::WasmerCompileError { msg } => Self::WasmerCompileError { msg },
1347        }
1348    }
1349}
1350
1351impl From<unc_vm_runner::logic::errors::FunctionCallError> for FunctionCallError {
1352    fn from(outer_err: unc_vm_runner::logic::errors::FunctionCallError) -> Self {
1353        use unc_vm_runner::logic::errors::FunctionCallError as FCE;
1354        match outer_err {
1355            FCE::CompilationError(e) => Self::CompilationError(e.into()),
1356            FCE::MethodResolveError(e) => Self::MethodResolveError(e.into()),
1357            // Note: We deliberately collapse all execution errors for
1358            // serialization to make the DB representation less dependent
1359            // on specific types in Rust code.
1360            FCE::HostError(ref _e) => Self::ExecutionError(outer_err.to_string()),
1361            FCE::LinkError { msg } => Self::ExecutionError(format!("Link Error: {}", msg)),
1362            FCE::WasmTrap(ref _e) => Self::ExecutionError(outer_err.to_string()),
1363        }
1364    }
1365}
1366
1367#[cfg(feature = "new_epoch_sync")]
1368pub mod epoch_sync {
1369    use std::fmt::Debug;
1370    use unc_primitives_core::hash::CryptoHash;
1371    use unc_primitives_core::types::EpochHeight;
1372
1373    #[derive(Eq, PartialEq, Clone, strum::Display, Debug)]
1374    pub enum EpochSyncHashType {
1375        LastEpochBlock,
1376        LastFinalBlock,
1377        FirstEpochBlock,
1378        NextEpochFirstBlock,
1379        Other,
1380        BlockToSave,
1381    }
1382
1383    #[derive(Eq, PartialEq, Clone, thiserror::Error, Debug)]
1384    pub enum EpochSyncInfoError {
1385        #[error("{hash_type} hash {hash:?} not a part of EpochSyncInfo for epoch {epoch_height}")]
1386        HashNotFound { hash: CryptoHash, hash_type: EpochSyncHashType, epoch_height: EpochHeight },
1387        #[error("all_block_hashes.len() < 2 for epoch {epoch_height}")]
1388        ShortEpoch { epoch_height: EpochHeight },
1389    }
1390}