Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 2 additions & 12 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
pub use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
use pallet_contracts_rpc_runtime_api::ContractExecResult;
use pallet_session::{historical as pallet_session_historical};
use sp_inherents::{InherentData, CheckInherentsResult};
use static_assertions::const_assert;
Expand Down Expand Up @@ -1124,17 +1123,8 @@ impl_runtime_apis! {
value: Balance,
gas_limit: u64,
input_data: Vec<u8>,
) -> ContractExecResult {
let (exec_result, gas_consumed) =
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,
}
) -> pallet_contracts_primitives::ContractExecResult {
Contracts::bare_call(origin, dest, value, gas_limit, input_data)
}

fn get_storage(
Expand Down
1 change: 0 additions & 1 deletion frame/contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ readme = "README.md"
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
bitflags = "1.0"
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-support = { version = "2.0.0", default-features = false, path = "../support" }
Expand Down
1 change: 1 addition & 0 deletions frame/contracts/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
# 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"] }
sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" }
sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" }
Expand Down
91 changes: 83 additions & 8 deletions frame/contracts/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,105 @@

#![cfg_attr(not(feature = "std"), no_std)]

use bitflags::bitflags;
use codec::{Decode, Encode};
use sp_runtime::{DispatchError, RuntimeDebug};
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>;

/// 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.
#[derive(Eq, PartialEq, codec::Encode, codec::Decode, sp_runtime::RuntimeDebug)]
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
pub enum ContractAccessError {
/// The given address doesn't point to a contract.
DoesntExist,
/// The specified contract is a tombstone and thus cannot have any storage.
IsTombstone,
}

/// A result type of a `rent_projection` call.
pub type RentProjectionResult<BlockNumber> =
Result<RentProjection<BlockNumber>, ContractAccessError>;

#[derive(Eq, PartialEq, codec::Encode, codec::Decode, sp_runtime::RuntimeDebug)]
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug)]
pub enum RentProjection<BlockNumber> {
/// Eviction is projected to happen at the specified block number.
EvictionAt(BlockNumber),
/// 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,
}

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>;
26 changes: 2 additions & 24 deletions frame/contracts/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,9 @@

#![cfg_attr(not(feature = "std"), no_std)]

use codec::{Codec, Decode, Encode};
use pallet_contracts_primitives::{GetStorageResult, RentProjectionResult};
use sp_runtime::RuntimeDebug;
use codec::Codec;
use sp_std::vec::Vec;

/// 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,
}
use pallet_contracts_primitives::{ContractExecResult, GetStorageResult, RentProjectionResult};

sp_api::decl_runtime_apis! {
/// The API to interact with contracts without using executive.
Expand Down
28 changes: 11 additions & 17 deletions frame/contracts/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,9 @@ use sp_runtime::{
traits::{Block as BlockT, Header as HeaderT},
};
use std::convert::TryInto;
use pallet_contracts_primitives::ContractExecResult;

pub use self::gen_client::Client as ContractsClient;
pub use pallet_contracts_rpc_runtime_api::{
self as runtime_api, ContractExecResult, ContractsApi as ContractsRuntimeApi,
};
pub use pallet_contracts_rpc_runtime_api::ContractsApi as ContractsRuntimeApi;

const RUNTIME_ERROR: i64 = 1;
const CONTRACT_DOESNT_EXIST: i64 = 2;
Expand Down Expand Up @@ -105,17 +103,13 @@ pub enum RpcContractExecResult {

impl From<ContractExecResult> for RpcContractExecResult {
fn from(r: ContractExecResult) -> Self {
match r {
ContractExecResult::Success {
flags,
data,
gas_consumed
} => RpcContractExecResult::Success {
flags,
data: data.into(),
gas_consumed,
match r.exec_result {
Ok(val) => RpcContractExecResult::Success {
flags: val.flags.bits(),
data: val.data.into(),
gas_consumed: r.gas_consumed,
},
ContractExecResult::Error => RpcContractExecResult::Error(()),
_ => RpcContractExecResult::Error(()),
}
}
}
Expand Down Expand Up @@ -233,7 +227,7 @@ where

let exec_result = api
.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())
}
Expand All @@ -251,7 +245,7 @@ where

let result = api
.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(Bytes);

Expand All @@ -270,7 +264,7 @@ where

let result = api
.rent_projection(&at, address)
.map_err(|e| runtime_error_into_rpc_err(e))?
.map_err(runtime_error_into_rpc_err)?
.map_err(ContractAccessError)?;

Ok(match result {
Expand Down
1 change: 1 addition & 0 deletions frame/contracts/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use frame_system::{Module as System, RawOrigin};
use parity_wasm::elements::{Instruction, ValueType, BlockType};
use sp_runtime::traits::{Hash, Bounded};
use sp_std::{default::Default, convert::{TryInto}};
use pallet_contracts_primitives::RentProjection;

/// How many batches we do per API benchmark.
const API_BENCHMARK_BATCHES: u32 = 20;
Expand Down
60 changes: 1 addition & 59 deletions frame/contracts/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::{
TrieId, BalanceOf, ContractInfo, TrieIdGenerator,
gas::GasMeter, rent, storage, Error, ContractInfoOf
};
use bitflags::bitflags;
use sp_std::prelude::*;
use sp_runtime::traits::{Bounded, Zero, Convert, Saturating};
use frame_support::{
Expand All @@ -28,6 +27,7 @@ use frame_support::{
weights::Weight,
ensure, StorageMap,
};
use pallet_contracts_primitives::{ErrorOrigin, ExecError, ExecReturnValue, ExecResult, ReturnFlags};

pub type AccountIdOf<T> = <T as frame_system::Trait>::AccountId;
pub type MomentOf<T> = <<T as Trait>::Time as Time>::Moment;
Expand All @@ -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.
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.
pub enum TransactorKind {
/// Transaction was initiated from a plain account. That can be either be through a
Expand All @@ -55,56 +47,6 @@ pub enum TransactorKind {
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
/// smart-contract is executed.
///
Expand Down
3 changes: 2 additions & 1 deletion frame/contracts/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
// You should have received a copy of the GNU General Public License
// 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_runtime::traits::Zero;
use frame_support::dispatch::{
DispatchResultWithPostInfo, PostDispatchInfo, DispatchErrorWithPostInfo,
};
use pallet_contracts_primitives::ExecError;

#[cfg(test)]
use std::{any::Any, fmt::Debug};
Expand Down
Loading