mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 17:31:02 +00:00
contracts: Refactor the runtime API in order to simplify node integration (#7409)
* contracts: Make use of existing type aliases for runtime API types * contracts: Refactor the contracts call runtime API * review: Fix comment typo Co-authored-by: Andrew Jones <ascjones@gmail.com> * Update frame/contracts/common/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * Update frame/contracts/common/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * Update frame/contracts/common/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * Update frame/contracts/common/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * Update frame/contracts/common/src/lib.rs Co-authored-by: Nikolay Volf <nikvolf@gmail.com> * Update lib.rs * review: Group crate imports Co-authored-by: Andrew Jones <ascjones@gmail.com> Co-authored-by: Addie Wagenknecht <addie@nortd.com> Co-authored-by: Nikolay Volf <nikvolf@gmail.com>
This commit is contained in:
committed by
GitHub
parent
bd450c24ff
commit
a5ec7e5c4e
Generated
+1
-1
@@ -4438,7 +4438,6 @@ name = "pallet-contracts"
|
|||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_matches",
|
"assert_matches",
|
||||||
"bitflags",
|
|
||||||
"frame-benchmarking",
|
"frame-benchmarking",
|
||||||
"frame-support",
|
"frame-support",
|
||||||
"frame-system",
|
"frame-system",
|
||||||
@@ -4466,6 +4465,7 @@ dependencies = [
|
|||||||
name = "pallet-contracts-primitives"
|
name = "pallet-contracts-primitives"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
"sp-std",
|
"sp-std",
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
|
|||||||
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
|
||||||
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
|
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
|
||||||
pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
|
pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
|
||||||
use pallet_contracts_rpc_runtime_api::ContractExecResult;
|
|
||||||
use pallet_session::{historical as pallet_session_historical};
|
use pallet_session::{historical as pallet_session_historical};
|
||||||
use sp_inherents::{InherentData, CheckInherentsResult};
|
use sp_inherents::{InherentData, CheckInherentsResult};
|
||||||
use static_assertions::const_assert;
|
use static_assertions::const_assert;
|
||||||
@@ -1124,17 +1123,8 @@ impl_runtime_apis! {
|
|||||||
value: Balance,
|
value: Balance,
|
||||||
gas_limit: u64,
|
gas_limit: u64,
|
||||||
input_data: Vec<u8>,
|
input_data: Vec<u8>,
|
||||||
) -> ContractExecResult {
|
) -> pallet_contracts_primitives::ContractExecResult {
|
||||||
let (exec_result, gas_consumed) =
|
Contracts::bare_call(origin, dest, value, gas_limit, input_data)
|
||||||
Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
|
|
||||||
match exec_result {
|
|
||||||
Ok(v) => ContractExecResult::Success {
|
|
||||||
flags: v.flags.bits(),
|
|
||||||
data: v.data,
|
|
||||||
gas_consumed: gas_consumed,
|
|
||||||
},
|
|
||||||
Err(_) => ContractExecResult::Error,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_storage(
|
fn get_storage(
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ readme = "README.md"
|
|||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
|
||||||
codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
|
codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
|
||||||
frame-benchmarking = { version = "2.0.0", default-features = false, path = "../benchmarking", optional = true }
|
frame-benchmarking = { version = "2.0.0", default-features = false, path = "../benchmarking", optional = true }
|
||||||
frame-support = { version = "2.0.0", default-features = false, path = "../support" }
|
frame-support = { version = "2.0.0", default-features = false, path = "../support" }
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# This crate should not rely on any of the frame primitives.
|
# This crate should not rely on any of the frame primitives.
|
||||||
|
bitflags = "1.0"
|
||||||
codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
|
codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
|
||||||
sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" }
|
sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" }
|
||||||
sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" }
|
sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" }
|
||||||
|
|||||||
@@ -18,13 +18,29 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
|
use bitflags::bitflags;
|
||||||
|
use codec::{Decode, Encode};
|
||||||
|
use sp_runtime::{DispatchError, RuntimeDebug};
|
||||||
use sp_std::prelude::*;
|
use sp_std::prelude::*;
|
||||||
|
|
||||||
/// A result type of a get storage call.
|
/// Result type of a `bare_call` call.
|
||||||
|
///
|
||||||
|
/// The result of a contract execution along with a gas consumed.
|
||||||
|
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
|
||||||
|
pub struct ContractExecResult {
|
||||||
|
pub exec_result: ExecResult,
|
||||||
|
pub gas_consumed: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Result type of a `get_storage` call.
|
||||||
pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>;
|
pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>;
|
||||||
|
|
||||||
|
/// Result type of a `rent_projection` call.
|
||||||
|
pub type RentProjectionResult<BlockNumber> =
|
||||||
|
Result<RentProjection<BlockNumber>, ContractAccessError>;
|
||||||
|
|
||||||
/// The possible errors that can happen querying the storage of a contract.
|
/// The possible errors that can happen querying the storage of a contract.
|
||||||
#[derive(Eq, PartialEq, codec::Encode, codec::Decode, sp_runtime::RuntimeDebug)]
|
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
|
||||||
pub enum ContractAccessError {
|
pub enum ContractAccessError {
|
||||||
/// The given address doesn't point to a contract.
|
/// The given address doesn't point to a contract.
|
||||||
DoesntExist,
|
DoesntExist,
|
||||||
@@ -32,16 +48,75 @@ pub enum ContractAccessError {
|
|||||||
IsTombstone,
|
IsTombstone,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A result type of a `rent_projection` call.
|
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
|
||||||
pub type RentProjectionResult<BlockNumber> =
|
|
||||||
Result<RentProjection<BlockNumber>, ContractAccessError>;
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, codec::Encode, codec::Decode, sp_runtime::RuntimeDebug)]
|
|
||||||
pub enum RentProjection<BlockNumber> {
|
pub enum RentProjection<BlockNumber> {
|
||||||
/// Eviction is projected to happen at the specified block number.
|
/// Eviction is projected to happen at the specified block number.
|
||||||
EvictionAt(BlockNumber),
|
EvictionAt(BlockNumber),
|
||||||
/// No eviction is scheduled.
|
/// No eviction is scheduled.
|
||||||
///
|
///
|
||||||
/// E.g. because the contract accumulated enough funds to offset the rent storage costs.
|
/// E.g. Contract accumulated enough funds to offset the rent storage costs.
|
||||||
NoEviction,
|
NoEviction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Flags used by a contract to customize exit behaviour.
|
||||||
|
#[derive(Encode, Decode)]
|
||||||
|
pub struct ReturnFlags: u32 {
|
||||||
|
/// If this bit is set all changes made by the contract execution are rolled back.
|
||||||
|
const REVERT = 0x0000_0001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Output of a contract call or instantiation which ran to completion.
|
||||||
|
#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||||
|
pub struct ExecReturnValue {
|
||||||
|
/// Flags passed along by `seal_return`. Empty when `seal_return` was never called.
|
||||||
|
pub flags: ReturnFlags,
|
||||||
|
/// Buffer passed along by `seal_return`. Empty when `seal_return` was never called.
|
||||||
|
pub data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecReturnValue {
|
||||||
|
/// We understand the absense of a revert flag as success.
|
||||||
|
pub fn is_success(&self) -> bool {
|
||||||
|
!self.flags.contains(ReturnFlags::REVERT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Origin of the error.
|
||||||
|
///
|
||||||
|
/// Call or instantiate both called into other contracts and pass through errors happening
|
||||||
|
/// in those to the caller. This enum is for the caller to distinguish whether the error
|
||||||
|
/// happened during the execution of the callee or in the current execution context.
|
||||||
|
#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||||
|
pub enum ErrorOrigin {
|
||||||
|
/// Caller error origin.
|
||||||
|
///
|
||||||
|
/// The error happened in the current exeuction context rather than in the one
|
||||||
|
/// of the contract that is called into.
|
||||||
|
Caller,
|
||||||
|
/// The error happened during execution of the called contract.
|
||||||
|
Callee,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error returned by contract exection.
|
||||||
|
#[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug)]
|
||||||
|
pub struct ExecError {
|
||||||
|
/// The reason why the execution failed.
|
||||||
|
pub error: DispatchError,
|
||||||
|
/// Origin of the error.
|
||||||
|
pub origin: ErrorOrigin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<DispatchError>> From<T> for ExecError {
|
||||||
|
fn from(error: T) -> Self {
|
||||||
|
Self {
|
||||||
|
error: error.into(),
|
||||||
|
origin: ErrorOrigin::Caller,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The result that is returned from contract execution. It either contains the output
|
||||||
|
/// buffer or an error describing the reason for failure.
|
||||||
|
pub type ExecResult = Result<ExecReturnValue, ExecError>;
|
||||||
|
|||||||
@@ -23,31 +23,9 @@
|
|||||||
|
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
use codec::{Codec, Decode, Encode};
|
use codec::Codec;
|
||||||
use pallet_contracts_primitives::{GetStorageResult, RentProjectionResult};
|
|
||||||
use sp_runtime::RuntimeDebug;
|
|
||||||
use sp_std::vec::Vec;
|
use sp_std::vec::Vec;
|
||||||
|
use pallet_contracts_primitives::{ContractExecResult, GetStorageResult, RentProjectionResult};
|
||||||
/// A result of execution of a contract.
|
|
||||||
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
|
|
||||||
pub enum ContractExecResult {
|
|
||||||
/// The contract returned successfully.
|
|
||||||
///
|
|
||||||
/// There is a status code and, optionally, some data returned by the contract.
|
|
||||||
Success {
|
|
||||||
/// Flags that the contract passed along on returning to alter its exit behaviour.
|
|
||||||
/// Described in `pallet_contracts::exec::ReturnFlags`.
|
|
||||||
flags: u32,
|
|
||||||
/// Output data returned by the contract.
|
|
||||||
///
|
|
||||||
/// Can be empty.
|
|
||||||
data: Vec<u8>,
|
|
||||||
/// How much gas was consumed by the call.
|
|
||||||
gas_consumed: u64,
|
|
||||||
},
|
|
||||||
/// The contract execution either trapped or returned an error.
|
|
||||||
Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
sp_api::decl_runtime_apis! {
|
sp_api::decl_runtime_apis! {
|
||||||
/// The API to interact with contracts without using executive.
|
/// The API to interact with contracts without using executive.
|
||||||
|
|||||||
@@ -33,11 +33,9 @@ use sp_runtime::{
|
|||||||
traits::{Block as BlockT, Header as HeaderT},
|
traits::{Block as BlockT, Header as HeaderT},
|
||||||
};
|
};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use pallet_contracts_primitives::ContractExecResult;
|
||||||
|
|
||||||
pub use self::gen_client::Client as ContractsClient;
|
pub use pallet_contracts_rpc_runtime_api::ContractsApi as ContractsRuntimeApi;
|
||||||
pub use pallet_contracts_rpc_runtime_api::{
|
|
||||||
self as runtime_api, ContractExecResult, ContractsApi as ContractsRuntimeApi,
|
|
||||||
};
|
|
||||||
|
|
||||||
const RUNTIME_ERROR: i64 = 1;
|
const RUNTIME_ERROR: i64 = 1;
|
||||||
const CONTRACT_DOESNT_EXIST: i64 = 2;
|
const CONTRACT_DOESNT_EXIST: i64 = 2;
|
||||||
@@ -105,17 +103,13 @@ pub enum RpcContractExecResult {
|
|||||||
|
|
||||||
impl From<ContractExecResult> for RpcContractExecResult {
|
impl From<ContractExecResult> for RpcContractExecResult {
|
||||||
fn from(r: ContractExecResult) -> Self {
|
fn from(r: ContractExecResult) -> Self {
|
||||||
match r {
|
match r.exec_result {
|
||||||
ContractExecResult::Success {
|
Ok(val) => RpcContractExecResult::Success {
|
||||||
flags,
|
flags: val.flags.bits(),
|
||||||
data,
|
data: val.data.into(),
|
||||||
gas_consumed
|
gas_consumed: r.gas_consumed,
|
||||||
} => RpcContractExecResult::Success {
|
|
||||||
flags,
|
|
||||||
data: data.into(),
|
|
||||||
gas_consumed,
|
|
||||||
},
|
},
|
||||||
ContractExecResult::Error => RpcContractExecResult::Error(()),
|
_ => RpcContractExecResult::Error(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +227,7 @@ where
|
|||||||
|
|
||||||
let exec_result = api
|
let exec_result = api
|
||||||
.call(&at, origin, dest, value, gas_limit, input_data.to_vec())
|
.call(&at, origin, dest, value, gas_limit, input_data.to_vec())
|
||||||
.map_err(|e| runtime_error_into_rpc_err(e))?;
|
.map_err(runtime_error_into_rpc_err)?;
|
||||||
|
|
||||||
Ok(exec_result.into())
|
Ok(exec_result.into())
|
||||||
}
|
}
|
||||||
@@ -251,7 +245,7 @@ where
|
|||||||
|
|
||||||
let result = api
|
let result = api
|
||||||
.get_storage(&at, address, key.into())
|
.get_storage(&at, address, key.into())
|
||||||
.map_err(|e| runtime_error_into_rpc_err(e))?
|
.map_err(runtime_error_into_rpc_err)?
|
||||||
.map_err(ContractAccessError)?
|
.map_err(ContractAccessError)?
|
||||||
.map(Bytes);
|
.map(Bytes);
|
||||||
|
|
||||||
@@ -270,7 +264,7 @@ where
|
|||||||
|
|
||||||
let result = api
|
let result = api
|
||||||
.rent_projection(&at, address)
|
.rent_projection(&at, address)
|
||||||
.map_err(|e| runtime_error_into_rpc_err(e))?
|
.map_err(runtime_error_into_rpc_err)?
|
||||||
.map_err(ContractAccessError)?;
|
.map_err(ContractAccessError)?;
|
||||||
|
|
||||||
Ok(match result {
|
Ok(match result {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use frame_system::{Module as System, RawOrigin};
|
|||||||
use parity_wasm::elements::{Instruction, ValueType, BlockType};
|
use parity_wasm::elements::{Instruction, ValueType, BlockType};
|
||||||
use sp_runtime::traits::{Hash, Bounded};
|
use sp_runtime::traits::{Hash, Bounded};
|
||||||
use sp_std::{default::Default, convert::{TryInto}};
|
use sp_std::{default::Default, convert::{TryInto}};
|
||||||
|
use pallet_contracts_primitives::RentProjection;
|
||||||
|
|
||||||
/// How many batches we do per API benchmark.
|
/// How many batches we do per API benchmark.
|
||||||
const API_BENCHMARK_BATCHES: u32 = 20;
|
const API_BENCHMARK_BATCHES: u32 = 20;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use crate::{
|
|||||||
TrieId, BalanceOf, ContractInfo, TrieIdGenerator,
|
TrieId, BalanceOf, ContractInfo, TrieIdGenerator,
|
||||||
gas::GasMeter, rent, storage, Error, ContractInfoOf
|
gas::GasMeter, rent, storage, Error, ContractInfoOf
|
||||||
};
|
};
|
||||||
use bitflags::bitflags;
|
|
||||||
use sp_std::prelude::*;
|
use sp_std::prelude::*;
|
||||||
use sp_runtime::traits::{Bounded, Zero, Convert, Saturating};
|
use sp_runtime::traits::{Bounded, Zero, Convert, Saturating};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
@@ -28,6 +27,7 @@ use frame_support::{
|
|||||||
weights::Weight,
|
weights::Weight,
|
||||||
ensure, StorageMap,
|
ensure, StorageMap,
|
||||||
};
|
};
|
||||||
|
use pallet_contracts_primitives::{ErrorOrigin, ExecError, ExecReturnValue, ExecResult, ReturnFlags};
|
||||||
|
|
||||||
pub type AccountIdOf<T> = <T as frame_system::Trait>::AccountId;
|
pub type AccountIdOf<T> = <T as frame_system::Trait>::AccountId;
|
||||||
pub type MomentOf<T> = <<T as Trait>::Time as Time>::Moment;
|
pub type MomentOf<T> = <<T as Trait>::Time as Time>::Moment;
|
||||||
@@ -38,14 +38,6 @@ pub type StorageKey = [u8; 32];
|
|||||||
/// A type that represents a topic of an event. At the moment a hash is used.
|
/// A type that represents a topic of an event. At the moment a hash is used.
|
||||||
pub type TopicOf<T> = <T as frame_system::Trait>::Hash;
|
pub type TopicOf<T> = <T as frame_system::Trait>::Hash;
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// Flags used by a contract to customize exit behaviour.
|
|
||||||
pub struct ReturnFlags: u32 {
|
|
||||||
/// If this bit is set all changes made by the contract exection are rolled back.
|
|
||||||
const REVERT = 0x0000_0001;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes whether we deal with a contract or a plain account.
|
/// Describes whether we deal with a contract or a plain account.
|
||||||
pub enum TransactorKind {
|
pub enum TransactorKind {
|
||||||
/// Transaction was initiated from a plain account. That can be either be through a
|
/// Transaction was initiated from a plain account. That can be either be through a
|
||||||
@@ -55,56 +47,6 @@ pub enum TransactorKind {
|
|||||||
Contract,
|
Contract,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Output of a contract call or instantiation which ran to completion.
|
|
||||||
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
|
|
||||||
pub struct ExecReturnValue {
|
|
||||||
/// Flags passed along by `seal_return`. Empty when `seal_return` was never called.
|
|
||||||
pub flags: ReturnFlags,
|
|
||||||
/// Buffer passed along by `seal_return`. Empty when `seal_return` was never called.
|
|
||||||
pub data: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExecReturnValue {
|
|
||||||
/// We understand the absense of a revert flag as success.
|
|
||||||
pub fn is_success(&self) -> bool {
|
|
||||||
!self.flags.contains(ReturnFlags::REVERT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Call or instantiate both call into other contracts and pass through errors happening
|
|
||||||
/// in those to the caller. This enum is for the caller to distinguish whether the error
|
|
||||||
/// happened during the execution of the callee or in the current execution context.
|
|
||||||
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
|
|
||||||
pub enum ErrorOrigin {
|
|
||||||
/// The error happened in the current exeuction context rather than in the one
|
|
||||||
/// of the contract that is called into.
|
|
||||||
Caller,
|
|
||||||
/// The error happened during execution of the called contract.
|
|
||||||
Callee,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error returned by contract exection.
|
|
||||||
#[cfg_attr(test, derive(PartialEq, Eq, Debug))]
|
|
||||||
pub struct ExecError {
|
|
||||||
/// The reason why the execution failed.
|
|
||||||
pub error: DispatchError,
|
|
||||||
/// Origin of the error.
|
|
||||||
pub origin: ErrorOrigin,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Into<DispatchError>> From<T> for ExecError {
|
|
||||||
fn from(error: T) -> Self {
|
|
||||||
Self {
|
|
||||||
error: error.into(),
|
|
||||||
origin: ErrorOrigin::Caller,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The result that is returned from contract execution. It either contains the output
|
|
||||||
/// buffer or an error describing the reason for failure.
|
|
||||||
pub type ExecResult = Result<ExecReturnValue, ExecError>;
|
|
||||||
|
|
||||||
/// An interface that provides access to the external environment in which the
|
/// An interface that provides access to the external environment in which the
|
||||||
/// smart-contract is executed.
|
/// smart-contract is executed.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -14,12 +14,13 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Trait, exec::ExecError};
|
use crate::Trait;
|
||||||
use sp_std::marker::PhantomData;
|
use sp_std::marker::PhantomData;
|
||||||
use sp_runtime::traits::Zero;
|
use sp_runtime::traits::Zero;
|
||||||
use frame_support::dispatch::{
|
use frame_support::dispatch::{
|
||||||
DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo,
|
DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo,
|
||||||
};
|
};
|
||||||
|
use pallet_contracts_primitives::ExecError;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use std::{any::Any, fmt::Debug};
|
use std::{any::Any, fmt::Debug};
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ use crate::exec::ExecutionContext;
|
|||||||
use crate::wasm::{WasmLoader, WasmVm};
|
use crate::wasm::{WasmLoader, WasmVm};
|
||||||
|
|
||||||
pub use crate::gas::{Gas, GasMeter};
|
pub use crate::gas::{Gas, GasMeter};
|
||||||
pub use crate::exec::{ExecResult, ExecReturnValue};
|
|
||||||
pub use crate::wasm::ReturnCode as RuntimeReturnCode;
|
pub use crate::wasm::ReturnCode as RuntimeReturnCode;
|
||||||
pub use crate::weight_info::WeightInfo;
|
pub use crate::weight_info::WeightInfo;
|
||||||
pub use crate::schedule::{Schedule, HostFnWeights, InstructionWeights};
|
pub use crate::schedule::{Schedule, HostFnWeights, InstructionWeights};
|
||||||
@@ -118,7 +117,9 @@ use frame_support::{
|
|||||||
traits::{OnUnbalanced, Currency, Get, Time, Randomness},
|
traits::{OnUnbalanced, Currency, Get, Time, Randomness},
|
||||||
};
|
};
|
||||||
use frame_system::{ensure_signed, ensure_root};
|
use frame_system::{ensure_signed, ensure_root};
|
||||||
use pallet_contracts_primitives::{RentProjection, ContractAccessError};
|
use pallet_contracts_primitives::{
|
||||||
|
RentProjectionResult, GetStorageResult, ContractAccessError, ContractExecResult, ExecResult,
|
||||||
|
};
|
||||||
use frame_support::weights::Weight;
|
use frame_support::weights::Weight;
|
||||||
|
|
||||||
pub type CodeHash<T> = <T as frame_system::Trait>::Hash;
|
pub type CodeHash<T> = <T as frame_system::Trait>::Hash;
|
||||||
@@ -639,21 +640,20 @@ impl<T: Trait> Module<T> {
|
|||||||
value: BalanceOf<T>,
|
value: BalanceOf<T>,
|
||||||
gas_limit: Gas,
|
gas_limit: Gas,
|
||||||
input_data: Vec<u8>,
|
input_data: Vec<u8>,
|
||||||
) -> (ExecResult, Gas) {
|
) -> ContractExecResult {
|
||||||
let mut gas_meter = GasMeter::new(gas_limit);
|
let mut gas_meter = GasMeter::new(gas_limit);
|
||||||
(
|
let exec_result = Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
|
||||||
Self::execute_wasm(origin, &mut gas_meter, |ctx, gas_meter| {
|
ctx.call(dest, value, gas_meter, input_data)
|
||||||
ctx.call(dest, value, gas_meter, input_data)
|
});
|
||||||
}),
|
let gas_consumed = gas_meter.gas_spent();
|
||||||
gas_meter.gas_spent(),
|
ContractExecResult {
|
||||||
)
|
exec_result,
|
||||||
|
gas_consumed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Query storage of a specified contract under a specified key.
|
/// Query storage of a specified contract under a specified key.
|
||||||
pub fn get_storage(
|
pub fn get_storage(address: T::AccountId, key: [u8; 32]) -> GetStorageResult {
|
||||||
address: T::AccountId,
|
|
||||||
key: [u8; 32],
|
|
||||||
) -> sp_std::result::Result<Option<Vec<u8>>, ContractAccessError> {
|
|
||||||
let contract_info = ContractInfoOf::<T>::get(&address)
|
let contract_info = ContractInfoOf::<T>::get(&address)
|
||||||
.ok_or(ContractAccessError::DoesntExist)?
|
.ok_or(ContractAccessError::DoesntExist)?
|
||||||
.get_alive()
|
.get_alive()
|
||||||
@@ -663,9 +663,7 @@ impl<T: Trait> Module<T> {
|
|||||||
Ok(maybe_value)
|
Ok(maybe_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rent_projection(
|
pub fn rent_projection(address: T::AccountId) -> RentProjectionResult<T::BlockNumber> {
|
||||||
address: T::AccountId,
|
|
||||||
) -> sp_std::result::Result<RentProjection<T::BlockNumber>, ContractAccessError> {
|
|
||||||
rent::compute_rent_projection::<T>(&address)
|
rent::compute_rent_projection::<T>(&address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1655,7 +1655,7 @@ fn crypto_hashes() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
params,
|
params,
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert!(result.is_success());
|
assert!(result.is_success());
|
||||||
let expected = hash_fn(input.as_ref());
|
let expected = hash_fn(input.as_ref());
|
||||||
assert_eq!(&result.data[..*expected_size], &*expected);
|
assert_eq!(&result.data[..*expected_size], &*expected);
|
||||||
@@ -1688,7 +1688,7 @@ fn transfer_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![],
|
vec![],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
||||||
|
|
||||||
// Contract has enough total balance in order to not go below the subsistence
|
// Contract has enough total balance in order to not go below the subsistence
|
||||||
@@ -1702,7 +1702,7 @@ fn transfer_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![],
|
vec![],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1735,7 +1735,7 @@ fn call_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![0],
|
vec![0],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::NotCallable);
|
assert_return_code!(result, RuntimeReturnCode::NotCallable);
|
||||||
|
|
||||||
assert_ok!(
|
assert_ok!(
|
||||||
@@ -1755,7 +1755,7 @@ fn call_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![0],
|
vec![0],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
||||||
|
|
||||||
// Contract has enough total balance in order to not go below the subsistence
|
// Contract has enough total balance in order to not go below the subsistence
|
||||||
@@ -1769,7 +1769,7 @@ fn call_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![0],
|
vec![0],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
||||||
|
|
||||||
// Contract has enough balance but callee reverts because "1" is passed.
|
// Contract has enough balance but callee reverts because "1" is passed.
|
||||||
@@ -1780,7 +1780,7 @@ fn call_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![1],
|
vec![1],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
|
assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
|
||||||
|
|
||||||
// Contract has enough balance but callee traps because "2" is passed.
|
// Contract has enough balance but callee traps because "2" is passed.
|
||||||
@@ -1790,7 +1790,7 @@ fn call_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![2],
|
vec![2],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
|
assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -1825,7 +1825,7 @@ fn instantiate_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![0; 33],
|
vec![0; 33],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
||||||
|
|
||||||
// Contract has enough total balance in order to not go below the subsistence
|
// Contract has enough total balance in order to not go below the subsistence
|
||||||
@@ -1839,7 +1839,7 @@ fn instantiate_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![0; 33],
|
vec![0; 33],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
||||||
|
|
||||||
// Contract has enough balance but the passed code hash is invalid
|
// Contract has enough balance but the passed code hash is invalid
|
||||||
@@ -1850,7 +1850,7 @@ fn instantiate_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
vec![0; 33],
|
vec![0; 33],
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::CodeNotFound);
|
assert_return_code!(result, RuntimeReturnCode::CodeNotFound);
|
||||||
|
|
||||||
// Contract has enough balance but callee reverts because "1" is passed.
|
// Contract has enough balance but callee reverts because "1" is passed.
|
||||||
@@ -1860,7 +1860,7 @@ fn instantiate_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
callee_hash.iter().cloned().chain(sp_std::iter::once(1)).collect(),
|
callee_hash.iter().cloned().chain(sp_std::iter::once(1)).collect(),
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
|
assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
|
||||||
|
|
||||||
// Contract has enough balance but callee traps because "2" is passed.
|
// Contract has enough balance but callee traps because "2" is passed.
|
||||||
@@ -1870,7 +1870,7 @@ fn instantiate_return_code() {
|
|||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
callee_hash.iter().cloned().chain(sp_std::iter::once(2)).collect(),
|
callee_hash.iter().cloned().chain(sp_std::iter::once(2)).collect(),
|
||||||
).0.unwrap();
|
).exec_result.unwrap();
|
||||||
assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
|
assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
use crate::{CodeHash, Schedule, Trait};
|
use crate::{CodeHash, Schedule, Trait};
|
||||||
use crate::wasm::env_def::FunctionImplProvider;
|
use crate::wasm::env_def::FunctionImplProvider;
|
||||||
use crate::exec::{Ext, ExecResult};
|
use crate::exec::Ext;
|
||||||
use crate::gas::GasMeter;
|
use crate::gas::GasMeter;
|
||||||
|
|
||||||
use sp_std::prelude::*;
|
use sp_std::prelude::*;
|
||||||
@@ -34,6 +34,7 @@ mod runtime;
|
|||||||
|
|
||||||
use self::runtime::{to_execution_result, Runtime};
|
use self::runtime::{to_execution_result, Runtime};
|
||||||
use self::code_cache::load as load_code;
|
use self::code_cache::load as load_code;
|
||||||
|
use pallet_contracts_primitives::ExecResult;
|
||||||
|
|
||||||
pub use self::code_cache::save as save_code;
|
pub use self::code_cache::save as save_code;
|
||||||
#[cfg(feature = "runtime-benchmarks")]
|
#[cfg(feature = "runtime-benchmarks")]
|
||||||
@@ -155,7 +156,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use sp_core::H256;
|
use sp_core::H256;
|
||||||
use crate::exec::{Ext, StorageKey, ExecReturnValue, ReturnFlags, ExecError, ErrorOrigin};
|
use crate::exec::{Ext, StorageKey};
|
||||||
use crate::gas::{Gas, GasMeter};
|
use crate::gas::{Gas, GasMeter};
|
||||||
use crate::tests::{Test, Call};
|
use crate::tests::{Test, Call};
|
||||||
use crate::wasm::prepare::prepare_contract;
|
use crate::wasm::prepare::prepare_contract;
|
||||||
@@ -163,6 +164,7 @@ mod tests {
|
|||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
use sp_runtime::DispatchError;
|
use sp_runtime::DispatchError;
|
||||||
use frame_support::weights::Weight;
|
use frame_support::weights::Weight;
|
||||||
|
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags, ExecError, ErrorOrigin};
|
||||||
|
|
||||||
const GAS_LIMIT: Gas = 10_000_000_000;
|
const GAS_LIMIT: Gas = 10_000_000_000;
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
//! Environment definition of the wasm smart-contract runtime.
|
//! Environment definition of the wasm smart-contract runtime.
|
||||||
|
|
||||||
use crate::{HostFnWeights, Schedule, Trait, CodeHash, BalanceOf, Error};
|
use crate::{
|
||||||
use crate::exec::{
|
HostFnWeights, Schedule, Trait, CodeHash, BalanceOf, Error,
|
||||||
Ext, ExecResult, ExecReturnValue, StorageKey, TopicOf, ReturnFlags, ExecError
|
exec::{Ext, StorageKey, TopicOf},
|
||||||
|
gas::{Gas, GasMeter, Token, GasMeterResult},
|
||||||
|
wasm::env_def::ConvertibleToWasm,
|
||||||
};
|
};
|
||||||
use crate::gas::{Gas, GasMeter, Token, GasMeterResult};
|
|
||||||
use crate::wasm::env_def::ConvertibleToWasm;
|
|
||||||
use sp_sandbox;
|
use sp_sandbox;
|
||||||
use parity_wasm::elements::ValueType;
|
use parity_wasm::elements::ValueType;
|
||||||
use frame_system;
|
use frame_system;
|
||||||
@@ -35,6 +35,7 @@ use sp_io::hashing::{
|
|||||||
blake2_128,
|
blake2_128,
|
||||||
sha2_256,
|
sha2_256,
|
||||||
};
|
};
|
||||||
|
use pallet_contracts_primitives::{ExecResult, ExecReturnValue, ReturnFlags, ExecError};
|
||||||
|
|
||||||
/// Every error that can be returned to a contract when it calls any of the host functions.
|
/// Every error that can be returned to a contract when it calls any of the host functions.
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
@@ -499,7 +500,7 @@ fn err_into_return_code<T: Trait>(from: DispatchError) -> Result<ReturnCode, Dis
|
|||||||
|
|
||||||
/// Fallible conversion of a `ExecResult` to `ReturnCode`.
|
/// Fallible conversion of a `ExecResult` to `ReturnCode`.
|
||||||
fn exec_into_return_code<T: Trait>(from: ExecResult) -> Result<ReturnCode, DispatchError> {
|
fn exec_into_return_code<T: Trait>(from: ExecResult) -> Result<ReturnCode, DispatchError> {
|
||||||
use crate::exec::ErrorOrigin::Callee;
|
use pallet_contracts_primitives::ErrorOrigin::Callee;
|
||||||
|
|
||||||
let ExecError { error, origin } = match from {
|
let ExecError { error, origin } = match from {
|
||||||
Ok(retval) => return Ok(retval.into()),
|
Ok(retval) => return Ok(retval.into()),
|
||||||
|
|||||||
Reference in New Issue
Block a user