mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 20:31:13 +00:00
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:
Generated
+1
@@ -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",
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(_));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user