mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 19:21:13 +00:00
contracts: Remove wat support from test fixtures (#3588)
In order to prepare for PolkaVM support I removed the wat support from our test fixture crate. - Removed redundant tests (invalid module checks are already inside the prepare module where they belong - Converted the gas_sync tests to Rust - Moved the start function test to the `wasm` module
This commit is contained in:
committed by
GitHub
parent
117a9433da
commit
4ae7398818
Generated
-1
@@ -9634,7 +9634,6 @@ dependencies = [
|
||||
"tempfile",
|
||||
"toml 0.8.8",
|
||||
"twox-hash",
|
||||
"wat",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -11,7 +11,6 @@ description = "Fixtures for testing contracts pallet."
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
wat = "1"
|
||||
frame-system = { path = "../../system" }
|
||||
sp-runtime = { path = "../../../primitives/runtime" }
|
||||
anyhow = "1.0.0"
|
||||
|
||||
+15
-2
@@ -14,12 +14,25 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//! Valid module but missing the call function
|
||||
|
||||
//! This fixture calls caller_is_origin `n` times.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate common;
|
||||
use common::input;
|
||||
use uapi::{HostFn, HostFnImpl as api};
|
||||
|
||||
#[no_mangle]
|
||||
#[polkavm_derive::polkavm_export]
|
||||
pub extern "C" fn deploy() {}
|
||||
|
||||
#[no_mangle]
|
||||
#[polkavm_derive::polkavm_export]
|
||||
pub extern "C" fn call() {
|
||||
input!(n: u32, );
|
||||
|
||||
for _ in 0..n {
|
||||
let _ = api::caller_is_origin();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
;; A valid contract which does nothing at all
|
||||
(module
|
||||
(func (export "deploy"))
|
||||
(func (export "call"))
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
;; An invalid module
|
||||
(module
|
||||
(func (export "deploy"))
|
||||
(func (export "call")
|
||||
;; imbalanced stack
|
||||
(i32.const 7)
|
||||
)
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
(module
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(start $start)
|
||||
(func $start
|
||||
(loop $inf (br $inf)) ;; just run out of gas
|
||||
(unreachable)
|
||||
)
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
@@ -1,14 +0,0 @@
|
||||
;; Everything prepared for the host function call, but no call is performed.
|
||||
(module
|
||||
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
;; [0, 8) buffer to write input
|
||||
|
||||
;; [8, 12) size of the input buffer
|
||||
(data (i32.const 8) "\04")
|
||||
|
||||
(func (export "call"))
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
@@ -1,22 +0,0 @@
|
||||
;; Stores a value of the passed size. The host function is called once.
|
||||
(module
|
||||
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
;; [0, 8) buffer to write input
|
||||
|
||||
;; [8, 12) size of the input buffer
|
||||
(data (i32.const 8) "\04")
|
||||
|
||||
(func (export "call")
|
||||
;; instructions to consume engine fuel
|
||||
(drop
|
||||
(i32.const 42)
|
||||
)
|
||||
|
||||
(call $seal_input (i32.const 0) (i32.const 8))
|
||||
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
;; Stores a value of the passed size. The host function is called twice.
|
||||
(module
|
||||
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
|
||||
(import "env" "memory" (memory 1 1))
|
||||
|
||||
;; [0, 8) buffer to write input
|
||||
|
||||
;; [8, 12) size of the input buffer
|
||||
(data (i32.const 8) "\04")
|
||||
|
||||
(func (export "call")
|
||||
;; instructions to consume engine fuel
|
||||
(drop
|
||||
(i32.const 42)
|
||||
)
|
||||
|
||||
(call $seal_input (i32.const 0) (i32.const 8))
|
||||
|
||||
;; instructions to consume engine fuel
|
||||
(drop
|
||||
(i32.const 42)
|
||||
)
|
||||
|
||||
(call $seal_input (i32.const 0) (i32.const 8))
|
||||
)
|
||||
|
||||
(func (export "deploy"))
|
||||
)
|
||||
@@ -16,34 +16,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use sp_runtime::traits::Hash;
|
||||
use std::{env::var, fs, path::PathBuf};
|
||||
|
||||
fn wat_root_dir() -> PathBuf {
|
||||
match (var("CARGO_MANIFEST_DIR"), var("CARGO_PKG_NAME")) {
|
||||
// When `CARGO_MANIFEST_DIR` is not set, Rust resolves relative paths from the root folder
|
||||
(Err(_), _) => "substrate/frame/contracts/fixtures/data".into(),
|
||||
(Ok(path), Ok(s)) if s == "pallet-contracts" => PathBuf::from(path).join("fixtures/data"),
|
||||
(Ok(path), Ok(s)) if s == "pallet-contracts-mock-network" =>
|
||||
PathBuf::from(path).parent().unwrap().join("fixtures/data"),
|
||||
(Ok(_), pkg_name) => panic!("Failed to resolve fixture dir for tests from {pkg_name:?}."),
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a given wasm module represented by a .wat file and returns a wasm binary contents along
|
||||
/// with it's hash.
|
||||
///
|
||||
/// The fixture files are located under the `fixtures/` directory.
|
||||
fn legacy_compile_module<T>(
|
||||
fixture_name: &str,
|
||||
) -> anyhow::Result<(Vec<u8>, <T::Hashing as Hash>::Output)>
|
||||
where
|
||||
T: frame_system::Config,
|
||||
{
|
||||
let fixture_path = wat_root_dir().join(format!("{fixture_name}.wat"));
|
||||
let wasm_binary = wat::parse_file(fixture_path)?;
|
||||
let code_hash = T::Hashing::hash(&wasm_binary);
|
||||
Ok((wasm_binary, code_hash))
|
||||
}
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
/// Load a given wasm module and returns a wasm binary contents along with it's hash.
|
||||
/// Use the legacy compile_module as fallback, if the rust fixture does not exist yet.
|
||||
@@ -53,15 +26,11 @@ pub fn compile_module<T>(
|
||||
where
|
||||
T: frame_system::Config,
|
||||
{
|
||||
let out_dir: std::path::PathBuf = env!("OUT_DIR").into();
|
||||
let out_dir: PathBuf = env!("OUT_DIR").into();
|
||||
let fixture_path = out_dir.join(format!("{fixture_name}.wasm"));
|
||||
match fs::read(fixture_path) {
|
||||
Ok(wasm_binary) => {
|
||||
let code_hash = T::Hashing::hash(&wasm_binary);
|
||||
Ok((wasm_binary, code_hash))
|
||||
},
|
||||
Err(_) => legacy_compile_module::<T>(fixture_name),
|
||||
}
|
||||
let binary = fs::read(fixture_path)?;
|
||||
let code_hash = T::Hashing::hash(&binary);
|
||||
Ok((binary, code_hash))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -852,27 +852,6 @@ fn deposit_event_max_value_limit() {
|
||||
});
|
||||
}
|
||||
|
||||
// Fail out of fuel (ref_time weight) inside the start function.
|
||||
#[test]
|
||||
fn run_out_of_fuel_start_fun() {
|
||||
let (wasm, _code_hash) = compile_module::<Test>("run_out_of_gas_start_fn").unwrap();
|
||||
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
|
||||
let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000);
|
||||
assert_err_ignore_postinfo!(
|
||||
Contracts::instantiate_with_code(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
0,
|
||||
Weight::from_parts(1_000_000_000_000, u64::MAX),
|
||||
None,
|
||||
wasm,
|
||||
vec![],
|
||||
vec![],
|
||||
),
|
||||
Error::<Test>::OutOfGas,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Fail out of fuel (ref_time weight) in the engine.
|
||||
#[test]
|
||||
fn run_out_of_fuel_engine() {
|
||||
@@ -956,50 +935,15 @@ fn run_out_of_fuel_host() {
|
||||
|
||||
#[test]
|
||||
fn gas_syncs_work() {
|
||||
let (wasm0, _code_hash) = compile_module::<Test>("seal_input_noop").unwrap();
|
||||
let (wasm1, _code_hash) = compile_module::<Test>("seal_input_once").unwrap();
|
||||
let (wasm2, _code_hash) = compile_module::<Test>("seal_input_twice").unwrap();
|
||||
let (code, _code_hash) = compile_module::<Test>("caller_is_origin_n").unwrap();
|
||||
ExtBuilder::default().existential_deposit(200).build().execute_with(|| {
|
||||
let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000);
|
||||
// Instantiate noop contract.
|
||||
let addr0 = Contracts::bare_instantiate(
|
||||
let addr = Contracts::bare_instantiate(
|
||||
ALICE,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
Code::Upload(wasm0),
|
||||
vec![],
|
||||
vec![],
|
||||
DebugInfo::Skip,
|
||||
CollectEvents::Skip,
|
||||
)
|
||||
.result
|
||||
.unwrap()
|
||||
.account_id;
|
||||
|
||||
// Instantiate 1st contract.
|
||||
let addr1 = Contracts::bare_instantiate(
|
||||
ALICE,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
Code::Upload(wasm1),
|
||||
vec![],
|
||||
vec![],
|
||||
DebugInfo::Skip,
|
||||
CollectEvents::Skip,
|
||||
)
|
||||
.result
|
||||
.unwrap()
|
||||
.account_id;
|
||||
|
||||
// Instantiate 2nd contract.
|
||||
let addr2 = Contracts::bare_instantiate(
|
||||
ALICE,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
Code::Upload(wasm2),
|
||||
Code::Upload(code),
|
||||
vec![],
|
||||
vec![],
|
||||
DebugInfo::Skip,
|
||||
@@ -1011,11 +955,11 @@ fn gas_syncs_work() {
|
||||
|
||||
let result = Contracts::bare_call(
|
||||
ALICE,
|
||||
addr0,
|
||||
addr.clone(),
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
1u8.to_le_bytes().to_vec(),
|
||||
0u32.encode(),
|
||||
DebugInfo::Skip,
|
||||
CollectEvents::Skip,
|
||||
Determinism::Enforced,
|
||||
@@ -1025,27 +969,28 @@ fn gas_syncs_work() {
|
||||
|
||||
let result = Contracts::bare_call(
|
||||
ALICE,
|
||||
addr1,
|
||||
addr.clone(),
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
1u8.to_le_bytes().to_vec(),
|
||||
1u32.encode(),
|
||||
DebugInfo::Skip,
|
||||
CollectEvents::Skip,
|
||||
Determinism::Enforced,
|
||||
);
|
||||
assert_ok!(result.result);
|
||||
let gas_consumed_once = result.gas_consumed.ref_time();
|
||||
let host_consumed_once = <Test as Config>::Schedule::get().host_fn_weights.input.ref_time();
|
||||
let host_consumed_once =
|
||||
<Test as Config>::Schedule::get().host_fn_weights.caller_is_origin.ref_time();
|
||||
let engine_consumed_once = gas_consumed_once - host_consumed_once - engine_consumed_noop;
|
||||
|
||||
let result = Contracts::bare_call(
|
||||
ALICE,
|
||||
addr2,
|
||||
addr,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
1u8.to_le_bytes().to_vec(),
|
||||
2u32.encode(),
|
||||
DebugInfo::Skip,
|
||||
CollectEvents::Skip,
|
||||
Determinism::Enforced,
|
||||
@@ -4453,96 +4398,6 @@ fn contract_reverted() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn code_rejected_error_works() {
|
||||
ExtBuilder::default().existential_deposit(200).build().execute_with(|| {
|
||||
let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000);
|
||||
|
||||
let (wasm, _) = compile_module::<Test>("invalid_module").unwrap();
|
||||
assert_noop!(
|
||||
Contracts::upload_code(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
wasm.clone(),
|
||||
None,
|
||||
Determinism::Enforced
|
||||
),
|
||||
<Error<Test>>::CodeRejected,
|
||||
);
|
||||
let result = Contracts::bare_instantiate(
|
||||
ALICE,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
Code::Upload(wasm),
|
||||
vec![],
|
||||
vec![],
|
||||
DebugInfo::UnsafeDebug,
|
||||
CollectEvents::Skip,
|
||||
);
|
||||
assert_err!(result.result, <Error<Test>>::CodeRejected);
|
||||
assert_eq!(
|
||||
std::str::from_utf8(&result.debug_message).unwrap(),
|
||||
"Can't load the module into wasmi!"
|
||||
);
|
||||
|
||||
let (wasm, _) = compile_module::<Test>("invalid_contract_no_call").unwrap();
|
||||
assert_noop!(
|
||||
Contracts::upload_code(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
wasm.clone(),
|
||||
None,
|
||||
Determinism::Enforced
|
||||
),
|
||||
<Error<Test>>::CodeRejected,
|
||||
);
|
||||
|
||||
let result = Contracts::bare_instantiate(
|
||||
ALICE,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
Code::Upload(wasm),
|
||||
vec![],
|
||||
vec![],
|
||||
DebugInfo::UnsafeDebug,
|
||||
CollectEvents::Skip,
|
||||
);
|
||||
assert_err!(result.result, <Error<Test>>::CodeRejected);
|
||||
assert_eq!(
|
||||
std::str::from_utf8(&result.debug_message).unwrap(),
|
||||
"call function isn't exported"
|
||||
);
|
||||
|
||||
let (wasm, _) = compile_module::<Test>("invalid_contract_no_memory").unwrap();
|
||||
assert_noop!(
|
||||
Contracts::upload_code(
|
||||
RuntimeOrigin::signed(ALICE),
|
||||
wasm.clone(),
|
||||
None,
|
||||
Determinism::Enforced
|
||||
),
|
||||
<Error<Test>>::CodeRejected,
|
||||
);
|
||||
|
||||
let result = Contracts::bare_instantiate(
|
||||
ALICE,
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
None,
|
||||
Code::Upload(wasm),
|
||||
vec![],
|
||||
vec![],
|
||||
DebugInfo::UnsafeDebug,
|
||||
CollectEvents::Skip,
|
||||
);
|
||||
assert_err!(result.result, <Error<Test>>::CodeRejected);
|
||||
assert_eq!(
|
||||
std::str::from_utf8(&result.debug_message).unwrap(),
|
||||
"No memory import found in the module"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_code_hash() {
|
||||
let (wasm, code_hash) = compile_module::<Test>("set_code_hash").unwrap();
|
||||
|
||||
@@ -3442,4 +3442,22 @@ mod tests {
|
||||
runtime.read_sandbox_memory_as(&memory, 0u32).unwrap();
|
||||
assert_eq!(decoded.into_inner(), data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_out_of_gas_in_start_fn() {
|
||||
const CODE: &str = r#"
|
||||
(module
|
||||
(import "env" "memory" (memory 1 1))
|
||||
(start $start)
|
||||
(func $start
|
||||
(loop $inf (br $inf)) ;; just run out of gas
|
||||
(unreachable)
|
||||
)
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
let mut mock_ext = MockExt::default();
|
||||
assert_err!(execute(&CODE, vec![], &mut mock_ext), <Error<Test>>::OutOfGas);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user