diff --git a/Cargo.lock b/Cargo.lock
index eafbb47adb3..33332f6484a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2001,11 +2001,14 @@ dependencies = [
name = "gear-common"
version = "0.1.0"
dependencies = [
+ "frame-benchmarking",
"frame-support",
+ "frame-system",
"gear-core",
"gear-runtime-interface",
"log",
"parity-scale-codec",
+ "parity-wasm 0.42.2",
"primitive-types",
"scale-info",
"sp-arithmetic",
@@ -2125,6 +2128,7 @@ dependencies = [
"pallet-gas",
"pallet-gear",
"pallet-gear-debug",
+ "pallet-gear-program",
"pallet-gear-rpc-runtime-api",
"pallet-grandpa",
"pallet-randomness-collective-flip",
@@ -4358,6 +4362,7 @@ dependencies = [
"pallet-authorship",
"pallet-balances",
"pallet-gas",
+ "pallet-gear-program",
"pallet-timestamp",
"parity-scale-codec",
"parity-wasm 0.42.2",
@@ -4374,6 +4379,7 @@ dependencies = [
"tests-exit-init",
"tests-init-wait",
"tests-program-factory",
+ "tests-proxy",
"wabt",
]
@@ -4394,6 +4400,7 @@ dependencies = [
"pallet-balances",
"pallet-gas",
"pallet-gear",
+ "pallet-gear-program",
"pallet-timestamp",
"parity-scale-codec",
"parity-wasm 0.42.2",
@@ -4407,6 +4414,27 @@ dependencies = [
"wabt",
]
+[[package]]
+name = "pallet-gear-program"
+version = "2.0.0"
+dependencies = [
+ "env_logger",
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "gear-common",
+ "gear-core",
+ "log",
+ "pallet-balances",
+ "parity-scale-codec",
+ "primitive-types",
+ "scale-info",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
[[package]]
name = "pallet-gear-rpc"
version = "2.0.0"
@@ -4586,6 +4614,7 @@ dependencies = [
"pallet-balances",
"pallet-gas",
"pallet-gear",
+ "pallet-gear-program",
"pallet-timestamp",
"parity-scale-codec",
"parity-wasm 0.42.2",
@@ -7716,6 +7745,16 @@ dependencies = [
"tests-common",
]
+[[package]]
+name = "tests-proxy"
+version = "0.1.0"
+dependencies = [
+ "gear-wasm-builder",
+ "gstd",
+ "parity-scale-codec",
+ "scale-info",
+]
+
[[package]]
name = "tests-wait-wake"
version = "0.1.0"
diff --git a/common/Cargo.toml b/common/Cargo.toml
index d53b25393f1..50d96f12edb 100644
--- a/common/Cargo.toml
+++ b/common/Cargo.toml
@@ -22,7 +22,10 @@ sp-runtime = { version = "5.0.0", git = "https://github.com/gear-tech/substrate.
sp-std = { version = "4.0.0", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
sp-arithmetic = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
frame-support = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+frame-system = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false, optional = true }
+frame-benchmarking = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false, optional = true }
gear-runtime-interface = { path = "../runtime-interface", default-features = false }
+parity-wasm = { version = "0.42.2", default-features = false, optional = true }
[features]
default = ["std"]
@@ -38,3 +41,9 @@ std = [
"primitive-types/std",
"gear-runtime-interface/std",
]
+runtime-benchmarks = [
+ "frame-benchmarking",
+ "frame-system/runtime-benchmarks",
+ "frame-support/runtime-benchmarks",
+ "parity-wasm",
+]
diff --git a/common/src/benchmarking.rs b/common/src/benchmarking.rs
new file mode 100644
index 00000000000..306ae9328d5
--- /dev/null
+++ b/common/src/benchmarking.rs
@@ -0,0 +1,147 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use super::*;
+
+use parity_wasm::elements::*;
+use sp_io::hashing::blake2_256;
+use sp_std::borrow::ToOwned;
+
+pub fn account(name: &'static str, index: u32, seed: u32) -> AccountId {
+ let entropy = (name, index, seed).using_encoded(blake2_256);
+ AccountId::from_origin(H256::from_slice(&entropy[..]))
+}
+
+// A wasm module that allocates `$num_pages` of memory in `init` function.
+// In text format would look something like
+// (module
+// (type (func))
+// (import "env" "memory" (memory $num_pages))
+// (func (type 0))
+// (export "init" (func 0)))
+pub fn create_module(num_pages: u32) -> parity_wasm::elements::Module {
+ parity_wasm::elements::Module::new(vec![
+ Section::Type(TypeSection::with_types(vec![Type::Function(
+ FunctionType::new(vec![], vec![]),
+ )])),
+ Section::Import(ImportSection::with_entries(vec![ImportEntry::new(
+ "env".into(),
+ "memory".into(),
+ External::Memory(MemoryType::new(num_pages, None)),
+ )])),
+ Section::Function(FunctionSection::with_entries(vec![Func::new(0)])),
+ Section::Export(ExportSection::with_entries(vec![ExportEntry::new(
+ "init".into(),
+ Internal::Function(0),
+ )])),
+ Section::Code(CodeSection::with_bodies(vec![FuncBody::new(
+ vec![],
+ Instructions::new(vec![Instruction::End]),
+ )])),
+ ])
+}
+
+pub fn generate_wasm(num_pages: u32) -> Result, &'static str> {
+ let module = create_module(num_pages);
+ let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
+
+ Ok(code)
+}
+
+// A wasm module that allocates `$num_pages` in `handle` function:
+// (module
+// (import "env" "memory" (memory 1))
+// (import "env" "alloc" (func $alloc (param i32) (result i32)))
+// (export "init" (func $init))
+// (export "handle" (func $handle))
+// (func $init)
+// (func $handle
+// (local $result i32)
+// (local.set $result (call $alloc (i32.const $num_pages)))
+// )
+// )
+pub fn generate_wasm2(num_pages: i32) -> Result, &'static str> {
+ let module = parity_wasm::elements::Module::new(vec![
+ Section::Type(TypeSection::with_types(vec![
+ Type::Function(FunctionType::new(
+ vec![ValueType::I32],
+ vec![ValueType::I32],
+ )),
+ Type::Function(FunctionType::new(vec![], vec![])),
+ ])),
+ Section::Import(ImportSection::with_entries(vec![
+ ImportEntry::new(
+ "env".into(),
+ "memory".into(),
+ External::Memory(MemoryType::new(1_u32, None)),
+ ),
+ ImportEntry::new("env".into(), "alloc".into(), External::Function(0_u32)),
+ ])),
+ Section::Function(FunctionSection::with_entries(vec![
+ Func::new(1_u32),
+ Func::new(1_u32),
+ ])),
+ Section::Export(ExportSection::with_entries(vec![
+ ExportEntry::new("init".into(), Internal::Function(1)),
+ ExportEntry::new("handle".into(), Internal::Function(2)),
+ ])),
+ Section::Code(CodeSection::with_bodies(vec![
+ FuncBody::new(vec![], Instructions::new(vec![Instruction::End])),
+ FuncBody::new(
+ vec![Local::new(1, ValueType::I32)],
+ Instructions::new(vec![
+ Instruction::I32Const(num_pages),
+ Instruction::Call(0),
+ Instruction::SetLocal(0),
+ Instruction::End,
+ ]),
+ ),
+ ])),
+ ]);
+ let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
+
+ Ok(code)
+}
+
+pub fn generate_wasm3(payload: Vec) -> Result, &'static str> {
+ let mut module = create_module(1);
+ module
+ .insert_section(Section::Custom(CustomSection::new(
+ "zeroed_section".to_owned(),
+ payload,
+ )))
+ .unwrap();
+ let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
+
+ Ok(code)
+}
+
+pub fn set_program(program_id: H256, code: Vec, static_pages: u32, nonce: u64) {
+ let code_hash = CodeHash::generate(&code).into_origin();
+ super::set_program(
+ program_id,
+ ActiveProgram {
+ static_pages,
+ persistent_pages: (0..static_pages).collect(),
+ code_hash,
+ nonce,
+ state: ProgramState::Initialized,
+ },
+ (0..static_pages).map(|i| (i, vec![0u8; 65536])).collect(),
+ );
+}
diff --git a/common/src/lib.rs b/common/src/lib.rs
index 3aeb1bfe6f4..d6a1594d8e1 100644
--- a/common/src/lib.rs
+++ b/common/src/lib.rs
@@ -22,6 +22,9 @@ pub mod lazy_pages;
pub mod native;
pub mod storage_queue;
+#[cfg(feature = "runtime-benchmarks")]
+pub mod benchmarking;
+
use codec::{Decode, Encode};
use frame_support::{
dispatch::{DispatchError, DispatchResult},
@@ -492,22 +495,32 @@ fn code_key(code_hash: H256, kind: CodeKeyPrefixKind) -> Vec {
key
}
-fn page_key(id: H256, page: u32) -> Vec {
+pub fn pages_prefix(program_id: H256) -> Vec {
let mut key = Vec::new();
key.extend(STORAGE_PROGRAM_PAGES_PREFIX);
- id.encode_to(&mut key);
+ program_id.encode_to(&mut key);
+
+ key
+}
+
+fn page_key(id: H256, page: u32) -> Vec {
+ let mut key = pages_prefix(id);
key.extend(b"::");
page.encode_to(&mut key);
key
}
-pub fn wait_key(prog_id: H256, msg_id: H256) -> Vec {
+pub fn wait_prefix(prog_id: H256) -> Vec {
let mut key = Vec::new();
key.extend(STORAGE_WAITLIST_PREFIX);
prog_id.encode_to(&mut key);
key.extend(b"::");
- msg_id.encode_to(&mut key);
+ key
+}
+pub fn wait_key(prog_id: H256, msg_id: H256) -> Vec {
+ let mut key = wait_prefix(prog_id);
+ msg_id.encode_to(&mut key);
key
}
@@ -545,9 +558,8 @@ pub fn set_program_terminated_status(id: H256) -> Result<(), ProgramError> {
if program.is_terminated() {
return Err(ProgramError::IsTerminated);
}
- let mut pages_prefix = STORAGE_PROGRAM_PAGES_PREFIX.to_vec();
- pages_prefix.extend(&program_key(id));
- sp_io::storage::clear_prefix(&pages_prefix, None);
+
+ sp_io::storage::clear_prefix(&pages_prefix(id), None);
sp_io::storage::set(&program_key(id), &Program::Terminated.encode());
Ok(())
@@ -699,7 +711,7 @@ pub fn remove_waiting_message(dest_prog_id: H256, msg_id: H256) -> Option<(Queue
msg
}
-fn waiting_init_prefix(prog_id: H256) -> Vec {
+pub fn waiting_init_prefix(prog_id: H256) -> Vec {
let mut key = Vec::new();
key.extend(STORAGE_PROGRAM_STATE_WAIT_PREFIX);
prog_id.encode_to(&mut key);
diff --git a/pallets/gear-debug/Cargo.toml b/pallets/gear-debug/Cargo.toml
index 95196f303a0..cea1fdcfdce 100644
--- a/pallets/gear-debug/Cargo.toml
+++ b/pallets/gear-debug/Cargo.toml
@@ -43,6 +43,7 @@ gear-backend-sandbox = { path = "../../core-backend/sandbox", default-features =
hex-literal = "0.3.3"
pallet-timestamp = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable" }
pallet-gas = { path = "../gas" }
+pallet-gear-program = { path = "../gear-program", default-features = false }
[features]
default = ['std']
diff --git a/pallets/gear-debug/src/mock.rs b/pallets/gear-debug/src/mock.rs
index 85fe2b993cf..82aa3785ded 100644
--- a/pallets/gear-debug/src/mock.rs
+++ b/pallets/gear-debug/src/mock.rs
@@ -118,6 +118,12 @@ impl common::GasPrice for GasConverter {
type Balance = u128;
}
+impl pallet_gear_program::Config for Test {
+ type Event = Event;
+ type WeightInfo = ();
+ type Currency = Balances;
+}
+
impl pallet_gear::Config for Test {
type Event = Event;
type Currency = Balances;
@@ -143,6 +149,7 @@ construct_runtime!(
Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
Authorship: pallet_authorship::{Pallet, Storage},
Timestamp: pallet_timestamp::{Pallet, Storage},
+ GearProgram: pallet_gear_program::{Pallet, Storage, Event},
Gear: pallet_gear::{Pallet, Call, Storage, Event},
Gas: pallet_gas,
}
diff --git a/pallets/gear-program/Cargo.toml b/pallets/gear-program/Cargo.toml
new file mode 100644
index 00000000000..52d9476153d
--- /dev/null
+++ b/pallets/gear-program/Cargo.toml
@@ -0,0 +1,59 @@
+[package]
+name = "pallet-gear-program"
+version = "2.0.0"
+authors = ['Gear Technologies']
+edition = '2018'
+license = "GPL-3.0"
+homepage = "https://gear-tech.io"
+repository = "https://github.com/gear-tech/gear"
+description = "Gear pallet to work with programs"
+readme = "README.md"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+codec = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0", default-features = false, features = ["derive"] }
+log = { version = "0.4.14", default-features = false }
+primitive-types = { version = "0.10.1", default-features = false, features = ["scale-info"] }
+
+# Internal deps
+common = { package = "gear-common", path = "../../common", default-features = false }
+
+# Substrate deps
+frame-support = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+frame-system = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+frame-benchmarking = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false, optional = true }
+sp-core = { version = "5.0.0", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+sp-std = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+sp-io = { version = "5.0.0", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+sp-runtime = { version = "5.0.0", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable", default-features = false }
+pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable" }
+
+[dev-dependencies]
+env_logger = "0.9"
+gear-core = { path = "../../core" }
+
+[features]
+default = ['std']
+std = [
+ "codec/std",
+ "log/std",
+ "common/std",
+ "frame-support/std",
+ "frame-system/std",
+ "scale-info/std",
+ "sp-io/std",
+ "sp-std/std",
+ "sp-core/std",
+ "sp-runtime/std",
+ "primitive-types/std",
+ "pallet-balances/std"
+]
+runtime-benchmarks = [
+ "frame-benchmarking",
+ "frame-system/runtime-benchmarks",
+ "frame-support/runtime-benchmarks",
+ "common/runtime-benchmarks"
+]
diff --git a/pallets/gear-program/README.md b/pallets/gear-program/README.md
new file mode 100644
index 00000000000..a35e52035ff
--- /dev/null
+++ b/pallets/gear-program/README.md
@@ -0,0 +1,14 @@
+# API to work with programs
+
+A module provides functions for things like pause/resume/check existence of programs.
+
+## Interface
+
+### Dispatchable Functions
+
+### Functions
+
+* `pause_program` - pause running program
+* `resume_program` - resumes previously paused program
+* `program_paused` - checks if the paused program with specified id exists
+* `program_exists` - checks if the program with specified id exists
diff --git a/pallets/gear-program/src/benchmarking.rs b/pallets/gear-program/src/benchmarking.rs
new file mode 100644
index 00000000000..575f3692a80
--- /dev/null
+++ b/pallets/gear-program/src/benchmarking.rs
@@ -0,0 +1,53 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use super::*;
+use common::{benchmarking, Origin};
+use sp_runtime::traits::UniqueSaturatedInto;
+
+#[allow(unused)]
+use crate::Pallet as GearProgram;
+use frame_benchmarking::{benchmarks, impl_benchmark_test_suite};
+use frame_support::traits::Currency;
+use frame_system::RawOrigin;
+
+benchmarks! {
+ where_clause { where
+ T::AccountId: Origin,
+ }
+
+ resume_program {
+ let q in 1 .. 256;
+ let caller: T::AccountId = benchmarking::account("caller", 0, 0);
+ ::Currency::deposit_creating(&caller, (1u128 << 60).unique_saturated_into());
+ let code = benchmarking::generate_wasm(q).unwrap();
+
+ let program_id = benchmarking::account::("program", 0, 100).into_origin();
+ benchmarking::set_program(program_id, code, q, 0u64);
+
+ let memory_pages = common::get_program_pages(program_id, (0..q).collect()).unwrap();
+
+ crate::Pallet::::pause_program(program_id).unwrap();
+ }: _(RawOrigin::Signed(caller), program_id, memory_pages, Default::default(), 10_000u32.into())
+ verify {
+ assert!(crate::Pallet::::program_exists(program_id));
+ assert!(!crate::Pallet::::program_paused(program_id));
+ }
+}
+
+impl_benchmark_test_suite!(GearProgram, crate::mock::new_test_ext(), crate::mock::Test);
diff --git a/pallets/gear-program/src/lib.rs b/pallets/gear-program/src/lib.rs
new file mode 100644
index 00000000000..1a5f5b47f49
--- /dev/null
+++ b/pallets/gear-program/src/lib.rs
@@ -0,0 +1,151 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use pallet::*;
+use primitive_types::H256;
+use sp_std::collections::btree_map::BTreeMap;
+use sp_std::prelude::*;
+
+mod pause;
+pub use pause::PauseError;
+
+mod program;
+
+#[cfg(test)]
+mod mock;
+
+#[cfg(test)]
+mod tests;
+
+pub mod weights;
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+
+#[frame_support::pallet]
+pub mod pallet {
+ use super::*;
+ use frame_support::{
+ pallet_prelude::*,
+ traits::{
+ Currency, ExistenceRequirement, LockIdentifier, LockableCurrency, WithdrawReasons,
+ },
+ };
+ use frame_system::pallet_prelude::*;
+ use sp_runtime::traits::{UniqueSaturatedInto, Zero};
+ use weights::WeightInfo;
+
+ const LOCK_ID: LockIdentifier = *b"resume_p";
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config {
+ /// Because this pallet emits events, it depends on the runtime's definition of an event.
+ type Event: From> + IsType<::Event>;
+
+ /// Weight information for extrinsics in this pallet.
+ type WeightInfo: WeightInfo;
+
+ type Currency: LockableCurrency;
+ }
+
+ type BalanceOf =
+ <::Currency as Currency<::AccountId>>::Balance;
+
+ #[pallet::pallet]
+ #[pallet::generate_store(pub(super) trait Store)]
+ pub struct Pallet(_);
+
+ #[pallet::event]
+ #[pallet::generate_deposit(pub(super) fn deposit_event)]
+ pub enum Event {
+ /// Program has been successfully resumed
+ ProgramResumed(H256),
+ /// Program has been paused
+ ProgramPaused(H256),
+ }
+
+ #[pallet::error]
+ pub enum Error {
+ PausedProgramNotFound,
+ WrongMemoryPages,
+ ResumeProgramNotEnoughValue,
+ WrongWaitList,
+ }
+
+ #[pallet::storage]
+ #[pallet::unbounded]
+ pub(crate) type PausedPrograms = StorageMap<_, Identity, H256, pause::PausedProgram>;
+
+ #[pallet::hooks]
+ impl Hooks> for Pallet {}
+
+ #[pallet::call]
+ impl Pallet
+ where
+ T::AccountId: common::Origin,
+ {
+ /// Resumes a previously paused program
+ ///
+ /// The origin must be Signed and the sender must have sufficient funds to
+ /// transfer value to the program.
+ ///
+ /// Parameters:
+ /// - `program_id`: id of the program to resume.
+ /// - `memory_pages`: program memory before it was paused.
+ /// - `value`: balance to be transferred to the program once it's been resumed.
+ ///
+ /// - `ProgramResumed(H256)` in the case of success.
+ #[frame_support::transactional]
+ #[pallet::weight(::WeightInfo::resume_program(memory_pages.values().map(|p| p.len() as u32).sum()))]
+ pub fn resume_program(
+ origin: OriginFor,
+ program_id: H256,
+ memory_pages: BTreeMap>,
+ wait_list: BTreeMap,
+ value: BalanceOf,
+ ) -> DispatchResultWithPostInfo {
+ let account = ensure_signed(origin)?;
+
+ ensure!(!value.is_zero(), Error::::ResumeProgramNotEnoughValue);
+
+ Self::resume_program_impl(
+ program_id,
+ memory_pages,
+ wait_list,
+ >::block_number().unique_saturated_into(),
+ )?;
+
+ let program_account = &::from_origin(program_id);
+ T::Currency::transfer(
+ &account,
+ program_account,
+ value,
+ ExistenceRequirement::AllowDeath,
+ )?;
+
+ // TODO: maybe it is sufficient just to reserve value? (#762)
+ T::Currency::extend_lock(LOCK_ID, program_account, value, WithdrawReasons::FEE);
+
+ Self::deposit_event(Event::ProgramResumed(program_id));
+
+ Ok(().into())
+ }
+ }
+}
diff --git a/pallets/gear-program/src/mock.rs b/pallets/gear-program/src/mock.rs
new file mode 100644
index 00000000000..2dbf60d4583
--- /dev/null
+++ b/pallets/gear-program/src/mock.rs
@@ -0,0 +1,114 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use crate as pallet_gear_program;
+use frame_support::traits::{OnFinalize, OnInitialize};
+use frame_support::{construct_runtime, parameter_types};
+use frame_system as system;
+use sp_core::H256;
+use sp_runtime::{
+ testing::Header,
+ traits::{BlakeTwo256, IdentityLookup},
+};
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
+type Block = frame_system::mocking::MockBlock;
+type AccountId = u64;
+
+// Configure a mock runtime to test the pallet.
+construct_runtime!(
+ pub enum Test where
+ Block = Block,
+ NodeBlock = Block,
+ UncheckedExtrinsic = UncheckedExtrinsic,
+ {
+ System: system::{Pallet, Call, Config, Storage, Event},
+ Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
+ GearProgram: pallet_gear_program::{Pallet, Storage, Event},
+ }
+);
+
+parameter_types! {
+ pub const BlockHashCount: u64 = 250;
+ pub const SS58Prefix: u8 = 42;
+ pub const ExistentialDeposit: u64 = 1;
+}
+
+impl system::Config for Test {
+ type BaseCallFilter = frame_support::traits::Everything;
+ type BlockWeights = ();
+ type BlockLength = ();
+ type DbWeight = ();
+ type Origin = Origin;
+ type Call = Call;
+ type Index = u64;
+ type BlockNumber = u64;
+ type Hash = H256;
+ type Hashing = BlakeTwo256;
+ type AccountId = AccountId;
+ type Lookup = IdentityLookup;
+ type Header = Header;
+ type Event = Event;
+ type BlockHashCount = BlockHashCount;
+ type Version = ();
+ type PalletInfo = PalletInfo;
+ type AccountData = pallet_balances::AccountData;
+ type OnNewAccount = ();
+ type OnKilledAccount = ();
+ type SystemWeightInfo = ();
+ type SS58Prefix = SS58Prefix;
+ type OnSetCode = ();
+ type MaxConsumers = frame_support::traits::ConstU32<16>;
+}
+
+impl pallet_balances::Config for Test {
+ type MaxLocks = ();
+ type MaxReserves = ();
+ type ReserveIdentifier = [u8; 8];
+ type Balance = u128;
+ type DustRemoval = ();
+ type Event = Event;
+ type ExistentialDeposit = ExistentialDeposit;
+ type AccountStore = System;
+ type WeightInfo = ();
+}
+
+impl pallet_gear_program::Config for Test {
+ type Event = Event;
+ type WeightInfo = ();
+ type Currency = Balances;
+}
+
+// Build genesis storage according to the mock runtime.
+pub fn new_test_ext() -> sp_io::TestExternalities {
+ let t = system::GenesisConfig::default()
+ .build_storage::()
+ .unwrap();
+
+ let mut ext = sp_io::TestExternalities::new(t);
+ ext.execute_with(|| System::set_block_number(1));
+ ext
+}
+
+pub fn run_to_block(n: u64, _remaining_weight: Option) {
+ while System::block_number() < n {
+ System::on_finalize(System::block_number());
+ System::set_block_number(System::block_number() + 1);
+ System::on_initialize(System::block_number());
+ }
+}
diff --git a/pallets/gear-program/src/pause.rs b/pallets/gear-program/src/pause.rs
new file mode 100644
index 00000000000..c05c9a9f836
--- /dev/null
+++ b/pallets/gear-program/src/pause.rs
@@ -0,0 +1,125 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use super::*;
+use codec::{Decode, Encode};
+use common::{self, QueuedDispatch};
+use frame_support::{dispatch::DispatchResult, storage::PrefixIterator};
+use scale_info::TypeInfo;
+
+#[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
+pub(super) struct PausedProgram {
+ program_id: H256,
+ program: common::ActiveProgram,
+ pages_hash: H256,
+ wait_list_hash: H256,
+ waiting_init: Vec,
+}
+
+fn decode_dispatch_tuple(_key: &[u8], value: &[u8]) -> Result<(QueuedDispatch, u32), codec::Error> {
+ <(QueuedDispatch, u32)>::decode(&mut &*value)
+}
+
+fn memory_pages_hash(pages: &BTreeMap>) -> H256 {
+ pages.using_encoded(sp_io::hashing::blake2_256).into()
+}
+
+fn wait_list_hash(wait_list: &BTreeMap) -> H256 {
+ wait_list.using_encoded(sp_io::hashing::blake2_256).into()
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum PauseError {
+ ProgramNotFound,
+ ProgramTerminated,
+}
+
+impl pallet::Pallet {
+ pub fn pause_program(program_id: H256) -> Result<(), PauseError> {
+ let program = common::get_program(program_id).ok_or(PauseError::ProgramNotFound)?;
+ let program: common::ActiveProgram = program
+ .try_into()
+ .map_err(|_| PauseError::ProgramTerminated)?;
+
+ let prefix = common::wait_prefix(program_id);
+ let previous_key = prefix.clone();
+
+ let paused_program = PausedProgram {
+ program_id,
+ pages_hash: memory_pages_hash(
+ &common::get_program_pages(program_id, program.persistent_pages.clone())
+ .expect("pause_program: active program exists, therefore pages do"),
+ ),
+ program,
+ wait_list_hash: wait_list_hash(
+ &PrefixIterator::<_, ()>::new(prefix, previous_key, decode_dispatch_tuple)
+ .drain()
+ .map(|(d, _)| (d.message.id, d))
+ .collect(),
+ ),
+ waiting_init: common::waiting_init_take_messages(program_id),
+ };
+
+ // code shouldn't be removed
+ // remove_program(program_id);
+ sp_io::storage::clear_prefix(&common::pages_prefix(program_id), None);
+ sp_io::storage::clear_prefix(&common::program_key(program_id), None);
+
+ PausedPrograms::::insert(program_id, paused_program);
+
+ Self::deposit_event(Event::ProgramPaused(program_id));
+
+ Ok(())
+ }
+
+ pub fn program_paused(id: H256) -> bool {
+ PausedPrograms::::contains_key(id)
+ }
+
+ pub(super) fn resume_program_impl(
+ program_id: H256,
+ memory_pages: BTreeMap>,
+ wait_list: BTreeMap,
+ block_number: u32,
+ ) -> DispatchResult {
+ let paused_program =
+ PausedPrograms::::get(program_id).ok_or(Error::::PausedProgramNotFound)?;
+
+ if paused_program.pages_hash != memory_pages_hash(&memory_pages) {
+ return Err(Error::::WrongMemoryPages.into());
+ }
+
+ if paused_program.wait_list_hash != wait_list_hash(&wait_list) {
+ return Err(Error::::WrongWaitList.into());
+ }
+
+ PausedPrograms::::remove(program_id);
+
+ common::set_program(program_id, paused_program.program, memory_pages);
+
+ wait_list.into_iter().for_each(|(msg_id, d)| {
+ common::insert_waiting_message(program_id, msg_id, d, block_number)
+ });
+ sp_io::storage::set(
+ &common::waiting_init_prefix(program_id),
+ &paused_program.waiting_init.encode()[..],
+ );
+
+ Ok(())
+ }
+}
diff --git a/pallets/gear-program/src/program.rs b/pallets/gear-program/src/program.rs
new file mode 100644
index 00000000000..608a87538db
--- /dev/null
+++ b/pallets/gear-program/src/program.rs
@@ -0,0 +1,29 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use super::*;
+
+impl pallet::Pallet {
+ pub fn program_exists(program_id: H256) -> bool {
+ common::program_exists(program_id) | Self::program_paused(program_id)
+ }
+
+ pub fn reset_storage() {
+ PausedPrograms::::remove_all(None);
+ }
+}
diff --git a/pallets/gear-program/src/tests.rs b/pallets/gear-program/src/tests.rs
new file mode 100644
index 00000000000..3c6fc829be3
--- /dev/null
+++ b/pallets/gear-program/src/tests.rs
@@ -0,0 +1,460 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use common::{ActiveProgram, Origin, ProgramState, QueuedDispatch, QueuedMessage};
+use frame_support::{assert_noop, assert_ok};
+use gear_core::program::CodeHash;
+use sp_std::collections::btree_map::BTreeMap;
+
+use super::*;
+use crate::mock::*;
+
+use utils::CreateProgramResult;
+
+#[test]
+fn pause_program_works() {
+ new_test_ext().execute_with(|| {
+ let code = b"pretended wasm code".to_vec();
+ let code_hash: H256 = CodeHash::generate(&code).into_origin();
+ common::set_code(code_hash, &code);
+
+ let static_pages: u32 = 16;
+ let memory_pages = {
+ let mut pages = BTreeMap::new();
+ pages.insert(static_pages, vec![static_pages as u8]);
+ pages.insert(static_pages + 2, vec![static_pages as u8 + 2]);
+ for i in 0..static_pages {
+ pages.insert(i, vec![i as u8]);
+ }
+
+ pages
+ };
+
+ let program_id = H256::from_low_u64_be(1);
+
+ common::set_program(
+ program_id,
+ ActiveProgram {
+ static_pages,
+ persistent_pages: memory_pages.clone().into_keys().collect(),
+ code_hash,
+ nonce: 0,
+ state: ProgramState::Initialized,
+ },
+ memory_pages.clone(),
+ );
+
+ let msg_id_1 = H256::from_low_u64_be(1);
+ common::insert_waiting_message(
+ program_id,
+ msg_id_1,
+ QueuedDispatch::new_handle(QueuedMessage {
+ id: msg_id_1,
+ source: H256::from_low_u64_be(3),
+ dest: program_id,
+ payload: Default::default(),
+ value: 0,
+ reply: None,
+ }),
+ 0,
+ );
+
+ let msg_id_2 = H256::from_low_u64_be(2);
+ common::insert_waiting_message(
+ program_id,
+ msg_id_2,
+ QueuedDispatch::new_handle(QueuedMessage {
+ id: msg_id_2,
+ source: H256::from_low_u64_be(4),
+ dest: program_id,
+ payload: Default::default(),
+ value: 0,
+ reply: None,
+ }),
+ 0,
+ );
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ assert!(GearProgram::program_paused(program_id));
+
+ assert!(common::get_code(code_hash).is_some());
+
+ // although the memory pages should be removed
+ assert_eq!(
+ common::get_program_pages(program_id, memory_pages.into_keys().collect()),
+ None
+ );
+
+ assert!(common::remove_waiting_message(program_id, msg_id_1).is_none());
+ assert!(common::remove_waiting_message(program_id, msg_id_2).is_none());
+ });
+}
+
+#[test]
+fn pause_program_twice_fails() {
+ new_test_ext().execute_with(|| {
+ let code = b"pretended wasm code".to_vec();
+ let code_hash: H256 = CodeHash::generate(&code).into_origin();
+ common::set_code(code_hash, &code);
+
+ let program_id = H256::from_low_u64_be(1);
+ let static_pages = 256;
+ common::set_program(
+ program_id,
+ ActiveProgram {
+ static_pages,
+ persistent_pages: Default::default(),
+ code_hash,
+ nonce: 0,
+ state: ProgramState::Initialized,
+ },
+ Default::default(),
+ );
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+ assert_noop!(
+ GearProgram::pause_program(program_id),
+ PauseError::ProgramNotFound
+ );
+ });
+}
+
+#[test]
+fn pause_terminated_program_fails() {
+ new_test_ext().execute_with(|| {
+ let code = b"pretended wasm code".to_vec();
+ let code_hash: H256 = CodeHash::generate(&code).into_origin();
+ common::set_code(code_hash, &code);
+
+ let program_id = H256::from_low_u64_be(1);
+ let static_pages = 256;
+ common::set_program(
+ program_id,
+ ActiveProgram {
+ static_pages,
+ persistent_pages: Default::default(),
+ code_hash,
+ nonce: 0,
+ state: ProgramState::Initialized,
+ },
+ Default::default(),
+ );
+
+ run_to_block(2, None);
+
+ assert_ok!(common::set_program_terminated_status(program_id));
+
+ assert_noop!(
+ GearProgram::pause_program(program_id),
+ PauseError::ProgramTerminated
+ );
+ });
+}
+
+#[test]
+fn pause_uninitialized_program_works() {
+ new_test_ext().execute_with(|| {
+ let static_pages = 16;
+ let CreateProgramResult {
+ program_id,
+ code_hash,
+ init_msg,
+ msg_1,
+ msg_2,
+ memory_pages,
+ } = utils::create_uninitialized_program_messages(static_pages);
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ assert!(GearProgram::program_paused(program_id));
+ assert!(common::get_program(program_id).is_none());
+
+ assert!(common::get_code(code_hash).is_some());
+
+ // although the memory pages should be removed
+ assert_eq!(
+ common::get_program_pages(program_id, memory_pages.into_keys().collect()),
+ None
+ );
+
+ assert!(common::remove_waiting_message(program_id, msg_1.message.id).is_none());
+ assert!(common::remove_waiting_message(program_id, msg_2.message.id).is_none());
+ assert!(common::remove_waiting_message(program_id, init_msg.message.id).is_none());
+
+ assert!(common::waiting_init_take_messages(program_id).is_empty());
+ });
+}
+
+#[test]
+fn resume_uninitialized_program_works() {
+ new_test_ext().execute_with(|| {
+ let static_pages = 16;
+ let CreateProgramResult {
+ program_id,
+ init_msg,
+ msg_1,
+ msg_2,
+ memory_pages,
+ ..
+ } = utils::create_uninitialized_program_messages(static_pages);
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ let wait_list = IntoIterator::into_iter([&init_msg, &msg_1, &msg_2])
+ .map(|d| (d.message.id, d.clone()))
+ .collect::>();
+
+ let block_number = 100;
+ assert_ok!(GearProgram::resume_program_impl(
+ program_id,
+ memory_pages.clone(),
+ wait_list,
+ block_number
+ ));
+ assert!(!GearProgram::program_paused(program_id));
+
+ let new_memory_pages =
+ common::get_program_pages(program_id, memory_pages.clone().into_keys().collect())
+ .unwrap();
+ assert_eq!(memory_pages, new_memory_pages);
+
+ let waiting_init = common::waiting_init_take_messages(program_id);
+ assert_eq!(waiting_init.len(), 2);
+ assert!(waiting_init.contains(&msg_1.message.id));
+ assert!(waiting_init.contains(&msg_2.message.id));
+
+ assert_eq!(
+ block_number,
+ common::remove_waiting_message(program_id, init_msg.message.id)
+ .map(|(_, bn)| bn)
+ .unwrap()
+ );
+ assert_eq!(
+ block_number,
+ common::remove_waiting_message(program_id, msg_1.message.id)
+ .map(|(_, bn)| bn)
+ .unwrap()
+ );
+ assert_eq!(
+ block_number,
+ common::remove_waiting_message(program_id, msg_2.message.id)
+ .map(|(_, bn)| bn)
+ .unwrap()
+ );
+ });
+}
+
+#[test]
+fn resume_program_twice_fails() {
+ new_test_ext().execute_with(|| {
+ let static_pages = 16;
+ let CreateProgramResult {
+ program_id,
+ memory_pages,
+ init_msg,
+ msg_1,
+ msg_2,
+ ..
+ } = utils::create_uninitialized_program_messages(static_pages);
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ let wait_list = IntoIterator::into_iter([init_msg, msg_1, msg_2])
+ .map(|d| (d.message.id, d))
+ .collect::>();
+
+ let block_number = 100;
+ assert_ok!(GearProgram::resume_program_impl(
+ program_id,
+ memory_pages.clone(),
+ wait_list.clone(),
+ block_number
+ ));
+ assert_noop!(
+ GearProgram::resume_program_impl(program_id, memory_pages, wait_list, block_number),
+ Error::::PausedProgramNotFound
+ );
+ });
+}
+
+#[test]
+fn resume_program_wrong_memory_fails() {
+ new_test_ext().execute_with(|| {
+ let static_pages = 16;
+ let CreateProgramResult {
+ program_id,
+ mut memory_pages,
+ init_msg,
+ msg_1,
+ msg_2,
+ ..
+ } = utils::create_uninitialized_program_messages(static_pages);
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ let block_number = 100;
+ memory_pages.remove(&0);
+ assert_noop!(
+ GearProgram::resume_program_impl(
+ program_id,
+ memory_pages,
+ IntoIterator::into_iter([init_msg, msg_1, msg_2])
+ .map(|d| (d.message.id, d))
+ .collect(),
+ block_number
+ ),
+ Error::::WrongMemoryPages
+ );
+ });
+}
+
+#[test]
+fn resume_program_wrong_list_fails() {
+ new_test_ext().execute_with(|| {
+ let static_pages = 16;
+ let CreateProgramResult {
+ program_id,
+ memory_pages,
+ init_msg,
+ msg_1,
+ mut msg_2,
+ ..
+ } = utils::create_uninitialized_program_messages(static_pages);
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ let block_number = 100;
+ msg_2.message.payload = [0, 1, 2, 3, 4, 5].into();
+ assert_noop!(
+ GearProgram::resume_program_impl(
+ program_id,
+ memory_pages,
+ IntoIterator::into_iter([init_msg, msg_1, msg_2])
+ .map(|d| (d.message.id, d))
+ .collect(),
+ block_number
+ ),
+ Error::::WrongWaitList
+ );
+ });
+}
+
+mod utils {
+ use super::*;
+
+ pub struct CreateProgramResult {
+ pub program_id: H256,
+ pub code_hash: H256,
+ pub init_msg: QueuedDispatch,
+ pub msg_1: QueuedDispatch,
+ pub msg_2: QueuedDispatch,
+ pub memory_pages: BTreeMap>,
+ }
+
+ pub fn create_uninitialized_program_messages(static_pages: u32) -> CreateProgramResult {
+ let code = b"pretended wasm code".to_vec();
+ let code_hash: H256 = CodeHash::generate(&code).into_origin();
+ common::set_code(code_hash, &code);
+
+ let memory_pages = {
+ let mut pages = BTreeMap::>::new();
+ pages.insert(static_pages, vec![static_pages as u8]);
+ pages.insert(static_pages + 2, vec![static_pages as u8 + 2]);
+ for i in 0..static_pages {
+ pages.insert(i, vec![i as u8]);
+ }
+
+ pages
+ };
+
+ let init_msg_id = H256::from_low_u64_be(3);
+ let program_id = H256::from_low_u64_be(1);
+ common::set_program(
+ program_id,
+ ActiveProgram {
+ static_pages,
+ persistent_pages: memory_pages.clone().into_keys().collect(),
+ code_hash,
+ nonce: 0,
+ state: ProgramState::Uninitialized {
+ message_id: init_msg_id,
+ },
+ },
+ memory_pages.clone(),
+ );
+
+ // init message
+ let init_msg = QueuedDispatch::new_handle(QueuedMessage {
+ id: init_msg_id,
+ source: H256::from_low_u64_be(3),
+ dest: program_id,
+ payload: Default::default(),
+ value: 0,
+ reply: None,
+ });
+ common::insert_waiting_message(program_id, init_msg_id, init_msg.clone(), 0);
+
+ let msg_id_1 = H256::from_low_u64_be(1);
+ let msg_1 = QueuedDispatch::new_handle(QueuedMessage {
+ id: msg_id_1,
+ source: H256::from_low_u64_be(3),
+ dest: program_id,
+ payload: Default::default(),
+ value: 0,
+ reply: None,
+ });
+ common::insert_waiting_message(program_id, msg_id_1, msg_1.clone(), 0);
+ common::waiting_init_append_message_id(program_id, msg_id_1);
+
+ let msg_id_2 = H256::from_low_u64_be(2);
+ let msg_2 = QueuedDispatch::new_handle(QueuedMessage {
+ id: msg_id_2,
+ source: H256::from_low_u64_be(4),
+ dest: program_id,
+ payload: Default::default(),
+ value: 0,
+ reply: None,
+ });
+ common::insert_waiting_message(program_id, msg_id_2, msg_2.clone(), 0);
+ common::waiting_init_append_message_id(program_id, msg_id_2);
+
+ CreateProgramResult {
+ program_id,
+ code_hash,
+ init_msg,
+ msg_1,
+ msg_2,
+ memory_pages,
+ }
+ }
+}
diff --git a/pallets/gear-program/src/weights/mod.rs b/pallets/gear-program/src/weights/mod.rs
new file mode 100644
index 00000000000..7d95887b4c5
--- /dev/null
+++ b/pallets/gear-program/src/weights/mod.rs
@@ -0,0 +1,38 @@
+// This file is part of Gear.
+
+// Copyright (C) 2022 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use frame_support::weights::{constants::RocksDbWeight, Weight};
+
+mod pallet_gear_program;
+pub use self::pallet_gear_program::WeightInfo as GearProgramWeight;
+
+/// Weight functions for pallet_gear_program.
+pub trait WeightInfo {
+ fn resume_program(q: u32) -> Weight;
+}
+
+// For backwards compatibility and tests
+const SUBMIT_WEIGHT_PER_BYTE: u64 = 1_000_000;
+
+impl WeightInfo for () {
+ fn resume_program(q: u32) -> Weight {
+ (0u64)
+ .saturating_add(RocksDbWeight::get().writes(4u64))
+ .saturating_add(SUBMIT_WEIGHT_PER_BYTE.saturating_mul(q as Weight))
+ }
+}
diff --git a/pallets/gear-program/src/weights/pallet_gear_program.rs b/pallets/gear-program/src/weights/pallet_gear_program.rs
new file mode 100644
index 00000000000..5cea7ff2b22
--- /dev/null
+++ b/pallets/gear-program/src/weights/pallet_gear_program.rs
@@ -0,0 +1,35 @@
+
+//! Autogenerated weights for `pallet_gear_program`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2022-03-14, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("local"), DB CACHE: 1024
+
+// Executed Command:
+// ./target/release/gear-node benchmark --chain=local --execution=wasm --wasm-execution=compiled --pallet=pallet_gear_program --steps 50 --repeat 20 --output ./pallets/gear-program/src/weights/ --extrinsic=*
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(clippy::unnecessary_cast)]
+
+use frame_support::{traits::Get, weights::Weight};
+use sp_std::marker::PhantomData;
+
+/// Weight functions for `pallet_gear_program`.
+pub struct WeightInfo(PhantomData);
+impl super::WeightInfo for WeightInfo {
+ // Storage: GearProgram PausedPrograms (r:1 w:1)
+ // Storage: System Account (r:2 w:2)
+ // Storage: unknown [0x673a3a70616765733a3a13614ad1183876953cdd99749d6dcf5d41b7ffc0740c] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a13614ad1183876953cdd99749d6dcf5d41b7ffc0740cd2] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f675f776169743a3a13614ad1183876953cdd99749d6dcf5d41b7] (r:0 w:1)
+ fn resume_program(q: u32, ) -> Weight {
+ (0 as Weight)
+ // Standard Error: 249_000
+ .saturating_add((133_779_000 as Weight).saturating_mul(q as Weight))
+ .saturating_add(T::DbWeight::get().reads(3 as Weight))
+ .saturating_add(T::DbWeight::get().writes(5 as Weight))
+ .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(q as Weight)))
+ }
+}
diff --git a/pallets/gear/Cargo.toml b/pallets/gear/Cargo.toml
index 09f10689804..2f6bf240af8 100644
--- a/pallets/gear/Cargo.toml
+++ b/pallets/gear/Cargo.toml
@@ -40,6 +40,7 @@ sp-arithmetic = { version = "4.0.0-dev", git = "https://github.com/gear-tech/sub
pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable" }
pallet-authorship = { version = "4.0.0-dev", default-features = false, git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable" }
pallet-timestamp = { version = "4.0.0-dev", default-features = false, git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable" }
+pallet-gear-program = { path = "../gear-program", default-features = false }
[dev-dependencies]
serde = "1.0.136"
@@ -52,6 +53,7 @@ tests-init-wait = { path = "../../tests/init-wait" }
tests-exit-init = { path = "../../tests/exit-init" }
tests-exit-handle = { path = "../../tests/exit-handle" }
tests-program-factory = { path = "../../tests/program-factory" }
+tests-proxy = { path = "../../tests/proxy" }
[features]
default = ['std']
@@ -70,6 +72,7 @@ std = [
"sp-runtime/std",
"pallet-balances/std",
"pallet-authorship/std",
+ "pallet-gear-program/std",
"primitive-types/std",
"serde/std",
"gear-runtime-interface/std",
@@ -79,4 +82,5 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"parity-wasm",
+ "common/runtime-benchmarks"
]
diff --git a/pallets/gear/src/benchmarking.rs b/pallets/gear/src/benchmarking.rs
index 559670b9af4..d795db1cdff 100644
--- a/pallets/gear/src/benchmarking.rs
+++ b/pallets/gear/src/benchmarking.rs
@@ -19,14 +19,10 @@
//! Gear pallet benchmarking
use super::*;
-use codec::Encode;
-use common::Origin;
+use common::{benchmarking, Origin};
use gear_core::program::CodeHash;
-use parity_wasm::elements::*;
use sp_core::H256;
-use sp_io::hashing::blake2_256;
use sp_runtime::traits::UniqueSaturatedInto;
-use sp_std::borrow::ToOwned;
use sp_std::prelude::*;
#[allow(unused)]
@@ -40,139 +36,15 @@ const MAX_CODE_LEN: u32 = 128 * 1024;
const MAX_PAYLOAD_LEN: u32 = 64 * 1024;
const MAX_PAGES: u32 = 512;
-pub fn account(name: &'static str, index: u32, seed: u32) -> AccountId {
- let entropy = (name, index, seed).using_encoded(blake2_256);
- AccountId::from_origin(H256::from_slice(&entropy[..]))
-}
-
-// A wasm module that allocates `$num_pages` of memory in `init` function.
-// In text format would look something like
-// (module
-// (type (func))
-// (import "env" "memory" (memory $num_pages))
-// (func (type 0))
-// (export "init" (func 0)))
-fn create_module(num_pages: u32) -> parity_wasm::elements::Module {
- parity_wasm::elements::Module::new(vec![
- Section::Type(TypeSection::with_types(vec![Type::Function(
- FunctionType::new(vec![], vec![]),
- )])),
- Section::Import(ImportSection::with_entries(vec![ImportEntry::new(
- "env".into(),
- "memory".into(),
- External::Memory(MemoryType::new(num_pages, None)),
- )])),
- Section::Function(FunctionSection::with_entries(vec![Func::new(0)])),
- Section::Export(ExportSection::with_entries(vec![ExportEntry::new(
- "init".into(),
- Internal::Function(0),
- )])),
- Section::Code(CodeSection::with_bodies(vec![FuncBody::new(
- vec![],
- Instructions::new(vec![Instruction::End]),
- )])),
- ])
-}
-
-fn generate_wasm(num_pages: u32) -> Result, &'static str> {
- let module = create_module(num_pages);
- let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
-
- Ok(code)
-}
-
-// A wasm module that allocates `$num_pages` in `handle` function:
-// (module
-// (import "env" "memory" (memory 1))
-// (import "env" "alloc" (func $alloc (param i32) (result i32)))
-// (export "init" (func $init))
-// (export "handle" (func $handle))
-// (func $init)
-// (func $handle
-// (local $result i32)
-// (local.set $result (call $alloc (i32.const $num_pages)))
-// )
-// )
-fn generate_wasm2(num_pages: i32) -> Result, &'static str> {
- let module = parity_wasm::elements::Module::new(vec![
- Section::Type(TypeSection::with_types(vec![
- Type::Function(FunctionType::new(
- vec![ValueType::I32],
- vec![ValueType::I32],
- )),
- Type::Function(FunctionType::new(vec![], vec![])),
- ])),
- Section::Import(ImportSection::with_entries(vec![
- ImportEntry::new(
- "env".into(),
- "memory".into(),
- External::Memory(MemoryType::new(1_u32, None)),
- ),
- ImportEntry::new("env".into(), "alloc".into(), External::Function(0_u32)),
- ])),
- Section::Function(FunctionSection::with_entries(vec![
- Func::new(1_u32),
- Func::new(1_u32),
- ])),
- Section::Export(ExportSection::with_entries(vec![
- ExportEntry::new("init".into(), Internal::Function(1)),
- ExportEntry::new("handle".into(), Internal::Function(2)),
- ])),
- Section::Code(CodeSection::with_bodies(vec![
- FuncBody::new(vec![], Instructions::new(vec![Instruction::End])),
- FuncBody::new(
- vec![Local::new(1, ValueType::I32)],
- Instructions::new(vec![
- Instruction::I32Const(num_pages),
- Instruction::Call(0),
- Instruction::SetLocal(0),
- Instruction::End,
- ]),
- ),
- ])),
- ]);
- let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
-
- Ok(code)
-}
-
-fn generate_wasm3(payload: Vec) -> Result, &'static str> {
- let mut module = create_module(1);
- module
- .insert_section(Section::Custom(CustomSection::new(
- "zeroed_section".to_owned(),
- payload,
- )))
- .unwrap();
- let code = parity_wasm::serialize(module).map_err(|_| "Failed to serialize module")?;
-
- Ok(code)
-}
-
-fn set_program(program_id: H256, code: Vec, static_pages: u32, nonce: u64) {
- let code_hash = CodeHash::generate(&code).into_origin();
- common::set_program(
- program_id,
- common::ActiveProgram {
- static_pages,
- persistent_pages: (0..static_pages).collect(),
- code_hash,
- nonce,
- state: common::ProgramState::Initialized,
- },
- (0..static_pages).map(|i| (i, vec![0u8; 65536])).collect(),
- );
-}
-
benchmarks! {
where_clause { where
T::AccountId: Origin,
}
submit_code {
- let c in 0 .. MAX_CODE_LEN;
- let caller: T::AccountId = account("caller", 0, 0);
- let code = vec![0u8; c as usize];
+ let c in MIN_CODE_LEN .. MAX_CODE_LEN;
+ let caller: T::AccountId = benchmarking::account("caller", 0, 0);
+ let code = benchmarking::generate_wasm3(vec![0u8; (c - MIN_CODE_LEN) as usize]).unwrap();
let code_hash: H256 = CodeHash::generate(&code).into_origin();
}: _(RawOrigin::Signed(caller), code)
verify {
@@ -182,9 +54,9 @@ benchmarks! {
submit_program {
let c in MIN_CODE_LEN .. MAX_CODE_LEN;
let p in 0 .. MAX_PAYLOAD_LEN;
- let caller: T::AccountId = account("caller", 0, 0);
- T::Currency::deposit_creating(&caller, 100_000_000_000_000_u128.unique_saturated_into());
- let code = generate_wasm3(vec![0u8; (c - MIN_CODE_LEN) as usize]).unwrap();
+ let caller: T::AccountId = benchmarking::account("caller", 0, 0);
+ ::Currency::deposit_creating(&caller, 100_000_000_000_000_u128.unique_saturated_into());
+ let code = benchmarking::generate_wasm3(vec![0u8; (c - MIN_CODE_LEN) as usize]).unwrap();
let salt = vec![255u8; 32];
let payload = vec![1_u8; p as usize];
// Using a non-zero `value` to count in the transfer, as well
@@ -196,11 +68,11 @@ benchmarks! {
send_message {
let p in 0 .. MAX_PAYLOAD_LEN;
- let caller = account("caller", 0, 0);
- T::Currency::deposit_creating(&caller, 100_000_000_000_000_u128.unique_saturated_into());
- let program_id = account::("program", 0, 100).into_origin();
- let code = generate_wasm2(16_i32).unwrap();
- set_program(program_id, code, 1_u32, 0_u64);
+ let caller = benchmarking::account("caller", 0, 0);
+ ::Currency::deposit_creating(&caller, 100_000_000_000_000_u128.unique_saturated_into());
+ let program_id = benchmarking::account::("program", 0, 100).into_origin();
+ let code = benchmarking::generate_wasm2(16_i32).unwrap();
+ benchmarking::set_program(program_id, code, 1_u32, 0_u64);
let payload = vec![0_u8; p as usize];
}: _(RawOrigin::Signed(caller), program_id, payload, 100_000_000_u64, 10_000_u32.into())
verify {
@@ -209,12 +81,12 @@ benchmarks! {
send_reply {
let p in 0 .. MAX_PAYLOAD_LEN;
- let caller = account("caller", 0, 0);
- T::Currency::deposit_creating(&caller, 100_000_000_000_000_u128.unique_saturated_into());
- let program_id = account::("program", 0, 100).into_origin();
- let code = generate_wasm2(16_i32).unwrap();
- set_program(program_id, code, 1_u32, 0_u64);
- let original_message_id = account::("message", 0, 100).into_origin();
+ let caller = benchmarking::account("caller", 0, 0);
+ ::Currency::deposit_creating(&caller, 100_000_000_000_000_u128.unique_saturated_into());
+ let program_id = benchmarking::account::("program", 0, 100).into_origin();
+ let code = benchmarking::generate_wasm2(16_i32).unwrap();
+ benchmarking::set_program(program_id, code, 1_u32, 0_u64);
+ let original_message_id = benchmarking::account::("message", 0, 100).into_origin();
Gear::::insert_to_mailbox(
caller.clone().into_origin(),
common::QueuedMessage {
@@ -234,9 +106,9 @@ benchmarks! {
initial_allocation {
let q in 1 .. MAX_PAGES;
- let caller: T::AccountId = account("caller", 0, 0);
- T::Currency::deposit_creating(&caller, (1u128 << 60).unique_saturated_into());
- let code = generate_wasm(q).unwrap();
+ let caller: T::AccountId = benchmarking::account("caller", 0, 0);
+ ::Currency::deposit_creating(&caller, (1u128 << 60).unique_saturated_into());
+ let code = benchmarking::generate_wasm(q).unwrap();
let salt = vec![255u8; 32];
}: {
let _ = crate::Pallet::::submit_program(RawOrigin::Signed(caller).into(), code, salt, vec![], 100_000_000u64, 0u32.into());
@@ -248,9 +120,9 @@ benchmarks! {
alloc_in_handle {
let q in 0 .. MAX_PAGES;
- let caller: T::AccountId = account("caller", 0, 0);
- T::Currency::deposit_creating(&caller, (1_u128 << 60).unique_saturated_into());
- let code = generate_wasm2(q as i32).unwrap();
+ let caller: T::AccountId = benchmarking::account("caller", 0, 0);
+ ::Currency::deposit_creating(&caller, (1_u128 << 60).unique_saturated_into());
+ let code = benchmarking::generate_wasm2(q as i32).unwrap();
let salt = vec![255u8; 32];
}: {
let _ = crate::Pallet::::submit_program(RawOrigin::Signed(caller).into(), code, salt, vec![], 100_000_000u64, 0u32.into());
diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs
index 15e8844ba03..36de01db6f5 100644
--- a/pallets/gear/src/lib.rs
+++ b/pallets/gear/src/lib.rs
@@ -37,6 +37,8 @@ mod tests;
pub type Authorship = pallet_authorship::Pallet;
+use pallet_gear_program::Pallet as GearProgramPallet;
+
pub trait DebugInfo {
fn is_remap_id_enabled() -> bool;
fn remap_id();
@@ -70,7 +72,7 @@ pub mod pallet {
use frame_support::{
dispatch::{DispatchError, DispatchResultWithPostInfo},
pallet_prelude::*,
- traits::{BalanceStatus, Currency, Get, ReservableCurrency},
+ traits::{BalanceStatus, Currency, Get, LockableCurrency, ReservableCurrency},
};
use frame_system::pallet_prelude::*;
use gear_backend_sandbox::SandboxEnvironment;
@@ -86,13 +88,16 @@ pub mod pallet {
#[pallet::config]
pub trait Config:
- frame_system::Config + pallet_authorship::Config + pallet_timestamp::Config
+ frame_system::Config
+ + pallet_authorship::Config
+ + pallet_timestamp::Config
+ + pallet_gear_program::Config::Currency>
{
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type Event: From> + IsType<::Event>;
/// Gas and value transfer currency
- type Currency: Currency + ReservableCurrency;
+ type Currency: LockableCurrency + ReservableCurrency;
/// Gas to Currency converter
type GasPrice: GasPrice>;
@@ -315,7 +320,7 @@ pub mod pallet {
if message.value > 0 {
// Assuming the programs has enough balance
- T::Currency::repatriate_reserved(
+ ::Currency::repatriate_reserved(
&::from_origin(message.source),
user_id,
message.value.unique_saturated_into(),
@@ -334,7 +339,8 @@ pub mod pallet {
timestamp: >::get().unique_saturated_into(),
};
- let existential_deposit = T::Currency::minimum_balance().unique_saturated_into();
+ let existential_deposit =
+ ::Currency::minimum_balance().unique_saturated_into();
let (dest, reply) = match kind {
HandleKind::Init(ref code) => (CodeHash::generate(code).into_origin(), None),
@@ -449,7 +455,8 @@ pub mod pallet {
timestamp: >::get().unique_saturated_into(),
};
- let existential_deposit = T::Currency::minimum_balance().unique_saturated_into();
+ let existential_deposit =
+ ::Currency::minimum_balance().unique_saturated_into();
if T::DebugInfo::is_remap_id_enabled() {
T::DebugInfo::remap_id();
@@ -473,15 +480,15 @@ pub mod pallet {
break;
}
- let maybe_active_actor = {
- let program_id = dispatch.message.dest;
+ let program_id = dispatch.message.dest;
+ let maybe_active_actor = if let Some(maybe_active_program) =
+ common::get_program(program_id)
+ {
let current_message_id = dispatch.message.id;
let maybe_message_reply = dispatch.message.reply;
- let maybe_program = common::get_program(program_id);
-
// Check whether message should be added to the wait list
- if let Some(Program::Active(ref prog)) = maybe_program {
+ if let Program::Active(ref prog) = maybe_active_program {
let is_for_wait_list = maybe_message_reply.is_none()
&& matches!(prog.state, ProgramState::Uninitialized {message_id} if message_id != current_message_id);
if is_for_wait_list {
@@ -498,16 +505,19 @@ pub mod pallet {
}
}
- maybe_program
- .and_then(|prog| prog.try_into_native(program_id).ok())
+ maybe_active_program
+ .try_into_native(program_id)
+ .ok()
.map(|program| {
- let balance = T::Currency::free_balance(
+ let balance = ::Currency::free_balance(
&::from_origin(program_id),
)
.unique_saturated_into();
ExecutableActor { program, balance }
})
+ } else {
+ None
};
let journal = core_processor::process::<
@@ -669,7 +679,7 @@ pub mod pallet {
// Make sure there is no program with such id in program storage
ensure!(
- !common::program_exists(id.into_origin()),
+ !GearProgramPallet::::program_exists(id.into_origin()),
Error::::ProgramAlreadyExists
);
@@ -682,7 +692,7 @@ pub mod pallet {
// First we reserve enough funds on the account to pay for `gas_limit`
// and to transfer declared value.
- T::Currency::reserve(&who, reserve_fee + value)
+ ::Currency::reserve(&who, reserve_fee + value)
.map_err(|_| Error::::NotEnoughBalanceForReserve)?;
let origin = who.into_origin();
@@ -747,7 +757,7 @@ pub mod pallet {
let who = ensure_signed(origin)?;
let numeric_value: u128 = value.unique_saturated_into();
- let minimum: u128 = T::Currency::minimum_balance().unique_saturated_into();
+ let minimum: u128 = ::Currency::minimum_balance().unique_saturated_into();
// Check that provided `gas_limit` value does not exceed the block gas limit
ensure!(
@@ -771,14 +781,14 @@ pub mod pallet {
// Message is not guaranteed to be executed, that's why value is not immediately transferred.
// That's because destination can fail to be initialized, while this dispatch message is next
// in the queue.
- T::Currency::reserve(&who, value.unique_saturated_into())
+ ::Currency::reserve(&who, value.unique_saturated_into())
.map_err(|_| Error::::NotEnoughBalanceForReserve)?;
- if common::program_exists(destination) {
+ if GearProgramPallet::::program_exists(destination) {
let gas_limit_reserve = T::GasPrice::gas_price(gas_limit);
// First we reserve enough funds on the account to pay for `gas_limit`
- T::Currency::reserve(&who, gas_limit_reserve)
+ ::Currency::reserve(&who, gas_limit_reserve)
.map_err(|_| Error::::NotEnoughBalanceForReserve)?;
let origin = who.into_origin();
@@ -843,7 +853,7 @@ pub mod pallet {
let who = ensure_signed(origin)?;
let numeric_value: u128 = value.unique_saturated_into();
- let minimum: u128 = T::Currency::minimum_balance().unique_saturated_into();
+ let minimum: u128 = ::Currency::minimum_balance().unique_saturated_into();
// Ensure the `gas_limit` allows the extrinsic to fit into a block
ensure!(
@@ -864,16 +874,16 @@ pub mod pallet {
// Message is not guaranteed to be executed, that's why value is not immediately transferred.
// That's because destination can fail to be initialized, while this dispatch message is next
// in the queue.
- T::Currency::reserve(&who, value.unique_saturated_into())
+ ::Currency::reserve(&who, value.unique_saturated_into())
.map_err(|_| Error::::NotEnoughBalanceForReserve)?;
let message_id = common::next_message_id(&payload);
- if common::program_exists(destination) {
+ if GearProgramPallet::::program_exists(destination) {
let gas_limit_reserve = T::GasPrice::gas_price(gas_limit);
// First we reserve enough funds on the account to pay for `gas_limit`
- T::Currency::reserve(&who, gas_limit_reserve)
+ ::Currency::reserve(&who, gas_limit_reserve)
.map_err(|_| Error::::NotEnoughBalanceForReserve)?;
let origin = who.into_origin();
@@ -934,6 +944,7 @@ pub mod pallet {
pub fn reset(origin: OriginFor) -> DispatchResult {
ensure_root(origin)?;
>::remove_all(None);
+ GearProgramPallet::::reset_storage();
common::reset_storage();
Self::deposit_event(Event::DatabaseWiped);
@@ -953,7 +964,7 @@ pub mod pallet {
dest: &T::AccountId,
amount: Self::Balance,
) -> Result<(), DispatchError> {
- let _ = T::Currency::repatriate_reserved(
+ let _ = ::Currency::repatriate_reserved(
&::from_origin(source),
dest,
amount,
diff --git a/pallets/gear/src/manager.rs b/pallets/gear/src/manager.rs
index 381ed68729f..1aafb2767a6 100644
--- a/pallets/gear/src/manager.rs
+++ b/pallets/gear/src/manager.rs
@@ -17,8 +17,8 @@
// along with this program. If not, see .
use crate::{
- pallet::Reason, Authorship, Config, DispatchOutcome, Event, ExecutionResult, MessageInfo,
- Pallet,
+ pallet::Reason, Authorship, Config, DispatchOutcome, Event, ExecutionResult, GearProgramPallet,
+ MessageInfo, Pallet,
};
use codec::{Decode, Encode};
use common::{DAGBasedLedger, GasPrice, Origin, Program, QueuedDispatch, STORAGE_PROGRAM_PREFIX};
@@ -132,8 +132,9 @@ where
let program = common::get_program(id)
.and_then(|prog_with_status| prog_with_status.try_into_native(id).ok())?;
- let balance = T::Currency::free_balance(&::from_origin(id))
- .unique_saturated_into();
+ let balance =
+ ::Currency::free_balance(&::from_origin(id))
+ .unique_saturated_into();
Some(ExecutableActor { program, balance })
}
@@ -298,7 +299,7 @@ where
if let Some((_, origin)) = T::GasHandler::get_limit(message_id) {
let charge = T::GasPrice::gas_price(amount);
if let Some(author) = Authorship::::author() {
- let _ = T::Currency::repatriate_reserved(
+ let _ = ::Currency::repatriate_reserved(
&::from_origin(origin),
&author,
charge,
@@ -335,9 +336,9 @@ where
assert!(res.is_ok(), "`exit` can be called only from active program");
let program_account = &::from_origin(program_id);
- let balance = T::Currency::total_balance(program_account);
+ let balance = ::Currency::total_balance(program_account);
if !balance.is_zero() {
- T::Currency::transfer(
+ ::Currency::transfer(
program_account,
&::from_origin(value_destination.into_origin()),
balance,
@@ -356,8 +357,10 @@ where
let refund = T::GasPrice::gas_price(gas_left);
- let _ =
- T::Currency::unreserve(&::from_origin(external), refund);
+ let _ = ::Currency::unreserve(
+ &::from_origin(external),
+ refund,
+ );
}
}
@@ -366,7 +369,7 @@ where
let (gas_limit, dispatch) = QueuedDispatch::without_gas_limit(dispatch);
if dispatch.message.value != 0
- && T::Currency::reserve(
+ && ::Currency::reserve(
&::from_origin(dispatch.message.source),
dispatch.message.value.unique_saturated_into(),
)
@@ -386,10 +389,11 @@ where
message_id
);
- if common::program_exists(dispatch.message.dest)
+ let destination = dispatch.message.dest;
+ if GearProgramPallet::::program_exists(destination)
|| self
.marked_destinations
- .contains(&ProgramId::from_origin(dispatch.message.dest))
+ .contains(&ProgramId::from_origin(destination))
{
if let Some(gas_limit) = gas_limit {
let _ =
@@ -402,7 +406,7 @@ where
// Being placed into a user's mailbox means the end of a message life cycle.
// There can be no further processing whatsoever, hence any gas attempted to be
// passed along must be returned (i.e. remain in the parent message's value tree).
- Pallet::::insert_to_mailbox(dispatch.message.dest, dispatch.message.clone());
+ Pallet::::insert_to_mailbox(destination, dispatch.message.clone());
Pallet::::deposit_event(Event::Log(dispatch.message));
}
}
@@ -444,7 +448,7 @@ where
if let Some((_, origin)) = T::GasHandler::get_limit(message_id.into_origin()) {
let charge = T::GasPrice::gas_price(chargeable_amount);
if let Some(author) = Authorship::::author() {
- let _ = T::Currency::repatriate_reserved(
+ let _ = ::Currency::repatriate_reserved(
&::from_origin(origin),
&author,
charge,
@@ -525,17 +529,18 @@ where
);
let from = ::from_origin(from);
let to = ::from_origin(to);
- if T::Currency::can_reserve(&to, T::Currency::minimum_balance()) {
+ if ::Currency::can_reserve(&to, ::Currency::minimum_balance())
+ {
// `to` account exists, so we can repatriate reserved value for it.
- let _ = T::Currency::repatriate_reserved(
+ let _ = ::Currency::repatriate_reserved(
&from,
&to,
value.unique_saturated_into(),
BalanceStatus::Free,
);
} else {
- T::Currency::unreserve(&from, value.unique_saturated_into());
- let _ = T::Currency::transfer(
+ ::Currency::unreserve(&from, value.unique_saturated_into());
+ let _ = ::Currency::transfer(
&from,
&to,
value.unique_saturated_into(),
@@ -545,7 +550,7 @@ where
} else {
log::debug!("Value unreserve of amount {:?} from {:?}", value, from,);
let from = ::from_origin(from);
- T::Currency::unreserve(&from, value.unique_saturated_into());
+ ::Currency::unreserve(&from, value.unique_saturated_into());
}
}
@@ -554,7 +559,7 @@ where
if let Some(code) = common::get_code(code_hash) {
for (candidate_id, init_message) in candidates {
- if !common::program_exists(candidate_id.into_origin()) {
+ if !GearProgramPallet::::program_exists(candidate_id.into_origin()) {
// Code hash for invalid code can't be added to the storage from extrinsics.
let new_program = NativeProgram::new(candidate_id, code.clone())
.expect("guaranteed to be valid");
diff --git a/pallets/gear/src/mock.rs b/pallets/gear/src/mock.rs
index 0d51df1f92e..5c97d0e33a4 100644
--- a/pallets/gear/src/mock.rs
+++ b/pallets/gear/src/mock.rs
@@ -44,6 +44,7 @@ construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: system::{Pallet, Call, Config, Storage, Event},
+ GearProgram: pallet_gear_program::{Pallet, Storage, Event},
Gear: pallet_gear::{Pallet, Call, Storage, Event},
Gas: pallet_gas::{Pallet, Storage},
Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
@@ -102,6 +103,12 @@ impl common::GasPrice for GasConverter {
type Balance = u128;
}
+impl pallet_gear_program::Config for Test {
+ type Event = Event;
+ type WeightInfo = ();
+ type Currency = Balances;
+}
+
parameter_types! {
pub const BlockGasLimit: u64 = 100_000_000;
pub const WaitListFeePerBlock: u64 = 1_000;
diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs
index 13ea0c4c841..c738949f961 100644
--- a/pallets/gear/src/tests.rs
+++ b/pallets/gear/src/tests.rs
@@ -28,11 +28,11 @@ use tests_program_factory::{CreateProgram, WASM_BINARY as PROGRAM_FACTORY_WASM_B
use super::{
manager::HandleKind,
mock::{
- new_test_ext, run_to_block, Event as MockEvent, Gear, Origin, System, Test, BLOCK_AUTHOR,
- LOW_BALANCE_USER, USER_1, USER_2, USER_3,
+ new_test_ext, run_to_block, Event as MockEvent, Gear, GearProgram, Origin, System, Test,
+ BLOCK_AUTHOR, LOW_BALANCE_USER, USER_1, USER_2, USER_3,
},
- pallet, Config, DispatchOutcome, Error, Event, ExecutionResult, GasAllowance, Mailbox,
- MessageInfo, Pallet as GearPallet, Reason,
+ pallet, Config, DispatchOutcome, Error, Event, ExecutionResult, GasAllowance,
+ GearProgramPallet, Mailbox, MessageInfo, Pallet as GearPallet, Reason,
};
use utils::*;
@@ -1267,18 +1267,7 @@ fn messages_to_uninitialized_program_wait() {
0u128
));
- let event = match SystemPallet::::events()
- .last()
- .map(|r| r.event.clone())
- {
- Some(MockEvent::Gear(e)) => e,
- _ => unreachable!("Should be one Gear event"),
- };
-
- let MessageInfo { program_id, .. } = match event {
- Event::InitMessageEnqueued(info) => info,
- _ => unreachable!("expect Event::InitMessageEnqueued"),
- };
+ let program_id = utils::get_last_program_id();
assert!(!Gear::is_initialized(program_id));
assert!(!Gear::is_terminated(program_id));
@@ -1319,18 +1308,7 @@ fn uninitialized_program_should_accept_replies() {
0u128
));
- let event = match SystemPallet::::events()
- .last()
- .map(|r| r.event.clone())
- {
- Some(MockEvent::Gear(e)) => e,
- _ => unreachable!("Should be one Gear event"),
- };
-
- let MessageInfo { program_id, .. } = match event {
- Event::InitMessageEnqueued(info) => info,
- _ => unreachable!("expect Event::InitMessageEnqueued"),
- };
+ let program_id = utils::get_last_program_id();
assert!(!Gear::is_initialized(program_id));
assert!(!Gear::is_terminated(program_id));
@@ -1381,18 +1359,7 @@ fn defer_program_initialization() {
0u128
));
- let event = match SystemPallet::::events()
- .last()
- .map(|r| r.event.clone())
- {
- Some(MockEvent::Gear(e)) => e,
- _ => unreachable!("Should be one Gear event"),
- };
-
- let MessageInfo { program_id, .. } = match event {
- Event::InitMessageEnqueued(info) => info,
- _ => unreachable!("expect Event::InitMessageEnqueued"),
- };
+ let program_id = utils::get_last_program_id();
run_to_block(2, None);
@@ -1456,18 +1423,7 @@ fn wake_messages_after_program_inited() {
0u128
));
- let event = match SystemPallet::::events()
- .last()
- .map(|r| r.event.clone())
- {
- Some(MockEvent::Gear(e)) => e,
- _ => unreachable!("Should be one Gear event"),
- };
-
- let MessageInfo { program_id, .. } = match event {
- Event::InitMessageEnqueued(info) => info,
- _ => unreachable!("expect Event::InitMessageEnqueued"),
- };
+ let program_id = utils::get_last_program_id();
run_to_block(2, None);
@@ -2109,6 +2065,276 @@ fn exit_handle() {
})
}
+#[test]
+fn paused_program_keeps_id() {
+ use tests_init_wait::WASM_BINARY;
+
+ init_logger();
+ new_test_ext().execute_with(|| {
+ System::reset_events();
+
+ let code = WASM_BINARY.to_vec();
+ assert_ok!(GearPallet::::submit_program(
+ Origin::signed(USER_1).into(),
+ code.clone(),
+ vec![],
+ Vec::new(),
+ 100_000_000u64,
+ 0u128
+ ));
+
+ let program_id = utils::get_last_program_id();
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ assert_noop!(
+ GearPallet::::submit_program(
+ Origin::signed(USER_3).into(),
+ code.clone(),
+ vec![],
+ Vec::new(),
+ 100_000_000u64,
+ 0u128
+ ),
+ Error::::ProgramAlreadyExists
+ );
+
+ assert!(!Gear::is_initialized(program_id));
+ assert!(!Gear::is_terminated(program_id));
+ })
+}
+
+#[test]
+fn messages_to_paused_program_skipped() {
+ use tests_init_wait::WASM_BINARY;
+
+ init_logger();
+ new_test_ext().execute_with(|| {
+ System::reset_events();
+
+ let code = WASM_BINARY.to_vec();
+ assert_ok!(GearPallet::::submit_program(
+ Origin::signed(USER_1).into(),
+ code.clone(),
+ vec![],
+ Vec::new(),
+ 100_000_000u64,
+ 0u128
+ ));
+
+ let program_id = utils::get_last_program_id();
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ let before_balance = BalancesPallet::::free_balance(USER_3);
+
+ assert_ok!(GearPallet::::send_message(
+ Origin::signed(USER_3).into(),
+ program_id,
+ vec![],
+ 100_000_000u64,
+ 1000u128
+ ));
+
+ run_to_block(3, None);
+
+ assert_eq!(before_balance, BalancesPallet::::free_balance(USER_3));
+ })
+}
+
+#[test]
+fn replies_to_paused_program_skipped() {
+ use tests_init_wait::WASM_BINARY;
+
+ init_logger();
+ new_test_ext().execute_with(|| {
+ System::reset_events();
+
+ let code = WASM_BINARY.to_vec();
+ assert_ok!(GearPallet::::submit_program(
+ Origin::signed(USER_1).into(),
+ code.clone(),
+ vec![],
+ Vec::new(),
+ 100_000_000u64,
+ 0u128
+ ));
+
+ let program_id = utils::get_last_program_id();
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ run_to_block(3, None);
+
+ let message_id = Gear::mailbox(USER_1).and_then(|t| {
+ let mut keys = t.keys();
+ keys.next().cloned()
+ });
+ assert!(message_id.is_some());
+
+ let before_balance = BalancesPallet::::free_balance(USER_1);
+
+ assert_ok!(GearPallet::::send_reply(
+ Origin::signed(USER_1).into(),
+ message_id.unwrap(),
+ b"PONG".to_vec(),
+ 50_000_000u64,
+ 1000u128,
+ ));
+
+ run_to_block(4, None);
+
+ assert_eq!(before_balance, BalancesPallet::::free_balance(USER_1));
+ })
+}
+
+#[test]
+fn program_messages_to_paused_program_skipped() {
+ use tests_init_wait::WASM_BINARY;
+ use tests_proxy::{InputArgs, WASM_BINARY as PROXY_WASM_BINARY};
+
+ init_logger();
+ new_test_ext().execute_with(|| {
+ System::reset_events();
+
+ let code = WASM_BINARY.to_vec();
+ assert_ok!(GearPallet::::submit_program(
+ Origin::signed(USER_1).into(),
+ code.clone(),
+ vec![],
+ Vec::new(),
+ 100_000_000u64,
+ 0u128
+ ));
+
+ let paused_program_id = utils::get_last_program_id();
+
+ let code = PROXY_WASM_BINARY.to_vec();
+ assert_ok!(GearPallet::::submit_program(
+ Origin::signed(USER_3).into(),
+ code.clone(),
+ vec![],
+ InputArgs {
+ destination: paused_program_id.into()
+ }
+ .encode(),
+ 100_000_000u64,
+ 1_000u128
+ ));
+
+ let program_id = utils::get_last_program_id();
+
+ run_to_block(2, None);
+
+ assert_ok!(GearProgram::pause_program(paused_program_id));
+
+ run_to_block(3, None);
+
+ assert_ok!(GearPallet::::send_message(
+ Origin::signed(USER_3).into(),
+ program_id,
+ vec![],
+ 100_000_000u64,
+ 1_000u128
+ ));
+
+ run_to_block(4, None);
+
+ assert_eq!(
+ 2_000u128,
+ BalancesPallet::::free_balance(
+ &::from_origin(program_id)
+ )
+ );
+ })
+}
+
+#[test]
+fn resume_program_works() {
+ use tests_init_wait::WASM_BINARY;
+
+ init_logger();
+ new_test_ext().execute_with(|| {
+ System::reset_events();
+
+ let code = WASM_BINARY.to_vec();
+ assert_ok!(GearPallet::::submit_program(
+ Origin::signed(USER_1).into(),
+ code.clone(),
+ vec![],
+ Vec::new(),
+ 100_000_000u64,
+ 0u128
+ ));
+
+ let program_id = utils::get_last_program_id();
+
+ run_to_block(2, None);
+
+ let message_id = Gear::mailbox(USER_1).and_then(|t| {
+ let mut keys = t.keys();
+ keys.next().cloned()
+ });
+ assert!(message_id.is_some());
+
+ assert_ok!(GearPallet::::send_reply(
+ Origin::signed(USER_1).into(),
+ message_id.unwrap(),
+ b"PONG".to_vec(),
+ 50_000_000u64,
+ 1_000u128,
+ ));
+
+ run_to_block(3, None);
+
+ let program = match common::get_program(program_id).expect("program exists") {
+ common::Program::Active(p) => p,
+ _ => unreachable!(),
+ };
+ let memory_pages = common::get_program_pages(program_id, program.persistent_pages)
+ .expect("program exists, so do pages");
+
+ assert_ok!(GearProgram::pause_program(program_id));
+
+ run_to_block(4, None);
+
+ assert_ok!(GearProgramPallet::::resume_program(
+ Origin::signed(USER_3).into(),
+ program_id,
+ memory_pages,
+ Default::default(),
+ 10_000u128
+ ));
+
+ assert_ok!(GearPallet::::send_message(
+ Origin::signed(USER_3).into(),
+ program_id,
+ vec![],
+ 25_000_000u64,
+ 0u128
+ ));
+
+ run_to_block(5, None);
+
+ let actual_n = Gear::mailbox(USER_3)
+ .map(|t| {
+ t.into_values().fold(0usize, |i, m| {
+ assert_eq!(m.payload, b"Hello, world!".encode());
+ i + 1
+ })
+ })
+ .unwrap_or(0);
+
+ assert_eq!(actual_n, 1);
+ })
+}
+
mod utils {
use codec::Encode;
use frame_support::dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo};
diff --git a/pallets/gear/src/weights.rs b/pallets/gear/src/weights.rs
index 4b1a160f66f..7acada8ab23 100644
--- a/pallets/gear/src/weights.rs
+++ b/pallets/gear/src/weights.rs
@@ -16,11 +16,11 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-//! Autogenerated weights for pallet_gear
+//! Autogenerated weights for `pallet_gear`
//!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
-//! DATE: 2021-08-25, STEPS: `[50, ]`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
-//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("local"), DB CACHE: 128
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
+//! DATE: 2022-02-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("local"), DB CACHE: 1024
// Executed Command:
// ./target/release/gear-node
@@ -29,86 +29,580 @@
// --execution=wasm
// --wasm-execution=compiled
// --pallet=pallet_gear
-// --extrinsic='*'
// --steps
// 50
// --repeat
// 20
// --output
// .
+// --extrinsic=*
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
use frame_support::{
- traits::Get,
- weights::{constants::RocksDbWeight, Weight},
+ traits::Get,
+ weights::{constants::RocksDbWeight, Weight},
};
use sp_std::marker::PhantomData;
/// Weight functions for pallet_gear.
pub trait WeightInfo {
- fn submit_code(c: u32) -> Weight;
- fn submit_program(c: u32, p: u32) -> Weight;
- fn send_message(p: u32) -> Weight;
- fn send_reply(p: u32) -> Weight;
+ fn submit_code(c: u32) -> Weight;
+ fn submit_program(c: u32, p: u32) -> Weight;
+ fn send_message(p: u32) -> Weight;
+ fn send_reply(p: u32) -> Weight;
}
+/// Weight functions for `pallet_gear`.
pub struct GearWeight(PhantomData);
impl WeightInfo for GearWeight {
- fn submit_code(c: u32) -> Weight {
- (17_289_000_u64)
- .saturating_add((1_000_u64).saturating_mul(c as Weight))
- .saturating_add(T::DbWeight::get().reads(1_u64))
- .saturating_add(T::DbWeight::get().writes(1_u64))
- }
-
- fn submit_program(c: u32, p: u32) -> Weight {
- (200_000_000_u64)
- .saturating_add((5_000_u64).saturating_mul(c as Weight))
- .saturating_add((5_000_u64).saturating_mul(p as Weight))
- .saturating_add(T::DbWeight::get().reads(4_u64))
- .saturating_add(T::DbWeight::get().writes(3_u64))
- }
-
- fn send_message(p: u32) -> Weight {
- (160_000_000_u64)
- .saturating_add((6_000_u64).saturating_mul(p as Weight))
- .saturating_add(T::DbWeight::get().reads(5_u64))
- .saturating_add(T::DbWeight::get().writes(4_u64))
- }
-
- fn send_reply(p: u32) -> Weight {
- (170_000_000_u64)
- .saturating_add((6_000_u64).saturating_mul(p as Weight))
- .saturating_add(T::DbWeight::get().reads(5_u64))
- .saturating_add(T::DbWeight::get().writes(5_u64))
- }
+ // Storage: unknown [0x673a3a636f64653a3ac9cc4c0689648a67c955143538b059c3522b99d4b3f4d4] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ac9cc4c0689648a67c955143538] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a7587bd872c774944a17e23b62e833d1958a4f947699c24] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a7587bd872c774944a17e23b62e] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a8923f0218f97fe793b9b7156b6dc3340e504036d40832a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a8923f0218f97fe793b9b7156b6] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a91e93c9050948319c98a0afb4370067915951b1d77a5d0] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a91e93c9050948319c98a0afb43] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ab989b1a047aad6c6696163cae14c434667e0709d554573] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab989b1a047aad6c6696163cae1] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3add349d2edb2feb38ae9a53b857bc960e79bb8dfc836097] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3add349d2edb2feb38ae9a53b857] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a767db7f1520a3b28964bf5a9801c57ad91703c1376014f] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a767db7f1520a3b28964bf5a980] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ae95634a640361cabe2a5c7e62976f0c41d9f2bc98eb4ee] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ae95634a640361cabe2a5c7e629] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ab7eab7925022c836e27c1551089891f85cb71d18d56a32] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab7eab7925022c836e27c155108] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3adf9b2dd3cd87b923039a2c25a2ae720cbcc4bd0efb8c3f] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3adf9b2dd3cd87b923039a2c25a2] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a485bf54cf8489305f0edc2e78793c43ba768d9305c7bb1] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a485bf54cf8489305f0edc2e787] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a534428c3d767f8ea2ca19380781ceaad4855e7f7a5e4f7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a534428c3d767f8ea2ca1938078] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ae1963c24744a86dac3013d8629255a29eb21db345b52cb] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ae1963c24744a86dac3013d8629] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a38479aa6ab8b9fcd96be87a161d5cdfd33efa2cfa41332] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a38479aa6ab8b9fcd96be87a161] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a9d358e3ec3d820aae2dde1f1417ce41b91a069813ea8c8] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a9d358e3ec3d820aae2dde1f141] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a0fabd078b4860c0cbb5f32860f8f61f4546e475a8da5a7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a0fabd078b4860c0cbb5f32860f] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ab8b600fc2f9378bd1732f19e6ffd0a8e8d81efa7c0df72] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab8b600fc2f9378bd1732f19e6f] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a5891990588de1d32dcba9c1303771c17bb372b9fd440a5] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5891990588de1d32dcba9c1303] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a3e0e4f9dd93be6d99fc9df63e2689689486fe325d7370b] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a3e0e4f9dd93be6d99fc9df63e2] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3acf933bd36643b6584d5b820c7ce4e0233f5c5de39dc1dc] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3acf933bd36643b6584d5b820c7c] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3af32325bf3bb7402a9ec60eb0e60dc662a425d1a7d33f07] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3af32325bf3bb7402a9ec60eb0e6] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3aff6a42141c69663e8b3b4384f8629bc21b12dacb84a617] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aff6a42141c69663e8b3b4384f8] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a44f39939d8d4435693e0596f2b1bd67f5d18e7d4870984] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a44f39939d8d4435693e0596f2b] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a2fe31b4c3d02326cd7d1ed09f242f0b8d058875223c452] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a2fe31b4c3d02326cd7d1ed09f2] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a861139ea34d3021d46e86da7a365d739f8a100032745b9] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a861139ea34d3021d46e86da7a3] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3afc74ae020a611048571dd6ba1659adff666e6c0847e9be] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3afc74ae020a611048571dd6ba16] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a310ee166c31f4f70ba738892e0981f9a2c9c067cb8dd6a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a310ee166c31f4f70ba738892e0] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ae67a81768a0934a97c511829d125a550271d6418b1867a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ae67a81768a0934a97c511829d1] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a3c0cb0b280a082d9786b0ad21bb60e412f38d1bb0409d4] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a3c0cb0b280a082d9786b0ad21b] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a36cccd720e5c737815c9da7a6959e8bdc059a35882de83] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a36cccd720e5c737815c9da7a69] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a5174704d3a61ef516278e5ad373eb332b62a8218c80fb8] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5174704d3a61ef516278e5ad37] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3aa15b86be5bec9f5231c60ed0fc8f6fefd65231aa0cfffd] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aa15b86be5bec9f5231c60ed0fc] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a2e6ec4391107dcafc3c046462a2ad3f9a78a36a111424f] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a2e6ec4391107dcafc3c046462a] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a1c1005bab4ab1fa306652ec3a33f0a2b269af07310c2a7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a1c1005bab4ab1fa306652ec3a3] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3aaafa9cc7b0008e26947ca47e3737887d67a9ae5b5646d3] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aaafa9cc7b0008e26947ca47e37] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a4a9d7be33b48393a2f3c1e5f2fd9af4be5e71de646c64d] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a4a9d7be33b48393a2f3c1e5f2f] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3aafcee95a8836c4477426fe0319a6a72f019fe07bc91a7a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aafcee95a8836c4477426fe0319] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a4958004a5bc5311052bd125f67ac0ebf2ee367ea79ee9b] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a4958004a5bc5311052bd125f67] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3af81de216441b17aefe48e94b5cfd111b83046330b4302e] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3af81de216441b17aefe48e94b5c] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ac1f1fe2d0437406ac3fa2777b76104958e38894e96211d] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ac1f1fe2d0437406ac3fa2777b7] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ab55852db1ba113fc8a9f391ecdaf84b690f1265b4e813c] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab55852db1ba113fc8a9f391ecd] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a64935351a68fbfd2d392d8dfaedaa8bc01d1f0e9a50a99] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a64935351a68fbfd2d392d8dfae] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a38fab0241e1a5ef738d73ba5acee5c3815f50a0a0d96a7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a38fab0241e1a5ef738d73ba5ac] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6ca822d162722dd0e4606a35ba098a44a289aa8bd959bd] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a6ca822d162722dd0e4606a35ba] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a5f365cf401bc9ce25862d7b2e884a64d43161cc26f7ce0] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5f365cf401bc9ce25862d7b2e8] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3abff7e68243e56af80e189657c6602dd8c43f19b0fcfb7c] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3abff7e68243e56af80e189657c6] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a9787170a91d30f935b8cf180cc6b43ec5cb9e97309d449] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a9787170a91d30f935b8cf180cc] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a5fe949460a655945d5ab38ab18e0b507322c52db80d4df] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5fe949460a655945d5ab38ab18] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a71927a87aa91cbf4e336418c036f450de11e831da5dcf7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a71927a87aa91cbf4e336418c03] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3abb443f78b6b1016408a2e194aa3ea4ec4978a7d7416caa] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3abb443f78b6b1016408a2e194aa] (r:0 w:1)
+ // Storage: unknown [0x673a3a636f64653a3afda0ad7c1b0733865c5d2de8d7e965359c140b43a55934] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3afda0ad7c1b0733865c5d2de8d7] (r:0 w:1)
+ fn submit_code(c: u32, ) -> Weight {
+ (27_434_000u32 as Weight)
+ // Standard Error: 0
+ .saturating_add((2_000u32 as Weight).saturating_mul(c as Weight))
+ .saturating_add(T::DbWeight::get().reads(1u32 as Weight))
+ .saturating_add(T::DbWeight::get().writes(2u32 as Weight))
+ }
+ // Storage: unknown [0x673a3a70726f673a3a67e342cacbd4e7809eb9498740b407c0bd24f18b77b3cf] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a67e342cacbd4e7809eb9498740b407c0] (r:1 w:0)
+ // Storage: System Account (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3ac9cc4c0689648a67c955143538b059c3522b99d4b3f4d4] (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a6e6f6e6365] (r:1 w:1)
+ // Storage: Gas ValueView (r:1 w:1)
+ // Storage: Gas TotalIssuance (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a68656164] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ac9cc4c0689648a67c955143538] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7461696c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aa65799c2efdac02e971c1e79a342b334afa3089b3fee3867] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a474dab32081a2c2deb31b7930866f2903f3af1c95fdc98] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a474dab32081a2c2deb31b7930866f290] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a7587bd872c774944a17e23b62e833d1958a4f947699c24] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a7587bd872c774944a17e23b62e] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a9ff48c8eed03a69ab9c3dfcd37fb11e471a90825058b39] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a9ff48c8eed03a69ab9c3dfcd37fb11e4] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a8923f0218f97fe793b9b7156b6dc3340e504036d40832a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a8923f0218f97fe793b9b7156b6] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a02ba1a898ad5d93fff57505441f504fe86b84802a14d90] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a02ba1a898ad5d93fff57505441f504fe] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a91e93c9050948319c98a0afb4370067915951b1d77a5d0] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a91e93c9050948319c98a0afb43] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3af69cc42a055e8b200f3069144d1f6b06fec08015251c58] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3af69cc42a055e8b200f3069144d1f6b06] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ab989b1a047aad6c6696163cae14c434667e0709d554573] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab989b1a047aad6c6696163cae1] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a0121e5a746c7c9612987084e95852bd93f3ce9be69c7cd] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a0121e5a746c7c9612987084e95852bd9] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3add349d2edb2feb38ae9a53b857bc960e79bb8dfc836097] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3add349d2edb2feb38ae9a53b857] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a4a2ff82be3be2f920fc90b1d2ab0e4b527df2c88546506] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a4a2ff82be3be2f920fc90b1d2ab0e4b5] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a767db7f1520a3b28964bf5a9801c57ad91703c1376014f] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a767db7f1520a3b28964bf5a980] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a972e42704e6bbeaa7b89d26efa29f38804ee3ed20df57a] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a972e42704e6bbeaa7b89d26efa29f388] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ae95634a640361cabe2a5c7e62976f0c41d9f2bc98eb4ee] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ae95634a640361cabe2a5c7e629] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a4e326680f6bd5a66860f806281412bdd0d93707a8808f2] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a4e326680f6bd5a66860f806281412bdd] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ab7eab7925022c836e27c1551089891f85cb71d18d56a32] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab7eab7925022c836e27c155108] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a838a5966185d4ec12f8fb9a6d3b375e7600779da58751d] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a838a5966185d4ec12f8fb9a6d3b375e7] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3adf9b2dd3cd87b923039a2c25a2ae720cbcc4bd0efb8c3f] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3adf9b2dd3cd87b923039a2c25a2] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3ad629e77ddaa9d4ed54f596a03b234408a3090cb7aa67bd] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3ad629e77ddaa9d4ed54f596a03b234408] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a485bf54cf8489305f0edc2e78793c43ba768d9305c7bb1] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a485bf54cf8489305f0edc2e787] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a93eb010622a4b1035851394b13873c0bedf2273e301165] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a93eb010622a4b1035851394b13873c0b] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a534428c3d767f8ea2ca19380781ceaad4855e7f7a5e4f7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a534428c3d767f8ea2ca1938078] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3ae589755546f966d4f2e8c1864b3fcea6d65992eac53ed6] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3ae589755546f966d4f2e8c1864b3fcea6] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ae1963c24744a86dac3013d8629255a29eb21db345b52cb] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ae1963c24744a86dac3013d8629] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3aba8d8d317997cce7f489dc6a4e5f8538c15622dd761475] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3aba8d8d317997cce7f489dc6a4e5f8538] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a38479aa6ab8b9fcd96be87a161d5cdfd33efa2cfa41332] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a38479aa6ab8b9fcd96be87a161] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a5d8d1fa3ca68d239b83b87d41bca3ffdcbdb6ca9639f61] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a5d8d1fa3ca68d239b83b87d41bca3ffd] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a9d358e3ec3d820aae2dde1f1417ce41b91a069813ea8c8] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a9d358e3ec3d820aae2dde1f141] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a1486da6045cc9a7d14355b2c8bb50211dd844a3b8fbde3] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a1486da6045cc9a7d14355b2c8bb50211] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a0fabd078b4860c0cbb5f32860f8f61f4546e475a8da5a7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a0fabd078b4860c0cbb5f32860f] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a3580459e8f7aabc1fb79d171055d50c2ab15014b140d50] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a3580459e8f7aabc1fb79d171055d50c2] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ab8b600fc2f9378bd1732f19e6ffd0a8e8d81efa7c0df72] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab8b600fc2f9378bd1732f19e6f] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3ae374408744fd339474eadfff456c8b7e988e87d9b201d8] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3ae374408744fd339474eadfff456c8b7e] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a5891990588de1d32dcba9c1303771c17bb372b9fd440a5] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5891990588de1d32dcba9c1303] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a15589c230b9d8382409935b6c552e7b80010b485681ac1] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a15589c230b9d8382409935b6c552e7b8] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a3e0e4f9dd93be6d99fc9df63e2689689486fe325d7370b] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a3e0e4f9dd93be6d99fc9df63e2] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3afd1628cb071e5fff5c4b65a82394be58d2c2fffdd17770] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3afd1628cb071e5fff5c4b65a82394be58] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3acf933bd36643b6584d5b820c7ce4e0233f5c5de39dc1dc] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3acf933bd36643b6584d5b820c7c] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a0bd3ba5708b04f2ab3a83c31e0f89b84215f61b3321534] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a0bd3ba5708b04f2ab3a83c31e0f89b84] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3af32325bf3bb7402a9ec60eb0e60dc662a425d1a7d33f07] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3af32325bf3bb7402a9ec60eb0e6] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a58165dd25529c3adaef7e727bbf3c1acfbf001a9e71360] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a58165dd25529c3adaef7e727bbf3c1ac] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3aff6a42141c69663e8b3b4384f8629bc21b12dacb84a617] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aff6a42141c69663e8b3b4384f8] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a136d1d40ce4039c202917469735d8de87f2927282920b9] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a136d1d40ce4039c202917469735d8de8] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a44f39939d8d4435693e0596f2b1bd67f5d18e7d4870984] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a44f39939d8d4435693e0596f2b] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a027687f0cd49a71377ede6d85aebeefd70ee91f99b3d45] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a027687f0cd49a71377ede6d85aebeefd] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a2fe31b4c3d02326cd7d1ed09f242f0b8d058875223c452] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a2fe31b4c3d02326cd7d1ed09f2] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a91507fd62b606c287f741ef5a246c34d34103dcc664f49] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a91507fd62b606c287f741ef5a246c34d] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a861139ea34d3021d46e86da7a365d739f8a100032745b9] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a861139ea34d3021d46e86da7a3] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a9831a829e78aea842eb7a39f251b5a0e018bf82017fc88] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a9831a829e78aea842eb7a39f251b5a0e] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3afc74ae020a611048571dd6ba1659adff666e6c0847e9be] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3afc74ae020a611048571dd6ba16] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3ae6383233415e9dd73e3a5386785c498e69f758ea040dd2] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3ae6383233415e9dd73e3a5386785c498e] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a310ee166c31f4f70ba738892e0981f9a2c9c067cb8dd6a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a310ee166c31f4f70ba738892e0] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a702b1dc288d12157078c46b21cebbcf85eb25b505f6de6] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a702b1dc288d12157078c46b21cebbcf8] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ae67a81768a0934a97c511829d125a550271d6418b1867a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ae67a81768a0934a97c511829d1] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3af7606fa5f9eb2b3b2d44bc8831b8875efaabc67e619ef7] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3af7606fa5f9eb2b3b2d44bc8831b8875e] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a3c0cb0b280a082d9786b0ad21bb60e412f38d1bb0409d4] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a3c0cb0b280a082d9786b0ad21b] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a8f3592870ef506c78caf3273733b89b2a89d3dc1bf717c] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a8f3592870ef506c78caf3273733b89b2] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a36cccd720e5c737815c9da7a6959e8bdc059a35882de83] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a36cccd720e5c737815c9da7a69] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a65deee47fa7d1854b84bab837fd643a0147888b37dd6ac] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a65deee47fa7d1854b84bab837fd643a0] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a5174704d3a61ef516278e5ad373eb332b62a8218c80fb8] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5174704d3a61ef516278e5ad37] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a26192ebc14aee01b696d312fa2ec8d78292319bae755c5] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a26192ebc14aee01b696d312fa2ec8d78] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3aa15b86be5bec9f5231c60ed0fc8f6fefd65231aa0cfffd] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aa15b86be5bec9f5231c60ed0fc] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3acf7d229e1073ed021b5394b156ae52c171113006189890] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3acf7d229e1073ed021b5394b156ae52c1] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a2e6ec4391107dcafc3c046462a2ad3f9a78a36a111424f] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a2e6ec4391107dcafc3c046462a] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a9251d449e35f168e39e508dcba3f7b19ed225e4ab1571c] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a9251d449e35f168e39e508dcba3f7b19] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a1c1005bab4ab1fa306652ec3a33f0a2b269af07310c2a7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a1c1005bab4ab1fa306652ec3a3] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3af91bfe31a82e875ec018ffa2d41e126928c251f7d26f1b] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3af91bfe31a82e875ec018ffa2d41e1269] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3aaafa9cc7b0008e26947ca47e3737887d67a9ae5b5646d3] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aaafa9cc7b0008e26947ca47e37] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a8827ff6a530efbb3a7a2c16b99700b6e8a061e4060baf6] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a8827ff6a530efbb3a7a2c16b99700b6e] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a4a9d7be33b48393a2f3c1e5f2fd9af4be5e71de646c64d] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a4a9d7be33b48393a2f3c1e5f2f] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a06420b6c0d04b077c4c1c0ef122f2f3c8baedec0c31c68] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a06420b6c0d04b077c4c1c0ef122f2f3c] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3aafcee95a8836c4477426fe0319a6a72f019fe07bc91a7a] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aafcee95a8836c4477426fe0319] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a51f96abf2299b290f0230d7261ec34f9608cd25706eef7] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a51f96abf2299b290f0230d7261ec34f9] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a4958004a5bc5311052bd125f67ac0ebf2ee367ea79ee9b] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a4958004a5bc5311052bd125f67] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3afd7ea8d55f24e554e8a5a15817659fa2ef184b7300ddce] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3afd7ea8d55f24e554e8a5a15817659fa2] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3af81de216441b17aefe48e94b5cfd111b83046330b4302e] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3af81de216441b17aefe48e94b5c] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a788cd30303963b03dd1d40697c31fb97645a97e7905d37] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a788cd30303963b03dd1d40697c31fb97] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ac1f1fe2d0437406ac3fa2777b76104958e38894e96211d] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ac1f1fe2d0437406ac3fa2777b7] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3acd41d7e468bd6e0e366099cda99c92cff0e0aa24d4116e] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3acd41d7e468bd6e0e366099cda99c92cf] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3ab55852db1ba113fc8a9f391ecdaf84b690f1265b4e813c] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3ab55852db1ba113fc8a9f391ecd] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3adb9d6eefd1c2bc17aed478d71f2e1088a7dbc733946f34] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3adb9d6eefd1c2bc17aed478d71f2e1088] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a64935351a68fbfd2d392d8dfaedaa8bc01d1f0e9a50a99] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a64935351a68fbfd2d392d8dfae] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a90675db93e49154ef8fc11fe09257e427ec49be23f6993] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a90675db93e49154ef8fc11fe09257e42] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a38fab0241e1a5ef738d73ba5acee5c3815f50a0a0d96a7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a38fab0241e1a5ef738d73ba5ac] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a0077bd3fa60bbc1ae773e7de394947f05c96d335392061] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a0077bd3fa60bbc1ae773e7de394947f0] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a6ca822d162722dd0e4606a35ba098a44a289aa8bd959bd] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a6ca822d162722dd0e4606a35ba] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a2634e60948085d16e2e5dbab22c57515759b3fef47bdfe] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a2634e60948085d16e2e5dbab22c57515] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a5f365cf401bc9ce25862d7b2e884a64d43161cc26f7ce0] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5f365cf401bc9ce25862d7b2e8] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a745d4768657b7dfdc5a828185043541d1c8cd435b73622] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a745d4768657b7dfdc5a828185043541d] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3abff7e68243e56af80e189657c6602dd8c43f19b0fcfb7c] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3abff7e68243e56af80e189657c6] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a7febff85204c1d69785da33a722f9cbf17310f7f761934] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a7febff85204c1d69785da33a722f9cbf] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a9787170a91d30f935b8cf180cc6b43ec5cb9e97309d449] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a9787170a91d30f935b8cf180cc] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3aa1e11b13847c0a1d2c98bb079c4108a688b8f40ce0a2fd] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3aa1e11b13847c0a1d2c98bb079c4108a6] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a5fe949460a655945d5ab38ab18e0b507322c52db80d4df] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a5fe949460a655945d5ab38ab18] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a8de5062cf07f378e6260fcb2594fd292723972edd88d9c] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a8de5062cf07f378e6260fcb2594fd292] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3a71927a87aa91cbf4e336418c036f450de11e831da5dcf7] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3a71927a87aa91cbf4e336418c03] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3acb9909d9a494d6f603d7fa13a380fd1663bc30d23cb914] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3acb9909d9a494d6f603d7fa13a380fd16] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3abb443f78b6b1016408a2e194aa3ea4ec4978a7d7416caa] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3abb443f78b6b1016408a2e194aa] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3ae41418438b8187d19d40827243c0d112ddf2791b20795a] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3ae41418438b8187d19d40827243c0d112] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3afda0ad7c1b0733865c5d2de8d7e965359c140b43a55934] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3afda0ad7c1b0733865c5d2de8d7] (r:0 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a7e72f07e9e79d04faaadf9e9d90363ad3326e51b9c3bea] (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a7e72f07e9e79d04faaadf9e9d90363ad] (r:1 w:0)
+ // Storage: unknown [0x673a3a636f64653a3aaf3fa9250be40e01e2597adb04c8128f2d7dcfef9a0393] (r:1 w:1)
+ // Storage: unknown [0x673a3a636f64653a3a6d657461646174613a3aaf3fa9250be40e01e2597adb04] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a29fd22b3bbfb883c65b0d117aef2acf005a322623e74e176] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a72c655e2fc927dfa34bb265a0fafba78952cd7e2277207de] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a1ed310eb2ab21836e2a2bd621ec74da64cd4e574be0a80d3] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a788293f49af1e8639b89ea671f2588bfe7e326d5f9744774] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aa39ad07faa5848c619216610ad3ef9afdfee65e3142f91f4] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aef9a3fee4b9f5b2d73aacf39a1f37fb1918c5ecda299abc1] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a30f27253451e0f9e3e1e36990d2a17095fdcd2cc04930f80] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a70999d5d9679be27e114baf64bd649e3bb62dd093737d4b4] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a8a5abbbd6b96e041af5856d09b4ac254d0c346b2e8fc51d8] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a668fe0cfdbb92b4bc779c7f2205162a90f75fac375c1dcb8] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a6fd4c342411c5e0d75cea409fedb9bd1c703e4968ec66325] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abebdb1c9c79a1b145459689bac92ac55f39a375ff1a312ee] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3af12e7cfc2dac7b6fce07eb00c6cc39c2f890b8a1d7022195] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a1834390ef741f1d1b874aa57a3e490b0657a33cd7fa7d1e5] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aae5ba1e6cbc3ccc5e54392d6989982172348488ad9d751e7] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9e8b6e599195553aacdf6836b79b358d6e4489880fe3535b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae4d9f74c92cd5e6eeb7d9d6dccca89b3258c5b95c3aa32d2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a92db6c15172756b9a0a647eb388fea594aae48ef43469644] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abad81620314439080f98e4516fcded95d1a569c22526f89b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ad1e32f4c34de078086660976c4eb9e2df9dc162026ecfd35] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9a974b2bce8da3cda0fc4c3cd5b3ed3d36e1b853faa3e11e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3afdcdb7cd9f528855f6808eba35a98f5181f72267b1952b12] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ad157ef36046f784171ee394eb6a78111f1b198b739afdab8] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abddea7b802ab0c607c9e1acbaeb775c2f7047686468f7b63] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ac2abe41015137dd68f06d3b0c16538713ef68663127b900b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5a9b70b97900c2fb3568a9ac6a7fe60c1d694e4fdf01c74d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a07d837b4b1207d45cf5ff714bad99bd72bd89502fb8c6558] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a1d14fbf47e1e7cc9809c14d43b7bc8191a8772cb3c67f6d3] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3af1f9c5d0697b9d0d84e38394f698fea3c777dc38158f01d4] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aa46ceb98695b52d9c50f7effd3a7dd5aa83ccac7fcfa1b12] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a492d3d6836cfac43e9406ea2d803232b9059352e9f35e752] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3adb2837ff4433ba56639d593af09a1bd1787cddbe8ffe9984] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3af6de683dd55aefcfa08830ebd32d1a0ecf8194a423952d03] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae158652fa6e8cd6df246427e752b5e35d1f17dd92287fd6a] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3acbc6b3c53e5971ca4a3f0459e8b767049adbe582f0cee4d9] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ac93d67bacfb8475a051f964ff92b53ce8fad8ecec2ad175d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3afeed710e1631b03a098c96edffc263b1b3629285015731be] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a6d209bad9598b629d1ec93fb1539891a61d280e2466cf75b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a15503ada741f6a1e455e5798a667b71c2c5acbf6832e374b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a14cb71dd8cb6e5f78cbb85e6d3f339e267ac7a5a1e64739f] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a500d3531ed91138b63e2d1e8ab70646da3d12fb8c1c38ed6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3acca39672d23556d2ad67ac33ebb981f8386597c747583b1d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a79620fef2fd6882919d0fbc8938a779fc6ebe069fc34d0a2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ab58c1f69844236a500160be3b323044ef61065e0622457c0] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9e29404010869da9758b4f9d52a6ca8fe5b68ecbb37269f8] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a34770943427885bd5d9feab330a40e47479716c08ea2a5b2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a1c0728ea29c8481eeeb85bc4dcecce7b54ddb658114d4495] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a8ac8066f558210b720374a38049f9c440376b8bf0922a399] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aa17ca0046fa9c9985e394bbedd9e9c00e9ae84b0c0837c22] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3adee80d31c0f5560d6dd7324bc01693c341807653fda3b609] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a71aed0e1fa1a567fb7aaf0756a4515aa007d4f87f6ceb046] (r:0 w:1)
+ fn submit_program(c: u32, p: u32, ) -> Weight {
+ (81_628_000u32 as Weight)
+ // Standard Error: 0
+ .saturating_add((4_000u32 as Weight).saturating_mul(c as Weight))
+ // Standard Error: 0
+ .saturating_add((1_000u32 as Weight).saturating_mul(p as Weight))
+ .saturating_add(T::DbWeight::get().reads(8u32 as Weight))
+ .saturating_add(T::DbWeight::get().writes(10u32 as Weight))
+ }
+ // Storage: unknown [0x673a3a70726f673a3a13614ad1183876953cdd99749d6dcf5d41b7ffc0740cd2] (r:1 w:0)
+ // Storage: unknown [0x673a3a6d73673a3a6e6f6e6365] (r:1 w:1)
+ // Storage: System Account (r:1 w:1)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a13614ad1183876953cdd99749d6dcf5d] (r:1 w:0)
+ // Storage: Gas ValueView (r:1 w:1)
+ // Storage: Gas TotalIssuance (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a68656164] (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a29fd22b3bbfb883c65b0d117aef2acf005a322623e74e176] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7461696c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a45072b00f246da7ee052d5ad6cbebd4c1524c1edfc330847] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a87dc935305f2e209459cf39b6f2972fc894617e8cd4539ac] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a197218d9d59fd62f6ebcf6dbde66cdf8556a48fbad332470] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a1b7eaf61e777c0bf465cc88eae6ed54dfacf298deac7c701] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ac579d303643059fb7368f6610e94f592f0057a74f812d2fa] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a3896343992d41b7fd8767d9e6ea1f3695c59b641703ac8e6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae9d26a2a3bf2090f327d4d91fac82b086d87e4a55eab5f77] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3afd7bb6f79afd54a537b1ed76e8fac1b5b878a60a1fa48c9f] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a77855e60112c4d0b2d804d7a1495562f5aec71899b9525e3] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5d7f398f50782c0ba9b4c07abbfc3f8b1756530c6ed011df] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a48be3fa5bd8701b408df8b85404638eac5a4415fb8a221c2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a02c45e34dcb34c0fb5e44055230eda06f61d43190bc60e28] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abdfa8756bf33be66f2b2627eab3f4d0564872e7110cf9d9f] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aa2d7ed0ff0aa76fba598942a21ebb99e3212358400b0c713] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ac823abce2e1f65e5dcf558a8fdbfb74cb7a59340667ed030] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3af04bdf70bf76040d894758abff16f96f3e71ef243a212762] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a6ed9442cbf9ad509824ab6e8d8bc755d403b092f3053788b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae685b493126a0a8dd32bebe67f87aeba55d6742641ae93e9] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a0c567787eab13cbfd34f8032356e1043460cdba3bd64269c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a61b41f6a5be081ee5b77933c14fe3110cbe28b3a5092208d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a62c54be0afe01930f756b38698e2a4d2073451e20e9fa114] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae14e807f66728b1c25f0a83def45e6e8d81e7bdc2d9f89b7] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a259f47c27cf9627c056f4cc6e0cdca0b89a3ab5317b04b9c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5711315315f1dfda45654675c464078d079197b2d4dd7601] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abb3b0641b9bc61c9b02cd92e7ab945bf5b92a8143a93e4f3] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a70054e7571d378d0e1b69f4e4d682a8082608c08f3d00950] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5a5101ea998de25aa93aa5d9cb395c3bb0c820375c124fa6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ab7d2ad61118df5ab6196fecfe086d0dec54c5e79ec89899e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a65ac638d8826a6b8ba051e8ffba5800d159de7da47c770e1] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a3eb97cf8504d86dbdd68bb8782598adbc39f4473757eed32] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a54bb7b2310535adbe1e1708b70a4eb5f2ef0cc0941df681b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a35248af2758765acd7b109f3468d6bf1b94fea502433c03e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7df1700e53703f2a7201292446cd4ef22ac12a3baa100e93] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aaec17edbd48453db6eb0ed02b5d20792206b77d4e6152a1e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abd2dbf3c9a55144ead83ccac62f5beb836c90d9b43d48ad2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a806e0a96788ffad2ff576e7766d29558055748946a986eb5] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5e3fcc25ec497d27126c30a27a51e44f15baf8ff45209600] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a2fa9fe6fa80c07cb72a0cbb837a0362344bd9a25a28dee21] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a3543c66e15b6629b3323171ce8eb20bde011baef92dd06f5] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7c64f5301d56b646a4249aafd23c5e2160e86a7b218720eb] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a2190f803ac4dbbb06a3cb8941a7e7efb8994b600fbee2214] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a515df56a1192fb9d06409745d25da087516cf97f77bac377] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a60f05b5c27c6a31a37d34d758231ad4b5ce75c6f6d4625a6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aadd2a58071db328143dec6c4e5a9ed067ad260e6a07689fd] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a707f7d0d2cf9f4f4070abbe10ef8845fbec05023bfe5ac02] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9f056a24e082286b8e04eb3c3076542707c0333cb259063d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7f3b1c4a5c931e5a62dd7d04c342d9d77c85a4c269367538] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5317b522ff4c944a681a57e0c17a8aaca91c47104761cfa9] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a53b03fae6bd8b459b234c767c0c3d0a16b08aef56b3f15db] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9844704e94d0c75b6ec6fb1678261c4a197acb2683a44d7b] (r:0 w:1)
+ fn send_message(p: u32, ) -> Weight {
+ (58_540_000u32 as Weight)
+ // Standard Error: 0
+ .saturating_add((2_000u32 as Weight).saturating_mul(p as Weight))
+ .saturating_add(T::DbWeight::get().reads(7u32 as Weight))
+ .saturating_add(T::DbWeight::get().writes(7u32 as Weight))
+ }
+ // Storage: Gear Mailbox (r:1 w:1)
+ // Storage: System Account (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a6e6f6e6365] (r:1 w:1)
+ // Storage: unknown [0x673a3a70726f673a3a13614ad1183876953cdd99749d6dcf5d41b7ffc0740cd2] (r:1 w:0)
+ // Storage: unknown [0x673a3a7061757365645f70726f673a3a13614ad1183876953cdd99749d6dcf5d] (r:1 w:0)
+ // Storage: Gas ValueView (r:1 w:1)
+ // Storage: Gas TotalIssuance (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a68656164] (r:1 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a29fd22b3bbfb883c65b0d117aef2acf005a322623e74e176] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7461696c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a45072b00f246da7ee052d5ad6cbebd4c1524c1edfc330847] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a87dc935305f2e209459cf39b6f2972fc894617e8cd4539ac] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a197218d9d59fd62f6ebcf6dbde66cdf8556a48fbad332470] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a1b7eaf61e777c0bf465cc88eae6ed54dfacf298deac7c701] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ac579d303643059fb7368f6610e94f592f0057a74f812d2fa] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a3896343992d41b7fd8767d9e6ea1f3695c59b641703ac8e6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae9d26a2a3bf2090f327d4d91fac82b086d87e4a55eab5f77] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3afd7bb6f79afd54a537b1ed76e8fac1b5b878a60a1fa48c9f] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a77855e60112c4d0b2d804d7a1495562f5aec71899b9525e3] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5d7f398f50782c0ba9b4c07abbfc3f8b1756530c6ed011df] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a48be3fa5bd8701b408df8b85404638eac5a4415fb8a221c2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a02c45e34dcb34c0fb5e44055230eda06f61d43190bc60e28] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abdfa8756bf33be66f2b2627eab3f4d0564872e7110cf9d9f] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aa2d7ed0ff0aa76fba598942a21ebb99e3212358400b0c713] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ac823abce2e1f65e5dcf558a8fdbfb74cb7a59340667ed030] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3af04bdf70bf76040d894758abff16f96f3e71ef243a212762] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a6ed9442cbf9ad509824ab6e8d8bc755d403b092f3053788b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae685b493126a0a8dd32bebe67f87aeba55d6742641ae93e9] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a0c567787eab13cbfd34f8032356e1043460cdba3bd64269c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a61b41f6a5be081ee5b77933c14fe3110cbe28b3a5092208d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a62c54be0afe01930f756b38698e2a4d2073451e20e9fa114] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ae14e807f66728b1c25f0a83def45e6e8d81e7bdc2d9f89b7] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a259f47c27cf9627c056f4cc6e0cdca0b89a3ab5317b04b9c] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5711315315f1dfda45654675c464078d079197b2d4dd7601] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abb3b0641b9bc61c9b02cd92e7ab945bf5b92a8143a93e4f3] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a70054e7571d378d0e1b69f4e4d682a8082608c08f3d00950] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5a5101ea998de25aa93aa5d9cb395c3bb0c820375c124fa6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3ab7d2ad61118df5ab6196fecfe086d0dec54c5e79ec89899e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a65ac638d8826a6b8ba051e8ffba5800d159de7da47c770e1] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a3eb97cf8504d86dbdd68bb8782598adbc39f4473757eed32] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a54bb7b2310535adbe1e1708b70a4eb5f2ef0cc0941df681b] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a35248af2758765acd7b109f3468d6bf1b94fea502433c03e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7df1700e53703f2a7201292446cd4ef22ac12a3baa100e93] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aaec17edbd48453db6eb0ed02b5d20792206b77d4e6152a1e] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3abd2dbf3c9a55144ead83ccac62f5beb836c90d9b43d48ad2] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a806e0a96788ffad2ff576e7766d29558055748946a986eb5] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5e3fcc25ec497d27126c30a27a51e44f15baf8ff45209600] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a2fa9fe6fa80c07cb72a0cbb837a0362344bd9a25a28dee21] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a3543c66e15b6629b3323171ce8eb20bde011baef92dd06f5] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7c64f5301d56b646a4249aafd23c5e2160e86a7b218720eb] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a2190f803ac4dbbb06a3cb8941a7e7efb8994b600fbee2214] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a515df56a1192fb9d06409745d25da087516cf97f77bac377] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a60f05b5c27c6a31a37d34d758231ad4b5ce75c6f6d4625a6] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3aadd2a58071db328143dec6c4e5a9ed067ad260e6a07689fd] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a707f7d0d2cf9f4f4070abbe10ef8845fbec05023bfe5ac02] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9f056a24e082286b8e04eb3c3076542707c0333cb259063d] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a7f3b1c4a5c931e5a62dd7d04c342d9d77c85a4c269367538] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a5317b522ff4c944a681a57e0c17a8aaca91c47104761cfa9] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a53b03fae6bd8b459b234c767c0c3d0a16b08aef56b3f15db] (r:0 w:1)
+ // Storage: unknown [0x673a3a6d73673a3a9844704e94d0c75b6ec6fb1678261c4a197acb2683a44d7b] (r:0 w:1)
+ fn send_reply(p: u32, ) -> Weight {
+ (70_895_000u32 as Weight)
+ // Standard Error: 0
+ .saturating_add((2_000u32 as Weight).saturating_mul(p as Weight))
+ .saturating_add(T::DbWeight::get().reads(8u32 as Weight))
+ .saturating_add(T::DbWeight::get().writes(8u32 as Weight))
+ }
}
// For backwards compatibility and tests
const SUBMIT_WEIGHT_PER_BYTE: u64 = 1_000_000;
const MESSAGE_PER_BYTE: u64 = 100_000;
impl WeightInfo for () {
- fn submit_code(c: u32) -> Weight {
- (0_u64)
- .saturating_add(RocksDbWeight::get().writes(1_u64))
- .saturating_add(SUBMIT_WEIGHT_PER_BYTE.saturating_mul(c as Weight))
- }
+ fn submit_code(c: u32) -> Weight {
+ (0_u64)
+ .saturating_add(RocksDbWeight::get().writes(1_u64))
+ .saturating_add(SUBMIT_WEIGHT_PER_BYTE.saturating_mul(c as Weight))
+ }
- fn submit_program(c: u32, p: u32) -> Weight {
- (0_u64)
- .saturating_add(RocksDbWeight::get().writes(4_u64))
- .saturating_add(SUBMIT_WEIGHT_PER_BYTE.saturating_mul(c as Weight))
- .saturating_add(MESSAGE_PER_BYTE.saturating_mul(p as Weight))
- }
+ fn submit_program(c: u32, p: u32) -> Weight {
+ (0_u64)
+ .saturating_add(RocksDbWeight::get().writes(4_u64))
+ .saturating_add(SUBMIT_WEIGHT_PER_BYTE.saturating_mul(c as Weight))
+ .saturating_add(MESSAGE_PER_BYTE.saturating_mul(p as Weight))
+ }
- fn send_message(p: u32) -> Weight {
- (0_u64)
- .saturating_add(RocksDbWeight::get().writes(4_u64))
- .saturating_add(MESSAGE_PER_BYTE.saturating_mul(p as Weight))
- }
+ fn send_message(p: u32) -> Weight {
+ (0_u64)
+ .saturating_add(RocksDbWeight::get().writes(4_u64))
+ .saturating_add(MESSAGE_PER_BYTE.saturating_mul(p as Weight))
+ }
- fn send_reply(p: u32) -> Weight {
- (0_u64)
- .saturating_add(RocksDbWeight::get().writes(4_u64))
- .saturating_add(MESSAGE_PER_BYTE.saturating_mul(p as Weight))
- }
+ fn send_reply(p: u32) -> Weight {
+ (0_u64)
+ .saturating_add(RocksDbWeight::get().writes(4_u64))
+ .saturating_add(MESSAGE_PER_BYTE.saturating_mul(p as Weight))
+ }
}
diff --git a/pallets/usage/Cargo.toml b/pallets/usage/Cargo.toml
index 9f19b39a06a..510c0fefb03 100644
--- a/pallets/usage/Cargo.toml
+++ b/pallets/usage/Cargo.toml
@@ -45,6 +45,7 @@ gear-core = { path = "../../core" }
pallet-gas = { path = "../gas" }
pallet-timestamp = { version = "4.0.0-dev", git = "https://github.com/gear-tech/substrate.git", branch = "gear-stable" }
hex-literal = "0.3.3"
+pallet-gear-program = { path = "../gear-program", default-features = false }
[features]
default = ['std']
diff --git a/pallets/usage/src/mock.rs b/pallets/usage/src/mock.rs
index 6ec77550094..5e35eafbbb4 100644
--- a/pallets/usage/src/mock.rs
+++ b/pallets/usage/src/mock.rs
@@ -49,6 +49,7 @@ construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: system::{Pallet, Call, Config, Storage, Event},
+ GearProgram: pallet_gear_program::{Pallet, Storage, Event},
Gear: pallet_gear::{Pallet, Call, Storage, Event},
Gas: pallet_gas::{Pallet, Storage},
Usage: pallet_usage::{Pallet, Call, Storage, Event, ValidateUnsigned},
@@ -108,6 +109,12 @@ impl common::GasPrice for GasConverter {
type Balance = u128;
}
+impl pallet_gear_program::Config for Test {
+ type Event = Event;
+ type WeightInfo = ();
+ type Currency = Balances;
+}
+
parameter_types! {
pub const WaitListFeePerBlock: u64 = 100;
}
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index c13e312ed18..20d0a9c9317 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -57,6 +57,7 @@ frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, g
hex-literal = { version = "0.3.4", optional = true }
# Internal deps
+pallet-gear-program = { version = "2.0.0", default-features = false, path = "../pallets/gear-program" }
pallet-gear = { version = "2.0.0", default-features = false, path = "../pallets/gear" }
pallet-gear-debug = { version = "2.0.0", default-features = false, path = "../pallets/gear-debug", optional = true }
pallet-usage = { version = "2.0.0", default-features = false, path = "../pallets/usage" }
@@ -78,6 +79,7 @@ std = [
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
+ "pallet-gear-program/std",
"pallet-gear/std",
"pallet-gear-debug/std",
"pallet-usage/std",
@@ -115,6 +117,7 @@ runtime-benchmarks = [
"pallet-balances/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-gear/runtime-benchmarks",
+ "pallet-gear-program/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
debug-mode = [
diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
index 94eedf6c99e..6ea9f90cc07 100644
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -124,7 +124,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// The version of the runtime specification. A full node will not attempt to use its native
// runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
// `spec_version`, and `authoring_version` are the same between Wasm and native.
- spec_version: 350,
+ spec_version: 360,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
@@ -328,6 +328,12 @@ impl gear_common::GasPrice for GasConverter {
type Balance = Balance;
}
+impl pallet_gear_program::Config for Runtime {
+ type Event = Event;
+ type WeightInfo = pallet_gear_program::weights::GearProgramWeight;
+ type Currency = Balances;
+}
+
parameter_types! {
pub const GasLimitMaxPercentage: Percent = Percent::from_percent(75);
pub BlockGasLimit: u64 = GasLimitMaxPercentage::get() * BlockWeights::get().max_block;
@@ -393,6 +399,7 @@ construct_runtime!(
Sudo: pallet_sudo,
Utility: pallet_utility,
Authorship: pallet_authorship,
+ GearProgram: pallet_gear_program,
Gear: pallet_gear,
Usage: pallet_usage,
Gas: pallet_gas,
@@ -419,6 +426,7 @@ construct_runtime!(
Sudo: pallet_sudo,
Utility: pallet_utility,
Authorship: pallet_authorship,
+ GearProgram: pallet_gear_program,
Gear: pallet_gear,
Usage: pallet_usage,
Gas: pallet_gas,
@@ -615,6 +623,7 @@ impl_runtime_apis! {
list_benchmark!(list, extra, frame_system, SystemBench::);
list_benchmark!(list, extra, pallet_balances, Balances);
list_benchmark!(list, extra, pallet_timestamp, Timestamp);
+ list_benchmark!(list, extra, pallet_gear_program, GearProgram);
list_benchmark!(list, extra, pallet_gear, Gear);
let storage_info = AllPalletsWithSystem::storage_info();
@@ -649,6 +658,7 @@ impl_runtime_apis! {
add_benchmark!(params, batches, frame_system, SystemBench::);
add_benchmark!(params, batches, pallet_balances, Balances);
add_benchmark!(params, batches, pallet_timestamp, Timestamp);
+ add_benchmark!(params, batches, pallet_gear_program, GearProgram);
add_benchmark!(params, batches, pallet_gear, Gear);
if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
diff --git a/tests/proxy/Cargo.toml b/tests/proxy/Cargo.toml
new file mode 100644
index 00000000000..d863ecc354d
--- /dev/null
+++ b/tests/proxy/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "tests-proxy"
+version = "0.1.0"
+authors = ["Gear Technologies"]
+edition = "2018"
+license = "GPL-3.0"
+
+[dependencies]
+gstd = { path = "../../gstd", features = ["debug"] }
+codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = ["derive"] }
+scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
+
+[build-dependencies]
+gear-wasm-builder = { path = "../../utils/wasm-builder" }
+
+[lib]
+
+[features]
+std = ["codec/std", "scale-info/std"]
+default = ["std"]
diff --git a/tests/proxy/build.rs b/tests/proxy/build.rs
new file mode 100644
index 00000000000..199b5faeeff
--- /dev/null
+++ b/tests/proxy/build.rs
@@ -0,0 +1,21 @@
+// This file is part of Gear.
+
+// Copyright (C) 2021 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+fn main() {
+ gear_wasm_builder::build();
+}
diff --git a/tests/proxy/src/lib.rs b/tests/proxy/src/lib.rs
new file mode 100644
index 00000000000..73f12e1b7d8
--- /dev/null
+++ b/tests/proxy/src/lib.rs
@@ -0,0 +1,60 @@
+// This file is part of Gear.
+
+// Copyright (C) 2021 Gear Technologies Inc.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use codec::{Decode, Encode};
+use scale_info::TypeInfo;
+
+#[cfg(feature = "std")]
+mod code {
+ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
+}
+
+#[cfg(feature = "std")]
+pub use code::WASM_BINARY_OPT as WASM_BINARY;
+
+#[derive(Debug, Decode, Encode, TypeInfo)]
+pub struct InputArgs {
+ pub destination: gstd::ActorId,
+}
+
+#[cfg(not(feature = "std"))]
+mod wasm {
+ use crate::InputArgs;
+ use gstd::{msg, ActorId, ToString};
+
+ static mut DESTINATION: ActorId = ActorId::new([0u8; 32]);
+
+ gstd::metadata! {
+ title: "tests-proxy",
+ handle:
+ input: InputArgs,
+ }
+
+ #[no_mangle]
+ pub unsafe extern "C" fn handle() {
+ msg::send(DESTINATION, b"proxied message", msg::value());
+ }
+
+ #[no_mangle]
+ pub unsafe extern "C" fn init() {
+ let args: InputArgs = msg::load().expect("Failed to decode `InputArgs'");
+ DESTINATION = args.destination;
+ }
+}
diff --git a/utils/wasm-builder/test-program/Cargo.lock b/utils/wasm-builder/test-program/Cargo.lock
index dd36f02648b..cd79d237530 100644
--- a/utils/wasm-builder/test-program/Cargo.lock
+++ b/utils/wasm-builder/test-program/Cargo.lock
@@ -564,7 +564,7 @@ dependencies = [
[[package]]
name = "gear-wasm-builder"
-version = "0.2.0"
+version = "0.1.2"
dependencies = [
"anyhow",
"cargo_metadata",