Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
@@ -27,16 +27,17 @@
//! 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::{
CodeHash, CodeStorage, PristineCode, Schedule, Config, Error, Weight,
wasm::{prepare, PrefabWasmModule}, Pallet as Contracts, Event,
gas::{GasMeter, Token},
weights::WeightInfo,
};
use sp_core::crypto::UncheckedFrom;
use frame_support::dispatch::DispatchError;
#[cfg(feature = "runtime-benchmarks")]
pub use self::private::reinstrument as reinstrument;
pub use self::private::reinstrument;
use crate::{
gas::{GasMeter, Token},
wasm::{prepare, PrefabWasmModule},
weights::WeightInfo,
CodeHash, CodeStorage, Config, Error, Event, Pallet as Contracts, PristineCode, Schedule,
Weight,
};
use frame_support::dispatch::DispatchError;
use sp_core::crypto::UncheckedFrom;
/// Put the instrumented module in storage.
///
@@ -44,7 +45,7 @@ pub use self::private::reinstrument as reinstrument;
/// under the specified `code_hash`.
pub fn store<T: Config>(mut prefab_module: PrefabWasmModule<T>)
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
let code_hash = sp_std::mem::take(&mut prefab_module.code_hash);
@@ -53,14 +54,12 @@ where
if let Some(code) = prefab_module.original_code.take() {
<PristineCode<T>>::insert(&code_hash, code);
}
<CodeStorage<T>>::mutate(&code_hash, |existing| {
match existing {
Some(module) => increment_64(&mut module.refcount),
None => {
*existing = Some(prefab_module);
Contracts::<T>::deposit_event(Event::CodeStored(code_hash))
}
}
<CodeStorage<T>>::mutate(&code_hash, |existing| match existing {
Some(module) => increment_64(&mut module.refcount),
None => {
*existing = Some(prefab_module);
Contracts::<T>::deposit_event(Event::CodeStored(code_hash))
},
});
}
@@ -69,7 +68,7 @@ where
/// Removes the code instead of storing it when the refcount drops to zero.
pub fn store_decremented<T: Config>(mut prefab_module: PrefabWasmModule<T>)
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
prefab_module.refcount = prefab_module.refcount.saturating_sub(1);
if prefab_module.refcount > 0 {
@@ -81,10 +80,12 @@ where
}
/// Increment the refcount of a code in-storage by one.
pub fn increment_refcount<T: Config>(code_hash: CodeHash<T>, gas_meter: &mut GasMeter<T>)
-> Result<(), DispatchError>
pub fn increment_refcount<T: Config>(
code_hash: CodeHash<T>,
gas_meter: &mut GasMeter<T>,
) -> Result<(), DispatchError>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
gas_meter.charge(CodeToken::UpdateRefcount(estimate_code_size::<T>(&code_hash)?))?;
<CodeStorage<T>>::mutate(code_hash, |existing| {
@@ -98,10 +99,12 @@ where
}
/// Decrement the refcount of a code in-storage by one and remove the code when it drops to zero.
pub fn decrement_refcount<T: Config>(code_hash: CodeHash<T>, gas_meter: &mut GasMeter<T>)
-> Result<(), DispatchError>
pub fn decrement_refcount<T: Config>(
code_hash: CodeHash<T>,
gas_meter: &mut GasMeter<T>,
) -> Result<(), DispatchError>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
if let Ok(len) = estimate_code_size::<T>(&code_hash) {
gas_meter.charge(CodeToken::UpdateRefcount(len))?;
@@ -133,7 +136,7 @@ pub fn load<T: Config>(
mut reinstrument: Option<(&Schedule<T>, &mut GasMeter<T>)>,
) -> Result<PrefabWasmModule<T>, DispatchError>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
// The reinstrument case coincides with the cases where we need to charge extra
// based upon the code size: On-chain execution.
@@ -141,8 +144,8 @@ where
gas_meter.charge(CodeToken::Load(estimate_code_size::<T>(&code_hash)?))?;
}
let mut prefab_module = <CodeStorage<T>>::get(code_hash)
.ok_or_else(|| Error::<T>::CodeNotFound)?;
let mut prefab_module =
<CodeStorage<T>>::get(code_hash).ok_or_else(|| Error::<T>::CodeNotFound)?;
prefab_module.code_hash = code_hash;
if let Some((schedule, gas_meter)) = reinstrument {
@@ -165,7 +168,7 @@ mod private {
schedule: &Schedule<T>,
) -> Result<(), DispatchError>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
let original_code = <PristineCode<T>>::get(&prefab_module.code_hash)
.ok_or_else(|| Error::<T>::CodeNotFound)?;
@@ -179,7 +182,7 @@ mod private {
/// Finish removal of a code by deleting the pristine code and emitting an event.
fn finish_removal<T: Config>(code_hash: CodeHash<T>)
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
<PristineCode<T>>::remove(code_hash);
Contracts::<T>::deposit_event(Event::CodeRemoved(code_hash))
@@ -190,13 +193,15 @@ where
/// We try hard to be infallible here because otherwise more storage transactions would be
/// necessary to account for failures in storing code for an already instantiated contract.
fn increment_64(refcount: &mut u64) {
*refcount = refcount.checked_add(1).expect("
*refcount = refcount.checked_add(1).expect(
"
refcount is 64bit. Generating this overflow would require to store
_at least_ 18 exabyte of data assuming that a contract consumes only
one byte of data. Any node would run out of storage space before hitting
this overflow.
qed
");
",
);
}
/// Get the size of the instrumented code stored at `code_hash` without loading it.
@@ -206,7 +211,7 @@ fn increment_64(refcount: &mut u64) {
/// compared to the code size. Additionally, charging too much weight is completely safe.
fn estimate_code_size<T: Config>(code_hash: &CodeHash<T>) -> Result<u32, DispatchError>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
let key = <CodeStorage<T>>::hashed_key_for(code_hash);
let mut data = [0u8; 0];
@@ -229,7 +234,7 @@ enum CodeToken {
impl<T> Token<T> for CodeToken
where
T: Config,
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
fn weight(&self) -> Weight {
use self::CodeToken::*;
@@ -240,9 +245,10 @@ where
// the contract.
match *self {
Instrument(len) => T::WeightInfo::instrument(len / 1024),
Load(len) => T::WeightInfo::code_load(len / 1024).saturating_sub(T::WeightInfo::code_load(0)),
UpdateRefcount(len) =>
T::WeightInfo::code_refcount(len / 1024).saturating_sub(T::WeightInfo::code_refcount(0)),
Load(len) =>
T::WeightInfo::code_load(len / 1024).saturating_sub(T::WeightInfo::code_load(0)),
UpdateRefcount(len) => T::WeightInfo::code_refcount(len / 1024)
.saturating_sub(T::WeightInfo::code_refcount(0)),
}
}
}
@@ -255,14 +255,14 @@ macro_rules! define_env {
#[cfg(test)]
mod tests {
use crate::{
exec::Ext,
wasm::{runtime::TrapReason, tests::MockExt, Runtime},
Weight,
};
use pwasm_utils::parity_wasm::elements::{FunctionType, ValueType};
use sp_runtime::traits::Zero;
use sp_sandbox::{ReturnValue, Value};
use crate::{
Weight,
wasm::{Runtime, runtime::TrapReason, tests::MockExt},
exec::Ext,
};
struct TestRuntime {
value: u32,
@@ -333,16 +333,15 @@ mod tests {
Err(TrapReason::Termination)
}
});
let _f: fn(&mut Runtime<MockExt>, &[sp_sandbox::Value])
-> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> = seal_gas::<MockExt>;
let _f: fn(
&mut Runtime<MockExt>,
&[sp_sandbox::Value],
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> = seal_gas::<MockExt>;
}
#[test]
fn macro_gen_signature() {
assert_eq!(
gen_signature!((i32)),
FunctionType::new(vec![ValueType::I32], vec![]),
);
assert_eq!(gen_signature!((i32)), FunctionType::new(vec![ValueType::I32], vec![]),);
assert_eq!(
gen_signature!( (i32, u32) -> u32 ),
@@ -387,11 +386,11 @@ mod tests {
},
);
assert!(
Env::can_satisfy(b"seal0", b"seal_gas",&FunctionType::new(vec![ValueType::I32], vec![]))
);
assert!(
!Env::can_satisfy(b"seal0", b"not_exists", &FunctionType::new(vec![], vec![]))
);
assert!(Env::can_satisfy(
b"seal0",
b"seal_gas",
&FunctionType::new(vec![ValueType::I32], vec![])
));
assert!(!Env::can_satisfy(b"seal0", b"not_exists", &FunctionType::new(vec![], vec![])));
}
}
@@ -18,8 +18,8 @@
use super::Runtime;
use crate::exec::Ext;
use sp_sandbox::Value;
use pwasm_utils::parity_wasm::elements::{FunctionType, ValueType};
use sp_sandbox::Value;
#[macro_use]
pub mod macros;
@@ -67,11 +67,10 @@ impl ConvertibleToWasm for u64 {
}
}
pub type HostFunc<E> =
fn(
&mut Runtime<E>,
&[sp_sandbox::Value]
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError>;
pub type HostFunc<E> = fn(
&mut Runtime<E>,
&[sp_sandbox::Value],
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError>;
pub trait FunctionImplProvider<E: Ext> {
fn impls<F: FnMut(&[u8], &[u8], HostFunc<E>)>(f: &mut F);
+127 -322
View File
@@ -24,19 +24,19 @@ mod code_cache;
mod prepare;
mod runtime;
use crate::{
CodeHash, Schedule, Config,
wasm::env_def::FunctionImplProvider,
exec::{Ext, Executable, ExportedFunction, ExecResult},
gas::GasMeter,
};
use sp_std::prelude::*;
use sp_core::crypto::UncheckedFrom;
use codec::{Encode, Decode};
use frame_support::dispatch::DispatchError;
pub use self::runtime::{ReturnCode, Runtime, RuntimeCosts};
#[cfg(feature = "runtime-benchmarks")]
pub use self::code_cache::reinstrument;
pub use self::runtime::{ReturnCode, Runtime, RuntimeCosts};
use crate::{
exec::{ExecResult, Executable, ExportedFunction, Ext},
gas::GasMeter,
wasm::env_def::FunctionImplProvider,
CodeHash, Config, Schedule,
};
use codec::{Decode, Encode};
use frame_support::dispatch::DispatchError;
use sp_core::crypto::UncheckedFrom;
use sp_std::prelude::*;
#[cfg(test)]
pub use tests::MockExt;
@@ -108,12 +108,12 @@ impl ExportedFunction {
impl<T: Config> PrefabWasmModule<T>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
/// Create the module by checking and instrumenting `original_code`.
pub fn from_code(
original_code: Vec<u8>,
schedule: &Schedule<T>
schedule: &Schedule<T>,
) -> Result<Self, DispatchError> {
prepare::prepare_contract(original_code, schedule).map_err(Into::into)
}
@@ -127,7 +127,7 @@ where
#[cfg(feature = "runtime-benchmarks")]
pub fn store_code_unchecked(
original_code: Vec<u8>,
schedule: &Schedule<T>
schedule: &Schedule<T>,
) -> Result<(), DispatchError> {
let executable = prepare::benchmarking::prepare_contract(original_code, schedule)
.map_err::<DispatchError, _>(Into::into)?;
@@ -150,7 +150,7 @@ where
impl<T: Config> Executable<T> for PrefabWasmModule<T>
where
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
fn from_storage(
code_hash: CodeHash<T>,
@@ -168,15 +168,14 @@ where
code_cache::store_decremented(self);
}
fn add_user(code_hash: CodeHash<T>, gas_meter: &mut GasMeter<T>)
-> Result<(), DispatchError>
{
fn add_user(code_hash: CodeHash<T>, gas_meter: &mut GasMeter<T>) -> Result<(), DispatchError> {
code_cache::increment_refcount::<T>(code_hash, gas_meter)
}
fn remove_user(code_hash: CodeHash<T>, gas_meter: &mut GasMeter<T>)
-> Result<(), DispatchError>
{
fn remove_user(
code_hash: CodeHash<T>,
gas_meter: &mut GasMeter<T>,
) -> Result<(), DispatchError> {
code_cache::decrement_refcount::<T>(code_hash, gas_meter)
}
@@ -187,16 +186,15 @@ where
input_data: Vec<u8>,
) -> ExecResult {
let memory =
sp_sandbox::Memory::new(self.initial, Some(self.maximum))
.unwrap_or_else(|_| {
sp_sandbox::Memory::new(self.initial, Some(self.maximum)).unwrap_or_else(|_| {
// unlike `.expect`, explicit panic preserves the source location.
// Needed as we can't use `RUST_BACKTRACE` in here.
panic!(
"exec.prefab_module.initial can't be greater than exec.prefab_module.maximum;
panic!(
"exec.prefab_module.initial can't be greater than exec.prefab_module.maximum;
thus Memory::new must not fail;
qed"
)
});
)
});
let mut imports = sp_sandbox::EnvironmentDefinitionBuilder::new();
imports.add_memory(self::prepare::IMPORT_MODULE_MEMORY, "memory", memory.clone());
@@ -204,11 +202,7 @@ where
imports.add_host_func(module, name, func_ptr);
});
let mut runtime = Runtime::new(
ext,
input_data,
memory,
);
let mut runtime = Runtime::new(ext, input_data, memory);
// We store before executing so that the code hash is available in the constructor.
let code = self.code.clone();
@@ -245,31 +239,27 @@ where
mod tests {
use super::*;
use crate::{
CodeHash, BalanceOf, Error, Pallet as Contracts,
exec::{
Ext, StorageKey, AccountIdOf, Executable, SeedOf, BlockNumberOf,
RentParams, ExecError, ErrorOrigin,
AccountIdOf, BlockNumberOf, ErrorOrigin, ExecError, Executable, Ext, RentParams,
SeedOf, StorageKey,
},
gas::GasMeter,
rent::RentStatus,
tests::{Test, Call, ALICE, BOB},
tests::{Call, Test, ALICE, BOB},
BalanceOf, CodeHash, Error, Pallet as Contracts,
};
use std::{
borrow::BorrowMut,
cell::RefCell,
collections::HashMap,
};
use sp_core::{Bytes, H256};
use hex_literal::hex;
use sp_runtime::DispatchError;
use assert_matches::assert_matches;
use frame_support::{
assert_ok,
dispatch::{DispatchResult, DispatchResultWithPostInfo},
weights::Weight,
};
use assert_matches::assert_matches;
use hex_literal::hex;
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
use pretty_assertions::assert_eq;
use sp_core::{Bytes, H256};
use sp_runtime::DispatchError;
use std::{borrow::BorrowMut, cell::RefCell, collections::HashMap};
#[derive(Debug, PartialEq, Eq)]
struct RestoreEntry {
@@ -360,12 +350,7 @@ mod tests {
data: Vec<u8>,
allows_reentry: bool,
) -> Result<ExecReturnValue, ExecError> {
self.calls.push(CallEntry {
to,
value,
data,
allows_reentry,
});
self.calls.push(CallEntry { to, value, data, allows_reentry });
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: call_return_data() })
}
fn instantiate(
@@ -385,30 +370,15 @@ mod tests {
});
Ok((
Contracts::<Test>::contract_address(&ALICE, &code_hash, salt),
ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes(Vec::new()),
},
ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) },
))
}
fn transfer(
&mut self,
to: &AccountIdOf<Self::T>,
value: u64,
) -> Result<(), DispatchError> {
self.transfers.push(TransferEntry {
to: to.clone(),
value,
});
fn transfer(&mut self, to: &AccountIdOf<Self::T>, value: u64) -> Result<(), DispatchError> {
self.transfers.push(TransferEntry { to: to.clone(), value });
Ok(())
}
fn terminate(
&mut self,
beneficiary: &AccountIdOf<Self::T>,
) -> Result<(), DispatchError> {
self.terminations.push(TerminationEntry {
beneficiary: beneficiary.clone(),
});
fn terminate(&mut self, beneficiary: &AccountIdOf<Self::T>) -> Result<(), DispatchError> {
self.terminations.push(TerminationEntry { beneficiary: beneficiary.clone() });
Ok(())
}
fn restore_to(
@@ -418,12 +388,7 @@ mod tests {
rent_allowance: u64,
delta: Vec<StorageKey>,
) -> Result<(), DispatchError> {
self.restores.push(RestoreEntry {
dest,
code_hash,
rent_allowance,
delta,
});
self.restores.push(RestoreEntry { dest, code_hash, rent_allowance, delta });
Ok(())
}
fn get_storage(&mut self, key: &StorageKey) -> Option<Vec<u8>> {
@@ -466,8 +431,12 @@ mod tests {
fn rent_allowance(&mut self) -> u64 {
self.rent_allowance
}
fn block_number(&self) -> u64 { 121 }
fn max_value_size(&self) -> u32 { 16_384 }
fn block_number(&self) -> u64 {
121
}
fn max_value_size(&self) -> u32 {
16_384
}
fn get_weight_price(&self, weight: Weight) -> BalanceOf<Self::T> {
BalanceOf::<Self::T>::from(1312_u32).saturating_mul(weight.into())
}
@@ -493,16 +462,11 @@ mod tests {
}
}
fn execute<E: BorrowMut<MockExt>>(
wat: &str,
input_data: Vec<u8>,
mut ext: E,
) -> ExecResult
{
fn execute<E: BorrowMut<MockExt>>(wat: &str, input_data: Vec<u8>, mut ext: E) -> ExecResult {
let wasm = wat::parse_str(wat).unwrap();
let schedule = crate::Schedule::default();
let executable = PrefabWasmModule::<<MockExt as Ext>::T>::from_code(wasm, &schedule)
.unwrap();
let executable =
PrefabWasmModule::<<MockExt as Ext>::T>::from_code(wasm, &schedule).unwrap();
executable.execute(ext.borrow_mut(), &ExportedFunction::Call, input_data)
}
@@ -543,19 +507,9 @@ mod tests {
#[test]
fn contract_transfer() {
let mut mock_ext = MockExt::default();
assert_ok!(execute(
CODE_TRANSFER,
vec![],
&mut mock_ext,
));
assert_ok!(execute(CODE_TRANSFER, vec![], &mut mock_ext,));
assert_eq!(
&mock_ext.transfers,
&[TransferEntry {
to: ALICE,
value: 153,
}]
);
assert_eq!(&mock_ext.transfers, &[TransferEntry { to: ALICE, value: 153 }]);
}
const CODE_CALL: &str = r#"
@@ -607,20 +561,11 @@ mod tests {
#[test]
fn contract_call() {
let mut mock_ext = MockExt::default();
assert_ok!(execute(
CODE_CALL,
vec![],
&mut mock_ext,
));
assert_ok!(execute(CODE_CALL, vec![], &mut mock_ext,));
assert_eq!(
&mock_ext.calls,
&[CallEntry {
to: ALICE,
value: 6,
data: vec![1, 2, 3, 4],
allows_reentry: true,
}]
&[CallEntry { to: ALICE, value: 6, data: vec![1, 2, 3, 4], allows_reentry: true }]
);
}
@@ -675,12 +620,7 @@ mod tests {
assert_eq!(
&mock_ext.calls,
&[CallEntry {
to: ALICE,
value: 0x2a,
data: input,
allows_reentry: false,
}]
&[CallEntry { to: ALICE, value: 0x2a, data: input, allows_reentry: false }]
);
}
@@ -736,12 +676,7 @@ mod tests {
assert_eq!(result.data.0, input);
assert_eq!(
&mock_ext.calls,
&[CallEntry {
to: ALICE,
value: 0x2a,
data: input,
allows_reentry: true,
}]
&[CallEntry { to: ALICE, value: 0x2a, data: input, allows_reentry: true }]
);
}
@@ -789,12 +724,7 @@ mod tests {
assert_eq!(result.data, call_return_data());
assert_eq!(
&mock_ext.calls,
&[CallEntry {
to: ALICE,
value: 0x2a,
data: input,
allows_reentry: false,
}]
&[CallEntry { to: ALICE, value: 0x2a, data: input, allows_reentry: false }]
);
}
@@ -857,11 +787,7 @@ mod tests {
#[test]
fn contract_instantiate() {
let mut mock_ext = MockExt::default();
assert_ok!(execute(
CODE_INSTANTIATE,
vec![],
&mut mock_ext,
));
assert_ok!(execute(CODE_INSTANTIATE, vec![], &mut mock_ext,));
assert_matches!(
&mock_ext.instantiates[..],
@@ -905,18 +831,9 @@ mod tests {
#[test]
fn contract_terminate() {
let mut mock_ext = MockExt::default();
execute(
CODE_TERMINATE,
vec![],
&mut mock_ext,
).unwrap();
execute(CODE_TERMINATE, vec![], &mut mock_ext).unwrap();
assert_eq!(
&mock_ext.terminations,
&[TerminationEntry {
beneficiary: ALICE,
}]
);
assert_eq!(&mock_ext.terminations, &[TerminationEntry { beneficiary: ALICE }]);
}
const CODE_TRANSFER_LIMITED_GAS: &str = r#"
@@ -967,20 +884,11 @@ mod tests {
#[test]
fn contract_call_limited_gas() {
let mut mock_ext = MockExt::default();
assert_ok!(execute(
&CODE_TRANSFER_LIMITED_GAS,
vec![],
&mut mock_ext,
));
assert_ok!(execute(&CODE_TRANSFER_LIMITED_GAS, vec![], &mut mock_ext,));
assert_eq!(
&mock_ext.calls,
&[CallEntry {
to: ALICE,
value: 6,
data: vec![1, 2, 3, 4],
allows_reentry: true,
}]
&[CallEntry { to: ALICE, value: 6, data: vec![1, 2, 3, 4], allows_reentry: true }]
);
}
@@ -1051,20 +959,14 @@ mod tests {
#[test]
fn get_storage_puts_data_into_buf() {
let mut mock_ext = MockExt::default();
mock_ext
.storage
.insert([0x11; 32], [0x22; 32].to_vec());
mock_ext.storage.insert([0x11; 32], [0x22; 32].to_vec());
let output = execute(
CODE_GET_STORAGE,
vec![],
mock_ext,
).unwrap();
let output = execute(CODE_GET_STORAGE, vec![], mock_ext).unwrap();
assert_eq!(output, ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes([0x22; 32].to_vec())
});
assert_eq!(
output,
ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes([0x22; 32].to_vec()) }
);
}
/// calls `seal_caller` and compares the result with the constant 42.
@@ -1112,11 +1014,7 @@ mod tests {
#[test]
fn caller() {
assert_ok!(execute(
CODE_CALLER,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_CALLER, vec![], MockExt::default(),));
}
/// calls `seal_address` and compares the result with the constant 69.
@@ -1164,11 +1062,7 @@ mod tests {
#[test]
fn address() {
assert_ok!(execute(
CODE_ADDRESS,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_ADDRESS, vec![], MockExt::default(),));
}
const CODE_BALANCE: &str = r#"
@@ -1214,11 +1108,7 @@ mod tests {
#[test]
fn balance() {
assert_ok!(execute(
CODE_BALANCE,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_BALANCE, vec![], MockExt::default(),));
}
const CODE_GAS_PRICE: &str = r#"
@@ -1264,11 +1154,7 @@ mod tests {
#[test]
fn gas_price() {
assert_ok!(execute(
CODE_GAS_PRICE,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_GAS_PRICE, vec![], MockExt::default(),));
}
const CODE_GAS_LEFT: &str = r#"
@@ -1315,11 +1201,7 @@ mod tests {
let mut ext = MockExt::default();
let gas_limit = ext.gas_meter.gas_left();
let output = execute(
CODE_GAS_LEFT,
vec![],
&mut ext,
).unwrap();
let output = execute(CODE_GAS_LEFT, vec![], &mut ext).unwrap();
let gas_left = Weight::decode(&mut &*output.data).unwrap();
let actual_left = ext.gas_meter.gas_left();
@@ -1370,11 +1252,7 @@ mod tests {
#[test]
fn value_transferred() {
assert_ok!(execute(
CODE_VALUE_TRANSFERRED,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_VALUE_TRANSFERRED, vec![], MockExt::default(),));
}
const CODE_RETURN_FROM_START_FN: &str = r#"
@@ -1403,18 +1281,11 @@ mod tests {
#[test]
fn return_from_start_fn() {
let output = execute(
CODE_RETURN_FROM_START_FN,
vec![],
MockExt::default(),
).unwrap();
let output = execute(CODE_RETURN_FROM_START_FN, vec![], MockExt::default()).unwrap();
assert_eq!(
output,
ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes(vec![1, 2, 3, 4])
}
ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(vec![1, 2, 3, 4]) }
);
}
@@ -1461,11 +1332,7 @@ mod tests {
#[test]
fn now() {
assert_ok!(execute(
CODE_TIMESTAMP_NOW,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_TIMESTAMP_NOW, vec![], MockExt::default(),));
}
const CODE_MINIMUM_BALANCE: &str = r#"
@@ -1510,11 +1377,7 @@ mod tests {
#[test]
fn minimum_balance() {
assert_ok!(execute(
CODE_MINIMUM_BALANCE,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_MINIMUM_BALANCE, vec![], MockExt::default(),));
}
const CODE_TOMBSTONE_DEPOSIT: &str = r#"
@@ -1559,11 +1422,7 @@ mod tests {
#[test]
fn tombstone_deposit() {
assert_ok!(execute(
CODE_TOMBSTONE_DEPOSIT,
vec![],
MockExt::default(),
));
assert_ok!(execute(CODE_TOMBSTONE_DEPOSIT, vec![], MockExt::default(),));
}
const CODE_RANDOM: &str = r#"
@@ -1622,11 +1481,7 @@ mod tests {
#[test]
fn random() {
let output = execute(
CODE_RANDOM,
vec![],
MockExt::default(),
).unwrap();
let output = execute(CODE_RANDOM, vec![], MockExt::default()).unwrap();
// The mock ext just returns the same data that was passed as the subject.
assert_eq!(
@@ -1697,26 +1552,24 @@ mod tests {
#[test]
fn random_v1() {
let output = execute(
CODE_RANDOM_V1,
vec![],
MockExt::default(),
).unwrap();
let output = execute(CODE_RANDOM_V1, vec![], MockExt::default()).unwrap();
// The mock ext just returns the same data that was passed as the subject.
assert_eq!(
output,
ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes((
data: Bytes(
(
hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"),
42u64,
).encode()),
)
.encode()
),
},
);
}
const CODE_DEPOSIT_EVENT: &str = r#"
(module
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
@@ -1743,16 +1596,15 @@ mod tests {
#[test]
fn deposit_event() {
let mut mock_ext = MockExt::default();
assert_ok!(execute(
CODE_DEPOSIT_EVENT,
vec![],
&mut mock_ext,
));
assert_ok!(execute(CODE_DEPOSIT_EVENT, vec![], &mut mock_ext,));
assert_eq!(mock_ext.events, vec![
(vec![H256::repeat_byte(0x33)],
vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00])
]);
assert_eq!(
mock_ext.events,
vec![(
vec![H256::repeat_byte(0x33)],
vec![0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x14, 0x00]
)]
);
assert!(mock_ext.gas_meter.gas_left() > 0);
}
@@ -1788,11 +1640,7 @@ mod tests {
#[test]
fn deposit_event_max_topics() {
assert_eq!(
execute(
CODE_DEPOSIT_EVENT_MAX_TOPICS,
vec![],
MockExt::default(),
),
execute(CODE_DEPOSIT_EVENT_MAX_TOPICS, vec![], MockExt::default(),),
Err(ExecError {
error: Error::<Test>::TooManyTopics.into(),
origin: ErrorOrigin::Caller,
@@ -1830,11 +1678,7 @@ mod tests {
#[test]
fn deposit_event_duplicates() {
assert_eq!(
execute(
CODE_DEPOSIT_EVENT_DUPLICATES,
vec![],
MockExt::default(),
),
execute(CODE_DEPOSIT_EVENT_DUPLICATES, vec![], MockExt::default(),),
Err(ExecError {
error: Error::<Test>::DuplicateTopics.into(),
origin: ErrorOrigin::Caller,
@@ -1887,11 +1731,7 @@ mod tests {
#[test]
fn block_number() {
let _ = execute(
CODE_BLOCK_NUMBER,
vec![],
MockExt::default(),
).unwrap();
let _ = execute(CODE_BLOCK_NUMBER, vec![], MockExt::default()).unwrap();
}
const CODE_RETURN_WITH_DATA: &str = r#"
@@ -1932,27 +1772,32 @@ mod tests {
CODE_RETURN_WITH_DATA,
hex!("00000000445566778899").to_vec(),
MockExt::default(),
).unwrap();
)
.unwrap();
assert_eq!(output, ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes(hex!("445566778899").to_vec()),
});
assert_eq!(
output,
ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes(hex!("445566778899").to_vec()),
}
);
assert!(output.is_success());
}
#[test]
fn return_with_revert_status() {
let output = execute(
CODE_RETURN_WITH_DATA,
hex!("010000005566778899").to_vec(),
MockExt::default(),
).unwrap();
let output =
execute(CODE_RETURN_WITH_DATA, hex!("010000005566778899").to_vec(), MockExt::default())
.unwrap();
assert_eq!(output, ExecReturnValue {
flags: ReturnFlags::REVERT,
data: Bytes(hex!("5566778899").to_vec()),
});
assert_eq!(
output,
ExecReturnValue {
flags: ReturnFlags::REVERT,
data: Bytes(hex!("5566778899").to_vec()),
}
);
assert!(!output.is_success());
}
@@ -1975,11 +1820,7 @@ mod tests {
#[test]
fn contract_out_of_bounds_access() {
let mut mock_ext = MockExt::default();
let result = execute(
CODE_OUT_OF_BOUNDS_ACCESS,
vec![],
&mut mock_ext,
);
let result = execute(CODE_OUT_OF_BOUNDS_ACCESS, vec![], &mut mock_ext);
assert_eq!(
result,
@@ -2009,11 +1850,7 @@ mod tests {
#[test]
fn contract_decode_length_ignored() {
let mut mock_ext = MockExt::default();
let result = execute(
CODE_DECODE_FAILURE,
vec![],
&mut mock_ext,
);
let result = execute(CODE_DECODE_FAILURE, vec![], &mut mock_ext);
// AccountID implements `MaxEncodeLen` and therefore the supplied length is
// no longer needed nor used to determine how much is read from contract memory.
assert_ok!(result);
@@ -2051,17 +1888,11 @@ mod tests {
(func (export "deploy"))
)
"#;
let output = execute(
CODE_RENT_PARAMS,
vec![],
MockExt::default(),
).unwrap();
let output = execute(CODE_RENT_PARAMS, vec![], MockExt::default()).unwrap();
let rent_params = Bytes(<RentParams<Test>>::default().encode());
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: rent_params });
}
#[test]
#[cfg(feature = "unstable-interface")]
fn rent_status_works() {
@@ -2095,11 +1926,7 @@ mod tests {
(func (export "deploy"))
)
"#;
let output = execute(
CODE_RENT_STATUS,
vec![],
MockExt::default(),
).unwrap();
let output = execute(CODE_RENT_STATUS, vec![], MockExt::default()).unwrap();
let rent_status = Bytes(<RentStatus<Test>>::default().encode());
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: rent_status });
}
@@ -2126,11 +1953,7 @@ mod tests {
)
"#;
let mut ext = MockExt::default();
execute(
CODE_DEBUG_MESSAGE,
vec![],
&mut ext,
).unwrap();
execute(CODE_DEBUG_MESSAGE, vec![], &mut ext).unwrap();
assert_eq!(std::str::from_utf8(&ext.debug_buffer).unwrap(), "Hello World!");
}
@@ -2157,11 +1980,7 @@ mod tests {
)
"#;
let mut ext = MockExt::default();
let result = execute(
CODE_DEBUG_MESSAGE_FAIL,
vec![],
&mut ext,
);
let result = execute(CODE_DEBUG_MESSAGE_FAIL, vec![], &mut ext);
assert_eq!(
result,
Err(ExecError {
@@ -2213,15 +2032,8 @@ mod tests {
use std::convert::TryInto;
let call = Call::System(frame_system::Call::remark(b"Hello World".to_vec()));
let mut ext = MockExt::default();
let result = execute(
CODE_CALL_RUNTIME,
call.encode(),
&mut ext,
).unwrap();
assert_eq!(
*ext.runtime_calls.borrow(),
vec![call],
);
let result = execute(CODE_CALL_RUNTIME, call.encode(), &mut ext).unwrap();
assert_eq!(*ext.runtime_calls.borrow(), vec![call],);
// 0 = ReturnCode::Success
assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0);
}
@@ -2230,11 +2042,7 @@ mod tests {
#[cfg(feature = "unstable-interface")]
fn call_runtime_panics_on_invalid_call() {
let mut ext = MockExt::default();
let result = execute(
CODE_CALL_RUNTIME,
vec![0x42],
&mut ext,
);
let result = execute(CODE_CALL_RUNTIME, vec![0x42], &mut ext);
assert_eq!(
result,
Err(ExecError {
@@ -2242,9 +2050,6 @@ mod tests {
origin: ErrorOrigin::Caller,
})
);
assert_eq!(
*ext.runtime_calls.borrow(),
vec![],
);
assert_eq!(*ext.runtime_calls.borrow(), vec![],);
}
}
+152 -146
View File
@@ -20,11 +20,11 @@
//! from a module.
use crate::{
Schedule, Config,
chain_extension::ChainExtension,
wasm::{PrefabWasmModule, env_def::ImportSatisfyCheck},
wasm::{env_def::ImportSatisfyCheck, PrefabWasmModule},
Config, Schedule,
};
use pwasm_utils::parity_wasm::elements::{self, Internal, External, MemoryType, Type, ValueType};
use pwasm_utils::parity_wasm::elements::{self, External, Internal, MemoryType, Type, ValueType};
use sp_runtime::traits::Hash;
use sp_std::prelude::*;
@@ -43,10 +43,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
///
/// 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<T>,
) -> Result<Self, &'static str> {
fn new(original_code: &[u8], schedule: &'a Schedule<T>) -> Result<Self, &'static str> {
use wasmi_validation::{validate_module, PlainValidator};
let module =
@@ -57,10 +54,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
// Return a `ContractModule` instance with
// __valid__ module.
Ok(ContractModule {
module,
schedule,
})
Ok(ContractModule { module, schedule })
}
/// Ensures that module doesn't declare internal memories.
@@ -69,11 +63,8 @@ impl<'a, T: Config> ContractModule<'a, T> {
/// Memory section contains declarations of internal linear memories, so if we find one
/// we reject such a module.
fn ensure_no_internal_memory(&self) -> Result<(), &'static str> {
if self.module
.memory_section()
.map_or(false, |ms| ms.entries().len() > 0)
{
return Err("module declares internal memory");
if self.module.memory_section().map_or(false, |ms| ms.entries().len() > 0) {
return Err("module declares internal memory")
}
Ok(())
}
@@ -84,7 +75,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
// In Wasm MVP spec, there may be at most one table declared. Double check this
// explicitly just in case the Wasm version changes.
if table_section.entries().len() > 1 {
return Err("multiple tables declared");
return Err("multiple tables declared")
}
if let Some(table_type) = table_section.entries().first() {
// Check the table's initial size as there is no instruction or environment function
@@ -102,7 +93,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
let code_section = if let Some(type_section) = self.module.code_section() {
type_section
} else {
return Ok(());
return Ok(())
};
for instr in code_section.bodies().iter().flat_map(|body| body.code().elements()) {
use self::elements::Instruction::BrTable;
@@ -131,7 +122,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
match global.global_type().content_type() {
ValueType::F32 | ValueType::F64 =>
return Err("use of floating point type in globals is forbidden"),
_ => {}
_ => {},
}
}
}
@@ -142,7 +133,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
match local.value_type() {
ValueType::F32 | ValueType::F64 =>
return Err("use of floating point type in locals is forbidden"),
_ => {}
_ => {},
}
}
}
@@ -156,11 +147,13 @@ impl<'a, T: Config> ContractModule<'a, T> {
for value_type in func_type.params().iter().chain(return_type) {
match value_type {
ValueType::F32 | ValueType::F64 =>
return Err("use of floating point type in function types is forbidden"),
_ => {}
return Err(
"use of floating point type in function types is forbidden",
),
_ => {},
}
}
}
},
}
}
}
@@ -173,12 +166,12 @@ impl<'a, T: Config> ContractModule<'a, T> {
let type_section = if let Some(type_section) = self.module.type_section() {
type_section
} else {
return Ok(());
return Ok(())
};
for Type::Function(func) in type_section.types() {
if func.params().len() > limit as usize {
return Err("Use of a function type with too many parameters.");
return Err("Use of a function type with too many parameters.")
}
}
@@ -187,26 +180,18 @@ impl<'a, T: Config> ContractModule<'a, T> {
fn inject_gas_metering(self) -> Result<Self, &'static str> {
let gas_rules = self.schedule.rules(&self.module);
let contract_module = pwasm_utils::inject_gas_counter(
self.module,
&gas_rules,
"seal0",
).map_err(|_| "gas instrumentation failed")?;
Ok(ContractModule {
module: contract_module,
schedule: self.schedule,
})
let contract_module = pwasm_utils::inject_gas_counter(self.module, &gas_rules, "seal0")
.map_err(|_| "gas instrumentation failed")?;
Ok(ContractModule { module: contract_module, schedule: self.schedule })
}
fn inject_stack_height_metering(self) -> Result<Self, &'static str> {
let contract_module =
pwasm_utils::stack_height
::inject_limiter(self.module, self.schedule.limits.stack_height)
.map_err(|_| "stack height instrumentation failed")?;
Ok(ContractModule {
module: contract_module,
schedule: self.schedule,
})
let contract_module = pwasm_utils::stack_height::inject_limiter(
self.module,
self.schedule.limits.stack_height,
)
.map_err(|_| "stack height instrumentation failed")?;
Ok(ContractModule { module: contract_module, schedule: self.schedule })
}
/// Check that the module has required exported functions. For now
@@ -223,14 +208,8 @@ impl<'a, T: Config> ContractModule<'a, T> {
let module = &self.module;
let types = module.type_section().map(|ts| ts.types()).unwrap_or(&[]);
let export_entries = module
.export_section()
.map(|is| is.entries())
.unwrap_or(&[]);
let func_entries = module
.function_section()
.map(|fs| fs.entries())
.unwrap_or(&[]);
let export_entries = module.export_section().map(|is| is.entries()).unwrap_or(&[]);
let func_entries = module.function_section().map(|fs| fs.entries()).unwrap_or(&[]);
// Function index space consists of imported function following by
// declared functions. Calculate the total number of imported functions so
@@ -240,11 +219,9 @@ impl<'a, T: Config> ContractModule<'a, T> {
.map(|is| is.entries())
.unwrap_or(&[])
.iter()
.filter(|entry| {
match *entry.external() {
External::Function(_) => true,
_ => false,
}
.filter(|entry| match *entry.external() {
External::Function(_) => true,
_ => false,
})
.count();
@@ -267,32 +244,32 @@ impl<'a, T: Config> ContractModule<'a, T> {
Some(fn_idx) => fn_idx,
None => {
// Underflow here means fn_idx points to imported function which we don't allow!
return Err("entry point points to an imported function");
}
return Err("entry point points to an imported function")
},
};
// Then check the signature.
// Both "call" and "deploy" has a () -> () function type.
// We still support () -> (i32) for backwards compatibility.
let func_ty_idx = func_entries.get(fn_idx as usize)
let func_ty_idx = func_entries
.get(fn_idx as usize)
.ok_or_else(|| "export refers to non-existent function")?
.type_ref();
let Type::Function(ref func_ty) = types
.get(func_ty_idx as usize)
.ok_or_else(|| "function has a non-existent type")?;
if !(
func_ty.params().is_empty() &&
(func_ty.results().is_empty() || func_ty.results() == [ValueType::I32])
) {
return Err("entry point has wrong signature");
if !(func_ty.params().is_empty() &&
(func_ty.results().is_empty() || func_ty.results() == [ValueType::I32]))
{
return Err("entry point has wrong signature")
}
}
if !deploy_found {
return Err("deploy function isn't exported");
return Err("deploy function isn't exported")
}
if !call_found {
return Err("call function isn't exported");
return Err("call function isn't exported")
}
Ok(())
@@ -306,16 +283,14 @@ impl<'a, T: Config> ContractModule<'a, T> {
/// their signatures.
/// - if there is a memory import, returns it's descriptor
/// `import_fn_banlist`: list of function names that are disallowed to be imported
fn scan_imports<C: ImportSatisfyCheck>(&self, import_fn_banlist: &[&[u8]])
-> Result<Option<&MemoryType>, &'static str>
{
fn scan_imports<C: ImportSatisfyCheck>(
&self,
import_fn_banlist: &[&[u8]],
) -> Result<Option<&MemoryType>, &'static str> {
let module = &self.module;
let types = module.type_section().map(|ts| ts.types()).unwrap_or(&[]);
let import_entries = module
.import_section()
.map(|is| is.entries())
.unwrap_or(&[]);
let import_entries = module.import_section().map(|is| is.entries()).unwrap_or(&[]);
let mut imported_mem_type = None;
@@ -326,7 +301,7 @@ impl<'a, T: Config> ContractModule<'a, T> {
&External::Function(ref type_idx) => type_idx,
&External::Memory(ref memory_type) => {
if import.module() != IMPORT_MODULE_MEMORY {
return Err("Invalid module for imported memory");
return Err("Invalid module for imported memory")
}
if import.field() != "memory" {
return Err("Memory import must have the field name 'memory'")
@@ -335,8 +310,8 @@ impl<'a, T: Config> ContractModule<'a, T> {
return Err("Multiple memory imports defined")
}
imported_mem_type = Some(memory_type);
continue;
}
continue
},
};
let Type::Function(ref func_ty) = types
@@ -346,48 +321,44 @@ impl<'a, T: Config> ContractModule<'a, T> {
if !T::ChainExtension::enabled() &&
import.field().as_bytes() == b"seal_call_chain_extension"
{
return Err("module uses chain extensions but chain extensions are disabled");
return Err("module uses chain extensions but chain extensions are disabled")
}
if import_fn_banlist.iter().any(|f| import.field().as_bytes() == *f)
|| !C::can_satisfy(
import.module().as_bytes(), import.field().as_bytes(), func_ty,
)
if import_fn_banlist.iter().any(|f| import.field().as_bytes() == *f) ||
!C::can_satisfy(import.module().as_bytes(), import.field().as_bytes(), func_ty)
{
return Err("module imports a non-existent function");
return Err("module imports a non-existent function")
}
}
Ok(imported_mem_type)
}
fn into_wasm_code(self) -> Result<Vec<u8>, &'static str> {
elements::serialize(self.module)
.map_err(|_| "error serializing instrumented module")
elements::serialize(self.module).map_err(|_| "error serializing instrumented module")
}
}
fn get_memory_limits<T: Config>(module: Option<&MemoryType>, schedule: &Schedule<T>)
-> Result<(u32, u32), &'static str>
{
fn get_memory_limits<T: Config>(
module: Option<&MemoryType>,
schedule: &Schedule<T>,
) -> Result<(u32, u32), &'static str> {
if let Some(memory_type) = module {
// Inspect the module to extract the initial and maximum page count.
let limits = memory_type.limits();
match (limits.initial(), limits.maximum()) {
(initial, Some(maximum)) if initial > maximum => {
(initial, Some(maximum)) if initial > maximum =>
return Err(
"Requested initial number of pages should not exceed the requested maximum",
);
}
(_, Some(maximum)) if maximum > schedule.limits.memory_pages => {
return Err("Maximum number of pages should not exceed the configured maximum.");
}
),
(_, Some(maximum)) if maximum > schedule.limits.memory_pages =>
return Err("Maximum number of pages should not exceed the configured maximum."),
(initial, Some(maximum)) => Ok((initial, maximum)),
(_, None) => {
// Maximum number of pages should be always declared.
// This isn't a hard requirement and can be treated as a maximum set
// to configured maximum.
return Err("Maximum number of pages should be always declared.");
}
return Err("Maximum number of pages should be always declared.")
},
}
} else {
// If none memory imported then just crate an empty placeholder.
@@ -411,10 +382,8 @@ fn check_and_instrument<C: ImportSatisfyCheck, T: Config>(
// We disallow importing `gas` function here since it is treated as implementation detail.
let disallowed_imports = [b"gas".as_ref()];
let memory_limits = get_memory_limits(
contract_module.scan_imports::<C>(&disallowed_imports)?,
schedule
)?;
let memory_limits =
get_memory_limits(contract_module.scan_imports::<C>(&disallowed_imports)?, schedule)?;
let code = contract_module
.inject_gas_metering()?
@@ -428,10 +397,8 @@ fn do_preparation<C: ImportSatisfyCheck, T: Config>(
original_code: Vec<u8>,
schedule: &Schedule<T>,
) -> Result<PrefabWasmModule<T>, &'static str> {
let (code, (initial, maximum)) = check_and_instrument::<C, T>(
original_code.as_ref(),
schedule,
)?;
let (code, (initial, maximum)) =
check_and_instrument::<C, T>(original_code.as_ref(), schedule)?;
Ok(PrefabWasmModule {
instruction_weights_version: schedule.instruction_weights.version,
initial,
@@ -483,8 +450,7 @@ pub fn reinstrument_contract<T: Config>(
/// in production code.
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking {
use super::*;
use super::elements::FunctionType;
use super::{elements::FunctionType, *};
impl ImportSatisfyCheck for () {
fn can_satisfy(_module: &[u8], _name: &[u8], _func_type: &FunctionType) -> bool {
@@ -493,9 +459,10 @@ pub mod benchmarking {
}
/// Prepare function that neither checks nor instruments the passed in code.
pub fn prepare_contract<T: Config>(original_code: Vec<u8>, schedule: &Schedule<T>)
-> Result<PrefabWasmModule<T>, &'static str>
{
pub fn prepare_contract<T: Config>(
original_code: Vec<u8>,
schedule: &Schedule<T>,
) -> Result<PrefabWasmModule<T>, &'static str> {
let contract_module = ContractModule::new(&original_code, schedule)?;
let memory_limits = get_memory_limits(contract_module.scan_imports::<()>(&[])?, schedule)?;
Ok(PrefabWasmModule {
@@ -566,7 +533,8 @@ mod tests {
};
}
prepare_test!(no_floats,
prepare_test!(
no_floats,
r#"
(module
(func (export "call")
@@ -585,7 +553,8 @@ mod tests {
mod functions {
use super::*;
prepare_test!(param_number_valid,
prepare_test!(
param_number_valid,
r#"
(module
(func (export "call"))
@@ -596,7 +565,8 @@ mod tests {
Ok(_)
);
prepare_test!(param_number_invalid,
prepare_test!(
param_number_invalid,
r#"
(module
(func (export "call"))
@@ -612,7 +582,8 @@ mod tests {
mod globals {
use super::*;
prepare_test!(global_number_valid,
prepare_test!(
global_number_valid,
r#"
(module
(global i64 (i64.const 0))
@@ -625,7 +596,8 @@ mod tests {
Ok(_)
);
prepare_test!(global_number_too_high,
prepare_test!(
global_number_too_high,
r#"
(module
(global i64 (i64.const 0))
@@ -643,7 +615,8 @@ mod tests {
mod memories {
use super::*;
prepare_test!(memory_with_one_page,
prepare_test!(
memory_with_one_page,
r#"
(module
(import "env" "memory" (memory 1 1))
@@ -655,7 +628,8 @@ mod tests {
Ok(_)
);
prepare_test!(internal_memory_declaration,
prepare_test!(
internal_memory_declaration,
r#"
(module
(memory 1 1)
@@ -667,7 +641,8 @@ mod tests {
Err("module declares internal memory")
);
prepare_test!(no_memory_import,
prepare_test!(
no_memory_import,
r#"
(module
;; no memory imported
@@ -678,7 +653,8 @@ mod tests {
Ok(_)
);
prepare_test!(initial_exceeds_maximum,
prepare_test!(
initial_exceeds_maximum,
r#"
(module
(import "env" "memory" (memory 16 1))
@@ -690,7 +666,8 @@ mod tests {
Err("Module is not valid")
);
prepare_test!(no_maximum,
prepare_test!(
no_maximum,
r#"
(module
(import "env" "memory" (memory 1))
@@ -702,7 +679,8 @@ mod tests {
Err("Maximum number of pages should be always declared.")
);
prepare_test!(requested_maximum_valid,
prepare_test!(
requested_maximum_valid,
r#"
(module
(import "env" "memory" (memory 1 16))
@@ -714,7 +692,8 @@ mod tests {
Ok(_)
);
prepare_test!(requested_maximum_exceeds_configured_maximum,
prepare_test!(
requested_maximum_exceeds_configured_maximum,
r#"
(module
(import "env" "memory" (memory 1 17))
@@ -726,7 +705,8 @@ mod tests {
Err("Maximum number of pages should not exceed the configured maximum.")
);
prepare_test!(field_name_not_memory,
prepare_test!(
field_name_not_memory,
r#"
(module
(import "env" "forgetit" (memory 1 1))
@@ -738,7 +718,8 @@ mod tests {
Err("Memory import must have the field name 'memory'")
);
prepare_test!(multiple_memory_imports,
prepare_test!(
multiple_memory_imports,
r#"
(module
(import "env" "memory" (memory 1 1))
@@ -751,7 +732,8 @@ mod tests {
Err("Module is not valid")
);
prepare_test!(table_import,
prepare_test!(
table_import,
r#"
(module
(import "seal0" "table" (table 1 anyfunc))
@@ -763,7 +745,8 @@ mod tests {
Err("Cannot import tables")
);
prepare_test!(global_import,
prepare_test!(
global_import,
r#"
(module
(global $g (import "seal0" "global") i32)
@@ -778,7 +761,8 @@ mod tests {
mod tables {
use super::*;
prepare_test!(no_tables,
prepare_test!(
no_tables,
r#"
(module
(func (export "call"))
@@ -788,7 +772,8 @@ mod tests {
Ok(_)
);
prepare_test!(table_valid_size,
prepare_test!(
table_valid_size,
r#"
(module
(table 3 funcref)
@@ -800,7 +785,8 @@ mod tests {
Ok(_)
);
prepare_test!(table_too_big,
prepare_test!(
table_too_big,
r#"
(module
(table 4 funcref)
@@ -811,7 +797,8 @@ mod tests {
Err("table exceeds maximum size allowed")
);
prepare_test!(br_table_valid_size,
prepare_test!(
br_table_valid_size,
r#"
(module
(func (export "call"))
@@ -825,7 +812,8 @@ mod tests {
Ok(_)
);
prepare_test!(br_table_too_big,
prepare_test!(
br_table_too_big,
r#"
(module
(func (export "call"))
@@ -842,7 +830,8 @@ mod tests {
mod imports {
use super::*;
prepare_test!(can_import_legit_function,
prepare_test!(
can_import_legit_function,
r#"
(module
(import "seal0" "nop" (func (param i64)))
@@ -856,7 +845,8 @@ mod tests {
// even though gas is defined the contract can't import it since
// it is an implementation defined.
prepare_test!(can_not_import_gas_function,
prepare_test!(
can_not_import_gas_function,
r#"
(module
(import "seal0" "gas" (func (param i32)))
@@ -869,7 +859,8 @@ mod tests {
);
// memory is in "env" and not in "seal0"
prepare_test!(memory_not_in_seal0,
prepare_test!(
memory_not_in_seal0,
r#"
(module
(import "seal0" "memory" (memory 1 1))
@@ -882,7 +873,8 @@ mod tests {
);
// memory is in "env" and not in some arbitrary module
prepare_test!(memory_not_in_arbitrary_module,
prepare_test!(
memory_not_in_arbitrary_module,
r#"
(module
(import "any_module" "memory" (memory 1 1))
@@ -894,7 +886,8 @@ mod tests {
Err("Invalid module for imported memory")
);
prepare_test!(function_in_other_module_works,
prepare_test!(
function_in_other_module_works,
r#"
(module
(import "seal1" "nop" (func (param i32)))
@@ -907,7 +900,8 @@ mod tests {
);
// wrong signature
prepare_test!(wrong_signature,
prepare_test!(
wrong_signature,
r#"
(module
(import "seal0" "gas" (func (param i64)))
@@ -919,7 +913,8 @@ mod tests {
Err("module imports a non-existent function")
);
prepare_test!(unknown_func_name,
prepare_test!(
unknown_func_name,
r#"
(module
(import "seal0" "unknown_func" (func))
@@ -935,7 +930,8 @@ mod tests {
mod entrypoints {
use super::*;
prepare_test!(it_works,
prepare_test!(
it_works,
r#"
(module
(func (export "call"))
@@ -945,7 +941,8 @@ mod tests {
Ok(_)
);
prepare_test!(omit_deploy,
prepare_test!(
omit_deploy,
r#"
(module
(func (export "call"))
@@ -954,7 +951,8 @@ mod tests {
Err("deploy function isn't exported")
);
prepare_test!(omit_call,
prepare_test!(
omit_call,
r#"
(module
(func (export "deploy"))
@@ -964,7 +962,8 @@ mod tests {
);
// Try to use imported function as an entry point.
prepare_test!(try_sneak_export_as_entrypoint,
prepare_test!(
try_sneak_export_as_entrypoint,
r#"
(module
(import "seal0" "panic" (func))
@@ -978,7 +977,8 @@ mod tests {
);
// Try to use imported function as an entry point.
prepare_test!(try_sneak_export_as_global,
prepare_test!(
try_sneak_export_as_global,
r#"
(module
(func (export "deploy"))
@@ -988,7 +988,8 @@ mod tests {
Err("expected a function")
);
prepare_test!(wrong_signature,
prepare_test!(
wrong_signature,
r#"
(module
(func (export "deploy"))
@@ -998,7 +999,8 @@ mod tests {
Err("entry point has wrong signature")
);
prepare_test!(unknown_exports,
prepare_test!(
unknown_exports,
r#"
(module
(func (export "call"))
@@ -1009,7 +1011,8 @@ mod tests {
Err("unknown export: expecting only deploy and call functions")
);
prepare_test!(global_float,
prepare_test!(
global_float,
r#"
(module
(global $x f32 (f32.const 0))
@@ -1020,7 +1023,8 @@ mod tests {
Err("use of floating point type in globals is forbidden")
);
prepare_test!(local_float,
prepare_test!(
local_float,
r#"
(module
(func $foo (local f32))
@@ -1031,7 +1035,8 @@ mod tests {
Err("use of floating point type in locals is forbidden")
);
prepare_test!(param_float,
prepare_test!(
param_float,
r#"
(module
(func $foo (param f32))
@@ -1042,7 +1047,8 @@ mod tests {
Err("use of floating point type in function types is forbidden")
);
prepare_test!(result_float,
prepare_test!(
result_float,
r#"
(module
(func $foo (result f32) (f32.const 0))
+86 -107
View File
@@ -18,25 +18,20 @@
//! Environment definition of the wasm smart-contract runtime.
use crate::{
Config, CodeHash, BalanceOf, Error,
exec::{Ext, StorageKey, TopicOf, ExecResult, ExecError},
gas::{Token, ChargedAmount},
wasm::env_def::ConvertibleToWasm,
exec::{ExecError, ExecResult, Ext, StorageKey, TopicOf},
gas::{ChargedAmount, Token},
schedule::HostFnWeights,
wasm::env_def::ConvertibleToWasm,
BalanceOf, CodeHash, Config, Error,
};
use bitflags::bitflags;
use pwasm_utils::parity_wasm::elements::ValueType;
use frame_support::{dispatch::DispatchError, ensure, weights::Weight};
use sp_std::prelude::*;
use codec::{Decode, DecodeAll, Encode, MaxEncodedLen};
use sp_core::{Bytes, crypto::UncheckedFrom};
use sp_io::hashing::{
keccak_256,
blake2_256,
blake2_128,
sha2_256,
};
use frame_support::{dispatch::DispatchError, ensure, weights::Weight};
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
use pwasm_utils::parity_wasm::elements::ValueType;
use sp_core::{crypto::UncheckedFrom, Bytes};
use sp_io::hashing::{blake2_128, blake2_256, keccak_256, sha2_256};
use sp_std::prelude::*;
/// Every error that can be returned to a contract when it calls any of the host functions.
///
@@ -178,7 +173,7 @@ pub enum RuntimeCosts {
/// Weight of calling `seal_random`. It includes the weight for copying the subject.
Random,
/// Weight of calling `seal_deposit_event` with the given number of topics and event size.
DepositEvent{num_topic: u32, len: u32},
DepositEvent { num_topic: u32, len: u32 },
/// Weight of calling `seal_debug_message`.
#[cfg(feature = "unstable-interface")]
DebugMessage,
@@ -203,7 +198,7 @@ pub enum RuntimeCosts {
/// 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},
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.
@@ -228,7 +223,7 @@ impl RuntimeCosts {
fn token<T>(&self, s: &HostFnWeights<T>) -> RuntimeToken
where
T: Config,
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
use self::RuntimeCosts::*;
let weight = match *self {
@@ -246,40 +241,44 @@ impl RuntimeCosts {
WeightToFee => s.weight_to_fee,
InputBase => s.input,
InputCopyOut(len) => s.input_per_byte.saturating_mul(len.into()),
Return(len) => s.r#return
.saturating_add(s.return_per_byte.saturating_mul(len.into())),
Return(len) => s.r#return.saturating_add(s.return_per_byte.saturating_mul(len.into())),
Terminate => s.terminate,
RestoreTo(delta) => s.restore_to
.saturating_add(s.restore_to_per_delta.saturating_mul(delta.into())),
RestoreTo(delta) =>
s.restore_to.saturating_add(s.restore_to_per_delta.saturating_mul(delta.into())),
Random => s.random,
DepositEvent{num_topic, len} => s.deposit_event
DepositEvent { num_topic, len } => s
.deposit_event
.saturating_add(s.deposit_event_per_topic.saturating_mul(num_topic.into()))
.saturating_add(s.deposit_event_per_byte.saturating_mul(len.into())),
#[cfg(feature = "unstable-interface")]
DebugMessage => s.debug_message,
SetRentAllowance => s.set_rent_allowance,
SetStorage(len) => s.set_storage
.saturating_add(s.set_storage_per_byte.saturating_mul(len.into())),
SetStorage(len) =>
s.set_storage.saturating_add(s.set_storage_per_byte.saturating_mul(len.into())),
ClearStorage => s.clear_storage,
GetStorageBase => s.get_storage,
GetStorageCopyOut(len) => s.get_storage_per_byte.saturating_mul(len.into()),
Transfer => s.transfer,
CallBase(len) => s.call
.saturating_add(s.call_per_input_byte.saturating_mul(len.into())),
CallBase(len) =>
s.call.saturating_add(s.call_per_input_byte.saturating_mul(len.into())),
CallSurchargeTransfer => s.call_transfer_surcharge,
CallCopyOut(len) => s.call_per_output_byte.saturating_mul(len.into()),
InstantiateBase{input_data_len, salt_len} => s.instantiate
InstantiateBase { input_data_len, salt_len } => s
.instantiate
.saturating_add(s.instantiate_per_input_byte.saturating_mul(input_data_len.into()))
.saturating_add(s.instantiate_per_salt_byte.saturating_mul(salt_len.into())),
InstantiateCopyOut(len) => s.instantiate_per_output_byte
.saturating_mul(len.into()),
HashSha256(len) => s.hash_sha2_256
InstantiateCopyOut(len) => s.instantiate_per_output_byte.saturating_mul(len.into()),
HashSha256(len) => s
.hash_sha2_256
.saturating_add(s.hash_sha2_256_per_byte.saturating_mul(len.into())),
HashKeccak256(len) => s.hash_keccak_256
HashKeccak256(len) => s
.hash_keccak_256
.saturating_add(s.hash_keccak_256_per_byte.saturating_mul(len.into())),
HashBlake256(len) => s.hash_blake2_256
HashBlake256(len) => s
.hash_blake2_256
.saturating_add(s.hash_blake2_256_per_byte.saturating_mul(len.into())),
HashBlake128(len) => s.hash_blake2_128
HashBlake128(len) => s
.hash_blake2_128
.saturating_add(s.hash_blake2_128_per_byte.saturating_mul(len.into())),
ChainExtension(amount) => amount,
#[cfg(feature = "unstable-interface")]
@@ -306,7 +305,7 @@ struct RuntimeToken {
impl<T> Token<T> for RuntimeToken
where
T: Config,
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>
T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,
{
fn weight(&self) -> Weight {
self.weight
@@ -373,19 +372,10 @@ impl<'a, E> Runtime<'a, E>
where
E: Ext + 'a,
<E::T as frame_system::Config>::AccountId:
UncheckedFrom<<E::T as frame_system::Config>::Hash> + AsRef<[u8]>
UncheckedFrom<<E::T as frame_system::Config>::Hash> + AsRef<[u8]>,
{
pub fn new(
ext: &'a mut E,
input_data: Vec<u8>,
memory: sp_sandbox::Memory,
) -> Self {
Runtime {
ext,
input_data: Some(input_data),
memory,
trap_reason: None,
}
pub fn new(ext: &'a mut E, input_data: Vec<u8>, memory: sp_sandbox::Memory) -> Self {
Runtime { ext, input_data: Some(input_data), memory, trap_reason: None }
}
/// Converts the sandbox result and the runtime state into the execution outcome.
@@ -401,27 +391,15 @@ where
if let Some(trap_reason) = self.trap_reason {
return match trap_reason {
// The trap was the result of the execution `return` host function.
TrapReason::Return(ReturnData{ flags, data }) => {
let flags = ReturnFlags::from_bits(flags).ok_or_else(||
"used reserved bit in return flags"
)?;
Ok(ExecReturnValue {
flags,
data: Bytes(data),
})
},
TrapReason::Termination => {
Ok(ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes(Vec::new()),
})
},
TrapReason::Restoration => {
Ok(ExecReturnValue {
flags: ReturnFlags::empty(),
data: Bytes(Vec::new()),
})
TrapReason::Return(ReturnData { flags, data }) => {
let flags = ReturnFlags::from_bits(flags)
.ok_or_else(|| "used reserved bit in return flags")?;
Ok(ExecReturnValue { flags, data: Bytes(data) })
},
TrapReason::Termination =>
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }),
TrapReason::Restoration =>
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }),
TrapReason::SupervisorError(error) => Err(error)?,
}
}
@@ -429,9 +407,7 @@ where
// Check the exact type of the error.
match sandbox_result {
// No traps were generated. Proceed normally.
Ok(_) => {
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) })
}
Ok(_) => Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }),
// `Error::Module` is returned only if instantiation or linking failed (i.e.
// wasm binary tried to import a function that is not provided by the host).
// This shouldn't happen because validation process ought to reject such binaries.
@@ -441,7 +417,7 @@ where
Err(sp_sandbox::Error::Module) => Err("validation error")?,
// Any other kind of a trap should result in a failure.
Err(sp_sandbox::Error::Execution) | Err(sp_sandbox::Error::OutOfBounds) =>
Err(Error::<E::T>::ContractTrapped)?
Err(Error::<E::T>::ContractTrapped)?,
}
}
@@ -484,12 +460,11 @@ where
/// Returns `Err` if one of the following conditions occurs:
///
/// - requested buffer is not within the bounds of the sandbox memory.
pub fn read_sandbox_memory(&self, ptr: u32, len: u32)
-> Result<Vec<u8>, DispatchError>
{
pub fn read_sandbox_memory(&self, ptr: u32, len: u32) -> Result<Vec<u8>, DispatchError> {
ensure!(len <= self.ext.schedule().limits.max_memory_size(), Error::<E::T>::OutOfBounds);
let mut buf = vec![0u8; len as usize];
self.memory.get(ptr, buf.as_mut_slice())
self.memory
.get(ptr, buf.as_mut_slice())
.map_err(|_| Error::<E::T>::OutOfBounds)?;
Ok(buf)
}
@@ -499,9 +474,11 @@ where
/// Returns `Err` if one of the following conditions occurs:
///
/// - requested buffer is not within the bounds of the sandbox memory.
pub fn read_sandbox_memory_into_buf(&self, ptr: u32, buf: &mut [u8])
-> Result<(), DispatchError>
{
pub fn read_sandbox_memory_into_buf(
&self,
ptr: u32,
buf: &mut [u8],
) -> Result<(), DispatchError> {
self.memory.get(ptr, buf).map_err(|_| Error::<E::T>::OutOfBounds.into())
}
@@ -511,9 +488,10 @@ where
///
/// The weight of reading a fixed value is included in the overall weight of any
/// contract callable function.
pub fn read_sandbox_memory_as<D: Decode + MaxEncodedLen>(&self, ptr: u32)
-> Result<D, DispatchError>
{
pub fn read_sandbox_memory_as<D: Decode + MaxEncodedLen>(
&self,
ptr: u32,
) -> Result<D, DispatchError> {
let buf = self.read_sandbox_memory(ptr, D::max_encoded_len() as u32)?;
let decoded = D::decode_all(&mut &buf[..])
.map_err(|_| DispatchError::from(Error::<E::T>::DecodingFailed))?;
@@ -531,9 +509,11 @@ where
///
/// There must be an extra benchmark for determining the influence of `len` with
/// regard to the overall weight.
pub fn read_sandbox_memory_as_unbounded<D: Decode>(&self, ptr: u32, len: u32)
-> Result<D, DispatchError>
{
pub fn read_sandbox_memory_as_unbounded<D: Decode>(
&self,
ptr: u32,
len: u32,
) -> Result<D, DispatchError> {
let buf = self.read_sandbox_memory(ptr, len)?;
let decoded = D::decode_all(&mut &buf[..])
.map_err(|_| DispatchError::from(Error::<E::T>::DecodingFailed))?;
@@ -566,10 +546,9 @@ where
buf: &[u8],
allow_skip: bool,
create_token: impl FnOnce(u32) -> Option<RuntimeCosts>,
) -> Result<(), DispatchError>
{
) -> Result<(), DispatchError> {
if allow_skip && out_ptr == u32::MAX {
return Ok(());
return Ok(())
}
let buf_len = buf.len() as u32;
@@ -583,10 +562,10 @@ where
self.charge_gas(costs)?;
}
self.memory.set(out_ptr, buf).and_then(|_| {
self.memory.set(out_len_ptr, &buf_len.encode())
})
.map_err(|_| Error::<E::T>::OutOfBounds)?;
self.memory
.set(out_ptr, buf)
.and_then(|_| self.memory.set(out_len_ptr, &buf_len.encode()))
.map_err(|_| Error::<E::T>::OutOfBounds)?;
Ok(())
}
@@ -650,7 +629,7 @@ where
x if x == not_funded => Ok(NewContractNotFunded),
x if x == no_code => Ok(CodeNotFound),
x if (x == not_found || x == is_tombstone || x == rent_not_paid) => Ok(NotCallable),
err => Err(err)
err => Err(err),
}
}
@@ -665,7 +644,7 @@ where
match (error, origin) {
(_, Callee) => Ok(ReturnCode::CalleeTrapped),
(err, _) => Self::err_into_return_code(err)
(err, _) => Self::err_into_return_code(err),
}
}
@@ -678,9 +657,8 @@ where
input_data_ptr: u32,
input_data_len: u32,
output_ptr: u32,
output_len_ptr: u32
) -> Result<ReturnCode, TrapReason>
{
output_len_ptr: u32,
) -> Result<ReturnCode, TrapReason> {
self.charge_gas(RuntimeCosts::CallBase(input_data_len))?;
let callee: <<E as Ext>::T as frame_system::Config>::AccountId =
self.read_sandbox_memory_as(callee_ptr)?;
@@ -696,9 +674,8 @@ where
self.charge_gas(RuntimeCosts::CallSurchargeTransfer)?;
}
let ext = &mut self.ext;
let call_outcome = ext.call(
gas, callee, value, input_data, flags.contains(CallFlags::ALLOW_REENTRY),
);
let call_outcome =
ext.call(gas, callee, value, input_data, flags.contains(CallFlags::ALLOW_REENTRY));
// `TAIL_CALL` only matters on an `OK` result. Otherwise the call stack comes to
// a halt anyways without anymore code being executed.
@@ -707,7 +684,7 @@ where
return Err(TrapReason::Return(ReturnData {
flags: return_value.flags.bits(),
data: return_value.data.0,
}));
}))
}
}
@@ -731,10 +708,9 @@ where
output_ptr: u32,
output_len_ptr: u32,
salt_ptr: u32,
salt_len: u32
) -> Result<ReturnCode, TrapReason>
{
self.charge_gas(RuntimeCosts::InstantiateBase {input_data_len, salt_len})?;
salt_len: u32,
) -> Result<ReturnCode, TrapReason> {
self.charge_gas(RuntimeCosts::InstantiateBase { input_data_len, salt_len })?;
let code_hash: CodeHash<<E as Ext>::T> = self.read_sandbox_memory_as(code_hash_ptr)?;
let value: BalanceOf<<E as Ext>::T> = self.read_sandbox_memory_as(value_ptr)?;
let input_data = self.read_sandbox_memory(input_data_ptr, input_data_len)?;
@@ -743,7 +719,11 @@ where
if let Ok((address, output)) = &instantiate_outcome {
if !output.flags.contains(ReturnFlags::REVERT) {
self.write_sandbox_output(
address_ptr, address_len_ptr, &address.encode(), true, already_charged,
address_ptr,
address_len_ptr,
&address.encode(),
true,
already_charged,
)?;
}
self.write_sandbox_output(output_ptr, output_len_ptr, &output.data, true, |len| {
@@ -767,13 +747,12 @@ where
code_hash_ptr: u32,
rent_allowance_ptr: u32,
delta_ptr: u32,
delta_count: u32
delta_count: u32,
) -> Result<(), TrapReason> {
self.charge_gas(RuntimeCosts::RestoreTo(delta_count))?;
let dest: <<E as Ext>::T as frame_system::Config>::AccountId =
self.read_sandbox_memory_as(dest_ptr)?;
let code_hash: CodeHash<<E as Ext>::T> =
self.read_sandbox_memory_as(code_hash_ptr)?;
let code_hash: CodeHash<<E as Ext>::T> = self.read_sandbox_memory_as(code_hash_ptr)?;
let rent_allowance: BalanceOf<<E as Ext>::T> =
self.read_sandbox_memory_as(rent_allowance_ptr)?;
let delta = {