From 86b2cf15ca0426331c74b7cd1405e5a8c5e85078 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Fri, 14 Jul 2023 14:26:46 +0300 Subject: [PATCH] near-vm-runner: move protocol-sensitive error schemas to near-primitives (#9295) This allows to drop a dependency on `near-account-id` and `near-rpc-error-macro` crates and brings us ever-so-slightly closer to having a contract runtime suitable for limited replayability. But more importantly this also solves a long-term pain point in the contract runtime where we never really felt too confident modifying errors that are output from the contract runtime due to our fears about it possibly affecting the protocol output. Now that the schemas are outside of `nearcore/runtime` there's also a neat rule of thumb: anything goes inside `nearcore/runtime` (as far as errors are concerned.) --- Cargo.lock | 2 - chain/jsonrpc/res/rpc_errors_schema.json | 854 +++++++++--------- core/primitives/src/errors.rs | 298 +++++- .../limit_contract_functions_number.rs | 7 +- .../src/tests/runtime/test_evil_contracts.rs | 5 +- .../src/tests/standard_cases/mod.rs | 12 +- runtime/near-vm-runner/Cargo.toml | 4 - runtime/near-vm-runner/src/logic/errors.rs | 215 ++--- .../src/logic/tests/promises.rs | 13 +- runtime/runtime/Cargo.toml | 1 - runtime/runtime/src/actions.rs | 8 +- 11 files changed, 815 insertions(+), 604 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff92cbade30..c212b8e5a95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4361,11 +4361,9 @@ dependencies = [ "hex", "loupe", "memoffset 0.8.0", - "near-account-id", "near-crypto", "near-primitives", "near-primitives-core", - "near-rpc-error-macro", "near-stdx", "near-test-contracts", "near-vm-compiler", diff --git a/chain/jsonrpc/res/rpc_errors_schema.json b/chain/jsonrpc/res/rpc_errors_schema.json index 5bd88fcd74b..1279c61751e 100644 --- a/chain/jsonrpc/res/rpc_errors_schema.json +++ b/chain/jsonrpc/res/rpc_errors_schema.json @@ -1,425 +1,5 @@ { "schema": { - "AltBn128InvalidInput": { - "name": "AltBn128InvalidInput", - "subtypes": [], - "props": { - "msg": "" - } - }, - "BadUTF16": { - "name": "BadUTF16", - "subtypes": [], - "props": {} - }, - "BadUTF8": { - "name": "BadUTF8", - "subtypes": [], - "props": {} - }, - "BalanceExceeded": { - "name": "BalanceExceeded", - "subtypes": [], - "props": {} - }, - "CallIndirectOOB": { - "name": "CallIndirectOOB", - "subtypes": [], - "props": {} - }, - "CannotAppendActionToJointPromise": { - "name": "CannotAppendActionToJointPromise", - "subtypes": [], - "props": {} - }, - "CannotReturnJointPromise": { - "name": "CannotReturnJointPromise", - "subtypes": [], - "props": {} - }, - "CodeDoesNotExist": { - "name": "CodeDoesNotExist", - "subtypes": [], - "props": { - "account_id": "" - } - }, - "CompilationError": { - "name": "CompilationError", - "subtypes": [ - "CodeDoesNotExist", - "PrepareError", - "WasmerCompileError" - ], - "props": {} - }, - "ContractSizeExceeded": { - "name": "ContractSizeExceeded", - "subtypes": [], - "props": { - "limit": "", - "size": "" - } - }, - "Deprecated": { - "name": "Deprecated", - "subtypes": [], - "props": { - "method_name": "" - } - }, - "Deserialization": { - "name": "Deserialization", - "subtypes": [], - "props": {} - }, - "ECRecoverError": { - "name": "ECRecoverError", - "subtypes": [], - "props": { - "msg": "" - } - }, - "Ed25519VerifyInvalidInput": { - "name": "Ed25519VerifyInvalidInput", - "subtypes": [], - "props": { - "msg": "" - } - }, - "EmptyMethodName": { - "name": "EmptyMethodName", - "subtypes": [], - "props": {} - }, - "GasExceeded": { - "name": "GasExceeded", - "subtypes": [], - "props": {} - }, - "GasInstrumentation": { - "name": "GasInstrumentation", - "subtypes": [], - "props": {} - }, - "GasLimitExceeded": { - "name": "GasLimitExceeded", - "subtypes": [], - "props": {} - }, - "GenericTrap": { - "name": "GenericTrap", - "subtypes": [], - "props": {} - }, - "GuestPanic": { - "name": "GuestPanic", - "subtypes": [], - "props": { - "panic_msg": "" - } - }, - "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", - "NumberOfLogsExceeded", - "KeyLengthExceeded", - "ValueLengthExceeded", - "TotalLogLengthExceeded", - "NumberPromisesExceeded", - "NumberInputDataDependenciesExceeded", - "ReturnedValueLengthExceeded", - "ContractSizeExceeded", - "Deprecated", - "ECRecoverError", - "AltBn128InvalidInput", - "Ed25519VerifyInvalidInput" - ], - "props": {} - }, - "IllegalArithmetic": { - "name": "IllegalArithmetic", - "subtypes": [], - "props": {} - }, - "IncorrectCallIndirectSignature": { - "name": "IncorrectCallIndirectSignature", - "subtypes": [], - "props": {} - }, - "IndirectCallToNull": { - "name": "IndirectCallToNull", - "subtypes": [], - "props": {} - }, - "Instantiate": { - "name": "Instantiate", - "subtypes": [], - "props": {} - }, - "IntegerOverflow": { - "name": "IntegerOverflow", - "subtypes": [], - "props": {} - }, - "InternalMemoryDeclared": { - "name": "InternalMemoryDeclared", - "subtypes": [], - "props": {} - }, - "InvalidAccountId": { - "name": "InvalidAccountId", - "subtypes": [], - "props": { - "account_id": "" - } - }, - "InvalidIteratorIndex": { - "name": "InvalidIteratorIndex", - "subtypes": [], - "props": { - "iterator_index": "" - } - }, - "InvalidMethodName": { - "name": "InvalidMethodName", - "subtypes": [], - "props": {} - }, - "InvalidPromiseIndex": { - "name": "InvalidPromiseIndex", - "subtypes": [], - "props": { - "promise_idx": "" - } - }, - "InvalidPromiseResultIndex": { - "name": "InvalidPromiseResultIndex", - "subtypes": [], - "props": { - "result_idx": "" - } - }, - "InvalidPublicKey": { - "name": "InvalidPublicKey", - "subtypes": [], - "props": {} - }, - "InvalidReceiptIndex": { - "name": "InvalidReceiptIndex", - "subtypes": [], - "props": { - "receipt_index": "" - } - }, - "InvalidRegisterId": { - "name": "InvalidRegisterId", - "subtypes": [], - "props": { - "register_id": "" - } - }, - "IteratorWasInvalidated": { - "name": "IteratorWasInvalidated", - "subtypes": [], - "props": { - "iterator_index": "" - } - }, - "KeyLengthExceeded": { - "name": "KeyLengthExceeded", - "subtypes": [], - "props": { - "length": "", - "limit": "" - } - }, - "Memory": { - "name": "Memory", - "subtypes": [], - "props": {} - }, - "MemoryAccessViolation": { - "name": "MemoryAccessViolation", - "subtypes": [], - "props": {} - }, - "MemoryOutOfBounds": { - "name": "MemoryOutOfBounds", - "subtypes": [], - "props": {} - }, - "MethodEmptyName": { - "name": "MethodEmptyName", - "subtypes": [], - "props": {} - }, - "MethodInvalidSignature": { - "name": "MethodInvalidSignature", - "subtypes": [], - "props": {} - }, - "MethodNotFound": { - "name": "MethodNotFound", - "subtypes": [], - "props": {} - }, - "MethodResolveError": { - "name": "MethodResolveError", - "subtypes": [ - "MethodEmptyName", - "MethodNotFound", - "MethodInvalidSignature" - ], - "props": {} - }, - "MisalignedAtomicAccess": { - "name": "MisalignedAtomicAccess", - "subtypes": [], - "props": {} - }, - "NumberInputDataDependenciesExceeded": { - "name": "NumberInputDataDependenciesExceeded", - "subtypes": [], - "props": { - "limit": "", - "number_of_input_data_dependencies": "" - } - }, - "NumberOfLogsExceeded": { - "name": "NumberOfLogsExceeded", - "subtypes": [], - "props": { - "limit": "" - } - }, - "NumberPromisesExceeded": { - "name": "NumberPromisesExceeded", - "subtypes": [], - "props": { - "limit": "", - "number_of_promises": "" - } - }, - "PrepareError": { - "name": "PrepareError", - "subtypes": [ - "Serialization", - "Deserialization", - "InternalMemoryDeclared", - "GasInstrumentation", - "StackHeightInstrumentation", - "Instantiate", - "Memory", - "TooManyFunctions", - "TooManyLocals" - ], - "props": {} - }, - "ProhibitedInView": { - "name": "ProhibitedInView", - "subtypes": [], - "props": { - "method_name": "" - } - }, - "ReturnedValueLengthExceeded": { - "name": "ReturnedValueLengthExceeded", - "subtypes": [], - "props": { - "length": "", - "limit": "" - } - }, - "Serialization": { - "name": "Serialization", - "subtypes": [], - "props": {} - }, - "StackHeightInstrumentation": { - "name": "StackHeightInstrumentation", - "subtypes": [], - "props": {} - }, - "StackOverflow": { - "name": "StackOverflow", - "subtypes": [], - "props": {} - }, - "TooManyFunctions": { - "name": "TooManyFunctions", - "subtypes": [], - "props": {} - }, - "TooManyLocals": { - "name": "TooManyLocals", - "subtypes": [], - "props": {} - }, - "TotalLogLengthExceeded": { - "name": "TotalLogLengthExceeded", - "subtypes": [], - "props": { - "length": "", - "limit": "" - } - }, - "Unreachable": { - "name": "Unreachable", - "subtypes": [], - "props": {} - }, - "ValueLengthExceeded": { - "name": "ValueLengthExceeded", - "subtypes": [], - "props": { - "length": "", - "limit": "" - } - }, - "WasmTrap": { - "name": "WasmTrap", - "subtypes": [ - "Unreachable", - "IncorrectCallIndirectSignature", - "MemoryOutOfBounds", - "CallIndirectOOB", - "IllegalArithmetic", - "MisalignedAtomicAccess", - "IndirectCallToNull", - "StackOverflow", - "GenericTrap" - ], - "props": {} - }, - "WasmerCompileError": { - "name": "WasmerCompileError", - "subtypes": [], - "props": { - "msg": "" - } - }, "AccessKeyNotFound": { "name": "AccessKeyNotFound", "subtypes": [], @@ -524,6 +104,28 @@ "total_number_of_bytes": "" } }, + "AltBn128InvalidInput": { + "name": "AltBn128InvalidInput", + "subtypes": [], + "props": { + "msg": "" + } + }, + "BadUTF16": { + "name": "BadUTF16", + "subtypes": [], + "props": {} + }, + "BadUTF8": { + "name": "BadUTF8", + "subtypes": [], + "props": {} + }, + "BalanceExceeded": { + "name": "BalanceExceeded", + "subtypes": [], + "props": {} + }, "BalanceMismatchError": { "name": "BalanceMismatchError", "subtypes": [], @@ -542,6 +144,45 @@ "tx_burnt_amount": "" } }, + "CallIndirectOOB": { + "name": "CallIndirectOOB", + "subtypes": [], + "props": {} + }, + "CannotAppendActionToJointPromise": { + "name": "CannotAppendActionToJointPromise", + "subtypes": [], + "props": {} + }, + "CannotReturnJointPromise": { + "name": "CannotReturnJointPromise", + "subtypes": [], + "props": {} + }, + "CodeDoesNotExist": { + "name": "CodeDoesNotExist", + "subtypes": [], + "props": { + "account_id": "" + } + }, + "CompilationError": { + "name": "CompilationError", + "subtypes": [ + "CodeDoesNotExist", + "PrepareError", + "WasmerCompileError" + ], + "props": {} + }, + "ContractSizeExceeded": { + "name": "ContractSizeExceeded", + "subtypes": [], + "props": { + "limit": "", + "size": "" + } + }, "CostOverflow": { "name": "CostOverflow", "subtypes": [], @@ -635,6 +276,37 @@ "subtypes": [], "props": {} }, + "Deprecated": { + "name": "Deprecated", + "subtypes": [], + "props": { + "method_name": "" + } + }, + "Deserialization": { + "name": "Deserialization", + "subtypes": [], + "props": {} + }, + "ECRecoverError": { + "name": "ECRecoverError", + "subtypes": [], + "props": { + "msg": "" + } + }, + "Ed25519VerifyInvalidInput": { + "name": "Ed25519VerifyInvalidInput", + "subtypes": [], + "props": { + "msg": "" + } + }, + "EmptyMethodName": { + "name": "EmptyMethodName", + "subtypes": [], + "props": {} + }, "Expired": { "name": "Expired", "subtypes": [], @@ -648,16 +320,102 @@ "limit": "" } }, - "FunctionCallMethodNameLengthExceeded": { - "name": "FunctionCallMethodNameLengthExceeded", + "FunctionCallMethodNameLengthExceeded": { + "name": "FunctionCallMethodNameLengthExceeded", + "subtypes": [], + "props": { + "length": "", + "limit": "" + } + }, + "FunctionCallZeroAttachedGas": { + "name": "FunctionCallZeroAttachedGas", + "subtypes": [], + "props": {} + }, + "GasExceeded": { + "name": "GasExceeded", + "subtypes": [], + "props": {} + }, + "GasInstrumentation": { + "name": "GasInstrumentation", + "subtypes": [], + "props": {} + }, + "GasLimitExceeded": { + "name": "GasLimitExceeded", + "subtypes": [], + "props": {} + }, + "GenericTrap": { + "name": "GenericTrap", + "subtypes": [], + "props": {} + }, + "GuestPanic": { + "name": "GuestPanic", + "subtypes": [], + "props": { + "panic_msg": "" + } + }, + "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", + "NumberOfLogsExceeded", + "KeyLengthExceeded", + "ValueLengthExceeded", + "TotalLogLengthExceeded", + "NumberPromisesExceeded", + "NumberInputDataDependenciesExceeded", + "ReturnedValueLengthExceeded", + "ContractSizeExceeded", + "Deprecated", + "ECRecoverError", + "AltBn128InvalidInput", + "Ed25519VerifyInvalidInput" + ], + "props": {} + }, + "IllegalArithmetic": { + "name": "IllegalArithmetic", + "subtypes": [], + "props": {} + }, + "IncorrectCallIndirectSignature": { + "name": "IncorrectCallIndirectSignature", + "subtypes": [], + "props": {} + }, + "IndirectCallToNull": { + "name": "IndirectCallToNull", "subtypes": [], - "props": { - "length": "", - "limit": "" - } + "props": {} }, - "FunctionCallZeroAttachedGas": { - "name": "FunctionCallZeroAttachedGas", + "Instantiate": { + "name": "Instantiate", "subtypes": [], "props": {} }, @@ -670,6 +428,16 @@ "stake": "" } }, + "IntegerOverflow": { + "name": "IntegerOverflow", + "subtypes": [], + "props": {} + }, + "InternalMemoryDeclared": { + "name": "InternalMemoryDeclared", + "subtypes": [], + "props": {} + }, "InvalidAccessKeyError": { "name": "InvalidAccessKeyError", "subtypes": [ @@ -682,6 +450,11 @@ ], "props": {} }, + "InvalidAccountId": { + "name": "InvalidAccountId", + "subtypes": [], + "props": {} + }, "InvalidChain": { "name": "InvalidChain", "subtypes": [], @@ -694,6 +467,18 @@ "account_id": "" } }, + "InvalidIteratorIndex": { + "name": "InvalidIteratorIndex", + "subtypes": [], + "props": { + "iterator_index": "" + } + }, + "InvalidMethodName": { + "name": "InvalidMethodName", + "subtypes": [], + "props": {} + }, "InvalidNonce": { "name": "InvalidNonce", "subtypes": [], @@ -709,6 +494,32 @@ "account_id": "" } }, + "InvalidPromiseIndex": { + "name": "InvalidPromiseIndex", + "subtypes": [], + "props": { + "promise_idx": "" + } + }, + "InvalidPromiseResultIndex": { + "name": "InvalidPromiseResultIndex", + "subtypes": [], + "props": { + "result_idx": "" + } + }, + "InvalidPublicKey": { + "name": "InvalidPublicKey", + "subtypes": [], + "props": {} + }, + "InvalidReceiptIndex": { + "name": "InvalidReceiptIndex", + "subtypes": [], + "props": { + "receipt_index": "" + } + }, "InvalidReceiverId": { "name": "InvalidReceiverId", "subtypes": [], @@ -716,6 +527,13 @@ "account_id": "" } }, + "InvalidRegisterId": { + "name": "InvalidRegisterId", + "subtypes": [], + "props": { + "register_id": "" + } + }, "InvalidSignature": { "name": "InvalidSignature", "subtypes": [], @@ -748,6 +566,21 @@ ], "props": {} }, + "IteratorWasInvalidated": { + "name": "IteratorWasInvalidated", + "subtypes": [], + "props": { + "iterator_index": "" + } + }, + "KeyLengthExceeded": { + "name": "KeyLengthExceeded", + "subtypes": [], + "props": { + "length": "", + "limit": "" + } + }, "LackBalanceForState": { "name": "LackBalanceForState", "subtypes": [], @@ -756,6 +589,31 @@ "amount": "" } }, + "Memory": { + "name": "Memory", + "subtypes": [], + "props": {} + }, + "MemoryAccessViolation": { + "name": "MemoryAccessViolation", + "subtypes": [], + "props": {} + }, + "MemoryOutOfBounds": { + "name": "MemoryOutOfBounds", + "subtypes": [], + "props": {} + }, + "MethodEmptyName": { + "name": "MethodEmptyName", + "subtypes": [], + "props": {} + }, + "MethodInvalidSignature": { + "name": "MethodInvalidSignature", + "subtypes": [], + "props": {} + }, "MethodNameMismatch": { "name": "MethodNameMismatch", "subtypes": [], @@ -763,6 +621,25 @@ "method_name": "" } }, + "MethodNotFound": { + "name": "MethodNotFound", + "subtypes": [], + "props": {} + }, + "MethodResolveError": { + "name": "MethodResolveError", + "subtypes": [ + "MethodEmptyName", + "MethodNotFound", + "MethodInvalidSignature" + ], + "props": {} + }, + "MisalignedAtomicAccess": { + "name": "MisalignedAtomicAccess", + "subtypes": [], + "props": {} + }, "NonceTooLarge": { "name": "NonceTooLarge", "subtypes": [], @@ -790,6 +667,29 @@ "signer_id": "" } }, + "NumberInputDataDependenciesExceeded": { + "name": "NumberInputDataDependenciesExceeded", + "subtypes": [], + "props": { + "limit": "", + "number_of_input_data_dependencies": "" + } + }, + "NumberOfLogsExceeded": { + "name": "NumberOfLogsExceeded", + "subtypes": [], + "props": { + "limit": "" + } + }, + "NumberPromisesExceeded": { + "name": "NumberPromisesExceeded", + "subtypes": [], + "props": { + "limit": "", + "number_of_promises": "" + } + }, "OnlyImplicitAccountCreationAllowed": { "name": "OnlyImplicitAccountCreationAllowed", "subtypes": [], @@ -797,6 +697,28 @@ "account_id": "" } }, + "PrepareError": { + "name": "PrepareError", + "subtypes": [ + "Serialization", + "Deserialization", + "InternalMemoryDeclared", + "GasInstrumentation", + "StackHeightInstrumentation", + "Instantiate", + "Memory", + "TooManyFunctions", + "TooManyLocals" + ], + "props": {} + }, + "ProhibitedInView": { + "name": "ProhibitedInView", + "subtypes": [], + "props": { + "method_name": "" + } + }, "ReceiptValidationError": { "name": "ReceiptValidationError", "subtypes": [ @@ -823,6 +745,19 @@ "subtypes": [], "props": {} }, + "ReturnedValueLengthExceeded": { + "name": "ReturnedValueLengthExceeded", + "subtypes": [], + "props": { + "length": "", + "limit": "" + } + }, + "Serialization": { + "name": "Serialization", + "subtypes": [], + "props": {} + }, "SignerDoesNotExist": { "name": "SignerDoesNotExist", "subtypes": [], @@ -830,6 +765,34 @@ "signer_id": "" } }, + "StackHeightInstrumentation": { + "name": "StackHeightInstrumentation", + "subtypes": [], + "props": {} + }, + "StackOverflow": { + "name": "StackOverflow", + "subtypes": [], + "props": {} + }, + "TooManyFunctions": { + "name": "TooManyFunctions", + "subtypes": [], + "props": {} + }, + "TooManyLocals": { + "name": "TooManyLocals", + "subtypes": [], + "props": {} + }, + "TotalLogLengthExceeded": { + "name": "TotalLogLengthExceeded", + "subtypes": [], + "props": { + "length": "", + "limit": "" + } + }, "TotalNumberOfActionsExceeded": { "name": "TotalNumberOfActionsExceeded", "subtypes": [], @@ -879,6 +842,11 @@ ], "props": {} }, + "Unreachable": { + "name": "Unreachable", + "subtypes": [], + "props": {} + }, "UnsuitableStakingKey": { "name": "UnsuitableStakingKey", "subtypes": [], @@ -894,6 +862,36 @@ "version": "" } }, + "ValueLengthExceeded": { + "name": "ValueLengthExceeded", + "subtypes": [], + "props": { + "length": "", + "limit": "" + } + }, + "WasmTrap": { + "name": "WasmTrap", + "subtypes": [ + "Unreachable", + "IncorrectCallIndirectSignature", + "MemoryOutOfBounds", + "CallIndirectOOB", + "IllegalArithmetic", + "MisalignedAtomicAccess", + "IndirectCallToNull", + "StackOverflow", + "GenericTrap" + ], + "props": {} + }, + "WasmerCompileError": { + "name": "WasmerCompileError", + "subtypes": [], + "props": { + "msg": "" + } + }, "Closed": { "name": "Closed", "subtypes": [], diff --git a/core/primitives/src/errors.rs b/core/primitives/src/errors.rs index f1678de9336..9ede1561aba 100644 --- a/core/primitives/src/errors.rs +++ b/core/primitives/src/errors.rs @@ -5,7 +5,6 @@ use borsh::{BorshDeserialize, BorshSerialize}; use near_crypto::PublicKey; use near_primitives_core::types::ProtocolVersion; use near_rpc_error_macro::RpcError; -use near_vm_runner::logic::errors::FunctionCallErrorSer; use std::fmt::{Debug, Display}; /// Error returned in the ExecutionOutcome in case of failure @@ -469,7 +468,7 @@ pub enum ActionErrorKind { minimum_stake: Balance, }, /// An error occurred during a `FunctionCall` Action, parameter is debug message. - FunctionCallError(FunctionCallErrorSer), + FunctionCallError(FunctionCallError), /// Error occurs when a new `ActionReceipt` created by the `FunctionCall` action fails /// receipt validation. NewReceiptValidationError(ReceiptValidationError), @@ -897,3 +896,298 @@ impl From for EpochError { EpochError::IOErr(error.to_string()) } } + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + BorshDeserialize, + BorshSerialize, + RpcError, + serde::Deserialize, + serde::Serialize, +)] +/// Error that can occur while preparing or executing Wasm smart-contract. +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, + /// Contract contains too many functions. + TooManyFunctions, + /// Contract contains too many locals. + TooManyLocals, +} + +/// A kind of a trap happened during execution of a binary +#[derive( + Debug, + Clone, + PartialEq, + Eq, + BorshDeserialize, + BorshSerialize, + RpcError, + serde::Deserialize, + serde::Serialize, + strum::IntoStaticStr, +)] +pub enum WasmTrap { + /// An `unreachable` opcode was executed. + Unreachable, + /// Call indirect incorrect signature trap. + IncorrectCallIndirectSignature, + /// Memory out of bounds trap. + MemoryOutOfBounds, + /// Call indirect out of bounds trap. + CallIndirectOOB, + /// An arithmetic exception, e.g. divided by zero. + IllegalArithmetic, + /// Misaligned atomic access trap. + MisalignedAtomicAccess, + /// Indirect call to null. + IndirectCallToNull, + /// Stack overflow. + StackOverflow, + /// Generic trap. + GenericTrap, +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + BorshDeserialize, + BorshSerialize, + RpcError, + serde::Deserialize, + serde::Serialize, + strum::IntoStaticStr, +)] +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 }, + /// The total number of logs will exceed the limit. + NumberOfLogsExceeded { limit: u64 }, + /// The storage key length exceeded the limit. + KeyLengthExceeded { length: u64, limit: u64 }, + /// The storage value length exceeded the limit. + ValueLengthExceeded { length: u64, limit: u64 }, + /// The total log length exceeded the limit. + TotalLogLengthExceeded { length: u64, limit: u64 }, + /// The maximum number of promises within a FunctionCall exceeded the limit. + NumberPromisesExceeded { number_of_promises: u64, limit: u64 }, + /// The maximum number of input data dependencies exceeded the limit. + NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 }, + /// The returned value length exceeded the limit. + ReturnedValueLengthExceeded { length: u64, limit: u64 }, + /// The contract size for DeployContract action exceeded the limit. + ContractSizeExceeded { size: u64, limit: u64 }, + /// The host function was deprecated. + Deprecated { method_name: String }, + /// General errors for ECDSA recover. + ECRecoverError { msg: String }, + /// Invalid input to alt_bn128 familiy of functions (e.g., point which isn't + /// on the curve). + AltBn128InvalidInput { msg: String }, + /// Invalid input to ed25519 signature verification function (e.g. signature cannot be + /// derived from bytes). + Ed25519VerifyInvalidInput { msg: String }, +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + BorshDeserialize, + BorshSerialize, + RpcError, + serde::Deserialize, + serde::Serialize, + strum::IntoStaticStr, +)] +pub enum MethodResolveError { + MethodEmptyName, + MethodNotFound, + MethodInvalidSignature, +} + +#[derive( + Debug, + Clone, + PartialEq, + Eq, + BorshDeserialize, + BorshSerialize, + RpcError, + serde::Deserialize, + serde::Serialize, + strum::IntoStaticStr, +)] +pub enum CompilationError { + CodeDoesNotExist { + account_id: AccountId, + }, + PrepareError(PrepareError), + /// This is for defense in depth. + /// We expect our runtime-independent preparation code to fully catch all invalid wasms, + /// but, if it ever misses something we’ll emit this error + WasmerCompileError { + msg: String, + }, +} + +/// Serializable version of `near-vm-runner::FunctionCallError`. +/// +/// Must never reorder/remove elements, can only add new variants at the end (but do that very +/// carefully). It describes stable serialization format, and only used by serialization logic. +#[derive( + Debug, + Clone, + PartialEq, + Eq, + BorshDeserialize, + BorshSerialize, + serde::Serialize, + serde::Deserialize, +)] +pub enum FunctionCallError { + /// Wasm compilation error + CompilationError(CompilationError), + /// Wasm binary env link error + /// + /// Note: this is only to deserialize old data, use execution error for new data + LinkError { + msg: String, + }, + /// Import/export resolve error + MethodResolveError(MethodResolveError), + /// A trap happened during execution of a binary + /// + /// Note: this is only to deserialize old data, use execution error for new data + WasmTrap(WasmTrap), + WasmUnknownError, + /// Note: this is only to deserialize old data, use execution error for new data + HostError(HostError), + // Unused, can be reused by a future error but must be exactly one error to keep ExecutionError + // error borsh serialized at correct index + _EVMError, + ExecutionError(String), +} + +impl From for MethodResolveError { + fn from(outer_err: near_vm_runner::logic::errors::MethodResolveError) -> Self { + use near_vm_runner::logic::errors::MethodResolveError as MRE; + match outer_err { + MRE::MethodEmptyName => Self::MethodEmptyName, + MRE::MethodNotFound => Self::MethodNotFound, + MRE::MethodInvalidSignature => Self::MethodInvalidSignature, + } + } +} + +impl From for PrepareError { + fn from(outer_err: near_vm_runner::logic::errors::PrepareError) -> Self { + use near_vm_runner::logic::errors::PrepareError as PE; + match outer_err { + PE::Serialization => Self::Serialization, + PE::Deserialization => Self::Deserialization, + PE::InternalMemoryDeclared => Self::InternalMemoryDeclared, + PE::GasInstrumentation => Self::GasInstrumentation, + PE::StackHeightInstrumentation => Self::StackHeightInstrumentation, + PE::Instantiate => Self::Instantiate, + PE::Memory => Self::Memory, + PE::TooManyFunctions => Self::TooManyFunctions, + PE::TooManyLocals => Self::TooManyLocals, + } + } +} + +impl From for CompilationError { + fn from(outer_err: near_vm_runner::logic::errors::CompilationError) -> Self { + use near_vm_runner::logic::errors::CompilationError as CE; + match outer_err { + CE::CodeDoesNotExist { account_id } => Self::CodeDoesNotExist { + account_id: account_id.parse().expect("account_id in error must be valid"), + }, + CE::PrepareError(pe) => Self::PrepareError(pe.into()), + CE::WasmerCompileError { msg } => Self::WasmerCompileError { msg }, + } + } +} + +impl From for FunctionCallError { + fn from(outer_err: near_vm_runner::logic::errors::FunctionCallError) -> Self { + use near_vm_runner::logic::errors::FunctionCallError as FCE; + match outer_err { + FCE::CompilationError(e) => Self::CompilationError(e.into()), + FCE::MethodResolveError(e) => Self::MethodResolveError(e.into()), + // Note: We deliberately collapse all execution errors for + // serialization to make the DB representation less dependent + // on specific types in Rust code. + FCE::HostError(ref _e) => Self::ExecutionError(outer_err.to_string()), + FCE::LinkError { msg } => Self::ExecutionError(format!("Link Error: {}", msg)), + FCE::WasmTrap(ref _e) => Self::ExecutionError(outer_err.to_string()), + } + } +} diff --git a/integration-tests/src/tests/client/features/limit_contract_functions_number.rs b/integration-tests/src/tests/client/features/limit_contract_functions_number.rs index 5d5af25b4d5..29a7ad5dacd 100644 --- a/integration-tests/src/tests/client/features/limit_contract_functions_number.rs +++ b/integration-tests/src/tests/client/features/limit_contract_functions_number.rs @@ -4,11 +4,12 @@ use assert_matches::assert_matches; use near_chain::ChainGenesis; use near_chain_configs::Genesis; use near_client::test_utils::TestEnv; -use near_primitives::errors::{ActionErrorKind, TxExecutionError}; +use near_primitives::errors::{ + ActionErrorKind, CompilationError, FunctionCallError, PrepareError, TxExecutionError, +}; use near_primitives::runtime::config_store::RuntimeConfigStore; use near_primitives::version::ProtocolFeature; use near_primitives::views::FinalExecutionStatus; -use near_vm_runner::logic::errors::{CompilationError, FunctionCallErrorSer, PrepareError}; use nearcore::config::GenesisExt; fn verify_contract_limits_upgrade( @@ -64,7 +65,7 @@ fn verify_contract_limits_upgrade( status => panic!("expected transaction to fail, got {:?}", status), }; match e.kind { - ActionErrorKind::FunctionCallError(FunctionCallErrorSer::CompilationError( + ActionErrorKind::FunctionCallError(FunctionCallError::CompilationError( CompilationError::PrepareError(e), )) if e == expected_prepare_err => (), kind => panic!("got unexpected action error kind: {:?}", kind), diff --git a/integration-tests/src/tests/runtime/test_evil_contracts.rs b/integration-tests/src/tests/runtime/test_evil_contracts.rs index ef0ad89a2a4..e6c11c6783f 100644 --- a/integration-tests/src/tests/runtime/test_evil_contracts.rs +++ b/integration-tests/src/tests/runtime/test_evil_contracts.rs @@ -1,7 +1,6 @@ use crate::node::{Node, RuntimeNode}; -use near_primitives::errors::{ActionError, ActionErrorKind}; +use near_primitives::errors::{ActionError, ActionErrorKind, FunctionCallError}; use near_primitives::views::FinalExecutionStatus; -use near_vm_runner::logic::errors::FunctionCallErrorSer; use std::mem::size_of; use assert_matches::assert_matches; @@ -129,7 +128,7 @@ fn test_evil_abort() { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCallError(FunctionCallErrorSer::ExecutionError( + kind: ActionErrorKind::FunctionCallError(FunctionCallError::ExecutionError( "String encoding is bad UTF-16 sequence.".to_string() )) } diff --git a/integration-tests/src/tests/standard_cases/mod.rs b/integration-tests/src/tests/standard_cases/mod.rs index 38e94ba2a76..65a91e5ee20 100644 --- a/integration-tests/src/tests/standard_cases/mod.rs +++ b/integration-tests/src/tests/standard_cases/mod.rs @@ -9,7 +9,8 @@ use near_jsonrpc_primitives::errors::ServerError; use near_primitives::account::{AccessKey, AccessKeyPermission, FunctionCallPermission}; use near_primitives::config::{ActionCosts, ExtCosts}; use near_primitives::errors::{ - ActionError, ActionErrorKind, InvalidAccessKeyError, InvalidTxError, TxExecutionError, + ActionError, ActionErrorKind, FunctionCallError, InvalidAccessKeyError, InvalidTxError, + MethodResolveError, TxExecutionError, }; use near_primitives::hash::{hash, CryptoHash}; use near_primitives::types::{AccountId, Balance, TrieNodesCount}; @@ -17,7 +18,6 @@ use near_primitives::views::{ AccessKeyView, AccountView, ExecutionMetadataView, FinalExecutionOutcomeView, FinalExecutionStatus, }; -use near_vm_runner::logic::errors::{FunctionCallErrorSer, MethodResolveError}; use nearcore::config::{NEAR_BASE, TESTING_INIT_BALANCE, TESTING_INIT_STAKE}; use crate::node::Node; @@ -89,7 +89,7 @@ pub fn test_smart_contract_panic(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCallError(FunctionCallErrorSer::ExecutionError( + kind: ActionErrorKind::FunctionCallError(FunctionCallError::ExecutionError( "Smart contract panicked: WAT?".to_string() )) } @@ -127,7 +127,7 @@ pub fn test_smart_contract_bad_method_name(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCallError(FunctionCallErrorSer::MethodResolveError( + kind: ActionErrorKind::FunctionCallError(FunctionCallError::MethodResolveError( MethodResolveError::MethodNotFound )) } @@ -151,7 +151,7 @@ pub fn test_smart_contract_empty_method_name_with_no_tokens(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCallError(FunctionCallErrorSer::MethodResolveError( + kind: ActionErrorKind::FunctionCallError(FunctionCallError::MethodResolveError( MethodResolveError::MethodEmptyName )) } @@ -175,7 +175,7 @@ pub fn test_smart_contract_empty_method_name_with_tokens(node: impl Node) { FinalExecutionStatus::Failure( ActionError { index: Some(0), - kind: ActionErrorKind::FunctionCallError(FunctionCallErrorSer::MethodResolveError( + kind: ActionErrorKind::FunctionCallError(FunctionCallError::MethodResolveError( MethodResolveError::MethodEmptyName )) } diff --git a/runtime/near-vm-runner/Cargo.toml b/runtime/near-vm-runner/Cargo.toml index b739c731ff2..95c3dd4f7d1 100644 --- a/runtime/near-vm-runner/Cargo.toml +++ b/runtime/near-vm-runner/Cargo.toml @@ -36,10 +36,8 @@ tracing.workspace = true wasmparser.workspace = true wasmtime = { workspace = true, optional = true } -near-account-id.workspace = true near-crypto.workspace = true near-primitives-core.workspace = true -near-rpc-error-macro.workspace = true # Old versions of pwasm-utils we need to preserve backwards compatibility under # old protocol versions. @@ -126,8 +124,6 @@ nightly = [ sandbox = [] io_trace = [] -dump_errors_schema = ["near-rpc-error-macro/dump_errors_schema"] - # Use this feature to enable counting of fees and costs applied. costs_counting = [] diff --git a/runtime/near-vm-runner/src/logic/errors.rs b/runtime/near-vm-runner/src/logic/errors.rs index 42a8388f7aa..6dd35cc65ec 100644 --- a/runtime/near-vm-runner/src/logic/errors.rs +++ b/runtime/near-vm-runner/src/logic/errors.rs @@ -1,6 +1,4 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use near_account_id::AccountId; -use near_rpc_error_macro::RpcError; use std::any::Any; use std::fmt::{self, Error, Formatter}; use std::io; @@ -55,44 +53,7 @@ pub enum FunctionCallError { HostError(HostError), } -/// Serializable version of `FunctionCallError`. Must never reorder/remove elements, can only -/// add new variants at the end (but do that very carefully). -/// It describes stable serialization format, and only used by serialization logic. -#[derive( - Debug, - Clone, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - serde::Serialize, - serde::Deserialize, -)] -pub enum FunctionCallErrorSer { - /// Wasm compilation error - CompilationError(CompilationError), - /// Wasm binary env link error - /// - /// Note: this is only to deserialize old data, use execution error for new data - LinkError { - msg: String, - }, - /// Import/export resolve error - MethodResolveError(MethodResolveError), - /// A trap happened during execution of a binary - /// - /// Note: this is only to deserialize old data, use execution error for new data - WasmTrap(WasmTrap), - WasmUnknownError, - /// Note: this is only to deserialize old data, use execution error for new data - HostError(HostError), - // Unused, can be reused by a future error but must be exactly one error to keep ExecutionError - // error borsh serialized at correct index - _EVMError, - ExecutionError(String), -} - -#[derive(Debug, strum::IntoStaticStr, thiserror::Error)] +#[derive(Debug, thiserror::Error, strum::IntoStaticStr)] pub enum CacheError { #[error("cache read error")] ReadError(#[source] io::Error), @@ -104,18 +65,7 @@ pub enum CacheError { SerializationError { hash: [u8; 32] }, } /// A kind of a trap happened during execution of a binary -#[derive( - Debug, - Clone, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - RpcError, - serde::Deserialize, - serde::Serialize, - strum::IntoStaticStr, -)] +#[derive(Debug, Clone, PartialEq, Eq, strum::IntoStaticStr)] pub enum WasmTrap { /// An `unreachable` opcode was executed. Unreachable, @@ -137,39 +87,17 @@ pub enum WasmTrap { GenericTrap, } -#[derive( - Debug, - Clone, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - RpcError, - serde::Deserialize, - serde::Serialize, - strum::IntoStaticStr, -)] +#[derive(Debug, Clone, PartialEq, Eq, strum::IntoStaticStr)] pub enum MethodResolveError { MethodEmptyName, MethodNotFound, MethodInvalidSignature, } -#[derive( - Debug, - Clone, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - RpcError, - serde::Deserialize, - serde::Serialize, - strum::IntoStaticStr, -)] +#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, strum::IntoStaticStr)] pub enum CompilationError { CodeDoesNotExist { - account_id: AccountId, + account_id: Box, }, PrepareError(PrepareError), /// This is for defense in depth. @@ -180,17 +108,7 @@ pub enum CompilationError { }, } -#[derive( - Debug, - Clone, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - RpcError, - serde::Deserialize, - serde::Serialize, -)] +#[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. @@ -220,18 +138,7 @@ pub enum PrepareError { TooManyLocals, } -#[derive( - Debug, - Clone, - PartialEq, - Eq, - BorshDeserialize, - BorshSerialize, - RpcError, - serde::Deserialize, - serde::Serialize, - strum::IntoStaticStr, -)] +#[derive(Debug, Clone, PartialEq, Eq, strum::IntoStaticStr)] pub enum HostError { /// String encoding is bad UTF-16 sequence BadUTF16, @@ -259,8 +166,6 @@ pub enum HostError { 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 @@ -323,27 +228,6 @@ pub enum InconsistentStateError { IntegerOverflow, } -impl From for FunctionCallErrorSer { - fn from(outer_err: FunctionCallError) -> Self { - match outer_err { - FunctionCallError::CompilationError(e) => FunctionCallErrorSer::CompilationError(e), - FunctionCallError::MethodResolveError(e) => FunctionCallErrorSer::MethodResolveError(e), - // Note: We deliberately collapse all execution errors for - // serialization to make the DB representation less dependent - // on specific types in Rust code. - FunctionCallError::HostError(ref _e) => { - FunctionCallErrorSer::ExecutionError(outer_err.to_string()) - } - FunctionCallError::LinkError { msg } => { - FunctionCallErrorSer::ExecutionError(format!("Link Error: {}", msg)) - } - FunctionCallError::WasmTrap(ref _e) => { - FunctionCallErrorSer::ExecutionError(outer_err.to_string()) - } - } - } -} - impl From for VMLogicError { fn from(err: HostError) -> Self { VMLogicError::HostError(err) @@ -476,36 +360,81 @@ impl std::fmt::Display for HostError { BadUTF8 => write!(f, "String encoding is bad UTF-8 sequence."), BadUTF16 => write!(f, "String encoding is bad UTF-16 sequence."), GasExceeded => write!(f, "Exceeded the prepaid gas."), - GasLimitExceeded => write!(f, "Exceeded the maximum amount of gas allowed to burn per contract."), + 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 { panic_msg } => write!(f, "Smart contract panicked: {}", panic_msg), IntegerOverflow => write!(f, "Integer overflow."), - 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 { 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), + 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 { result_idx } => { + write!(f, "Accessed invalid promise result index: {:?}", result_idx) + } + InvalidRegisterId { register_id } => { + write!(f, "Accessed invalid register id: {:?}", register_id) + } MemoryAccessViolation => write!(f, "Accessed memory outside the bounds."), - InvalidReceiptIndex { receipt_index } => write!(f, "VM Logic returned an invalid receipt index: {:?}", receipt_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), - NumberOfLogsExceeded { limit } => write!(f, "The number of logs will exceed the limit {}", limit), - KeyLengthExceeded { length, limit } => write!(f, "The length of a storage key {} exceeds the limit {}", length, limit), - ValueLengthExceeded { length, limit } => write!(f, "The length of a storage value {} exceeds the limit {}", length, limit), - TotalLogLengthExceeded{ length, limit } => write!(f, "The length of a log message {} exceeds the limit {}", length, limit), - NumberPromisesExceeded { number_of_promises, limit } => write!(f, "The number of promises within a FunctionCall {} exceeds the limit {}", number_of_promises, limit), - NumberInputDataDependenciesExceeded { number_of_input_data_dependencies, limit } => write!(f, "The number of input data dependencies {} exceeds the limit {}", number_of_input_data_dependencies, limit), - ReturnedValueLengthExceeded { length, limit } => write!(f, "The length of a returned value {} exceeds the limit {}", length, limit), - ContractSizeExceeded { size, limit } => write!(f, "The size of a contract code in DeployContract action {} exceeds the limit {}", size, limit), - Deprecated {method_name}=> write!(f, "Attempted to call deprecated host function {}", method_name), + ProhibitedInView { method_name } => { + write!(f, "{} is not allowed in view calls", method_name) + } + NumberOfLogsExceeded { limit } => { + write!(f, "The number of logs will exceed the limit {}", limit) + } + KeyLengthExceeded { length, limit } => { + write!(f, "The length of a storage key {} exceeds the limit {}", length, limit) + } + ValueLengthExceeded { length, limit } => { + write!(f, "The length of a storage value {} exceeds the limit {}", length, limit) + } + TotalLogLengthExceeded { length, limit } => { + write!(f, "The length of a log message {} exceeds the limit {}", length, limit) + } + NumberPromisesExceeded { number_of_promises, limit } => write!( + f, + "The number of promises within a FunctionCall {} exceeds the limit {}", + number_of_promises, limit + ), + NumberInputDataDependenciesExceeded { number_of_input_data_dependencies, limit } => { + write!( + f, + "The number of input data dependencies {} exceeds the limit {}", + number_of_input_data_dependencies, limit + ) + } + ReturnedValueLengthExceeded { length, limit } => { + write!(f, "The length of a returned value {} exceeds the limit {}", length, limit) + } + ContractSizeExceeded { size, limit } => write!( + f, + "The size of a contract code in DeployContract action {} exceeds the limit {}", + size, limit + ), + Deprecated { method_name } => { + write!(f, "Attempted to call deprecated host function {}", method_name) + } AltBn128InvalidInput { msg } => write!(f, "AltBn128 invalid input: {}", msg), ECRecoverError { msg } => write!(f, "ECDSA recover error: {}", msg), - Ed25519VerifyInvalidInput { msg } => write!(f, "ED25519 signature verification error: {}", msg), + Ed25519VerifyInvalidInput { msg } => { + write!(f, "ED25519 signature verification error: {}", msg) + } } } } diff --git a/runtime/near-vm-runner/src/logic/tests/promises.rs b/runtime/near-vm-runner/src/logic/tests/promises.rs index 98b068e79c7..d85b7c5e762 100644 --- a/runtime/near-vm-runner/src/logic/tests/promises.rs +++ b/runtime/near-vm-runner/src/logic/tests/promises.rs @@ -4,17 +4,16 @@ use crate::logic::tests::vm_logic_builder::VMLogicBuilder; use crate::logic::types::PromiseResult; use crate::logic::VMLogic; use borsh::BorshSerialize; -use near_account_id::AccountId; use near_crypto::PublicKey; use serde_json; -#[derive(serde::Serialize)] -struct ReceiptView<'a> { - receiver_id: &'a AccountId, - actions: &'a [Action], -} +fn vm_receipts<'a>(logic: &'a VMLogic) -> Vec { + #[derive(serde::Serialize)] + struct ReceiptView<'a, T> { + receiver_id: T, + actions: &'a [Action], + } -fn vm_receipts<'a>(logic: &'a VMLogic) -> Vec> { logic .receipt_manager() .action_receipts diff --git a/runtime/runtime/Cargo.toml b/runtime/runtime/Cargo.toml index 22a7dc366ec..9321c338d1a 100644 --- a/runtime/runtime/Cargo.toml +++ b/runtime/runtime/Cargo.toml @@ -40,7 +40,6 @@ nightly = [ "near-vm-runner/nightly", ] default = [] -dump_errors_schema = ["near-vm-runner/dump_errors_schema"] nightly_protocol = [ "near-chain-configs/nightly_protocol", "near-o11y/nightly_protocol", diff --git a/runtime/runtime/src/actions.rs b/runtime/runtime/src/actions.rs index f03f4ef9d9b..82386289880 100644 --- a/runtime/runtime/src/actions.rs +++ b/runtime/runtime/src/actions.rs @@ -31,8 +31,7 @@ use near_store::{ StorageError, TrieUpdate, }; use near_vm_runner::logic::errors::{ - CompilationError, FunctionCallError, FunctionCallErrorSer, InconsistentStateError, - VMRunnerError, + CompilationError, FunctionCallError, InconsistentStateError, VMRunnerError, }; use near_vm_runner::logic::types::PromiseResult; use near_vm_runner::logic::{ActionCosts, VMContext, VMOutcome}; @@ -58,7 +57,7 @@ pub(crate) fn execute_function_call( Ok(Some(code)) => code, Ok(None) => { let error = FunctionCallError::CompilationError(CompilationError::CodeDoesNotExist { - account_id: account_id.clone(), + account_id: account_id.as_str().into(), }); return Ok(VMOutcome::nop_outcome(error)); } @@ -241,8 +240,7 @@ pub(crate) fn action_function_call( } // Update action result with the abort error converted to the // transaction runtime's format of errors. - let ser: FunctionCallErrorSer = err.into(); - let action_err: ActionError = ActionErrorKind::FunctionCallError(ser).into(); + let action_err: ActionError = ActionErrorKind::FunctionCallError(err.into()).into(); result.result = Err(action_err); } result.gas_burnt = safe_add_gas(result.gas_burnt, outcome.burnt_gas)?;