From 775c141747d19db8abe0f8d207556227c3b38d31 Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 12 Dec 2019 13:43:17 +0300 Subject: [PATCH 01/48] use VMError instead of String in FunctionCall error --- Cargo.lock | 4 +++ core/primitives/Cargo.toml | 1 + core/primitives/src/errors.rs | 6 ++-- runtime/near-vm-errors/Cargo.toml | 1 + runtime/near-vm-errors/src/lib.rs | 41 ++++++++++++++-------------- runtime/near-vm-runner/src/errors.rs | 24 ++++++++-------- runtime/near-vm-runner/src/runner.rs | 10 +++---- runtime/runtime/src/actions.rs | 11 ++++---- 8 files changed, 53 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7ac96b6220..830989fbf1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2300,6 +2300,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "near-crypto 0.1.0", + "near-vm-errors 0.4.0", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "reed-solomon-erasure 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2351,6 +2352,9 @@ dependencies = [ [[package]] name = "near-vm-errors" version = "0.4.0" +dependencies = [ + "borsh 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "near-vm-logic" diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index 9f7306062e2..e998913c8a4 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -26,6 +26,7 @@ actix = "0.8.1" borsh = "0.2.10" near-crypto = { path = "../crypto" } +near-vm-errors = { path = "../../runtime/near-vm-errors" } [features] default = ["jemallocator"] diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 2eb66f05a9b..0f93086e9a4 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -1,6 +1,8 @@ use crate::types::{AccountId, Balance, Nonce}; use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::PublicKey; +// TODO: looks like in this crate we're trying to avoid inner deps, but I can't find a better solution so far +use near_vm_errors::VMError; use std::fmt::Display; /// Internal @@ -64,7 +66,7 @@ pub enum ActionError { RentUnpaid(AccountId, Balance), TriesToUnstake(AccountId), TriesToStake(AccountId, Balance, Balance, Balance), - FunctionCallError(String), // TODO type + FunctionCallError(VMError), } impl Display for InvalidTxError { @@ -316,7 +318,7 @@ impl Display for ActionError { "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", account_id, balance ), - ActionError::FunctionCallError(s) => write!(f, "{}", s), + ActionError::FunctionCallError(s) => write!(f, "FunctionCall action error: {}", s), } } } diff --git a/runtime/near-vm-errors/Cargo.toml b/runtime/near-vm-errors/Cargo.toml index f14dbfea2e7..fdafa67aaff 100644 --- a/runtime/near-vm-errors/Cargo.toml +++ b/runtime/near-vm-errors/Cargo.toml @@ -13,3 +13,4 @@ Error that can occur inside Near Runtime encapsulated in a separate crate. Might """ [dependencies] +borsh = "0.2.10" diff --git a/runtime/near-vm-errors/src/lib.rs b/runtime/near-vm-errors/src/lib.rs index 014ec376f11..ad8f75f3299 100644 --- a/runtime/near-vm-errors/src/lib.rs +++ b/runtime/near-vm-errors/src/lib.rs @@ -1,13 +1,14 @@ +use borsh::{BorshDeserialize, BorshSerialize}; use std::fmt; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] pub enum VMError { - FunctionCallError(FunctionCallError), + FunctionExecError(FunctionExecError), StorageError(Vec), } -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum FunctionCallError { +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +pub enum FunctionExecError { CompilationError(CompilationError), LinkError(String), ResolveError(MethodResolveError), @@ -15,7 +16,7 @@ pub enum FunctionCallError { HostError(HostError), } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] pub enum MethodResolveError { MethodEmptyName, MethodUTF8Error, @@ -23,14 +24,14 @@ pub enum MethodResolveError { MethodInvalidSignature, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] pub enum CompilationError { CodeDoesNotExist(String), PrepareError(PrepareError), WasmerCompileError(String), } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] /// Error that can occur while preparing or executing Wasm smart-contract. pub enum PrepareError { /// Error happened while serializing the module. @@ -62,7 +63,7 @@ pub enum PrepareError { Memory, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] pub enum HostError { BadUTF16, BadUTF8, @@ -87,7 +88,7 @@ pub enum HostError { ProhibitedInView(String), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize)] pub enum HostErrorOrStorageError { HostError(HostError), /// Error from underlying storage, serialized @@ -102,7 +103,7 @@ impl From for HostErrorOrStorageError { impl From for VMError { fn from(err: PrepareError) -> Self { - VMError::FunctionCallError(FunctionCallError::CompilationError( + VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(err), )) } @@ -125,14 +126,14 @@ impl fmt::Display for PrepareError { } } -impl fmt::Display for FunctionCallError { +impl fmt::Display for FunctionExecError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - FunctionCallError::CompilationError(e) => e.fmt(f), - FunctionCallError::ResolveError(e) => e.fmt(f), - FunctionCallError::HostError(e) => e.fmt(f), - FunctionCallError::LinkError(s) => write!(f, "{}", s), - FunctionCallError::WasmTrap(s) => write!(f, "WebAssembly trap: {}", s), + FunctionExecError::CompilationError(e) => e.fmt(f), + FunctionExecError::ResolveError(e) => e.fmt(f), + FunctionExecError::HostError(e) => e.fmt(f), + FunctionExecError::LinkError(s) => write!(f, "{}", s), + FunctionExecError::WasmTrap(s) => write!(f, "WebAssembly trap: {}", s), } } } @@ -158,7 +159,7 @@ impl fmt::Display for MethodResolveError { impl fmt::Display for VMError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - VMError::FunctionCallError(err) => fmt::Display::fmt(err, f), + VMError::FunctionExecError(err) => fmt::Display::fmt(err, f), VMError::StorageError(_err) => write!(f, "StorageError"), } } @@ -195,20 +196,20 @@ impl std::fmt::Display for HostError { #[cfg(test)] mod tests { - use crate::{CompilationError, FunctionCallError, MethodResolveError, PrepareError, VMError}; + use crate::{CompilationError, FunctionExecError, MethodResolveError, PrepareError, VMError}; #[test] fn test_display() { // TODO: proper printing assert_eq!( - VMError::FunctionCallError(FunctionCallError::ResolveError( + VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodInvalidSignature )) .to_string(), "MethodInvalidSignature" ); assert_eq!( - VMError::FunctionCallError(FunctionCallError::CompilationError( + VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::StackHeightInstrumentation) )) .to_string(), diff --git a/runtime/near-vm-runner/src/errors.rs b/runtime/near-vm-runner/src/errors.rs index 34b604c76af..c189711f388 100644 --- a/runtime/near-vm-runner/src/errors.rs +++ b/runtime/near-vm-runner/src/errors.rs @@ -1,4 +1,4 @@ -use near_vm_errors::{CompilationError, FunctionCallError, MethodResolveError, VMError}; +use near_vm_errors::{CompilationError, FunctionExecError, MethodResolveError, VMError}; use near_vm_logic::HostErrorOrStorageError; pub trait IntoVMError { @@ -10,7 +10,7 @@ impl IntoVMError for wasmer_runtime::error::Error { use wasmer_runtime::error::Error; match self { Error::CompileError(err) => err.into_vm_error(), - Error::LinkError(err) => VMError::FunctionCallError(FunctionCallError::LinkError( + Error::LinkError(err) => VMError::FunctionExecError(FunctionExecError::LinkError( format!("{:.500}", Error::LinkError(err).to_string()), )), Error::RuntimeError(err) => err.into_vm_error(), @@ -33,7 +33,7 @@ impl IntoVMError for wasmer_runtime::error::CallError { impl IntoVMError for wasmer_runtime::error::CompileError { fn into_vm_error(self) -> VMError { - VMError::FunctionCallError(FunctionCallError::CompilationError( + VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::WasmerCompileError(self.to_string()), )) } @@ -43,14 +43,14 @@ impl IntoVMError for wasmer_runtime::error::ResolveError { fn into_vm_error(self) -> VMError { use wasmer_runtime::error::ResolveError as WasmerResolveError; match self { - WasmerResolveError::Signature { .. } => VMError::FunctionCallError( - FunctionCallError::ResolveError(MethodResolveError::MethodInvalidSignature), + WasmerResolveError::Signature { .. } => VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodInvalidSignature), ), - WasmerResolveError::ExportNotFound { .. } => VMError::FunctionCallError( - FunctionCallError::ResolveError(MethodResolveError::MethodNotFound), + WasmerResolveError::ExportNotFound { .. } => VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodNotFound), ), - WasmerResolveError::ExportWrongType { .. } => VMError::FunctionCallError( - FunctionCallError::ResolveError(MethodResolveError::MethodNotFound), + WasmerResolveError::ExportWrongType { .. } => VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodNotFound), ), } } @@ -61,7 +61,7 @@ impl IntoVMError for wasmer_runtime::error::RuntimeError { use wasmer_runtime::error::RuntimeError; match &self { RuntimeError::Trap { msg } => { - VMError::FunctionCallError(FunctionCallError::WasmTrap(msg.to_string())) + VMError::FunctionExecError(FunctionExecError::WasmTrap(msg.to_string())) } RuntimeError::Error { data } => { if let Some(err) = data.downcast_ref::() { @@ -70,7 +70,7 @@ impl IntoVMError for wasmer_runtime::error::RuntimeError { VMError::StorageError(s.clone()) } HostErrorOrStorageError::HostError(h) => { - VMError::FunctionCallError(FunctionCallError::HostError(h.clone())) + VMError::FunctionExecError(FunctionExecError::HostError(h.clone())) } } } else { @@ -79,7 +79,7 @@ impl IntoVMError for wasmer_runtime::error::RuntimeError { data.type_id(), self.to_string() ); - VMError::FunctionCallError(FunctionCallError::WasmTrap("unknown".to_string())) + VMError::FunctionExecError(FunctionExecError::WasmTrap("unknown".to_string())) } } } diff --git a/runtime/near-vm-runner/src/runner.rs b/runtime/near-vm-runner/src/runner.rs index be830cbb3fd..7cb0eefc654 100644 --- a/runtime/near-vm-runner/src/runner.rs +++ b/runtime/near-vm-runner/src/runner.rs @@ -2,7 +2,7 @@ use crate::errors::IntoVMError; use crate::memory::WasmerMemory; use crate::{cache, imports}; use near_runtime_fees::RuntimeFeesConfig; -use near_vm_errors::{FunctionCallError, MethodResolveError, VMError}; +use near_vm_errors::{FunctionExecError, MethodResolveError, VMError}; use near_vm_logic::types::PromiseResult; use near_vm_logic::{External, VMConfig, VMContext, VMLogic, VMOutcome}; use wasmer_runtime::Module; @@ -16,12 +16,12 @@ fn check_method(module: &Module, method_name: &str) -> Result<(), VMError> { if sig.params().is_empty() && sig.returns().is_empty() { Ok(()) } else { - Err(VMError::FunctionCallError(FunctionCallError::ResolveError( + Err(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodInvalidSignature, ))) } } else { - Err(VMError::FunctionCallError(FunctionCallError::ResolveError( + Err(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodNotFound, ))) } @@ -51,7 +51,7 @@ pub fn run<'a>( if method_name.is_empty() { return ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodEmptyName, ))), ); @@ -77,7 +77,7 @@ pub fn run<'a>( Err(_) => { return ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodUTF8Error, ))), ) diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index c8f7fa2c0b9..d03d292bacd 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -27,7 +27,7 @@ use crate::config::RuntimeConfig; use crate::ext::RuntimeExt; use crate::{ActionResult, ApplyState}; use near_primitives::errors::ActionError; -use near_vm_errors::{CompilationError, FunctionCallError}; +use near_vm_errors::{CompilationError, FunctionExecError}; use near_vm_runner::VMError; /// Number of epochs it takes to unstake. @@ -119,10 +119,10 @@ pub(crate) fn action_function_call( let code = match get_code_with_cache(state_update, account_id, &account) { Ok(Some(code)) => code, Ok(None) => { - let error = FunctionCallError::CompilationError(CompilationError::CodeDoesNotExist( - account_id.clone(), + let error = VMError::FunctionExecError(FunctionExecError::CompilationError( + CompilationError::CodeDoesNotExist(account_id.clone()), )); - result.result = Err(ActionError::FunctionCallError(error.to_string())); + result.result = Err(ActionError::FunctionCallError(error)); return Ok(()); } Err(e) => { @@ -179,8 +179,7 @@ pub(crate) fn action_function_call( borsh::BorshDeserialize::try_from_slice(&storage).expect("Borsh cannot fail"); return Err(err); } - // TODO(#1731): Handle VMError::FunctionCallError better. - result.result = Err(ActionError::FunctionCallError(err.to_string())); + result.result = Err(ActionError::FunctionCallError(err)); if let Some(outcome) = outcome { result.gas_burnt += outcome.burnt_gas; result.gas_burnt_for_function_call += outcome.burnt_gas; From 5f2226fa46ced1840eca5d873cca36eab3026090 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 18 Dec 2019 14:19:31 +0300 Subject: [PATCH 02/48] some progress on errors --- Cargo.lock | 2 + core/primitives/src/errors.rs | 331 ++++++++++-------- core/primitives/src/views.rs | 136 ++++--- runtime/near-vm-errors/Cargo.toml | 1 + runtime/near-vm-errors/src/lib.rs | 22 +- runtime/runtime/src/actions.rs | 67 ++-- runtime/runtime/src/lib.rs | 64 ++-- runtime/runtime/tests/test_evil_contracts.rs | 8 +- test-utils/testlib/Cargo.toml | 1 + test-utils/testlib/src/standard_test_cases.rs | 136 ++++--- 10 files changed, 424 insertions(+), 344 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 830989fbf1c..29f3232ca38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2354,6 +2354,7 @@ name = "near-vm-errors" version = "0.4.0" dependencies = [ "borsh 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3556,6 +3557,7 @@ dependencies = [ "near-primitives 0.1.0", "near-runtime-fees 0.4.0", "near-store 0.1.0", + "near-vm-errors 0.4.0", "node-runtime 0.0.1", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 0f93086e9a4..f0093d8e56a 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -1,12 +1,14 @@ +use crate::hash::CryptoHash; use crate::types::{AccountId, Balance, Nonce}; use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::PublicKey; // TODO: looks like in this crate we're trying to avoid inner deps, but I can't find a better solution so far -use near_vm_errors::VMError; +pub use near_vm_errors::VMError; + use std::fmt::Display; /// Internal -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub enum StorageError { /// Key-value db internal failure StorageInternalError, @@ -29,122 +31,199 @@ impl std::fmt::Display for StorageError { impl std::error::Error for StorageError {} /// External -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] -pub enum InvalidTxError { - InvalidSigner(AccountId), - SignerDoesNotExist(AccountId), - InvalidAccessKey(InvalidAccessKeyError), - InvalidNonce(Nonce, Nonce), - InvalidReceiver(AccountId), - InvalidSignature, - NotEnoughBalance(AccountId, Balance, Balance), - RentUnpaid(AccountId, Balance), +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +#[serde(tag = "type")] +pub struct InvalidTxError { + pub signer_id: AccountId, + pub public_key: PublicKey, + pub nonce: Nonce, + pub receiver_id: AccountId, + pub block_hash: CryptoHash, + pub kind: InvalidTxErrorKind, +} + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +pub enum InvalidTxErrorKind { + InvalidAccessKey(InvalidAccessKeyErrorKind), + Action(ActionError), + InvalidSigner, + SignerDoesNotExist, + InvalidNonce { + access_key_nonce: Nonce, + }, + InvalidReceiver, + NotEnoughBalance { + balance: Balance, + cost: Balance, + }, + RentUnpaid { + amount: Balance, + }, CostOverflow, InvalidChain, + InvalidSignature, Expired, + AccessKeyNotFound, + /// For this action the sender is required to be equal to the receiver + OwnershipError, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] -pub enum InvalidAccessKeyError { - AccessKeyNotFound(AccountId, PublicKey), - ReceiverMismatch(AccountId, AccountId), - MethodNameMismatch(String), +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +#[serde(tag = "type")] +pub enum InvalidAccessKeyErrorKind { + ReceiverMismatch { + tx_receiver_id: AccountId, + ak_receiver_id: AccountId, + }, + MethodNameMismatch { + method_name: String, + }, ActionError, - NotEnoughAllowance(AccountId, PublicKey, Balance, Balance), + NotEnoughAllowance { + signer_id: AccountId, + public_key: PublicKey, + allowed: Balance, + cost: Balance, + }, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] -pub enum ActionError { - AccountAlreadyExists(AccountId), - AccountDoesNotExist(String, AccountId), - CreateAccountNotAllowed(AccountId, AccountId), - ActorNoPermission(AccountId, AccountId, String), - DeleteKeyDoesNotExist(AccountId), - AddKeyAlreadyExists(PublicKey), - DeleteAccountStaking(AccountId), - DeleteAccountHasRent(AccountId, Balance), - RentUnpaid(AccountId, Balance), - TriesToUnstake(AccountId), - TriesToStake(AccountId, Balance, Balance, Balance), - FunctionCallError(VMError), +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +pub struct ActionError { + // position of a failed action in the transaction/receipt + index: u64, + kind: ActionErrorKind, +} + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] +pub enum ActionErrorKind { + AccountAlreadyExists, + AccountDoesNotExist { action: String }, + CreateAccountNotAllowed, + ActorNoPermission { actor_id, action: String }, + DeleteKeyDoesNotExist { public_key: PublicKey }, + AddKeyAlreadyExists { public_key: PublicKey }, + DeleteAccountStaking, + DeleteAccountHasRent { amount: Balance }, + TriesToUnstake, + TriesToStake { stake: Balance, staked: Balance, amount: Balance }, + FunctionCall(VMError), } impl Display for InvalidTxError { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - InvalidTxError::InvalidSigner(signer_id) => { - write!(f, "Invalid signer account ID {:?} according to requirements", signer_id) + match self.kind { + InvalidTxErrorKind::InvalidAccessKey(access_key_error) => + match access_key_error { + InvalidAccessKeyErrorKind::ReceiverMismatch { tx_receiver_id, ak_receiver_id } => write!( + f, + "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}", + tx_receiver_id, ak_receiver_id + ), + InvalidAccessKeyErrorKind::MethodNameMismatch { method_name } => write!( + f, + "Transaction method name {:?} isn't allowed by the access key", + method_name + ), + InvalidAccessKeyErrorKind::ActionError => { + write!(f, "The used access key requires exactly one FunctionCall action") + } + InvalidAccessKeyErrorKind::NotEnoughAllowance { signer_id, public_key, allowed, cost } => { + write!( + f, + "Access Key {:?}:{} does not have enough balance {} for transaction costing {}", + signer_id, public_key, allowed, cost + ) + } + }, + InvalidTxErrorKind::Action(action) => { + match action.kind { + ActionErrorKind::AccountAlreadyExists => { + write!(f, "Can't create a new account {:?}, because it already exists", self.receiver_id) + } + ActionErrorKind::AccountDoesNotExist { action } => write!( + f, + "Can't complete the action {:?}, because account {:?} doesn't exist", + action, self.receiver_id + ), + ActionErrorKind::ActorNoPermission { actor_id, action } => write!( + f, + "Actor {:?} doesn't have permission to account {:?} to complete the action {:?}", + actor_id, self.receiver_id, action + ), + ActionErrorKind::TriesToUnstake => { + write!(f, "Account {:?} is not yet staked, but tries to unstake", self.receiver_id) + } + ActionErrorKind::TriesToStake {stake, staked, amount } => write!( + f, + "Account {:?} tries to stake {}, but has staked {} and only has {}", + self.receiver_id, stake, staked, amount + ), + ActionErrorKind::CreateAccountNotAllowed => write!( + f, + "The new account_id {:?} can't be created by {:?}", + self.receiver_id, self.signer_id + ), + ActionErrorKind::DeleteKeyDoesNotExist {public_key} => write!( + f, + "Account {:?} tries to remove an access key {:?} that doesn't exist", + self.receiver_id, public_key + ), + ActionErrorKind::AddKeyAlreadyExists => write!( + f, + "The public key {:?} for account {:?} is already used for an existing access key", + self.public_key, self.receiver_id + ), + ActionErrorKind::DeleteAccountStaking => { + write!(f, "Account {:?} is staking and can not be deleted", self.receiver_id) + } + ActionErrorKind::DeleteAccountHasRent { receiver_id, amount } => write!( + f, + "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", + receiver_id, amount + ), + ActionErrorKind::FunctionCall(s) => write!(f, "FunctionCall action error: {}", s), + } } - InvalidTxError::SignerDoesNotExist(signer_id) => { - write!(f, "Signer {:?} does not exist", signer_id) + InvalidTxErrorKind::InvalidSigner => { + write!(f, "Invalid signer account ID {:?} according to requirements", self.signer_id) } - InvalidTxError::InvalidAccessKey(access_key_error) => access_key_error.fmt(f), - InvalidTxError::InvalidNonce(tx_nonce, ak_nonce) => write!( + InvalidTxErrorKind::SignerDoesNotExist => { + write!(f, "Signer {:?} does not exist", self.signer_id) + } + InvalidTxErrorKind::InvalidNonce{access_key_nonce} => write!( f, "Transaction nonce {} must be larger than nonce of the used access key {}", - tx_nonce, ak_nonce + self.nonce, access_key_nonce ), - InvalidTxError::InvalidReceiver(receiver_id) => { - write!(f, "Invalid receiver account ID {:?} according to requirements", receiver_id) + InvalidTxErrorKind::InvalidReceiver => { + write!(f, "Invalid receiver account ID {:?} according to requirements", self.receiver_id) } - InvalidTxError::InvalidSignature => { - write!(f, "Transaction is not signed with the given public key") - } - InvalidTxError::NotEnoughBalance(signer_id, balance, cost) => write!( + + InvalidTxErrorKind::NotEnoughBalance{balance, cost} => write!( f, "Sender {:?} does not have enough balance {} for operation costing {}", - signer_id, balance, cost + self.signer_id, balance, cost ), - InvalidTxError::RentUnpaid(signer_id, amount) => { - write!(f, "Failed to execute, because the account {:?} wouldn't have enough to pay required rent {}", signer_id, amount) + InvalidTxErrorKind::RentUnpaid{amount} => { + write!(f, "Failed to execute, because the account {:?} wouldn't have enough to pay required rent {}", self.signer_id, amount) } - InvalidTxError::CostOverflow => { + InvalidTxErrorKind::CostOverflow => { write!(f, "Transaction gas or balance cost is too high") } - InvalidTxError::InvalidChain => { + InvalidTxErrorKind::InvalidChain => { write!(f, "Transaction parent block hash doesn't belong to the current chain") } - InvalidTxError::Expired => { + InvalidTxErrorKind::InvalidSignature => { + write!(f, "Transaction is not signed with the given public key") + } + InvalidTxErrorKind::Expired => { write!(f, "Transaction has expired") } - } - } -} - -impl From for InvalidTxError { - fn from(error: InvalidAccessKeyError) -> Self { - InvalidTxError::InvalidAccessKey(error) - } -} - -impl Display for InvalidAccessKeyError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - InvalidAccessKeyError::AccessKeyNotFound(account_id, public_key) => write!( + InvalidTxErrorKind::AccessKeyNotFound => write!( f, "Signer {:?} doesn't have access key with the given public_key {}", - account_id, public_key - ), - InvalidAccessKeyError::ReceiverMismatch(tx_receiver, ak_receiver) => write!( - f, - "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}", - tx_receiver, ak_receiver - ), - InvalidAccessKeyError::MethodNameMismatch(method_name) => write!( - f, - "Transaction method name {:?} isn't allowed by the access key", - method_name - ), - InvalidAccessKeyError::ActionError => { - write!(f, "The used access key requires exactly one FunctionCall action") - } - InvalidAccessKeyError::NotEnoughAllowance(account_id, public_key, allowance, cost) => { - write!( - f, - "Access Key {:?}:{} does not have enough balance {} for transaction costing {}", - account_id, public_key, allowance, cost - ) - } + self.signer_id, self.public_key + ) } } } @@ -231,14 +310,14 @@ pub struct IntegerOverflowError; #[derive(Debug, Clone, PartialEq, Eq)] pub enum RuntimeError { UnexpectedIntegerOverflow, - InvalidTxError(InvalidTxError), + InvalidTxErrorKind(InvalidTxErrorKind), StorageError(StorageError), BalanceMismatch(BalanceMismatchError), } -impl From for InvalidTxError { +impl From for InvalidTxErrorKind { fn from(_: IntegerOverflowError) -> Self { - InvalidTxError::CostOverflow + InvalidTxErrorKind::CostOverflow } } @@ -260,73 +339,15 @@ impl From for RuntimeError { } } -impl From for RuntimeError { - fn from(e: InvalidTxError) -> Self { - RuntimeError::InvalidTxError(e) - } -} - -impl Display for ActionError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - ActionError::AccountAlreadyExists(account_id) => { - write!(f, "Can't create a new account {:?}, because it already exists", account_id) - } - ActionError::AccountDoesNotExist(action, account_id) => write!( - f, - "Can't complete the action {:?}, because account {:?} doesn't exist", - action, account_id - ), - ActionError::ActorNoPermission(actor_id, account_id, action) => write!( - f, - "Actor {:?} doesn't have permission to account {:?} to complete the action {:?}", - actor_id, account_id, action - ), - ActionError::RentUnpaid(account_id, amount) => write!( - f, - "The account {} wouldn't have enough balance to pay required rent {}", - account_id, amount - ), - ActionError::TriesToUnstake(account_id) => { - write!(f, "Account {:?} is not yet staked, but tries to unstake", account_id) - } - ActionError::TriesToStake(account_id, stake, staked, balance) => write!( - f, - "Account {:?} tries to stake {}, but has staked {} and only has {}", - account_id, stake, staked, balance - ), - ActionError::CreateAccountNotAllowed(account_id, predecessor_id) => write!( - f, - "The new account_id {:?} can't be created by {:?}", - account_id, predecessor_id - ), - ActionError::DeleteKeyDoesNotExist(account_id) => write!( - f, - "Account {:?} tries to remove an access key that doesn't exist", - account_id - ), - ActionError::AddKeyAlreadyExists(public_key) => write!( - f, - "The public key {:?} is already used for an existing access key", - public_key - ), - ActionError::DeleteAccountStaking(account_id) => { - write!(f, "Account {:?} is staking and can not be deleted", account_id) - } - ActionError::DeleteAccountHasRent(account_id, balance) => write!( - f, - "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", - account_id, balance - ), - ActionError::FunctionCallError(s) => write!(f, "FunctionCall action error: {}", s), - } +impl From for RuntimeError { + fn from(e: InvalidTxErrorKind) -> Self { + RuntimeError::InvalidTxErrorKind(e) } } /// Error returned in the ExecutionOutcome in case of failure. -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub enum ExecutionError { - Action(ActionError), InvalidTx(InvalidTxError), } @@ -345,8 +366,8 @@ impl From for ExecutionError { } } -impl From for ExecutionError { - fn from(error: InvalidTxError) -> Self { +impl From for ExecutionError { + fn from(error: InvalidTxErrorKind) -> Self { ExecutionError::InvalidTx(error) } } diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index a80d8511fb0..758907b9c14 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -668,7 +668,9 @@ impl Default for FinalExecutionStatus { } } -#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive( + BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default, +)] pub struct ExecutionErrorView { pub error_message: String, pub error_type: String, @@ -676,84 +678,74 @@ pub struct ExecutionErrorView { impl From for ExecutionErrorView { fn from(error: ExecutionError) -> Self { - ExecutionErrorView { - error_message: format!("{}", error), - error_type: match &error { - ExecutionError::Action(e) => match e { - ActionError::AccountAlreadyExists(_) => { - "ActionError::AccountAlreadyExists".to_string() - } - ActionError::AccountDoesNotExist(_, _) => { - "ActionError::AccountDoesNotExist".to_string() - } - ActionError::CreateAccountNotAllowed(_, _) => { - "ActionError::CreateAccountNotAllowed".to_string() - } - ActionError::ActorNoPermission(_, _, _) => { - "ActionError::ActorNoPermission".to_string() - } - ActionError::DeleteKeyDoesNotExist(_) => { - "ActionError::DeleteKeyDoesNotExist".to_string() - } - ActionError::AddKeyAlreadyExists(_) => { - "ActionError::AddKeyAlreadyExists".to_string() - } - ActionError::DeleteAccountStaking(_) => { - "ActionError::DeleteAccountStaking".to_string() - } - ActionError::DeleteAccountHasRent(_, _) => { - "ActionError::DeleteAccountHasRent".to_string() - } - ActionError::RentUnpaid(_, _) => "ActionError::RentUnpaid".to_string(), - ActionError::TriesToUnstake(_) => "ActionError::TriesToUnstake".to_string(), - ActionError::TriesToStake(_, _, _, _) => { - "ActionError::TriesToStake".to_string() - } - ActionError::FunctionCallError(_) => { - "ActionError::FunctionCallError".to_string() - } - }, - ExecutionError::InvalidTx(e) => match e { - InvalidTxError::InvalidSigner(_) => "InvalidTxError::InvalidSigner".to_string(), - InvalidTxError::SignerDoesNotExist(_) => { - "InvalidTxError::SignerDoesNotExist".to_string() + let error_type = match &error { + ExecutionError::Action(e) => match e { + ActionError::AccountAlreadyExists { .. } => { + "ActionError::AccountAlreadyExists".to_string() + } + ActionError::AccountDoesNotExist { .. } => { + "ActionError::AccountDoesNotExist".to_string() + } + ActionError::CreateAccountNotAllowed { .. } => { + "ActionError::CreateAccountNotAllowed".to_string() + } + ActionError::ActorNoPermission { .. } => { + "ActionError::ActorNoPermission".to_string() + } + ActionError::DeleteKeyDoesNotExist { .. } => { + "ActionError::DeleteKeyDoesNotExist".to_string() + } + ActionError::AddKeyAlreadyExists { .. } => { + "ActionError::AddKeyAlreadyExists".to_string() + } + ActionError::DeleteAccountStaking { .. } => { + "ActionError::DeleteAccountStaking".to_string() + } + ActionError::DeleteAccountHasRent { .. } => { + "ActionError::DeleteAccountHasRent".to_string() + } + ActionError::RentUnpaid { .. } => "ActionError::RentUnpaid".to_string(), + ActionError::TriesToUnstake { .. } => "ActionError::TriesToUnstake".to_string(), + ActionError::TriesToStake { .. } => "ActionError::TriesToStake".to_string(), + ActionError::FunctionCall { .. } => "ActionError::FunctionCall".to_string(), + }, + ExecutionError::InvalidTx(e) => match e { + InvalidTxError::InvalidSigner { .. } => "InvalidTxError::InvalidSigner".to_string(), + InvalidTxError::SignerDoesNotExist { .. } => { + "InvalidTxError::SignerDoesNotExist".to_string() + } + InvalidTxError::InvalidAccessKey(e) => match e { + InvalidAccessKeyError::AccessKeyNotFound { .. } => { + "InvalidTxError::InvalidAccessKey::AccessKeyNotFound".to_string() } - InvalidTxError::InvalidAccessKey(e) => match e { - InvalidAccessKeyError::AccessKeyNotFound(_, _) => { - "InvalidTxError::InvalidAccessKey::AccessKeyNotFound".to_string() - } - InvalidAccessKeyError::ReceiverMismatch(_, _) => { - "InvalidTxError::InvalidAccessKey::ReceiverMismatch".to_string() - } - InvalidAccessKeyError::MethodNameMismatch(_) => { - "InvalidTxError::InvalidAccessKey::MethodNameMismatch".to_string() - } - InvalidAccessKeyError::ActionError => { - "InvalidTxError::InvalidAccessKey::ActionError".to_string() - } - InvalidAccessKeyError::NotEnoughAllowance(_, _, _, _) => { - "InvalidTxError::InvalidAccessKey::NotEnoughAllowance".to_string() - } - }, - InvalidTxError::InvalidNonce(_, _) => { - "InvalidTxError::InvalidNonce".to_string() + InvalidAccessKeyError::ReceiverMismatch { .. } => { + "InvalidTxError::InvalidAccessKey::ReceiverMismatch".to_string() } - InvalidTxError::InvalidReceiver(_) => { - "InvalidTxError::InvalidReceiver".to_string() + InvalidAccessKeyError::MethodNameMismatch { .. } => { + "InvalidTxError::InvalidAccessKey::MethodNameMismatch".to_string() } - InvalidTxError::InvalidSignature => { - "InvalidTxError::InvalidSignature".to_string() + InvalidAccessKeyError::ActionError => { + "InvalidTxError::InvalidAccessKey::ActionError".to_string() } - InvalidTxError::NotEnoughBalance(_, _, _) => { - "InvalidTxError::NotEnoughBalance".to_string() + InvalidAccessKeyError::NotEnoughAllowance { .. } => { + "InvalidTxError::InvalidAccessKey::NotEnoughAllowance".to_string() } - InvalidTxError::RentUnpaid(_, _) => "InvalidTxError::RentUnpaid".to_string(), - InvalidTxError::CostOverflow => "InvalidTxError::CostOverflow".to_string(), - InvalidTxError::InvalidChain => "InvalidTxError::InvalidChain".to_string(), - InvalidTxError::Expired => "InvalidTxError::Expired".to_string(), }, + InvalidTxError::InvalidNonce { .. } => "InvalidTxError::InvalidNonce".to_string(), + InvalidTxError::InvalidReceiver { .. } => { + "InvalidTxError::InvalidReceiver".to_string() + } + InvalidTxError::InvalidSignature => "InvalidTxError::InvalidSignature".to_string(), + InvalidTxError::NotEnoughBalance { .. } => { + "InvalidTxError::NotEnoughBalance".to_string() + } + InvalidTxError::RentUnpaid { .. } => "InvalidTxError::RentUnpaid".to_string(), + InvalidTxError::CostOverflow => "InvalidTxError::CostOverflow".to_string(), + InvalidTxError::InvalidChain => "InvalidTxError::InvalidChain".to_string(), + InvalidTxError::Expired => "InvalidTxError::Expired".to_string(), }, - } + }; + ExecutionErrorView { error_message: format!("{}", error), error_type } } } diff --git a/runtime/near-vm-errors/Cargo.toml b/runtime/near-vm-errors/Cargo.toml index fdafa67aaff..c8f4b16ebbc 100644 --- a/runtime/near-vm-errors/Cargo.toml +++ b/runtime/near-vm-errors/Cargo.toml @@ -14,3 +14,4 @@ Error that can occur inside Near Runtime encapsulated in a separate crate. Might [dependencies] borsh = "0.2.10" +serde = { version = "1.0", features = ["derive"] } diff --git a/runtime/near-vm-errors/src/lib.rs b/runtime/near-vm-errors/src/lib.rs index ad8f75f3299..25e80ca1230 100644 --- a/runtime/near-vm-errors/src/lib.rs +++ b/runtime/near-vm-errors/src/lib.rs @@ -1,13 +1,16 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type", content = "c")] pub enum VMError { FunctionExecError(FunctionExecError), StorageError(Vec), } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type")] pub enum FunctionExecError { CompilationError(CompilationError), LinkError(String), @@ -16,7 +19,8 @@ pub enum FunctionExecError { HostError(HostError), } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type")] pub enum MethodResolveError { MethodEmptyName, MethodUTF8Error, @@ -24,14 +28,16 @@ pub enum MethodResolveError { MethodInvalidSignature, } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type")] pub enum CompilationError { CodeDoesNotExist(String), PrepareError(PrepareError), WasmerCompileError(String), } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type")] /// Error that can occur while preparing or executing Wasm smart-contract. pub enum PrepareError { /// Error happened while serializing the module. @@ -63,7 +69,8 @@ pub enum PrepareError { Memory, } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type")] pub enum HostError { BadUTF16, BadUTF8, @@ -88,7 +95,8 @@ pub enum HostError { ProhibitedInView(String), } -#[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize)] +#[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[serde(tag = "type")] pub enum HostErrorOrStorageError { HostError(HostError), /// Error from underlying storage, serialized diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index d03d292bacd..0a73fa0d1fc 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -122,7 +122,7 @@ pub(crate) fn action_function_call( let error = VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::CodeDoesNotExist(account_id.clone()), )); - result.result = Err(ActionError::FunctionCallError(error)); + result.result = Err(ActionError::FunctionCall(error)); return Ok(()); } Err(e) => { @@ -179,7 +179,7 @@ pub(crate) fn action_function_call( borsh::BorshDeserialize::try_from_slice(&storage).expect("Borsh cannot fail"); return Err(err); } - result.result = Err(ActionError::FunctionCallError(err)); + result.result = Err(ActionError::FunctionCall(err)); if let Some(outcome) = outcome { result.gas_burnt += outcome.burnt_gas; result.gas_burnt_for_function_call += outcome.burnt_gas; @@ -215,7 +215,7 @@ pub(crate) fn action_stake( if account.amount >= increment { if account.locked == 0 && stake.stake == 0 { // if the account hasn't staked, it cannot unstake - result.result = Err(ActionError::TriesToUnstake(account_id.clone())); + result.result = Err(ActionError::TriesToUnstake { receiver_id: account_id.clone() }); return; } result.validator_proposals.push(ValidatorStake { @@ -228,12 +228,12 @@ pub(crate) fn action_stake( account.locked = stake.stake; } } else { - result.result = Err(ActionError::TriesToStake( - account_id.clone(), - stake.stake, - account.locked, - account.amount, - )); + result.result = Err(ActionError::TriesToStake { + receiver_id: account_id.clone(), + stake: stake.stake, + staked: account.locked, + amount: account.amount, + }); } } @@ -253,10 +253,10 @@ pub(crate) fn action_create_account( if !is_valid_top_level_account_id(account_id) && !is_valid_sub_account_id(&receipt.predecessor_id, account_id) { - result.result = Err(ActionError::CreateAccountNotAllowed( - account_id.clone(), - receipt.predecessor_id.clone(), - )); + result.result = Err(ActionError::CreateAccountNotAllowed { + receiver_id: account_id.clone(), + sender_id: receipt.predecessor_id.clone(), + }); return; } *actor_id = receipt.receiver_id.clone(); @@ -317,7 +317,10 @@ pub(crate) fn action_delete_key( let account = account.as_mut().unwrap(); let access_key = get_access_key(state_update, account_id, &delete_key.public_key)?; if access_key.is_none() { - result.result = Err(ActionError::DeleteKeyDoesNotExist(account_id.clone())); + result.result = Err(ActionError::DeleteKeyDoesNotExist { + public_key: delete_key.public_key.clone(), + receiver_id: account_id.clone(), + }); return Ok(()); } // Remove access key @@ -343,7 +346,10 @@ pub(crate) fn action_add_key( ) -> Result<(), StorageError> { let account = account.as_mut().unwrap(); if get_access_key(state_update, account_id, &add_key.public_key)?.is_some() { - result.result = Err(ActionError::AddKeyAlreadyExists(add_key.public_key.clone())); + result.result = Err(ActionError::AddKeyAlreadyExists { + receiver_id: account_id.to_owned(), + public_key: add_key.public_key.clone(), + }); return Ok(()); } set_access_key(state_update, account_id, &add_key.public_key, &add_key.access_key); @@ -369,16 +375,16 @@ pub(crate) fn check_actor_permissions( match action { Action::DeployContract(_) | Action::Stake(_) | Action::AddKey(_) | Action::DeleteKey(_) => { if actor_id != account_id { - return Err(ActionError::ActorNoPermission( - actor_id.clone(), - account_id.clone(), - action_type_as_string(action).to_owned(), - )); + return Err(ActionError::ActorNoPermission { + sender_id: actor_id.clone(), + receiver_id: account_id.clone(), + action: action_type_as_string(action).to_owned(), + }); } } Action::DeleteAccount(_) => { if account.as_ref().unwrap().locked != 0 { - return Err(ActionError::DeleteAccountStaking(account_id.clone())); + return Err(ActionError::DeleteAccountStaking { receiver_id: account_id.clone() }); } if actor_id != account_id && check_rent( @@ -389,10 +395,10 @@ pub(crate) fn check_actor_permissions( ) .is_ok() { - return Err(ActionError::DeleteAccountHasRent( - account_id.clone(), - account.as_ref().unwrap().amount, - )); + return Err(ActionError::DeleteAccountHasRent { + receiver_id: account_id.clone(), + amount: account.as_ref().unwrap().amount, + }); } } Action::CreateAccount(_) | Action::FunctionCall(_) | Action::Transfer(_) => (), @@ -421,7 +427,7 @@ pub(crate) fn check_account_existence( match action { Action::CreateAccount(_) => { if account.is_some() { - return Err(ActionError::AccountAlreadyExists(account_id.clone())); + return Err(ActionError::AccountAlreadyExists { receiver_id: account_id.clone() }); } } Action::DeployContract(_) @@ -432,12 +438,11 @@ pub(crate) fn check_account_existence( | Action::DeleteKey(_) | Action::DeleteAccount(_) => { if account.is_none() { - return Err(ActionError::AccountDoesNotExist( - action_type_as_string(action).to_owned(), - account_id.clone(), - )); + return Err(ActionError::AccountDoesNotExist { + action: action_type_as_string(action).to_owned(), + receiver_id: account_id.clone(), + }); } - // } }; Ok(()) diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index 28ba12a12ed..619786e3908 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -216,10 +216,13 @@ impl Runtime { let transaction = &signed_transaction.transaction; let signer_id = &transaction.signer_id; if !is_valid_account_id(&signer_id) { - return Err(InvalidTxError::InvalidSigner(signer_id.clone()).into()); + return Err(InvalidTxError::InvalidSigner { signer_id: signer_id.clone() }.into()); } if !is_valid_account_id(&transaction.receiver_id) { - return Err(InvalidTxError::InvalidReceiver(transaction.receiver_id.clone()).into()); + return Err(InvalidTxError::InvalidReceiver { + receiver_id: transaction.receiver_id.clone(), + } + .into()); } if !signed_transaction @@ -231,7 +234,9 @@ impl Runtime { let mut signer = match get_account(state_update, signer_id)? { Some(signer) => signer, None => { - return Err(InvalidTxError::SignerDoesNotExist(signer_id.clone()).into()); + return Err( + InvalidTxError::SignerDoesNotExist { signer_id: signer_id.clone() }.into() + ); } }; let mut access_key = @@ -239,17 +244,21 @@ impl Runtime { Some(access_key) => access_key, None => { return Err(InvalidTxError::InvalidAccessKey( - InvalidAccessKeyError::AccessKeyNotFound( - signer_id.clone(), - transaction.public_key.clone(), - ), + InvalidAccessKeyError::AccessKeyNotFound { + account_id: signer_id.clone(), + public_key: transaction.public_key.clone(), + }, ) .into()); } }; if transaction.nonce <= access_key.nonce { - return Err(InvalidTxError::InvalidNonce(transaction.nonce, access_key.nonce).into()); + return Err(InvalidTxError::InvalidNonce { + tx_nonce: transaction.nonce, + ak_nonce: access_key.nonce, + } + .into()); } let sender_is_receiver = &transaction.receiver_id == signer_id; @@ -266,7 +275,11 @@ impl Runtime { .map_err(|_| InvalidTxError::CostOverflow)?; signer.amount = signer.amount.checked_sub(total_cost).ok_or_else(|| { - InvalidTxError::NotEnoughBalance(signer_id.clone(), signer.amount, total_cost) + InvalidTxError::NotEnoughBalance { + sender_id: signer_id.clone(), + balance: signer.amount, + cost: total_cost, + } })?; if let AccessKeyPermission::FunctionCall(ref mut function_call_permission) = @@ -274,19 +287,19 @@ impl Runtime { { if let Some(ref mut allowance) = function_call_permission.allowance { *allowance = allowance.checked_sub(total_cost).ok_or_else(|| { - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::NotEnoughAllowance( - signer_id.clone(), - transaction.public_key.clone(), - *allowance, - total_cost, - )) + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::NotEnoughAllowance { + signer_id: signer_id.clone(), + public_key: transaction.public_key.clone(), + allowed: *allowance, + cost: total_cost, + }) })?; } } if let Err(amount) = check_rent(&signer_id, &signer, &self.config, apply_state.epoch_length) { - return Err(InvalidTxError::RentUnpaid(signer_id.clone(), amount).into()); + return Err(InvalidTxError::RentUnpaid { account_id: signer_id.clone(), amount }.into()); } if let AccessKeyPermission::FunctionCall(ref function_call_permission) = @@ -300,10 +313,10 @@ impl Runtime { if let Some(Action::FunctionCall(ref function_call)) = transaction.actions.get(0) { if transaction.receiver_id != function_call_permission.receiver_id { return Err(InvalidTxError::InvalidAccessKey( - InvalidAccessKeyError::ReceiverMismatch( - transaction.receiver_id.clone(), - function_call_permission.receiver_id.clone(), - ), + InvalidAccessKeyError::ReceiverMismatch { + tx_receiver_id: transaction.receiver_id.clone(), + ak_receiver_id: function_call_permission.receiver_id.clone(), + }, ) .into()); } @@ -314,9 +327,9 @@ impl Runtime { .all(|method_name| &function_call.method_name != method_name) { return Err(InvalidTxError::InvalidAccessKey( - InvalidAccessKeyError::MethodNameMismatch( - function_call.method_name.clone(), - ), + InvalidAccessKeyError::MethodNameMismatch { + method_name: function_call.method_name.clone(), + }, ) .into()); } @@ -604,7 +617,10 @@ impl Runtime { check_rent(account_id, account, &self.config, apply_state.epoch_length) { result.merge(ActionResult { - result: Err(ActionError::RentUnpaid(account_id.clone(), amount)), + result: Err(ActionError::RentUnpaid { + receiver_id: account_id.clone(), + amount, + }), ..Default::default() })?; } else { diff --git a/runtime/runtime/tests/test_evil_contracts.rs b/runtime/runtime/tests/test_evil_contracts.rs index e223d1afd75..fa61aa12578 100644 --- a/runtime/runtime/tests/test_evil_contracts.rs +++ b/runtime/runtime/tests/test_evil_contracts.rs @@ -2,6 +2,7 @@ use near_primitives::errors::ActionError; use near_primitives::serialize::to_base64; use near_primitives::types::Gas; use near_primitives::views::FinalExecutionStatus; +use near_vm_errors::{FunctionExecError, HostError, MethodResolveError, VMError}; use std::mem::size_of; use testlib::node::{Node, RuntimeNode}; @@ -141,10 +142,9 @@ fn test_evil_abort() { .unwrap(); assert_eq!( res.status, - FinalExecutionStatus::Failure( - ActionError::FunctionCallError("String encoding is bad UTF-16 sequence.".to_string()) - .into() - ), + FinalExecutionStatus::Failure(ActionError::FunctionCallError(VMError::FunctionExecError( + FunctionExecError::HostError(HostError::BadUTF16) + ))), "{:?}", res ); diff --git a/test-utils/testlib/Cargo.toml b/test-utils/testlib/Cargo.toml index 6186baed38a..dbe6fb5da22 100644 --- a/test-utils/testlib/Cargo.toml +++ b/test-utils/testlib/Cargo.toml @@ -27,6 +27,7 @@ near-crypto = { path = "../../core/crypto" } near-primitives = { path = "../../core/primitives" } near-store = { path = "../../core/store" } node-runtime = { path = "../../runtime/runtime" } +near-vm-errors = { path = "../../runtime/near-vm-errors" } near-chain = { path = "../../chain/chain" } near-client = { path = "../../chain/client" } near-jsonrpc = { path = "../../chain/jsonrpc" } diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index a7b6a3a56d2..ff351f5dee8 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -9,6 +9,7 @@ use near_primitives::serialize::to_base64; use near_primitives::types::Balance; use near_primitives::views::FinalExecutionStatus; use near_primitives::views::{AccountView, FinalExecutionOutcomeView}; +use near_vm_errors::{FunctionExecError, HostError, MethodResolveError, VMError}; use crate::fees_utils::FeeHelper; use crate::node::Node; @@ -61,19 +62,22 @@ pub fn test_smart_contract_simple(node: impl Node) { assert_ne!(root, new_root); } -pub fn test_smart_contract_panic(node: impl Node) { - let node_user = node.user(); - let transaction_result = node_user - .function_call(alice_account(), alice_account(), "panic_with_message", vec![], 1000000, 0) - .unwrap(); - assert_eq!( - transaction_result.status, - FinalExecutionStatus::Failure( - ActionError::FunctionCallError("Smart contract panicked: WAT?".to_string()).into() - ) - ); - assert_eq!(transaction_result.receipts.len(), 2); -} +// pub fn test_smart_contract_panic(node: impl Node) { +// let node_user = node.user(); +// let transaction_result = node_user +// .function_call(alice_account(), alice_account(), "panic_with_message", vec![], 1000000, 0) +// .unwrap(); +// assert_eq!( +// transaction_result.status, +// FinalExecutionStatus::Failure( +// ActionError::FunctionCallError(VMError::FunctionExecError( +// FunctionExecError::HostError(HostError::GuestPanic("WAT?".to_owned())) +// )) +// .into() +// ) +// ); +// assert_eq!(transaction_result.receipts.len(), 2); +// } pub fn test_smart_contract_self_call(node: impl Node) { let account_id = &node.account_id().unwrap(); @@ -101,7 +105,10 @@ pub fn test_smart_contract_bad_method_name(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCallError("MethodNotFound".to_string()).into() + ActionError::FunctionCallError(VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodNotFound) + )) + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -118,7 +125,10 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCallError("MethodEmptyName".to_string()).into() + ActionError::FunctionCallError(VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) + )) + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -126,23 +136,24 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { assert_ne!(root, new_root); } -pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { - let account_id = &node.account_id().unwrap(); - let node_user = node.user(); - let root = node_user.get_state_root(); - let transaction_result = node_user - .function_call(account_id.clone(), bob_account(), "", vec![], 1000000, 10) - .unwrap(); - assert_eq!( - transaction_result.status, - FinalExecutionStatus::Failure( - ActionError::FunctionCallError("MethodEmptyName".to_string()).into() - ) - ); - assert_eq!(transaction_result.receipts.len(), 2); - let new_root = node_user.get_state_root(); - assert_ne!(root, new_root); -} +// pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { +// let account_id = &node.account_id().unwrap(); +// let node_user = node.user(); +// let root = node_user.get_state_root(); +// let transaction_result = node_user +// .function_call(account_id.clone(), bob_account(), "", vec![], 1000000, 10) +// .unwrap(); +// assert_eq!( +// transaction_result.status, +// FinalExecutionStatus::Failure(ActionError::FunctionCallError(VMError::FunctionExecError( +// FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) +// ))) +// .into() +// ); +// assert_eq!(transaction_result.receipts.len(), 2); +// let new_root = node_user.get_state_root(); +// assert_ne!(root, new_root); +// } pub fn test_smart_contract_with_args(node: impl Node) { let account_id = &node.account_id().unwrap(); @@ -337,8 +348,11 @@ pub fn test_refund_on_send_money_to_non_existent_account(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountDoesNotExist("Transfer".to_string(), eve_dot_alice_account()) - .into() + ActionError::AccountDoesNotExist { + action: "Transfer".to_string(), + receiver_id: eve_dot_alice_account() + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -429,7 +443,7 @@ pub fn test_create_account_again(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountAlreadyExists(eve_dot_alice_account()).into() + ActionError::AccountAlreadyExists { receiver_id: eve_dot_alice_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -469,7 +483,10 @@ pub fn test_create_account_failure_invalid_name(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - format!("{}", InvalidTxError::InvalidReceiver(invalid_account_name.to_string())) + format!( + "{}", + InvalidTxError::InvalidReceiver { receiver_id: invalid_account_name.to_string() } + ) ); } } @@ -488,7 +505,9 @@ pub fn test_create_account_failure_already_exists(node: impl Node) { fee_helper.create_account_transfer_full_key_cost_fail_on_create_account(); assert_eq!( transaction_result.status, - FinalExecutionStatus::Failure(ActionError::AccountAlreadyExists(bob_account()).into()) + FinalExecutionStatus::Failure( + ActionError::AccountAlreadyExists { receiver_id: bob_account() }.into() + ) ); assert_eq!(transaction_result.receipts.len(), 2); let new_root = node_user.get_state_root(); @@ -565,7 +584,11 @@ pub fn test_add_existing_key(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AddKeyAlreadyExists(node.signer().public_key()).into() + ActionError::AddKeyAlreadyExists { + receiver_id: account_id.clone(), + public_key: node.signer().public_key().clone() + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -610,7 +633,11 @@ pub fn test_delete_key_not_owned(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteKeyDoesNotExist(account_id.clone()).into() + ActionError::DeleteKeyDoesNotExist { + receiver_id: account_id.clone(), + public_key: signer2.public_key.clone() + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -818,9 +845,9 @@ pub fn test_access_key_smart_contract_reject_method_name(node: impl Node) { transaction_result, format!( "{}", - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::MethodNameMismatch( - "run_test".to_string() - )) + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::MethodNameMismatch { + method_name: "run_test".to_string() + }) ) ); } @@ -847,10 +874,10 @@ pub fn test_access_key_smart_contract_reject_contract_id(node: impl Node) { transaction_result, format!( "{}", - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ReceiverMismatch( - eve_dot_alice_account(), - bob_account(), - )) + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ReceiverMismatch { + tx_receiver_id: eve_dot_alice_account(), + ak_receiver_id: bob_account() + }) ) ); } @@ -930,7 +957,9 @@ pub fn test_unstake_while_not_staked(node: impl Node) { node_user.stake(eve_dot_alice_account(), node.block_signer().public_key(), 0).unwrap(); assert_eq!( transaction_result.status, - FinalExecutionStatus::Failure(ActionError::TriesToUnstake(eve_dot_alice_account()).into()) + FinalExecutionStatus::Failure( + ActionError::TriesToUnstake { receiver_id: eve_dot_alice_account() }.into() + ) ); assert_eq!(transaction_result.receipts.len(), 1); } @@ -1005,7 +1034,9 @@ pub fn test_delete_account_fail(node: impl Node) { let transaction_result = node_user.delete_account(alice_account(), bob_account()).unwrap(); assert_eq!( transaction_result.status, - FinalExecutionStatus::Failure(ActionError::DeleteAccountStaking(bob_account()).into()) + FinalExecutionStatus::Failure( + ActionError::DeleteAccountStaking { receiver_id: bob_account() }.into() + ) ); assert_eq!(transaction_result.receipts.len(), 1); assert!(node.user().view_account(&bob_account()).is_ok()); @@ -1022,8 +1053,11 @@ pub fn test_delete_account_no_account(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountDoesNotExist("DeleteAccount".to_string(), eve_dot_alice_account()) - .into() + ActionError::AccountDoesNotExist { + action: "DeleteAccount".to_string(), + receiver_id: eve_dot_alice_account() + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -1050,7 +1084,7 @@ pub fn test_delete_account_while_staking(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteAccountStaking(eve_dot_alice_account()).into() + ActionError::DeleteAccountStaking { receiver_id: eve_dot_alice_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 1); From a986bc72fd81488c88e54c32cebdaf7d38633ed0 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 18 Dec 2019 16:05:46 +0300 Subject: [PATCH 03/48] errors refactor --- core/primitives/src/errors.rs | 327 +++++++++++++++++----------------- core/primitives/src/views.rs | 2 +- 2 files changed, 161 insertions(+), 168 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index f0093d8e56a..0d565748df4 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -1,14 +1,10 @@ -use crate::hash::CryptoHash; use crate::types::{AccountId, Balance, Nonce}; use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::PublicKey; -// TODO: looks like in this crate we're trying to avoid inner deps, but I can't find a better solution so far -pub use near_vm_errors::VMError; - use std::fmt::Display; /// Internal -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] pub enum StorageError { /// Key-value db internal failure StorageInternalError, @@ -31,199 +27,138 @@ impl std::fmt::Display for StorageError { impl std::error::Error for StorageError {} /// External -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] -#[serde(tag = "type")] -pub struct InvalidTxError { - pub signer_id: AccountId, - pub public_key: PublicKey, - pub nonce: Nonce, - pub receiver_id: AccountId, - pub block_hash: CryptoHash, - pub kind: InvalidTxErrorKind, -} - -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] -pub enum InvalidTxErrorKind { - InvalidAccessKey(InvalidAccessKeyErrorKind), - Action(ActionError), - InvalidSigner, - SignerDoesNotExist, - InvalidNonce { - access_key_nonce: Nonce, - }, - InvalidReceiver, - NotEnoughBalance { - balance: Balance, - cost: Balance, - }, - RentUnpaid { - amount: Balance, - }, +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +pub enum InvalidTxError { + InvalidAccessKey(InvalidAccessKeyError), + InvalidSigner { signer_id: AccountId }, + SignerDoesNotExist { signer_id: AccountId }, + InvalidNonce { tx_nonce: Nonce, ak_nonce: Nonce }, + InvalidReceiver { receiver_id: AccountId }, + InvalidSignature, + NotEnoughBalance { signer_id: AccountId, balance: Balance, cost: Balance }, + RentUnpaid { signer_id: AccountId, amount: Balance }, CostOverflow, InvalidChain, - InvalidSignature, Expired, - AccessKeyNotFound, - /// For this action the sender is required to be equal to the receiver - OwnershipError, } -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] -#[serde(tag = "type")] -pub enum InvalidAccessKeyErrorKind { +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +pub enum InvalidAccessKeyError { + AccessKeyNotFound { + account_id: AccountId, + public_key: PublicKey, + }, ReceiverMismatch { - tx_receiver_id: AccountId, - ak_receiver_id: AccountId, + tx_receiver: AccountId, + ak_receiver: AccountId, }, MethodNameMismatch { method_name: String, }, ActionError, NotEnoughAllowance { - signer_id: AccountId, + account_id: AccountId, public_key: PublicKey, - allowed: Balance, + allowance: Balance, cost: Balance, }, } -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] -pub struct ActionError { - // position of a failed action in the transaction/receipt - index: u64, - kind: ActionErrorKind, -} - -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Deserialize, Serialize)] -pub enum ActionErrorKind { - AccountAlreadyExists, - AccountDoesNotExist { action: String }, - CreateAccountNotAllowed, - ActorNoPermission { actor_id, action: String }, - DeleteKeyDoesNotExist { public_key: PublicKey }, +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +pub enum ActionError { + AccountAlreadyExists { account_id: AccountId }, + AccountDoesNotExist { action: String, account_id: AccountId }, + CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId }, + ActorNoPermission { account_id: AccountId, actor_id: AccountId, action: String }, + DeleteKeyDoesNotExist { account_id: AccountId }, AddKeyAlreadyExists { public_key: PublicKey }, - DeleteAccountStaking, - DeleteAccountHasRent { amount: Balance }, - TriesToUnstake, - TriesToStake { stake: Balance, staked: Balance, amount: Balance }, - FunctionCall(VMError), + DeleteAccountStaking { account_id: AccountId }, + DeleteAccountHasRent { account_id: AccountId, balance: Balance }, + RentUnpaid { account_id: AccountId, amount: Balance }, + TriesToUnstake { account_id: AccountId }, + TriesToStake { account_id: AccountId, stake: Balance, locked: Balance, balance: Balance }, + FunctionCallError(String), // TODO type } impl Display for InvalidTxError { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self.kind { - InvalidTxErrorKind::InvalidAccessKey(access_key_error) => - match access_key_error { - InvalidAccessKeyErrorKind::ReceiverMismatch { tx_receiver_id, ak_receiver_id } => write!( - f, - "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}", - tx_receiver_id, ak_receiver_id - ), - InvalidAccessKeyErrorKind::MethodNameMismatch { method_name } => write!( - f, - "Transaction method name {:?} isn't allowed by the access key", - method_name - ), - InvalidAccessKeyErrorKind::ActionError => { - write!(f, "The used access key requires exactly one FunctionCall action") - } - InvalidAccessKeyErrorKind::NotEnoughAllowance { signer_id, public_key, allowed, cost } => { - write!( - f, - "Access Key {:?}:{} does not have enough balance {} for transaction costing {}", - signer_id, public_key, allowed, cost - ) - } - }, - InvalidTxErrorKind::Action(action) => { - match action.kind { - ActionErrorKind::AccountAlreadyExists => { - write!(f, "Can't create a new account {:?}, because it already exists", self.receiver_id) - } - ActionErrorKind::AccountDoesNotExist { action } => write!( - f, - "Can't complete the action {:?}, because account {:?} doesn't exist", - action, self.receiver_id - ), - ActionErrorKind::ActorNoPermission { actor_id, action } => write!( - f, - "Actor {:?} doesn't have permission to account {:?} to complete the action {:?}", - actor_id, self.receiver_id, action - ), - ActionErrorKind::TriesToUnstake => { - write!(f, "Account {:?} is not yet staked, but tries to unstake", self.receiver_id) - } - ActionErrorKind::TriesToStake {stake, staked, amount } => write!( - f, - "Account {:?} tries to stake {}, but has staked {} and only has {}", - self.receiver_id, stake, staked, amount - ), - ActionErrorKind::CreateAccountNotAllowed => write!( - f, - "The new account_id {:?} can't be created by {:?}", - self.receiver_id, self.signer_id - ), - ActionErrorKind::DeleteKeyDoesNotExist {public_key} => write!( - f, - "Account {:?} tries to remove an access key {:?} that doesn't exist", - self.receiver_id, public_key - ), - ActionErrorKind::AddKeyAlreadyExists => write!( - f, - "The public key {:?} for account {:?} is already used for an existing access key", - self.public_key, self.receiver_id - ), - ActionErrorKind::DeleteAccountStaking => { - write!(f, "Account {:?} is staking and can not be deleted", self.receiver_id) - } - ActionErrorKind::DeleteAccountHasRent { receiver_id, amount } => write!( - f, - "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", - receiver_id, amount - ), - ActionErrorKind::FunctionCall(s) => write!(f, "FunctionCall action error: {}", s), - } - } - InvalidTxErrorKind::InvalidSigner => { - write!(f, "Invalid signer account ID {:?} according to requirements", self.signer_id) + match self { + InvalidTxError::InvalidSigner{signer_id} => { + write!(f, "Invalid signer account ID {:?} according to requirements", signer_id) } - InvalidTxErrorKind::SignerDoesNotExist => { - write!(f, "Signer {:?} does not exist", self.signer_id) + InvalidTxError::SignerDoesNotExist{signer_id} => { + write!(f, "Signer {:?} does not exist", signer_id) } - InvalidTxErrorKind::InvalidNonce{access_key_nonce} => write!( + InvalidTxError::InvalidAccessKey(access_key_error) => access_key_error.fmt(f), + InvalidTxError::InvalidNonce{tx_nonce, ak_nonce} => write!( f, "Transaction nonce {} must be larger than nonce of the used access key {}", - self.nonce, access_key_nonce + tx_nonce, ak_nonce ), - InvalidTxErrorKind::InvalidReceiver => { - write!(f, "Invalid receiver account ID {:?} according to requirements", self.receiver_id) + InvalidTxError::InvalidReceiver{receiver_id} => { + write!(f, "Invalid receiver account ID {:?} according to requirements", receiver_id) } - - InvalidTxErrorKind::NotEnoughBalance{balance, cost} => write!( + InvalidTxError::InvalidSignature => { + write!(f, "Transaction is not signed with the given public key") + } + InvalidTxError::NotEnoughBalance{signer_id, balance, cost} => write!( f, "Sender {:?} does not have enough balance {} for operation costing {}", - self.signer_id, balance, cost + signer_id, balance, cost ), - InvalidTxErrorKind::RentUnpaid{amount} => { - write!(f, "Failed to execute, because the account {:?} wouldn't have enough to pay required rent {}", self.signer_id, amount) + InvalidTxError::RentUnpaid{ signer_id, amount} => { + write!(f, "Failed to execute, because the account {:?} wouldn't have enough to pay required rent {}", signer_id, amount) } - InvalidTxErrorKind::CostOverflow => { + InvalidTxError::CostOverflow => { write!(f, "Transaction gas or balance cost is too high") } - InvalidTxErrorKind::InvalidChain => { + InvalidTxError::InvalidChain => { write!(f, "Transaction parent block hash doesn't belong to the current chain") } - InvalidTxErrorKind::InvalidSignature => { - write!(f, "Transaction is not signed with the given public key") - } - InvalidTxErrorKind::Expired => { + InvalidTxError::Expired => { write!(f, "Transaction has expired") } - InvalidTxErrorKind::AccessKeyNotFound => write!( + } + } +} + +impl From for InvalidTxError { + fn from(error: InvalidAccessKeyError) -> Self { + InvalidTxError::InvalidAccessKey(error) + } +} + +impl Display for InvalidAccessKeyError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match self { + InvalidAccessKeyError::AccessKeyNotFound { account_id, public_key } => write!( f, "Signer {:?} doesn't have access key with the given public_key {}", - self.signer_id, self.public_key - ) + account_id, public_key + ), + InvalidAccessKeyError::ReceiverMismatch { tx_receiver, ak_receiver } => write!( + f, + "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}", + tx_receiver, ak_receiver + ), + InvalidAccessKeyError::MethodNameMismatch { method_name } => write!( + f, + "Transaction method name {:?} isn't allowed by the access key", + method_name + ), + InvalidAccessKeyError::ActionError => { + write!(f, "The used access key requires exactly one FunctionCall action") + } + InvalidAccessKeyError::NotEnoughAllowance { + account_id, + public_key, + allowance, + cost, + } => write!( + f, + "Access Key {:?}:{} does not have enough balance {} for transaction costing {}", + account_id, public_key, allowance, cost + ), } } } @@ -310,14 +245,14 @@ pub struct IntegerOverflowError; #[derive(Debug, Clone, PartialEq, Eq)] pub enum RuntimeError { UnexpectedIntegerOverflow, - InvalidTxErrorKind(InvalidTxErrorKind), + InvalidTxError(InvalidTxError), StorageError(StorageError), BalanceMismatch(BalanceMismatchError), } -impl From for InvalidTxErrorKind { +impl From for InvalidTxError { fn from(_: IntegerOverflowError) -> Self { - InvalidTxErrorKind::CostOverflow + InvalidTxError::CostOverflow } } @@ -339,15 +274,73 @@ impl From for RuntimeError { } } -impl From for RuntimeError { - fn from(e: InvalidTxErrorKind) -> Self { - RuntimeError::InvalidTxErrorKind(e) +impl From for RuntimeError { + fn from(e: InvalidTxError) -> Self { + RuntimeError::InvalidTxError(e) + } +} + +impl Display for ActionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match self { + ActionError::AccountAlreadyExists { account_id } => { + write!(f, "Can't create a new account {:?}, because it already exists", account_id) + } + ActionError::AccountDoesNotExist { action, account_id } => write!( + f, + "Can't complete the action {:?}, because account {:?} doesn't exist", + action, account_id + ), + ActionError::ActorNoPermission { actor_id, account_id, action } => write!( + f, + "Actor {:?} doesn't have permission to account {:?} to complete the action {:?}", + actor_id, account_id, action + ), + ActionError::RentUnpaid { account_id, amount } => write!( + f, + "The account {} wouldn't have enough balance to pay required rent {}", + account_id, amount + ), + ActionError::TriesToUnstake { account_id } => { + write!(f, "Account {:?} is not yet staked, but tries to unstake", account_id) + } + ActionError::TriesToStake { account_id, stake, locked, balance } => write!( + f, + "Account {:?} tries to stake {}, but has staked {} and only has {}", + account_id, stake, locked, balance + ), + ActionError::CreateAccountNotAllowed { account_id, predecessor_id } => write!( + f, + "The new account_id {:?} can't be created by {:?}", + account_id, predecessor_id + ), + ActionError::DeleteKeyDoesNotExist { account_id } => write!( + f, + "Account {:?} tries to remove an access key that doesn't exist", + account_id + ), + ActionError::AddKeyAlreadyExists { public_key } => write!( + f, + "The public key {:?} is already used for an existing access key", + public_key + ), + ActionError::DeleteAccountStaking { account_id } => { + write!(f, "Account {:?} is staking and can not be deleted", account_id) + } + ActionError::DeleteAccountHasRent { account_id, balance } => write!( + f, + "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", + account_id, balance + ), + ActionError::FunctionCallError(s) => write!(f, "{}", s), + } } } /// Error returned in the ExecutionOutcome in case of failure. -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] pub enum ExecutionError { + Action(ActionError), InvalidTx(InvalidTxError), } @@ -366,8 +359,8 @@ impl From for ExecutionError { } } -impl From for ExecutionError { - fn from(error: InvalidTxErrorKind) -> Self { +impl From for ExecutionError { + fn from(error: InvalidTxError) -> Self { ExecutionError::InvalidTx(error) } } diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 758907b9c14..58194b2e1d3 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -707,7 +707,7 @@ impl From for ExecutionErrorView { ActionError::RentUnpaid { .. } => "ActionError::RentUnpaid".to_string(), ActionError::TriesToUnstake { .. } => "ActionError::TriesToUnstake".to_string(), ActionError::TriesToStake { .. } => "ActionError::TriesToStake".to_string(), - ActionError::FunctionCall { .. } => "ActionError::FunctionCall".to_string(), + ActionError::FunctionCallError { .. } => "ActionError::FunctionCall".to_string(), }, ExecutionError::InvalidTx(e) => match e { InvalidTxError::InvalidSigner { .. } => "InvalidTxError::InvalidSigner".to_string(), From bc9910c3d21551995443f2b048d55c992bf59eb6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 18 Dec 2019 18:26:54 +0300 Subject: [PATCH 04/48] revert changes (rename fields) --- core/primitives/src/errors.rs | 12 ++++++------ core/primitives/src/views.rs | 2 +- runtime/runtime/src/actions.rs | 34 +++++++++++++++++----------------- runtime/runtime/src/lib.rs | 14 +++++++------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 0d565748df4..3ee88484e98 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -70,14 +70,14 @@ pub enum ActionError { AccountDoesNotExist { action: String, account_id: AccountId }, CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId }, ActorNoPermission { account_id: AccountId, actor_id: AccountId, action: String }, - DeleteKeyDoesNotExist { account_id: AccountId }, - AddKeyAlreadyExists { public_key: PublicKey }, + DeleteKeyDoesNotExist { account_id: AccountId, public_key: PublicKey }, + AddKeyAlreadyExists { account_id: AccountId, public_key: PublicKey }, DeleteAccountStaking { account_id: AccountId }, DeleteAccountHasRent { account_id: AccountId, balance: Balance }, RentUnpaid { account_id: AccountId, amount: Balance }, TriesToUnstake { account_id: AccountId }, TriesToStake { account_id: AccountId, stake: Balance, locked: Balance, balance: Balance }, - FunctionCallError(String), // TODO type + FunctionCall(String), // TODO type } impl Display for InvalidTxError { @@ -314,12 +314,12 @@ impl Display for ActionError { "The new account_id {:?} can't be created by {:?}", account_id, predecessor_id ), - ActionError::DeleteKeyDoesNotExist { account_id } => write!( + ActionError::DeleteKeyDoesNotExist { account_id, .. } => write!( f, "Account {:?} tries to remove an access key that doesn't exist", account_id ), - ActionError::AddKeyAlreadyExists { public_key } => write!( + ActionError::AddKeyAlreadyExists { public_key, .. } => write!( f, "The public key {:?} is already used for an existing access key", public_key @@ -332,7 +332,7 @@ impl Display for ActionError { "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", account_id, balance ), - ActionError::FunctionCallError(s) => write!(f, "{}", s), + ActionError::FunctionCall(s) => write!(f, "{}", s), } } } diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 58194b2e1d3..758907b9c14 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -707,7 +707,7 @@ impl From for ExecutionErrorView { ActionError::RentUnpaid { .. } => "ActionError::RentUnpaid".to_string(), ActionError::TriesToUnstake { .. } => "ActionError::TriesToUnstake".to_string(), ActionError::TriesToStake { .. } => "ActionError::TriesToStake".to_string(), - ActionError::FunctionCallError { .. } => "ActionError::FunctionCall".to_string(), + ActionError::FunctionCall { .. } => "ActionError::FunctionCall".to_string(), }, ExecutionError::InvalidTx(e) => match e { InvalidTxError::InvalidSigner { .. } => "InvalidTxError::InvalidSigner".to_string(), diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 0a73fa0d1fc..08b49fccc28 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -122,7 +122,7 @@ pub(crate) fn action_function_call( let error = VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::CodeDoesNotExist(account_id.clone()), )); - result.result = Err(ActionError::FunctionCall(error)); + result.result = Err(ActionError::FunctionCall(error.to_string())); return Ok(()); } Err(e) => { @@ -179,7 +179,7 @@ pub(crate) fn action_function_call( borsh::BorshDeserialize::try_from_slice(&storage).expect("Borsh cannot fail"); return Err(err); } - result.result = Err(ActionError::FunctionCall(err)); + result.result = Err(ActionError::FunctionCall(err.to_string())); if let Some(outcome) = outcome { result.gas_burnt += outcome.burnt_gas; result.gas_burnt_for_function_call += outcome.burnt_gas; @@ -215,7 +215,7 @@ pub(crate) fn action_stake( if account.amount >= increment { if account.locked == 0 && stake.stake == 0 { // if the account hasn't staked, it cannot unstake - result.result = Err(ActionError::TriesToUnstake { receiver_id: account_id.clone() }); + result.result = Err(ActionError::TriesToUnstake { account_id: account_id.clone() }); return; } result.validator_proposals.push(ValidatorStake { @@ -229,10 +229,10 @@ pub(crate) fn action_stake( } } else { result.result = Err(ActionError::TriesToStake { - receiver_id: account_id.clone(), + account_id: account_id.clone(), stake: stake.stake, - staked: account.locked, - amount: account.amount, + locked: account.locked, + balance: account.amount, }); } } @@ -254,8 +254,8 @@ pub(crate) fn action_create_account( && !is_valid_sub_account_id(&receipt.predecessor_id, account_id) { result.result = Err(ActionError::CreateAccountNotAllowed { - receiver_id: account_id.clone(), - sender_id: receipt.predecessor_id.clone(), + account_id: account_id.clone(), + predecessor_id: receipt.predecessor_id.clone(), }); return; } @@ -319,7 +319,7 @@ pub(crate) fn action_delete_key( if access_key.is_none() { result.result = Err(ActionError::DeleteKeyDoesNotExist { public_key: delete_key.public_key.clone(), - receiver_id: account_id.clone(), + account_id: account_id.clone(), }); return Ok(()); } @@ -347,7 +347,7 @@ pub(crate) fn action_add_key( let account = account.as_mut().unwrap(); if get_access_key(state_update, account_id, &add_key.public_key)?.is_some() { result.result = Err(ActionError::AddKeyAlreadyExists { - receiver_id: account_id.to_owned(), + account_id: account_id.to_owned(), public_key: add_key.public_key.clone(), }); return Ok(()); @@ -376,15 +376,15 @@ pub(crate) fn check_actor_permissions( Action::DeployContract(_) | Action::Stake(_) | Action::AddKey(_) | Action::DeleteKey(_) => { if actor_id != account_id { return Err(ActionError::ActorNoPermission { - sender_id: actor_id.clone(), - receiver_id: account_id.clone(), + account_id: actor_id.clone(), + actor_id: account_id.clone(), action: action_type_as_string(action).to_owned(), }); } } Action::DeleteAccount(_) => { if account.as_ref().unwrap().locked != 0 { - return Err(ActionError::DeleteAccountStaking { receiver_id: account_id.clone() }); + return Err(ActionError::DeleteAccountStaking { account_id: account_id.clone() }); } if actor_id != account_id && check_rent( @@ -396,8 +396,8 @@ pub(crate) fn check_actor_permissions( .is_ok() { return Err(ActionError::DeleteAccountHasRent { - receiver_id: account_id.clone(), - amount: account.as_ref().unwrap().amount, + account_id: account_id.clone(), + balance: account.as_ref().unwrap().amount, }); } } @@ -427,7 +427,7 @@ pub(crate) fn check_account_existence( match action { Action::CreateAccount(_) => { if account.is_some() { - return Err(ActionError::AccountAlreadyExists { receiver_id: account_id.clone() }); + return Err(ActionError::AccountAlreadyExists { account_id: account_id.clone() }); } } Action::DeployContract(_) @@ -440,7 +440,7 @@ pub(crate) fn check_account_existence( if account.is_none() { return Err(ActionError::AccountDoesNotExist { action: action_type_as_string(action).to_owned(), - receiver_id: account_id.clone(), + account_id: account_id.clone(), }); } } diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index 619786e3908..404abc14bcb 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -276,7 +276,7 @@ impl Runtime { signer.amount = signer.amount.checked_sub(total_cost).ok_or_else(|| { InvalidTxError::NotEnoughBalance { - sender_id: signer_id.clone(), + signer_id: signer_id.clone(), balance: signer.amount, cost: total_cost, } @@ -288,9 +288,9 @@ impl Runtime { if let Some(ref mut allowance) = function_call_permission.allowance { *allowance = allowance.checked_sub(total_cost).ok_or_else(|| { InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::NotEnoughAllowance { - signer_id: signer_id.clone(), + account_id: signer_id.clone(), public_key: transaction.public_key.clone(), - allowed: *allowance, + allowance: *allowance, cost: total_cost, }) })?; @@ -299,7 +299,7 @@ impl Runtime { if let Err(amount) = check_rent(&signer_id, &signer, &self.config, apply_state.epoch_length) { - return Err(InvalidTxError::RentUnpaid { account_id: signer_id.clone(), amount }.into()); + return Err(InvalidTxError::RentUnpaid { signer_id: signer_id.clone(), amount }.into()); } if let AccessKeyPermission::FunctionCall(ref function_call_permission) = @@ -314,8 +314,8 @@ impl Runtime { if transaction.receiver_id != function_call_permission.receiver_id { return Err(InvalidTxError::InvalidAccessKey( InvalidAccessKeyError::ReceiverMismatch { - tx_receiver_id: transaction.receiver_id.clone(), - ak_receiver_id: function_call_permission.receiver_id.clone(), + tx_receiver: transaction.receiver_id.clone(), + ak_receiver: function_call_permission.receiver_id.clone(), }, ) .into()); @@ -618,7 +618,7 @@ impl Runtime { { result.merge(ActionResult { result: Err(ActionError::RentUnpaid { - receiver_id: account_id.clone(), + account_id: account_id.clone(), amount, }), ..Default::default() From ad1e8307b981d30c3d76ad4c32f37de111485fff Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 18 Dec 2019 20:58:13 +0300 Subject: [PATCH 05/48] test pass --- .../near-vm-runner/tests/test_rs_contract.rs | 4 +- runtime/runtime/tests/test_evil_contracts.rs | 6 +- test-utils/testlib/src/standard_test_cases.rs | 101 ++++++++---------- 3 files changed, 50 insertions(+), 61 deletions(-) diff --git a/runtime/near-vm-runner/tests/test_rs_contract.rs b/runtime/near-vm-runner/tests/test_rs_contract.rs index ce42116b1c4..80069fd08a4 100644 --- a/runtime/near-vm-runner/tests/test_rs_contract.rs +++ b/runtime/near-vm-runner/tests/test_rs_contract.rs @@ -1,5 +1,5 @@ use near_runtime_fees::RuntimeFeesConfig; -use near_vm_errors::FunctionCallError; +use near_vm_errors::FunctionCall; use near_vm_logic::mocks::mock_external::MockedExternal; use near_vm_logic::types::ReturnData; use near_vm_logic::{VMConfig, VMContext, VMOutcome}; @@ -174,6 +174,6 @@ pub fn test_out_of_memory() { ); assert_eq!( result.1, - Some(VMError::FunctionCallError(FunctionCallError::WasmTrap("unknown".to_string()))) + Some(VMError::FunctionCall(FunctionCall::WasmTrap("unknown".to_string()))) ); } diff --git a/runtime/runtime/tests/test_evil_contracts.rs b/runtime/runtime/tests/test_evil_contracts.rs index fa61aa12578..7508dac7c62 100644 --- a/runtime/runtime/tests/test_evil_contracts.rs +++ b/runtime/runtime/tests/test_evil_contracts.rs @@ -142,9 +142,9 @@ fn test_evil_abort() { .unwrap(); assert_eq!( res.status, - FinalExecutionStatus::Failure(ActionError::FunctionCallError(VMError::FunctionExecError( - FunctionExecError::HostError(HostError::BadUTF16) - ))), + FinalExecutionStatus::Failure( + ActionError::FunctionCall("String encoding is bad UTF-16 sequence.".to_string()).into() + ), "{:?}", res ); diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index ff351f5dee8..7eaeb3f2861 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -9,7 +9,6 @@ use near_primitives::serialize::to_base64; use near_primitives::types::Balance; use near_primitives::views::FinalExecutionStatus; use near_primitives::views::{AccountView, FinalExecutionOutcomeView}; -use near_vm_errors::{FunctionExecError, HostError, MethodResolveError, VMError}; use crate::fees_utils::FeeHelper; use crate::node::Node; @@ -62,22 +61,19 @@ pub fn test_smart_contract_simple(node: impl Node) { assert_ne!(root, new_root); } -// pub fn test_smart_contract_panic(node: impl Node) { -// let node_user = node.user(); -// let transaction_result = node_user -// .function_call(alice_account(), alice_account(), "panic_with_message", vec![], 1000000, 0) -// .unwrap(); -// assert_eq!( -// transaction_result.status, -// FinalExecutionStatus::Failure( -// ActionError::FunctionCallError(VMError::FunctionExecError( -// FunctionExecError::HostError(HostError::GuestPanic("WAT?".to_owned())) -// )) -// .into() -// ) -// ); -// assert_eq!(transaction_result.receipts.len(), 2); -// } +pub fn test_smart_contract_panic(node: impl Node) { + let node_user = node.user(); + let transaction_result = node_user + .function_call(alice_account(), alice_account(), "panic_with_message", vec![], 1000000, 0) + .unwrap(); + assert_eq!( + transaction_result.status, + FinalExecutionStatus::Failure( + ActionError::FunctionCall("Smart contract panicked: WAT?".to_string()).into() + ) + ); + assert_eq!(transaction_result.receipts.len(), 2); +} pub fn test_smart_contract_self_call(node: impl Node) { let account_id = &node.account_id().unwrap(); @@ -105,10 +101,7 @@ pub fn test_smart_contract_bad_method_name(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCallError(VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodNotFound) - )) - .into() + ActionError::FunctionCall("MethodNotFound".to_string()).into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -125,10 +118,7 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCallError(VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) - )) - .into() + ActionError::FunctionCall("MethodEmptyName".to_string()).into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -136,24 +126,23 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { assert_ne!(root, new_root); } -// pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { -// let account_id = &node.account_id().unwrap(); -// let node_user = node.user(); -// let root = node_user.get_state_root(); -// let transaction_result = node_user -// .function_call(account_id.clone(), bob_account(), "", vec![], 1000000, 10) -// .unwrap(); -// assert_eq!( -// transaction_result.status, -// FinalExecutionStatus::Failure(ActionError::FunctionCallError(VMError::FunctionExecError( -// FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) -// ))) -// .into() -// ); -// assert_eq!(transaction_result.receipts.len(), 2); -// let new_root = node_user.get_state_root(); -// assert_ne!(root, new_root); -// } +pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { + let account_id = &node.account_id().unwrap(); + let node_user = node.user(); + let root = node_user.get_state_root(); + let transaction_result = node_user + .function_call(account_id.clone(), bob_account(), "", vec![], 1000000, 10) + .unwrap(); + assert_eq!( + transaction_result.status, + FinalExecutionStatus::Failure( + ActionError::FunctionCall("MethodEmptyName".to_string()).into() + ) + ); + assert_eq!(transaction_result.receipts.len(), 2); + let new_root = node_user.get_state_root(); + assert_ne!(root, new_root); +} pub fn test_smart_contract_with_args(node: impl Node) { let account_id = &node.account_id().unwrap(); @@ -189,7 +178,7 @@ pub fn test_async_call_with_logs(node: impl Node) { assert_eq!(transaction_result.receipts.len(), 2); let new_root = node_user.get_state_root(); assert_ne!(root, new_root); - assert_eq!(transaction_result.receipts[0].outcome.logs[0], "LOG: hello".to_string()); + assert_eq!(transaction_result.receipts[0].outcome.logs[0], "hello".to_string()); } pub fn test_nonce_update_when_deploying_contract(node: impl Node) { @@ -350,7 +339,7 @@ pub fn test_refund_on_send_money_to_non_existent_account(node: impl Node) { FinalExecutionStatus::Failure( ActionError::AccountDoesNotExist { action: "Transfer".to_string(), - receiver_id: eve_dot_alice_account() + account_id: eve_dot_alice_account() } .into() ) @@ -443,7 +432,7 @@ pub fn test_create_account_again(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountAlreadyExists { receiver_id: eve_dot_alice_account() }.into() + ActionError::AccountAlreadyExists { account_id: eve_dot_alice_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -506,7 +495,7 @@ pub fn test_create_account_failure_already_exists(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountAlreadyExists { receiver_id: bob_account() }.into() + ActionError::AccountAlreadyExists { account_id: bob_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -585,8 +574,8 @@ pub fn test_add_existing_key(node: impl Node) { transaction_result.status, FinalExecutionStatus::Failure( ActionError::AddKeyAlreadyExists { - receiver_id: account_id.clone(), - public_key: node.signer().public_key().clone() + account_id: account_id.clone(), + public_key: node.signer().public_key() } .into() ) @@ -634,7 +623,7 @@ pub fn test_delete_key_not_owned(node: impl Node) { transaction_result.status, FinalExecutionStatus::Failure( ActionError::DeleteKeyDoesNotExist { - receiver_id: account_id.clone(), + account_id: account_id.clone(), public_key: signer2.public_key.clone() } .into() @@ -875,8 +864,8 @@ pub fn test_access_key_smart_contract_reject_contract_id(node: impl Node) { format!( "{}", InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ReceiverMismatch { - tx_receiver_id: eve_dot_alice_account(), - ak_receiver_id: bob_account() + tx_receiver: eve_dot_alice_account(), + ak_receiver: bob_account() }) ) ); @@ -958,7 +947,7 @@ pub fn test_unstake_while_not_staked(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::TriesToUnstake { receiver_id: eve_dot_alice_account() }.into() + ActionError::TriesToUnstake { account_id: eve_dot_alice_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -1035,7 +1024,7 @@ pub fn test_delete_account_fail(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteAccountStaking { receiver_id: bob_account() }.into() + ActionError::DeleteAccountStaking { account_id: bob_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -1055,7 +1044,7 @@ pub fn test_delete_account_no_account(node: impl Node) { FinalExecutionStatus::Failure( ActionError::AccountDoesNotExist { action: "DeleteAccount".to_string(), - receiver_id: eve_dot_alice_account() + account_id: eve_dot_alice_account() } .into() ) @@ -1084,7 +1073,7 @@ pub fn test_delete_account_while_staking(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteAccountStaking { receiver_id: eve_dot_alice_account() }.into() + ActionError::DeleteAccountStaking { account_id: eve_dot_alice_account() }.into() ) ); assert_eq!(transaction_result.receipts.len(), 1); From 4cd0ff52b4cd161ec6a4ae6923edf0169cb08845 Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 19 Dec 2019 19:05:00 +0300 Subject: [PATCH 06/48] error view update --- chain/jsonrpc/src/lib.rs | 10 ++--- core/primitives/src/errors.rs | 13 +++--- core/primitives/src/views.rs | 74 ++--------------------------------- 3 files changed, 13 insertions(+), 84 deletions(-) diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index 4f81fbc0d82..5336fc80ccc 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -119,14 +119,11 @@ fn parse_hash(params: Option) -> Result { } fn convert_mailbox_error(e: MailboxError) -> ExecutionErrorView { - ExecutionErrorView { error_message: e.to_string(), error_type: "MailBoxError".to_string() } + ExecutionErrorView { error: "MailBoxError".to_string() } } fn timeout_err() -> RpcError { - RpcError::server_error(Some(ExecutionErrorView { - error_message: "send_tx_commit has timed out".to_string(), - error_type: "TimeoutError".to_string(), - })) + RpcError::server_error(Some(ExecutionErrorView { error: "TimeoutError".to_string() })) } struct JsonRpcHandler { @@ -222,8 +219,7 @@ impl JsonRpcHandler { } NetworkClientResponses::NoResponse => { Err(RpcError::server_error(Some(ExecutionErrorView { - error_message: "send_tx_commit has timed out".to_string(), - error_type: "TimeoutError".to_string(), + error: "TimeoutError".to_string(), }))) } _ => unreachable!(), diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 3ee88484e98..419311c0290 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -1,6 +1,7 @@ use crate::types::{AccountId, Balance, Nonce}; use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::PublicKey; +use serde::{Deserialize, Serialize}; use std::fmt::Display; /// Internal @@ -27,7 +28,7 @@ impl std::fmt::Display for StorageError { impl std::error::Error for StorageError {} /// External -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub enum InvalidTxError { InvalidAccessKey(InvalidAccessKeyError), InvalidSigner { signer_id: AccountId }, @@ -42,7 +43,7 @@ pub enum InvalidTxError { Expired, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub enum InvalidAccessKeyError { AccessKeyNotFound { account_id: AccountId, @@ -64,7 +65,7 @@ pub enum InvalidAccessKeyError { }, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub enum ActionError { AccountAlreadyExists { account_id: AccountId }, AccountDoesNotExist { action: String, account_id: AccountId }, @@ -164,7 +165,7 @@ impl Display for InvalidAccessKeyError { } /// Happens when the input balance doesn't match the output balance in Runtime apply. -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct BalanceMismatchError { // Input balances pub incoming_validator_rewards: Balance, @@ -238,7 +239,7 @@ impl Display for BalanceMismatchError { } } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct IntegerOverflowError; /// Error returned from `Runtime::apply` @@ -338,7 +339,7 @@ impl Display for ActionError { } /// Error returned in the ExecutionOutcome in case of failure. -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub enum ExecutionError { Action(ActionError), InvalidTx(InvalidTxError), diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 758907b9c14..f18cab1d3e9 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -10,7 +10,7 @@ use near_crypto::{PublicKey, Signature}; use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission}; use crate::block::{Approval, Block, BlockHeader, BlockHeaderInnerLite, BlockHeaderInnerRest}; use crate::challenge::{Challenge, ChallengesResult}; -use crate::errors::{ActionError, ExecutionError, InvalidAccessKeyError, InvalidTxError}; +use crate::errors::{ActionError, ExecutionError, InvalidTxError}; use crate::hash::CryptoHash; use crate::logging; use crate::merkle::MerklePath; @@ -672,80 +672,12 @@ impl Default for FinalExecutionStatus { BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default, )] pub struct ExecutionErrorView { - pub error_message: String, - pub error_type: String, + pub error: String, } impl From for ExecutionErrorView { fn from(error: ExecutionError) -> Self { - let error_type = match &error { - ExecutionError::Action(e) => match e { - ActionError::AccountAlreadyExists { .. } => { - "ActionError::AccountAlreadyExists".to_string() - } - ActionError::AccountDoesNotExist { .. } => { - "ActionError::AccountDoesNotExist".to_string() - } - ActionError::CreateAccountNotAllowed { .. } => { - "ActionError::CreateAccountNotAllowed".to_string() - } - ActionError::ActorNoPermission { .. } => { - "ActionError::ActorNoPermission".to_string() - } - ActionError::DeleteKeyDoesNotExist { .. } => { - "ActionError::DeleteKeyDoesNotExist".to_string() - } - ActionError::AddKeyAlreadyExists { .. } => { - "ActionError::AddKeyAlreadyExists".to_string() - } - ActionError::DeleteAccountStaking { .. } => { - "ActionError::DeleteAccountStaking".to_string() - } - ActionError::DeleteAccountHasRent { .. } => { - "ActionError::DeleteAccountHasRent".to_string() - } - ActionError::RentUnpaid { .. } => "ActionError::RentUnpaid".to_string(), - ActionError::TriesToUnstake { .. } => "ActionError::TriesToUnstake".to_string(), - ActionError::TriesToStake { .. } => "ActionError::TriesToStake".to_string(), - ActionError::FunctionCall { .. } => "ActionError::FunctionCall".to_string(), - }, - ExecutionError::InvalidTx(e) => match e { - InvalidTxError::InvalidSigner { .. } => "InvalidTxError::InvalidSigner".to_string(), - InvalidTxError::SignerDoesNotExist { .. } => { - "InvalidTxError::SignerDoesNotExist".to_string() - } - InvalidTxError::InvalidAccessKey(e) => match e { - InvalidAccessKeyError::AccessKeyNotFound { .. } => { - "InvalidTxError::InvalidAccessKey::AccessKeyNotFound".to_string() - } - InvalidAccessKeyError::ReceiverMismatch { .. } => { - "InvalidTxError::InvalidAccessKey::ReceiverMismatch".to_string() - } - InvalidAccessKeyError::MethodNameMismatch { .. } => { - "InvalidTxError::InvalidAccessKey::MethodNameMismatch".to_string() - } - InvalidAccessKeyError::ActionError => { - "InvalidTxError::InvalidAccessKey::ActionError".to_string() - } - InvalidAccessKeyError::NotEnoughAllowance { .. } => { - "InvalidTxError::InvalidAccessKey::NotEnoughAllowance".to_string() - } - }, - InvalidTxError::InvalidNonce { .. } => "InvalidTxError::InvalidNonce".to_string(), - InvalidTxError::InvalidReceiver { .. } => { - "InvalidTxError::InvalidReceiver".to_string() - } - InvalidTxError::InvalidSignature => "InvalidTxError::InvalidSignature".to_string(), - InvalidTxError::NotEnoughBalance { .. } => { - "InvalidTxError::NotEnoughBalance".to_string() - } - InvalidTxError::RentUnpaid { .. } => "InvalidTxError::RentUnpaid".to_string(), - InvalidTxError::CostOverflow => "InvalidTxError::CostOverflow".to_string(), - InvalidTxError::InvalidChain => "InvalidTxError::InvalidChain".to_string(), - InvalidTxError::Expired => "InvalidTxError::Expired".to_string(), - }, - }; - ExecutionErrorView { error_message: format!("{}", error), error_type } + Self { error: serde_json::to_string(&error).expect("error serialize cannot fail") } } } From 5fc2e6197dd52bd8dfff96a3fb17fc52234f2fdc Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 19 Dec 2019 21:19:15 +0300 Subject: [PATCH 07/48] WIP --- chain/jsonrpc/src/lib.rs | 29 +++++++++---- core/primitives/src/views.rs | 34 ++++----------- test-utils/testlib/src/standard_test_cases.rs | 34 +++++++-------- test-utils/testlib/src/user/mod.rs | 43 ++++++++++--------- test-utils/testlib/src/user/rpc_user.rs | 12 +++--- test-utils/testlib/src/user/runtime_user.rs | 5 ++- tests/test_errors.rs | 18 ++++---- 7 files changed, 85 insertions(+), 90 deletions(-) diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index 5336fc80ccc..c8959328ab6 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -25,11 +25,12 @@ pub use near_jsonrpc_client as client; use near_jsonrpc_client::{message, BlockId, ChunkId}; use near_metrics::{Encoder, TextEncoder}; use near_network::{NetworkClientMessages, NetworkClientResponses}; +use near_primitives::errors::ExecutionError; use near_primitives::hash::CryptoHash; use near_primitives::serialize::{from_base, from_base64, BaseEncode}; use near_primitives::transaction::SignedTransaction; use near_primitives::types::AccountId; -use near_primitives::views::{ExecutionErrorView, FinalExecutionStatus}; +use near_primitives::views::FinalExecutionStatus; mod metrics; pub mod test_utils; @@ -118,12 +119,24 @@ fn parse_hash(params: Option) -> Result { }) } -fn convert_mailbox_error(e: MailboxError) -> ExecutionErrorView { - ExecutionErrorView { error: "MailBoxError".to_string() } +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub enum ServerError { + TxExecutionError(ExecutionError), + Timeout, + Closed, +} + +impl From for ServerError { + fn from(e: MailboxError) -> Self { + match e { + MailboxError::Closed => ServerError::Closed, + MailboxError::Timeout => ServerError::Timeout, + } + } } fn timeout_err() -> RpcError { - RpcError::server_error(Some(ExecutionErrorView { error: "TimeoutError".to_string() })) + RpcError::server_error(Some(ServerError::Timeout)) } struct JsonRpcHandler { @@ -207,7 +220,7 @@ impl JsonRpcHandler { let result = self .client_addr .send(NetworkClientMessages::Transaction(tx)) - .map_err(|err| RpcError::server_error(Some(convert_mailbox_error(err)))) + .map_err(|err| RpcError::server_error(Some(ServerError::from(err)))) .compat() .await?; match result { @@ -215,12 +228,10 @@ impl JsonRpcHandler { self.tx_polling(tx_hash, signer_account_id).await } NetworkClientResponses::InvalidTx(err) => { - Err(RpcError::server_error(Some(ExecutionErrorView::from(err)))) + Err(RpcError::server_error(Some(ServerError::TxExecutionError(err.into())))) } NetworkClientResponses::NoResponse => { - Err(RpcError::server_error(Some(ExecutionErrorView { - error: "TimeoutError".to_string(), - }))) + Err(RpcError::server_error(Some(ServerError::Timeout))) } _ => unreachable!(), } diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index f18cab1d3e9..25d5eadc1c3 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -643,7 +643,7 @@ pub enum FinalExecutionStatus { /// The execution has started and still going. Started, /// The execution has failed with the given error. - Failure(ExecutionErrorView), + Failure(ExecutionError), /// The execution has succeeded and returned some value or an empty vec encoded in base64. SuccessValue(String), } @@ -668,29 +668,11 @@ impl Default for FinalExecutionStatus { } } -#[derive( - BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default, -)] -pub struct ExecutionErrorView { - pub error: String, -} - -impl From for ExecutionErrorView { - fn from(error: ExecutionError) -> Self { - Self { error: serde_json::to_string(&error).expect("error serialize cannot fail") } - } -} - -impl From for ExecutionErrorView { - fn from(error: ActionError) -> Self { - ExecutionError::Action(error).into() - } -} - -impl From for ExecutionErrorView { - fn from(error: InvalidTxError) -> Self { - ExecutionError::InvalidTx(error).into() - } +#[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub enum ServerError { + TxExecutionError(ExecutionError), + Timeout, + Closed, } #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, PartialEq, Eq, Clone)] @@ -698,7 +680,7 @@ pub enum ExecutionStatusView { /// The execution is pending or unknown. Unknown, /// The execution has failed. - Failure(ExecutionErrorView), + Failure(ExecutionError), /// The final action succeeded and returned some value or an empty vec encoded in base64. SuccessValue(String), /// The final action of the receipt returned a promise or the signed transaction was converted @@ -726,7 +708,7 @@ impl From for ExecutionStatusView { fn from(outcome: ExecutionStatus) -> Self { match outcome { ExecutionStatus::Unknown => ExecutionStatusView::Unknown, - ExecutionStatus::Failure(e) => ExecutionStatusView::Failure(e.into()), + ExecutionStatus::Failure(e) => ExecutionStatusView::Failure(e), ExecutionStatus::SuccessValue(v) => ExecutionStatusView::SuccessValue(to_base64(&v)), ExecutionStatus::SuccessReceiptId(receipt_id) => { ExecutionStatusView::SuccessReceiptId(receipt_id) diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index 7eaeb3f2861..2e58630f4ac 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -2,8 +2,9 @@ use std::sync::Arc; use near::config::{TESTING_INIT_BALANCE, TESTING_INIT_STAKE}; use near_crypto::{InMemorySigner, KeyType}; +use near_jsonrpc::ServerError; use near_primitives::account::{AccessKey, AccessKeyPermission, FunctionCallPermission}; -use near_primitives::errors::{ActionError, InvalidAccessKeyError, InvalidTxError}; +use near_primitives::errors::{ActionError, ExecutionError, InvalidAccessKeyError, InvalidTxError}; use near_primitives::hash::hash; use near_primitives::serialize::to_base64; use near_primitives::types::Balance; @@ -472,10 +473,9 @@ pub fn test_create_account_failure_invalid_name(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - format!( - "{}", + ServerError::TxExecutionError(ExecutionError::InvalidTx( InvalidTxError::InvalidReceiver { receiver_id: invalid_account_name.to_string() } - ) + )) ); } } @@ -832,12 +832,9 @@ pub fn test_access_key_smart_contract_reject_method_name(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - format!( - "{}", - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::MethodNameMismatch { - method_name: "run_test".to_string() - }) - ) + ServerError::TxExecutionError(ExecutionError::InvalidTx(InvalidTxError::InvalidAccessKey( + InvalidAccessKeyError::MethodNameMismatch { method_name: "run_test".to_string() } + ))) ); } @@ -861,13 +858,12 @@ pub fn test_access_key_smart_contract_reject_contract_id(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - format!( - "{}", - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ReceiverMismatch { + ServerError::TxExecutionError(ExecutionError::InvalidTx(InvalidTxError::InvalidAccessKey( + InvalidAccessKeyError::ReceiverMismatch { tx_receiver: eve_dot_alice_account(), ak_receiver: bob_account() - }) - ) + } + ))) ); } @@ -890,7 +886,9 @@ pub fn test_access_key_reject_non_function_call(node: impl Node) { node_user.delete_key(account_id.clone(), node.signer().public_key()).unwrap_err(); assert_eq!( transaction_result, - format!("{}", InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ActionError)) + ServerError::TxExecutionError(ExecutionError::InvalidTx(InvalidTxError::InvalidAccessKey( + InvalidAccessKeyError::ActionError + ))) ); } @@ -981,7 +979,9 @@ fn test_stake_fail_not_enough_rent_with_balance(node: impl Node, initial_balance node_user.stake(new_account_id.clone(), node.block_signer().public_key(), 5).unwrap(); assert_matches!( &transaction_result.status, - FinalExecutionStatus::Failure(e) if e.error_type == "ActionError::RentUnpaid" + FinalExecutionStatus::Failure(e) if e == &ExecutionError::Action(ActionError::RentUnpaid{ + account_id: alice_account(), amount: 0u128 + }) ); assert_eq!(transaction_result.receipts.len(), 1); } diff --git a/test-utils/testlib/src/user/mod.rs b/test-utils/testlib/src/user/mod.rs index 8bd50b37514..3f1fc992c76 100644 --- a/test-utils/testlib/src/user/mod.rs +++ b/test-utils/testlib/src/user/mod.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use futures::Future; use near_crypto::{PublicKey, Signer}; +use near_jsonrpc::ServerError; use near_primitives::account::AccessKey; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; @@ -36,7 +37,7 @@ pub trait User { fn commit_transaction( &self, signed_transaction: SignedTransaction, - ) -> Result; + ) -> Result; fn add_receipt(&self, receipt: Receipt) -> Result<(), String>; @@ -72,7 +73,7 @@ pub trait User { signer_id: AccountId, receiver_id: AccountId, actions: Vec, - ) -> Result { + ) -> Result { let block_hash = self.get_best_block_hash().unwrap_or(CryptoHash::default()); let signed_transaction = SignedTransaction::from_actions( self.get_access_key_nonce_for_signer(&signer_id).unwrap_or_default() + 1, @@ -90,7 +91,7 @@ pub trait User { signer_id: AccountId, receiver_id: AccountId, amount: Balance, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id, receiver_id, @@ -102,7 +103,7 @@ pub trait User { &self, signer_id: AccountId, code: Vec, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id.clone(), signer_id, @@ -118,7 +119,7 @@ pub trait User { args: Vec, gas: Gas, deposit: Balance, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id, contract_id, @@ -137,7 +138,7 @@ pub trait User { new_account_id: AccountId, public_key: PublicKey, amount: Balance, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id, new_account_id, @@ -154,7 +155,7 @@ pub trait User { signer_id: AccountId, public_key: PublicKey, access_key: AccessKey, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id.clone(), signer_id, @@ -166,7 +167,7 @@ pub trait User { &self, signer_id: AccountId, public_key: PublicKey, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id.clone(), signer_id, @@ -180,7 +181,7 @@ pub trait User { old_public_key: PublicKey, new_public_key: PublicKey, access_key: AccessKey, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id.clone(), signer_id, @@ -195,7 +196,7 @@ pub trait User { &self, signer_id: AccountId, receiver_id: AccountId, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id.clone(), receiver_id, @@ -208,7 +209,7 @@ pub trait User { signer_id: AccountId, public_key: PublicKey, amount: Balance, - ) -> Result { + ) -> Result { self.sign_and_commit_actions( signer_id.clone(), signer_id, @@ -222,49 +223,49 @@ pub trait AsyncUser: Send + Sync { fn view_account( &self, account_id: &AccountId, - ) -> Box>; + ) -> Box>; fn view_balance( &self, account_id: &AccountId, - ) -> Box> { + ) -> Box> { Box::new(self.view_account(account_id).map(|acc| acc.amount)) } fn view_state( &self, account_id: &AccountId, - ) -> Box>; + ) -> Box>; fn add_transaction( &self, transaction: SignedTransaction, - ) -> Box + Send>; + ) -> Box + Send>; - fn add_receipt(&self, receipt: Receipt) -> Box>; + fn add_receipt(&self, receipt: Receipt) -> Box>; fn get_account_nonce( &self, account_id: &AccountId, ) -> Box>; - fn get_best_block_index(&self) -> Box>; + fn get_best_block_index(&self) -> Box>; fn get_transaction_result( &self, hash: &CryptoHash, - ) -> Box>; + ) -> Box>; fn get_transaction_final_result( &self, hash: &CryptoHash, - ) -> Box>; + ) -> Box>; - fn get_state_root(&self) -> Box>; + fn get_state_root(&self) -> Box>; fn get_access_key( &self, account_id: &AccountId, public_key: &PublicKey, - ) -> Box, Error = String>>; + ) -> Box, Error = ServerError>>; } diff --git a/test-utils/testlib/src/user/rpc_user.rs b/test-utils/testlib/src/user/rpc_user.rs index 8f7750e1b80..ba5547f3f4b 100644 --- a/test-utils/testlib/src/user/rpc_user.rs +++ b/test-utils/testlib/src/user/rpc_user.rs @@ -9,15 +9,17 @@ use borsh::BorshSerialize; use near_client::StatusResponse; use near_crypto::{PublicKey, Signer}; use near_jsonrpc::client::{new_client, JsonRpcClient}; +use near_jsonrpc::ServerError; use near_jsonrpc_client::BlockId; +use near_primitives::errors::ExecutionError; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; use near_primitives::serialize::{to_base, to_base64}; use near_primitives::transaction::SignedTransaction; use near_primitives::types::AccountId; use near_primitives::views::{ - AccessKeyView, AccountView, BlockView, ExecutionErrorView, ExecutionOutcomeView, - FinalExecutionOutcomeView, QueryResponse, ViewStateResult, + AccessKeyView, AccountView, BlockView, ExecutionOutcomeView, FinalExecutionOutcomeView, + QueryResponse, ViewStateResult, }; use crate::user::User; @@ -64,7 +66,7 @@ impl User for RpcUser { fn commit_transaction( &self, transaction: SignedTransaction, - ) -> Result { + ) -> Result { let bytes = transaction.try_to_vec().unwrap(); let result = System::new("actix") .block_on(self.client.write().unwrap().broadcast_tx_commit(to_base64(&bytes))); @@ -75,9 +77,7 @@ impl User for RpcUser { } match result { Ok(outcome) => Ok(outcome), - Err(err) => Err(serde_json::from_value::(err.data.unwrap()) - .unwrap() - .error_message), + Err(err) => Err(serde_json::from_value::(err.data.unwrap()).unwrap()), } } diff --git a/test-utils/testlib/src/user/runtime_user.rs b/test-utils/testlib/src/user/runtime_user.rs index 5de57abdc1f..3068bb4c76b 100644 --- a/test-utils/testlib/src/user/runtime_user.rs +++ b/test-utils/testlib/src/user/runtime_user.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::{Arc, RwLock}; use near_crypto::{PublicKey, Signer}; +use near_jsonrpc::ServerError; use near_primitives::errors::RuntimeError; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; @@ -64,7 +65,7 @@ impl RuntimeUser { apply_state: ApplyState, prev_receipts: Vec, transactions: Vec, - ) -> Result<(), String> { + ) -> Result<(), ServerError> { let mut receipts = prev_receipts; let mut txs = transactions; loop { @@ -190,7 +191,7 @@ impl User for RuntimeUser { fn commit_transaction( &self, transaction: SignedTransaction, - ) -> Result { + ) -> Result { self.apply_all(self.apply_state(), vec![], vec![transaction.clone()])?; Ok(self.get_transaction_final_result(&transaction.get_hash())) } diff --git a/tests/test_errors.rs b/tests/test_errors.rs index 8bacd81c1ef..a2f0520d5d8 100644 --- a/tests/test_errors.rs +++ b/tests/test_errors.rs @@ -49,10 +49,10 @@ fn test_check_tx_error_log() { tx_result, format!( "{}", - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::AccessKeyNotFound( - "bob.near".to_string(), - signer.public_key.clone() - )) + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::AccessKeyNotFound { + account_id: "bob.near".to_string(), + public_key: signer.public_key.clone() + }) ), ); } @@ -88,11 +88,11 @@ fn test_deliver_tx_error_log() { tx_result, format!( "{}", - InvalidTxError::NotEnoughBalance( - "alice.near".to_string(), - TESTING_INIT_BALANCE - TESTING_INIT_STAKE, - TESTING_INIT_BALANCE + 1 + cost - ) + InvalidTxError::NotEnoughBalance { + signer_id: "alice.near".to_string(), + balance: TESTING_INIT_BALANCE - TESTING_INIT_STAKE, + cost: TESTING_INIT_BALANCE + 1 + cost + } ), ); } From 5696c9964a9584a5cfe90b98439559cf16ec914f Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 19 Dec 2019 23:20:28 +0300 Subject: [PATCH 08/48] make it compile --- chain/jsonrpc/src/lib.rs | 14 ++++++++++- test-utils/testlib/src/node/mod.rs | 3 ++- test-utils/testlib/src/user/mod.rs | 4 ++-- test-utils/testlib/src/user/rpc_user.rs | 9 ++++--- test-utils/testlib/src/user/runtime_user.rs | 10 ++++---- tests/test_errors.rs | 26 +++++++++------------ 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index c8959328ab6..1ade4b18cb2 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -25,7 +25,7 @@ pub use near_jsonrpc_client as client; use near_jsonrpc_client::{message, BlockId, ChunkId}; use near_metrics::{Encoder, TextEncoder}; use near_network::{NetworkClientMessages, NetworkClientResponses}; -use near_primitives::errors::ExecutionError; +use near_primitives::errors::{ExecutionError, InvalidTxError}; use near_primitives::hash::CryptoHash; use near_primitives::serialize::{from_base, from_base64, BaseEncode}; use near_primitives::transaction::SignedTransaction; @@ -126,6 +126,12 @@ pub enum ServerError { Closed, } +impl From for ServerError { + fn from(e: InvalidTxError) -> ServerError { + ServerError::TxExecutionError(ExecutionError::InvalidTx(e)) + } +} + impl From for ServerError { fn from(e: MailboxError) -> Self { match e { @@ -135,6 +141,12 @@ impl From for ServerError { } } +impl From for RpcError { + fn from(e: ServerError) -> RpcError { + RpcError::server_error(Some(e)) + } +} + fn timeout_err() -> RpcError { RpcError::server_error(Some(ServerError::Timeout)) } diff --git a/test-utils/testlib/src/node/mod.rs b/test-utils/testlib/src/node/mod.rs index 5224ba93f42..9a95cb66645 100644 --- a/test-utils/testlib/src/node/mod.rs +++ b/test-utils/testlib/src/node/mod.rs @@ -9,6 +9,7 @@ use near::config::{ }; use near::NearConfig; use near_crypto::{InMemorySigner, Signer}; +use near_jsonrpc::ServerError; use near_primitives::serialize::to_base64; use near_primitives::transaction::SignedTransaction; use near_primitives::types::{AccountId, Balance}; @@ -66,7 +67,7 @@ pub trait Node: Send + Sync { self.user().view_balance(account_id) } - fn add_transaction(&self, transaction: SignedTransaction) -> Result<(), String> { + fn add_transaction(&self, transaction: SignedTransaction) -> Result<(), ServerError> { self.user().add_transaction(transaction) } diff --git a/test-utils/testlib/src/user/mod.rs b/test-utils/testlib/src/user/mod.rs index 3f1fc992c76..83adfddfdd3 100644 --- a/test-utils/testlib/src/user/mod.rs +++ b/test-utils/testlib/src/user/mod.rs @@ -32,14 +32,14 @@ pub trait User { fn view_state(&self, account_id: &AccountId, prefix: &[u8]) -> Result; - fn add_transaction(&self, signed_transaction: SignedTransaction) -> Result<(), String>; + fn add_transaction(&self, signed_transaction: SignedTransaction) -> Result<(), ServerError>; fn commit_transaction( &self, signed_transaction: SignedTransaction, ) -> Result; - fn add_receipt(&self, receipt: Receipt) -> Result<(), String>; + fn add_receipt(&self, receipt: Receipt) -> Result<(), ServerError>; fn get_access_key_nonce_for_signer(&self, account_id: &AccountId) -> Result { self.get_access_key(account_id, &self.signer().public_key()) diff --git a/test-utils/testlib/src/user/rpc_user.rs b/test-utils/testlib/src/user/rpc_user.rs index ba5547f3f4b..bbea328e770 100644 --- a/test-utils/testlib/src/user/rpc_user.rs +++ b/test-utils/testlib/src/user/rpc_user.rs @@ -55,11 +55,14 @@ impl User for RpcUser { self.query(format!("contract/{}", account_id), prefix)?.try_into() } - fn add_transaction(&self, transaction: SignedTransaction) -> Result<(), String> { + fn add_transaction(&self, transaction: SignedTransaction) -> Result<(), ServerError> { let bytes = transaction.try_to_vec().unwrap(); let _ = System::new("actix") .block_on(self.client.write().unwrap().broadcast_tx_async(to_base64(&bytes))) - .map_err(|err| err.to_string())?; + .map_err(|e| { + serde_json::from_value::(e.data.expect("server error must carry data")) + .expect("deserialize server error must be ok") + })?; Ok(()) } @@ -81,7 +84,7 @@ impl User for RpcUser { } } - fn add_receipt(&self, _receipt: Receipt) -> Result<(), String> { + fn add_receipt(&self, _receipt: Receipt) -> Result<(), ServerError> { // TDDO: figure out if rpc will support this unimplemented!() } diff --git a/test-utils/testlib/src/user/runtime_user.rs b/test-utils/testlib/src/user/runtime_user.rs index 3068bb4c76b..d3ba67f4e2a 100644 --- a/test-utils/testlib/src/user/runtime_user.rs +++ b/test-utils/testlib/src/user/runtime_user.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, RwLock}; use near_crypto::{PublicKey, Signer}; use near_jsonrpc::ServerError; -use near_primitives::errors::RuntimeError; +use near_primitives::errors::{ExecutionError, RuntimeError}; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; use near_primitives::transaction::SignedTransaction; @@ -82,7 +82,9 @@ impl RuntimeUser { &HashSet::new(), ) .map_err(|e| match e { - RuntimeError::InvalidTxError(e) => format!("{}", e), + RuntimeError::InvalidTxError(e) => { + ServerError::TxExecutionError(ExecutionError::InvalidTx(e)) + } RuntimeError::BalanceMismatch(e) => panic!("{}", e), RuntimeError::StorageError(e) => panic!("Storage error {:?}", e), RuntimeError::UnexpectedIntegerOverflow => { @@ -183,7 +185,7 @@ impl User for RuntimeUser { .map_err(|err| err.to_string()) } - fn add_transaction(&self, transaction: SignedTransaction) -> Result<(), String> { + fn add_transaction(&self, transaction: SignedTransaction) -> Result<(), ServerError> { self.apply_all(self.apply_state(), vec![], vec![transaction])?; Ok(()) } @@ -196,7 +198,7 @@ impl User for RuntimeUser { Ok(self.get_transaction_final_result(&transaction.get_hash())) } - fn add_receipt(&self, receipt: Receipt) -> Result<(), String> { + fn add_receipt(&self, receipt: Receipt) -> Result<(), ServerError> { self.apply_all(self.apply_state(), vec![receipt], vec![])?; Ok(()) } diff --git a/tests/test_errors.rs b/tests/test_errors.rs index a2f0520d5d8..118f825e550 100644 --- a/tests/test_errors.rs +++ b/tests/test_errors.rs @@ -47,13 +47,11 @@ fn test_check_tx_error_log() { let tx_result = node.user().commit_transaction(tx).unwrap_err(); assert_eq!( tx_result, - format!( - "{}", - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::AccessKeyNotFound { - account_id: "bob.near".to_string(), - public_key: signer.public_key.clone() - }) - ), + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::AccessKeyNotFound { + account_id: "bob.near".to_string(), + public_key: signer.public_key.clone() + }) + .into() ); } @@ -86,13 +84,11 @@ fn test_deliver_tx_error_log() { let tx_result = node.user().commit_transaction(tx).unwrap_err(); assert_eq!( tx_result, - format!( - "{}", - InvalidTxError::NotEnoughBalance { - signer_id: "alice.near".to_string(), - balance: TESTING_INIT_BALANCE - TESTING_INIT_STAKE, - cost: TESTING_INIT_BALANCE + 1 + cost - } - ), + InvalidTxError::NotEnoughBalance { + signer_id: "alice.near".to_string(), + balance: TESTING_INIT_BALANCE - TESTING_INIT_STAKE, + cost: TESTING_INIT_BALANCE + 1 + cost + } + .into() ); } From 27ab39b8c07a268efbe46af82364dc145dc7e275 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 20 Dec 2019 17:56:31 +0300 Subject: [PATCH 09/48] action index added to ActionError --- core/primitives/src/errors.rs | 44 +++++++++++++++++++-------- core/primitives/src/views.rs | 2 +- runtime/runtime/src/actions.rs | 54 +++++++++++++++++++++------------- runtime/runtime/src/lib.rs | 16 ++++++---- 4 files changed, 77 insertions(+), 39 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 99fbb98be67..279340f1a11 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -88,7 +88,13 @@ pub enum InvalidAccessKeyError { } #[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub enum ActionError { +pub struct ActionError { + pub index: Option, + pub kind: ActionErrorKind, +} + +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +pub enum ActionErrorKind { AccountAlreadyExists { account_id: AccountId, }, @@ -140,6 +146,12 @@ pub enum ActionError { FunctionCall(String), // TODO type } +impl From for ActionError { + fn from(e: ActionErrorKind) -> ActionError { + ActionError { index: None, kind: e } + } +} + impl Display for InvalidTxError { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match self { @@ -341,58 +353,64 @@ impl From for RuntimeError { } impl Display for ActionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(f, "Action #{}: {}", self.index.unwrap_or_default(), self.kind) + } +} + +impl Display for ActionErrorKind { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match self { - ActionError::AccountAlreadyExists { account_id } => { + ActionErrorKind::AccountAlreadyExists { account_id } => { write!(f, "Can't create a new account {:?}, because it already exists", account_id) } - ActionError::AccountDoesNotExist { action, account_id } => write!( + ActionErrorKind::AccountDoesNotExist { action, account_id } => write!( f, "Can't complete the action {:?}, because account {:?} doesn't exist", action, account_id ), - ActionError::ActorNoPermission { actor_id, account_id, action } => write!( + ActionErrorKind::ActorNoPermission { actor_id, account_id, action } => write!( f, "Actor {:?} doesn't have permission to account {:?} to complete the action {:?}", actor_id, account_id, action ), - ActionError::RentUnpaid { account_id, amount } => write!( + ActionErrorKind::RentUnpaid { account_id, amount } => write!( f, "The account {} wouldn't have enough balance to pay required rent {}", account_id, amount ), - ActionError::TriesToUnstake { account_id } => { + ActionErrorKind::TriesToUnstake { account_id } => { write!(f, "Account {:?} is not yet staked, but tries to unstake", account_id) } - ActionError::TriesToStake { account_id, stake, locked, balance } => write!( + ActionErrorKind::TriesToStake { account_id, stake, locked, balance } => write!( f, "Account {:?} tries to stake {}, but has staked {} and only has {}", account_id, stake, locked, balance ), - ActionError::CreateAccountNotAllowed { account_id, predecessor_id } => write!( + ActionErrorKind::CreateAccountNotAllowed { account_id, predecessor_id } => write!( f, "The new account_id {:?} can't be created by {:?}", account_id, predecessor_id ), - ActionError::DeleteKeyDoesNotExist { account_id, .. } => write!( + ActionErrorKind::DeleteKeyDoesNotExist { account_id, .. } => write!( f, "Account {:?} tries to remove an access key that doesn't exist", account_id ), - ActionError::AddKeyAlreadyExists { public_key, .. } => write!( + ActionErrorKind::AddKeyAlreadyExists { public_key, .. } => write!( f, "The public key {:?} is already used for an existing access key", public_key ), - ActionError::DeleteAccountStaking { account_id } => { + ActionErrorKind::DeleteAccountStaking { account_id } => { write!(f, "Account {:?} is staking and can not be deleted", account_id) } - ActionError::DeleteAccountHasRent { account_id, balance } => write!( + ActionErrorKind::DeleteAccountHasRent { account_id, balance } => write!( f, "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", account_id, balance ), - ActionError::FunctionCall(s) => write!(f, "{}", s), + ActionErrorKind::FunctionCall(s) => write!(f, "{}", s), } } } diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 5c55bc0e4d8..6bd8e247c05 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -10,7 +10,7 @@ use near_crypto::{PublicKey, Signature}; use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission}; use crate::block::{Approval, Block, BlockHeader, BlockHeaderInnerLite, BlockHeaderInnerRest}; use crate::challenge::{Challenge, ChallengesResult}; -use crate::errors::{ActionError, ExecutionError, InvalidTxError}; +use crate::errors::ExecutionError; use crate::hash::CryptoHash; use crate::logging; use crate::merkle::MerklePath; diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 7263fc494f0..3c776ce8633 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -26,7 +26,7 @@ use near_vm_logic::VMContext; use crate::config::RuntimeConfig; use crate::ext::RuntimeExt; use crate::{ActionResult, ApplyState}; -use near_primitives::errors::ActionError; +use near_primitives::errors::{ActionError, ActionErrorKind}; use near_vm_errors::{CompilationError, FunctionExecError}; use near_vm_runner::VMError; @@ -122,7 +122,7 @@ pub(crate) fn action_function_call( let error = VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::CodeDoesNotExist(account_id.clone()), )); - result.result = Err(ActionError::FunctionCall(error.to_string())); + result.result = Err(ActionErrorKind::FunctionCall(error.to_string()).into()); return Ok(()); } Err(e) => { @@ -180,7 +180,7 @@ pub(crate) fn action_function_call( borsh::BorshDeserialize::try_from_slice(&storage).expect("Borsh cannot fail"); return Err(err); } - result.result = Err(ActionError::FunctionCall(err.to_string())); + result.result = Err(ActionErrorKind::FunctionCall(err.to_string()).into()); if let Some(outcome) = outcome { result.gas_burnt += outcome.burnt_gas; result.gas_burnt_for_function_call += outcome.burnt_gas; @@ -216,7 +216,8 @@ pub(crate) fn action_stake( if account.amount >= increment { if account.locked == 0 && stake.stake == 0 { // if the account hasn't staked, it cannot unstake - result.result = Err(ActionError::TriesToUnstake { account_id: account_id.clone() }); + result.result = + Err(ActionErrorKind::TriesToUnstake { account_id: account_id.clone() }.into()); return; } result.validator_proposals.push(ValidatorStake { @@ -229,12 +230,13 @@ pub(crate) fn action_stake( account.locked = stake.stake; } } else { - result.result = Err(ActionError::TriesToStake { + result.result = Err(ActionErrorKind::TriesToStake { account_id: account_id.clone(), stake: stake.stake, locked: account.locked, balance: account.amount, - }); + } + .into()); } } @@ -254,10 +256,11 @@ pub(crate) fn action_create_account( if !is_valid_top_level_account_id(account_id) && !is_valid_sub_account_id(&receipt.predecessor_id, account_id) { - result.result = Err(ActionError::CreateAccountNotAllowed { + result.result = Err(ActionErrorKind::CreateAccountNotAllowed { account_id: account_id.clone(), predecessor_id: receipt.predecessor_id.clone(), - }); + } + .into()); return; } *actor_id = receipt.receiver_id.clone(); @@ -320,10 +323,11 @@ pub(crate) fn action_delete_key( let account = account.as_mut().unwrap(); let access_key = get_access_key(state_update, account_id, &delete_key.public_key)?; if access_key.is_none() { - result.result = Err(ActionError::DeleteKeyDoesNotExist { + result.result = Err(ActionErrorKind::DeleteKeyDoesNotExist { public_key: delete_key.public_key.clone(), account_id: account_id.clone(), - }); + } + .into()); return Ok(()); } // Remove access key @@ -350,10 +354,11 @@ pub(crate) fn action_add_key( ) -> Result<(), StorageError> { let account = account.as_mut().unwrap(); if get_access_key(state_update, account_id, &add_key.public_key)?.is_some() { - result.result = Err(ActionError::AddKeyAlreadyExists { + result.result = Err(ActionErrorKind::AddKeyAlreadyExists { account_id: account_id.to_owned(), public_key: add_key.public_key.clone(), - }); + } + .into()); return Ok(()); } set_access_key(state_update, account_id, &add_key.public_key, &add_key.access_key); @@ -379,16 +384,20 @@ pub(crate) fn check_actor_permissions( match action { Action::DeployContract(_) | Action::Stake(_) | Action::AddKey(_) | Action::DeleteKey(_) => { if actor_id != account_id { - return Err(ActionError::ActorNoPermission { + return Err(ActionErrorKind::ActorNoPermission { account_id: actor_id.clone(), actor_id: account_id.clone(), action: action_type_as_string(action).to_owned(), - }); + } + .into()); } } Action::DeleteAccount(_) => { if account.as_ref().unwrap().locked != 0 { - return Err(ActionError::DeleteAccountStaking { account_id: account_id.clone() }); + return Err(ActionErrorKind::DeleteAccountStaking { + account_id: account_id.clone(), + } + .into()); } if actor_id != account_id && check_rent( @@ -399,10 +408,11 @@ pub(crate) fn check_actor_permissions( ) .is_ok() { - return Err(ActionError::DeleteAccountHasRent { + return Err(ActionErrorKind::DeleteAccountHasRent { account_id: account_id.clone(), balance: account.as_ref().unwrap().amount, - }); + } + .into()); } } Action::CreateAccount(_) | Action::FunctionCall(_) | Action::Transfer(_) => (), @@ -431,7 +441,10 @@ pub(crate) fn check_account_existence( match action { Action::CreateAccount(_) => { if account.is_some() { - return Err(ActionError::AccountAlreadyExists { account_id: account_id.clone() }); + return Err(ActionErrorKind::AccountAlreadyExists { + account_id: account_id.clone().into(), + } + .into()); } } Action::DeployContract(_) @@ -442,10 +455,11 @@ pub(crate) fn check_account_existence( | Action::DeleteKey(_) | Action::DeleteAccount(_) => { if account.is_none() { - return Err(ActionError::AccountDoesNotExist { + return Err(ActionErrorKind::AccountDoesNotExist { action: action_type_as_string(action).to_owned(), account_id: account_id.clone(), - }); + } + .into()); } } }; diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index 0c86f2c6d26..215785516b8 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -16,7 +16,8 @@ use near_crypto::PublicKey; use near_primitives::account::{AccessKey, AccessKeyPermission, Account}; use near_primitives::contract::ContractCode; use near_primitives::errors::{ - ActionError, ExecutionError, InvalidAccessKeyError, InvalidTxError, RuntimeError, + ActionError, ActionErrorKind, ExecutionError, InvalidAccessKeyError, InvalidTxError, + RuntimeError, }; use near_primitives::hash::CryptoHash; use near_primitives::receipt::{ActionReceipt, DataReceipt, Receipt, ReceiptEnum, ReceivedData}; @@ -605,7 +606,8 @@ impl Runtime { is_last_action, )?)?; // TODO storage error - if result.result.is_err() { + if let Err(ref mut res) = result.result { + res.index = Some(action_index as u64); break; } } @@ -617,9 +619,13 @@ impl Runtime { check_rent(account_id, account, &self.config, apply_state.epoch_length) { result.merge(ActionResult { - result: Err(ActionError::RentUnpaid { - account_id: account_id.clone(), - amount, + result: Err(ActionError { + // TODO: looks like this shouldn't be in a ActionError category (which action where failed?) + index: None, + kind: ActionErrorKind::RentUnpaid { + account_id: account_id.clone(), + amount, + }, }), ..Default::default() })?; From 30622910a44d9eadfa22b757b7a54ac0936d2559 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 20 Dec 2019 18:44:54 +0300 Subject: [PATCH 10/48] action index added: test pass --- core/primitives/src/errors.rs | 14 ++- runtime/runtime/src/actions.rs | 15 --- runtime/runtime/tests/test_evil_contracts.rs | 10 +- test-utils/testlib/src/standard_test_cases.rs | 92 ++++++++++++++----- 4 files changed, 82 insertions(+), 49 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 279340f1a11..0fa6dd4c053 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -99,7 +99,6 @@ pub enum ActionErrorKind { account_id: AccountId, }, AccountDoesNotExist { - action: String, account_id: AccountId, }, CreateAccountNotAllowed { @@ -109,7 +108,6 @@ pub enum ActionErrorKind { ActorNoPermission { account_id: AccountId, actor_id: AccountId, - action: String, }, DeleteKeyDoesNotExist { account_id: AccountId, @@ -364,15 +362,15 @@ impl Display for ActionErrorKind { ActionErrorKind::AccountAlreadyExists { account_id } => { write!(f, "Can't create a new account {:?}, because it already exists", account_id) } - ActionErrorKind::AccountDoesNotExist { action, account_id } => write!( + ActionErrorKind::AccountDoesNotExist { account_id } => write!( f, - "Can't complete the action {:?}, because account {:?} doesn't exist", - action, account_id + "Can't complete the action because account {:?} doesn't exist", + account_id ), - ActionErrorKind::ActorNoPermission { actor_id, account_id, action } => write!( + ActionErrorKind::ActorNoPermission { actor_id, account_id } => write!( f, - "Actor {:?} doesn't have permission to account {:?} to complete the action {:?}", - actor_id, account_id, action + "Actor {:?} doesn't have permission to account {:?} to complete the action", + actor_id, account_id ), ActionErrorKind::RentUnpaid { account_id, amount } => write!( f, diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 3c776ce8633..29d8dc17387 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -387,7 +387,6 @@ pub(crate) fn check_actor_permissions( return Err(ActionErrorKind::ActorNoPermission { account_id: actor_id.clone(), actor_id: account_id.clone(), - action: action_type_as_string(action).to_owned(), } .into()); } @@ -420,19 +419,6 @@ pub(crate) fn check_actor_permissions( Ok(()) } -fn action_type_as_string(action: &Action) -> &'static str { - match action { - Action::CreateAccount(_) => "CreateAccount", - Action::DeployContract(_) => "DeployContract", - Action::FunctionCall(_) => "FunctionCall", - Action::Transfer(_) => "Transfer", - Action::Stake(_) => "Stake", - Action::AddKey(_) => "AddKey", - Action::DeleteKey(_) => "DeleteKey", - Action::DeleteAccount(_) => "DeleteAccount", - } -} - pub(crate) fn check_account_existence( action: &Action, account: &mut Option, @@ -456,7 +442,6 @@ pub(crate) fn check_account_existence( | Action::DeleteAccount(_) => { if account.is_none() { return Err(ActionErrorKind::AccountDoesNotExist { - action: action_type_as_string(action).to_owned(), account_id: account_id.clone(), } .into()); diff --git a/runtime/runtime/tests/test_evil_contracts.rs b/runtime/runtime/tests/test_evil_contracts.rs index 54359f42b1c..e8df87b97d8 100644 --- a/runtime/runtime/tests/test_evil_contracts.rs +++ b/runtime/runtime/tests/test_evil_contracts.rs @@ -1,4 +1,4 @@ -use near_primitives::errors::ActionError; +use near_primitives::errors::{ActionError, ActionErrorKind}; use near_primitives::serialize::to_base64; use near_primitives::views::FinalExecutionStatus; use near_vm_errors::{FunctionExecError, HostError, MethodResolveError, VMError}; @@ -135,7 +135,13 @@ fn test_evil_abort() { assert_eq!( res.status, FinalExecutionStatus::Failure( - ActionError::FunctionCall("String encoding is bad UTF-16 sequence.".to_string()).into() + ActionError { + index: Some(0), + kind: ActionErrorKind::FunctionCall( + "String encoding is bad UTF-16 sequence.".to_string() + ) + } + .into() ), "{:?}", res diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index bec5ead66dc..96386437645 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -4,7 +4,9 @@ use near::config::{TESTING_INIT_BALANCE, TESTING_INIT_STAKE}; use near_crypto::{InMemorySigner, KeyType}; use near_jsonrpc::ServerError; use near_primitives::account::{AccessKey, AccessKeyPermission, FunctionCallPermission}; -use near_primitives::errors::{ActionError, ExecutionError, InvalidAccessKeyError, InvalidTxError}; +use near_primitives::errors::{ + ActionError, ActionErrorKind, ExecutionError, InvalidAccessKeyError, InvalidTxError, +}; use near_primitives::hash::hash; use near_primitives::serialize::to_base64; use near_primitives::types::Balance; @@ -77,7 +79,11 @@ pub fn test_smart_contract_panic(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCall("Smart contract panicked: WAT?".to_string()).into() + ActionError { + index: Some(0), + kind: ActionErrorKind::FunctionCall("Smart contract panicked: WAT?".to_string()) + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -109,7 +115,11 @@ pub fn test_smart_contract_bad_method_name(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCall("MethodNotFound".to_string()).into() + ActionError { + index: Some(0), + kind: ActionErrorKind::FunctionCall("MethodNotFound".to_string()) + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -127,7 +137,11 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCall("MethodEmptyName".to_string()).into() + ActionError { + index: Some(0), + kind: ActionErrorKind::FunctionCall("MethodEmptyName".to_string()) + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -145,7 +159,11 @@ pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::FunctionCall("MethodEmptyName".to_string()).into() + ActionError { + index: Some(0), + kind: ActionErrorKind::FunctionCall("MethodEmptyName".to_string()) + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -346,9 +364,9 @@ pub fn test_refund_on_send_money_to_non_existent_account(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountDoesNotExist { - action: "Transfer".to_string(), - account_id: eve_dot_alice_account() + ActionError { + index: Some(0), + kind: ActionErrorKind::AccountDoesNotExist { account_id: eve_dot_alice_account() } } .into() ) @@ -441,7 +459,11 @@ pub fn test_create_account_again(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountAlreadyExists { account_id: eve_dot_alice_account() }.into() + ActionError { + index: Some(0), + kind: ActionErrorKind::AccountAlreadyExists { account_id: eve_dot_alice_account() } + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -503,7 +525,11 @@ pub fn test_create_account_failure_already_exists(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountAlreadyExists { account_id: bob_account() }.into() + ActionError { + index: Some(0), + kind: ActionErrorKind::AccountAlreadyExists { account_id: bob_account() } + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 2); @@ -581,9 +607,12 @@ pub fn test_add_existing_key(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AddKeyAlreadyExists { - account_id: account_id.clone(), - public_key: node.signer().public_key() + ActionError { + index: Some(0), + kind: ActionErrorKind::AddKeyAlreadyExists { + account_id: account_id.clone(), + public_key: node.signer().public_key() + } } .into() ) @@ -630,9 +659,12 @@ pub fn test_delete_key_not_owned(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteKeyDoesNotExist { - account_id: account_id.clone(), - public_key: signer2.public_key.clone() + ActionError { + index: Some(0), + kind: ActionErrorKind::DeleteKeyDoesNotExist { + account_id: account_id.clone(), + public_key: signer2.public_key.clone() + } } .into() ) @@ -965,7 +997,11 @@ pub fn test_unstake_while_not_staked(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::TriesToUnstake { account_id: eve_dot_alice_account() }.into() + ActionError { + index: Some(0), + kind: ActionErrorKind::TriesToUnstake { account_id: eve_dot_alice_account() } + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -1001,8 +1037,8 @@ fn test_stake_fail_not_enough_rent_with_balance(node: impl Node, initial_balance &transaction_result.status, FinalExecutionStatus::Failure(e) => match &e { &ExecutionError::Action(action_err) => - match action_err { - ActionError::RentUnpaid{..} => {}, + match action_err.kind { + ActionErrorKind::RentUnpaid{..} => {}, _ => panic!("should be RentUnpaid") } _ => panic!("should be Action") @@ -1049,7 +1085,11 @@ pub fn test_delete_account_fail(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteAccountStaking { account_id: bob_account() }.into() + ActionError { + index: Some(0), + kind: ActionErrorKind::DeleteAccountStaking { account_id: bob_account() } + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 1); @@ -1067,9 +1107,9 @@ pub fn test_delete_account_no_account(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::AccountDoesNotExist { - action: "DeleteAccount".to_string(), - account_id: eve_dot_alice_account() + ActionError { + index: Some(0), + kind: ActionErrorKind::AccountDoesNotExist { account_id: eve_dot_alice_account() } } .into() ) @@ -1098,7 +1138,11 @@ pub fn test_delete_account_while_staking(node: impl Node) { assert_eq!( transaction_result.status, FinalExecutionStatus::Failure( - ActionError::DeleteAccountStaking { account_id: eve_dot_alice_account() }.into() + ActionError { + index: Some(0), + kind: ActionErrorKind::DeleteAccountStaking { account_id: eve_dot_alice_account() } + } + .into() ) ); assert_eq!(transaction_result.receipts.len(), 1); From 6d7c555ed19cef3e8a4941cef965daf500254c26 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 23 Dec 2019 16:34:53 +0300 Subject: [PATCH 11/48] FunctionCall(String) -> FunctionCall(VMError) --- core/primitives/src/errors.rs | 4 +++- runtime/near-vm-errors/src/lib.rs | 7 ------- runtime/runtime/src/actions.rs | 4 ++-- test-utils/testlib/src/standard_test_cases.rs | 17 +++++++++++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 0fa6dd4c053..f376588fa5a 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -5,6 +5,8 @@ use near_crypto::PublicKey; use serde::{Deserialize, Serialize}; use std::fmt::Display; +use near_vm_errors::VMError; + /// Internal #[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] pub enum StorageError { @@ -141,7 +143,7 @@ pub enum ActionErrorKind { #[serde(with = "u128_dec_format")] balance: Balance, }, - FunctionCall(String), // TODO type + FunctionCall(VMError), } impl From for ActionError { diff --git a/runtime/near-vm-errors/src/lib.rs b/runtime/near-vm-errors/src/lib.rs index 25e80ca1230..5c6f93ebd69 100644 --- a/runtime/near-vm-errors/src/lib.rs +++ b/runtime/near-vm-errors/src/lib.rs @@ -3,14 +3,12 @@ use serde::{Deserialize, Serialize}; use std::fmt; #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type", content = "c")] pub enum VMError { FunctionExecError(FunctionExecError), StorageError(Vec), } #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type")] pub enum FunctionExecError { CompilationError(CompilationError), LinkError(String), @@ -20,7 +18,6 @@ pub enum FunctionExecError { } #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type")] pub enum MethodResolveError { MethodEmptyName, MethodUTF8Error, @@ -29,7 +26,6 @@ pub enum MethodResolveError { } #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type")] pub enum CompilationError { CodeDoesNotExist(String), PrepareError(PrepareError), @@ -37,7 +33,6 @@ pub enum CompilationError { } #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type")] /// Error that can occur while preparing or executing Wasm smart-contract. pub enum PrepareError { /// Error happened while serializing the module. @@ -70,7 +65,6 @@ pub enum PrepareError { } #[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type")] pub enum HostError { BadUTF16, BadUTF8, @@ -96,7 +90,6 @@ pub enum HostError { } #[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] -#[serde(tag = "type")] pub enum HostErrorOrStorageError { HostError(HostError), /// Error from underlying storage, serialized diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 29d8dc17387..ded59b611f2 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -122,7 +122,7 @@ pub(crate) fn action_function_call( let error = VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::CodeDoesNotExist(account_id.clone()), )); - result.result = Err(ActionErrorKind::FunctionCall(error.to_string()).into()); + result.result = Err(ActionErrorKind::FunctionCall(error).into()); return Ok(()); } Err(e) => { @@ -180,7 +180,7 @@ pub(crate) fn action_function_call( borsh::BorshDeserialize::try_from_slice(&storage).expect("Borsh cannot fail"); return Err(err); } - result.result = Err(ActionErrorKind::FunctionCall(err.to_string()).into()); + result.result = Err(ActionErrorKind::FunctionCall(err).into()); if let Some(outcome) = outcome { result.gas_burnt += outcome.burnt_gas; result.gas_burnt_for_function_call += outcome.burnt_gas; diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index 0cb8191a4ed..c244a6dea63 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -12,6 +12,7 @@ use near_primitives::serialize::to_base64; use near_primitives::types::Balance; use near_primitives::views::FinalExecutionStatus; use near_primitives::views::{AccountView, FinalExecutionOutcomeView}; +use near_vm_errors::{FunctionExecError, HostError, MethodResolveError, VMError}; use crate::fees_utils::FeeHelper; use crate::node::Node; @@ -81,7 +82,9 @@ pub fn test_smart_contract_panic(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCall("Smart contract panicked: WAT?".to_string()) + kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( + FunctionExecError::HostError(HostError::GuestPanic("WAT?".to_string())) + )) } .into() ) @@ -117,7 +120,9 @@ pub fn test_smart_contract_bad_method_name(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCall("MethodNotFound".to_string()) + kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodNotFound) + )) } .into() ) @@ -139,7 +144,9 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCall("MethodEmptyName".to_string()) + kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) + )) } .into() ) @@ -161,7 +168,9 @@ pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCall("MethodEmptyName".to_string()) + kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( + FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) + )) } .into() ) From 52ebc4d4e55cf4462780ac7de0d89f6e6c98f10a Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 25 Dec 2019 19:07:25 +0300 Subject: [PATCH 12/48] rpctypegen start --- Cargo.lock | 12 + Cargo.toml | 1 + core/primitives/Cargo.toml | 1 + core/primitives/src/errors.rs | 80 +- tools/rpctypegen/Cargo.toml | 15 + tools/rpctypegen/err.txt | 11902 +++++++++++++++++++++++++++++++ tools/rpctypegen/src/lib.rs | 55 + tools/rpctypegen/src/parser.rs | 35 + 8 files changed, 12063 insertions(+), 38 deletions(-) create mode 100644 tools/rpctypegen/Cargo.toml create mode 100644 tools/rpctypegen/err.txt create mode 100644 tools/rpctypegen/src/lib.rs create mode 100644 tools/rpctypegen/src/parser.rs diff --git a/Cargo.lock b/Cargo.lock index 2bb39ff22ee..cf8a8e5ea5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2228,6 +2228,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "near-crypto 0.1.0", + "near-rpc-error-macro 0.1.0", "near-vm-errors 0.4.3", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "reed-solomon-erasure 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2238,6 +2239,17 @@ dependencies = [ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "near-rpc-error-macro" +version = "0.1.0" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "near-runtime-fees" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 2c12dbfec0c..880248b2ba5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ "test-utils/loadtester", "test-utils/state-viewer", "near/", + "tools/rpctypegen", "genesis-tools/genesis-csv-to-json", "genesis-tools/genesis-populate", "genesis-tools/keypair-generator", diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index e998913c8a4..cf54aed201c 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -27,6 +27,7 @@ borsh = "0.2.10" near-crypto = { path = "../crypto" } near-vm-errors = { path = "../../runtime/near-vm-errors" } +near-rpc-error-macro = { path = "../../tools/rpctypegen" } [features] default = ["jemallocator"] diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index f376588fa5a..1a48e1fe585 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -5,10 +5,51 @@ use near_crypto::PublicKey; use serde::{Deserialize, Serialize}; use std::fmt::Display; +use near_rpc_error_macro::RpcError; use near_vm_errors::VMError; +/// Error returned in the ExecutionOutcome in case of failure. +#[derive( + BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, +)] +#[rpc_error_parent = "ServerError"] +pub enum ExecutionError { + Action(ActionError), + InvalidTx(InvalidTxError), +} + +impl Display for ExecutionError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match self { + ExecutionError::Action(e) => write!(f, "{}", e), + ExecutionError::InvalidTx(e) => write!(f, "{}", e), + } + } +} + +impl From for ExecutionError { + fn from(error: ActionError) -> Self { + ExecutionError::Action(error) + } +} + +impl From for ExecutionError { + fn from(error: InvalidTxError) -> Self { + ExecutionError::InvalidTx(error) + } +} + +/// Error returned from `Runtime::apply` +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RuntimeError { + UnexpectedIntegerOverflow, + InvalidTxError(InvalidTxError), + StorageError(StorageError), + BalanceMismatch(BalanceMismatchError), +} + /// Internal -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, RpcError)] pub enum StorageError { /// Key-value db internal failure StorageInternalError, @@ -313,15 +354,6 @@ impl Display for BalanceMismatchError { #[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct IntegerOverflowError; -/// Error returned from `Runtime::apply` -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum RuntimeError { - UnexpectedIntegerOverflow, - InvalidTxError(InvalidTxError), - StorageError(StorageError), - BalanceMismatch(BalanceMismatchError), -} - impl From for InvalidTxError { fn from(_: IntegerOverflowError) -> Self { InvalidTxError::CostOverflow @@ -414,31 +446,3 @@ impl Display for ActionErrorKind { } } } - -/// Error returned in the ExecutionOutcome in case of failure. -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub enum ExecutionError { - Action(ActionError), - InvalidTx(InvalidTxError), -} - -impl Display for ExecutionError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match self { - ExecutionError::Action(e) => write!(f, "{}", e), - ExecutionError::InvalidTx(e) => write!(f, "{}", e), - } - } -} - -impl From for ExecutionError { - fn from(error: ActionError) -> Self { - ExecutionError::Action(error) - } -} - -impl From for ExecutionError { - fn from(error: InvalidTxError) -> Self { - ExecutionError::InvalidTx(error) - } -} diff --git a/tools/rpctypegen/Cargo.toml b/tools/rpctypegen/Cargo.toml new file mode 100644 index 00000000000..308fbc6d9c1 --- /dev/null +++ b/tools/rpctypegen/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "near-rpc-error-macro" +version = "0.1.0" +authors = ["Alexey "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +serde = "1.0" +serde_json = "1.0" +syn = { version = "1.0", features = ["full", "extra-traits"]} +quote = "1.0" +proc-macro2 = "1.0" diff --git a/tools/rpctypegen/err.txt b/tools/rpctypegen/err.txt new file mode 100644 index 00000000000..acf2173230f --- /dev/null +++ b/tools/rpctypegen/err.txt @@ -0,0 +1,11902 @@ +File { + shebang: None, + attrs: [], + items: [ + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + crate, + ), + colon2_token: Colon2, + tree: Path( + UsePath { + ident: Ident( + serialize, + ), + colon2_token: Colon2, + tree: Name( + UseName { + ident: Ident( + u128_dec_format, + ), + }, + ), + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + crate, + ), + colon2_token: Colon2, + tree: Path( + UsePath { + ident: Ident( + types, + ), + colon2_token: Colon2, + tree: Group( + UseGroup { + brace_token: Brace, + items: [ + Name( + UseName { + ident: Ident( + AccountId, + ), + }, + ), + Comma, + Name( + UseName { + ident: Ident( + Balance, + ), + }, + ), + Comma, + Name( + UseName { + ident: Ident( + Nonce, + ), + }, + ), + ], + }, + ), + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + borsh, + ), + colon2_token: Colon2, + tree: Group( + UseGroup { + brace_token: Brace, + items: [ + Name( + UseName { + ident: Ident( + BorshDeserialize, + ), + }, + ), + Comma, + Name( + UseName { + ident: Ident( + BorshSerialize, + ), + }, + ), + ], + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + near_crypto, + ), + colon2_token: Colon2, + tree: Name( + UseName { + ident: Ident( + PublicKey, + ), + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + serde, + ), + colon2_token: Colon2, + tree: Group( + UseGroup { + brace_token: Brace, + items: [ + Name( + UseName { + ident: Ident( + Deserialize, + ), + }, + ), + Comma, + Name( + UseName { + ident: Ident( + Serialize, + ), + }, + ), + ], + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + std, + ), + colon2_token: Colon2, + tree: Path( + UsePath { + ident: Ident( + fmt, + ), + colon2_token: Colon2, + tree: Name( + UseName { + ident: Ident( + Display, + ), + }, + ), + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Use( + ItemUse { + attrs: [], + vis: Inherited, + use_token: Use, + leading_colon: None, + tree: Path( + UsePath { + ident: Ident( + near_vm_errors, + ), + colon2_token: Colon2, + tree: Name( + UseName { + ident: Ident( + VMError, + ), + }, + ), + }, + ), + semi_token: Semi, + }, + ), + Enum( + ItemEnum { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Internal", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + enum_token: Enum, + ident: Ident( + StorageError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + brace_token: Brace, + variants: [ + Variant { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Key-value db internal failure", + }, + ], + }, + ], + ident: Ident( + StorageInternalError, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Storage is PartialStorage and requested a missing trie node", + }, + ], + }, + ], + ident: Ident( + TrieNodeMissing, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Either invalid state or key-value db is corrupted.", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " For PartialStorage it cannot be corrupted.", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Error message is unreliable and for debugging purposes only. It's also probably ok to", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " panic in every place that produces this error.", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " We can check if db is corrupted by verifying everything in the state trie.", + }, + ], + }, + ], + ident: Ident( + StorageInconsistentState, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + String, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + StorageError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + MethodCall( + ExprMethodCall { + attrs: [], + receiver: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + f, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + method: Ident( + write_str, + ), + turbofish: None, + paren_token: Paren, + args: [ + Reference( + ExprReference { + attrs: [], + and_token: And, + raw: Reserved { + private: (), + }, + mutability: None, + expr: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + format, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Literal { + lit: "{:?}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + ], + }, + }, + ), + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + error, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + StorageError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [], + }, + ), + Enum( + ItemEnum { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " External", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + enum_token: Enum, + ident: Ident( + InvalidTxError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + brace_token: Brace, + variants: [ + Variant { + attrs: [], + ident: Ident( + InvalidAccessKey, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidSigner, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + signer_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + SignerDoesNotExist, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + signer_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidNonce, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + tx_nonce, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Nonce, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + ak_nonce, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Nonce, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidReceiver, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + receiver_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidSignature, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + NotEnoughBalance, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + signer_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + cost, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + RentUnpaid, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + signer_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + amount, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + CostOverflow, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidChain, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + Expired, + ), + fields: Unit, + discriminant: None, + }, + Comma, + ], + }, + ), + Enum( + ItemEnum { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + enum_token: Enum, + ident: Ident( + InvalidAccessKeyError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + brace_token: Brace, + variants: [ + Variant { + attrs: [], + ident: Ident( + AccessKeyNotFound, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + public_key, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + PublicKey, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + ReceiverMismatch, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + tx_receiver, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + ak_receiver, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + MethodNameMismatch, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + method_name, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + String, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + ActionError, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + NotEnoughAllowance, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + public_key, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + PublicKey, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + allowance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + cost, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + ], + }, + ), + Struct( + ItemStruct { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + struct_token: Struct, + ident: Ident( + ActionError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + index, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Option, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + u64, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + kind, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + semi_token: None, + }, + ), + Enum( + ItemEnum { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + enum_token: Enum, + ident: Ident( + ActionErrorKind, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + brace_token: Brace, + variants: [ + Variant { + attrs: [], + ident: Ident( + AccountAlreadyExists, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + AccountDoesNotExist, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + CreateAccountNotAllowed, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + predecessor_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + ActorNoPermission, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + actor_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + DeleteKeyDoesNotExist, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + public_key, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + PublicKey, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + AddKeyAlreadyExists, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + public_key, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + PublicKey, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + DeleteAccountStaking, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + DeleteAccountHasRent, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + RentUnpaid, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + amount, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + TriesToUnstake, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + TriesToStake, + ), + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Inherited, + ident: Some( + Ident( + account_id, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + AccountId, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + stake, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + locked, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + serde, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: with, + }, + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: "u128_dec_format", + }, + ], + }, + ], + }, + ], + vis: Inherited, + ident: Some( + Ident( + balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + FunctionCall, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + VMError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + e, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Struct( + ExprStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldValue { + attrs: [], + member: Named( + Ident( + index, + ), + ), + colon_token: Some( + Colon, + ), + expr: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + None, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + FieldValue { + attrs: [], + member: Named( + Ident( + kind, + ), + ), + colon_token: Some( + Colon, + ), + expr: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + e, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + dot2_token: None, + rest: None, + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Match( + ExprMatch { + attrs: [], + match_token: Match, + expr: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + arms: [ + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidSigner, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + signer_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + signer_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Invalid signer account ID {:?} according to requirements", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: signer_id, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + SignerDoesNotExist, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + signer_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + signer_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Signer {:?} does not exist", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: signer_id, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: TupleStruct( + PatTupleStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidAccessKey, + ), + arguments: None, + }, + ], + }, + pat: PatTuple { + attrs: [], + paren_token: Paren, + elems: [ + Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + access_key_error, + ), + subpat: None, + }, + ), + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: MethodCall( + ExprMethodCall { + attrs: [], + receiver: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + access_key_error, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + method: Ident( + fmt, + ), + turbofish: None, + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + f, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidNonce, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + tx_nonce, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + tx_nonce, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + ak_nonce, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + ak_nonce, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction nonce {} must be larger than nonce of the used access key {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: tx_nonce, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: ak_nonce, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidReceiver, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + receiver_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + receiver_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Invalid receiver account ID {:?} according to requirements", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: receiver_id, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Path( + PatPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidSignature, + ), + arguments: None, + }, + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction is not signed with the given public key", + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + NotEnoughBalance, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + signer_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + signer_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + balance, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + balance, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + cost, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + cost, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Sender {:?} does not have enough balance {} for operation costing {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: signer_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: cost, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + RentUnpaid, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + signer_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + signer_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + amount, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + amount, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Failed to execute, because the account {:?} wouldn't have enough to pay required rent {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: signer_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: amount, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Path( + PatPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + CostOverflow, + ), + arguments: None, + }, + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction gas or balance cost is too high", + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Path( + PatPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidChain, + ), + arguments: None, + }, + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction parent block hash doesn't belong to the current chain", + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Path( + PatPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Expired, + ), + arguments: None, + }, + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction has expired", + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + error, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Call( + ExprCall { + attrs: [], + func: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidAccessKey, + ), + arguments: None, + }, + ], + }, + }, + ), + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + error, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Match( + ExprMatch { + attrs: [], + match_token: Match, + expr: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + arms: [ + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + AccessKeyNotFound, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + public_key, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + public_key, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Signer {:?} doesn't have access key with the given public_key {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: public_key, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + ReceiverMismatch, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + tx_receiver, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + tx_receiver, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + ak_receiver, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + ak_receiver, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: tx_receiver, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: ak_receiver, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + MethodNameMismatch, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + method_name, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + method_name, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Transaction method name {:?} isn't allowed by the access key", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: method_name, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Path( + PatPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "The used access key requires exactly one FunctionCall action", + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidAccessKeyError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + NotEnoughAllowance, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + public_key, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + public_key, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + allowance, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + allowance, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + cost, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + cost, + ), + subpat: None, + }, + ), + }, + Comma, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Access Key {:?}:{} does not have enough balance {} for transaction costing {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: public_key, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: allowance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: cost, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Struct( + ItemStruct { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Happens when the input balance doesn't match the output balance in Runtime apply.", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + struct_token: Struct, + ident: Ident( + BalanceMismatchError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + fields: Named( + FieldsNamed { + brace_token: Brace, + named: [ + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + incoming_validator_rewards, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + initial_accounts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + incoming_receipts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + processed_delayed_receipts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + initial_postponed_receipts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + final_accounts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + outgoing_receipts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + new_delayed_receipts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + final_postponed_receipts_balance, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + total_rent_paid, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + total_validator_reward, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + total_balance_burnt, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + Field { + attrs: [], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + ident: Some( + Ident( + total_balance_slashed, + ), + ), + colon_token: Some( + Colon, + ), + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Balance, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + Comma, + ], + }, + ), + semi_token: None, + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + BalanceMismatchError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Local( + Local { + attrs: [], + let_token: Let, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + initial_balance, + ), + subpat: None, + }, + ), + init: Some( + ( + Eq, + MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + incoming_validator_rewards, + ), + ), + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + initial_accounts_balance, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + incoming_receipts_balance, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + processed_delayed_receipts_balance, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + initial_postponed_receipts_balance, + ), + ), + }, + ), + ], + }, + ), + ), + ), + semi_token: Semi, + }, + ), + Local( + Local { + attrs: [], + let_token: Let, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + final_balance, + ), + subpat: None, + }, + ), + init: Some( + ( + Eq, + MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: MethodCall( + ExprMethodCall { + attrs: [], + receiver: Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + final_accounts_balance, + ), + ), + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + outgoing_receipts_balance, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + new_delayed_receipts_balance, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + final_postponed_receipts_balance, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + total_rent_paid, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + total_validator_reward, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + total_balance_burnt, + ), + ), + }, + ), + ], + }, + ), + dot_token: Dot, + method: Ident( + saturating_add, + ), + turbofish: None, + paren_token: Paren, + args: [ + Field( + ExprField { + attrs: [], + base: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + dot_token: Dot, + member: Named( + Ident( + total_balance_slashed, + ), + ), + }, + ), + ], + }, + ), + ), + ), + semi_token: Semi, + }, + ), + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Balance Mismatch Error. The input balance {} doesn't match output balance {}\n\ + Inputs:\n\ + \tIncoming validator rewards sum: {}\n\ + \tInitial accounts balance sum: {}\n\ + \tIncoming receipts balance sum: {}\n\ + \tProcessed delayed receipts balance sum: {}\n\ + \tInitial postponed receipts balance sum: {}\n\ + Outputs:\n\ + \tFinal accounts balance sum: {}\n\ + \tOutgoing receipts balance sum: {}\n\ + \tNew delayed receipts balance sum: {}\n\ + \tFinal postponed receipts balance sum: {}\n\ + \tTotal rent paid: {}\n\ + \tTotal validators reward: {}\n\ + \tTotal balance burnt: {}\n\ + \tTotal balance slashed: {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: initial_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: final_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: incoming_validator_rewards, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: initial_accounts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: incoming_receipts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: processed_delayed_receipts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: initial_postponed_receipts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: final_accounts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: outgoing_receipts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: new_delayed_receipts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: final_postponed_receipts_balance, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: total_rent_paid, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: total_validator_reward, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: total_balance_burnt, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: total_balance_slashed, + }, + Punct { + op: ',', + spacing: Alone, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Struct( + ItemStruct { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + struct_token: Struct, + ident: Ident( + IntegerOverflowError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + fields: Unit, + semi_token: Some( + Semi, + ), + }, + ), + Enum( + ItemEnum { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Error returned from `Runtime::apply`", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + enum_token: Enum, + ident: Ident( + RuntimeError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + brace_token: Brace, + variants: [ + Variant { + attrs: [], + ident: Ident( + UnexpectedIntegerOverflow, + ), + fields: Unit, + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidTxError, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + StorageError, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + StorageError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + BalanceMismatch, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + BalanceMismatchError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + IntegerOverflowError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Wild( + PatWild { + attrs: [], + underscore_token: Underscore, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + IntegerOverflowError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + CostOverflow, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + IntegerOverflowError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Wild( + PatWild { + attrs: [], + underscore_token: Underscore, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + IntegerOverflowError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + UnexpectedIntegerOverflow, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + StorageError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + e, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + StorageError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Call( + ExprCall { + attrs: [], + func: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + StorageError, + ), + arguments: None, + }, + ], + }, + }, + ), + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + e, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + BalanceMismatchError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + e, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + BalanceMismatchError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Call( + ExprCall { + attrs: [], + func: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + BalanceMismatch, + ), + arguments: None, + }, + ], + }, + }, + ), + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + e, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + e, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Call( + ExprCall { + attrs: [], + func: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + RuntimeError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + e, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Action #{}: {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: index, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: unwrap_or_default, + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: self, + }, + Punct { + op: '.', + spacing: Alone, + }, + Ident { + sym: kind, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Match( + ExprMatch { + attrs: [], + match_token: Match, + expr: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + arms: [ + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + AccountAlreadyExists, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Can't create a new account {:?}, because it already exists", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + AccountDoesNotExist, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Can't complete the action because account {:?} doesn't exist", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + ActorNoPermission, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + actor_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + actor_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Actor {:?} doesn't have permission to account {:?} to complete the action", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: actor_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + RentUnpaid, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + amount, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + amount, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "The account {} wouldn't have enough balance to pay required rent {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: amount, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + TriesToUnstake, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Account {:?} is not yet staked, but tries to unstake", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + TriesToStake, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + stake, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + stake, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + locked, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + locked, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + balance, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + balance, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Account {:?} tries to stake {}, but has staked {} and only has {}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: stake, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: locked, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: balance, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + CreateAccountNotAllowed, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + predecessor_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + predecessor_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "The new account_id {:?} can't be created by {:?}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: predecessor_id, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + DeleteKeyDoesNotExist, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + ], + dot2_token: Some( + Dot2, + ), + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Account {:?} tries to remove an access key that doesn't exist", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + AddKeyAlreadyExists, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + public_key, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + public_key, + ), + subpat: None, + }, + ), + }, + Comma, + ], + dot2_token: Some( + Dot2, + ), + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "The public key {:?} is already used for an existing access key", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: public_key, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + DeleteAccountStaking, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Block( + ExprBlock { + attrs: [], + label: None, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Account {:?} is staking and can not be deleted", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + ], + }, + }, + ), + ), + ], + }, + }, + ), + comma: None, + }, + Arm { + attrs: [], + pat: Struct( + PatStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + DeleteAccountHasRent, + ), + arguments: None, + }, + ], + }, + brace_token: Brace, + fields: [ + FieldPat { + attrs: [], + member: Named( + Ident( + account_id, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + account_id, + ), + subpat: None, + }, + ), + }, + Comma, + FieldPat { + attrs: [], + member: Named( + Ident( + balance, + ), + ), + colon_token: None, + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + balance, + ), + subpat: None, + }, + ), + }, + ], + dot2_token: None, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: account_id, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: balance, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: TupleStruct( + PatTupleStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionErrorKind, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + FunctionCall, + ), + arguments: None, + }, + ], + }, + pat: PatTuple { + attrs: [], + paren_token: Paren, + elems: [ + Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + s, + ), + subpat: None, + }, + ), + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "{}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: s, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Enum( + ItemEnum { + attrs: [ + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + doc, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Punct { + op: '=', + spacing: Alone, + }, + Literal { + lit: " Error returned in the ExecutionOutcome in case of failure.", + }, + ], + }, + Attribute { + pound_token: Pound, + style: Outer, + bracket_token: Bracket, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + derive, + ), + arguments: None, + }, + ], + }, + tokens: TokenStream [ + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + sym: BorshSerialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: BorshDeserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Debug, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Clone, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: PartialEq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Eq, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Deserialize, + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: Serialize, + }, + ], + }, + ], + }, + ], + vis: Public( + VisPublic { + pub_token: Pub, + }, + ), + enum_token: Enum, + ident: Ident( + ExecutionError, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + brace_token: Brace, + variants: [ + Variant { + attrs: [], + ident: Ident( + Action, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + Variant { + attrs: [], + ident: Ident( + InvalidTx, + ), + fields: Unnamed( + FieldsUnnamed { + paren_token: Paren, + unnamed: [ + Field { + attrs: [], + vis: Inherited, + ident: None, + colon_token: None, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ], + }, + ), + discriminant: None, + }, + Comma, + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Display, + ), + arguments: None, + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + fmt, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Receiver( + Receiver { + attrs: [], + reference: Some( + ( + And, + None, + ), + ), + mutability: None, + self_token: SelfValue, + }, + ), + Comma, + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + f, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Reference( + TypeReference { + and_token: And, + lifetime: None, + mutability: Some( + Mut, + ), + elem: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Formatter, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Result, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Tuple( + TypeTuple { + paren_token: Paren, + elems: [], + }, + ), + ), + Comma, + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + std, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + fmt, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Error, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Match( + ExprMatch { + attrs: [], + match_token: Match, + expr: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + self, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + arms: [ + Arm { + attrs: [], + pat: TupleStruct( + PatTupleStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Action, + ), + arguments: None, + }, + ], + }, + pat: PatTuple { + attrs: [], + paren_token: Paren, + elems: [ + Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + e, + ), + subpat: None, + }, + ), + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "{}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: e, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + Arm { + attrs: [], + pat: TupleStruct( + PatTupleStruct { + attrs: [], + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidTx, + ), + arguments: None, + }, + ], + }, + pat: PatTuple { + attrs: [], + paren_token: Paren, + elems: [ + Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + e, + ), + subpat: None, + }, + ), + ], + }, + }, + ), + guard: None, + fat_arrow_token: FatArrow, + body: Macro( + ExprMacro { + attrs: [], + mac: Macro { + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + write, + ), + arguments: None, + }, + ], + }, + bang_token: Bang, + delimiter: Paren( + Paren, + ), + tokens: TokenStream [ + Ident { + sym: f, + }, + Punct { + op: ',', + spacing: Alone, + }, + Literal { + lit: "{}", + }, + Punct { + op: ',', + spacing: Alone, + }, + Ident { + sym: e, + }, + ], + }, + }, + ), + comma: Some( + Comma, + ), + }, + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + error, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ActionError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Call( + ExprCall { + attrs: [], + func: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + Action, + ), + arguments: None, + }, + ], + }, + }, + ), + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + error, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + Impl( + ItemImpl { + attrs: [], + defaultness: None, + unsafety: None, + impl_token: Impl, + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + trait_: Some( + ( + None, + Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + From, + ), + arguments: AngleBracketed( + AngleBracketedGenericArguments { + colon2_token: None, + lt_token: Lt, + args: [ + Type( + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + ], + gt_token: Gt, + }, + ), + }, + ], + }, + For, + ), + ), + self_ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + ], + }, + }, + ), + brace_token: Brace, + items: [ + Method( + ImplItemMethod { + attrs: [], + vis: Inherited, + defaultness: None, + sig: Signature { + constness: None, + asyncness: None, + unsafety: None, + abi: None, + fn_token: Fn, + ident: Ident( + from, + ), + generics: Generics { + lt_token: None, + params: [], + gt_token: None, + where_clause: None, + }, + paren_token: Paren, + inputs: [ + Typed( + PatType { + attrs: [], + pat: Ident( + PatIdent { + attrs: [], + by_ref: None, + mutability: None, + ident: Ident( + error, + ), + subpat: None, + }, + ), + colon_token: Colon, + ty: Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + InvalidTxError, + ), + arguments: None, + }, + ], + }, + }, + ), + }, + ), + ], + variadic: None, + output: Type( + RArrow, + Path( + TypePath { + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + Self, + ), + arguments: None, + }, + ], + }, + }, + ), + ), + }, + block: Block { + brace_token: Brace, + stmts: [ + Expr( + Call( + ExprCall { + attrs: [], + func: Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + ExecutionError, + ), + arguments: None, + }, + Colon2, + PathSegment { + ident: Ident( + InvalidTx, + ), + arguments: None, + }, + ], + }, + }, + ), + paren_token: Paren, + args: [ + Path( + ExprPath { + attrs: [], + qself: None, + path: Path { + leading_colon: None, + segments: [ + PathSegment { + ident: Ident( + error, + ), + arguments: None, + }, + ], + }, + }, + ), + ], + }, + ), + ), + ], + }, + }, + ), + ], + }, + ), + ], +} diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs new file mode 100644 index 00000000000..5c45db664e6 --- /dev/null +++ b/tools/rpctypegen/src/lib.rs @@ -0,0 +1,55 @@ +extern crate proc_macro; +extern crate proc_macro2; +use proc_macro::TokenStream; +use proc_macro2::Literal; +use quote::quote; +use serde::{Deserialize, Serialize}; +use std::cell::RefCell; +use std::collections::HashMap; +use syn::parse::{Parse, ParseStream}; +use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue}; + +struct ErrorVariants { + name: String, +} + +#[derive(Default, Debug, Deserialize, Serialize)] +struct ErrorType { + /// A type name of the error + name: String, + /// Names of subtypes of the error + kinds: Vec, + // /// An error input + props: Vec, +} + +thread_local!(static SCHEMA: RefCell>> = RefCell::new(HashMap::new())); + +fn parse_parent_name(input: &DeriveInput) -> Option { + input.attrs.iter().find_map(|attr| { + if !attr.path.is_ident("rpc_error_parent") { + return None; + } + match attr.parse_meta().unwrap() { + Meta::NameValue(MetaNameValue { lit: Lit::Str(lit), .. }) => Some(lit.value()), + _ => None, + } + }) +} + +#[proc_macro_derive(RpcError, attributes(rpc_error_parent))] +pub fn rpc_error(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let parent_name = parse_parent_name(input); + SCHEMA.with(|s| { + s.borrow_mut().insert(format!("{}", parent_name), Default::default()); + }); + + SCHEMA.with(|s| { + println!("{:?}", s.borrow()); + }); + + println!("{:?}", parse_parent_name(&input)); + + TokenStream::new() +} diff --git a/tools/rpctypegen/src/parser.rs b/tools/rpctypegen/src/parser.rs new file mode 100644 index 00000000000..db008340023 --- /dev/null +++ b/tools/rpctypegen/src/parser.rs @@ -0,0 +1,35 @@ + +pub struct Config { + pub primitives: HashMap; + pub types: Vec; + pub kinds: HashMap; +} + +enum Entry { + Kind(Kind), + Type(Type), + KindAndType(Kind, Type), +} + +struct Kind { + name: String, +} + +struct Type { + name: String, + args: Value, +} + +struct Generator { + config: Config, +} + +impl Generator { + pub fn new(config: Config) -> Self { + + } +} + +fn parse_from_str (input: ) { + +} From a339c34127e3356e9561594410c852ee64b55ff3 Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 26 Dec 2019 14:16:07 +0300 Subject: [PATCH 13/48] continue with RpcError derive_macro --- chain/jsonrpc/src/lib.rs | 3 +- core/primitives/src/errors.rs | 14 ++++++++- tools/rpctypegen/src/lib.rs | 53 ++++++++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index 9d498d71678..dc52fce9c65 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -119,7 +119,8 @@ fn parse_hash(params: Option) -> Result { }) } -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, RpcError)] +#[rpc_error_variant = "ServerError"] pub enum ServerError { TxExecutionError(ExecutionError), Timeout, diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 1a48e1fe585..5c77430e728 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -12,7 +12,7 @@ use near_vm_errors::VMError; #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_parent = "ServerError"] +#[rpc_error_variant = "TxExecutionError"] pub enum ExecutionError { Action(ActionError), InvalidTx(InvalidTxError), @@ -130,6 +130,18 @@ pub enum InvalidAccessKeyError { }, } +/// +/// +/// Variants are types +/// +/// {"ServerError": { "TxError" { "kind": { "ActionError" : { } } } +/// kind: "TxError", +/// +/// } +/// } +/// +/// + #[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct ActionError { pub index: Option, diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 5c45db664e6..88125d56154 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -7,27 +7,23 @@ use serde::{Deserialize, Serialize}; use std::cell::RefCell; use std::collections::HashMap; use syn::parse::{Parse, ParseStream}; -use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue}; - -struct ErrorVariants { - name: String, -} +use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue, Data, DataEnum, Fields, FieldsUnnamed}; #[derive(Default, Debug, Deserialize, Serialize)] struct ErrorType { /// A type name of the error - name: String, + pub name: String, /// Names of subtypes of the error - kinds: Vec, + pub subtypes: Vec, // /// An error input - props: Vec, + pub props: HashMap, } thread_local!(static SCHEMA: RefCell>> = RefCell::new(HashMap::new())); -fn parse_parent_name(input: &DeriveInput) -> Option { +fn parse_rpc_error_variant(input: &DeriveInput) -> Option { input.attrs.iter().find_map(|attr| { - if !attr.path.is_ident("rpc_error_parent") { + if !attr.path.is_ident("rpc_error_variant") { return None; } match attr.parse_meta().unwrap() { @@ -37,12 +33,43 @@ fn parse_parent_name(input: &DeriveInput) -> Option { }) } -#[proc_macro_derive(RpcError, attributes(rpc_error_parent))] +fn parse_error_type(input: &DeriveInput) -> ErrorType { + let mut error_type = ErrorType::default(); + error_type.name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); + match input.data { + // If Variant is a NewType add to subtypes + // - if Variant is a struct-variant, create a new + Data::Enum(DataEnum{ variants, .. }) => { + for variant in variants { + match variant.fields { + Fields::Unnamed( ) => { + + } + } + } + error_type.subtypes = variants.iter().map(|variant| { + variant.fields.iter + match variant.fields { + + } + }) + }, + Body::Struct(VariantData::Struct( fields )) => { + + // for field in fields { + // println!("{:?}", field.); + // } + // error_type.props = fields.iter().collect::>>(); + } + } + error_type +} + +#[proc_macro_derive(RpcError, attributes(rpc_error_variant))] pub fn rpc_error(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); - let parent_name = parse_parent_name(input); SCHEMA.with(|s| { - s.borrow_mut().insert(format!("{}", parent_name), Default::default()); + s.borrow_mut().insert(format!("{}", parent_name.unwrap()), Default::default()); }); SCHEMA.with(|s| { From c32ddb9e1d7b2963796b64120d5e23151dda1c27 Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 26 Dec 2019 20:41:36 +0300 Subject: [PATCH 14/48] continue working --- core/primitives/src/errors.rs | 11 +++-- tools/rpctypegen/src/lib.rs | 83 +++++++++++++++++++++++------------ 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 5c77430e728..78a8a064b8a 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -49,7 +49,7 @@ pub enum RuntimeError { } /// Internal -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, RpcError)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] pub enum StorageError { /// Key-value db internal failure StorageInternalError, @@ -72,7 +72,8 @@ impl std::fmt::Display for StorageError { impl std::error::Error for StorageError {} /// External -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[rpc_error_variant = "InvalidTx"] pub enum InvalidTxError { InvalidAccessKey(InvalidAccessKeyError), InvalidSigner { @@ -106,7 +107,8 @@ pub enum InvalidTxError { Expired, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[rpc_error_variant = "InvalidAccessKey"] pub enum InvalidAccessKeyError { AccessKeyNotFound { account_id: AccountId, @@ -142,7 +144,8 @@ pub enum InvalidAccessKeyError { /// /// -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[rpc_error_variant = "Action"] pub struct ActionError { pub index: Option, pub kind: ActionErrorKind, diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 88125d56154..02dce524bb3 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use std::cell::RefCell; use std::collections::HashMap; use syn::parse::{Parse, ParseStream}; -use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue, Data, DataEnum, Fields, FieldsUnnamed}; +use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue, Data, DataEnum, DataStruct, Fields, FieldsUnnamed, FieldsNamed}; #[derive(Default, Debug, Deserialize, Serialize)] struct ErrorType { @@ -15,11 +15,11 @@ struct ErrorType { pub name: String, /// Names of subtypes of the error pub subtypes: Vec, - // /// An error input + // /// An error input name and type pub props: HashMap, } -thread_local!(static SCHEMA: RefCell>> = RefCell::new(HashMap::new())); +thread_local!(static SCHEMA: RefCell> = RefCell::new(HashMap::new())); fn parse_rpc_error_variant(input: &DeriveInput) -> Option { input.attrs.iter().find_map(|attr| { @@ -33,50 +33,77 @@ fn parse_rpc_error_variant(input: &DeriveInput) -> Option { }) } -fn parse_error_type(input: &DeriveInput) -> ErrorType { - let mut error_type = ErrorType::default(); - error_type.name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); - match input.data { +fn error_type_unique_insert<'a>(schema: &'a mut HashMap, name: String) -> &'a mut ErrorType { + if schema.contains_key(&name) { + panic!(format!("Error variant duplication ({})", name)) + } + let error_type = ErrorType{ name: name.clone(), ..Default::default() }; + schema.insert(name.clone(), error_type); + schema.get_mut(&name).unwrap() +} + +fn parse_error_type(schema: &mut HashMap, input: &DeriveInput) { + let name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); + let mut error_type = error_type_unique_insert(schema, name); + let mut direct_error_types = vec![]; + match &input.data { // If Variant is a NewType add to subtypes // - if Variant is a struct-variant, create a new - Data::Enum(DataEnum{ variants, .. }) => { + Data::Enum(DataEnum{ ref variants, .. }) => { for variant in variants { - match variant.fields { - Fields::Unnamed( ) => { - + match &variant.fields { + Fields::Unnamed( FieldsUnnamed { ref unnamed, .. } ) => { + // Subtype + if unnamed.iter().count() > 1 { + panic!("Error types doesn't support tuple variants with multiple fields"); + } + error_type.subtypes.push(variant.ident.to_string()); + } + Fields::Named(FieldsNamed { ref named, .. }) => { + // If variant is Enum with a named fields - create a new type for each variant with named props + let mut error_type = ErrorType::default(); + error_type.name = variant.ident.to_string(); + for field in named { + error_type.props.insert(field.ident.as_ref().expect("named fields must have ident").to_string(), "".to_owned()); // TODO: add type + } + direct_error_types.push(error_type); + } + Fields::Unit => { + direct_error_types.push(ErrorType{name: variant.ident.to_string(), ..Default::default()}); } } } - error_type.subtypes = variants.iter().map(|variant| { - variant.fields.iter - match variant.fields { - - } - }) }, - Body::Struct(VariantData::Struct( fields )) => { + Data::Struct(DataStruct{ fields, .. }) => { - // for field in fields { - // println!("{:?}", field.); - // } - // error_type.props = fields.iter().collect::>>(); + }, + Data::Union(_) => { + panic!("Unions are not supported"); } } - error_type + for e in direct_error_types { + let mut error_type = error_type_unique_insert(schema, e.name.clone()); + error_type.name = e.name; + error_type.props = e.props; + } } #[proc_macro_derive(RpcError, attributes(rpc_error_variant))] pub fn rpc_error(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); - SCHEMA.with(|s| { - s.borrow_mut().insert(format!("{}", parent_name.unwrap()), Default::default()); - }); SCHEMA.with(|s| { - println!("{:?}", s.borrow()); + parse_error_type(&mut s.borrow_mut(), &input); }); + // SCHEMA.with(|s| { + // s.borrow_mut().insert(format!("{}", parent_name.unwrap()), Default::default()); + // }); + + // SCHEMA.with(|s| { + // println!("{:?}", s.borrow()); + // }); - println!("{:?}", parse_parent_name(&input)); + // println!("{:?}", parse_parent_name(&input)); TokenStream::new() } From 63e7cc4b051e97cc2755d41c420a1a31c4fa2fb6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 27 Dec 2019 17:27:23 +0300 Subject: [PATCH 15/48] errors JSON schema generation done --- core/primitives/src/errors.rs | 3 +- tools/rpctypegen/src/lib.rs | 73 +++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 78a8a064b8a..0faa2d5e88c 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -151,7 +151,8 @@ pub struct ActionError { pub kind: ActionErrorKind, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[rpc_error_variant = "Action"] pub enum ActionErrorKind { AccountAlreadyExists { account_id: AccountId, diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 02dce524bb3..1986512d46e 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -9,6 +9,20 @@ use std::collections::HashMap; use syn::parse::{Parse, ParseStream}; use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue, Data, DataEnum, DataStruct, Fields, FieldsUnnamed, FieldsNamed}; +#[derive(Default, Debug, Deserialize, Serialize)] +struct Schema { + pub schema: HashMap, +} + +impl Drop for Schema { + fn drop(&mut self) { + // std::env::var("CARGO_TARGET_DIR") doesn't work for some reason + let filename = "./target/errors_schema.json"; + let json = serde_json::to_string_pretty(self).expect("Schema serialize failed"); + std::fs::write(filename, json).expect("Unable to save the errors schema file"); + } +} + #[derive(Default, Debug, Deserialize, Serialize)] struct ErrorType { /// A type name of the error @@ -19,7 +33,7 @@ struct ErrorType { pub props: HashMap, } -thread_local!(static SCHEMA: RefCell> = RefCell::new(HashMap::new())); +thread_local!(static SCHEMA: RefCell = RefCell::new(Schema::default())); fn parse_rpc_error_variant(input: &DeriveInput) -> Option { input.attrs.iter().find_map(|attr| { @@ -33,38 +47,35 @@ fn parse_rpc_error_variant(input: &DeriveInput) -> Option { }) } -fn error_type_unique_insert<'a>(schema: &'a mut HashMap, name: String) -> &'a mut ErrorType { - if schema.contains_key(&name) { - panic!(format!("Error variant duplication ({})", name)) - } +fn error_type_name<'a>(schema: &'a mut HashMap, name: String) -> &'a mut ErrorType { let error_type = ErrorType{ name: name.clone(), ..Default::default() }; - schema.insert(name.clone(), error_type); - schema.get_mut(&name).unwrap() + schema.entry(name.clone()).or_insert(error_type) } fn parse_error_type(schema: &mut HashMap, input: &DeriveInput) { let name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); - let mut error_type = error_type_unique_insert(schema, name); - let mut direct_error_types = vec![]; match &input.data { // If Variant is a NewType add to subtypes // - if Variant is a struct-variant, create a new Data::Enum(DataEnum{ ref variants, .. }) => { + let mut error_type = error_type_name(schema, name); + let mut direct_error_types = vec![]; for variant in variants { + error_type.subtypes.push(variant.ident.to_string()); match &variant.fields { Fields::Unnamed( FieldsUnnamed { ref unnamed, .. } ) => { // Subtype if unnamed.iter().count() > 1 { panic!("Error types doesn't support tuple variants with multiple fields"); } - error_type.subtypes.push(variant.ident.to_string()); } Fields::Named(FieldsNamed { ref named, .. }) => { // If variant is Enum with a named fields - create a new type for each variant with named props let mut error_type = ErrorType::default(); error_type.name = variant.ident.to_string(); for field in named { - error_type.props.insert(field.ident.as_ref().expect("named fields must have ident").to_string(), "".to_owned()); // TODO: add type + error_type.props.insert(field.ident.as_ref() + .expect("named fields must have ident").to_string(), "".to_owned()); // TODO: add type } direct_error_types.push(error_type); } @@ -73,19 +84,33 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput } } } + for e in direct_error_types { + let mut error_type = error_type_name(schema, e.name.clone()); + error_type.name = e.name; + error_type.props = e.props; + } }, - Data::Struct(DataStruct{ fields, .. }) => { - + Data::Struct(DataStruct{ ref fields, ..} ) => { + let mut error_type = error_type_name(schema, name); + match fields { + Fields::Named(FieldsNamed{ ref named, .. }) => { + for field in named { + let field_name = field.ident.as_ref().expect("named fields must have ident").to_string(); + if field_name == "kind" { + continue; + } + error_type.props.insert(field_name, "".to_owned()); // TODO: add prop type + } + } + _ => { + panic!("RpcError supports structs with the named fields only"); + } + } }, Data::Union(_) => { panic!("Unions are not supported"); } } - for e in direct_error_types { - let mut error_type = error_type_unique_insert(schema, e.name.clone()); - error_type.name = e.name; - error_type.props = e.props; - } } #[proc_macro_derive(RpcError, attributes(rpc_error_variant))] @@ -93,17 +118,7 @@ pub fn rpc_error(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); SCHEMA.with(|s| { - parse_error_type(&mut s.borrow_mut(), &input); + parse_error_type(&mut s.borrow_mut().schema, &input); }); - // SCHEMA.with(|s| { - // s.borrow_mut().insert(format!("{}", parent_name.unwrap()), Default::default()); - // }); - - // SCHEMA.with(|s| { - // println!("{:?}", s.borrow()); - // }); - - // println!("{:?}", parse_parent_name(&input)); - TokenStream::new() } From 3aebd7504aa81217961d511314ace2b975833ee0 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 30 Dec 2019 19:07:22 +0300 Subject: [PATCH 16/48] Do not rewrite the schema file. Merge error schemas instead. --- Cargo.lock | 1 + chain/jsonrpc/Cargo.toml | 1 + chain/jsonrpc/src/lib.rs | 3 +- core/primitives/src/errors.rs | 30 ++++++------- tools/rpctypegen/src/lib.rs | 80 ++++++++++++++++++++++++---------- tools/rpctypegen/src/parser.rs | 35 --------------- 6 files changed, 74 insertions(+), 76 deletions(-) delete mode 100644 tools/rpctypegen/src/parser.rs diff --git a/Cargo.lock b/Cargo.lock index cf8a8e5ea5d..e591245e007 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2143,6 +2143,7 @@ dependencies = [ "near-network 0.1.0", "near-pool 0.1.0", "near-primitives 0.1.0", + "near-rpc-error-macro 0.1.0", "near-store 0.1.0", "prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/chain/jsonrpc/Cargo.toml b/chain/jsonrpc/Cargo.toml index ce3113e5f35..5b4fb041112 100644 --- a/chain/jsonrpc/Cargo.toml +++ b/chain/jsonrpc/Cargo.toml @@ -34,3 +34,4 @@ near-client = { path = "../client" } near-network = { path = "../network" } near-pool = { path = "../pool" } near-jsonrpc-client = { path = "client" } +near-rpc-error-macro = { path = "../../tools/rpctypegen" } diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index dc52fce9c65..aad0c6b5631 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -119,7 +119,8 @@ fn parse_hash(params: Option) -> Result { }) } -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, RpcError)] +/// A general Server Error +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, near_rpc_error_macro::RpcError)] #[rpc_error_variant = "ServerError"] pub enum ServerError { TxExecutionError(ExecutionError), diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 0faa2d5e88c..58eb26b0450 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -8,7 +8,7 @@ use std::fmt::Display; use near_rpc_error_macro::RpcError; use near_vm_errors::VMError; -/// Error returned in the ExecutionOutcome in case of failure. +/// Error returned in the ExecutionOutcome in case of failure #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] @@ -72,7 +72,9 @@ impl std::fmt::Display for StorageError { impl std::error::Error for StorageError {} /// External -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[derive( + BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, +)] #[rpc_error_variant = "InvalidTx"] pub enum InvalidTxError { InvalidAccessKey(InvalidAccessKeyError), @@ -107,7 +109,9 @@ pub enum InvalidTxError { Expired, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[derive( + BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, +)] #[rpc_error_variant = "InvalidAccessKey"] pub enum InvalidAccessKeyError { AccessKeyNotFound { @@ -132,26 +136,18 @@ pub enum InvalidAccessKeyError { }, } -/// -/// -/// Variants are types -/// -/// {"ServerError": { "TxError" { "kind": { "ActionError" : { } } } -/// kind: "TxError", -/// -/// } -/// } -/// -/// - -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[derive( + BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, +)] #[rpc_error_variant = "Action"] pub struct ActionError { pub index: Option, pub kind: ActionErrorKind, } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError)] +#[derive( + BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, +)] #[rpc_error_variant = "Action"] pub enum ActionErrorKind { AccountAlreadyExists { diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 1986512d46e..53901376dc1 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -1,13 +1,27 @@ extern crate proc_macro; extern crate proc_macro2; use proc_macro::TokenStream; -use proc_macro2::Literal; -use quote::quote; use serde::{Deserialize, Serialize}; +use serde_json::Value; use std::cell::RefCell; use std::collections::HashMap; -use syn::parse::{Parse, ParseStream}; -use syn::{parse_macro_input, DeriveInput, Lit, Meta, MetaNameValue, Data, DataEnum, DataStruct, Fields, FieldsUnnamed, FieldsNamed}; +use syn::{ + parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, + Lit, Meta, MetaNameValue, +}; + +fn merge(a: &mut Value, b: &Value) { + match (a, b) { + (&mut Value::Object(ref mut a), &Value::Object(ref b)) => { + for (k, v) in b { + merge(a.entry(k.clone()).or_insert(Value::Null), v); + } + } + (a, b) => { + *a = b.clone(); + } + } +} #[derive(Default, Debug, Deserialize, Serialize)] struct Schema { @@ -18,7 +32,14 @@ impl Drop for Schema { fn drop(&mut self) { // std::env::var("CARGO_TARGET_DIR") doesn't work for some reason let filename = "./target/errors_schema.json"; - let json = serde_json::to_string_pretty(self).expect("Schema serialize failed"); + let mut json_value = serde_json::to_value(self).expect("Schema serialize failed"); + if let Ok(data) = std::fs::read(filename) { + if let Ok(existing_schema) = serde_json::from_slice::(&data) { + merge(&mut json_value, &existing_schema); + }; + }; + let json = + serde_json::to_string_pretty(&json_value).expect("error schema serialization failed"); std::fs::write(filename, json).expect("Unable to save the errors schema file"); } } @@ -47,26 +68,29 @@ fn parse_rpc_error_variant(input: &DeriveInput) -> Option { }) } -fn error_type_name<'a>(schema: &'a mut HashMap, name: String) -> &'a mut ErrorType { - let error_type = ErrorType{ name: name.clone(), ..Default::default() }; - schema.entry(name.clone()).or_insert(error_type) +fn error_type_name<'a>( + schema: &'a mut HashMap, + name: String, +) -> &'a mut ErrorType { + let error_type = ErrorType { name: name.clone(), ..Default::default() }; + schema.entry(name.clone()).or_insert(error_type) } fn parse_error_type(schema: &mut HashMap, input: &DeriveInput) { let name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); match &input.data { - // If Variant is a NewType add to subtypes - // - if Variant is a struct-variant, create a new - Data::Enum(DataEnum{ ref variants, .. }) => { - let mut error_type = error_type_name(schema, name); + Data::Enum(DataEnum { ref variants, .. }) => { + let error_type = error_type_name(schema, name); let mut direct_error_types = vec![]; for variant in variants { error_type.subtypes.push(variant.ident.to_string()); match &variant.fields { - Fields::Unnamed( FieldsUnnamed { ref unnamed, .. } ) => { + Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) => { // Subtype if unnamed.iter().count() > 1 { - panic!("Error types doesn't support tuple variants with multiple fields"); + panic!( + "Error types doesn't support tuple variants with multiple fields" + ); } } Fields::Named(FieldsNamed { ref named, .. }) => { @@ -74,13 +98,22 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput let mut error_type = ErrorType::default(); error_type.name = variant.ident.to_string(); for field in named { - error_type.props.insert(field.ident.as_ref() - .expect("named fields must have ident").to_string(), "".to_owned()); // TODO: add type + error_type.props.insert( + field + .ident + .as_ref() + .expect("named fields must have ident") + .to_string(), + "".to_owned(), + ); // TODO: add type } direct_error_types.push(error_type); } Fields::Unit => { - direct_error_types.push(ErrorType{name: variant.ident.to_string(), ..Default::default()}); + direct_error_types.push(ErrorType { + name: variant.ident.to_string(), + ..Default::default() + }); } } } @@ -89,13 +122,14 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput error_type.name = e.name; error_type.props = e.props; } - }, - Data::Struct(DataStruct{ ref fields, ..} ) => { - let mut error_type = error_type_name(schema, name); + } + Data::Struct(DataStruct { ref fields, .. }) => { + let error_type = error_type_name(schema, name); match fields { - Fields::Named(FieldsNamed{ ref named, .. }) => { + Fields::Named(FieldsNamed { ref named, .. }) => { for field in named { - let field_name = field.ident.as_ref().expect("named fields must have ident").to_string(); + let field_name = + field.ident.as_ref().expect("named fields must have ident").to_string(); if field_name == "kind" { continue; } @@ -106,7 +140,7 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput panic!("RpcError supports structs with the named fields only"); } } - }, + } Data::Union(_) => { panic!("Unions are not supported"); } diff --git a/tools/rpctypegen/src/parser.rs b/tools/rpctypegen/src/parser.rs deleted file mode 100644 index db008340023..00000000000 --- a/tools/rpctypegen/src/parser.rs +++ /dev/null @@ -1,35 +0,0 @@ - -pub struct Config { - pub primitives: HashMap; - pub types: Vec; - pub kinds: HashMap; -} - -enum Entry { - Kind(Kind), - Type(Type), - KindAndType(Kind, Type), -} - -struct Kind { - name: String, -} - -struct Type { - name: String, - args: Value, -} - -struct Generator { - config: Config, -} - -impl Generator { - pub fn new(config: Config) -> Self { - - } -} - -fn parse_from_str (input: ) { - -} From 695c11b54797743451df7b115fb7acad2f9bda32 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 30 Dec 2019 19:41:20 +0300 Subject: [PATCH 17/48] small fix --- tools/rpctypegen/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 53901376dc1..b92efe5d64e 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -32,10 +32,10 @@ impl Drop for Schema { fn drop(&mut self) { // std::env::var("CARGO_TARGET_DIR") doesn't work for some reason let filename = "./target/errors_schema.json"; - let mut json_value = serde_json::to_value(self).expect("Schema serialize failed"); + let json_value = serde_json::to_value(self).expect("Schema serialize failed"); if let Ok(data) = std::fs::read(filename) { - if let Ok(existing_schema) = serde_json::from_slice::(&data) { - merge(&mut json_value, &existing_schema); + if let Ok(mut existing_schema) = serde_json::from_slice::(&data) { + merge(&mut existing_schema, &json_value); }; }; let json = From 212a430c620beabdbbfa7ebf2d911faeec191da6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 31 Dec 2019 16:51:45 +0300 Subject: [PATCH 18/48] VMErrors refactoring --- Cargo.lock | 1 + runtime/near-vm-errors/Cargo.toml | 1 + runtime/near-vm-errors/src/lib.rs | 82 +++++++---- runtime/near-vm-logic/src/logic.rs | 132 +++++++++++------- .../near-vm-logic/src/mocks/mock_external.rs | 6 +- runtime/near-vm-runner/src/errors.rs | 14 +- runtime/runtime/src/actions.rs | 2 +- runtime/runtime/src/ext.rs | 6 +- tools/rpctypegen/src/lib.rs | 14 +- 9 files changed, 162 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e591245e007..d97e1158aaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2295,6 +2295,7 @@ name = "near-vm-errors" version = "0.4.3" dependencies = [ "borsh 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "near-rpc-error-macro 0.1.0", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/runtime/near-vm-errors/Cargo.toml b/runtime/near-vm-errors/Cargo.toml index e7c002a222e..c8aaf577539 100644 --- a/runtime/near-vm-errors/Cargo.toml +++ b/runtime/near-vm-errors/Cargo.toml @@ -13,5 +13,6 @@ Error that can occur inside Near Runtime encapsulated in a separate crate. Might """ [dependencies] +near-rpc-error-macro = { path = "../../tools/rpctypegen" } borsh = "0.2.10" serde = { version = "1.0", features = ["derive"] } diff --git a/runtime/near-vm-errors/src/lib.rs b/runtime/near-vm-errors/src/lib.rs index 5c6f93ebd69..3087dfca8f1 100644 --- a/runtime/near-vm-errors/src/lib.rs +++ b/runtime/near-vm-errors/src/lib.rs @@ -1,23 +1,34 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use near_rpc_error_macro::RpcError; use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[derive( + Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, +)] +#[rpc_error_variant = "FunctionCall"] pub enum VMError { FunctionExecError(FunctionExecError), + // TODO: serialize/deserialize? StorageError(Vec), } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[derive( + Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, +)] +#[rpc_error_variant = "FunctionExecError"] pub enum FunctionExecError { CompilationError(CompilationError), - LinkError(String), + LinkError { msg: String }, ResolveError(MethodResolveError), - WasmTrap(String), + WasmTrap { msg: String }, HostError(HostError), } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[derive( + Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, +)] +#[rpc_error_variant = "ResolveError"] pub enum MethodResolveError { MethodEmptyName, MethodUTF8Error, @@ -25,14 +36,20 @@ pub enum MethodResolveError { MethodInvalidSignature, } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[derive( + Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, +)] +#[rpc_error_variant = "CompilationError"] pub enum CompilationError { - CodeDoesNotExist(String), + CodeDoesNotExist { account_id: String }, PrepareError(PrepareError), - WasmerCompileError(String), + WasmerCompileError { msg: String }, } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[derive( + Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, +)] +#[rpc_error_variant = "PrepareError"] /// Error that can occur while preparing or executing Wasm smart-contract. pub enum PrepareError { /// Error happened while serializing the module. @@ -64,7 +81,10 @@ pub enum PrepareError { Memory, } -#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] +#[derive( + Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, +)] +#[rpc_error_variant = "HostError"] pub enum HostError { BadUTF16, BadUTF8, @@ -72,21 +92,21 @@ pub enum HostError { GasLimitExceeded, BalanceExceeded, EmptyMethodName, - GuestPanic(String), + GuestPanic { panic_msg: String }, IntegerOverflow, - InvalidPromiseIndex(u64), + InvalidPromiseIndex { promise_idx: u64 }, CannotAppendActionToJointPromise, CannotReturnJointPromise, - InvalidPromiseResultIndex(u64), - InvalidRegisterId(u64), - IteratorWasInvalidated(u64), + InvalidPromiseResultIndex { result_idx: u64 }, + InvalidRegisterId { register_id: u64 }, + IteratorWasInvalidated { iterator_index: u64 }, MemoryAccessViolation, - InvalidReceiptIndex(u64), - InvalidIteratorIndex(u64), + InvalidReceiptIndex { receipt_index: u64 }, + InvalidIteratorIndex { iterator_index: u64 }, InvalidAccountId, InvalidMethodName, InvalidPublicKey, - ProhibitedInView(String), + ProhibitedInView { method_name: String }, } #[derive(Debug, Clone, PartialEq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)] @@ -133,8 +153,8 @@ impl fmt::Display for FunctionExecError { FunctionExecError::CompilationError(e) => e.fmt(f), FunctionExecError::ResolveError(e) => e.fmt(f), FunctionExecError::HostError(e) => e.fmt(f), - FunctionExecError::LinkError(s) => write!(f, "{}", s), - FunctionExecError::WasmTrap(s) => write!(f, "WebAssembly trap: {}", s), + FunctionExecError::LinkError { msg } => write!(f, "{}", msg), + FunctionExecError::WasmTrap { msg } => write!(f, "WebAssembly trap: {}", msg), } } } @@ -142,11 +162,13 @@ impl fmt::Display for FunctionExecError { impl fmt::Display for CompilationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { - CompilationError::CodeDoesNotExist(account_id) => { + CompilationError::CodeDoesNotExist { account_id } => { write!(f, "cannot find contract code for account {}", account_id) } CompilationError::PrepareError(p) => write!(f, "PrepareError: {}", p), - CompilationError::WasmerCompileError(s) => write!(f, "Wasmer compilation error: {}", s), + CompilationError::WasmerCompileError { msg } => { + write!(f, "Wasmer compilation error: {}", msg) + } } } } @@ -176,21 +198,21 @@ impl std::fmt::Display for HostError { GasLimitExceeded => write!(f, "Exceeded the maximum amount of gas allowed to burn per contract."), BalanceExceeded => write!(f, "Exceeded the account balance."), EmptyMethodName => write!(f, "Tried to call an empty method name."), - GuestPanic(s) => write!(f, "Smart contract panicked: {}", s), + GuestPanic{ panic_msg } => write!(f, "Smart contract panicked: {}", panic_msg), IntegerOverflow => write!(f, "Integer overflow."), - InvalidIteratorIndex(index) => write!(f, "Iterator index {:?} does not exist", index), - InvalidPromiseIndex(index) => write!(f, "{:?} does not correspond to existing promises", index), + InvalidIteratorIndex{iterator_index} => write!(f, "Iterator index {:?} does not exist", iterator_index), + InvalidPromiseIndex{promise_idx} => write!(f, "{:?} does not correspond to existing promises", promise_idx), CannotAppendActionToJointPromise => write!(f, "Actions can only be appended to non-joint promise."), CannotReturnJointPromise => write!(f, "Returning joint promise is currently prohibited."), - InvalidPromiseResultIndex(index) => write!(f, "Accessed invalid promise result index: {:?}", index), - InvalidRegisterId(id) => write!(f, "Accessed invalid register id: {:?}", id), - IteratorWasInvalidated(index) => write!(f, "Iterator {:?} was invalidated after its creation by performing a mutable operation on trie", index), + InvalidPromiseResultIndex{result_idx} => write!(f, "Accessed invalid promise result index: {:?}", result_idx), + InvalidRegisterId{register_id} => write!(f, "Accessed invalid register id: {:?}", register_id), + IteratorWasInvalidated{iterator_index} => write!(f, "Iterator {:?} was invalidated after its creation by performing a mutable operation on trie", iterator_index), MemoryAccessViolation => write!(f, "Accessed memory outside the bounds."), - InvalidReceiptIndex(index) => write!(f, "VM Logic returned an invalid receipt index: {:?}", index), + InvalidReceiptIndex{receipt_index} => write!(f, "VM Logic returned an invalid receipt index: {:?}", receipt_index), InvalidAccountId => write!(f, "VM Logic returned an invalid account id"), InvalidMethodName => write!(f, "VM Logic returned an invalid method name"), InvalidPublicKey => write!(f, "VM Logic provided an invalid public key"), - ProhibitedInView(method_name) => write!(f, "{} is not allowed in view calls", method_name), + ProhibitedInView{method_name} => write!(f, "{} is not allowed in view calls", method_name), } } } diff --git a/runtime/near-vm-logic/src/logic.rs b/runtime/near-vm-logic/src/logic.rs index eef5ddb2abe..12dcb99af90 100644 --- a/runtime/near-vm-logic/src/logic.rs +++ b/runtime/near-vm-logic/src/logic.rs @@ -208,7 +208,7 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_per_byte(read_register_byte, data.len() as _)?; Ok(data.clone()) } else { - Err(HostError::InvalidRegisterId(register_id).into()) + Err(HostError::InvalidRegisterId { register_id }.into()) } } @@ -429,7 +429,10 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("signer_account_id".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "signer_account_id".to_string(), + } + .into()); } self.internal_write_register( register_id, @@ -453,7 +456,10 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("signer_account_pk".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "signer_account_pk".to_string(), + } + .into()); } self.internal_write_register(register_id, self.context.signer_account_pk.clone()) } @@ -474,7 +480,10 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("predecessor_account_id".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "predecessor_account_id".to_string(), + } + .into()); } self.internal_write_register( register_id, @@ -569,7 +578,10 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("attached_deposit".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "attached_deposit".to_string(), + } + .into()); } self.memory_set_u128(balance_ptr, self.context.attached_deposit) } @@ -586,7 +598,9 @@ impl<'a> VMLogic<'a> { pub fn prepaid_gas(&mut self) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("prepaid_gas".to_string()).into()); + return Err( + HostError::ProhibitedInView { method_name: "prepaid_gas".to_string() }.into() + ); } Ok(self.context.prepaid_gas) } @@ -603,7 +617,7 @@ impl<'a> VMLogic<'a> { pub fn used_gas(&mut self) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("used_gas".to_string()).into()); + return Err(HostError::ProhibitedInView { method_name: "used_gas".to_string() }.into()); } Ok(self.gas_counter.used_gas()) } @@ -814,7 +828,9 @@ impl<'a> VMLogic<'a> { ) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("promise_and".to_string()).into()); + return Err( + HostError::ProhibitedInView { method_name: "promise_and".to_string() }.into() + ); } self.gas_counter.pay_base(promise_and_base)?; self.gas_counter.pay_per_byte( @@ -831,7 +847,7 @@ impl<'a> VMLogic<'a> { let promise = self .promises .get(*promise_idx as usize) - .ok_or(HostError::InvalidPromiseIndex(*promise_idx))?; + .ok_or(HostError::InvalidPromiseIndex { promise_idx: *promise_idx })?; match &promise.promise_to_receipt { PromiseToReceipts::Receipt(receipt_idx) => { receipt_dependencies.push(*receipt_idx); @@ -872,7 +888,10 @@ impl<'a> VMLogic<'a> { ) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("promise_batch_create".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_create".to_string(), + } + .into()); } let account_id = self.read_and_parse_account_id(account_id_ptr, account_id_len)?; let sir = account_id == self.context.current_account_id; @@ -913,14 +932,17 @@ impl<'a> VMLogic<'a> { ) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("promise_batch_then".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_then".to_string(), + } + .into()); } let account_id = self.read_and_parse_account_id(account_id_ptr, account_id_len)?; // Update the DAG and return new promise idx. let promise = self .promises .get(promise_idx as usize) - .ok_or(HostError::InvalidPromiseIndex(promise_idx))?; + .ok_or(HostError::InvalidPromiseIndex { promise_idx })?; let receipt_dependencies = match &promise.promise_to_receipt { PromiseToReceipts::Receipt(receipt_idx) => vec![*receipt_idx], PromiseToReceipts::NotReceipt(receipt_indices) => receipt_indices.clone(), @@ -956,7 +978,7 @@ impl<'a> VMLogic<'a> { let promise = self .promises .get(promise_idx as usize) - .ok_or(HostError::InvalidPromiseIndex(promise_idx))?; + .ok_or(HostError::InvalidPromiseIndex { promise_idx })?; let receipt_idx = match &promise.promise_to_receipt { PromiseToReceipts::Receipt(receipt_idx) => Ok(*receipt_idx), PromiseToReceipts::NotReceipt(_) => Err(HostError::CannotAppendActionToJointPromise), @@ -987,9 +1009,9 @@ impl<'a> VMLogic<'a> { pub fn promise_batch_action_create_account(&mut self, promise_idx: u64) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView( - "promise_batch_action_create_account".to_string(), - ) + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_create_account".to_string(), + } .into()); } let (receipt_idx, sir) = self.promise_idx_to_receipt_idx_with_sir(promise_idx)?; @@ -1025,9 +1047,9 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView( - "promise_batch_action_deploy_contract".to_string(), - ) + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_deploy_contract".to_string(), + } .into()); } let code = self.get_vec_from_memory_or_register(code_ptr, code_len)?; @@ -1077,9 +1099,9 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView( - "promise_batch_action_function_call".to_string(), - ) + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_function_call".to_string(), + } .into()); } let amount = self.memory_get_u128(amount_ptr)?; @@ -1131,9 +1153,10 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err( - HostError::ProhibitedInView("promise_batch_action_transfer".to_string()).into() - ); + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_transfer".to_string(), + } + .into()); } let amount = self.memory_get_u128(amount_ptr)?; @@ -1174,9 +1197,10 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err( - HostError::ProhibitedInView("promise_batch_action_stake".to_string()).into() - ); + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_stake".to_string(), + } + .into()); } let amount = self.memory_get_u128(amount_ptr)?; let public_key = self.get_vec_from_memory_or_register(public_key_ptr, public_key_len)?; @@ -1218,9 +1242,9 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView( - "promise_batch_action_add_key_with_full_access".to_string(), - ) + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_add_key_with_full_access".to_string(), + } .into()); } let public_key = self.get_vec_from_memory_or_register(public_key_ptr, public_key_len)?; @@ -1269,9 +1293,9 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView( - "promise_batch_action_add_key_with_function_call".to_string(), - ) + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_add_key_with_function_call".to_string(), + } .into()); } let public_key = self.get_vec_from_memory_or_register(public_key_ptr, public_key_len)?; @@ -1343,9 +1367,10 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err( - HostError::ProhibitedInView("promise_batch_action_delete_key".to_string()).into() - ); + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_delete_key".to_string(), + } + .into()); } let public_key = self.get_vec_from_memory_or_register(public_key_ptr, public_key_len)?; @@ -1382,9 +1407,9 @@ impl<'a> VMLogic<'a> { ) -> Result<()> { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView( - "promise_batch_action_delete_account".to_string(), - ) + return Err(HostError::ProhibitedInView { + method_name: "promise_batch_action_delete_account".to_string(), + } .into()); } let beneficiary_id = @@ -1416,7 +1441,10 @@ impl<'a> VMLogic<'a> { pub fn promise_results_count(&mut self) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("promise_results_count".to_string()).into()); + return Err(HostError::ProhibitedInView { + method_name: "promise_results_count".to_string(), + } + .into()); } Ok(self.promise_results.len() as _) } @@ -1446,12 +1474,14 @@ impl<'a> VMLogic<'a> { pub fn promise_result(&mut self, result_idx: u64, register_id: u64) -> Result { self.gas_counter.pay_base(base)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("promise_result".to_string()).into()); + return Err( + HostError::ProhibitedInView { method_name: "promise_result".to_string() }.into() + ); } match self .promise_results .get(result_idx as usize) - .ok_or(HostError::InvalidPromiseResultIndex(result_idx))? + .ok_or(HostError::InvalidPromiseResultIndex { result_idx })? { PromiseResult::NotReady => Ok(0), PromiseResult::Successful(data) => { @@ -1477,12 +1507,14 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_base(base)?; self.gas_counter.pay_base(promise_return)?; if self.context.is_view { - return Err(HostError::ProhibitedInView("promise_return".to_string()).into()); + return Err( + HostError::ProhibitedInView { method_name: "promise_return".to_string() }.into() + ); } match self .promises .get(promise_idx as usize) - .ok_or(HostError::InvalidPromiseIndex(promise_idx))? + .ok_or(HostError::InvalidPromiseIndex { promise_idx })? .promise_to_receipt { PromiseToReceipts::Receipt(receipt_idx) => { @@ -1545,7 +1577,7 @@ impl<'a> VMLogic<'a> { /// `base` pub fn panic(&mut self) -> Result<()> { self.gas_counter.pay_base(base)?; - Err(HostError::GuestPanic("explicit guest panic".to_string()).into()) + Err(HostError::GuestPanic { panic_msg: "explicit guest panic".to_string() }.into()) } /// Guest panics with the UTF-8 encoded string. @@ -1561,7 +1593,7 @@ impl<'a> VMLogic<'a> { /// `base + cost of reading and decoding a utf8 string` pub fn panic_utf8(&mut self, len: u64, ptr: u64) -> Result<()> { self.gas_counter.pay_base(base)?; - Err(HostError::GuestPanic(self.get_utf8_string(len, ptr)?).into()) + Err(HostError::GuestPanic { panic_msg: self.get_utf8_string(len, ptr)? }.into()) } /// Logs the UTF-8 encoded string. @@ -1631,7 +1663,7 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_per_byte(log_byte, message.as_bytes().len() as u64)?; self.logs.push(format!("ABORT: {}", message)); - Err(HostError::GuestPanic(message).into()) + Err(HostError::GuestPanic { panic_msg: message }.into()) } // ############### @@ -1945,9 +1977,9 @@ impl<'a> VMLogic<'a> { self.gas_counter.pay_base(base)?; self.gas_counter.pay_base(storage_iter_next_base)?; if self.invalid_iterators.contains(&iterator_id) { - return Err(HostError::IteratorWasInvalidated(iterator_id).into()); + return Err(HostError::IteratorWasInvalidated { iterator_index: iterator_id }.into()); } else if !self.valid_iterators.contains(&iterator_id) { - return Err(HostError::InvalidIteratorIndex(iterator_id).into()); + return Err(HostError::InvalidIteratorIndex { iterator_index: iterator_id }.into()); } let nodes_before = self.ext.get_touched_nodes_count(); diff --git a/runtime/near-vm-logic/src/mocks/mock_external.rs b/runtime/near-vm-logic/src/mocks/mock_external.rs index 60ccbc9c367..6df3a098c21 100644 --- a/runtime/near-vm-logic/src/mocks/mock_external.rs +++ b/runtime/near-vm-logic/src/mocks/mock_external.rs @@ -123,13 +123,13 @@ impl External for MockedExternal { } None => Ok(None), }, - None => Err(HostError::InvalidIteratorIndex(iterator_idx).into()), + None => Err(HostError::InvalidIteratorIndex { iterator_index: iterator_idx }.into()), } } fn storage_iter_drop(&mut self, iterator_idx: u64) -> Result<()> { if self.iterators.remove(&iterator_idx).is_none() { - Err(HostError::InvalidIteratorIndex(iterator_idx).into()) + Err(HostError::InvalidIteratorIndex { iterator_index: iterator_idx }.into()) } else { Ok(()) } @@ -137,7 +137,7 @@ impl External for MockedExternal { fn create_receipt(&mut self, receipt_indices: Vec, receiver_id: String) -> Result { if let Some(index) = receipt_indices.iter().find(|&&el| el >= self.receipts.len() as u64) { - return Err(HostError::InvalidReceiptIndex(*index).into()); + return Err(HostError::InvalidReceiptIndex { receipt_index: *index }.into()); } let res = self.receipts.len() as u64; self.receipts.push(Receipt { receipt_indices, receiver_id, actions: vec![] }); diff --git a/runtime/near-vm-runner/src/errors.rs b/runtime/near-vm-runner/src/errors.rs index c189711f388..7df8b8669cb 100644 --- a/runtime/near-vm-runner/src/errors.rs +++ b/runtime/near-vm-runner/src/errors.rs @@ -10,9 +10,9 @@ impl IntoVMError for wasmer_runtime::error::Error { use wasmer_runtime::error::Error; match self { Error::CompileError(err) => err.into_vm_error(), - Error::LinkError(err) => VMError::FunctionExecError(FunctionExecError::LinkError( - format!("{:.500}", Error::LinkError(err).to_string()), - )), + Error::LinkError(err) => VMError::FunctionExecError(FunctionExecError::LinkError { + msg: format!("{:.500}", Error::LinkError(err).to_string()), + }), Error::RuntimeError(err) => err.into_vm_error(), Error::ResolveError(err) => err.into_vm_error(), Error::CallError(err) => err.into_vm_error(), @@ -34,7 +34,7 @@ impl IntoVMError for wasmer_runtime::error::CallError { impl IntoVMError for wasmer_runtime::error::CompileError { fn into_vm_error(self) -> VMError { VMError::FunctionExecError(FunctionExecError::CompilationError( - CompilationError::WasmerCompileError(self.to_string()), + CompilationError::WasmerCompileError { msg: self.to_string() }, )) } } @@ -61,7 +61,7 @@ impl IntoVMError for wasmer_runtime::error::RuntimeError { use wasmer_runtime::error::RuntimeError; match &self { RuntimeError::Trap { msg } => { - VMError::FunctionExecError(FunctionExecError::WasmTrap(msg.to_string())) + VMError::FunctionExecError(FunctionExecError::WasmTrap { msg: msg.to_string() }) } RuntimeError::Error { data } => { if let Some(err) = data.downcast_ref::() { @@ -79,7 +79,9 @@ impl IntoVMError for wasmer_runtime::error::RuntimeError { data.type_id(), self.to_string() ); - VMError::FunctionExecError(FunctionExecError::WasmTrap("unknown".to_string())) + VMError::FunctionExecError(FunctionExecError::WasmTrap { + msg: "unknown".to_string(), + }) } } } diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index ded59b611f2..e81cbbfcf1e 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -120,7 +120,7 @@ pub(crate) fn action_function_call( Ok(Some(code)) => code, Ok(None) => { let error = VMError::FunctionExecError(FunctionExecError::CompilationError( - CompilationError::CodeDoesNotExist(account_id.clone()), + CompilationError::CodeDoesNotExist { account_id: account_id.clone() }, )); result.result = Err(ActionErrorKind::FunctionCall(error).into()); return Ok(()); diff --git a/runtime/runtime/src/ext.rs b/runtime/runtime/src/ext.rs index d5a130d8bad..f5ce3a91b8f 100644 --- a/runtime/runtime/src/ext.rs +++ b/runtime/runtime/src/ext.rs @@ -166,7 +166,9 @@ impl<'a> External for RuntimeExt<'a> { ) -> ExtResult, Box)>> { let result = match self.iters.get_mut(&iterator_idx) { Some(iter) => iter.next(), - None => return Err(HostError::InvalidIteratorIndex(iterator_idx).into()), + None => { + return Err(HostError::InvalidIteratorIndex { iterator_index: iterator_idx }.into()) + } }; match result { None => { @@ -199,7 +201,7 @@ impl<'a> External for RuntimeExt<'a> { .get_mut(receipt_index as usize) .ok_or_else(|| { HostErrorOrStorageError::HostError( - HostError::InvalidReceiptIndex(receipt_index).into(), + HostError::InvalidReceiptIndex { receipt_index }.into(), ) })? .1 diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index b92efe5d64e..3f92215600e 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -30,17 +30,23 @@ struct Schema { impl Drop for Schema { fn drop(&mut self) { - // std::env::var("CARGO_TARGET_DIR") doesn't work for some reason + // std::env::var("CARGO_TARGET_DIR") doesn't exists let filename = "./target/errors_schema.json"; let json_value = serde_json::to_value(self).expect("Schema serialize failed"); if let Ok(data) = std::fs::read(filename) { if let Ok(mut existing_schema) = serde_json::from_slice::(&data) { merge(&mut existing_schema, &json_value); + let json = serde_json::to_string_pretty(&existing_schema) + .expect("error schema serialization failed"); + println!("{}", &existing_schema); + std::fs::write(filename, json).expect("Unable to save the errors schema file"); }; + } else { + let json = serde_json::to_string_pretty(&json_value) + .expect("error schema serialization failed"); + println!("{}", &json); + std::fs::write(filename, json).expect("Unable to save the errors schema file"); }; - let json = - serde_json::to_string_pretty(&json_value).expect("error schema serialization failed"); - std::fs::write(filename, json).expect("Unable to save the errors schema file"); } } From 08f601fd96e7a259e91dde241fc77c85219ef57f Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 3 Jan 2020 22:21:03 +0300 Subject: [PATCH 19/48] expose errors schema --- build_errors_schema.sh | 2 + res/errors_schema.json | 543 ++ tools/rpctypegen/Cargo.toml | 2 +- tools/rpctypegen/err.txt | 11902 ---------------------------------- tools/rpctypegen/src/lib.rs | 32 +- 5 files changed, 562 insertions(+), 11919 deletions(-) create mode 100644 build_errors_schema.sh create mode 100644 res/errors_schema.json delete mode 100644 tools/rpctypegen/err.txt diff --git a/build_errors_schema.sh b/build_errors_schema.sh new file mode 100644 index 00000000000..8710ccd9d90 --- /dev/null +++ b/build_errors_schema.sh @@ -0,0 +1,2 @@ +cargo clean && cargo build --manifest-path near/Cargo.toml +cp target/errors_schema.json res/errors_schema.json diff --git a/res/errors_schema.json b/res/errors_schema.json new file mode 100644 index 00000000000..429361b8132 --- /dev/null +++ b/res/errors_schema.json @@ -0,0 +1,543 @@ +{ + "schema": { + "GasLimitExceeded": { + "name": "GasLimitExceeded", + "subtypes": [], + "props": {} + }, + "MethodEmptyName": { + "name": "MethodEmptyName", + "subtypes": [], + "props": {} + }, + "WasmerCompileError": { + "name": "WasmerCompileError", + "subtypes": [], + "props": { + "msg": "" + } + }, + "GuestPanic": { + "name": "GuestPanic", + "subtypes": [], + "props": { + "panic_msg": "" + } + }, + "Memory": { + "name": "Memory", + "subtypes": [], + "props": {} + }, + "GasExceeded": { + "name": "GasExceeded", + "subtypes": [], + "props": {} + }, + "MethodUTF8Error": { + "name": "MethodUTF8Error", + "subtypes": [], + "props": {} + }, + "FunctionCall": { + "name": "FunctionCall", + "subtypes": [ + "FunctionExecError", + "StorageError" + ], + "props": {} + }, + "BadUTF16": { + "name": "BadUTF16", + "subtypes": [], + "props": {} + }, + "WasmTrap": { + "name": "WasmTrap", + "subtypes": [], + "props": { + "msg": "" + } + }, + "GasInstrumentation": { + "name": "GasInstrumentation", + "subtypes": [], + "props": {} + }, + "HostError": { + "name": "HostError", + "subtypes": [ + "BadUTF16", + "BadUTF8", + "GasExceeded", + "GasLimitExceeded", + "BalanceExceeded", + "EmptyMethodName", + "GuestPanic", + "IntegerOverflow", + "InvalidPromiseIndex", + "CannotAppendActionToJointPromise", + "CannotReturnJointPromise", + "InvalidPromiseResultIndex", + "InvalidRegisterId", + "IteratorWasInvalidated", + "MemoryAccessViolation", + "InvalidReceiptIndex", + "InvalidIteratorIndex", + "InvalidAccountId", + "InvalidMethodName", + "InvalidPublicKey", + "ProhibitedInView" + ], + "props": {} + }, + "InvalidPromiseIndex": { + "name": "InvalidPromiseIndex", + "subtypes": [], + "props": { + "promise_idx": "" + } + }, + "InvalidPromiseResultIndex": { + "name": "InvalidPromiseResultIndex", + "subtypes": [], + "props": { + "result_idx": "" + } + }, + "Deserialization": { + "name": "Deserialization", + "subtypes": [], + "props": {} + }, + "MethodNotFound": { + "name": "MethodNotFound", + "subtypes": [], + "props": {} + }, + "InvalidRegisterId": { + "name": "InvalidRegisterId", + "subtypes": [], + "props": { + "register_id": "" + } + }, + "InvalidReceiptIndex": { + "name": "InvalidReceiptIndex", + "subtypes": [], + "props": { + "receipt_index": "" + } + }, + "EmptyMethodName": { + "name": "EmptyMethodName", + "subtypes": [], + "props": {} + }, + "CannotReturnJointPromise": { + "name": "CannotReturnJointPromise", + "subtypes": [], + "props": {} + }, + "StackHeightInstrumentation": { + "name": "StackHeightInstrumentation", + "subtypes": [], + "props": {} + }, + "PrepareError": { + "name": "PrepareError", + "subtypes": [ + "Serialization", + "Deserialization", + "InternalMemoryDeclared", + "GasInstrumentation", + "StackHeightInstrumentation", + "Instantiate", + "Memory" + ], + "props": {} + }, + "CodeDoesNotExist": { + "name": "CodeDoesNotExist", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "MethodInvalidSignature": { + "name": "MethodInvalidSignature", + "subtypes": [], + "props": {} + }, + "CompilationError": { + "name": "CompilationError", + "subtypes": [ + "CodeDoesNotExist", + "PrepareError", + "WasmerCompileError" + ], + "props": {} + }, + "IntegerOverflow": { + "name": "IntegerOverflow", + "subtypes": [], + "props": {} + }, + "MemoryAccessViolation": { + "name": "MemoryAccessViolation", + "subtypes": [], + "props": {} + }, + "InvalidIteratorIndex": { + "name": "InvalidIteratorIndex", + "subtypes": [], + "props": { + "iterator_index": "" + } + }, + "IteratorWasInvalidated": { + "name": "IteratorWasInvalidated", + "subtypes": [], + "props": { + "iterator_index": "" + } + }, + "InvalidAccountId": { + "name": "InvalidAccountId", + "subtypes": [], + "props": {} + }, + "Serialization": { + "name": "Serialization", + "subtypes": [], + "props": {} + }, + "CannotAppendActionToJointPromise": { + "name": "CannotAppendActionToJointPromise", + "subtypes": [], + "props": {} + }, + "InternalMemoryDeclared": { + "name": "InternalMemoryDeclared", + "subtypes": [], + "props": {} + }, + "Instantiate": { + "name": "Instantiate", + "subtypes": [], + "props": {} + }, + "ProhibitedInView": { + "name": "ProhibitedInView", + "subtypes": [], + "props": { + "method_name": "" + } + }, + "FunctionExecError": { + "name": "FunctionExecError", + "subtypes": [ + "CompilationError", + "LinkError", + "ResolveError", + "WasmTrap", + "HostError" + ], + "props": {} + }, + "InvalidMethodName": { + "name": "InvalidMethodName", + "subtypes": [], + "props": {} + }, + "ResolveError": { + "name": "ResolveError", + "subtypes": [ + "MethodEmptyName", + "MethodUTF8Error", + "MethodNotFound", + "MethodInvalidSignature" + ], + "props": {} + }, + "BadUTF8": { + "name": "BadUTF8", + "subtypes": [], + "props": {} + }, + "BalanceExceeded": { + "name": "BalanceExceeded", + "subtypes": [], + "props": {} + }, + "LinkError": { + "name": "LinkError", + "subtypes": [], + "props": { + "msg": "" + } + }, + "InvalidPublicKey": { + "name": "InvalidPublicKey", + "subtypes": [], + "props": {} + }, + "InvalidTx": { + "name": "InvalidTx", + "subtypes": [ + "InvalidAccessKey", + "InvalidSigner", + "SignerDoesNotExist", + "InvalidNonce", + "InvalidReceiver", + "InvalidSignature", + "NotEnoughBalance", + "RentUnpaid", + "CostOverflow", + "InvalidChain", + "Expired" + ], + "props": {} + }, + "ActorNoPermission": { + "name": "ActorNoPermission", + "subtypes": [], + "props": { + "actor_id": "", + "account_id": "" + } + }, + "RentUnpaid": { + "name": "RentUnpaid", + "subtypes": [], + "props": { + "account_id": "", + "amount": "" + } + }, + "ReceiverMismatch": { + "name": "ReceiverMismatch", + "subtypes": [], + "props": { + "ak_receiver": "", + "tx_receiver": "" + } + }, + "TxExecutionError": { + "name": "TxExecutionError", + "subtypes": [ + "Action", + "InvalidTx" + ], + "props": {} + }, + "CostOverflow": { + "name": "CostOverflow", + "subtypes": [], + "props": {} + }, + "InvalidSignature": { + "name": "InvalidSignature", + "subtypes": [], + "props": {} + }, + "Action": { + "name": "Action", + "subtypes": [ + "AccountAlreadyExists", + "AccountDoesNotExist", + "CreateAccountNotAllowed", + "ActorNoPermission", + "DeleteKeyDoesNotExist", + "AddKeyAlreadyExists", + "DeleteAccountStaking", + "DeleteAccountHasRent", + "RentUnpaid", + "TriesToUnstake", + "TriesToStake", + "FunctionCall" + ], + "props": { + "index": "" + } + }, + "AccessKeyNotFound": { + "name": "AccessKeyNotFound", + "subtypes": [], + "props": { + "account_id": "", + "public_key": "" + } + }, + "NotEnoughBalance": { + "name": "NotEnoughBalance", + "subtypes": [], + "props": { + "balance": "", + "cost": "", + "signer_id": "" + } + }, + "NotEnoughAllowance": { + "name": "NotEnoughAllowance", + "subtypes": [], + "props": { + "account_id": "", + "allowance": "", + "cost": "", + "public_key": "" + } + }, + "Expired": { + "name": "Expired", + "subtypes": [], + "props": {} + }, + "DeleteAccountStaking": { + "name": "DeleteAccountStaking", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "SignerDoesNotExist": { + "name": "SignerDoesNotExist", + "subtypes": [], + "props": { + "signer_id": "" + } + }, + "TriesToStake": { + "name": "TriesToStake", + "subtypes": [], + "props": { + "stake": "", + "locked": "", + "account_id": "", + "balance": "" + } + }, + "AddKeyAlreadyExists": { + "name": "AddKeyAlreadyExists", + "subtypes": [], + "props": { + "account_id": "", + "public_key": "" + } + }, + "InvalidSigner": { + "name": "InvalidSigner", + "subtypes": [], + "props": { + "signer_id": "" + } + }, + "CreateAccountNotAllowed": { + "name": "CreateAccountNotAllowed", + "subtypes": [], + "props": { + "account_id": "", + "predecessor_id": "" + } + }, + "ActionError": { + "name": "ActionError", + "subtypes": [], + "props": {} + }, + "InvalidAccessKey": { + "name": "InvalidAccessKey", + "subtypes": [ + "AccessKeyNotFound", + "ReceiverMismatch", + "MethodNameMismatch", + "ActionError", + "NotEnoughAllowance" + ], + "props": {} + }, + "TriesToUnstake": { + "name": "TriesToUnstake", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "InvalidNonce": { + "name": "InvalidNonce", + "subtypes": [], + "props": { + "ak_nonce": "", + "tx_nonce": "" + } + }, + "AccountAlreadyExists": { + "name": "AccountAlreadyExists", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "InvalidChain": { + "name": "InvalidChain", + "subtypes": [], + "props": {} + }, + "AccountDoesNotExist": { + "name": "AccountDoesNotExist", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "MethodNameMismatch": { + "name": "MethodNameMismatch", + "subtypes": [], + "props": { + "method_name": "" + } + }, + "DeleteAccountHasRent": { + "name": "DeleteAccountHasRent", + "subtypes": [], + "props": { + "account_id": "", + "balance": "" + } + }, + "InvalidReceiver": { + "name": "InvalidReceiver", + "subtypes": [], + "props": { + "receiver_id": "" + } + }, + "DeleteKeyDoesNotExist": { + "name": "DeleteKeyDoesNotExist", + "subtypes": [], + "props": { + "account_id": "", + "public_key": "" + } + }, + "Timeout": { + "name": "Timeout", + "subtypes": [], + "props": {} + }, + "Closed": { + "name": "Closed", + "subtypes": [], + "props": {} + }, + "ServerError": { + "name": "ServerError", + "subtypes": [ + "TxExecutionError", + "Timeout", + "Closed" + ], + "props": {} + } + } +} diff --git a/tools/rpctypegen/Cargo.toml b/tools/rpctypegen/Cargo.toml index 308fbc6d9c1..70cd2cdca31 100644 --- a/tools/rpctypegen/Cargo.toml +++ b/tools/rpctypegen/Cargo.toml @@ -9,7 +9,7 @@ proc-macro = true [dependencies] serde = "1.0" -serde_json = "1.0" +serde_json = {version = "1.0", features = ["preserve_order"]} syn = { version = "1.0", features = ["full", "extra-traits"]} quote = "1.0" proc-macro2 = "1.0" diff --git a/tools/rpctypegen/err.txt b/tools/rpctypegen/err.txt deleted file mode 100644 index acf2173230f..00000000000 --- a/tools/rpctypegen/err.txt +++ /dev/null @@ -1,11902 +0,0 @@ -File { - shebang: None, - attrs: [], - items: [ - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - crate, - ), - colon2_token: Colon2, - tree: Path( - UsePath { - ident: Ident( - serialize, - ), - colon2_token: Colon2, - tree: Name( - UseName { - ident: Ident( - u128_dec_format, - ), - }, - ), - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - crate, - ), - colon2_token: Colon2, - tree: Path( - UsePath { - ident: Ident( - types, - ), - colon2_token: Colon2, - tree: Group( - UseGroup { - brace_token: Brace, - items: [ - Name( - UseName { - ident: Ident( - AccountId, - ), - }, - ), - Comma, - Name( - UseName { - ident: Ident( - Balance, - ), - }, - ), - Comma, - Name( - UseName { - ident: Ident( - Nonce, - ), - }, - ), - ], - }, - ), - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - borsh, - ), - colon2_token: Colon2, - tree: Group( - UseGroup { - brace_token: Brace, - items: [ - Name( - UseName { - ident: Ident( - BorshDeserialize, - ), - }, - ), - Comma, - Name( - UseName { - ident: Ident( - BorshSerialize, - ), - }, - ), - ], - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - near_crypto, - ), - colon2_token: Colon2, - tree: Name( - UseName { - ident: Ident( - PublicKey, - ), - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - serde, - ), - colon2_token: Colon2, - tree: Group( - UseGroup { - brace_token: Brace, - items: [ - Name( - UseName { - ident: Ident( - Deserialize, - ), - }, - ), - Comma, - Name( - UseName { - ident: Ident( - Serialize, - ), - }, - ), - ], - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - std, - ), - colon2_token: Colon2, - tree: Path( - UsePath { - ident: Ident( - fmt, - ), - colon2_token: Colon2, - tree: Name( - UseName { - ident: Ident( - Display, - ), - }, - ), - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Use( - ItemUse { - attrs: [], - vis: Inherited, - use_token: Use, - leading_colon: None, - tree: Path( - UsePath { - ident: Ident( - near_vm_errors, - ), - colon2_token: Colon2, - tree: Name( - UseName { - ident: Ident( - VMError, - ), - }, - ), - }, - ), - semi_token: Semi, - }, - ), - Enum( - ItemEnum { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Internal", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - enum_token: Enum, - ident: Ident( - StorageError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - brace_token: Brace, - variants: [ - Variant { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Key-value db internal failure", - }, - ], - }, - ], - ident: Ident( - StorageInternalError, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Storage is PartialStorage and requested a missing trie node", - }, - ], - }, - ], - ident: Ident( - TrieNodeMissing, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Either invalid state or key-value db is corrupted.", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " For PartialStorage it cannot be corrupted.", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Error message is unreliable and for debugging purposes only. It's also probably ok to", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " panic in every place that produces this error.", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " We can check if db is corrupted by verifying everything in the state trie.", - }, - ], - }, - ], - ident: Ident( - StorageInconsistentState, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - String, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - StorageError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - MethodCall( - ExprMethodCall { - attrs: [], - receiver: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - f, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - method: Ident( - write_str, - ), - turbofish: None, - paren_token: Paren, - args: [ - Reference( - ExprReference { - attrs: [], - and_token: And, - raw: Reserved { - private: (), - }, - mutability: None, - expr: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - format, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Literal { - lit: "{:?}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - ], - }, - }, - ), - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - error, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - StorageError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [], - }, - ), - Enum( - ItemEnum { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " External", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - enum_token: Enum, - ident: Ident( - InvalidTxError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - brace_token: Brace, - variants: [ - Variant { - attrs: [], - ident: Ident( - InvalidAccessKey, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidSigner, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - signer_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - SignerDoesNotExist, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - signer_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidNonce, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - tx_nonce, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Nonce, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - ak_nonce, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Nonce, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidReceiver, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - receiver_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidSignature, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - NotEnoughBalance, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - signer_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - cost, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - RentUnpaid, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - signer_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - amount, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - CostOverflow, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidChain, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - Expired, - ), - fields: Unit, - discriminant: None, - }, - Comma, - ], - }, - ), - Enum( - ItemEnum { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - enum_token: Enum, - ident: Ident( - InvalidAccessKeyError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - brace_token: Brace, - variants: [ - Variant { - attrs: [], - ident: Ident( - AccessKeyNotFound, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - public_key, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - PublicKey, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - ReceiverMismatch, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - tx_receiver, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - ak_receiver, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - MethodNameMismatch, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - method_name, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - String, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - ActionError, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - NotEnoughAllowance, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - public_key, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - PublicKey, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - allowance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - cost, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - ], - }, - ), - Struct( - ItemStruct { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - struct_token: Struct, - ident: Ident( - ActionError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - index, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Option, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - u64, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - kind, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - semi_token: None, - }, - ), - Enum( - ItemEnum { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - enum_token: Enum, - ident: Ident( - ActionErrorKind, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - brace_token: Brace, - variants: [ - Variant { - attrs: [], - ident: Ident( - AccountAlreadyExists, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - AccountDoesNotExist, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - CreateAccountNotAllowed, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - predecessor_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - ActorNoPermission, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - actor_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - DeleteKeyDoesNotExist, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - public_key, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - PublicKey, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - AddKeyAlreadyExists, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - public_key, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - PublicKey, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - DeleteAccountStaking, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - DeleteAccountHasRent, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - RentUnpaid, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - amount, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - TriesToUnstake, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - TriesToStake, - ), - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Inherited, - ident: Some( - Ident( - account_id, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - AccountId, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - stake, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - locked, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - serde, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: with, - }, - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: "u128_dec_format", - }, - ], - }, - ], - }, - ], - vis: Inherited, - ident: Some( - Ident( - balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - FunctionCall, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - VMError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - e, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Struct( - ExprStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldValue { - attrs: [], - member: Named( - Ident( - index, - ), - ), - colon_token: Some( - Colon, - ), - expr: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - None, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - FieldValue { - attrs: [], - member: Named( - Ident( - kind, - ), - ), - colon_token: Some( - Colon, - ), - expr: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - e, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - dot2_token: None, - rest: None, - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Match( - ExprMatch { - attrs: [], - match_token: Match, - expr: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - arms: [ - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidSigner, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - signer_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - signer_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Invalid signer account ID {:?} according to requirements", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: signer_id, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - SignerDoesNotExist, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - signer_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - signer_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Signer {:?} does not exist", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: signer_id, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: TupleStruct( - PatTupleStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidAccessKey, - ), - arguments: None, - }, - ], - }, - pat: PatTuple { - attrs: [], - paren_token: Paren, - elems: [ - Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - access_key_error, - ), - subpat: None, - }, - ), - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: MethodCall( - ExprMethodCall { - attrs: [], - receiver: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - access_key_error, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - method: Ident( - fmt, - ), - turbofish: None, - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - f, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidNonce, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - tx_nonce, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - tx_nonce, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - ak_nonce, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - ak_nonce, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction nonce {} must be larger than nonce of the used access key {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: tx_nonce, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: ak_nonce, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidReceiver, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - receiver_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - receiver_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Invalid receiver account ID {:?} according to requirements", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: receiver_id, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Path( - PatPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidSignature, - ), - arguments: None, - }, - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction is not signed with the given public key", - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - NotEnoughBalance, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - signer_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - signer_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - balance, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - balance, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - cost, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - cost, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Sender {:?} does not have enough balance {} for operation costing {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: signer_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: cost, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - RentUnpaid, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - signer_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - signer_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - amount, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - amount, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Failed to execute, because the account {:?} wouldn't have enough to pay required rent {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: signer_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: amount, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Path( - PatPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - CostOverflow, - ), - arguments: None, - }, - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction gas or balance cost is too high", - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Path( - PatPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidChain, - ), - arguments: None, - }, - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction parent block hash doesn't belong to the current chain", - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Path( - PatPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Expired, - ), - arguments: None, - }, - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction has expired", - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - error, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Call( - ExprCall { - attrs: [], - func: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidAccessKey, - ), - arguments: None, - }, - ], - }, - }, - ), - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - error, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Match( - ExprMatch { - attrs: [], - match_token: Match, - expr: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - arms: [ - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - AccessKeyNotFound, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - public_key, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - public_key, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Signer {:?} doesn't have access key with the given public_key {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: public_key, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - ReceiverMismatch, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - tx_receiver, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - tx_receiver, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - ak_receiver, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - ak_receiver, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction receiver_id {:?} doesn't match the access key receiver_id {:?}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: tx_receiver, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: ak_receiver, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - MethodNameMismatch, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - method_name, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - method_name, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Transaction method name {:?} isn't allowed by the access key", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: method_name, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Path( - PatPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "The used access key requires exactly one FunctionCall action", - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidAccessKeyError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - NotEnoughAllowance, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - public_key, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - public_key, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - allowance, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - allowance, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - cost, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - cost, - ), - subpat: None, - }, - ), - }, - Comma, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Access Key {:?}:{} does not have enough balance {} for transaction costing {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: public_key, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: allowance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: cost, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Struct( - ItemStruct { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Happens when the input balance doesn't match the output balance in Runtime apply.", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - struct_token: Struct, - ident: Ident( - BalanceMismatchError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - fields: Named( - FieldsNamed { - brace_token: Brace, - named: [ - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - incoming_validator_rewards, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - initial_accounts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - incoming_receipts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - processed_delayed_receipts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - initial_postponed_receipts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - final_accounts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - outgoing_receipts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - new_delayed_receipts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - final_postponed_receipts_balance, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - total_rent_paid, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - total_validator_reward, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - total_balance_burnt, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - Field { - attrs: [], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - ident: Some( - Ident( - total_balance_slashed, - ), - ), - colon_token: Some( - Colon, - ), - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Balance, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - Comma, - ], - }, - ), - semi_token: None, - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - BalanceMismatchError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Local( - Local { - attrs: [], - let_token: Let, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - initial_balance, - ), - subpat: None, - }, - ), - init: Some( - ( - Eq, - MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - incoming_validator_rewards, - ), - ), - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - initial_accounts_balance, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - incoming_receipts_balance, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - processed_delayed_receipts_balance, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - initial_postponed_receipts_balance, - ), - ), - }, - ), - ], - }, - ), - ), - ), - semi_token: Semi, - }, - ), - Local( - Local { - attrs: [], - let_token: Let, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - final_balance, - ), - subpat: None, - }, - ), - init: Some( - ( - Eq, - MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: MethodCall( - ExprMethodCall { - attrs: [], - receiver: Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - final_accounts_balance, - ), - ), - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - outgoing_receipts_balance, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - new_delayed_receipts_balance, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - final_postponed_receipts_balance, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - total_rent_paid, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - total_validator_reward, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - total_balance_burnt, - ), - ), - }, - ), - ], - }, - ), - dot_token: Dot, - method: Ident( - saturating_add, - ), - turbofish: None, - paren_token: Paren, - args: [ - Field( - ExprField { - attrs: [], - base: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - dot_token: Dot, - member: Named( - Ident( - total_balance_slashed, - ), - ), - }, - ), - ], - }, - ), - ), - ), - semi_token: Semi, - }, - ), - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Balance Mismatch Error. The input balance {} doesn't match output balance {}\n\ - Inputs:\n\ - \tIncoming validator rewards sum: {}\n\ - \tInitial accounts balance sum: {}\n\ - \tIncoming receipts balance sum: {}\n\ - \tProcessed delayed receipts balance sum: {}\n\ - \tInitial postponed receipts balance sum: {}\n\ - Outputs:\n\ - \tFinal accounts balance sum: {}\n\ - \tOutgoing receipts balance sum: {}\n\ - \tNew delayed receipts balance sum: {}\n\ - \tFinal postponed receipts balance sum: {}\n\ - \tTotal rent paid: {}\n\ - \tTotal validators reward: {}\n\ - \tTotal balance burnt: {}\n\ - \tTotal balance slashed: {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: initial_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: final_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: incoming_validator_rewards, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: initial_accounts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: incoming_receipts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: processed_delayed_receipts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: initial_postponed_receipts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: final_accounts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: outgoing_receipts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: new_delayed_receipts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: final_postponed_receipts_balance, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: total_rent_paid, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: total_validator_reward, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: total_balance_burnt, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: total_balance_slashed, - }, - Punct { - op: ',', - spacing: Alone, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Struct( - ItemStruct { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - struct_token: Struct, - ident: Ident( - IntegerOverflowError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - fields: Unit, - semi_token: Some( - Semi, - ), - }, - ), - Enum( - ItemEnum { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Error returned from `Runtime::apply`", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - enum_token: Enum, - ident: Ident( - RuntimeError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - brace_token: Brace, - variants: [ - Variant { - attrs: [], - ident: Ident( - UnexpectedIntegerOverflow, - ), - fields: Unit, - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidTxError, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - StorageError, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - StorageError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - BalanceMismatch, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - BalanceMismatchError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - IntegerOverflowError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Wild( - PatWild { - attrs: [], - underscore_token: Underscore, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - IntegerOverflowError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - CostOverflow, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - IntegerOverflowError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Wild( - PatWild { - attrs: [], - underscore_token: Underscore, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - IntegerOverflowError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - UnexpectedIntegerOverflow, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - StorageError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - e, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - StorageError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Call( - ExprCall { - attrs: [], - func: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - StorageError, - ), - arguments: None, - }, - ], - }, - }, - ), - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - e, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - BalanceMismatchError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - e, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - BalanceMismatchError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Call( - ExprCall { - attrs: [], - func: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - BalanceMismatch, - ), - arguments: None, - }, - ], - }, - }, - ), - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - e, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - e, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Call( - ExprCall { - attrs: [], - func: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - RuntimeError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - e, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Action #{}: {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: index, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: unwrap_or_default, - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [], - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: self, - }, - Punct { - op: '.', - spacing: Alone, - }, - Ident { - sym: kind, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Match( - ExprMatch { - attrs: [], - match_token: Match, - expr: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - arms: [ - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - AccountAlreadyExists, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Can't create a new account {:?}, because it already exists", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - AccountDoesNotExist, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Can't complete the action because account {:?} doesn't exist", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - ActorNoPermission, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - actor_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - actor_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Actor {:?} doesn't have permission to account {:?} to complete the action", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: actor_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - RentUnpaid, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - amount, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - amount, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "The account {} wouldn't have enough balance to pay required rent {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: amount, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - TriesToUnstake, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Account {:?} is not yet staked, but tries to unstake", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - TriesToStake, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - stake, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - stake, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - locked, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - locked, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - balance, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - balance, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Account {:?} tries to stake {}, but has staked {} and only has {}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: stake, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: locked, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: balance, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - CreateAccountNotAllowed, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - predecessor_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - predecessor_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "The new account_id {:?} can't be created by {:?}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: predecessor_id, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - DeleteKeyDoesNotExist, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - ], - dot2_token: Some( - Dot2, - ), - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Account {:?} tries to remove an access key that doesn't exist", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - AddKeyAlreadyExists, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - public_key, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - public_key, - ), - subpat: None, - }, - ), - }, - Comma, - ], - dot2_token: Some( - Dot2, - ), - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "The public key {:?} is already used for an existing access key", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: public_key, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - DeleteAccountStaking, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Block( - ExprBlock { - attrs: [], - label: None, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Account {:?} is staking and can not be deleted", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - ], - }, - }, - ), - ), - ], - }, - }, - ), - comma: None, - }, - Arm { - attrs: [], - pat: Struct( - PatStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - DeleteAccountHasRent, - ), - arguments: None, - }, - ], - }, - brace_token: Brace, - fields: [ - FieldPat { - attrs: [], - member: Named( - Ident( - account_id, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - account_id, - ), - subpat: None, - }, - ), - }, - Comma, - FieldPat { - attrs: [], - member: Named( - Ident( - balance, - ), - ), - colon_token: None, - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - balance, - ), - subpat: None, - }, - ), - }, - ], - dot2_token: None, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "Account {:?} can't be deleted. It has {}, which is enough to cover the rent", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: account_id, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: balance, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: TupleStruct( - PatTupleStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionErrorKind, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - FunctionCall, - ), - arguments: None, - }, - ], - }, - pat: PatTuple { - attrs: [], - paren_token: Paren, - elems: [ - Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - s, - ), - subpat: None, - }, - ), - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "{}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: s, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Enum( - ItemEnum { - attrs: [ - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - doc, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Punct { - op: '=', - spacing: Alone, - }, - Literal { - lit: " Error returned in the ExecutionOutcome in case of failure.", - }, - ], - }, - Attribute { - pound_token: Pound, - style: Outer, - bracket_token: Bracket, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - derive, - ), - arguments: None, - }, - ], - }, - tokens: TokenStream [ - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - sym: BorshSerialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: BorshDeserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Debug, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Clone, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: PartialEq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Eq, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Deserialize, - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: Serialize, - }, - ], - }, - ], - }, - ], - vis: Public( - VisPublic { - pub_token: Pub, - }, - ), - enum_token: Enum, - ident: Ident( - ExecutionError, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - brace_token: Brace, - variants: [ - Variant { - attrs: [], - ident: Ident( - Action, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - Variant { - attrs: [], - ident: Ident( - InvalidTx, - ), - fields: Unnamed( - FieldsUnnamed { - paren_token: Paren, - unnamed: [ - Field { - attrs: [], - vis: Inherited, - ident: None, - colon_token: None, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ], - }, - ), - discriminant: None, - }, - Comma, - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Display, - ), - arguments: None, - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - fmt, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Receiver( - Receiver { - attrs: [], - reference: Some( - ( - And, - None, - ), - ), - mutability: None, - self_token: SelfValue, - }, - ), - Comma, - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - f, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Reference( - TypeReference { - and_token: And, - lifetime: None, - mutability: Some( - Mut, - ), - elem: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Formatter, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Result, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Tuple( - TypeTuple { - paren_token: Paren, - elems: [], - }, - ), - ), - Comma, - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - std, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - fmt, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Error, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Match( - ExprMatch { - attrs: [], - match_token: Match, - expr: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - self, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - arms: [ - Arm { - attrs: [], - pat: TupleStruct( - PatTupleStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Action, - ), - arguments: None, - }, - ], - }, - pat: PatTuple { - attrs: [], - paren_token: Paren, - elems: [ - Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - e, - ), - subpat: None, - }, - ), - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "{}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: e, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - Arm { - attrs: [], - pat: TupleStruct( - PatTupleStruct { - attrs: [], - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidTx, - ), - arguments: None, - }, - ], - }, - pat: PatTuple { - attrs: [], - paren_token: Paren, - elems: [ - Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - e, - ), - subpat: None, - }, - ), - ], - }, - }, - ), - guard: None, - fat_arrow_token: FatArrow, - body: Macro( - ExprMacro { - attrs: [], - mac: Macro { - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - write, - ), - arguments: None, - }, - ], - }, - bang_token: Bang, - delimiter: Paren( - Paren, - ), - tokens: TokenStream [ - Ident { - sym: f, - }, - Punct { - op: ',', - spacing: Alone, - }, - Literal { - lit: "{}", - }, - Punct { - op: ',', - spacing: Alone, - }, - Ident { - sym: e, - }, - ], - }, - }, - ), - comma: Some( - Comma, - ), - }, - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - error, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ActionError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Call( - ExprCall { - attrs: [], - func: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - Action, - ), - arguments: None, - }, - ], - }, - }, - ), - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - error, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - Impl( - ItemImpl { - attrs: [], - defaultness: None, - unsafety: None, - impl_token: Impl, - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - trait_: Some( - ( - None, - Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - From, - ), - arguments: AngleBracketed( - AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Lt, - args: [ - Type( - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - ], - gt_token: Gt, - }, - ), - }, - ], - }, - For, - ), - ), - self_ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - ], - }, - }, - ), - brace_token: Brace, - items: [ - Method( - ImplItemMethod { - attrs: [], - vis: Inherited, - defaultness: None, - sig: Signature { - constness: None, - asyncness: None, - unsafety: None, - abi: None, - fn_token: Fn, - ident: Ident( - from, - ), - generics: Generics { - lt_token: None, - params: [], - gt_token: None, - where_clause: None, - }, - paren_token: Paren, - inputs: [ - Typed( - PatType { - attrs: [], - pat: Ident( - PatIdent { - attrs: [], - by_ref: None, - mutability: None, - ident: Ident( - error, - ), - subpat: None, - }, - ), - colon_token: Colon, - ty: Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - InvalidTxError, - ), - arguments: None, - }, - ], - }, - }, - ), - }, - ), - ], - variadic: None, - output: Type( - RArrow, - Path( - TypePath { - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - Self, - ), - arguments: None, - }, - ], - }, - }, - ), - ), - }, - block: Block { - brace_token: Brace, - stmts: [ - Expr( - Call( - ExprCall { - attrs: [], - func: Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - ExecutionError, - ), - arguments: None, - }, - Colon2, - PathSegment { - ident: Ident( - InvalidTx, - ), - arguments: None, - }, - ], - }, - }, - ), - paren_token: Paren, - args: [ - Path( - ExprPath { - attrs: [], - qself: None, - path: Path { - leading_colon: None, - segments: [ - PathSegment { - ident: Ident( - error, - ), - arguments: None, - }, - ], - }, - }, - ), - ], - }, - ), - ), - ], - }, - }, - ), - ], - }, - ), - ], -} diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 3f92215600e..e6fcc70cfd7 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -2,7 +2,7 @@ extern crate proc_macro; extern crate proc_macro2; use proc_macro::TokenStream; use serde::{Deserialize, Serialize}; -use serde_json::Value; +use serde_json::{Map, Value}; use std::cell::RefCell; use std::collections::HashMap; use syn::{ @@ -32,21 +32,21 @@ impl Drop for Schema { fn drop(&mut self) { // std::env::var("CARGO_TARGET_DIR") doesn't exists let filename = "./target/errors_schema.json"; - let json_value = serde_json::to_value(self).expect("Schema serialize failed"); - if let Ok(data) = std::fs::read(filename) { - if let Ok(mut existing_schema) = serde_json::from_slice::(&data) { - merge(&mut existing_schema, &json_value); - let json = serde_json::to_string_pretty(&existing_schema) - .expect("error schema serialization failed"); - println!("{}", &existing_schema); - std::fs::write(filename, json).expect("Unable to save the errors schema file"); - }; + let schema_json = serde_json::to_value(self).expect("Schema serialize failed"); + let mut new_schema_json = if let Ok(data) = std::fs::read(filename) { + // merge to the existing file + let mut existing_schema = serde_json::from_slice::(&data) + .expect("cannot deserialize target/existing_schema.json"); + merge(&mut existing_schema, &schema_json); + existing_schema } else { - let json = serde_json::to_string_pretty(&json_value) - .expect("error schema serialization failed"); - println!("{}", &json); - std::fs::write(filename, json).expect("Unable to save the errors schema file"); + schema_json }; + new_schema_json.as_object_mut().map(Map::sort_keys); + let new_schema_json_string = serde_json::to_string_pretty(&new_schema_json) + .expect("error schema serialization failed"); + std::fs::write(filename, new_schema_json_string) + .expect("Unable to save the errors schema file"); } } @@ -56,7 +56,7 @@ struct ErrorType { pub name: String, /// Names of subtypes of the error pub subtypes: Vec, - // /// An error input name and type + /// An error input name and a type pub props: HashMap, } @@ -111,7 +111,7 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput .expect("named fields must have ident") .to_string(), "".to_owned(), - ); // TODO: add type + ); // TODO: add type? } direct_error_types.push(error_type); } From 614287fb9b3e04aa10c370a6bf8f5f261ebee45e Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 6 Jan 2020 15:19:02 +0300 Subject: [PATCH 20/48] rename rpc_errors_schema.json --- build_errors_schema.sh | 2 +- res/{errors_schema.json => rpc_errors_schema.json} | 2 +- tools/rpctypegen/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename res/{errors_schema.json => rpc_errors_schema.json} (99%) diff --git a/build_errors_schema.sh b/build_errors_schema.sh index 8710ccd9d90..dc402e69481 100644 --- a/build_errors_schema.sh +++ b/build_errors_schema.sh @@ -1,2 +1,2 @@ cargo clean && cargo build --manifest-path near/Cargo.toml -cp target/errors_schema.json res/errors_schema.json +cp target/rpc_errors_schema.json res/rpc_errors_schema.json diff --git a/res/errors_schema.json b/res/rpc_errors_schema.json similarity index 99% rename from res/errors_schema.json rename to res/rpc_errors_schema.json index 429361b8132..11c04b2520b 100644 --- a/res/errors_schema.json +++ b/res/rpc_errors_schema.json @@ -540,4 +540,4 @@ "props": {} } } -} +} \ No newline at end of file diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index e6fcc70cfd7..09a4e24f46c 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -31,7 +31,7 @@ struct Schema { impl Drop for Schema { fn drop(&mut self) { // std::env::var("CARGO_TARGET_DIR") doesn't exists - let filename = "./target/errors_schema.json"; + let filename = "./target/rpc_errors_schema.json"; let schema_json = serde_json::to_value(self).expect("Schema serialize failed"); let mut new_schema_json = if let Ok(data) = std::fs::read(filename) { // merge to the existing file From 95ce4232c96293cffe6f8961435b6975fb43e3e6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 8 Jan 2020 20:46:26 +0300 Subject: [PATCH 21/48] specify a nearlib revision to test against --- scripts/test_nearlib.sh | 14 ++++---------- tools/rpctypegen/src/lib.rs | 3 ++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/scripts/test_nearlib.sh b/scripts/test_nearlib.sh index 63e87089291..92125db7a17 100755 --- a/scripts/test_nearlib.sh +++ b/scripts/test_nearlib.sh @@ -21,9 +21,10 @@ function get_nearlib_nearshell_release () { function get_nearlib_nearshell_git () { rm -rf nearlib - git clone --single-branch --branch master https://github.com/nearprotocol/nearlib.git nearlib - rm -rf near-shell - git clone --single-branch --branch master https://git@github.com/nearprotocol/near-shell.git near-shell + git clone https://github.com/nearprotocol/nearlib.git nearlib + cd nearlib + git checkout 436ed6339337e11cc4aca79cd43dd5f27feadd39 + cd .. } if [ -z "${NEARLIB_RELEASE}" ]; then @@ -39,10 +40,3 @@ yarn build ../scripts/waitonserver.sh yarn test yarn doc -cd .. - -# Try creating and building new project using NEAR CLI tools -cd near-shell -yarn -#yarn test -cd .. diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index a5b1663ac31..343cb9b2975 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -85,6 +85,7 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput let name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); match &input.data { Data::Enum(DataEnum { ref variants, .. }) => { + // TODO: check for uniqueness let error_type = error_type_name(schema, name); let mut direct_error_types = vec![]; for variant in variants { @@ -110,7 +111,7 @@ fn parse_error_type(schema: &mut HashMap, input: &DeriveInput .expect("named fields must have ident") .to_string(), "".to_owned(), - ); // TODO: add type? + ); } direct_error_types.push(error_type); } From c09cb6c28bd5225b7cd9d6cc97df153da2ea5af5 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 8 Jan 2020 20:53:59 +0300 Subject: [PATCH 22/48] fix tests --- runtime/near-vm-logic/tests/test_registers.rs | 2 +- .../near-vm-runner/tests/test_error_cases.rs | 56 ++++++++++--------- .../tests/test_invalid_contracts.rs | 14 ++--- .../near-vm-runner/tests/test_rs_contract.rs | 6 +- .../near-vm-runner/tests/test_ts_contract.rs | 8 +-- 5 files changed, 47 insertions(+), 39 deletions(-) diff --git a/runtime/near-vm-logic/tests/test_registers.rs b/runtime/near-vm-logic/tests/test_registers.rs index ddc2cc132cd..7e69cf63491 100644 --- a/runtime/near-vm-logic/tests/test_registers.rs +++ b/runtime/near-vm-logic/tests/test_registers.rs @@ -26,7 +26,7 @@ fn test_non_existent_register() { let buffer = [0u8; 3]; assert_eq!( logic.read_register(0, buffer.as_ptr() as u64), - Err(HostError::InvalidRegisterId(0).into()) + Err(HostError::InvalidRegisterId { register_id: 0 }.into()) ); } diff --git a/runtime/near-vm-runner/tests/test_error_cases.rs b/runtime/near-vm-runner/tests/test_error_cases.rs index c8d5577b719..eabb34eeb6d 100644 --- a/runtime/near-vm-runner/tests/test_error_cases.rs +++ b/runtime/near-vm-runner/tests/test_error_cases.rs @@ -1,5 +1,5 @@ use crate::utils::{make_simple_contract_call, make_simple_contract_call_with_gas}; -use near_vm_errors::{CompilationError, FunctionCallError, MethodResolveError, PrepareError}; +use near_vm_errors::{CompilationError, FunctionExecError, MethodResolveError, PrepareError}; use near_vm_logic::{HostError, ReturnData, VMOutcome}; use near_vm_runner::VMError; @@ -36,7 +36,7 @@ fn test_infinite_initializer() { make_simple_contract_call(&infinite_initializer_contract(), b"hello"), ( Some(vm_outcome_with_gas(100000000000000)), - Some(VMError::FunctionCallError(FunctionCallError::HostError(HostError::GasExceeded))) + Some(VMError::FunctionExecError(FunctionExecError::HostError(HostError::GasExceeded))) ) ); } @@ -47,7 +47,7 @@ fn test_infinite_initializer_export_not_found() { make_simple_contract_call(&infinite_initializer_contract(), b"hello2"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodNotFound ))) ) @@ -80,7 +80,7 @@ fn test_export_not_found() { make_simple_contract_call(&simple_contract(), b"hello2"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodNotFound ))) ) @@ -93,7 +93,7 @@ fn test_empty_method() { make_simple_contract_call(&simple_contract(), b""), ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodEmptyName ))) ) @@ -106,7 +106,7 @@ fn test_invalid_utf8() { make_simple_contract_call(&simple_contract(), &[255u8]), ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodUTF8Error ))) ) @@ -131,7 +131,9 @@ fn test_trap_contract() { make_simple_contract_call(&trap_contract(), b"hello"), ( Some(vm_outcome_with_gas(3856371)), - Some(VMError::FunctionCallError(FunctionCallError::WasmTrap("unknown".to_string()))) + Some(VMError::FunctionExecError(FunctionExecError::WasmTrap { + msg: "unknown".to_string() + })) ) ); } @@ -155,7 +157,9 @@ fn test_trap_initializer() { make_simple_contract_call(&trap_initializer(), b"hello"), ( Some(vm_outcome_with_gas(3856371)), - Some(VMError::FunctionCallError(FunctionCallError::WasmTrap("unknown".to_string()))) + Some(VMError::FunctionExecError(FunctionExecError::WasmTrap { + msg: "unknown".to_string() + })) ) ); } @@ -178,7 +182,7 @@ fn test_wrong_signature_contract() { make_simple_contract_call(&wrong_signature_contract(), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodInvalidSignature ))) ) @@ -202,7 +206,7 @@ fn test_export_wrong_type() { make_simple_contract_call(&export_wrong_type(), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::ResolveError( MethodResolveError::MethodNotFound ))) ) @@ -228,9 +232,9 @@ fn test_guest_panic() { make_simple_contract_call(&guest_panic(), b"hello"), ( Some(vm_outcome_with_gas(130080593)), - Some(VMError::FunctionCallError(FunctionCallError::HostError(HostError::GuestPanic( - "explicit guest panic".to_string() - )))) + Some(VMError::FunctionExecError(FunctionExecError::HostError(HostError::GuestPanic { + panic_msg: "explicit guest panic".to_string() + }))) ) ); } @@ -253,7 +257,9 @@ fn test_stack_overflow() { make_simple_contract_call(&stack_overflow(), b"hello"), ( Some(vm_outcome_with_gas(63182782464)), - Some(VMError::FunctionCallError(FunctionCallError::WasmTrap("unknown".to_string()))) + Some(VMError::FunctionExecError(FunctionExecError::WasmTrap { + msg: "unknown".to_string() + })) ) ); } @@ -283,7 +289,7 @@ fn test_memory_grow() { make_simple_contract_call(&memory_grow(), b"hello"), ( Some(vm_outcome_with_gas(100000000000000)), - Some(VMError::FunctionCallError(FunctionCallError::HostError(HostError::GasExceeded))) + Some(VMError::FunctionExecError(FunctionExecError::HostError(HostError::GasExceeded))) ) ); } @@ -325,7 +331,7 @@ fn test_bad_import_1() { make_simple_contract_call(&bad_import_global("wtf"), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Instantiate) ))) ) @@ -338,7 +344,7 @@ fn test_bad_import_2() { make_simple_contract_call(&bad_import_func("wtf"), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Instantiate) ))) ) @@ -351,9 +357,9 @@ fn test_bad_import_3() { make_simple_contract_call(&bad_import_global("env"), b"hello"), ( Some(vm_outcome_with_gas(0)), - Some(VMError::FunctionCallError(FunctionCallError::LinkError( - "link error: Incorrect import type, namespace: env, name: input, expected type: global, found type: function".to_string() - ))) + Some(VMError::FunctionExecError(FunctionExecError::LinkError{ + msg: "link error: Incorrect import type, namespace: env, name: input, expected type: global, found type: function".to_string() + })) ) ); } @@ -364,9 +370,9 @@ fn test_bad_import_4() { make_simple_contract_call(&bad_import_func("env"), b"hello"), ( Some(vm_outcome_with_gas(0)), - Some(VMError::FunctionCallError(FunctionCallError::LinkError( - "link error: Import not found, namespace: env, name: wtf".to_string() - ))) + Some(VMError::FunctionExecError(FunctionExecError::LinkError { + msg: "link error: Import not found, namespace: env, name: wtf".to_string() + })) ) ); } @@ -390,7 +396,7 @@ fn test_initializer_no_gas() { make_simple_contract_call_with_gas(&some_initializer_contract(), b"hello", 0), ( Some(vm_outcome_with_gas(0)), - Some(VMError::FunctionCallError(FunctionCallError::HostError(HostError::GasExceeded))) + Some(VMError::FunctionExecError(FunctionExecError::HostError(HostError::GasExceeded))) ) ); } @@ -421,7 +427,7 @@ fn bad_many_imports() -> Vec { fn test_bad_many_imports() { let result = make_simple_contract_call(&bad_many_imports(), b"hello"); assert_eq!(result.0, Some(vm_outcome_with_gas(0))); - if let Some(VMError::FunctionCallError(FunctionCallError::LinkError(msg))) = result.1 { + if let Some(VMError::FunctionExecError(FunctionExecError::LinkError { msg })) = result.1 { eprintln!("{}", msg); assert!(msg.len() < 1000, format!("Huge error message: {}", msg.len())); } else { diff --git a/runtime/near-vm-runner/tests/test_invalid_contracts.rs b/runtime/near-vm-runner/tests/test_invalid_contracts.rs index acfddb042f7..b20f3bc1f46 100644 --- a/runtime/near-vm-runner/tests/test_invalid_contracts.rs +++ b/runtime/near-vm-runner/tests/test_invalid_contracts.rs @@ -1,5 +1,5 @@ use crate::utils::{make_simple_contract_call, wat2wasm_no_validate}; -use near_vm_errors::{CompilationError, FunctionCallError, PrepareError}; +use near_vm_errors::{CompilationError, FunctionExecError, PrepareError}; use near_vm_runner::VMError; mod utils; @@ -22,7 +22,7 @@ fn test_initializer_wrong_signature_contract() { make_simple_contract_call(&initializer_wrong_signature_contract(), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Deserialization) ))) ) @@ -45,7 +45,7 @@ fn test_function_not_defined_contract() { make_simple_contract_call(&function_not_defined_contract(), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Deserialization) ))) ) @@ -69,7 +69,7 @@ fn test_function_type_not_defined_contract_1() { make_simple_contract_call(&function_type_not_defined_contract(1), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Deserialization) ))) ) @@ -83,7 +83,7 @@ fn test_function_type_not_defined_contract_2() { make_simple_contract_call(&function_type_not_defined_contract(0), b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Deserialization) ))) ) @@ -96,7 +96,7 @@ fn test_garbage_contract() { make_simple_contract_call(&[], b"hello"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Deserialization) ))) ) @@ -121,7 +121,7 @@ fn test_evil_function_index() { make_simple_contract_call(&evil_function_index(), b"abort_with_zero"), ( None, - Some(VMError::FunctionCallError(FunctionCallError::CompilationError( + Some(VMError::FunctionExecError(FunctionExecError::CompilationError( CompilationError::PrepareError(PrepareError::Deserialization) ))) ) diff --git a/runtime/near-vm-runner/tests/test_rs_contract.rs b/runtime/near-vm-runner/tests/test_rs_contract.rs index 2d124794ef9..b3bdf75390f 100644 --- a/runtime/near-vm-runner/tests/test_rs_contract.rs +++ b/runtime/near-vm-runner/tests/test_rs_contract.rs @@ -1,5 +1,5 @@ use near_runtime_fees::RuntimeFeesConfig; -use near_vm_errors::FunctionCall; +use near_vm_errors::FunctionExecError; use near_vm_logic::mocks::mock_external::MockedExternal; use near_vm_logic::types::ReturnData; use near_vm_logic::{VMConfig, VMContext, VMOutcome}; @@ -174,6 +174,8 @@ pub fn test_out_of_memory() { ); assert_eq!( result.1, - Some(VMError::FunctionCall(FunctionCall::WasmTrap("unknown".to_string()))) + Some(VMError::FunctionExecError(FunctionExecError::WasmTrap { + msg: "unknown".to_string() + })) ); } diff --git a/runtime/near-vm-runner/tests/test_ts_contract.rs b/runtime/near-vm-runner/tests/test_ts_contract.rs index c3b2c576c3b..88c93fe4581 100644 --- a/runtime/near-vm-runner/tests/test_ts_contract.rs +++ b/runtime/near-vm-runner/tests/test_ts_contract.rs @@ -1,5 +1,5 @@ use near_runtime_fees::RuntimeFeesConfig; -use near_vm_errors::FunctionCallError; +use near_vm_errors::FunctionExecError; use near_vm_logic::mocks::mock_external::MockedExternal; use near_vm_logic::types::ReturnData; use near_vm_logic::{External, HostError, VMConfig, VMContext}; @@ -37,9 +37,9 @@ pub fn test_ts_contract() { ); assert_eq!( result.1, - Some(VMError::FunctionCallError(FunctionCallError::HostError(HostError::GuestPanic( - "explicit guest panic".to_string() - )))) + Some(VMError::FunctionExecError(FunctionExecError::HostError(HostError::GuestPanic { + panic_msg: "explicit guest panic".to_string() + }))) ); // Call method that writes something into storage. From cd6e006382e1175e62d1de4fb0fc6eba5446eaf1 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 8 Jan 2020 22:10:42 +0300 Subject: [PATCH 23/48] fix merge --- runtime/runtime/tests/test_evil_contracts.rs | 8 +-- test-utils/testlib/src/standard_test_cases.rs | 4 +- test-utils/testlib/src/user/mod.rs | 59 ++++--------------- test-utils/testlib/src/user/rpc_user.rs | 6 +- 4 files changed, 22 insertions(+), 55 deletions(-) diff --git a/runtime/runtime/tests/test_evil_contracts.rs b/runtime/runtime/tests/test_evil_contracts.rs index 437340198ba..e74f41eb0f9 100644 --- a/runtime/runtime/tests/test_evil_contracts.rs +++ b/runtime/runtime/tests/test_evil_contracts.rs @@ -1,7 +1,7 @@ use near_primitives::errors::{ActionError, ActionErrorKind}; use near_primitives::serialize::to_base64; use near_primitives::views::FinalExecutionStatus; -use near_vm_errors::{FunctionExecError, HostError, MethodResolveError, VMError}; +use near_vm_errors::{FunctionExecError, HostError, VMError}; use std::mem::size_of; use testlib::node::{Node, RuntimeNode}; @@ -137,9 +137,9 @@ fn test_evil_abort() { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCall( - "String encoding is bad UTF-16 sequence.".to_string() - ) + kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( + FunctionExecError::HostError(HostError::BadUTF16) + )) } .into() ), diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index c244a6dea63..39daeeb0425 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -83,7 +83,9 @@ pub fn test_smart_contract_panic(node: impl Node) { ActionError { index: Some(0), kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( - FunctionExecError::HostError(HostError::GuestPanic("WAT?".to_string())) + FunctionExecError::HostError(HostError::GuestPanic { + panic_msg: "WAT?".to_string() + }) )) } .into() diff --git a/test-utils/testlib/src/user/mod.rs b/test-utils/testlib/src/user/mod.rs index 24335f257bd..6842948d9f0 100644 --- a/test-utils/testlib/src/user/mod.rs +++ b/test-utils/testlib/src/user/mod.rs @@ -223,86 +223,49 @@ pub trait AsyncUser: Send + Sync { fn view_account( &self, account_id: &AccountId, -<<<<<<< HEAD - ) -> Box>; -======= - ) -> LocalBoxFuture<'static, Result>; ->>>>>>> staging + ) -> LocalBoxFuture<'static, Result>; fn view_balance( &self, account_id: &AccountId, -<<<<<<< HEAD - ) -> Box> { - Box::new(self.view_account(account_id).map(|acc| acc.amount)) -======= - ) -> LocalBoxFuture<'static, Result> { + ) -> LocalBoxFuture<'static, Result> { self.view_account(account_id).map(|res| res.map(|acc| acc.amount)).boxed_local() ->>>>>>> staging } fn view_state( &self, account_id: &AccountId, -<<<<<<< HEAD - ) -> Box>; -======= - ) -> LocalBoxFuture<'static, Result>; ->>>>>>> staging + ) -> LocalBoxFuture<'static, Result>; fn add_transaction( &self, transaction: SignedTransaction, -<<<<<<< HEAD - ) -> Box + Send>; + ) -> LocalBoxFuture<'static, Result<(), ServerError>>; - fn add_receipt(&self, receipt: Receipt) -> Box>; -======= - ) -> LocalBoxFuture<'static, Result<(), String>>; - - fn add_receipt(&self, receipt: Receipt) -> LocalBoxFuture<'static, Result<(), String>>; ->>>>>>> staging + fn add_receipt(&self, receipt: Receipt) -> LocalBoxFuture<'static, Result<(), ServerError>>; fn get_account_nonce( &self, account_id: &AccountId, - ) -> LocalBoxFuture<'static, Result>; + ) -> LocalBoxFuture<'static, Result>; -<<<<<<< HEAD - fn get_best_block_index(&self) -> Box>; -======= - fn get_best_height(&self) -> LocalBoxFuture<'static, Result>; ->>>>>>> staging + fn get_best_height(&self) -> LocalBoxFuture<'static, Result>; fn get_transaction_result( &self, hash: &CryptoHash, -<<<<<<< HEAD - ) -> Box>; -======= - ) -> LocalBoxFuture<'static, Result>; ->>>>>>> staging + ) -> LocalBoxFuture<'static, Result>; fn get_transaction_final_result( &self, hash: &CryptoHash, -<<<<<<< HEAD - ) -> Box>; - - fn get_state_root(&self) -> Box>; -======= - ) -> LocalBoxFuture<'static, Result>; + ) -> LocalBoxFuture<'static, Result>; - fn get_state_root(&self) -> LocalBoxFuture<'static, Result>; ->>>>>>> staging + fn get_state_root(&self) -> LocalBoxFuture<'static, Result>; fn get_access_key( &self, account_id: &AccountId, public_key: &PublicKey, -<<<<<<< HEAD - ) -> Box, Error = ServerError>>; -======= - ) -> LocalBoxFuture<'static, Result, String>>; ->>>>>>> staging + ) -> LocalBoxFuture<'static, Result, ServerError>>; } diff --git a/test-utils/testlib/src/user/rpc_user.rs b/test-utils/testlib/src/user/rpc_user.rs index a9e9bae4fd8..ef1045868fa 100644 --- a/test-utils/testlib/src/user/rpc_user.rs +++ b/test-utils/testlib/src/user/rpc_user.rs @@ -73,8 +73,10 @@ impl User for RpcUser { let _ = self .actix(move |client| client.write().unwrap().broadcast_tx_async(to_base64(&bytes))) .map_err(|err| { - serde_json::from_value::(e.data.expect("server error must carry data")) - .expect("deserialize server error must be ok") + serde_json::from_value::( + err.data.expect("server error must carry data"), + ) + .expect("deserialize server error must be ok") })?; Ok(()) } From 03c0ee830feab38e32fa6f9bc2c8bf7f26a11690 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 8 Jan 2020 22:51:37 +0300 Subject: [PATCH 24/48] fix rpctypegen build --- tools/rpctypegen/Cargo.toml | 2 +- tools/rpctypegen/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/rpctypegen/Cargo.toml b/tools/rpctypegen/Cargo.toml index 70cd2cdca31..13ce15ff8ae 100644 --- a/tools/rpctypegen/Cargo.toml +++ b/tools/rpctypegen/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" proc-macro = true [dependencies] -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0", features = ["preserve_order"]} syn = { version = "1.0", features = ["full", "extra-traits"]} quote = "1.0" diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 343cb9b2975..78ed7557663 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -1,5 +1,6 @@ extern crate proc_macro; extern crate proc_macro2; + use proc_macro::TokenStream; use serde::{Deserialize, Serialize}; use serde_json::Value; From 86ad27216c2e2d180ddb29859e0f65efc3463cd7 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 10 Jan 2020 16:59:20 +0300 Subject: [PATCH 25/48] fix ci: exclude near_rpc_error_macro from tests --- scripts/parallel_run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/parallel_run_tests.py b/scripts/parallel_run_tests.py index e813f6614cf..e869f437a31 100644 --- a/scripts/parallel_run_tests.py +++ b/scripts/parallel_run_tests.py @@ -17,7 +17,7 @@ def show_test_result(binary, result): if __name__ == "__main__": clean_binary_tests() build_tests() - binaries = test_binaries(exclude=[r'test_regression-.*']) + binaries = test_binaries(exclude=[r'test_regression-.*', r'near_rpc_error_macro-.*']) print(f'========= collected {len(binaries)} test binaries:') print('\n'.join(binaries)) From a82fa00214a480e427aacccfb550218b3786ab21 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 15:24:11 +0300 Subject: [PATCH 26/48] add Errors docs, rename error types fix Balance formatting --- build_errors_schema.sh | 1 + chain/jsonrpc/src/lib.rs | 6 +- core/primitives/src/errors.rs | 115 ++-- core/primitives/src/transaction.rs | 4 +- core/primitives/src/views.rs | 8 +- res/rpc_errors_schema.json | 597 +++++++++--------- runtime/near-vm-errors/src/lib.rs | 27 +- runtime/runtime/src/lib.rs | 10 +- test-utils/testlib/src/standard_test_cases.rs | 30 +- test-utils/testlib/src/user/runtime_user.rs | 4 +- 10 files changed, 425 insertions(+), 377 deletions(-) mode change 100644 => 100755 build_errors_schema.sh diff --git a/build_errors_schema.sh b/build_errors_schema.sh old mode 100644 new mode 100755 index dc402e69481..3890d3892f7 --- a/build_errors_schema.sh +++ b/build_errors_schema.sh @@ -1,2 +1,3 @@ +#!/bin/bash cargo clean && cargo build --manifest-path near/Cargo.toml cp target/rpc_errors_schema.json res/rpc_errors_schema.json diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index f68073dc845..8c49909428e 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -24,7 +24,7 @@ pub use near_jsonrpc_client as client; use near_jsonrpc_client::{message, BlockId, ChunkId}; use near_metrics::{Encoder, TextEncoder}; use near_network::{NetworkClientMessages, NetworkClientResponses}; -use near_primitives::errors::{ExecutionError, InvalidTxError}; +use near_primitives::errors::{InvalidTxError, TxExecutionError}; use near_primitives::hash::CryptoHash; use near_primitives::serialize::{from_base, from_base64, BaseEncode}; use near_primitives::transaction::SignedTransaction; @@ -123,14 +123,14 @@ fn parse_hash(params: Option) -> Result { #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, near_rpc_error_macro::RpcError)] #[rpc_error_variant = "ServerError"] pub enum ServerError { - TxExecutionError(ExecutionError), + TxExecutionError(TxExecutionError), Timeout, Closed, } impl From for ServerError { fn from(e: InvalidTxError) -> ServerError { - ServerError::TxExecutionError(ExecutionError::InvalidTx(e)) + ServerError::TxExecutionError(TxExecutionError::InvalidTxError(e)) } } diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 58eb26b0450..4c3340f63f4 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -13,38 +13,44 @@ use near_vm_errors::VMError; BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] #[rpc_error_variant = "TxExecutionError"] -pub enum ExecutionError { - Action(ActionError), - InvalidTx(InvalidTxError), +pub enum TxExecutionError { + /// An error happened during Acton execution + ActionError(ActionError), + /// An error happened during Transaction execution + InvalidTxError(InvalidTxError), } -impl Display for ExecutionError { +impl Display for TxExecutionError { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match self { - ExecutionError::Action(e) => write!(f, "{}", e), - ExecutionError::InvalidTx(e) => write!(f, "{}", e), + TxExecutionError::ActionError(e) => write!(f, "{}", e), + TxExecutionError::InvalidTxError(e) => write!(f, "{}", e), } } } -impl From for ExecutionError { +impl From for TxExecutionError { fn from(error: ActionError) -> Self { - ExecutionError::Action(error) + TxExecutionError::ActionError(error) } } -impl From for ExecutionError { +impl From for TxExecutionError { fn from(error: InvalidTxError) -> Self { - ExecutionError::InvalidTx(error) + TxExecutionError::InvalidTxError(error) } } /// Error returned from `Runtime::apply` #[derive(Debug, Clone, PartialEq, Eq)] pub enum RuntimeError { + /// An integeroverflow during counting ApplyStats UnexpectedIntegerOverflow, + /// An error happened during TX execution InvalidTxError(InvalidTxError), + /// Unexpected error which is typically related to the node storage corruption StorageError(StorageError), + /// An error happens if `check_balance` fails BalanceMismatch(BalanceMismatchError), } @@ -71,27 +77,25 @@ impl std::fmt::Display for StorageError { impl std::error::Error for StorageError {} -/// External +/// An error happened during TX execution #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "InvalidTx"] +#[rpc_error_variant = "InvalidTxError"] pub enum InvalidTxError { + /// Happens if a wrong AccessKey used or AccessKey has not enough permissions InvalidAccessKey(InvalidAccessKeyError), - InvalidSigner { - signer_id: AccountId, - }, - SignerDoesNotExist { - signer_id: AccountId, - }, - InvalidNonce { - tx_nonce: Nonce, - ak_nonce: Nonce, - }, - InvalidReceiver { - receiver_id: AccountId, - }, + /// TX signer_id is not in a valid format or not satisfy requirements see `near_core::primitives::utils::is_valid_account_id` + InvalidSignerId { signer_id: AccountId }, + /// TX signer_id is not found in a storage + SignerDoesNotExist { signer_id: AccountId }, + /// Transaction nonce must be account[access_key].nonce + 1 + InvalidNonce { tx_nonce: Nonce, ak_nonce: Nonce }, + /// TX receiver_id is not in a valid format or not satisfy requirements see `near_core::primitives::utils::is_valid_account_id` + InvalidReceiverId { receiver_id: AccountId }, + /// TX signature is not valid InvalidSignature, + /// Account have not enough tokens to cover TX cost NotEnoughBalance { signer_id: AccountId, #[serde(with = "u128_dec_format")] @@ -99,13 +103,19 @@ pub enum InvalidTxError { #[serde(with = "u128_dec_format")] cost: Balance, }, + /// Signer account rent is unpaid RentUnpaid { + /// An account which is required to pay the rent signer_id: AccountId, + /// Required balance to cover the state rent #[serde(with = "u128_dec_format")] amount: Balance, }, + /// Transaction gas or balance cost is too high CostOverflow, + /// Transaction parent block hash doesn't belong to the current chain InvalidChain, + /// Transaction has expired Expired, } @@ -114,18 +124,15 @@ pub enum InvalidTxError { )] #[rpc_error_variant = "InvalidAccessKey"] pub enum InvalidAccessKeyError { - AccessKeyNotFound { - account_id: AccountId, - public_key: PublicKey, - }, - ReceiverMismatch { - tx_receiver: AccountId, - ak_receiver: AccountId, - }, - MethodNameMismatch { - method_name: String, - }, + /// Unable to found an access key for account_id identified by a public_key + AccessKeyNotFound { account_id: AccountId, public_key: PublicKey }, + /// Transaction receiver_id doesn't match the access key receiver_id + ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, + /// Transaction method name isn't allowed by the access key + MethodNameMismatch { method_name: String }, + /// The used access key requires exactly one FunctionCall action ActionError, + /// Access Key does not have enough balance for transaction NotEnoughAllowance { account_id: AccountId, public_key: PublicKey, @@ -139,7 +146,7 @@ pub enum InvalidAccessKeyError { #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "Action"] +#[rpc_error_variant = "ActionError"] pub struct ActionError { pub index: Option, pub kind: ActionErrorKind, @@ -148,45 +155,59 @@ pub struct ActionError { #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "Action"] +#[rpc_error_variant = "ActionError"] pub enum ActionErrorKind { + /// Happens when CreateAccount action tries to create an account with account_id which is already exists in the storage AccountAlreadyExists { account_id: AccountId, }, + /// Happens when TX receiver_id doesn't exist (but action is not Action::CreateAccount) AccountDoesNotExist { account_id: AccountId, }, + /// A newly created account must be under a namespace of the creator account CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId, }, + /// Administrative actions like DeployContract, Stake, AddKey, DeleteKey. can be proceed only if sender=receiver. ActorNoPermission { account_id: AccountId, actor_id: AccountId, }, + /// Account tries to remove an access key that doesn't exist DeleteKeyDoesNotExist { account_id: AccountId, public_key: PublicKey, }, + /// The public key is already used for an existing access key AddKeyAlreadyExists { account_id: AccountId, public_key: PublicKey, }, + /// Account is staking and can not be deleted DeleteAccountStaking { account_id: AccountId, }, + /// Have to cover rent before delete an account DeleteAccountHasRent { account_id: AccountId, + #[serde(with = "u128_dec_format")] balance: Balance, }, + /// ActionReceipt can't be applied for an account. Account state rent is not payed. RentUnpaid { + /// An account which is required to pay the rent account_id: AccountId, + /// Required balance to cover the state rent #[serde(with = "u128_dec_format")] amount: Balance, }, + /// Account is not yet staked, but tries to unstake TriesToUnstake { account_id: AccountId, }, + /// Account tries to stake but it is already staked. TriesToStake { account_id: AccountId, #[serde(with = "u128_dec_format")] @@ -208,7 +229,7 @@ impl From for ActionError { impl Display for InvalidTxError { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match self { - InvalidTxError::InvalidSigner{signer_id} => { + InvalidTxError::InvalidSignerId{signer_id} => { write!(f, "Invalid signer account ID {:?} according to requirements", signer_id) } InvalidTxError::SignerDoesNotExist{signer_id} => { @@ -220,7 +241,7 @@ impl Display for InvalidTxError { "Transaction nonce {} must be larger than nonce of the used access key {}", tx_nonce, ak_nonce ), - InvalidTxError::InvalidReceiver{receiver_id} => { + InvalidTxError::InvalidReceiverId{receiver_id} => { write!(f, "Invalid receiver account ID {:?} according to requirements", receiver_id) } InvalidTxError::InvalidSignature => { @@ -292,19 +313,32 @@ impl Display for InvalidAccessKeyError { #[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] pub struct BalanceMismatchError { // Input balances + #[serde(with = "u128_dec_format")] pub incoming_validator_rewards: Balance, + #[serde(with = "u128_dec_format")] pub initial_accounts_balance: Balance, + #[serde(with = "u128_dec_format")] pub incoming_receipts_balance: Balance, + #[serde(with = "u128_dec_format")] pub processed_delayed_receipts_balance: Balance, + #[serde(with = "u128_dec_format")] pub initial_postponed_receipts_balance: Balance, // Output balances + #[serde(with = "u128_dec_format")] pub final_accounts_balance: Balance, + #[serde(with = "u128_dec_format")] pub outgoing_receipts_balance: Balance, + #[serde(with = "u128_dec_format")] pub new_delayed_receipts_balance: Balance, + #[serde(with = "u128_dec_format")] pub final_postponed_receipts_balance: Balance, + #[serde(with = "u128_dec_format")] pub total_rent_paid: Balance, + #[serde(with = "u128_dec_format")] pub total_validator_reward: Balance, + #[serde(with = "u128_dec_format")] pub total_balance_burnt: Balance, + #[serde(with = "u128_dec_format")] pub total_balance_slashed: Balance, } @@ -408,6 +442,7 @@ impl Display for ActionErrorKind { ActionErrorKind::AccountAlreadyExists { account_id } => { write!(f, "Can't create a new account {:?}, because it already exists", account_id) } + ActionErrorKind::AccountDoesNotExist { account_id } => write!( f, "Can't complete the action because account {:?} doesn't exist", diff --git a/core/primitives/src/transaction.rs b/core/primitives/src/transaction.rs index f7b674cea51..75861175cc0 100644 --- a/core/primitives/src/transaction.rs +++ b/core/primitives/src/transaction.rs @@ -6,7 +6,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::{PublicKey, Signature, Signer}; use crate::account::AccessKey; -use crate::errors::ExecutionError; +use crate::errors::TxExecutionError; use crate::hash::{hash, CryptoHash}; use crate::logging; use crate::merkle::MerklePath; @@ -211,7 +211,7 @@ pub enum ExecutionStatus { /// The execution is pending or unknown. Unknown, /// The execution has failed with the given execution error. - Failure(ExecutionError), + Failure(TxExecutionError), /// The final action succeeded and returned some value or an empty vec. SuccessValue(Vec), /// The final action of the receipt returned a promise or the signed transaction was converted diff --git a/core/primitives/src/views.rs b/core/primitives/src/views.rs index 3951cf4b4a9..446843f73d7 100644 --- a/core/primitives/src/views.rs +++ b/core/primitives/src/views.rs @@ -10,7 +10,7 @@ use near_crypto::{PublicKey, Signature}; use crate::account::{AccessKey, AccessKeyPermission, Account, FunctionCallPermission}; use crate::block::{Approval, Block, BlockHeader, BlockHeaderInnerLite, BlockHeaderInnerRest}; use crate::challenge::{Challenge, ChallengesResult}; -use crate::errors::ExecutionError; +use crate::errors::TxExecutionError; use crate::hash::{hash, CryptoHash}; use crate::logging; use crate::merkle::MerklePath; @@ -643,7 +643,7 @@ pub enum FinalExecutionStatus { /// The execution has started and still going. Started, /// The execution has failed with the given error. - Failure(ExecutionError), + Failure(TxExecutionError), /// The execution has succeeded and returned some value or an empty vec encoded in base64. SuccessValue(String), } @@ -670,7 +670,7 @@ impl Default for FinalExecutionStatus { #[derive(BorshSerialize, BorshDeserialize, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub enum ServerError { - TxExecutionError(ExecutionError), + TxExecutionError(TxExecutionError), Timeout, Closed, } @@ -680,7 +680,7 @@ pub enum ExecutionStatusView { /// The execution is pending or unknown. Unknown, /// The execution has failed. - Failure(ExecutionError), + Failure(TxExecutionError), /// The final action succeeded and returned some value or an empty vec encoded in base64. SuccessValue(String), /// The final action of the receipt returned a promise or the signed transaction was converted diff --git a/res/rpc_errors_schema.json b/res/rpc_errors_schema.json index 11c04b2520b..2d5f0281fa7 100644 --- a/res/rpc_errors_schema.json +++ b/res/rpc_errors_schema.json @@ -1,27 +1,54 @@ { "schema": { - "GasLimitExceeded": { - "name": "GasLimitExceeded", + "InvalidIteratorIndex": { + "name": "InvalidIteratorIndex", + "subtypes": [], + "props": { + "iterator_index": "" + } + }, + "InvalidPublicKey": { + "name": "InvalidPublicKey", "subtypes": [], "props": {} }, - "MethodEmptyName": { - "name": "MethodEmptyName", + "CannotAppendActionToJointPromise": { + "name": "CannotAppendActionToJointPromise", "subtypes": [], "props": {} }, - "WasmerCompileError": { - "name": "WasmerCompileError", + "Instantiate": { + "name": "Instantiate", + "subtypes": [], + "props": {} + }, + "MemoryAccessViolation": { + "name": "MemoryAccessViolation", + "subtypes": [], + "props": {} + }, + "BadUTF16": { + "name": "BadUTF16", + "subtypes": [], + "props": {} + }, + "LinkError": { + "name": "LinkError", "subtypes": [], "props": { "msg": "" } }, - "GuestPanic": { - "name": "GuestPanic", + "StackHeightInstrumentation": { + "name": "StackHeightInstrumentation", + "subtypes": [], + "props": {} + }, + "WasmerCompileError": { + "name": "WasmerCompileError", "subtypes": [], "props": { - "panic_msg": "" + "msg": "" } }, "Memory": { @@ -29,8 +56,28 @@ "subtypes": [], "props": {} }, - "GasExceeded": { - "name": "GasExceeded", + "InvalidAccountId": { + "name": "InvalidAccountId", + "subtypes": [], + "props": {} + }, + "ResolveError": { + "name": "ResolveError", + "subtypes": [ + "MethodEmptyName", + "MethodUTF8Error", + "MethodNotFound", + "MethodInvalidSignature" + ], + "props": {} + }, + "InternalMemoryDeclared": { + "name": "InternalMemoryDeclared", + "subtypes": [], + "props": {} + }, + "GasInstrumentation": { + "name": "GasInstrumentation", "subtypes": [], "props": {} }, @@ -39,135 +86,134 @@ "subtypes": [], "props": {} }, - "FunctionCall": { - "name": "FunctionCall", + "PrepareError": { + "name": "PrepareError", "subtypes": [ - "FunctionExecError", - "StorageError" + "Serialization", + "Deserialization", + "InternalMemoryDeclared", + "GasInstrumentation", + "StackHeightInstrumentation", + "Instantiate", + "Memory" ], "props": {} }, - "BadUTF16": { - "name": "BadUTF16", + "CannotReturnJointPromise": { + "name": "CannotReturnJointPromise", "subtypes": [], "props": {} }, - "WasmTrap": { - "name": "WasmTrap", + "MethodInvalidSignature": { + "name": "MethodInvalidSignature", + "subtypes": [], + "props": {} + }, + "InvalidRegisterId": { + "name": "InvalidRegisterId", "subtypes": [], "props": { - "msg": "" + "register_id": "" } }, - "GasInstrumentation": { - "name": "GasInstrumentation", + "GasExceeded": { + "name": "GasExceeded", "subtypes": [], "props": {} }, - "HostError": { - "name": "HostError", + "FunctionCall": { + "name": "FunctionCall", "subtypes": [ - "BadUTF16", - "BadUTF8", - "GasExceeded", - "GasLimitExceeded", - "BalanceExceeded", - "EmptyMethodName", - "GuestPanic", - "IntegerOverflow", - "InvalidPromiseIndex", - "CannotAppendActionToJointPromise", - "CannotReturnJointPromise", - "InvalidPromiseResultIndex", - "InvalidRegisterId", - "IteratorWasInvalidated", - "MemoryAccessViolation", - "InvalidReceiptIndex", - "InvalidIteratorIndex", - "InvalidAccountId", - "InvalidMethodName", - "InvalidPublicKey", - "ProhibitedInView" + "FunctionExecError", + "StorageError" ], "props": {} }, - "InvalidPromiseIndex": { - "name": "InvalidPromiseIndex", + "Deserialization": { + "name": "Deserialization", "subtypes": [], - "props": { - "promise_idx": "" - } + "props": {} }, - "InvalidPromiseResultIndex": { - "name": "InvalidPromiseResultIndex", + "FunctionExecError": { + "name": "FunctionExecError", + "subtypes": [ + "CompilationError", + "LinkError", + "ResolveError", + "WasmTrap", + "HostError" + ], + "props": {} + }, + "GasLimitExceeded": { + "name": "GasLimitExceeded", "subtypes": [], - "props": { - "result_idx": "" - } + "props": {} }, - "Deserialization": { - "name": "Deserialization", + "BalanceExceeded": { + "name": "BalanceExceeded", "subtypes": [], "props": {} }, - "MethodNotFound": { - "name": "MethodNotFound", + "Serialization": { + "name": "Serialization", "subtypes": [], "props": {} }, - "InvalidRegisterId": { - "name": "InvalidRegisterId", + "WasmTrap": { + "name": "WasmTrap", "subtypes": [], "props": { - "register_id": "" + "msg": "" } }, - "InvalidReceiptIndex": { - "name": "InvalidReceiptIndex", + "ProhibitedInView": { + "name": "ProhibitedInView", "subtypes": [], "props": { - "receipt_index": "" + "method_name": "" } }, + "MethodEmptyName": { + "name": "MethodEmptyName", + "subtypes": [], + "props": {} + }, "EmptyMethodName": { "name": "EmptyMethodName", "subtypes": [], "props": {} }, - "CannotReturnJointPromise": { - "name": "CannotReturnJointPromise", + "GuestPanic": { + "name": "GuestPanic", "subtypes": [], - "props": {} + "props": { + "panic_msg": "" + } }, - "StackHeightInstrumentation": { - "name": "StackHeightInstrumentation", + "InvalidMethodName": { + "name": "InvalidMethodName", "subtypes": [], "props": {} }, - "PrepareError": { - "name": "PrepareError", - "subtypes": [ - "Serialization", - "Deserialization", - "InternalMemoryDeclared", - "GasInstrumentation", - "StackHeightInstrumentation", - "Instantiate", - "Memory" - ], + "MethodNotFound": { + "name": "MethodNotFound", + "subtypes": [], "props": {} }, - "CodeDoesNotExist": { - "name": "CodeDoesNotExist", + "InvalidPromiseResultIndex": { + "name": "InvalidPromiseResultIndex", "subtypes": [], "props": { - "account_id": "" + "result_idx": "" } }, - "MethodInvalidSignature": { - "name": "MethodInvalidSignature", + "IteratorWasInvalidated": { + "name": "IteratorWasInvalidated", "subtypes": [], - "props": {} + "props": { + "iterator_index": "" + } }, "CompilationError": { "name": "CompilationError", @@ -178,118 +224,152 @@ ], "props": {} }, - "IntegerOverflow": { - "name": "IntegerOverflow", + "InvalidPromiseIndex": { + "name": "InvalidPromiseIndex", "subtypes": [], - "props": {} + "props": { + "promise_idx": "" + } }, - "MemoryAccessViolation": { - "name": "MemoryAccessViolation", + "BadUTF8": { + "name": "BadUTF8", "subtypes": [], "props": {} }, - "InvalidIteratorIndex": { - "name": "InvalidIteratorIndex", + "InvalidReceiptIndex": { + "name": "InvalidReceiptIndex", "subtypes": [], "props": { - "iterator_index": "" + "receipt_index": "" } }, - "IteratorWasInvalidated": { - "name": "IteratorWasInvalidated", + "CodeDoesNotExist": { + "name": "CodeDoesNotExist", "subtypes": [], "props": { - "iterator_index": "" + "account_id": "" } }, - "InvalidAccountId": { - "name": "InvalidAccountId", - "subtypes": [], + "HostError": { + "name": "HostError", + "subtypes": [ + "BadUTF16", + "BadUTF8", + "GasExceeded", + "GasLimitExceeded", + "BalanceExceeded", + "EmptyMethodName", + "GuestPanic", + "IntegerOverflow", + "InvalidPromiseIndex", + "CannotAppendActionToJointPromise", + "CannotReturnJointPromise", + "InvalidPromiseResultIndex", + "InvalidRegisterId", + "IteratorWasInvalidated", + "MemoryAccessViolation", + "InvalidReceiptIndex", + "InvalidIteratorIndex", + "InvalidAccountId", + "InvalidMethodName", + "InvalidPublicKey", + "ProhibitedInView" + ], "props": {} }, - "Serialization": { - "name": "Serialization", + "IntegerOverflow": { + "name": "IntegerOverflow", "subtypes": [], "props": {} }, - "CannotAppendActionToJointPromise": { - "name": "CannotAppendActionToJointPromise", + "NotEnoughAllowance": { + "name": "NotEnoughAllowance", "subtypes": [], - "props": {} + "props": { + "public_key": "", + "allowance": "", + "account_id": "", + "cost": "" + } + }, + "ReceiverMismatch": { + "name": "ReceiverMismatch", + "subtypes": [], + "props": { + "ak_receiver": "", + "tx_receiver": "" + } + }, + "DeleteAccountStaking": { + "name": "DeleteAccountStaking", + "subtypes": [], + "props": { + "account_id": "" + } }, - "InternalMemoryDeclared": { - "name": "InternalMemoryDeclared", + "TriesToStake": { + "name": "TriesToStake", "subtypes": [], - "props": {} + "props": { + "balance": "", + "account_id": "", + "locked": "", + "stake": "" + } }, - "Instantiate": { - "name": "Instantiate", + "InvalidReceiverId": { + "name": "InvalidReceiverId", "subtypes": [], - "props": {} + "props": { + "receiver_id": "" + } }, - "ProhibitedInView": { - "name": "ProhibitedInView", + "AccessKeyNotFound": { + "name": "AccessKeyNotFound", "subtypes": [], "props": { - "method_name": "" + "public_key": "", + "account_id": "" } }, - "FunctionExecError": { - "name": "FunctionExecError", - "subtypes": [ - "CompilationError", - "LinkError", - "ResolveError", - "WasmTrap", - "HostError" - ], - "props": {} - }, - "InvalidMethodName": { - "name": "InvalidMethodName", + "RentUnpaid": { + "name": "RentUnpaid", "subtypes": [], - "props": {} + "props": { + "amount": "", + "account_id": "" + } }, - "ResolveError": { - "name": "ResolveError", - "subtypes": [ - "MethodEmptyName", - "MethodUTF8Error", - "MethodNotFound", - "MethodInvalidSignature" - ], + "Expired": { + "name": "Expired", + "subtypes": [], "props": {} }, - "BadUTF8": { - "name": "BadUTF8", + "InvalidSignature": { + "name": "InvalidSignature", "subtypes": [], "props": {} }, - "BalanceExceeded": { - "name": "BalanceExceeded", + "InvalidChain": { + "name": "InvalidChain", "subtypes": [], "props": {} }, - "LinkError": { - "name": "LinkError", + "MethodNameMismatch": { + "name": "MethodNameMismatch", "subtypes": [], "props": { - "msg": "" + "method_name": "" } }, - "InvalidPublicKey": { - "name": "InvalidPublicKey", - "subtypes": [], - "props": {} - }, - "InvalidTx": { - "name": "InvalidTx", + "InvalidTxError": { + "name": "InvalidTxError", "subtypes": [ "InvalidAccessKey", - "InvalidSigner", + "InvalidSignerId", "SignerDoesNotExist", "InvalidNonce", - "InvalidReceiver", + "InvalidReceiverId", "InvalidSignature", "NotEnoughBalance", "RentUnpaid", @@ -299,152 +379,81 @@ ], "props": {} }, - "ActorNoPermission": { - "name": "ActorNoPermission", - "subtypes": [], - "props": { - "actor_id": "", - "account_id": "" - } - }, - "RentUnpaid": { - "name": "RentUnpaid", - "subtypes": [], - "props": { - "account_id": "", - "amount": "" - } - }, - "ReceiverMismatch": { - "name": "ReceiverMismatch", + "InvalidSignerId": { + "name": "InvalidSignerId", "subtypes": [], "props": { - "ak_receiver": "", - "tx_receiver": "" + "signer_id": "" } }, - "TxExecutionError": { - "name": "TxExecutionError", - "subtypes": [ - "Action", - "InvalidTx" - ], - "props": {} - }, "CostOverflow": { "name": "CostOverflow", "subtypes": [], "props": {} }, - "InvalidSignature": { - "name": "InvalidSignature", - "subtypes": [], - "props": {} - }, - "Action": { - "name": "Action", - "subtypes": [ - "AccountAlreadyExists", - "AccountDoesNotExist", - "CreateAccountNotAllowed", - "ActorNoPermission", - "DeleteKeyDoesNotExist", - "AddKeyAlreadyExists", - "DeleteAccountStaking", - "DeleteAccountHasRent", - "RentUnpaid", - "TriesToUnstake", - "TriesToStake", - "FunctionCall" - ], - "props": { - "index": "" - } - }, - "AccessKeyNotFound": { - "name": "AccessKeyNotFound", + "ActorNoPermission": { + "name": "ActorNoPermission", "subtypes": [], "props": { "account_id": "", - "public_key": "" - } - }, - "NotEnoughBalance": { - "name": "NotEnoughBalance", - "subtypes": [], - "props": { - "balance": "", - "cost": "", - "signer_id": "" + "actor_id": "" } }, - "NotEnoughAllowance": { - "name": "NotEnoughAllowance", + "DeleteKeyDoesNotExist": { + "name": "DeleteKeyDoesNotExist", "subtypes": [], "props": { "account_id": "", - "allowance": "", - "cost": "", "public_key": "" } }, - "Expired": { - "name": "Expired", - "subtypes": [], - "props": {} - }, - "DeleteAccountStaking": { - "name": "DeleteAccountStaking", + "AddKeyAlreadyExists": { + "name": "AddKeyAlreadyExists", "subtypes": [], "props": { + "public_key": "", "account_id": "" } }, - "SignerDoesNotExist": { - "name": "SignerDoesNotExist", + "DeleteAccountHasRent": { + "name": "DeleteAccountHasRent", "subtypes": [], "props": { - "signer_id": "" + "balance": "", + "account_id": "" } }, - "TriesToStake": { - "name": "TriesToStake", + "TriesToUnstake": { + "name": "TriesToUnstake", "subtypes": [], "props": { - "stake": "", - "locked": "", - "account_id": "", - "balance": "" + "account_id": "" } }, - "AddKeyAlreadyExists": { - "name": "AddKeyAlreadyExists", - "subtypes": [], - "props": { - "account_id": "", - "public_key": "" - } + "TxExecutionError": { + "name": "TxExecutionError", + "subtypes": [ + "ActionError", + "InvalidTxError" + ], + "props": {} }, - "InvalidSigner": { - "name": "InvalidSigner", + "AccountAlreadyExists": { + "name": "AccountAlreadyExists", "subtypes": [], "props": { - "signer_id": "" + "account_id": "" } }, - "CreateAccountNotAllowed": { - "name": "CreateAccountNotAllowed", + "NotEnoughBalance": { + "name": "NotEnoughBalance", "subtypes": [], "props": { - "account_id": "", - "predecessor_id": "" + "balance": "", + "signer_id": "", + "cost": "" } }, - "ActionError": { - "name": "ActionError", - "subtypes": [], - "props": {} - }, "InvalidAccessKey": { "name": "InvalidAccessKey", "subtypes": [ @@ -456,13 +465,6 @@ ], "props": {} }, - "TriesToUnstake": { - "name": "TriesToUnstake", - "subtypes": [], - "props": { - "account_id": "" - } - }, "InvalidNonce": { "name": "InvalidNonce", "subtypes": [], @@ -471,17 +473,32 @@ "tx_nonce": "" } }, - "AccountAlreadyExists": { - "name": "AccountAlreadyExists", + "SignerDoesNotExist": { + "name": "SignerDoesNotExist", "subtypes": [], "props": { - "account_id": "" + "signer_id": "" } }, - "InvalidChain": { - "name": "InvalidChain", - "subtypes": [], - "props": {} + "ActionError": { + "name": "ActionError", + "subtypes": [ + "AccountAlreadyExists", + "AccountDoesNotExist", + "CreateAccountNotAllowed", + "ActorNoPermission", + "DeleteKeyDoesNotExist", + "AddKeyAlreadyExists", + "DeleteAccountStaking", + "DeleteAccountHasRent", + "RentUnpaid", + "TriesToUnstake", + "TriesToStake", + "FunctionCall" + ], + "props": { + "index": "" + } }, "AccountDoesNotExist": { "name": "AccountDoesNotExist", @@ -490,46 +507,24 @@ "account_id": "" } }, - "MethodNameMismatch": { - "name": "MethodNameMismatch", - "subtypes": [], - "props": { - "method_name": "" - } - }, - "DeleteAccountHasRent": { - "name": "DeleteAccountHasRent", - "subtypes": [], - "props": { - "account_id": "", - "balance": "" - } - }, - "InvalidReceiver": { - "name": "InvalidReceiver", + "CreateAccountNotAllowed": { + "name": "CreateAccountNotAllowed", "subtypes": [], "props": { - "receiver_id": "" + "predecessor_id": "", + "account_id": "" } }, - "DeleteKeyDoesNotExist": { - "name": "DeleteKeyDoesNotExist", + "Closed": { + "name": "Closed", "subtypes": [], - "props": { - "account_id": "", - "public_key": "" - } + "props": {} }, "Timeout": { "name": "Timeout", "subtypes": [], "props": {} }, - "Closed": { - "name": "Closed", - "subtypes": [], - "props": {} - }, "ServerError": { "name": "ServerError", "subtypes": [ @@ -540,4 +535,4 @@ "props": {} } } -} \ No newline at end of file +} diff --git a/runtime/near-vm-errors/src/lib.rs b/runtime/near-vm-errors/src/lib.rs index 3087dfca8f1..f38bd5e99f8 100644 --- a/runtime/near-vm-errors/src/lib.rs +++ b/runtime/near-vm-errors/src/lib.rs @@ -54,29 +54,23 @@ pub enum CompilationError { pub enum PrepareError { /// Error happened while serializing the module. Serialization, - /// Error happened while deserializing the module. Deserialization, - /// Internal memory declaration has been found in the module. InternalMemoryDeclared, - /// Gas instrumentation failed. /// /// This most likely indicates the module isn't valid. GasInstrumentation, - /// Stack instrumentation failed. /// /// This most likely indicates the module isn't valid. StackHeightInstrumentation, - /// Error happened during instantiation. /// /// This might indicate that `start` function trapped, or module isn't /// instantiable and/or unlinkable. Instantiate, - /// Error creating memory. Memory, } @@ -86,26 +80,47 @@ pub enum PrepareError { )] #[rpc_error_variant = "HostError"] pub enum HostError { + /// String encoding is bad UTF-16 sequence BadUTF16, + /// String encoding is bad UTF-8 sequence BadUTF8, + /// Exceeded the prepaid gas GasExceeded, + /// Exceeded the maximum amount of gas allowed to burn per contract GasLimitExceeded, + /// Exceeded the account balance BalanceExceeded, + /// Tried to call an empty method name EmptyMethodName, + /// Smart contract panicked GuestPanic { panic_msg: String }, + /// IntegerOverflow happened during a contract execution IntegerOverflow, + /// `promise_idx` does not correspond to existing promises InvalidPromiseIndex { promise_idx: u64 }, + /// Actions can only be appended to non-joint promise. CannotAppendActionToJointPromise, + /// Returning joint promise is currently prohibited CannotReturnJointPromise, + /// Accessed invalid promise result index InvalidPromiseResultIndex { result_idx: u64 }, + /// Accessed invalid register id InvalidRegisterId { register_id: u64 }, + /// Iterator `iterator_index` was invalidated after its creation by performing a mutable operation on trie IteratorWasInvalidated { iterator_index: u64 }, + /// Accessed memory outside the bounds MemoryAccessViolation, + /// VM Logic returned an invalid receipt index InvalidReceiptIndex { receipt_index: u64 }, + /// Iterator index `iterator_index` does not exist InvalidIteratorIndex { iterator_index: u64 }, + /// VM Logic returned an invalid account id InvalidAccountId, + /// VM Logic returned an invalid method name InvalidMethodName, + /// VM Logic provided an invalid public key InvalidPublicKey, + /// `method_name` is not allowed in view calls ProhibitedInView { method_name: String }, } diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index f02f62ed193..cd4ba559382 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -16,8 +16,8 @@ use near_crypto::PublicKey; use near_primitives::account::{AccessKey, AccessKeyPermission, Account}; use near_primitives::contract::ContractCode; use near_primitives::errors::{ - ActionError, ActionErrorKind, ExecutionError, InvalidAccessKeyError, InvalidTxError, - RuntimeError, + ActionError, ActionErrorKind, InvalidAccessKeyError, InvalidTxError, RuntimeError, + TxExecutionError, }; use near_primitives::hash::CryptoHash; use near_primitives::receipt::{ActionReceipt, DataReceipt, Receipt, ReceiptEnum, ReceivedData}; @@ -218,10 +218,10 @@ impl Runtime { let transaction = &signed_transaction.transaction; let signer_id = &transaction.signer_id; if !is_valid_account_id(&signer_id) { - return Err(InvalidTxError::InvalidSigner { signer_id: signer_id.clone() }.into()); + return Err(InvalidTxError::InvalidSignerId { signer_id: signer_id.clone() }.into()); } if !is_valid_account_id(&transaction.receiver_id) { - return Err(InvalidTxError::InvalidReceiver { + return Err(InvalidTxError::InvalidReceiverId { receiver_id: transaction.receiver_id.clone(), } .into()); @@ -758,7 +758,7 @@ impl Runtime { ), Ok(ReturnData::Value(data)) => ExecutionStatus::SuccessValue(data), Ok(ReturnData::None) => ExecutionStatus::SuccessValue(vec![]), - Err(e) => ExecutionStatus::Failure(ExecutionError::Action(e)), + Err(e) => ExecutionStatus::Failure(TxExecutionError::ActionError(e)), }; Self::print_log(&result.logs); diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index 39daeeb0425..ca211b3e127 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -5,7 +5,7 @@ use near_crypto::{InMemorySigner, KeyType}; use near_jsonrpc::ServerError; use near_primitives::account::{AccessKey, AccessKeyPermission, FunctionCallPermission}; use near_primitives::errors::{ - ActionError, ActionErrorKind, ExecutionError, InvalidAccessKeyError, InvalidTxError, + ActionError, ActionErrorKind, TxExecutionError, InvalidAccessKeyError, InvalidTxError, }; use near_primitives::hash::hash; use near_primitives::serialize::to_base64; @@ -514,8 +514,8 @@ pub fn test_create_account_failure_invalid_name(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - ServerError::TxExecutionError(ExecutionError::InvalidTx( - InvalidTxError::InvalidReceiver { receiver_id: invalid_account_name.to_string() } + ServerError::TxExecutionError(TxExecutionError::InvalidTxError( + InvalidTxError::InvalidReceiverId { receiver_id: invalid_account_name.to_string() } )) ); } @@ -883,9 +883,11 @@ pub fn test_access_key_smart_contract_reject_method_name(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - ServerError::TxExecutionError(ExecutionError::InvalidTx(InvalidTxError::InvalidAccessKey( - InvalidAccessKeyError::MethodNameMismatch { method_name: "run_test".to_string() } - ))) + ServerError::TxExecutionError(TxExecutionError::InvalidTxError( + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::MethodNameMismatch { + method_name: "run_test".to_string() + }) + )) ); } @@ -916,12 +918,12 @@ pub fn test_access_key_smart_contract_reject_contract_id(node: impl Node) { .unwrap_err(); assert_eq!( transaction_result, - ServerError::TxExecutionError(ExecutionError::InvalidTx(InvalidTxError::InvalidAccessKey( - InvalidAccessKeyError::ReceiverMismatch { + ServerError::TxExecutionError(TxExecutionError::InvalidTxError( + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ReceiverMismatch { tx_receiver: eve_dot_alice_account(), ak_receiver: bob_account() - } - ))) + }) + )) ); } @@ -944,9 +946,9 @@ pub fn test_access_key_reject_non_function_call(node: impl Node) { node_user.delete_key(account_id.clone(), node.signer().public_key()).unwrap_err(); assert_eq!( transaction_result, - ServerError::TxExecutionError(ExecutionError::InvalidTx(InvalidTxError::InvalidAccessKey( - InvalidAccessKeyError::ActionError - ))) + ServerError::TxExecutionError(TxExecutionError::InvalidTxError( + InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ActionError) + )) ); } @@ -1047,7 +1049,7 @@ fn test_stake_fail_not_enough_rent_with_balance(node: impl Node, initial_balance assert_matches!( &transaction_result.status, FinalExecutionStatus::Failure(e) => match &e { - &ExecutionError::Action(action_err) => + &TxExecutionError::ActionError(action_err) => match action_err.kind { ActionErrorKind::RentUnpaid{..} => {}, _ => panic!("should be RentUnpaid") diff --git a/test-utils/testlib/src/user/runtime_user.rs b/test-utils/testlib/src/user/runtime_user.rs index 337e8c7b1e4..9774fa5eeae 100644 --- a/test-utils/testlib/src/user/runtime_user.rs +++ b/test-utils/testlib/src/user/runtime_user.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, RwLock}; use near_crypto::{PublicKey, Signer}; use near_jsonrpc::ServerError; -use near_primitives::errors::{ExecutionError, RuntimeError}; +use near_primitives::errors::{RuntimeError, TxExecutionError}; use near_primitives::hash::CryptoHash; use near_primitives::receipt::Receipt; use near_primitives::transaction::SignedTransaction; @@ -88,7 +88,7 @@ impl RuntimeUser { ) .map_err(|e| match e { RuntimeError::InvalidTxError(e) => { - ServerError::TxExecutionError(ExecutionError::InvalidTx(e)) + ServerError::TxExecutionError(TxExecutionError::InvalidTxError(e)) } RuntimeError::BalanceMismatch(e) => panic!("{}", e), RuntimeError::StorageError(e) => panic!("Storage error {:?}", e), From 9694cf650e1717e3961ee99f3ab1f5b2fdd3f861 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 16:45:48 +0300 Subject: [PATCH 27/48] fix formatting --- test-utils/testlib/src/standard_test_cases.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index ca211b3e127..57727d69b2b 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -5,7 +5,7 @@ use near_crypto::{InMemorySigner, KeyType}; use near_jsonrpc::ServerError; use near_primitives::account::{AccessKey, AccessKeyPermission, FunctionCallPermission}; use near_primitives::errors::{ - ActionError, ActionErrorKind, TxExecutionError, InvalidAccessKeyError, InvalidTxError, + ActionError, ActionErrorKind, InvalidAccessKeyError, InvalidTxError, TxExecutionError, }; use near_primitives::hash::hash; use near_primitives::serialize::to_base64; From 709076361fbd734b819c73f543f2e6944e6f67c7 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 21:46:07 +0300 Subject: [PATCH 28/48] make schema deterministic --- tools/rpctypegen/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 78ed7557663..e8e67cea68e 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -5,7 +5,7 @@ use proc_macro::TokenStream; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::BTreeMap; use syn::{ parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Lit, Meta, MetaNameValue, @@ -26,7 +26,7 @@ fn merge(a: &mut Value, b: &Value) { #[derive(Default, Debug, Deserialize, Serialize)] struct Schema { - pub schema: HashMap, + pub schema: BTreeMap, } impl Drop for Schema { @@ -57,7 +57,7 @@ struct ErrorType { /// Names of subtypes of the error pub subtypes: Vec, /// An error input name and a type - pub props: HashMap, + pub props: BTreeMap, } thread_local!(static SCHEMA: RefCell = RefCell::new(Schema::default())); @@ -75,14 +75,14 @@ fn parse_rpc_error_variant(input: &DeriveInput) -> Option { } fn error_type_name<'a>( - schema: &'a mut HashMap, + schema: &'a mut BTreeMap, name: String, ) -> &'a mut ErrorType { let error_type = ErrorType { name: name.clone(), ..Default::default() }; schema.entry(name.clone()).or_insert(error_type) } -fn parse_error_type(schema: &mut HashMap, input: &DeriveInput) { +fn parse_error_type(schema: &mut BTreeMap, input: &DeriveInput) { let name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); match &input.data { Data::Enum(DataEnum { ref variants, .. }) => { From c15391cff2ef4e66cc4f906641e3e357549f7d26 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 21:52:05 +0300 Subject: [PATCH 29/48] Update core/primitives/src/errors.rs Co-Authored-By: Evgeny Kuzyakov --- core/primitives/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 4c3340f63f4..03d6368cf2b 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -44,7 +44,7 @@ impl From for TxExecutionError { /// Error returned from `Runtime::apply` #[derive(Debug, Clone, PartialEq, Eq)] pub enum RuntimeError { - /// An integeroverflow during counting ApplyStats + /// An unexpected integer overflow occurred. The likely issue is an invalid state or the transition. UnexpectedIntegerOverflow, /// An error happened during TX execution InvalidTxError(InvalidTxError), From d3f7e7bbf37590338376dc98aa72171340ba9707 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 21:52:29 +0300 Subject: [PATCH 30/48] Update core/primitives/src/errors.rs Co-Authored-By: Evgeny Kuzyakov --- core/primitives/src/errors.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 03d6368cf2b..3ea9629ec21 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -46,7 +46,8 @@ impl From for TxExecutionError { pub enum RuntimeError { /// An unexpected integer overflow occurred. The likely issue is an invalid state or the transition. UnexpectedIntegerOverflow, - /// An error happened during TX execution + /// An error happened during TX verification and account charging. It's likely the chunk is invalid. + /// and should be challenged. InvalidTxError(InvalidTxError), /// Unexpected error which is typically related to the node storage corruption StorageError(StorageError), From 6f30669057a09ccbadf3a7954ca2702b12496612 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 21:53:35 +0300 Subject: [PATCH 31/48] Update core/primitives/src/errors.rs Co-Authored-By: Evgeny Kuzyakov --- core/primitives/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 3ea9629ec21..0f942f943ae 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -133,7 +133,7 @@ pub enum InvalidAccessKeyError { MethodNameMismatch { method_name: String }, /// The used access key requires exactly one FunctionCall action ActionError, - /// Access Key does not have enough balance for transaction + /// Access Key does not have enough allowance to cover transaction cost NotEnoughAllowance { account_id: AccountId, public_key: PublicKey, From 3c8f755ea3ce1824077af1e0e1424f8aca442672 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 22:05:49 +0300 Subject: [PATCH 32/48] Apply suggestions from code review Co-Authored-By: Evgeny Kuzyakov --- core/primitives/src/errors.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 0f942f943ae..1edabb5e106 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -112,7 +112,7 @@ pub enum InvalidTxError { #[serde(with = "u128_dec_format")] amount: Balance, }, - /// Transaction gas or balance cost is too high + /// An integer overflow occurred during transaction cost estimation. CostOverflow, /// Transaction parent block hash doesn't belong to the current chain InvalidChain, @@ -125,7 +125,7 @@ pub enum InvalidTxError { )] #[rpc_error_variant = "InvalidAccessKey"] pub enum InvalidAccessKeyError { - /// Unable to found an access key for account_id identified by a public_key + /// The access key identified by the public_key doesn't exist for the account AccessKeyNotFound { account_id: AccountId, public_key: PublicKey }, /// Transaction receiver_id doesn't match the access key receiver_id ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, @@ -200,7 +200,7 @@ pub enum ActionErrorKind { RentUnpaid { /// An account which is required to pay the rent account_id: AccountId, - /// Required balance to cover the state rent + /// Rent due to pay. #[serde(with = "u128_dec_format")] amount: Balance, }, @@ -208,7 +208,7 @@ pub enum ActionErrorKind { TriesToUnstake { account_id: AccountId, }, - /// Account tries to stake but it is already staked. + /// The account doesn't have enough balance to increase the stake. TriesToStake { account_id: AccountId, #[serde(with = "u128_dec_format")] @@ -218,6 +218,7 @@ pub enum ActionErrorKind { #[serde(with = "u128_dec_format")] balance: Balance, }, + /// An error occurred during a FunctionCall Action. FunctionCall(VMError), } From 006bdf80d3aadee3af6d82db8b48de44845ba955 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 22:31:09 +0300 Subject: [PATCH 33/48] return ActionErrorKind::ActorNoPermission on AccountDelete and not sir --- core/primitives/src/errors.rs | 4 +++- runtime/runtime/src/actions.rs | 15 ++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 4c3340f63f4..2712cc57f47 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -143,6 +143,7 @@ pub enum InvalidAccessKeyError { }, } +/// An error happened during Acton execution #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] @@ -170,7 +171,8 @@ pub enum ActionErrorKind { account_id: AccountId, predecessor_id: AccountId, }, - /// Administrative actions like DeployContract, Stake, AddKey, DeleteKey. can be proceed only if sender=receiver. + /// Administrative actions like DeployContract, Stake, AddKey, DeleteKey. can be proceed only if sender=receiver + /// or the first TX action is a CreateAccount action ActorNoPermission { account_id: AccountId, actor_id: AccountId, diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index 85b22c57524..f3db9461541 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -399,13 +399,14 @@ pub(crate) fn check_actor_permissions( } .into()); } - if actor_id != account_id - && check_rent( - account_id, - account.as_mut().unwrap(), - config, - apply_state.epoch_length, - ) + if actor_id != account_id { + return Err(ActionErrorKind::ActorNoPermission { + account_id: account_id.clone(), + actor_id: actor_id.clone(), + } + .into()); + } + if check_rent(account_id, account.as_mut().unwrap(), config, apply_state.epoch_length) .is_ok() { return Err(ActionErrorKind::DeleteAccountHasRent { From 4c476f1492abbe5b0be9ef3181b3d68dbcf1ebbd Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 22:33:44 +0300 Subject: [PATCH 34/48] StorageError doc comment addition --- core/primitives/src/errors.rs | 43 ++++++++++------------------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 07a5f068b02..a411e7a53a6 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -44,12 +44,13 @@ impl From for TxExecutionError { /// Error returned from `Runtime::apply` #[derive(Debug, Clone, PartialEq, Eq)] pub enum RuntimeError { - /// An unexpected integer overflow occurred. The likely issue is an invalid state or the transition. + /// An unexpected integer overflow occurred. The likely issue is an invalid state or the transition. UnexpectedIntegerOverflow, /// An error happened during TX verification and account charging. It's likely the chunk is invalid. - /// and should be challenged. + /// and should be challenged. InvalidTxError(InvalidTxError), - /// Unexpected error which is typically related to the node storage corruption + /// Unexpected error which is typically related to the node storage corruption.account + /// That it's possible the input state is invalid or malicious. StorageError(StorageError), /// An error happens if `check_balance` fails BalanceMismatch(BalanceMismatchError), @@ -160,38 +161,20 @@ pub struct ActionError { #[rpc_error_variant = "ActionError"] pub enum ActionErrorKind { /// Happens when CreateAccount action tries to create an account with account_id which is already exists in the storage - AccountAlreadyExists { - account_id: AccountId, - }, + AccountAlreadyExists { account_id: AccountId }, /// Happens when TX receiver_id doesn't exist (but action is not Action::CreateAccount) - AccountDoesNotExist { - account_id: AccountId, - }, + AccountDoesNotExist { account_id: AccountId }, /// A newly created account must be under a namespace of the creator account - CreateAccountNotAllowed { - account_id: AccountId, - predecessor_id: AccountId, - }, + CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId }, /// Administrative actions like DeployContract, Stake, AddKey, DeleteKey. can be proceed only if sender=receiver /// or the first TX action is a CreateAccount action - ActorNoPermission { - account_id: AccountId, - actor_id: AccountId, - }, + ActorNoPermission { account_id: AccountId, actor_id: AccountId }, /// Account tries to remove an access key that doesn't exist - DeleteKeyDoesNotExist { - account_id: AccountId, - public_key: PublicKey, - }, + DeleteKeyDoesNotExist { account_id: AccountId, public_key: PublicKey }, /// The public key is already used for an existing access key - AddKeyAlreadyExists { - account_id: AccountId, - public_key: PublicKey, - }, + AddKeyAlreadyExists { account_id: AccountId, public_key: PublicKey }, /// Account is staking and can not be deleted - DeleteAccountStaking { - account_id: AccountId, - }, + DeleteAccountStaking { account_id: AccountId }, /// Have to cover rent before delete an account DeleteAccountHasRent { account_id: AccountId, @@ -207,9 +190,7 @@ pub enum ActionErrorKind { amount: Balance, }, /// Account is not yet staked, but tries to unstake - TriesToUnstake { - account_id: AccountId, - }, + TriesToUnstake { account_id: AccountId }, /// The account doesn't have enough balance to increase the stake. TriesToStake { account_id: AccountId, From 75f53834b2c1d44a7324514f2f34a82f086d1263 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 22:36:16 +0300 Subject: [PATCH 35/48] update BalanceMismatch doc comment --- core/primitives/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index a411e7a53a6..13a02ccb963 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -52,7 +52,7 @@ pub enum RuntimeError { /// Unexpected error which is typically related to the node storage corruption.account /// That it's possible the input state is invalid or malicious. StorageError(StorageError), - /// An error happens if `check_balance` fails + /// An error happens if `check_balance` fails, which is likely an indication of an invalid state. BalanceMismatch(BalanceMismatchError), } From 90c1f4430a66a5b0a3ddda9b23f1ab6a272bfbe6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 22:39:13 +0300 Subject: [PATCH 36/48] Apply suggestions from code review Co-Authored-By: Evgeny Kuzyakov --- core/primitives/src/errors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 13a02ccb963..abd318f335e 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -97,7 +97,7 @@ pub enum InvalidTxError { InvalidReceiverId { receiver_id: AccountId }, /// TX signature is not valid InvalidSignature, - /// Account have not enough tokens to cover TX cost + /// Account does not have enough balance to cover TX cost NotEnoughBalance { signer_id: AccountId, #[serde(with = "u128_dec_format")] @@ -181,7 +181,7 @@ pub enum ActionErrorKind { #[serde(with = "u128_dec_format")] balance: Balance, }, - /// ActionReceipt can't be applied for an account. Account state rent is not payed. + /// ActionReceipt can't be completed, because the remaining balance will not be enough to pay rent. RentUnpaid { /// An account which is required to pay the rent account_id: AccountId, From 1a7eb067eacc1ae57eaa57ecd2e7368bfc83838c Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 13 Jan 2020 23:34:43 +0300 Subject: [PATCH 37/48] ActionError index doc added --- core/primitives/src/errors.rs | 17 ++++++++++------- runtime/runtime/src/lib.rs | 1 - 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index abd318f335e..c3e2540be5c 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -97,7 +97,7 @@ pub enum InvalidTxError { InvalidReceiverId { receiver_id: AccountId }, /// TX signature is not valid InvalidSignature, - /// Account does not have enough balance to cover TX cost + /// Account does not have enough balance to cover TX cost NotEnoughBalance { signer_id: AccountId, #[serde(with = "u128_dec_format")] @@ -126,13 +126,13 @@ pub enum InvalidTxError { )] #[rpc_error_variant = "InvalidAccessKey"] pub enum InvalidAccessKeyError { - /// The access key identified by the public_key doesn't exist for the account + /// The access key identified by the `public_key` doesn't exist for the account AccessKeyNotFound { account_id: AccountId, public_key: PublicKey }, - /// Transaction receiver_id doesn't match the access key receiver_id + /// Transaction `receiver_id` doesn't match the access key receiver_id ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, /// Transaction method name isn't allowed by the access key MethodNameMismatch { method_name: String }, - /// The used access key requires exactly one FunctionCall action + /// The used access key requires exactly one `FunctionCall` action ActionError, /// Access Key does not have enough allowance to cover transaction cost NotEnoughAllowance { @@ -151,7 +151,10 @@ pub enum InvalidAccessKeyError { )] #[rpc_error_variant = "ActionError"] pub struct ActionError { + /// Index of the failed action in the transaction. + /// Action index is not defined if ActionError.kind is `ActionErrorKind::RentUnpaid` pub index: Option, + /// The kind of ActionError happened pub kind: ActionErrorKind, } @@ -166,8 +169,8 @@ pub enum ActionErrorKind { AccountDoesNotExist { account_id: AccountId }, /// A newly created account must be under a namespace of the creator account CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId }, - /// Administrative actions like DeployContract, Stake, AddKey, DeleteKey. can be proceed only if sender=receiver - /// or the first TX action is a CreateAccount action + /// Administrative actions like `DeployContract`, `Stake`, `AddKey`, `DeleteKey`. can be proceed only if sender=receiver + /// or the first TX action is a `CreateAccount` action ActorNoPermission { account_id: AccountId, actor_id: AccountId }, /// Account tries to remove an access key that doesn't exist DeleteKeyDoesNotExist { account_id: AccountId, public_key: PublicKey }, @@ -201,7 +204,7 @@ pub enum ActionErrorKind { #[serde(with = "u128_dec_format")] balance: Balance, }, - /// An error occurred during a FunctionCall Action. + /// An error occurred during a `FunctionCall` Action. FunctionCall(VMError), } diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index cd4ba559382..3f4692b2dd3 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -621,7 +621,6 @@ impl Runtime { { result.merge(ActionResult { result: Err(ActionError { - // TODO: looks like this shouldn't be in a ActionError category (which action where failed?) index: None, kind: ActionErrorKind::RentUnpaid { account_id: account_id.clone(), From a2ae077daf3a956b8a93ffcf4516206c465fa7f5 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 14 Jan 2020 01:14:55 +0300 Subject: [PATCH 38/48] fix check_actor_permissions for DeleteAccount --- Cargo.lock | 4 ++-- core/primitives/src/errors.rs | 2 +- runtime/runtime/src/actions.rs | 15 +++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8f02e2fb0b..9fe8d5c63bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2218,8 +2218,8 @@ dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index c3e2540be5c..9014e196cb9 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -178,7 +178,7 @@ pub enum ActionErrorKind { AddKeyAlreadyExists { account_id: AccountId, public_key: PublicKey }, /// Account is staking and can not be deleted DeleteAccountStaking { account_id: AccountId }, - /// Have to cover rent before delete an account + /// Foreign sender (sender=!receiver) can delete an account only if a target account hasn't enough tokens to pay rent DeleteAccountHasRent { account_id: AccountId, #[serde(with = "u128_dec_format")] diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index f3db9461541..85b22c57524 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -399,14 +399,13 @@ pub(crate) fn check_actor_permissions( } .into()); } - if actor_id != account_id { - return Err(ActionErrorKind::ActorNoPermission { - account_id: account_id.clone(), - actor_id: actor_id.clone(), - } - .into()); - } - if check_rent(account_id, account.as_mut().unwrap(), config, apply_state.epoch_length) + if actor_id != account_id + && check_rent( + account_id, + account.as_mut().unwrap(), + config, + apply_state.epoch_length, + ) .is_ok() { return Err(ActionErrorKind::DeleteAccountHasRent { From 879dffe206e381e766592ede74a537d5363dd13d Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 14 Jan 2020 01:19:37 +0300 Subject: [PATCH 39/48] no cargo clean in build_errors_schema.sh and move to scripts --- build_errors_schema.sh | 3 --- scripts/build_errors_schema.sh | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100755 build_errors_schema.sh create mode 100755 scripts/build_errors_schema.sh diff --git a/build_errors_schema.sh b/build_errors_schema.sh deleted file mode 100755 index 3890d3892f7..00000000000 --- a/build_errors_schema.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cargo clean && cargo build --manifest-path near/Cargo.toml -cp target/rpc_errors_schema.json res/rpc_errors_schema.json diff --git a/scripts/build_errors_schema.sh b/scripts/build_errors_schema.sh new file mode 100755 index 00000000000..32f87d6b9fa --- /dev/null +++ b/scripts/build_errors_schema.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cargo build --manifest-path near/Cargo.toml +cp ../target/rpc_errors_schema.json ../res/rpc_errors_schema.json From c641f4a9bc44db590eff58bd4e592b7a622a1a78 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 14 Jan 2020 15:29:19 +0300 Subject: [PATCH 40/48] feature-gated schema dump generation --- chain/jsonrpc/Cargo.toml | 3 +++ core/primitives/Cargo.toml | 1 + near/Cargo.toml | 3 +++ runtime/near-vm-errors/Cargo.toml | 5 ++++- runtime/runtime/Cargo.toml | 1 + scripts/build_errors_schema.sh | 2 +- tools/rpctypegen/Cargo.toml | 3 +++ tools/rpctypegen/src/lib.rs | 2 ++ 8 files changed, 18 insertions(+), 2 deletions(-) diff --git a/chain/jsonrpc/Cargo.toml b/chain/jsonrpc/Cargo.toml index 420974ac6a5..7100e4ad1ed 100644 --- a/chain/jsonrpc/Cargo.toml +++ b/chain/jsonrpc/Cargo.toml @@ -34,3 +34,6 @@ near-network = { path = "../network" } near-pool = { path = "../pool" } near-jsonrpc-client = { path = "client" } near-rpc-error-macro = { path = "../../tools/rpctypegen" } + +[features] +dump_errors_schema = ["near-rpc-error-macro/dump_errors_schema"] diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index 48cdabacbeb..6adca19b4c5 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -31,6 +31,7 @@ near-rpc-error-macro = { path = "../../tools/rpctypegen" } [features] default = ["jemallocator"] +dump_errors_schema = ["near-rpc-error-macro/dump_errors_schema"] [dev-dependencies] bencher = "0.1.5" diff --git a/near/Cargo.toml b/near/Cargo.toml index 95e5eda528b..b861cacf2ee 100644 --- a/near/Cargo.toml +++ b/near/Cargo.toml @@ -40,3 +40,6 @@ near-epoch-manager = { path = "../chain/epoch_manager" } [dev-dependencies] tempdir = "0.3" testlib = { path = "../test-utils/testlib" } + +[features] +dump_errors_schema = ["near-primitives/dump_errors_schema", "near-jsonrpc/dump_errors_schema", "node-runtime/dump_errors_schema"] diff --git a/runtime/near-vm-errors/Cargo.toml b/runtime/near-vm-errors/Cargo.toml index c8aaf577539..bf3b940a2db 100644 --- a/runtime/near-vm-errors/Cargo.toml +++ b/runtime/near-vm-errors/Cargo.toml @@ -13,6 +13,9 @@ Error that can occur inside Near Runtime encapsulated in a separate crate. Might """ [dependencies] -near-rpc-error-macro = { path = "../../tools/rpctypegen" } borsh = "0.2.10" +near-rpc-error-macro = { path = "../../tools/rpctypegen" } serde = { version = "1.0", features = ["derive"] } + +[features] +dump_errors_schema = ["near-rpc-error-macro/dump_errors_schema"] diff --git a/runtime/runtime/Cargo.toml b/runtime/runtime/Cargo.toml index a87519b6b0f..73e3e057201 100644 --- a/runtime/runtime/Cargo.toml +++ b/runtime/runtime/Cargo.toml @@ -30,6 +30,7 @@ near-vm-errors = { path = "../../runtime/near-vm-errors" } [features] default = [] +dump_errors_schema = ["near-vm-errors/dump_errors_schema"] # Use this feature to enable counting of fees and costs applied. costs_counting = ["near-vm-logic/costs_counting", "near-vm-runner/costs_counting"] diff --git a/scripts/build_errors_schema.sh b/scripts/build_errors_schema.sh index 32f87d6b9fa..b7f1622d138 100755 --- a/scripts/build_errors_schema.sh +++ b/scripts/build_errors_schema.sh @@ -1,3 +1,3 @@ #!/bin/bash -cargo build --manifest-path near/Cargo.toml +cargo build --features dump_errors_schema --manifest-path near/Cargo.toml cp ../target/rpc_errors_schema.json ../res/rpc_errors_schema.json diff --git a/tools/rpctypegen/Cargo.toml b/tools/rpctypegen/Cargo.toml index 13ce15ff8ae..003c14278a1 100644 --- a/tools/rpctypegen/Cargo.toml +++ b/tools/rpctypegen/Cargo.toml @@ -13,3 +13,6 @@ serde_json = {version = "1.0", features = ["preserve_order"]} syn = { version = "1.0", features = ["full", "extra-traits"]} quote = "1.0" proc-macro2 = "1.0" + +[features] +dump_errors_schema = [] diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index e8e67cea68e..1c95ac69590 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -11,6 +11,7 @@ use syn::{ Lit, Meta, MetaNameValue, }; +#[cfg(feature = "dump_errors_schema")] fn merge(a: &mut Value, b: &Value) { match (a, b) { (&mut Value::Object(ref mut a), &Value::Object(ref b)) => { @@ -29,6 +30,7 @@ struct Schema { pub schema: BTreeMap, } +#[cfg(feature = "dump_errors_schema")] impl Drop for Schema { fn drop(&mut self) { // std::env::var("CARGO_TARGET_DIR") doesn't exists From 18ccdf344084724494b9f02010a636f69c418c89 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 17 Jan 2020 17:34:46 +0300 Subject: [PATCH 41/48] Update tools/rpctypegen/Cargo.toml Co-Authored-By: Maksym Zavershynskyi <35039879+nearmax@users.noreply.github.com> --- tools/rpctypegen/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rpctypegen/Cargo.toml b/tools/rpctypegen/Cargo.toml index 003c14278a1..93c719623e7 100644 --- a/tools/rpctypegen/Cargo.toml +++ b/tools/rpctypegen/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "near-rpc-error-macro" version = "0.1.0" -authors = ["Alexey "] +authors = ["Near Inc "] edition = "2018" [lib] From 361319b8ea1674b5405425790385ec60c0de3fa9 Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 20 Jan 2020 15:50:32 +0300 Subject: [PATCH 42/48] removed rpc_error_variant attribute --- chain/jsonrpc/src/lib.rs | 1 - core/primitives/src/errors.rs | 21 +- near/src/runtime.rs | 2 +- res/rpc_errors_schema.json | 634 ++++++++++-------- runtime/near-vm-errors/src/lib.rs | 12 +- runtime/near-vm-runner/src/errors.rs | 6 +- runtime/near-vm-runner/src/runner.rs | 8 +- .../near-vm-runner/tests/test_error_cases.rs | 12 +- runtime/runtime/src/balance_checker.rs | 2 +- runtime/runtime/src/lib.rs | 34 +- scripts/build_errors_schema.sh | 2 +- test-utils/testlib/src/standard_test_cases.rs | 12 +- test-utils/testlib/src/user/runtime_user.rs | 2 +- tests/test_errors.rs | 2 +- tools/rpctypegen/src/lib.rs | 20 +- 15 files changed, 403 insertions(+), 367 deletions(-) diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index 8c49909428e..e8a7ee848c8 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -121,7 +121,6 @@ fn parse_hash(params: Option) -> Result { /// A general Server Error #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, near_rpc_error_macro::RpcError)] -#[rpc_error_variant = "ServerError"] pub enum ServerError { TxExecutionError(TxExecutionError), Timeout, diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 9014e196cb9..83a02933726 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -12,7 +12,6 @@ use near_vm_errors::VMError; #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "TxExecutionError"] pub enum TxExecutionError { /// An error happened during Acton execution ActionError(ActionError), @@ -53,7 +52,7 @@ pub enum RuntimeError { /// That it's possible the input state is invalid or malicious. StorageError(StorageError), /// An error happens if `check_balance` fails, which is likely an indication of an invalid state. - BalanceMismatch(BalanceMismatchError), + BalanceMismatchError(BalanceMismatchError), } /// Internal @@ -83,10 +82,9 @@ impl std::error::Error for StorageError {} #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "InvalidTxError"] pub enum InvalidTxError { /// Happens if a wrong AccessKey used or AccessKey has not enough permissions - InvalidAccessKey(InvalidAccessKeyError), + InvalidAccessKeyError(InvalidAccessKeyError), /// TX signer_id is not in a valid format or not satisfy requirements see `near_core::primitives::utils::is_valid_account_id` InvalidSignerId { signer_id: AccountId }, /// TX signer_id is not found in a storage @@ -124,7 +122,6 @@ pub enum InvalidTxError { #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "InvalidAccessKey"] pub enum InvalidAccessKeyError { /// The access key identified by the `public_key` doesn't exist for the account AccessKeyNotFound { account_id: AccountId, public_key: PublicKey }, @@ -149,7 +146,6 @@ pub enum InvalidAccessKeyError { #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "ActionError"] pub struct ActionError { /// Index of the failed action in the transaction. /// Action index is not defined if ActionError.kind is `ActionErrorKind::RentUnpaid` @@ -161,7 +157,6 @@ pub struct ActionError { #[derive( BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "ActionError"] pub enum ActionErrorKind { /// Happens when CreateAccount action tries to create an account with account_id which is already exists in the storage AccountAlreadyExists { account_id: AccountId }, @@ -223,7 +218,7 @@ impl Display for InvalidTxError { InvalidTxError::SignerDoesNotExist{signer_id} => { write!(f, "Signer {:?} does not exist", signer_id) } - InvalidTxError::InvalidAccessKey(access_key_error) => access_key_error.fmt(f), + InvalidTxError::InvalidAccessKeyError(access_key_error) => access_key_error.fmt(f), InvalidTxError::InvalidNonce{tx_nonce, ak_nonce} => write!( f, "Transaction nonce {} must be larger than nonce of the used access key {}", @@ -258,7 +253,7 @@ impl Display for InvalidTxError { impl From for InvalidTxError { fn from(error: InvalidAccessKeyError) -> Self { - InvalidTxError::InvalidAccessKey(error) + InvalidTxError::InvalidAccessKeyError(error) } } @@ -298,7 +293,9 @@ impl Display for InvalidAccessKeyError { } /// Happens when the input balance doesn't match the output balance in Runtime apply. -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive( + BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, RpcError, +)] pub struct BalanceMismatchError { // Input balances #[serde(with = "u128_dec_format")] @@ -385,7 +382,7 @@ impl Display for BalanceMismatchError { } } -#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] +#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq, Eq)] pub struct IntegerOverflowError; impl From for InvalidTxError { @@ -408,7 +405,7 @@ impl From for RuntimeError { impl From for RuntimeError { fn from(e: BalanceMismatchError) -> Self { - RuntimeError::BalanceMismatch(e) + RuntimeError::BalanceMismatchError(e) } } diff --git a/near/src/runtime.rs b/near/src/runtime.rs index 69ec7fccfb3..539b496087c 100644 --- a/near/src/runtime.rs +++ b/near/src/runtime.rs @@ -304,7 +304,7 @@ impl NightshadeRuntime { ) .map_err(|e| match e { RuntimeError::InvalidTxError(_) => ErrorKind::InvalidTransactions, - RuntimeError::BalanceMismatch(e) => panic!("{}", e), + RuntimeError::BalanceMismatchError(e) => panic!("{}", e), // TODO: process gracefully RuntimeError::UnexpectedIntegerOverflow => { panic!("RuntimeError::UnexpectedIntegerOverflow") diff --git a/res/rpc_errors_schema.json b/res/rpc_errors_schema.json index 2d5f0281fa7..c9c8f7b24d7 100644 --- a/res/rpc_errors_schema.json +++ b/res/rpc_errors_schema.json @@ -1,78 +1,77 @@ { "schema": { - "InvalidIteratorIndex": { - "name": "InvalidIteratorIndex", - "subtypes": [], - "props": { - "iterator_index": "" - } - }, - "InvalidPublicKey": { - "name": "InvalidPublicKey", + "BadUTF16": { + "name": "BadUTF16", "subtypes": [], "props": {} }, - "CannotAppendActionToJointPromise": { - "name": "CannotAppendActionToJointPromise", + "BadUTF8": { + "name": "BadUTF8", "subtypes": [], "props": {} }, - "Instantiate": { - "name": "Instantiate", + "BalanceExceeded": { + "name": "BalanceExceeded", "subtypes": [], "props": {} }, - "MemoryAccessViolation": { - "name": "MemoryAccessViolation", + "CannotAppendActionToJointPromise": { + "name": "CannotAppendActionToJointPromise", "subtypes": [], "props": {} }, - "BadUTF16": { - "name": "BadUTF16", + "CannotReturnJointPromise": { + "name": "CannotReturnJointPromise", "subtypes": [], "props": {} }, - "LinkError": { - "name": "LinkError", + "CodeDoesNotExist": { + "name": "CodeDoesNotExist", "subtypes": [], "props": { - "msg": "" + "account_id": "" } }, - "StackHeightInstrumentation": { - "name": "StackHeightInstrumentation", - "subtypes": [], + "CompilationError": { + "name": "CompilationError", + "subtypes": [ + "CodeDoesNotExist", + "PrepareError", + "WasmerCompileError" + ], "props": {} }, - "WasmerCompileError": { - "name": "WasmerCompileError", + "Deserialization": { + "name": "Deserialization", "subtypes": [], - "props": { - "msg": "" - } + "props": {} }, - "Memory": { - "name": "Memory", + "EmptyMethodName": { + "name": "EmptyMethodName", "subtypes": [], "props": {} }, - "InvalidAccountId": { - "name": "InvalidAccountId", - "subtypes": [], + "FunctionCall": { + "name": "FunctionCall", + "subtypes": [ + "FunctionExecError", + "StorageError" + ], "props": {} }, - "ResolveError": { - "name": "ResolveError", + "FunctionExecError": { + "name": "FunctionExecError", "subtypes": [ - "MethodEmptyName", - "MethodUTF8Error", - "MethodNotFound", - "MethodInvalidSignature" + "CompilationError", + "LinkError", + "MethodResolveError", + "WasmTrap", + "HostError" ], "props": {} }, - "InternalMemoryDeclared": { - "name": "InternalMemoryDeclared", + "GasExceeded": { + "name": "GasExceeded", "subtypes": [], "props": {} }, @@ -81,118 +80,141 @@ "subtypes": [], "props": {} }, - "MethodUTF8Error": { - "name": "MethodUTF8Error", + "GasLimitExceeded": { + "name": "GasLimitExceeded", "subtypes": [], "props": {} }, - "PrepareError": { - "name": "PrepareError", + "GuestPanic": { + "name": "GuestPanic", + "subtypes": [], + "props": { + "panic_msg": "" + } + }, + "HostError": { + "name": "HostError", "subtypes": [ - "Serialization", - "Deserialization", - "InternalMemoryDeclared", - "GasInstrumentation", - "StackHeightInstrumentation", - "Instantiate", - "Memory" + "BadUTF16", + "BadUTF8", + "GasExceeded", + "GasLimitExceeded", + "BalanceExceeded", + "EmptyMethodName", + "GuestPanic", + "IntegerOverflow", + "InvalidPromiseIndex", + "CannotAppendActionToJointPromise", + "CannotReturnJointPromise", + "InvalidPromiseResultIndex", + "InvalidRegisterId", + "IteratorWasInvalidated", + "MemoryAccessViolation", + "InvalidReceiptIndex", + "InvalidIteratorIndex", + "InvalidAccountId", + "InvalidMethodName", + "InvalidPublicKey", + "ProhibitedInView" ], "props": {} }, - "CannotReturnJointPromise": { - "name": "CannotReturnJointPromise", + "Instantiate": { + "name": "Instantiate", "subtypes": [], "props": {} }, - "MethodInvalidSignature": { - "name": "MethodInvalidSignature", + "IntegerOverflow": { + "name": "IntegerOverflow", "subtypes": [], "props": {} }, - "InvalidRegisterId": { - "name": "InvalidRegisterId", + "InternalMemoryDeclared": { + "name": "InternalMemoryDeclared", "subtypes": [], - "props": { - "register_id": "" - } + "props": {} }, - "GasExceeded": { - "name": "GasExceeded", + "InvalidAccountId": { + "name": "InvalidAccountId", "subtypes": [], "props": {} }, - "FunctionCall": { - "name": "FunctionCall", - "subtypes": [ - "FunctionExecError", - "StorageError" - ], - "props": {} + "InvalidIteratorIndex": { + "name": "InvalidIteratorIndex", + "subtypes": [], + "props": { + "iterator_index": "" + } }, - "Deserialization": { - "name": "Deserialization", + "InvalidMethodName": { + "name": "InvalidMethodName", "subtypes": [], "props": {} }, - "FunctionExecError": { - "name": "FunctionExecError", - "subtypes": [ - "CompilationError", - "LinkError", - "ResolveError", - "WasmTrap", - "HostError" - ], - "props": {} + "InvalidPromiseIndex": { + "name": "InvalidPromiseIndex", + "subtypes": [], + "props": { + "promise_idx": "" + } }, - "GasLimitExceeded": { - "name": "GasLimitExceeded", + "InvalidPromiseResultIndex": { + "name": "InvalidPromiseResultIndex", "subtypes": [], - "props": {} + "props": { + "result_idx": "" + } }, - "BalanceExceeded": { - "name": "BalanceExceeded", + "InvalidPublicKey": { + "name": "InvalidPublicKey", "subtypes": [], "props": {} }, - "Serialization": { - "name": "Serialization", + "InvalidReceiptIndex": { + "name": "InvalidReceiptIndex", "subtypes": [], - "props": {} + "props": { + "receipt_index": "" + } }, - "WasmTrap": { - "name": "WasmTrap", + "InvalidRegisterId": { + "name": "InvalidRegisterId", "subtypes": [], "props": { - "msg": "" + "register_id": "" } }, - "ProhibitedInView": { - "name": "ProhibitedInView", + "IteratorWasInvalidated": { + "name": "IteratorWasInvalidated", "subtypes": [], "props": { - "method_name": "" + "iterator_index": "" } }, - "MethodEmptyName": { - "name": "MethodEmptyName", + "LinkError": { + "name": "LinkError", + "subtypes": [], + "props": { + "msg": "" + } + }, + "Memory": { + "name": "Memory", "subtypes": [], "props": {} }, - "EmptyMethodName": { - "name": "EmptyMethodName", + "MemoryAccessViolation": { + "name": "MemoryAccessViolation", "subtypes": [], "props": {} }, - "GuestPanic": { - "name": "GuestPanic", + "MethodEmptyName": { + "name": "MethodEmptyName", "subtypes": [], - "props": { - "panic_msg": "" - } + "props": {} }, - "InvalidMethodName": { - "name": "InvalidMethodName", + "MethodInvalidSignature": { + "name": "MethodInvalidSignature", "subtypes": [], "props": {} }, @@ -201,143 +223,157 @@ "subtypes": [], "props": {} }, - "InvalidPromiseResultIndex": { - "name": "InvalidPromiseResultIndex", + "MethodUTF8Error": { + "name": "MethodUTF8Error", "subtypes": [], - "props": { - "result_idx": "" - } + "props": {} }, - "IteratorWasInvalidated": { - "name": "IteratorWasInvalidated", + "PrepareError": { + "name": "PrepareError", + "subtypes": [ + "Serialization", + "Deserialization", + "InternalMemoryDeclared", + "GasInstrumentation", + "StackHeightInstrumentation", + "Instantiate", + "Memory" + ], + "props": {} + }, + "ProhibitedInView": { + "name": "ProhibitedInView", "subtypes": [], "props": { - "iterator_index": "" + "method_name": "" } }, - "CompilationError": { - "name": "CompilationError", + "ResolveError": { + "name": "ResolveError", "subtypes": [ - "CodeDoesNotExist", - "PrepareError", - "WasmerCompileError" + "MethodEmptyName", + "MethodUTF8Error", + "MethodNotFound", + "MethodInvalidSignature" ], "props": {} }, - "InvalidPromiseIndex": { - "name": "InvalidPromiseIndex", + "Serialization": { + "name": "Serialization", + "subtypes": [], + "props": {} + }, + "StackHeightInstrumentation": { + "name": "StackHeightInstrumentation", + "subtypes": [], + "props": {} + }, + "WasmTrap": { + "name": "WasmTrap", "subtypes": [], "props": { - "promise_idx": "" + "msg": "" } }, - "BadUTF8": { - "name": "BadUTF8", + "WasmerCompileError": { + "name": "WasmerCompileError", "subtypes": [], - "props": {} + "props": { + "msg": "" + } }, - "InvalidReceiptIndex": { - "name": "InvalidReceiptIndex", + "AccessKeyNotFound": { + "name": "AccessKeyNotFound", "subtypes": [], "props": { - "receipt_index": "" + "account_id": "", + "public_key": "" } }, - "CodeDoesNotExist": { - "name": "CodeDoesNotExist", + "AccountAlreadyExists": { + "name": "AccountAlreadyExists", "subtypes": [], "props": { "account_id": "" } }, - "HostError": { - "name": "HostError", - "subtypes": [ - "BadUTF16", - "BadUTF8", - "GasExceeded", - "GasLimitExceeded", - "BalanceExceeded", - "EmptyMethodName", - "GuestPanic", - "IntegerOverflow", - "InvalidPromiseIndex", - "CannotAppendActionToJointPromise", - "CannotReturnJointPromise", - "InvalidPromiseResultIndex", - "InvalidRegisterId", - "IteratorWasInvalidated", - "MemoryAccessViolation", - "InvalidReceiptIndex", - "InvalidIteratorIndex", - "InvalidAccountId", - "InvalidMethodName", - "InvalidPublicKey", - "ProhibitedInView" + "AccountDoesNotExist": { + "name": "AccountDoesNotExist", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "ActionError": { + "name": "ActionError", + "subtypes": [ + "AccountAlreadyExists", + "AccountDoesNotExist", + "CreateAccountNotAllowed", + "ActorNoPermission", + "DeleteKeyDoesNotExist", + "AddKeyAlreadyExists", + "DeleteAccountStaking", + "DeleteAccountHasRent", + "RentUnpaid", + "TriesToUnstake", + "TriesToStake", + "FunctionCall" ], - "props": {} - }, - "IntegerOverflow": { - "name": "IntegerOverflow", - "subtypes": [], - "props": {} + "props": { + "index": "" + } }, - "NotEnoughAllowance": { - "name": "NotEnoughAllowance", + "ActorNoPermission": { + "name": "ActorNoPermission", "subtypes": [], "props": { - "public_key": "", - "allowance": "", "account_id": "", - "cost": "" + "actor_id": "" } }, - "ReceiverMismatch": { - "name": "ReceiverMismatch", + "AddKeyAlreadyExists": { + "name": "AddKeyAlreadyExists", "subtypes": [], "props": { - "ak_receiver": "", - "tx_receiver": "" + "account_id": "", + "public_key": "" } }, - "DeleteAccountStaking": { - "name": "DeleteAccountStaking", + "CostOverflow": { + "name": "CostOverflow", "subtypes": [], - "props": { - "account_id": "" - } + "props": {} }, - "TriesToStake": { - "name": "TriesToStake", + "CreateAccountNotAllowed": { + "name": "CreateAccountNotAllowed", "subtypes": [], "props": { - "balance": "", "account_id": "", - "locked": "", - "stake": "" + "predecessor_id": "" } }, - "InvalidReceiverId": { - "name": "InvalidReceiverId", + "DeleteAccountHasRent": { + "name": "DeleteAccountHasRent", "subtypes": [], "props": { - "receiver_id": "" + "account_id": "", + "balance": "" } }, - "AccessKeyNotFound": { - "name": "AccessKeyNotFound", + "DeleteAccountStaking": { + "name": "DeleteAccountStaking", "subtypes": [], "props": { - "public_key": "", "account_id": "" } }, - "RentUnpaid": { - "name": "RentUnpaid", + "DeleteKeyDoesNotExist": { + "name": "DeleteKeyDoesNotExist", "subtypes": [], "props": { - "amount": "", - "account_id": "" + "account_id": "", + "public_key": "" } }, "Expired": { @@ -345,9 +381,15 @@ "subtypes": [], "props": {} }, - "InvalidSignature": { - "name": "InvalidSignature", - "subtypes": [], + "InvalidAccessKey": { + "name": "InvalidAccessKey", + "subtypes": [ + "AccessKeyNotFound", + "ReceiverMismatch", + "MethodNameMismatch", + "ActionError", + "NotEnoughAllowance" + ], "props": {} }, "InvalidChain": { @@ -355,17 +397,37 @@ "subtypes": [], "props": {} }, - "MethodNameMismatch": { - "name": "MethodNameMismatch", + "InvalidNonce": { + "name": "InvalidNonce", "subtypes": [], "props": { - "method_name": "" + "ak_nonce": "", + "tx_nonce": "" + } + }, + "InvalidReceiverId": { + "name": "InvalidReceiverId", + "subtypes": [], + "props": { + "receiver_id": "" + } + }, + "InvalidSignature": { + "name": "InvalidSignature", + "subtypes": [], + "props": {} + }, + "InvalidSignerId": { + "name": "InvalidSignerId", + "subtypes": [], + "props": { + "signer_id": "" } }, "InvalidTxError": { "name": "InvalidTxError", "subtypes": [ - "InvalidAccessKey", + "InvalidAccessKeyError", "InvalidSignerId", "SignerDoesNotExist", "InvalidNonce", @@ -379,48 +441,63 @@ ], "props": {} }, - "InvalidSignerId": { - "name": "InvalidSignerId", + "MethodNameMismatch": { + "name": "MethodNameMismatch", "subtypes": [], "props": { - "signer_id": "" + "method_name": "" } }, - "CostOverflow": { - "name": "CostOverflow", + "NotEnoughAllowance": { + "name": "NotEnoughAllowance", "subtypes": [], - "props": {} + "props": { + "account_id": "", + "allowance": "", + "cost": "", + "public_key": "" + } }, - "ActorNoPermission": { - "name": "ActorNoPermission", + "NotEnoughBalance": { + "name": "NotEnoughBalance", "subtypes": [], "props": { - "account_id": "", - "actor_id": "" + "balance": "", + "cost": "", + "signer_id": "" } }, - "DeleteKeyDoesNotExist": { - "name": "DeleteKeyDoesNotExist", + "ReceiverMismatch": { + "name": "ReceiverMismatch", + "subtypes": [], + "props": { + "ak_receiver": "", + "tx_receiver": "" + } + }, + "RentUnpaid": { + "name": "RentUnpaid", "subtypes": [], "props": { "account_id": "", - "public_key": "" + "amount": "" } }, - "AddKeyAlreadyExists": { - "name": "AddKeyAlreadyExists", + "SignerDoesNotExist": { + "name": "SignerDoesNotExist", "subtypes": [], "props": { - "public_key": "", - "account_id": "" + "signer_id": "" } }, - "DeleteAccountHasRent": { - "name": "DeleteAccountHasRent", + "TriesToStake": { + "name": "TriesToStake", "subtypes": [], "props": { + "account_id": "", "balance": "", - "account_id": "" + "locked": "", + "stake": "" } }, "TriesToUnstake": { @@ -438,99 +515,70 @@ ], "props": {} }, - "AccountAlreadyExists": { - "name": "AccountAlreadyExists", - "subtypes": [], - "props": { - "account_id": "" - } - }, - "NotEnoughBalance": { - "name": "NotEnoughBalance", + "Closed": { + "name": "Closed", "subtypes": [], - "props": { - "balance": "", - "signer_id": "", - "cost": "" - } + "props": {} }, - "InvalidAccessKey": { - "name": "InvalidAccessKey", + "ServerError": { + "name": "ServerError", "subtypes": [ - "AccessKeyNotFound", - "ReceiverMismatch", - "MethodNameMismatch", - "ActionError", - "NotEnoughAllowance" + "TxExecutionError", + "Timeout", + "Closed" ], "props": {} }, - "InvalidNonce": { - "name": "InvalidNonce", - "subtypes": [], - "props": { - "ak_nonce": "", - "tx_nonce": "" - } - }, - "SignerDoesNotExist": { - "name": "SignerDoesNotExist", + "Timeout": { + "name": "Timeout", "subtypes": [], - "props": { - "signer_id": "" - } + "props": {} }, - "ActionError": { - "name": "ActionError", + "MethodResolveError": { + "name": "MethodResolveError", "subtypes": [ - "AccountAlreadyExists", - "AccountDoesNotExist", - "CreateAccountNotAllowed", - "ActorNoPermission", - "DeleteKeyDoesNotExist", - "AddKeyAlreadyExists", - "DeleteAccountStaking", - "DeleteAccountHasRent", - "RentUnpaid", - "TriesToUnstake", - "TriesToStake", - "FunctionCall" + "MethodEmptyName", + "MethodUTF8Error", + "MethodNotFound", + "MethodInvalidSignature" ], - "props": { - "index": "" - } + "props": {} }, - "AccountDoesNotExist": { - "name": "AccountDoesNotExist", - "subtypes": [], - "props": { - "account_id": "" - } + "VMError": { + "name": "VMError", + "subtypes": [ + "FunctionExecError", + "StorageError" + ], + "props": {} }, - "CreateAccountNotAllowed": { - "name": "CreateAccountNotAllowed", + "BalanceMismatchError": { + "name": "BalanceMismatchError", "subtypes": [], "props": { - "predecessor_id": "", - "account_id": "" + "final_accounts_balance": "", + "final_postponed_receipts_balance": "", + "incoming_receipts_balance": "", + "incoming_validator_rewards": "", + "initial_accounts_balance": "", + "initial_postponed_receipts_balance": "", + "new_delayed_receipts_balance": "", + "outgoing_receipts_balance": "", + "processed_delayed_receipts_balance": "", + "total_balance_burnt": "", + "total_balance_slashed": "", + "total_rent_paid": "", + "total_validator_reward": "" } }, - "Closed": { - "name": "Closed", - "subtypes": [], - "props": {} - }, - "Timeout": { - "name": "Timeout", - "subtypes": [], - "props": {} - }, - "ServerError": { - "name": "ServerError", + "InvalidAccessKeyError": { + "name": "InvalidAccessKeyError", "subtypes": [ - "TxExecutionError", - "Timeout", - "Closed" + "AccessKeyNotFound", + "ReceiverMismatch", + "MethodNameMismatch", + "ActionError", + "NotEnoughAllowance" ], "props": {} } diff --git a/runtime/near-vm-errors/src/lib.rs b/runtime/near-vm-errors/src/lib.rs index f38bd5e99f8..ec67da2d937 100644 --- a/runtime/near-vm-errors/src/lib.rs +++ b/runtime/near-vm-errors/src/lib.rs @@ -6,7 +6,6 @@ use std::fmt; #[derive( Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "FunctionCall"] pub enum VMError { FunctionExecError(FunctionExecError), // TODO: serialize/deserialize? @@ -16,11 +15,10 @@ pub enum VMError { #[derive( Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "FunctionExecError"] pub enum FunctionExecError { CompilationError(CompilationError), LinkError { msg: String }, - ResolveError(MethodResolveError), + MethodResolveError(MethodResolveError), WasmTrap { msg: String }, HostError(HostError), } @@ -28,7 +26,6 @@ pub enum FunctionExecError { #[derive( Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "ResolveError"] pub enum MethodResolveError { MethodEmptyName, MethodUTF8Error, @@ -39,7 +36,6 @@ pub enum MethodResolveError { #[derive( Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "CompilationError"] pub enum CompilationError { CodeDoesNotExist { account_id: String }, PrepareError(PrepareError), @@ -49,7 +45,6 @@ pub enum CompilationError { #[derive( Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "PrepareError"] /// Error that can occur while preparing or executing Wasm smart-contract. pub enum PrepareError { /// Error happened while serializing the module. @@ -78,7 +73,6 @@ pub enum PrepareError { #[derive( Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError, )] -#[rpc_error_variant = "HostError"] pub enum HostError { /// String encoding is bad UTF-16 sequence BadUTF16, @@ -166,7 +160,7 @@ impl fmt::Display for FunctionExecError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self { FunctionExecError::CompilationError(e) => e.fmt(f), - FunctionExecError::ResolveError(e) => e.fmt(f), + FunctionExecError::MethodResolveError(e) => e.fmt(f), FunctionExecError::HostError(e) => e.fmt(f), FunctionExecError::LinkError { msg } => write!(f, "{}", msg), FunctionExecError::WasmTrap { msg } => write!(f, "WebAssembly trap: {}", msg), @@ -240,7 +234,7 @@ mod tests { fn test_display() { // TODO: proper printing assert_eq!( - VMError::FunctionExecError(FunctionExecError::ResolveError( + VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodInvalidSignature )) .to_string(), diff --git a/runtime/near-vm-runner/src/errors.rs b/runtime/near-vm-runner/src/errors.rs index 7df8b8669cb..76d96eaacc6 100644 --- a/runtime/near-vm-runner/src/errors.rs +++ b/runtime/near-vm-runner/src/errors.rs @@ -44,13 +44,13 @@ impl IntoVMError for wasmer_runtime::error::ResolveError { use wasmer_runtime::error::ResolveError as WasmerResolveError; match self { WasmerResolveError::Signature { .. } => VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodInvalidSignature), + FunctionExecError::MethodResolveError(MethodResolveError::MethodInvalidSignature), ), WasmerResolveError::ExportNotFound { .. } => VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodNotFound), + FunctionExecError::MethodResolveError(MethodResolveError::MethodNotFound), ), WasmerResolveError::ExportWrongType { .. } => VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodNotFound), + FunctionExecError::MethodResolveError(MethodResolveError::MethodNotFound), ), } } diff --git a/runtime/near-vm-runner/src/runner.rs b/runtime/near-vm-runner/src/runner.rs index ee3741a33ac..c1a6108edf3 100644 --- a/runtime/near-vm-runner/src/runner.rs +++ b/runtime/near-vm-runner/src/runner.rs @@ -16,12 +16,12 @@ fn check_method(module: &Module, method_name: &str) -> Result<(), VMError> { if sig.params().is_empty() && sig.returns().is_empty() { Ok(()) } else { - Err(VMError::FunctionExecError(FunctionExecError::ResolveError( + Err(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodInvalidSignature, ))) } } else { - Err(VMError::FunctionExecError(FunctionExecError::ResolveError( + Err(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodNotFound, ))) } @@ -57,7 +57,7 @@ pub fn run<'a>( if method_name.is_empty() { return ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodEmptyName, ))), ); @@ -83,7 +83,7 @@ pub fn run<'a>( Err(_) => { return ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodUTF8Error, ))), ) diff --git a/runtime/near-vm-runner/tests/test_error_cases.rs b/runtime/near-vm-runner/tests/test_error_cases.rs index eabb34eeb6d..cff219058b0 100644 --- a/runtime/near-vm-runner/tests/test_error_cases.rs +++ b/runtime/near-vm-runner/tests/test_error_cases.rs @@ -47,7 +47,7 @@ fn test_infinite_initializer_export_not_found() { make_simple_contract_call(&infinite_initializer_contract(), b"hello2"), ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodNotFound ))) ) @@ -80,7 +80,7 @@ fn test_export_not_found() { make_simple_contract_call(&simple_contract(), b"hello2"), ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodNotFound ))) ) @@ -93,7 +93,7 @@ fn test_empty_method() { make_simple_contract_call(&simple_contract(), b""), ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodEmptyName ))) ) @@ -106,7 +106,7 @@ fn test_invalid_utf8() { make_simple_contract_call(&simple_contract(), &[255u8]), ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodUTF8Error ))) ) @@ -182,7 +182,7 @@ fn test_wrong_signature_contract() { make_simple_contract_call(&wrong_signature_contract(), b"hello"), ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodInvalidSignature ))) ) @@ -206,7 +206,7 @@ fn test_export_wrong_type() { make_simple_contract_call(&export_wrong_type(), b"hello"), ( None, - Some(VMError::FunctionExecError(FunctionExecError::ResolveError( + Some(VMError::FunctionExecError(FunctionExecError::MethodResolveError( MethodResolveError::MethodNotFound ))) ) diff --git a/runtime/runtime/src/balance_checker.rs b/runtime/runtime/src/balance_checker.rs index 3324d774b4e..ab2231493d8 100644 --- a/runtime/runtime/src/balance_checker.rs +++ b/runtime/runtime/src/balance_checker.rs @@ -281,7 +281,7 @@ mod tests { &ApplyStats::default(), ) .unwrap_err(); - assert_matches!(err, RuntimeError::BalanceMismatch(_)); + assert_matches!(err, RuntimeError::BalanceMismatchError(_)); } #[test] diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index 3f4692b2dd3..f896e6030dc 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -245,7 +245,7 @@ impl Runtime { match get_access_key(state_update, &signer_id, &transaction.public_key)? { Some(access_key) => access_key, None => { - return Err(InvalidTxError::InvalidAccessKey( + return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::AccessKeyNotFound { account_id: signer_id.clone(), public_key: transaction.public_key.clone(), @@ -289,12 +289,14 @@ impl Runtime { { if let Some(ref mut allowance) = function_call_permission.allowance { *allowance = allowance.checked_sub(total_cost).ok_or_else(|| { - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::NotEnoughAllowance { - account_id: signer_id.clone(), - public_key: transaction.public_key.clone(), - allowance: *allowance, - cost: total_cost, - }) + InvalidTxError::InvalidAccessKeyError( + InvalidAccessKeyError::NotEnoughAllowance { + account_id: signer_id.clone(), + public_key: transaction.public_key.clone(), + allowance: *allowance, + cost: total_cost, + }, + ) })?; } } @@ -308,13 +310,14 @@ impl Runtime { access_key.permission { if transaction.actions.len() != 1 { - return Err( - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ActionError).into() - ); + return Err(InvalidTxError::InvalidAccessKeyError( + InvalidAccessKeyError::ActionError, + ) + .into()); } if let Some(Action::FunctionCall(ref function_call)) = transaction.actions.get(0) { if transaction.receiver_id != function_call_permission.receiver_id { - return Err(InvalidTxError::InvalidAccessKey( + return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::ReceiverMismatch { tx_receiver: transaction.receiver_id.clone(), ak_receiver: function_call_permission.receiver_id.clone(), @@ -328,7 +331,7 @@ impl Runtime { .iter() .all(|method_name| &function_call.method_name != method_name) { - return Err(InvalidTxError::InvalidAccessKey( + return Err(InvalidTxError::InvalidAccessKeyError( InvalidAccessKeyError::MethodNameMismatch { method_name: function_call.method_name.clone(), }, @@ -336,9 +339,10 @@ impl Runtime { .into()); } } else { - return Err( - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ActionError).into() - ); + return Err(InvalidTxError::InvalidAccessKeyError( + InvalidAccessKeyError::ActionError, + ) + .into()); } }; diff --git a/scripts/build_errors_schema.sh b/scripts/build_errors_schema.sh index b7f1622d138..70da0bc314f 100755 --- a/scripts/build_errors_schema.sh +++ b/scripts/build_errors_schema.sh @@ -1,3 +1,3 @@ #!/bin/bash cargo build --features dump_errors_schema --manifest-path near/Cargo.toml -cp ../target/rpc_errors_schema.json ../res/rpc_errors_schema.json +cp ./target/rpc_errors_schema.json ./res/rpc_errors_schema.json diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index 57727d69b2b..0fa44ad2baf 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -123,7 +123,7 @@ pub fn test_smart_contract_bad_method_name(node: impl Node) { ActionError { index: Some(0), kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodNotFound) + FunctionExecError::MethodResolveError(MethodResolveError::MethodNotFound) )) } .into() @@ -147,7 +147,7 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { ActionError { index: Some(0), kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) + FunctionExecError::MethodResolveError(MethodResolveError::MethodEmptyName) )) } .into() @@ -171,7 +171,7 @@ pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { ActionError { index: Some(0), kind: ActionErrorKind::FunctionCall(VMError::FunctionExecError( - FunctionExecError::ResolveError(MethodResolveError::MethodEmptyName) + FunctionExecError::MethodResolveError(MethodResolveError::MethodEmptyName) )) } .into() @@ -884,7 +884,7 @@ pub fn test_access_key_smart_contract_reject_method_name(node: impl Node) { assert_eq!( transaction_result, ServerError::TxExecutionError(TxExecutionError::InvalidTxError( - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::MethodNameMismatch { + InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::MethodNameMismatch { method_name: "run_test".to_string() }) )) @@ -919,7 +919,7 @@ pub fn test_access_key_smart_contract_reject_contract_id(node: impl Node) { assert_eq!( transaction_result, ServerError::TxExecutionError(TxExecutionError::InvalidTxError( - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ReceiverMismatch { + InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::ReceiverMismatch { tx_receiver: eve_dot_alice_account(), ak_receiver: bob_account() }) @@ -947,7 +947,7 @@ pub fn test_access_key_reject_non_function_call(node: impl Node) { assert_eq!( transaction_result, ServerError::TxExecutionError(TxExecutionError::InvalidTxError( - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::ActionError) + InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::ActionError) )) ); } diff --git a/test-utils/testlib/src/user/runtime_user.rs b/test-utils/testlib/src/user/runtime_user.rs index 9774fa5eeae..d33714e8bc7 100644 --- a/test-utils/testlib/src/user/runtime_user.rs +++ b/test-utils/testlib/src/user/runtime_user.rs @@ -90,7 +90,7 @@ impl RuntimeUser { RuntimeError::InvalidTxError(e) => { ServerError::TxExecutionError(TxExecutionError::InvalidTxError(e)) } - RuntimeError::BalanceMismatch(e) => panic!("{}", e), + RuntimeError::BalanceMismatchError(e) => panic!("{}", e), RuntimeError::StorageError(e) => panic!("Storage error {:?}", e), RuntimeError::UnexpectedIntegerOverflow => { panic!("UnexpectedIntegerOverflow error") diff --git a/tests/test_errors.rs b/tests/test_errors.rs index 118f825e550..9c39ce2e0ab 100644 --- a/tests/test_errors.rs +++ b/tests/test_errors.rs @@ -47,7 +47,7 @@ fn test_check_tx_error_log() { let tx_result = node.user().commit_transaction(tx).unwrap_err(); assert_eq!( tx_result, - InvalidTxError::InvalidAccessKey(InvalidAccessKeyError::AccessKeyNotFound { + InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::AccessKeyNotFound { account_id: "bob.near".to_string(), public_key: signer.public_key.clone() }) diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs index 1c95ac69590..fda01d07f46 100644 --- a/tools/rpctypegen/src/lib.rs +++ b/tools/rpctypegen/src/lib.rs @@ -3,12 +3,12 @@ extern crate proc_macro2; use proc_macro::TokenStream; use serde::{Deserialize, Serialize}; +#[cfg(feature = "dump_errors_schema")] use serde_json::Value; use std::cell::RefCell; use std::collections::BTreeMap; use syn::{ parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, - Lit, Meta, MetaNameValue, }; #[cfg(feature = "dump_errors_schema")] @@ -64,16 +64,10 @@ struct ErrorType { thread_local!(static SCHEMA: RefCell = RefCell::new(Schema::default())); -fn parse_rpc_error_variant(input: &DeriveInput) -> Option { - input.attrs.iter().find_map(|attr| { - if !attr.path.is_ident("rpc_error_variant") { - return None; - } - match attr.parse_meta().unwrap() { - Meta::NameValue(MetaNameValue { lit: Lit::Str(lit), .. }) => Some(lit.value()), - _ => None, - } - }) +fn parse_rpc_error_variant(input: &DeriveInput) -> String { + let type_name = input.ident.to_string(); + let type_kind: Vec<&str> = type_name.split("Kind").collect(); + type_kind[0].to_string() } fn error_type_name<'a>( @@ -85,7 +79,7 @@ fn error_type_name<'a>( } fn parse_error_type(schema: &mut BTreeMap, input: &DeriveInput) { - let name = parse_rpc_error_variant(input).expect("should have a rpc_error_variant with value"); + let name = parse_rpc_error_variant(input); match &input.data { Data::Enum(DataEnum { ref variants, .. }) => { // TODO: check for uniqueness @@ -156,7 +150,7 @@ fn parse_error_type(schema: &mut BTreeMap, input: &DeriveInpu } } -#[proc_macro_derive(RpcError, attributes(rpc_error_variant))] +#[proc_macro_derive(RpcError)] pub fn rpc_error(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); From 7bbba23b84938ba43be7fa23d26d9ecdeaf5e83d Mon Sep 17 00:00:00 2001 From: Alexey Date: Mon, 20 Jan 2020 19:46:14 +0300 Subject: [PATCH 43/48] split rpctypegen into core and macro crated + tests added --- Cargo.lock | 23 ++ Cargo.toml | 4 +- chain/jsonrpc/Cargo.toml | 2 +- core/primitives/Cargo.toml | 2 +- res/rpc_errors_schema.json | 2 +- runtime/near-vm-errors/Cargo.toml | 2 +- tools/rpctypegen/{ => core}/Cargo.toml | 6 +- tools/rpctypegen/core/src/lib.rs | 293 +++++++++++++++++++++++++ tools/rpctypegen/macro/Cargo.toml | 20 ++ tools/rpctypegen/macro/src/lib.rs | 65 ++++++ tools/rpctypegen/src/lib.rs | 161 -------------- 11 files changed, 410 insertions(+), 170 deletions(-) rename tools/rpctypegen/{ => core}/Cargo.toml (86%) create mode 100644 tools/rpctypegen/core/src/lib.rs create mode 100644 tools/rpctypegen/macro/Cargo.toml create mode 100644 tools/rpctypegen/macro/src/lib.rs delete mode 100644 tools/rpctypegen/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 45d3896e098..46523d35008 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2211,10 +2211,22 @@ dependencies = [ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "near-rpc-error-core" +version = "0.1.0" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "near-rpc-error-macro" version = "0.1.0" dependencies = [ + "near-rpc-error-core 0.1.0", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2222,6 +2234,17 @@ dependencies = [ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "near-rpc-error-macro-tests" +version = "0.1.0" +dependencies = [ + "near-rpc-error-core 0.1.0", + "near-rpc-error-macro 0.1.0", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "near-runtime-fees" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 30d2ce7fa0d..dc6506885a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,9 @@ members = [ "test-utils/loadtester", "test-utils/state-viewer", "near/", - "tools/rpctypegen", + "tools/rpctypegen/core", + "tools/rpctypegen/macro", + "tools/rpctypegen/tests", "genesis-tools/genesis-csv-to-json", "genesis-tools/genesis-populate", "genesis-tools/keypair-generator", diff --git a/chain/jsonrpc/Cargo.toml b/chain/jsonrpc/Cargo.toml index 7100e4ad1ed..d6e25ae7727 100644 --- a/chain/jsonrpc/Cargo.toml +++ b/chain/jsonrpc/Cargo.toml @@ -33,7 +33,7 @@ near-client = { path = "../client" } near-network = { path = "../network" } near-pool = { path = "../pool" } near-jsonrpc-client = { path = "client" } -near-rpc-error-macro = { path = "../../tools/rpctypegen" } +near-rpc-error-macro = { path = "../../tools/rpctypegen/macro" } [features] dump_errors_schema = ["near-rpc-error-macro/dump_errors_schema"] diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index 6adca19b4c5..afe5e1077fd 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -27,7 +27,7 @@ borsh = "0.2.10" near-crypto = { path = "../crypto" } near-vm-errors = { path = "../../runtime/near-vm-errors" } -near-rpc-error-macro = { path = "../../tools/rpctypegen" } +near-rpc-error-macro = { path = "../../tools/rpctypegen/macro" } [features] default = ["jemallocator"] diff --git a/res/rpc_errors_schema.json b/res/rpc_errors_schema.json index c9c8f7b24d7..514db6dc0f5 100644 --- a/res/rpc_errors_schema.json +++ b/res/rpc_errors_schema.json @@ -583,4 +583,4 @@ "props": {} } } -} +} \ No newline at end of file diff --git a/runtime/near-vm-errors/Cargo.toml b/runtime/near-vm-errors/Cargo.toml index bf3b940a2db..03d0941fa57 100644 --- a/runtime/near-vm-errors/Cargo.toml +++ b/runtime/near-vm-errors/Cargo.toml @@ -14,7 +14,7 @@ Error that can occur inside Near Runtime encapsulated in a separate crate. Might [dependencies] borsh = "0.2.10" -near-rpc-error-macro = { path = "../../tools/rpctypegen" } +near-rpc-error-macro = { path = "../../tools/rpctypegen/macro" } serde = { version = "1.0", features = ["derive"] } [features] diff --git a/tools/rpctypegen/Cargo.toml b/tools/rpctypegen/core/Cargo.toml similarity index 86% rename from tools/rpctypegen/Cargo.toml rename to tools/rpctypegen/core/Cargo.toml index 93c719623e7..9ce6952bee1 100644 --- a/tools/rpctypegen/Cargo.toml +++ b/tools/rpctypegen/core/Cargo.toml @@ -1,12 +1,9 @@ [package] -name = "near-rpc-error-macro" +name = "near-rpc-error-core" version = "0.1.0" authors = ["Near Inc "] edition = "2018" -[lib] -proc-macro = true - [dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0", features = ["preserve_order"]} @@ -15,4 +12,5 @@ quote = "1.0" proc-macro2 = "1.0" [features] +test = [] dump_errors_schema = [] diff --git a/tools/rpctypegen/core/src/lib.rs b/tools/rpctypegen/core/src/lib.rs new file mode 100644 index 00000000000..d41825acd6a --- /dev/null +++ b/tools/rpctypegen/core/src/lib.rs @@ -0,0 +1,293 @@ +extern crate proc_macro; +extern crate proc_macro2; + +use std::collections::BTreeMap; +use syn::{Data, DataEnum, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed}; + +use serde::{Deserialize, Serialize}; + +#[derive(Default, Debug, Deserialize, Serialize)] +pub struct ErrorType { + /// A type name of the error + pub name: String, + /// Names of subtypes of the error + pub subtypes: Vec, + /// An error input name and a type + pub props: BTreeMap, +} + +fn parse_rpc_error_variant(input: &DeriveInput) -> String { + let type_name = input.ident.to_string(); + let type_kind: Vec<&str> = type_name.split("Kind").collect(); + type_kind[0].to_string() +} + +fn error_type_name<'a>( + schema: &'a mut BTreeMap, + name: String, +) -> &'a mut ErrorType { + let error_type = ErrorType { name: name.clone(), ..Default::default() }; + schema.entry(name.clone()).or_insert(error_type) +} + +pub fn parse_error_type(schema: &mut BTreeMap, input: &DeriveInput) { + let name = parse_rpc_error_variant(input); + match &input.data { + Data::Enum(DataEnum { ref variants, .. }) => { + // TODO: check for uniqueness + let error_type = error_type_name(schema, name); + let mut direct_error_types = vec![]; + for variant in variants { + error_type.subtypes.push(variant.ident.to_string()); + match &variant.fields { + Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) => { + // Subtype + if unnamed.iter().count() > 1 { + panic!( + "Error types doesn't support tuple variants with multiple fields" + ); + } + } + Fields::Named(FieldsNamed { ref named, .. }) => { + // If variant is Enum with a named fields - create a new type for each variant with named props + let mut error_type = ErrorType::default(); + error_type.name = variant.ident.to_string(); + for field in named { + error_type.props.insert( + field + .ident + .as_ref() + .expect("named fields must have ident") + .to_string(), + "".to_owned(), + ); + } + direct_error_types.push(error_type); + } + Fields::Unit => { + direct_error_types.push(ErrorType { + name: variant.ident.to_string(), + ..Default::default() + }); + } + } + } + for e in direct_error_types { + let mut error_type = error_type_name(schema, e.name.clone()); + error_type.name = e.name; + error_type.props = e.props; + } + } + Data::Struct(DataStruct { ref fields, .. }) => { + let error_type = error_type_name(schema, name); + match fields { + Fields::Named(FieldsNamed { ref named, .. }) => { + for field in named { + let field_name = + field.ident.as_ref().expect("named fields must have ident").to_string(); + if field_name == "kind" { + continue; + } + error_type.props.insert(field_name, "".to_owned()); // TODO: add prop type + } + } + _ => { + panic!("RpcError supports structs with the named fields only"); + } + } + } + Data::Union(_) => { + panic!("Unions are not supported"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use quote::quote; + #[test] + fn should_merge_kind() { + let mut schema = BTreeMap::default(); + let error_type = syn::parse2(quote! { + pub struct ActionError { + pub index: Option, + pub kind: ActionErrorKind, + } + }) + .unwrap(); + parse_error_type(&mut schema, &error_type); + let expected: BTreeMap = serde_json::from_str( + r#" + { + "ActionError": { + "name": "ActionError", + "subtypes": [], + "props": { + "index": "" + } + } + } + "#, + ) + .unwrap(); + assert_eq!( + serde_json::to_string(&expected).unwrap(), + serde_json::to_string(&schema).unwrap() + ); + let error_type_kind: DeriveInput = syn::parse2(quote! { + pub enum ActionErrorKind { + AccountAlreadyExists { account_id: String }, + } + }) + .unwrap(); + let expected: BTreeMap = serde_json::from_str( + r#" + { + "ActionError": { + "name": "ActionError", + "subtypes": ["AccountAlreadyExists"], + "props": { + "index": "" + } + }, + "AccountAlreadyExists": { + "name": "AccountAlreadyExists", + "subtypes": [], + "props": { + "account_id": "" + } + } + } + "#, + ) + .unwrap(); + parse_error_type(&mut schema, &error_type_kind); + assert_eq!( + serde_json::to_string(&expected).unwrap(), + serde_json::to_string(&schema).unwrap() + ); + } + + #[test] + fn complex() { + let mut schema = BTreeMap::default(); + parse_error_type( + &mut schema, + &syn::parse2(quote! { + pub enum TxExecutionError { + ActionError(ActionError), + InvalidTxError(InvalidTxError), + } + }) + .unwrap(), + ); + parse_error_type( + &mut schema, + &syn::parse2(quote! { + pub enum InvalidTxError { + InvalidAccessKeyError(InvalidAccessKeyError), + InvalidSignerId { signer_id: AccountId }, + } + }) + .unwrap(), + ); + parse_error_type( + &mut schema, + &syn::parse2(quote! { + pub enum InvalidAccessKeyError { + /// The access key identified by the `public_key` doesn't exist for the account + AccessKeyNotFound { account_id: AccountId, public_key: PublicKey }, + } + }) + .unwrap(), + ); + parse_error_type( + &mut schema, + &syn::parse2(quote! { + pub struct ActionError { + pub index: Option, + pub kind: ActionErrorKind, + } + }) + .unwrap(), + ); + parse_error_type( + &mut schema, + &syn::parse2(quote! { + pub enum ActionErrorKind { + AccountAlreadyExists { account_id: String }, + } + }) + .unwrap(), + ); + let expected: BTreeMap = serde_json::from_str( + r#" + { + "AccountAlreadyExists": { + "name": "AccountAlreadyExists", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "ActionError": { + "name": "ActionError", + "subtypes": [ + "AccountAlreadyExists" + ], + "props": { + "index": "" + } + }, + "InvalidSignerId": { + "name": "InvalidSignerId", + "subtypes": [], + "props": { + "signer_id": "" + } + }, + "InvalidTxError": { + "name": "InvalidTxError", + "subtypes": [ + "InvalidAccessKeyError", + "InvalidSignerId" + ], + "props": {} + }, + InvalidAccessKeyError: { + "name": "InvalidAccessKeyError", + "subtypes": [], + "props: {} + } + "TxExecutionError": { + "name": "TxExecutionError", + "subtypes": [ + "ActionError", + "InvalidTxError" + ], + "props": {} + } + }"#, + ) + .unwrap(); + assert_eq!( + serde_json::to_string(&expected).unwrap(), + serde_json::to_string(&schema).unwrap() + ); + } + #[test] + #[should_panic] + fn should_not_accept_tuples() { + let mut schema = BTreeMap::default(); + parse_error_type( + &mut schema, + &syn::parse2(quote! { + pub enum ErrorWithATupleVariant { + Var(One, Two) + } + }) + .unwrap(), + ); + } +} diff --git a/tools/rpctypegen/macro/Cargo.toml b/tools/rpctypegen/macro/Cargo.toml new file mode 100644 index 00000000000..0d382a8b203 --- /dev/null +++ b/tools/rpctypegen/macro/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "near-rpc-error-macro" +version = "0.1.0" +authors = ["Near Inc "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = {version = "1.0", features = ["preserve_order"]} +syn = { version = "1.0", features = ["full", "extra-traits"]} +quote = "1.0" +proc-macro2 = "1.0" +near-rpc-error-core = { path = "../core/." } + +[features] +test = [] +dump_errors_schema = ["near-rpc-error-core/dump_errors_schema"] diff --git a/tools/rpctypegen/macro/src/lib.rs b/tools/rpctypegen/macro/src/lib.rs new file mode 100644 index 00000000000..ec4e3d299ed --- /dev/null +++ b/tools/rpctypegen/macro/src/lib.rs @@ -0,0 +1,65 @@ +extern crate proc_macro; +extern crate proc_macro2; + +use near_rpc_error_core::{parse_error_type, ErrorType}; +use proc_macro::TokenStream; +#[cfg(feature = "dump_errors_schema")] +use serde::{Deserialize, Serialize}; +#[cfg(feature = "dump_errors_schema")] +use serde_json::Value; +use std::cell::RefCell; +use std::collections::BTreeMap; +use syn::{parse_macro_input, DeriveInput}; + +thread_local!(static SCHEMA: RefCell = RefCell::new(Schema::default())); + +#[derive(Default, Debug, Deserialize, Serialize)] +struct Schema { + pub schema: BTreeMap, +} + +#[cfg(feature = "dump_errors_schema")] +fn merge(a: &mut Value, b: &Value) { + match (a, b) { + (&mut Value::Object(ref mut a), &Value::Object(ref b)) => { + for (k, v) in b { + merge(a.entry(k.clone()).or_insert(Value::Null), v); + } + } + (a, b) => { + *a = b.clone(); + } + } +} + +#[cfg(feature = "dump_errors_schema")] +impl Drop for Schema { + fn drop(&mut self) { + // std::env::var("CARGO_TARGET_DIR") doesn't exists + let filename = "./target/rpc_errors_schema.json"; + let schema_json = serde_json::to_value(self).expect("Schema serialize failed"); + let new_schema_json = if let Ok(data) = std::fs::read(filename) { + // merge to the existing file + let mut existing_schema = serde_json::from_slice::(&data) + .expect("cannot deserialize target/existing_schema.json"); + merge(&mut existing_schema, &schema_json); + existing_schema + } else { + schema_json + }; + let new_schema_json_string = serde_json::to_string_pretty(&new_schema_json) + .expect("error schema serialization failed"); + std::fs::write(filename, new_schema_json_string) + .expect("Unable to save the errors schema file"); + } +} + +#[proc_macro_derive(RpcError)] +pub fn rpc_error(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + + SCHEMA.with(|s| { + parse_error_type(&mut s.borrow_mut().schema, &input); + }); + TokenStream::new() +} diff --git a/tools/rpctypegen/src/lib.rs b/tools/rpctypegen/src/lib.rs deleted file mode 100644 index fda01d07f46..00000000000 --- a/tools/rpctypegen/src/lib.rs +++ /dev/null @@ -1,161 +0,0 @@ -extern crate proc_macro; -extern crate proc_macro2; - -use proc_macro::TokenStream; -use serde::{Deserialize, Serialize}; -#[cfg(feature = "dump_errors_schema")] -use serde_json::Value; -use std::cell::RefCell; -use std::collections::BTreeMap; -use syn::{ - parse_macro_input, Data, DataEnum, DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, -}; - -#[cfg(feature = "dump_errors_schema")] -fn merge(a: &mut Value, b: &Value) { - match (a, b) { - (&mut Value::Object(ref mut a), &Value::Object(ref b)) => { - for (k, v) in b { - merge(a.entry(k.clone()).or_insert(Value::Null), v); - } - } - (a, b) => { - *a = b.clone(); - } - } -} - -#[derive(Default, Debug, Deserialize, Serialize)] -struct Schema { - pub schema: BTreeMap, -} - -#[cfg(feature = "dump_errors_schema")] -impl Drop for Schema { - fn drop(&mut self) { - // std::env::var("CARGO_TARGET_DIR") doesn't exists - let filename = "./target/rpc_errors_schema.json"; - let schema_json = serde_json::to_value(self).expect("Schema serialize failed"); - let new_schema_json = if let Ok(data) = std::fs::read(filename) { - // merge to the existing file - let mut existing_schema = serde_json::from_slice::(&data) - .expect("cannot deserialize target/existing_schema.json"); - merge(&mut existing_schema, &schema_json); - existing_schema - } else { - schema_json - }; - let new_schema_json_string = serde_json::to_string_pretty(&new_schema_json) - .expect("error schema serialization failed"); - std::fs::write(filename, new_schema_json_string) - .expect("Unable to save the errors schema file"); - } -} - -#[derive(Default, Debug, Deserialize, Serialize)] -struct ErrorType { - /// A type name of the error - pub name: String, - /// Names of subtypes of the error - pub subtypes: Vec, - /// An error input name and a type - pub props: BTreeMap, -} - -thread_local!(static SCHEMA: RefCell = RefCell::new(Schema::default())); - -fn parse_rpc_error_variant(input: &DeriveInput) -> String { - let type_name = input.ident.to_string(); - let type_kind: Vec<&str> = type_name.split("Kind").collect(); - type_kind[0].to_string() -} - -fn error_type_name<'a>( - schema: &'a mut BTreeMap, - name: String, -) -> &'a mut ErrorType { - let error_type = ErrorType { name: name.clone(), ..Default::default() }; - schema.entry(name.clone()).or_insert(error_type) -} - -fn parse_error_type(schema: &mut BTreeMap, input: &DeriveInput) { - let name = parse_rpc_error_variant(input); - match &input.data { - Data::Enum(DataEnum { ref variants, .. }) => { - // TODO: check for uniqueness - let error_type = error_type_name(schema, name); - let mut direct_error_types = vec![]; - for variant in variants { - error_type.subtypes.push(variant.ident.to_string()); - match &variant.fields { - Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) => { - // Subtype - if unnamed.iter().count() > 1 { - panic!( - "Error types doesn't support tuple variants with multiple fields" - ); - } - } - Fields::Named(FieldsNamed { ref named, .. }) => { - // If variant is Enum with a named fields - create a new type for each variant with named props - let mut error_type = ErrorType::default(); - error_type.name = variant.ident.to_string(); - for field in named { - error_type.props.insert( - field - .ident - .as_ref() - .expect("named fields must have ident") - .to_string(), - "".to_owned(), - ); - } - direct_error_types.push(error_type); - } - Fields::Unit => { - direct_error_types.push(ErrorType { - name: variant.ident.to_string(), - ..Default::default() - }); - } - } - } - for e in direct_error_types { - let mut error_type = error_type_name(schema, e.name.clone()); - error_type.name = e.name; - error_type.props = e.props; - } - } - Data::Struct(DataStruct { ref fields, .. }) => { - let error_type = error_type_name(schema, name); - match fields { - Fields::Named(FieldsNamed { ref named, .. }) => { - for field in named { - let field_name = - field.ident.as_ref().expect("named fields must have ident").to_string(); - if field_name == "kind" { - continue; - } - error_type.props.insert(field_name, "".to_owned()); // TODO: add prop type - } - } - _ => { - panic!("RpcError supports structs with the named fields only"); - } - } - } - Data::Union(_) => { - panic!("Unions are not supported"); - } - } -} - -#[proc_macro_derive(RpcError)] -pub fn rpc_error(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - - SCHEMA.with(|s| { - parse_error_type(&mut s.borrow_mut().schema, &input); - }); - TokenStream::new() -} From addf11ff1bc04370cb46b191f5307cb88828693f Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 21 Jan 2020 00:18:21 +0300 Subject: [PATCH 44/48] ServerError Display impl --- chain/jsonrpc/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/chain/jsonrpc/src/lib.rs b/chain/jsonrpc/src/lib.rs index ebe7c6e3d04..306687f6dd8 100644 --- a/chain/jsonrpc/src/lib.rs +++ b/chain/jsonrpc/src/lib.rs @@ -1,6 +1,7 @@ extern crate prometheus; use std::convert::TryFrom; +use std::fmt::Display; use std::string::FromUtf8Error; use std::time::Duration; @@ -120,6 +121,16 @@ pub enum ServerError { Closed, } +impl Display for ServerError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match self { + ServerError::TxExecutionError(e) => write!(f, "ServerError: {}", e), + ServerError::Timeout => write!(f, "ServerError: Timeout"), + ServerError::Closed => write!(f, "ServerError: Closed"), + } + } +} + impl From for ServerError { fn from(e: InvalidTxError) -> ServerError { ServerError::TxExecutionError(TxExecutionError::InvalidTxError(e)) From c1a094bf32313098bcc0f38976a02db0218fac12 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 21 Jan 2020 01:35:03 +0300 Subject: [PATCH 45/48] moved build_errors_schema.sh and res/rpc_errors_schema.json to a json-rpc crate --- Cargo.lock | 1 + chain/jsonrpc/Cargo.toml | 4 +- chain/jsonrpc/build_errors_schema.sh | 3 + .../jsonrpc/res}/rpc_errors_schema.json | 107 +++++++----------- near/Cargo.toml | 3 - scripts/build_errors_schema.sh | 3 - 6 files changed, 46 insertions(+), 75 deletions(-) create mode 100755 chain/jsonrpc/build_errors_schema.sh rename {res => chain/jsonrpc/res}/rpc_errors_schema.json (95%) delete mode 100755 scripts/build_errors_schema.sh diff --git a/Cargo.lock b/Cargo.lock index 67e0896b2d6..a6a3567b079 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2113,6 +2113,7 @@ dependencies = [ "near-rpc-error-macro 0.1.0", "near-store 0.1.0", "prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/chain/jsonrpc/Cargo.toml b/chain/jsonrpc/Cargo.toml index d6e25ae7727..7c46872ed2c 100644 --- a/chain/jsonrpc/Cargo.toml +++ b/chain/jsonrpc/Cargo.toml @@ -21,7 +21,6 @@ serde_derive = "1.0" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } uuid = { version = "~0.8", features = ["v4"] } - borsh = "0.2.10" near-crypto = { path = "../../core/crypto" } @@ -35,5 +34,8 @@ near-pool = { path = "../pool" } near-jsonrpc-client = { path = "client" } near-rpc-error-macro = { path = "../../tools/rpctypegen/macro" } +[build-dependencies] +_rand = { package = "rand", version = "0.6.5" } + [features] dump_errors_schema = ["near-rpc-error-macro/dump_errors_schema"] diff --git a/chain/jsonrpc/build_errors_schema.sh b/chain/jsonrpc/build_errors_schema.sh new file mode 100755 index 00000000000..59aa28ddf35 --- /dev/null +++ b/chain/jsonrpc/build_errors_schema.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cargo build --features dump_errors_schema +cp ../../target/rpc_errors_schema.json ./res/rpc_errors_schema.json diff --git a/res/rpc_errors_schema.json b/chain/jsonrpc/res/rpc_errors_schema.json similarity index 95% rename from res/rpc_errors_schema.json rename to chain/jsonrpc/res/rpc_errors_schema.json index 514db6dc0f5..1f8e8a24753 100644 --- a/res/rpc_errors_schema.json +++ b/chain/jsonrpc/res/rpc_errors_schema.json @@ -51,14 +51,6 @@ "subtypes": [], "props": {} }, - "FunctionCall": { - "name": "FunctionCall", - "subtypes": [ - "FunctionExecError", - "StorageError" - ], - "props": {} - }, "FunctionExecError": { "name": "FunctionExecError", "subtypes": [ @@ -223,6 +215,16 @@ "subtypes": [], "props": {} }, + "MethodResolveError": { + "name": "MethodResolveError", + "subtypes": [ + "MethodEmptyName", + "MethodUTF8Error", + "MethodNotFound", + "MethodInvalidSignature" + ], + "props": {} + }, "MethodUTF8Error": { "name": "MethodUTF8Error", "subtypes": [], @@ -248,16 +250,6 @@ "method_name": "" } }, - "ResolveError": { - "name": "ResolveError", - "subtypes": [ - "MethodEmptyName", - "MethodUTF8Error", - "MethodNotFound", - "MethodInvalidSignature" - ], - "props": {} - }, "Serialization": { "name": "Serialization", "subtypes": [], @@ -268,6 +260,14 @@ "subtypes": [], "props": {} }, + "VMError": { + "name": "VMError", + "subtypes": [ + "FunctionExecError", + "StorageError" + ], + "props": {} + }, "WasmTrap": { "name": "WasmTrap", "subtypes": [], @@ -340,6 +340,25 @@ "public_key": "" } }, + "BalanceMismatchError": { + "name": "BalanceMismatchError", + "subtypes": [], + "props": { + "final_accounts_balance": "", + "final_postponed_receipts_balance": "", + "incoming_receipts_balance": "", + "incoming_validator_rewards": "", + "initial_accounts_balance": "", + "initial_postponed_receipts_balance": "", + "new_delayed_receipts_balance": "", + "outgoing_receipts_balance": "", + "processed_delayed_receipts_balance": "", + "total_balance_burnt": "", + "total_balance_slashed": "", + "total_rent_paid": "", + "total_validator_reward": "" + } + }, "CostOverflow": { "name": "CostOverflow", "subtypes": [], @@ -381,8 +400,8 @@ "subtypes": [], "props": {} }, - "InvalidAccessKey": { - "name": "InvalidAccessKey", + "InvalidAccessKeyError": { + "name": "InvalidAccessKeyError", "subtypes": [ "AccessKeyNotFound", "ReceiverMismatch", @@ -533,54 +552,6 @@ "name": "Timeout", "subtypes": [], "props": {} - }, - "MethodResolveError": { - "name": "MethodResolveError", - "subtypes": [ - "MethodEmptyName", - "MethodUTF8Error", - "MethodNotFound", - "MethodInvalidSignature" - ], - "props": {} - }, - "VMError": { - "name": "VMError", - "subtypes": [ - "FunctionExecError", - "StorageError" - ], - "props": {} - }, - "BalanceMismatchError": { - "name": "BalanceMismatchError", - "subtypes": [], - "props": { - "final_accounts_balance": "", - "final_postponed_receipts_balance": "", - "incoming_receipts_balance": "", - "incoming_validator_rewards": "", - "initial_accounts_balance": "", - "initial_postponed_receipts_balance": "", - "new_delayed_receipts_balance": "", - "outgoing_receipts_balance": "", - "processed_delayed_receipts_balance": "", - "total_balance_burnt": "", - "total_balance_slashed": "", - "total_rent_paid": "", - "total_validator_reward": "" - } - }, - "InvalidAccessKeyError": { - "name": "InvalidAccessKeyError", - "subtypes": [ - "AccessKeyNotFound", - "ReceiverMismatch", - "MethodNameMismatch", - "ActionError", - "NotEnoughAllowance" - ], - "props": {} } } } \ No newline at end of file diff --git a/near/Cargo.toml b/near/Cargo.toml index b861cacf2ee..95e5eda528b 100644 --- a/near/Cargo.toml +++ b/near/Cargo.toml @@ -40,6 +40,3 @@ near-epoch-manager = { path = "../chain/epoch_manager" } [dev-dependencies] tempdir = "0.3" testlib = { path = "../test-utils/testlib" } - -[features] -dump_errors_schema = ["near-primitives/dump_errors_schema", "near-jsonrpc/dump_errors_schema", "node-runtime/dump_errors_schema"] diff --git a/scripts/build_errors_schema.sh b/scripts/build_errors_schema.sh deleted file mode 100755 index 70da0bc314f..00000000000 --- a/scripts/build_errors_schema.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cargo build --features dump_errors_schema --manifest-path near/Cargo.toml -cp ./target/rpc_errors_schema.json ./res/rpc_errors_schema.json From d9f3c6d65dcd81c2858c9eb94a2632ed7accf28f Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 21 Jan 2020 16:47:59 +0300 Subject: [PATCH 46/48] fix rpc-errors test --- tools/rpctypegen/core/src/lib.rs | 102 +++++++++++++++++-------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/tools/rpctypegen/core/src/lib.rs b/tools/rpctypegen/core/src/lib.rs index d41825acd6a..b2f64b9b1e0 100644 --- a/tools/rpctypegen/core/src/lib.rs +++ b/tools/rpctypegen/core/src/lib.rs @@ -223,52 +223,62 @@ mod tests { ); let expected: BTreeMap = serde_json::from_str( r#" - { - "AccountAlreadyExists": { - "name": "AccountAlreadyExists", - "subtypes": [], - "props": { - "account_id": "" - } - }, - "ActionError": { - "name": "ActionError", - "subtypes": [ - "AccountAlreadyExists" - ], - "props": { - "index": "" - } - }, - "InvalidSignerId": { - "name": "InvalidSignerId", - "subtypes": [], - "props": { - "signer_id": "" - } - }, - "InvalidTxError": { - "name": "InvalidTxError", - "subtypes": [ - "InvalidAccessKeyError", - "InvalidSignerId" - ], - "props": {} - }, - InvalidAccessKeyError: { - "name": "InvalidAccessKeyError", - "subtypes": [], - "props: {} - } - "TxExecutionError": { - "name": "TxExecutionError", - "subtypes": [ - "ActionError", - "InvalidTxError" - ], - "props": {} - } - }"#, + { + "AccessKeyNotFound": { + "name": "AccessKeyNotFound", + "subtypes": [], + "props": { + "account_id": "", + "public_key": "" + } + }, + "AccountAlreadyExists": { + "name": "AccountAlreadyExists", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "ActionError": { + "name": "ActionError", + "subtypes": [ + "AccountAlreadyExists" + ], + "props": { + "index": "" + } + }, + "InvalidAccessKeyError": { + "name": "InvalidAccessKeyError", + "subtypes": [ + "AccessKeyNotFound" + ], + "props": {} + }, + "InvalidSignerId": { + "name": "InvalidSignerId", + "subtypes": [], + "props": { + "signer_id": "" + } + }, + "InvalidTxError": { + "name": "InvalidTxError", + "subtypes": [ + "InvalidAccessKeyError", + "InvalidSignerId" + ], + "props": {} + }, + "TxExecutionError": { + "name": "TxExecutionError", + "subtypes": [ + "ActionError", + "InvalidTxError" + ], + "props": {} + } + }"#, ) .unwrap(); assert_eq!( From e44e157c60c833987805517db4633d97a0f5a582 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 21 Jan 2020 18:20:20 +0300 Subject: [PATCH 47/48] ActionError -> RequiresFullAccess --- chain/jsonrpc/res/rpc_errors_schema.json | 7 ++++++- core/primitives/src/errors.rs | 13 ++++++++----- runtime/runtime/src/lib.rs | 4 ++-- test-utils/testlib/src/standard_test_cases.rs | 2 +- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/chain/jsonrpc/res/rpc_errors_schema.json b/chain/jsonrpc/res/rpc_errors_schema.json index 1f8e8a24753..1b97a6b787c 100644 --- a/chain/jsonrpc/res/rpc_errors_schema.json +++ b/chain/jsonrpc/res/rpc_errors_schema.json @@ -406,7 +406,7 @@ "AccessKeyNotFound", "ReceiverMismatch", "MethodNameMismatch", - "ActionError", + "RequiresFullAccess", "NotEnoughAllowance" ], "props": {} @@ -552,6 +552,11 @@ "name": "Timeout", "subtypes": [], "props": {} + }, + "RequiresFullAccess": { + "name": "RequiresFullAccess", + "subtypes": [], + "props": {} } } } \ No newline at end of file diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index 83a02933726..d4a7d032071 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -129,8 +129,8 @@ pub enum InvalidAccessKeyError { ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, /// Transaction method name isn't allowed by the access key MethodNameMismatch { method_name: String }, - /// The used access key requires exactly one `FunctionCall` action - ActionError, + /// Transaction requires a full access token + RequiresFullAccess, /// Access Key does not have enough allowance to cover transaction cost NotEnoughAllowance { account_id: AccountId, @@ -275,9 +275,12 @@ impl Display for InvalidAccessKeyError { "Transaction method name {:?} isn't allowed by the access key", method_name ), - InvalidAccessKeyError::ActionError => { - write!(f, "The used access key requires exactly one FunctionCall action") - } + InvalidAccessKeyError::RequiresFullAccess => write!( + f, + "The transaction contains more then one action, but it was signed \ + with an access key which allows transaction to apply only one specific action. \ + To apply more then one actions TX must be signed with a full access key" + ), InvalidAccessKeyError::NotEnoughAllowance { account_id, public_key, diff --git a/runtime/runtime/src/lib.rs b/runtime/runtime/src/lib.rs index f896e6030dc..7b5aae250b3 100644 --- a/runtime/runtime/src/lib.rs +++ b/runtime/runtime/src/lib.rs @@ -311,7 +311,7 @@ impl Runtime { { if transaction.actions.len() != 1 { return Err(InvalidTxError::InvalidAccessKeyError( - InvalidAccessKeyError::ActionError, + InvalidAccessKeyError::RequiresFullAccess, ) .into()); } @@ -340,7 +340,7 @@ impl Runtime { } } else { return Err(InvalidTxError::InvalidAccessKeyError( - InvalidAccessKeyError::ActionError, + InvalidAccessKeyError::RequiresFullAccess, ) .into()); } diff --git a/test-utils/testlib/src/standard_test_cases.rs b/test-utils/testlib/src/standard_test_cases.rs index 0fa44ad2baf..20f87ff0f1e 100644 --- a/test-utils/testlib/src/standard_test_cases.rs +++ b/test-utils/testlib/src/standard_test_cases.rs @@ -947,7 +947,7 @@ pub fn test_access_key_reject_non_function_call(node: impl Node) { assert_eq!( transaction_result, ServerError::TxExecutionError(TxExecutionError::InvalidTxError( - InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::ActionError) + InvalidTxError::InvalidAccessKeyError(InvalidAccessKeyError::RequiresFullAccess) )) ); } From 983478b799c4a90ecacbc694e0eef36e43679265 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 22 Jan 2020 16:00:29 +0300 Subject: [PATCH 48/48] fix comment Co-Authored-By: Evgeny Kuzyakov --- core/primitives/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index d4a7d032071..679da83c88b 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -129,7 +129,7 @@ pub enum InvalidAccessKeyError { ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, /// Transaction method name isn't allowed by the access key MethodNameMismatch { method_name: String }, - /// Transaction requires a full access token + /// Transaction requires a full permission access key. RequiresFullAccess, /// Access Key does not have enough allowance to cover transaction cost NotEnoughAllowance {