srml-contract: Fix Gas type to u64 (#2944)

* srml-contract: Move gas costs from Config to Schedule.

* srml-contract: Define Gas units fixed as u64.

This removes Gas as a configurable type on the contracts Trait.

* Bump node runtime spec/impl versions.
This commit is contained in:
Jim Posen
2019-06-26 14:17:45 +02:00
committed by Gavin Wood
parent 554a790eaa
commit 4c52aec260
13 changed files with 151 additions and 145 deletions
+1
View File
@@ -2156,6 +2156,7 @@ dependencies = [
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-io 2.0.0",
"sr-primitives 2.0.0",
"srml-contracts 2.0.0",
"srml-finality-tracker 2.0.0",
"srml-indices 2.0.0",
"srml-timestamp 2.0.0",
+1
View File
@@ -38,6 +38,7 @@ indices = { package = "srml-indices", path = "../../srml/indices" }
timestamp = { package = "srml-timestamp", path = "../../srml/timestamp", default-features = false }
rand = "0.6"
finality_tracker = { package = "srml-finality-tracker", path = "../../srml/finality-tracker", default-features = false }
contracts = { package = "srml-contracts", path = "../../srml/contracts" }
[dev-dependencies]
consensus-common = { package = "substrate-consensus-common", path = "../../core/consensus/common" }
+25 -25
View File
@@ -174,12 +174,14 @@ fn staging_testnet_config_genesis() -> GenesisConfig {
transfer_fee: 1 * CENTS,
creation_fee: 1 * CENTS,
contract_fee: 1 * CENTS,
call_base_fee: 1000,
create_base_fee: 1000,
gas_price: 1 * MILLICENTS,
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: Default::default(),
current_schedule: contracts::Schedule {
call_base_cost: 1000,
instantiate_base_cost: 1000,
..Default::default()
},
}),
sudo: Some(SudoConfig {
key: endowed_accounts[0].clone(),
@@ -268,27 +270,6 @@ pub fn testnet_genesis(
const ENDOWMENT: u128 = 1 << 20;
let council_desired_seats = (endowed_accounts.len() / 2 - initial_authorities.len()) as u32;
let mut contracts_config = ContractsConfig {
signed_claim_handicap: 2,
rent_byte_price: 4,
rent_deposit_offset: 1000,
storage_size_offset: 8,
surcharge_reward: 150,
tombstone_deposit: 16,
transaction_base_fee: 1,
transaction_byte_fee: 0,
transfer_fee: 0,
creation_fee: 0,
contract_fee: 21,
call_base_fee: 135,
create_base_fee: 175,
gas_price: 1,
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: Default::default(),
};
// this should only be enabled on development chains
contracts_config.current_schedule.enable_println = enable_println;
GenesisConfig {
system: Some(SystemConfig {
@@ -349,7 +330,26 @@ pub fn testnet_genesis(
spend_period: 12 * 60 * 24,
burn: Permill::from_percent(50),
}),
contracts: Some(contracts_config),
contracts: Some(ContractsConfig {
signed_claim_handicap: 2,
rent_byte_price: 4,
rent_deposit_offset: 1000,
storage_size_offset: 8,
surcharge_reward: 150,
tombstone_deposit: 16,
transaction_base_fee: 1,
transaction_byte_fee: 0,
transfer_fee: 0,
creation_fee: 0,
contract_fee: 21,
gas_price: 1,
max_depth: 1024,
block_gas_limit: 10_000_000,
current_schedule: contracts::Schedule {
enable_println, // this should only be enabled on development chains
..Default::default()
},
}),
sudo: Some(SudoConfig {
key: root_key,
}),
+2 -3
View File
@@ -58,8 +58,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node"),
impl_name: create_runtime_str!("substrate-node"),
authoring_version: 10,
spec_version: 98,
impl_version: 101,
spec_version: 99,
impl_version: 102,
apis: RUNTIME_API_VERSIONS,
};
@@ -221,7 +221,6 @@ impl contracts::Trait for Runtime {
type Currency = Balances;
type Call = Call;
type Event = Event;
type Gas = u64;
type DetermineContractAddress = contracts::SimpleAddressDeterminator<Runtime>;
type ComputeDispatchFee = contracts::DefaultDispatchFeeComputor<Runtime>;
type TrieIdGenerator = contracts::TrieIdFromParentCounter<Runtime>;
+7 -7
View File
@@ -17,7 +17,7 @@
use super::{CodeHash, Config, ContractAddressFor, Event, RawEvent, Trait,
TrieId, BalanceOf, ContractInfoOf};
use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb};
use crate::gas::{GasMeter, Token, approx_gas_for_balance};
use crate::gas::{Gas, GasMeter, Token, approx_gas_for_balance};
use rstd::prelude::*;
use runtime_primitives::traits::{Bounded, CheckedAdd, CheckedSub, Zero};
@@ -239,10 +239,10 @@ pub enum ExecFeeToken {
impl<T: Trait> Token<T> for ExecFeeToken {
type Metadata = Config<T>;
#[inline]
fn calculate_amount(&self, metadata: &Config<T>) -> T::Gas {
fn calculate_amount(&self, metadata: &Config<T>) -> Gas {
match *self {
ExecFeeToken::Call => metadata.call_base_fee,
ExecFeeToken::Instantiate => metadata.instantiate_base_fee,
ExecFeeToken::Call => metadata.schedule.call_base_cost,
ExecFeeToken::Instantiate => metadata.schedule.instantiate_base_cost,
}
}
}
@@ -465,13 +465,13 @@ impl<T: Trait> Token<T> for TransferFeeToken<BalanceOf<T>> {
type Metadata = Config<T>;
#[inline]
fn calculate_amount(&self, metadata: &Config<T>) -> T::Gas {
fn calculate_amount(&self, metadata: &Config<T>) -> Gas {
let balance_fee = match self.kind {
TransferFeeKind::ContractInstantiate => metadata.contract_account_instantiate_fee,
TransferFeeKind::AccountCreate => metadata.account_create_fee,
TransferFeeKind::Transfer => metadata.transfer_fee,
};
approx_gas_for_balance::<T>(self.gas_price, balance_fee)
approx_gas_for_balance(self.gas_price, balance_fee)
}
}
@@ -491,7 +491,7 @@ enum TransferCause {
/// is specified using the `cause` parameter.
///
/// NOTE: that the fee is denominated in `BalanceOf<T>` units, but
/// charged in `T::Gas` from the provided `gas_meter`. This means
/// charged in `Gas` from the provided `gas_meter`. This means
/// that the actual amount charged might differ.
///
/// NOTE: that we allow for draining all funds of the contract so it
+28 -17
View File
@@ -15,13 +15,18 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::{GasSpent, Module, Trait, BalanceOf, NegativeImbalanceOf};
use rstd::convert::TryFrom;
use runtime_primitives::BLOCK_FULL;
use runtime_primitives::traits::{CheckedMul, CheckedSub, Zero, SaturatedConversion};
use runtime_primitives::traits::{CheckedMul, Zero, SaturatedConversion, SimpleArithmetic, UniqueSaturatedInto};
use srml_support::{StorageValue, traits::{OnUnbalanced, ExistenceRequirement, WithdrawReason, Currency, Imbalance}};
#[cfg(test)]
use std::{any::Any, fmt::Debug};
// Gas units are chosen to be represented by u64 so that gas metering instructions can operate on
// them efficiently.
pub type Gas = u64;
#[must_use]
#[derive(Debug, PartialEq, Eq)]
pub enum GasMeterResult {
@@ -68,7 +73,7 @@ pub trait Token<T: Trait>: Copy + Clone + TestAuxiliaries {
/// That said, implementors of this function still can run into overflows
/// while calculating the amount. In this case it is ok to use saturating operations
/// since on overflow they will return `max_value` which should consume all gas.
fn calculate_amount(&self, metadata: &Self::Metadata) -> T::Gas;
fn calculate_amount(&self, metadata: &Self::Metadata) -> Gas;
}
/// A wrapper around a type-erased trait object of what used to be a `Token`.
@@ -79,9 +84,9 @@ pub struct ErasedToken {
}
pub struct GasMeter<T: Trait> {
limit: T::Gas,
limit: Gas,
/// Amount of gas left from initial gas limit. Can reach zero.
gas_left: T::Gas,
gas_left: Gas,
gas_price: BalanceOf<T>,
#[cfg(test)]
@@ -89,7 +94,7 @@ pub struct GasMeter<T: Trait> {
}
impl<T: Trait> GasMeter<T> {
#[cfg(test)]
pub fn with_limit(gas_limit: T::Gas, gas_price: BalanceOf<T>) -> GasMeter<T> {
pub fn with_limit(gas_limit: Gas, gas_price: BalanceOf<T>) -> GasMeter<T> {
GasMeter {
limit: gas_limit,
gas_left: gas_limit,
@@ -125,7 +130,7 @@ impl<T: Trait> GasMeter<T> {
}
let amount = token.calculate_amount(metadata);
let new_value = match self.gas_left.checked_sub(&amount) {
let new_value = match self.gas_left.checked_sub(amount) {
None => None,
Some(val) => Some(val),
};
@@ -148,7 +153,7 @@ impl<T: Trait> GasMeter<T> {
/// All unused gas in the nested gas meter is returned to this gas meter.
pub fn with_nested<R, F: FnOnce(Option<&mut GasMeter<T>>) -> R>(
&mut self,
amount: T::Gas,
amount: Gas,
f: F,
) -> R {
// NOTE that it is ok to allocate all available gas since it still ensured
@@ -178,12 +183,12 @@ impl<T: Trait> GasMeter<T> {
}
/// Returns how much gas left from the initial budget.
pub fn gas_left(&self) -> T::Gas {
pub fn gas_left(&self) -> Gas {
self.gas_left
}
/// Returns how much gas was spent.
fn spent(&self) -> T::Gas {
fn spent(&self) -> Gas {
self.limit - self.gas_left
}
@@ -199,7 +204,7 @@ impl<T: Trait> GasMeter<T> {
/// The funds are deducted from `transactor`.
pub fn buy_gas<T: Trait>(
transactor: &T::AccountId,
gas_limit: T::Gas,
gas_limit: Gas,
) -> Result<(GasMeter<T>, NegativeImbalanceOf<T>), &'static str> {
// Check if the specified amount of gas is available in the current block.
// This cannot underflow since `gas_spent` is never greater than `block_gas_limit`.
@@ -211,9 +216,13 @@ pub fn buy_gas<T: Trait>(
// Buy the specified amount of gas.
let gas_price = <Module<T>>::gas_price();
let cost = gas_limit.clone().into()
.checked_mul(&gas_price)
.ok_or("overflow multiplying gas limit by price")?;
let cost = if gas_price.is_zero() {
<BalanceOf<T>>::zero()
} else {
<BalanceOf<T> as TryFrom<Gas>>::try_from(gas_limit).ok()
.and_then(|gas_limit| gas_price.checked_mul(&gas_limit))
.ok_or("overflow multiplying gas limit by price")?
};
let imbalance = T::Currency::withdraw(
transactor,
@@ -243,11 +252,11 @@ pub fn refund_unused_gas<T: Trait>(
// Increase total spent gas.
// This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which
// also has T::Gas type.
// also has Gas type.
<GasSpent<T>>::mutate(|block_gas_spent| *block_gas_spent += gas_spent);
// Refund gas left by the price it was bought at.
let refund = gas_left.into() * gas_meter.gas_price;
let refund = gas_meter.gas_price * gas_left.unique_saturated_into();
let refund_imbalance = T::Currency::deposit_creating(transactor, refund);
if let Ok(imbalance) = imbalance.offset(refund_imbalance) {
T::GasPayment::on_unbalanced(imbalance);
@@ -256,8 +265,10 @@ pub fn refund_unused_gas<T: Trait>(
/// A little handy utility for converting a value in balance units into approximate value in gas units
/// at the given gas price.
pub fn approx_gas_for_balance<T: Trait>(gas_price: BalanceOf<T>, balance: BalanceOf<T>) -> T::Gas {
(balance / gas_price).saturated_into::<T::Gas>()
pub fn approx_gas_for_balance<Balance>(gas_price: Balance, balance: Balance) -> Gas
where Balance: SimpleArithmetic
{
(balance / gas_price).saturated_into::<Gas>()
}
/// A simple utility macro that helps to match against a
+31 -33
View File
@@ -90,15 +90,16 @@ mod tests;
use crate::exec::ExecutionContext;
use crate::account_db::{AccountDb, DirectAccountDb};
use crate::gas::Gas;
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use substrate_primitives::crypto::UncheckedFrom;
use rstd::{prelude::*, marker::PhantomData, convert::TryFrom};
use rstd::{prelude::*, marker::PhantomData};
use parity_codec::{Codec, Encode, Decode};
use runtime_io::blake2_256;
use runtime_primitives::traits::{
Hash, SimpleArithmetic, Bounded, StaticLookup, Zero, MaybeSerializeDebug, Member
Hash, StaticLookup, Zero, MaybeSerializeDebug, Member
};
use srml_support::dispatch::{Result, Dispatchable};
use srml_support::{
@@ -287,9 +288,6 @@ pub trait Trait: timestamp::Trait {
/// The overarching event type.
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
type Gas: Parameter + Default + Codec + SimpleArithmetic + Bounded + Copy +
Into<BalanceOf<Self>> + TryFrom<BalanceOf<Self>>;
/// A function type to get the contract address given the creator.
type DetermineContractAddress: ContractAddressFor<CodeHash<Self>, Self::AccountId>;
@@ -349,7 +347,7 @@ decl_module! {
/// Updates the schedule for metering contracts.
///
/// The schedule must have a greater version than the stored schedule.
pub fn update_schedule(schedule: Schedule<T::Gas>) -> Result {
pub fn update_schedule(schedule: Schedule) -> Result {
if <Module<T>>::current_schedule().version >= schedule.version {
return Err("new schedule must have a greater version than current");
}
@@ -364,7 +362,7 @@ decl_module! {
/// You can instantiate contracts only with stored code.
pub fn put_code(
origin,
#[compact] gas_limit: T::Gas,
#[compact] gas_limit: Gas,
code: Vec<u8>
) -> Result {
let origin = ensure_signed(origin)?;
@@ -393,7 +391,7 @@ decl_module! {
origin,
dest: <T::Lookup as StaticLookup>::Source,
#[compact] value: BalanceOf<T>,
#[compact] gas_limit: T::Gas,
#[compact] gas_limit: Gas,
data: Vec<u8>
) -> Result {
let origin = ensure_signed(origin)?;
@@ -453,7 +451,7 @@ decl_module! {
pub fn create(
origin,
#[compact] endowment: BalanceOf<T>,
#[compact] gas_limit: T::Gas,
#[compact] gas_limit: Gas,
code_hash: CodeHash<T>,
data: Vec<u8>
) -> Result {
@@ -679,20 +677,16 @@ decl_storage! {
TransactionByteFee get(transaction_byte_fee) config(): BalanceOf<T>;
/// The fee required to create a contract instance.
ContractFee get(contract_fee) config(): BalanceOf<T> = 21.into();
/// The base fee charged for calling into a contract.
CallBaseFee get(call_base_fee) config(): T::Gas = 135.into();
/// The base fee charged for creating a contract.
CreateBaseFee get(create_base_fee) config(): T::Gas = 175.into();
/// The price of one unit of gas.
GasPrice get(gas_price) config(): BalanceOf<T> = 1.into();
/// The maximum nesting level of a call/create stack.
MaxDepth get(max_depth) config(): u32 = 100;
/// The maximum amount of gas that could be expended per block.
BlockGasLimit get(block_gas_limit) config(): T::Gas = 10_000_000.into();
BlockGasLimit get(block_gas_limit) config(): Gas = 10_000_000;
/// Gas spent so far in this block.
GasSpent get(gas_spent): T::Gas;
GasSpent get(gas_spent): Gas;
/// Current cost schedule for contracts.
CurrentSchedule get(current_schedule) config(): Schedule<T::Gas> = Schedule::default();
CurrentSchedule get(current_schedule) config(): Schedule = Schedule::default();
/// A mapping from an original code hash to the original code, untouched by instrumentation.
pub PristineCode: map CodeHash<T> => Option<Vec<u8>>;
/// A mapping between an original code hash and instrumented wasm code, ready for execution.
@@ -718,14 +712,12 @@ impl<T: Trait> OnFreeBalanceZero<T::AccountId> for Module<T> {
/// We assume that these values can't be changed in the
/// course of transaction execution.
pub struct Config<T: Trait> {
pub schedule: Schedule<T::Gas>,
pub schedule: Schedule,
pub existential_deposit: BalanceOf<T>,
pub max_depth: u32,
pub contract_account_instantiate_fee: BalanceOf<T>,
pub account_create_fee: BalanceOf<T>,
pub transfer_fee: BalanceOf<T>,
pub call_base_fee: T::Gas,
pub instantiate_base_fee: T::Gas,
}
impl<T: Trait> Config<T> {
@@ -737,8 +729,6 @@ impl<T: Trait> Config<T> {
contract_account_instantiate_fee: <Module<T>>::contract_fee(),
account_create_fee: <Module<T>>::creation_fee(),
transfer_fee: <Module<T>>::transfer_fee(),
call_base_fee: <Module<T>>::call_base_fee(),
instantiate_base_fee: <Module<T>>::create_base_fee(),
}
}
}
@@ -746,7 +736,7 @@ impl<T: Trait> Config<T> {
/// Definition of the cost schedule and other parameterizations for wasm vm.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[derive(Clone, Encode, Decode, PartialEq, Eq)]
pub struct Schedule<Gas> {
pub struct Schedule {
/// Version of the schedule.
pub version: u32,
@@ -771,6 +761,12 @@ pub struct Schedule<Gas> {
/// Gas cost to deposit an event; the base.
pub event_base_cost: Gas,
/// Base gas cost to call into a contract.
pub call_base_cost: Gas,
/// Base gas cost to instantiate a contract.
pub instantiate_base_cost: Gas,
/// Gas cost per one byte read from the sandbox memory.
pub sandbox_data_read_cost: Gas,
@@ -797,19 +793,21 @@ pub struct Schedule<Gas> {
pub max_subject_len: u32,
}
impl<Gas: From<u32>> Default for Schedule<Gas> {
fn default() -> Schedule<Gas> {
impl Default for Schedule {
fn default() -> Schedule {
Schedule {
version: 0,
put_code_per_byte_cost: 1.into(),
grow_mem_cost: 1.into(),
regular_op_cost: 1.into(),
return_data_per_byte_cost: 1.into(),
event_data_per_byte_cost: 1.into(),
event_per_topic_cost: 1.into(),
event_base_cost: 1.into(),
sandbox_data_read_cost: 1.into(),
sandbox_data_write_cost: 1.into(),
put_code_per_byte_cost: 1,
grow_mem_cost: 1,
regular_op_cost: 1,
return_data_per_byte_cost: 1,
event_data_per_byte_cost: 1,
event_per_topic_cost: 1,
event_base_cost: 1,
call_base_cost: 135,
instantiate_base_cost: 175,
sandbox_data_read_cost: 1,
sandbox_data_write_cost: 1,
max_event_topics: 4,
max_stack_height: 64 * 1024,
max_memory_pages: 16,
-3
View File
@@ -93,7 +93,6 @@ impl timestamp::Trait for Test {
impl Trait for Test {
type Currency = Balances;
type Call = Call;
type Gas = u64;
type DetermineContractAddress = DummyContractAddressFor;
type Event = MetaEvent;
type ComputeDispatchFee = DummyComputeDispatchFee;
@@ -215,8 +214,6 @@ impl ExtBuilder {
transfer_fee: self.transfer_fee,
creation_fee: self.creation_fee,
contract_fee: 21,
call_base_fee: 135,
create_base_fee: 175,
gas_price: self.gas_price,
max_depth: 100,
block_gas_limit: self.block_gas_limit,
@@ -26,11 +26,11 @@
//! this guarantees that every instrumented contract code in cache cannot have the version equal to the current one.
//! Thus, before executing a contract it should be reinstrument with new schedule.
use crate::gas::{GasMeter, Token};
use crate::gas::{Gas, GasMeter, Token};
use crate::wasm::{prepare, runtime::Env, PrefabWasmModule};
use crate::{CodeHash, CodeStorage, PristineCode, Schedule, Trait};
use rstd::prelude::*;
use runtime_primitives::traits::{CheckedMul, Hash, Bounded};
use runtime_primitives::traits::{Hash, Bounded};
use srml_support::StorageMap;
/// Gas metering token that used for charging storing code into the code storage.
@@ -41,12 +41,12 @@ use srml_support::StorageMap;
pub struct PutCodeToken(u32);
impl<T: Trait> Token<T> for PutCodeToken {
type Metadata = Schedule<T::Gas>;
type Metadata = Schedule;
fn calculate_amount(&self, metadata: &Schedule<T::Gas>) -> T::Gas {
fn calculate_amount(&self, metadata: &Schedule) -> Gas {
metadata
.put_code_per_byte_cost
.checked_mul(&self.0.into())
.checked_mul(self.0.into())
.unwrap_or_else(|| Bounded::max_value())
}
}
@@ -58,7 +58,7 @@ impl<T: Trait> Token<T> for PutCodeToken {
pub fn save<T: Trait>(
original_code: Vec<u8>,
gas_meter: &mut GasMeter<T>,
schedule: &Schedule<T::Gas>,
schedule: &Schedule,
) -> Result<CodeHash<T>, &'static str> {
// The first time instrumentation is on the user. However, consequent reinstrumentation
// due to the schedule changes is on governance system.
@@ -69,7 +69,7 @@ pub fn save<T: Trait>(
return Err("there is not enough gas for storing the code");
}
let prefab_module = prepare::prepare_contract::<T, Env>(&original_code, schedule)?;
let prefab_module = prepare::prepare_contract::<Env>(&original_code, schedule)?;
let code_hash = T::Hashing::hash(&original_code);
<CodeStorage<T>>::insert(code_hash, prefab_module);
@@ -85,7 +85,7 @@ pub fn save<T: Trait>(
/// re-instrumentation and update the cache in the storage.
pub fn load<T: Trait>(
code_hash: &CodeHash<T>,
schedule: &Schedule<T::Gas>,
schedule: &Schedule,
) -> Result<PrefabWasmModule, &'static str> {
let mut prefab_module =
<CodeStorage<T>>::get(code_hash).ok_or_else(|| "code is not found")?;
@@ -97,7 +97,7 @@ pub fn load<T: Trait>(
// We need to re-instrument the code with the latest schedule here.
let original_code =
<PristineCode<T>>::get(code_hash).ok_or_else(|| "pristine code is not found")?;
prefab_module = prepare::prepare_contract::<T, Env>(&original_code, schedule)?;
prefab_module = prepare::prepare_contract::<Env>(&original_code, schedule)?;
<CodeStorage<T>>::insert(code_hash, prefab_module.clone());
}
Ok(prefab_module)
@@ -200,7 +200,7 @@ mod tests {
use crate::wasm::tests::MockExt;
use crate::wasm::Runtime;
use crate::exec::Ext;
use crate::Trait;
use crate::gas::Gas;
#[test]
fn macro_unmarshall_then_body_then_marshall_value_or_trap() {
@@ -256,7 +256,7 @@ mod tests {
#[test]
fn macro_define_func() {
define_func!( <E: Ext> ext_gas (_ctx, amount: u32) => {
let amount = <E::T as Trait>::Gas::from(amount);
let amount = Gas::from(amount);
if !amount.is_zero() {
Ok(())
} else {
@@ -308,7 +308,7 @@ mod tests {
define_env!(Env, <E: Ext>,
ext_gas( _ctx, amount: u32 ) => {
let amount = <E::T as Trait>::Gas::from(amount);
let amount = Gas::from(amount);
if !amount.is_zero() {
Ok(())
} else {
+12 -12
View File
@@ -63,17 +63,17 @@ pub struct WasmExecutable {
}
/// Loader which fetches `WasmExecutable` from the code cache.
pub struct WasmLoader<'a, T: Trait> {
schedule: &'a Schedule<T::Gas>,
pub struct WasmLoader<'a> {
schedule: &'a Schedule,
}
impl<'a, T: Trait> WasmLoader<'a, T> {
pub fn new(schedule: &'a Schedule<T::Gas>) -> Self {
impl<'a> WasmLoader<'a> {
pub fn new(schedule: &'a Schedule) -> Self {
WasmLoader { schedule }
}
}
impl<'a, T: Trait> crate::exec::Loader<T> for WasmLoader<'a, T> {
impl<'a, T: Trait> crate::exec::Loader<T> for WasmLoader<'a> {
type Executable = WasmExecutable;
fn load_init(&self, code_hash: &CodeHash<T>) -> Result<WasmExecutable, &'static str> {
@@ -93,17 +93,17 @@ impl<'a, T: Trait> crate::exec::Loader<T> for WasmLoader<'a, T> {
}
/// Implementation of `Vm` that takes `WasmExecutable` and executes it.
pub struct WasmVm<'a, T: Trait> {
schedule: &'a Schedule<T::Gas>,
pub struct WasmVm<'a> {
schedule: &'a Schedule,
}
impl<'a, T: Trait> WasmVm<'a, T> {
pub fn new(schedule: &'a Schedule<T::Gas>) -> Self {
impl<'a> WasmVm<'a> {
pub fn new(schedule: &'a Schedule) -> Self {
WasmVm { schedule }
}
}
impl<'a, T: Trait> crate::exec::Vm<T> for WasmVm<'a, T> {
impl<'a, T: Trait> crate::exec::Vm<T> for WasmVm<'a> {
type Executable = WasmExecutable;
fn execute<E: Ext<T = T>>(
@@ -303,9 +303,9 @@ mod tests {
use crate::exec::Vm;
let wasm = wabt::wat2wasm(wat).unwrap();
let schedule = crate::Schedule::<u64>::default();
let schedule = crate::Schedule::default();
let prefab_module =
prepare_contract::<Test, super::runtime::Env>(&wasm, &schedule).unwrap();
prepare_contract::<super::runtime::Env>(&wasm, &schedule).unwrap();
let exec = WasmExecutable {
// Use a "call" convention.
+14 -15
View File
@@ -20,33 +20,33 @@
use crate::wasm::env_def::ImportSatisfyCheck;
use crate::wasm::PrefabWasmModule;
use crate::{Schedule, Trait};
use crate::Schedule;
use parity_wasm::elements::{self, Internal, External, MemoryType, Type};
use pwasm_utils;
use pwasm_utils::rules;
use rstd::prelude::*;
use runtime_primitives::traits::{UniqueSaturatedInto, SaturatedConversion};
use runtime_primitives::traits::{SaturatedConversion};
struct ContractModule<'a, Gas: 'a> {
struct ContractModule<'a> {
/// A deserialized module. The module is valid (this is Guaranteed by `new` method).
///
/// An `Option` is used here for loaning (`take()`-ing) the module.
/// Invariant: Can't be `None` (i.e. on enter and on exit from the function
/// the value *must* be `Some`).
module: Option<elements::Module>,
schedule: &'a Schedule<Gas>,
schedule: &'a Schedule,
}
impl<'a, Gas: 'a + From<u32> + UniqueSaturatedInto<u32> + Clone> ContractModule<'a, Gas> {
impl<'a> ContractModule<'a> {
/// Creates a new instance of `ContractModule`.
///
/// Returns `Err` if the `original_code` couldn't be decoded or
/// if it contains an invalid module.
fn new(
original_code: &[u8],
schedule: &'a Schedule<Gas>,
) -> Result<ContractModule<'a, Gas>, &'static str> {
schedule: &'a Schedule,
) -> Result<Self, &'static str> {
use wasmi_validation::{validate_module, PlainValidator};
let module =
@@ -290,9 +290,9 @@ impl<'a, Gas: 'a + From<u32> + UniqueSaturatedInto<u32> + Clone> ContractModule<
/// - all imported functions from the external environment matches defined by `env` module,
///
/// The preprocessing includes injecting code for gas metering and metering the height of stack.
pub fn prepare_contract<T: Trait, C: ImportSatisfyCheck>(
pub fn prepare_contract<C: ImportSatisfyCheck>(
original_code: &[u8],
schedule: &Schedule<T::Gas>,
schedule: &Schedule,
) -> Result<PrefabWasmModule, &'static str> {
let mut contract_module = ContractModule::new(original_code, schedule)?;
contract_module.scan_exports()?;
@@ -347,7 +347,6 @@ pub fn prepare_contract<T: Trait, C: ImportSatisfyCheck>(
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::Test;
use crate::exec::Ext;
use std::fmt;
use wabt;
@@ -377,8 +376,8 @@ mod tests {
#[test]
fn $name() {
let wasm = wabt::Wat2Wasm::new().validate(false).convert($wat).unwrap();
let schedule = Schedule::<u64>::default();
let r = prepare_contract::<Test, TestEnv>(wasm.as_ref(), &schedule);
let schedule = Schedule::default();
let r = prepare_contract::<TestEnv>(wasm.as_ref(), &schedule);
assert_matches!(r, $($expected)*);
}
};
@@ -406,7 +405,7 @@ mod tests {
// Tests below assumes that maximum page number is configured to a certain number.
#[test]
fn assume_memory_size() {
assert_eq!(Schedule::<u64>::default().max_memory_pages, 16);
assert_eq!(Schedule::default().max_memory_pages, 16);
}
prepare_test!(memory_with_one_page,
@@ -620,9 +619,9 @@ mod tests {
)
"#
).unwrap();
let mut schedule = Schedule::<u64>::default();
let mut schedule = Schedule::default();
schedule.enable_println = true;
let r = prepare_contract::<Test, TestEnv>(wasm.as_ref(), &schedule);
let r = prepare_contract::<TestEnv>(wasm.as_ref(), &schedule);
assert_matches!(r, Ok(_));
}
}
+18 -18
View File
@@ -21,13 +21,13 @@ use crate::exec::{
Ext, VmExecResult, OutputBuf, EmptyOutputBuf, CallReceipt, InstantiateReceipt, StorageKey,
TopicOf,
};
use crate::gas::{GasMeter, Token, GasMeterResult, approx_gas_for_balance};
use crate::gas::{Gas, GasMeter, Token, GasMeterResult, approx_gas_for_balance};
use sandbox;
use system;
use rstd::prelude::*;
use rstd::mem;
use parity_codec::{Decode, Encode};
use runtime_primitives::traits::{CheckedMul, CheckedAdd, Bounded, SaturatedConversion};
use runtime_primitives::traits::{Bounded, SaturatedConversion};
/// Enumerates all possible *special* trap conditions.
///
@@ -45,7 +45,7 @@ pub(crate) struct Runtime<'a, E: Ext + 'a> {
// we wrap output buffer to make it possible to take the buffer out.
empty_output_buf: Option<EmptyOutputBuf>,
scratch_buf: Vec<u8>,
schedule: &'a Schedule<<E::T as Trait>::Gas>,
schedule: &'a Schedule,
memory: sandbox::Memory,
gas_meter: &'a mut GasMeter<E::T>,
special_trap: Option<SpecialTrap>,
@@ -55,7 +55,7 @@ impl<'a, E: Ext + 'a> Runtime<'a, E> {
ext: &'a mut E,
input_data: Vec<u8>,
empty_output_buf: EmptyOutputBuf,
schedule: &'a Schedule<<E::T as Trait>::Gas>,
schedule: &'a Schedule,
memory: sandbox::Memory,
gas_meter: &'a mut GasMeter<E::T>,
) -> Self {
@@ -97,7 +97,7 @@ pub(crate) fn to_execution_result<E: Ext>(
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
#[derive(Copy, Clone)]
pub enum RuntimeToken<Gas> {
pub enum RuntimeToken {
/// Explicit call to the `gas` function. Charge the gas meter
/// with the value provided.
Explicit(u32),
@@ -115,39 +115,39 @@ pub enum RuntimeToken<Gas> {
DepositEvent(u32, u32),
}
impl<T: Trait> Token<T> for RuntimeToken<T::Gas> {
type Metadata = Schedule<T::Gas>;
impl<T: Trait> Token<T> for RuntimeToken {
type Metadata = Schedule;
fn calculate_amount(&self, metadata: &Schedule<T::Gas>) -> T::Gas {
fn calculate_amount(&self, metadata: &Schedule) -> Gas {
use self::RuntimeToken::*;
let value = match *self {
Explicit(amount) => Some(amount.into()),
ReadMemory(byte_count) => metadata
.sandbox_data_read_cost
.checked_mul(&byte_count.into()),
.checked_mul(byte_count.into()),
WriteMemory(byte_count) => metadata
.sandbox_data_write_cost
.checked_mul(&byte_count.into()),
.checked_mul(byte_count.into()),
ReturnData(byte_count) => metadata
.return_data_per_byte_cost
.checked_mul(&byte_count.into()),
.checked_mul(byte_count.into()),
DepositEvent(topic_count, data_byte_count) => {
let data_cost = metadata
.event_data_per_byte_cost
.checked_mul(&data_byte_count.into());
.checked_mul(data_byte_count.into());
let topics_cost = metadata
.event_per_topic_cost
.checked_mul(&topic_count.into());
.checked_mul(topic_count.into());
data_cost
.and_then(|data_cost| {
topics_cost.and_then(|topics_cost| {
data_cost.checked_add(&topics_cost)
data_cost.checked_add(topics_cost)
})
})
.and_then(|data_and_topics_cost|
data_and_topics_cost.checked_add(&metadata.event_base_cost)
data_and_topics_cost.checked_add(metadata.event_base_cost)
)
},
ComputedDispatchFee(gas) => Some(gas),
@@ -221,7 +221,7 @@ fn read_sandbox_memory_into_buf<E: Ext>(
/// - out of gas
/// - designated area is not within the bounds of the sandbox memory.
fn write_sandbox_memory<T: Trait>(
schedule: &Schedule<T::Gas>,
schedule: &Schedule,
gas_meter: &mut GasMeter<T>,
memory: &sandbox::Memory,
ptr: u32,
@@ -509,7 +509,7 @@ define_env!(Env, <E: Ext>,
// Stores the amount of gas left into the scratch buffer.
//
// The data is encoded as T::Balance. The current contents of the scratch buffer are overwritten.
// The data is encoded as Gas. The current contents of the scratch buffer are overwritten.
ext_gas_left(ctx) => {
ctx.scratch_buf.clear();
ctx.gas_meter.gas_left().encode_to(&mut ctx.scratch_buf);
@@ -573,7 +573,7 @@ define_env!(Env, <E: Ext>,
// Charge gas for dispatching this call.
let fee = {
let balance_fee = <<E as Ext>::T as Trait>::ComputeDispatchFee::compute_dispatch_fee(&call);
approx_gas_for_balance::<<E as Ext>::T>(ctx.gas_meter.gas_price(), balance_fee)
approx_gas_for_balance(ctx.gas_meter.gas_price(), balance_fee)
};
charge_gas(&mut ctx.gas_meter, ctx.schedule, RuntimeToken::ComputedDispatchFee(fee))?;