mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 17:11:02 +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:
@@ -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