Newer
Older
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Environment definition of the wasm smart-contract runtime.
Alexander Theißen
committed
use crate::{
HostFnWeights, Schedule, Trait, CodeHash, BalanceOf, Error,
exec::{Ext, StorageKey, TopicOf},
gas::{Gas, GasMeter, Token, GasMeterResult},
wasm::env_def::ConvertibleToWasm,
use parity_wasm::elements::ValueType;
use frame_support::dispatch::DispatchError;
use sp_std::prelude::*;
use sp_runtime::traits::SaturatedConversion;
use sp_core::crypto::UncheckedFrom;
use sp_io::hashing::{
keccak_256,
blake2_256,
blake2_128,
sha2_256,
};
Alexander Theißen
committed
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.
#[repr(u32)]
pub enum ReturnCode {
/// API call successful.
Success = 0,
/// The called function trapped and has its state changes reverted.
/// In this case no output buffer is returned.
CalleeTrapped = 1,
/// The called function ran to completion but decided to revert its state.
/// An output buffer is returned when one was supplied.
CalleeReverted = 2,
/// The passed key does not exist in storage.
KeyNotFound = 3,
/// Transfer failed because it would have brought the sender's total balance below the
/// subsistence threshold.
BelowSubsistenceThreshold = 4,
/// Transfer failed for other reasons. Most probably reserved or locked balance of the
/// sender prevents the transfer.
TransferFailed = 5,
/// The newly created contract is below the subsistence threshold after executing
/// its constructor.
NewContractNotFunded = 6,
/// No code could be found at the supplied code hash.
CodeNotFound = 7,
/// The contract that was called is either no contract at all (a plain account)
/// or is a tombstone.
NotCallable = 8,
}
impl ConvertibleToWasm for ReturnCode {
type NativeType = Self;
const VALUE_TYPE: ValueType = ValueType::I32;
fn to_typed_value(self) -> sp_sandbox::Value {
sp_sandbox::Value::I32(self as i32)
}
fn from_typed_value(_: sp_sandbox::Value) -> Option<Self> {
debug_assert!(false, "We will never receive a ReturnCode but only send it to wasm.");
None
}
}
impl From<ExecReturnValue> for ReturnCode {
fn from(from: ExecReturnValue) -> Self {
if from.flags.contains(ReturnFlags::REVERT) {
Self::CalleeReverted
} else {
Self::Success
}
}
}
Alexander Theißen
committed
/// The data passed through when a contract uses `seal_return`.
struct ReturnData {
/// The flags as passed through by the contract. They are still unchecked and
/// will later be parsed into a `ReturnFlags` bitflags struct.
flags: u32,
/// The output buffer passed by the contract as return data.
data: Vec<u8>,
}
/// Enumerates all possible reasons why a trap was generated.
/// This is either used to supply the caller with more information about why an error
/// occurred (the SupervisorError variant).
/// The other case is where the trap does not constitute an error but rather was invoked
/// as a quick way to terminate the application (all other variants).
enum TrapReason {
/// The supervisor trapped the contract because of an error condition occurred during
/// execution in privileged code.
SupervisorError(DispatchError),
Alexander Theißen
committed
/// Signals that trap was generated in response to call `seal_return` host function.
/// Signals that a trap was generated in response to a successful call to the
Alexander Theißen
committed
/// `seal_terminate` host function.
/// Signals that a trap was generated because of a successful restoration.
Restoration,
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[derive(Copy, Clone)]
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/// Charge the gas meter with the cost of a metering block. The charged costs are
/// the supplied cost of the block plus the overhead of the metering itself.
MeteringBlock(u32),
/// Weight of calling `seal_caller`.
Caller,
/// Weight of calling `seal_address`.
Address,
/// Weight of calling `seal_gas_left`.
GasLeft,
/// Weight of calling `seal_balance`.
Balance,
/// Weight of calling `seal_value_transferred`.
ValueTransferred,
/// Weight of calling `seal_minimum_balance`.
MinimumBalance,
/// Weight of calling `seal_tombstone_deposit`.
TombstoneDeposit,
/// Weight of calling `seal_rent_allowance`.
RentAllowance,
/// Weight of calling `seal_block_number`.
BlockNumber,
/// Weight of calling `seal_now`.
Now,
/// Weight of calling `seal_weight_to_fee`.
WeightToFee,
/// Weight of calling `seal_input` without the weight of copying the input.
InputBase,
/// Weight of copying the input data for the given size.
InputCopyOut(u32),
/// Weight of calling `seal_return` for the given output size.
Return(u32),
/// Weight of calling `seal_terminate`.
Terminate,
/// Weight of calling `seal_restore_to` per number of supplied delta entries.
RestoreTo(u32),
/// Weight of calling `seal_random`. It includes the weight for copying the subject.
Random,
/// Weight of calling `seal_reposit_event` with the given number of topics and event size.
DepositEvent{num_topic: u32, len: u32},
/// Weight of calling `seal_set_rent_allowance`.
SetRentAllowance,
/// Weight of calling `seal_set_storage` for the given storage item size.
SetStorage(u32),
/// Weight of calling `seal_clear_storage`.
ClearStorage,
/// Weight of calling `seal_get_storage` without output weight.
GetStorageBase,
/// Weight of an item received via `seal_get_storage` for the given size.
GetStorageCopyOut(u32),
/// Weight of calling `seal_transfer`.
Transfer,
/// Weight of calling `seal_call` for the given input size.
CallBase(u32),
/// Weight of the transfer performed during a call.
CallSurchargeTransfer,
/// Weight of output received through `seal_call` for the given size.
CallCopyOut(u32),
/// Weight of calling `seal_instantiate` for the given input and salt without output weight.
/// This includes the transfer as an instantiate without a value will always be below
/// the existential deposit and is disregarded as corner case.
InstantiateBase{input_data_len: u32, salt_len: u32},
/// Weight of output received through `seal_instantiate` for the given size.
InstantiateCopyOut(u32),
/// Weight of calling `seal_hash_sha_256` for the given input size.
HashSha256(u32),
/// Weight of calling `seal_hash_keccak_256` for the given input size.
HashKeccak256(u32),
/// Weight of calling `seal_hash_blake2_256` for the given input size.
HashBlake256(u32),
/// Weight of calling `seal_hash_blake2_128` for the given input size.
HashBlake128(u32),
impl<T: Trait> Token<T> for RuntimeToken
where
T::AccountId: UncheckedFrom<T::Hash>, T::AccountId: AsRef<[u8]>
{
type Metadata = HostFnWeights<T>;
Loading full blame...