From 29a7dc307bfde8e48413ec533c97abcc57e51256 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Tue, 19 Jul 2022 17:55:37 +0400 Subject: [PATCH 01/16] two test cases --- pallets/gear/src/tests.rs | 152 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index d012448a321..39c55c119ac 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -4010,6 +4010,158 @@ fn test_async_messages() { }) } +#[test] +fn missing_functions_are_not_executed() { + // handle is copied from ProgramCodeKind::OutgoingWithValueInHandle + let wat = r#" + (module + (import "env" "gr_send_wgas" (func $send (param i32 i32 i32 i64 i32 i32) (result i32))) + (import "env" "memory" (memory 10)) + (export "handle" (func $handle)) + (func $handle + (local $msg_source i32) + (local $msg_val i32) + (i32.store offset=2 + (get_local $msg_source) + (i32.const 1) + ) + (i32.store offset=10 + (get_local $msg_val) + (i32.const 1000) + ) + (call $send (i32.const 2) (i32.const 0) (i32.const 32) (i64.const 10000000) (i32.const 10) (i32.const 40000)) + (if + (then unreachable) + (else) + ) + ) + )"#; + + init_logger(); + new_test_ext().execute_with(|| { + let initial_balance = BalancesPallet::::free_balance(USER_1); + + let program_id = { + let res = submit_program_default(USER_1, ProgramCodeKind::Custom(wat)); + assert_ok!(res); + res.expect("submit result was asserted") + }; + + let GasInfo { + min_limit, + .. + } = Gear::calculate_gas_info( + USER_1.into_origin(), + HandleKind::Init(ProgramCodeKind::Custom(wat).to_bytes()), + EMPTY_PAYLOAD.to_vec(), + 0, + true, + ) + .expect("calculate_gas_info failed"); + + assert_eq!(min_limit, 0); + + run_to_next_block(None); + + // there is no 'init' so memory pages don't get loaded and + // no execution is performed at all and hence user was not charged. + assert_eq!(initial_balance, BalancesPallet::::free_balance(USER_1)); + + // this value is actually a constant in the wat. + let locked_value = 1_000; + assert_ok!( + as frame_support::traits::Currency<_>>::transfer( + &USER_1, + &AccountId::from_origin(program_id.into_origin()), + locked_value, + frame_support::traits::ExistenceRequirement::AllowDeath + ) + ); + + assert_ok!(GearPallet::::send_message( + Origin::signed(USER_3), + program_id, + EMPTY_PAYLOAD.to_vec(), + 1_000_000_000, + 0, + )); + + run_to_next_block(None); + + let reply_to_id = get_last_mail(USER_1).id(); + + let GasInfo { + min_limit, + .. + } = Gear::calculate_gas_info( + USER_1.into_origin(), + HandleKind::Reply(reply_to_id, 0), + EMPTY_PAYLOAD.to_vec(), + 0, + true, + ) + .expect("calculate_gas_info failed"); + + assert_eq!(min_limit, 0); + + let reply_value = 1_500; + assert_ok!(GearPallet::::send_reply( + Origin::signed(USER_1), + reply_to_id, + EMPTY_PAYLOAD.to_vec(), + 100_000_000, + reply_value, + )); + + run_to_next_block(None); + + // there is no 'handle_reply' too + assert_eq!(initial_balance - reply_value, BalancesPallet::::free_balance(USER_1)); + }); +} + +#[test] +fn missing_handle_is_not_executed() { + let wat = r#" + (module + (import "env" "memory" (memory 2)) + (export "init" (func $init)) + (func $init) + )"#; + + init_logger(); + new_test_ext().execute_with(|| { + let program_id = GearPallet::::submit_program( + Origin::signed(USER_1), + ProgramCodeKind::Custom(wat).to_bytes(), + vec![], + EMPTY_PAYLOAD.to_vec(), + 1_000_000_000, + 0, + ) + .map(|_| get_last_program_id()) + .expect("submit_program failed"); + + run_to_next_block(None); + + let balance_before = BalancesPallet::::free_balance(USER_1); + + assert_ok!(GearPallet::::send_message( + Origin::signed(USER_1), + program_id, + EMPTY_PAYLOAD.to_vec(), + 1_000_000_000, + 0, + )); + + run_to_next_block(None); + + // there is no 'handle' so no memory pages are loaded and + // the program is not executed. Hence the user didn't pay for processing. + assert_eq!(balance_before, BalancesPallet::::free_balance(USER_1)); + }); +} + mod utils { #![allow(unused)] From bc9653273e13de519bd1e68ae2686e0c6534c0f0 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 20 Jul 2022 11:03:26 +0400 Subject: [PATCH 02/16] add core_processor::prepare --- core-processor/src/common.rs | 36 +++++- core-processor/src/executor.rs | 92 ++++++++++--- core-processor/src/lib.rs | 2 +- core-processor/src/processor.rs | 220 +++++++++++++++++++------------- pallets/gear/src/lib.rs | 118 +++++++++++------ pallets/gear/src/manager/mod.rs | 12 +- 6 files changed, 315 insertions(+), 165 deletions(-) diff --git a/core-processor/src/common.rs b/core-processor/src/common.rs index c01ce0f180d..2a2b68e9b8c 100644 --- a/core-processor/src/common.rs +++ b/core-processor/src/common.rs @@ -26,7 +26,7 @@ use alloc::{ use codec::{Decode, Encode}; use gear_backend_common::TrapExplanation; use gear_core::{ - gas::GasAmount, + gas::{GasAmount, GasAllowanceCounter, GasCounter}, ids::{CodeId, MessageId, ProgramId}, memory::{PageBuf, PageNumber, WasmPageNumber}, message::{ContextStore, Dispatch, IncomingDispatch, StoredDispatch}, @@ -90,10 +90,31 @@ impl DispatchResult { self.dispatch.source() } - /// Return dispatch message value + /// Return dispatch message value. pub fn message_value(&self) -> u128 { self.dispatch.value() } + + /// Create partially initialized instance with the kind + /// representing Success. + pub fn success( + dispatch: IncomingDispatch, + program_id: ProgramId, + gas_amount: GasAmount, + ) -> Self { + Self { + kind: DispatchResultKind::Success, + dispatch, + program_id, + context_store: Default::default(), + generated_dispatches: Default::default(), + awakening: Default::default(), + program_candidates: Default::default(), + gas_amount, + page_update: Default::default(), + allocations: Default::default(), + } + } } /// Dispatch outcome of the specific message. @@ -357,15 +378,16 @@ pub struct Actor { pub struct ExecutableActorData { /// Program. pub program: Program, - /// Data which some program allocated pages may have. - pub pages_data: BTreeMap, + /// Numbers of memory pages with some data. + pub pages_with_data: BTreeSet, } /// Execution context. -#[derive(Clone, Debug, Decode, Encode)] pub struct WasmExecutionContext { /// Original user. pub origin: ProgramId, - /// Gas allowance of the block. - pub gas_allowance: u64, + /// A counter for gas. + pub gas_counter: GasCounter, + /// A counter for gas allowance. + pub gas_allowance_counter: GasAllowanceCounter, } diff --git a/core-processor/src/executor.rs b/core-processor/src/executor.rs index 6b0f84c3e5d..c48152fa391 100644 --- a/core-processor/src/executor.rs +++ b/core-processor/src/executor.rs @@ -21,7 +21,7 @@ use crate::{ DispatchResult, DispatchResultKind, ExecutableActorData, ExecutionError, ExecutionErrorReason, WasmExecutionContext, }, - configs::ExecutionSettings, + configs::{ExecutionSettings, AllocationsConfig}, ext::{ProcessorContext, ProcessorExt}, }; use alloc::{ @@ -34,7 +34,7 @@ use gear_core::{ gas::{ChargeResult, GasAllowanceCounter, GasCounter, ValueCounter}, ids::ProgramId, memory::{AllocationsContext, Memory, PageBuf, PageNumber, WasmPageNumber}, - message::{ContextSettings, DispatchKind, IncomingDispatch, MessageContext}, + message::{ContextSettings, DispatchKind, IncomingDispatch, MessageContext}, program::Program, }; /// Make checks that everything with memory pages go well. @@ -67,7 +67,67 @@ fn make_checks_and_charge_gas_for_pages<'a>( }; // Charging gas for loaded pages - let amount = settings.load_page_cost() * (allocations.len() as u64 + static_pages.0 as u64); + // let amount = settings.load_page_cost() * (allocations.len() as u64 + static_pages.0 as u64); + + // if gas_allowance_counter.charge(amount) != ChargeResult::Enough { + // return Err(ExecutionErrorReason::LoadMemoryBlockGasExceeded); + // } + + // if gas_counter.charge(amount) != ChargeResult::Enough { + // return Err(ExecutionErrorReason::LoadMemoryGasExceeded); + // } + + // // Charging gas for mem size + // let amount = + // settings.mem_grow_cost() * (max_wasm_page.0 as u64 + 1 - static_pages.0 as u64); + + // if gas_allowance_counter.charge(amount) != ChargeResult::Enough { + // return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); + // } + + // if gas_counter.charge(amount) != ChargeResult::Enough { + // return Err(ExecutionErrorReason::GrowMemoryGasExceeded); + // } + + // +1 because pages numeration begins from 0 + max_wasm_page + 1.into() + } else { + // Charging gas for initial pages + // let amount = settings.init_cost() * static_pages.0 as u64; + + // if gas_allowance_counter.charge(amount) != ChargeResult::Enough { + // return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); + // } + + // if gas_counter.charge(amount) != ChargeResult::Enough { + // return Err(ExecutionErrorReason::InitialMemoryGasExceeded); + // } + + static_pages + }; + + if mem_size < static_pages { + log::error!( + "Mem size less then static pages num: mem_size = {:?}, static_pages = {:?}", + mem_size, + static_pages + ); + return Err(ExecutionErrorReason::InsufficientMemorySize); + } + + Ok(mem_size) +} + +pub(crate) fn charge_gas_for_pages<'a>( + settings: &AllocationsConfig, + gas_counter: &mut GasCounter, + gas_allowance_counter: &mut GasAllowanceCounter, + allocations: &BTreeSet, + static_pages: WasmPageNumber, +) -> Result<(), ExecutionErrorReason> { + let mem_size = if let Some(max_wasm_page) = allocations.iter().next_back() { + // Charging gas for loaded pages + let amount = settings.load_page_cost * allocations.len() as u64; if gas_allowance_counter.charge(amount) != ChargeResult::Enough { return Err(ExecutionErrorReason::LoadMemoryBlockGasExceeded); @@ -79,7 +139,7 @@ fn make_checks_and_charge_gas_for_pages<'a>( // Charging gas for mem size let amount = - settings.mem_grow_cost() * (max_wasm_page.0 as u64 + 1 - static_pages.0 as u64); + settings.mem_grow_cost * (max_wasm_page.0 as u64 + 1 - static_pages.0 as u64); if gas_allowance_counter.charge(amount) != ChargeResult::Enough { return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); @@ -90,10 +150,10 @@ fn make_checks_and_charge_gas_for_pages<'a>( } // +1 because pages numeration begins from 0 - max_wasm_page + 1.into() + *max_wasm_page + 1.into() } else { // Charging gas for initial pages - let amount = settings.init_cost() * static_pages.0 as u64; + let amount = settings.init_cost * static_pages.0 as u64; if gas_allowance_counter.charge(amount) != ChargeResult::Enough { return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); @@ -115,7 +175,7 @@ fn make_checks_and_charge_gas_for_pages<'a>( return Err(ExecutionErrorReason::InsufficientMemorySize); } - Ok(mem_size) + Ok(()) } /// Writes initial pages data to memory and prepare memory for execution. @@ -211,7 +271,8 @@ fn get_pages_to_be_updated( /// Execute wasm with dispatch and return dispatch result. pub fn execute_wasm>( balance: u128, - data: ExecutableActorData, + program: Program, + mut pages_initial_data: BTreeMap, dispatch: IncomingDispatch, context: WasmExecutionContext, settings: ExecutionSettings, @@ -225,20 +286,17 @@ pub fn execute_wasm>( +pub struct PreparedMessageExecutionContext { + gas_counter: GasCounter, + gas_allowance_counter: GasAllowanceCounter, + dispatch: IncomingDispatch, + origin: ProgramId, + balance: u128, + program: Program, +} + +pub enum PrepareResult { + Ok { + context: PreparedMessageExecutionContext, + pages_with_data: BTreeSet, + }, + WontExecute(Vec), + Error(Vec), +} + +pub fn prepare( block_config: &BlockConfig, execution_context: MessageExecutionContext, -) -> Vec { +) -> PrepareResult { let MessageExecutionContext { actor, dispatch, @@ -59,16 +76,116 @@ pub fn process process_non_executable(dispatch, destination_program, exit_code), - Ok(data) => process_executable::( - origin, - gas_allowance, - data, + let data = match check_is_executable(executable_data, &dispatch) { + Err(exit_code) => return PrepareResult::Error(process_non_executable(dispatch, destination_program, exit_code)), + Ok(data) => data, + }; + + let program = &data.program; + let program_id = program.id(); + let mut gas_counter = GasCounter::new(dispatch.gas_limit()); + if !program.code().exports().contains(&dispatch.kind()) { + return PrepareResult::WontExecute(process_success(SuccessfulDispatchResultKind::Success, + DispatchResult::success(dispatch, program_id, gas_counter.into()))); + } + + let mut gas_allowance_counter = GasAllowanceCounter::new(gas_allowance); + if let Err(reason) = executor::charge_gas_for_pages(&block_config.allocations_config, &mut gas_counter, &mut gas_allowance_counter, program.get_allocations(), program.static_pages()) { + log::debug!("failed to charge for memory pages: {:?}", reason); + return PrepareResult::Error(process_error(dispatch, program_id, gas_counter.burned(), reason)); + } + + PrepareResult::Ok{ + context: PreparedMessageExecutionContext { + gas_counter, + gas_allowance_counter, dispatch, + origin, balance, - block_config.clone(), - ), + program: data.program, + }, + pages_with_data: data.pages_with_data, + } +} + +/// Process program & dispatch for it and return journal for updates. +pub fn process>( + block_config: &BlockConfig, + execution_context: PreparedMessageExecutionContext, + memory_pages: BTreeMap, +) -> Vec { + use SuccessfulDispatchResultKind::*; + + let BlockConfig { + block_info, + allocations_config, + existential_deposit, + outgoing_limit, + host_fn_weights, + forbidden_funcs, + mailbox_threshold, + } = block_config.clone(); + + let execution_settings = ExecutionSettings::new( + block_info, + existential_deposit, + allocations_config, + host_fn_weights, + forbidden_funcs, + mailbox_threshold, + ); + + let dispatch = execution_context.dispatch; + let balance = execution_context.balance; + let program = execution_context.program; + let execution_context = WasmExecutionContext { + origin: execution_context.origin, + gas_counter: execution_context.gas_counter, + gas_allowance_counter: execution_context.gas_allowance_counter, + }; + let msg_ctx_settings = gear_core::message::ContextSettings::new(0, outgoing_limit); + + let program_id = program.id(); + + let exec_result = executor::execute_wasm::( + balance, + program, + memory_pages, + dispatch.clone(), + execution_context, + execution_settings, + msg_ctx_settings, + ) + .map_err(|err| { + log::debug!("Wasm execution error: {}", err.reason); + err + }); + + match exec_result { + Ok(res) => match res.kind { + DispatchResultKind::Trap(reason) => process_error( + res.dispatch, + program_id, + res.gas_amount.burned(), + ExecutionErrorReason::Ext(reason), + ), + DispatchResultKind::Success => process_success(Success, res), + DispatchResultKind::Wait => process_success(Wait, res), + DispatchResultKind::Exit(value_destination) => { + process_success(Exit(value_destination), res) + } + DispatchResultKind::GasAllowanceExceed => { + process_allowance_exceed(dispatch, program_id, res.gas_amount.burned()) + } + }, + Err(e) => match e.reason { + ExecutionErrorReason::InitialMemoryBlockGasExceeded + | ExecutionErrorReason::GrowMemoryBlockGasExceeded + | ExecutionErrorReason::LoadMemoryBlockGasExceeded => { + process_allowance_exceed(dispatch, program_id, e.gas_amount.burned()) + } + _ => process_error(dispatch, program_id, e.gas_amount.burned(), e.reason), + }, } } @@ -269,83 +386,6 @@ fn process_success( journal } -pub fn process_executable>( - origin: ProgramId, - gas_allowance: u64, - data: ExecutableActorData, - dispatch: IncomingDispatch, - balance: u128, - block_config: BlockConfig, -) -> Vec { - use SuccessfulDispatchResultKind::*; - - let BlockConfig { - block_info, - allocations_config, - existential_deposit, - outgoing_limit, - host_fn_weights, - forbidden_funcs, - mailbox_threshold, - } = block_config; - - let execution_settings = ExecutionSettings::new( - block_info, - existential_deposit, - allocations_config, - host_fn_weights, - forbidden_funcs, - mailbox_threshold, - ); - let execution_context = WasmExecutionContext { - origin, - gas_allowance, - }; - let msg_ctx_settings = gear_core::message::ContextSettings::new(0, outgoing_limit); - - let program_id = data.program.id(); - - let exec_result = executor::execute_wasm::( - balance, - data, - dispatch.clone(), - execution_context, - execution_settings, - msg_ctx_settings, - ) - .map_err(|err| { - log::debug!("Wasm execution error: {}", err.reason); - err - }); - - match exec_result { - Ok(res) => match res.kind { - DispatchResultKind::Trap(reason) => process_error( - res.dispatch, - program_id, - res.gas_amount.burned(), - ExecutionErrorReason::Ext(reason), - ), - DispatchResultKind::Success => process_success(Success, res), - DispatchResultKind::Wait => process_success(Wait, res), - DispatchResultKind::Exit(value_destination) => { - process_success(Exit(value_destination), res) - } - DispatchResultKind::GasAllowanceExceed => { - process_allowance_exceed(dispatch, program_id, res.gas_amount.burned()) - } - }, - Err(e) => match e.reason { - ExecutionErrorReason::InitialMemoryBlockGasExceeded - | ExecutionErrorReason::GrowMemoryBlockGasExceeded - | ExecutionErrorReason::LoadMemoryBlockGasExceeded => { - process_allowance_exceed(dispatch, program_id, e.gas_amount.burned()) - } - _ => process_error(dispatch, program_id, e.gas_amount.burned(), e.reason), - }, - } -} - fn process_allowance_exceed( dispatch: IncomingDispatch, program_id: ProgramId, diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index cfeabb5d889..705aa652c32 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -141,7 +141,7 @@ pub mod pallet { JournalNote, }, configs::{AllocationsConfig, BlockConfig, BlockInfo, MessageExecutionContext}, - Ext, + Ext, PrepareResult, }; use frame_support::{ dispatch::{DispatchError, DispatchResultWithPostInfo}, @@ -788,16 +788,42 @@ pub mod pallet { gas_allowance: u64::MAX, }; - let journal = if lazy_pages_enabled { - core_processor::process::>( - &block_config, - message_execution_context, - ) - } else { - core_processor::process::>( - &block_config, - message_execution_context, - ) + let journal = match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::Ok{ context, pages_with_data } => { + // load memory pages + let memory_pages = if lazy_pages_enabled { + Default::default() + } else { + match common::get_program_data_for_pages( + actor_id.into_origin(), + pages_with_data.iter(), + ) { + Ok(data) => data, + Err(err) => { + log::error!( + "Page data in storage is in invalid state: {}", + err + ); + continue; + } + } + }; + + if lazy_pages_enabled { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } else { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } + } + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, }; let get_main_limit = || { @@ -1131,27 +1157,9 @@ pub mod pallet { matches!(prog.state, ProgramState::Initialized), ); - let pages_data = if lazy_pages_enabled { - Default::default() - } else { - match common::get_program_data_for_pages( - dispatch.destination().into_origin(), - prog.pages_with_data.iter(), - ) { - Ok(data) => data, - Err(err) => { - log::error!( - "Page data in storage is in invalid state: {}", - err - ); - continue; - } - } - }; - Some(ExecutableActorData { program, - pages_data, + pages_with_data: prog.pages_with_data, }) } else { // Reaching this branch is possible when init message was processed with failure, while other kind of messages @@ -1176,10 +1184,11 @@ pub mod pallet { ) .unique_saturated_into(); + let program_id = dispatch.destination(); let message_execution_context = MessageExecutionContext { actor: Actor { balance, - destination_program: dispatch.destination(), + destination_program: program_id, executable_data: active_actor_data, }, dispatch: dispatch.into_incoming(gas_limit), @@ -1187,16 +1196,43 @@ pub mod pallet { gas_allowance: GasAllowanceOf::::get(), }; - let journal = if lazy_pages_enabled { - core_processor::process::>( - &block_config, - message_execution_context, - ) - } else { - core_processor::process::>( - &block_config, - message_execution_context, - ) + let journal = match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::Ok{ context, pages_with_data } => { + // load memory pages + // todo!(); + let memory_pages = if lazy_pages_enabled { + Default::default() + } else { + match common::get_program_data_for_pages( + program_id.into_origin(), + pages_with_data.iter(), + ) { + Ok(data) => data, + Err(err) => { + log::error!( + "Page data in storage is in invalid state: {}", + err + ); + continue; + } + } + }; + + if lazy_pages_enabled { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } else { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } + } + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, }; core_processor::handle_journal(journal, &mut ext_manager); diff --git a/pallets/gear/src/manager/mod.rs b/pallets/gear/src/manager/mod.rs index 5522f7e4179..fe7154a49d7 100644 --- a/pallets/gear/src/manager/mod.rs +++ b/pallets/gear/src/manager/mod.rs @@ -161,21 +161,15 @@ where }; let balance = - CurrencyOf::::free_balance(&::from_origin(id.into_origin())) - .unique_saturated_into(); - let pages_data = if with_pages { - common::get_program_data_for_pages(id.into_origin(), active.pages_with_data.iter()) - .ok()? - } else { - Default::default() - }; + CurrencyOf::::free_balance(&::from_origin(id.into_origin())) + .unique_saturated_into(); Some(Actor { balance, destination_program: id, executable_data: Some(ExecutableActorData { program, - pages_data, + pages_with_data: active.pages_with_data, }), }) } From df9a7a23adf79dec792b402780f61a7dac669201 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 20 Jul 2022 11:32:14 +0400 Subject: [PATCH 03/16] return memory_size from charge_for_pages adjust to the change --- core-processor/src/executor.rs | 139 ++++++++++---------------------- core-processor/src/processor.rs | 17 ++-- 2 files changed, 53 insertions(+), 103 deletions(-) diff --git a/core-processor/src/executor.rs b/core-processor/src/executor.rs index c48152fa391..b794604dc02 100644 --- a/core-processor/src/executor.rs +++ b/core-processor/src/executor.rs @@ -18,7 +18,7 @@ use crate::{ common::{ - DispatchResult, DispatchResultKind, ExecutableActorData, ExecutionError, + DispatchResult, DispatchResultKind, ExecutionError, ExecutionErrorReason, WasmExecutionContext, }, configs::{ExecutionSettings, AllocationsConfig}, @@ -34,21 +34,16 @@ use gear_core::{ gas::{ChargeResult, GasAllowanceCounter, GasCounter, ValueCounter}, ids::ProgramId, memory::{AllocationsContext, Memory, PageBuf, PageNumber, WasmPageNumber}, - message::{ContextSettings, DispatchKind, IncomingDispatch, MessageContext}, program::Program, + message::{ContextSettings, IncomingDispatch, MessageContext}, program::Program, }; -/// Make checks that everything with memory pages go well. -/// Charge gas for pages init/load/grow and checks that there is enough gas for that. -/// Returns size of wasm memory buffer which must be created in execution environment. -fn make_checks_and_charge_gas_for_pages<'a>( - settings: &ExecutionSettings, - gas_counter: &mut GasCounter, - gas_allowance_counter: &mut GasAllowanceCounter, +/// Make checks that everything with memory goes well. +fn check_memory<'a>( allocations: &BTreeSet, pages_with_data: impl Iterator, static_pages: WasmPageNumber, - initial_execution: bool, -) -> Result { + memory_size: WasmPageNumber, +) -> Result<(), ExecutionErrorReason> { // Checks that all pages with data are in allocations set. for page in pages_with_data { let wasm_page = page.to_wasm_page(); @@ -57,75 +52,37 @@ fn make_checks_and_charge_gas_for_pages<'a>( } } - let mem_size = if !initial_execution { - let max_wasm_page = if let Some(page) = allocations.iter().next_back() { - *page - } else if static_pages != WasmPageNumber(0) { - static_pages - 1.into() - } else { - return Ok(0.into()); - }; - - // Charging gas for loaded pages - // let amount = settings.load_page_cost() * (allocations.len() as u64 + static_pages.0 as u64); - - // if gas_allowance_counter.charge(amount) != ChargeResult::Enough { - // return Err(ExecutionErrorReason::LoadMemoryBlockGasExceeded); - // } - - // if gas_counter.charge(amount) != ChargeResult::Enough { - // return Err(ExecutionErrorReason::LoadMemoryGasExceeded); - // } - - // // Charging gas for mem size - // let amount = - // settings.mem_grow_cost() * (max_wasm_page.0 as u64 + 1 - static_pages.0 as u64); - - // if gas_allowance_counter.charge(amount) != ChargeResult::Enough { - // return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); - // } - - // if gas_counter.charge(amount) != ChargeResult::Enough { - // return Err(ExecutionErrorReason::GrowMemoryGasExceeded); - // } - - // +1 because pages numeration begins from 0 - max_wasm_page + 1.into() - } else { - // Charging gas for initial pages - // let amount = settings.init_cost() * static_pages.0 as u64; - - // if gas_allowance_counter.charge(amount) != ChargeResult::Enough { - // return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); - // } - - // if gas_counter.charge(amount) != ChargeResult::Enough { - // return Err(ExecutionErrorReason::InitialMemoryGasExceeded); - // } - - static_pages - }; - - if mem_size < static_pages { + if memory_size < static_pages { log::error!( "Mem size less then static pages num: mem_size = {:?}, static_pages = {:?}", - mem_size, + memory_size, static_pages ); return Err(ExecutionErrorReason::InsufficientMemorySize); } - Ok(mem_size) + Ok(()) } -pub(crate) fn charge_gas_for_pages<'a>( +/// Charge gas for pages init/load/grow and checks that there is enough gas for that. +/// Returns size of wasm memory buffer which must be created in execution environment. +pub(crate) fn charge_gas_for_pages( settings: &AllocationsConfig, gas_counter: &mut GasCounter, gas_allowance_counter: &mut GasAllowanceCounter, allocations: &BTreeSet, static_pages: WasmPageNumber, -) -> Result<(), ExecutionErrorReason> { - let mem_size = if let Some(max_wasm_page) = allocations.iter().next_back() { + initial_execution: bool, +) -> Result { + if !initial_execution { + let max_wasm_page = if let Some(page) = allocations.iter().next_back() { + *page + } else if static_pages != WasmPageNumber(0) { + static_pages - 1.into() + } else { + return Ok(0.into()); + }; + // Charging gas for loaded pages let amount = settings.load_page_cost * allocations.len() as u64; @@ -150,7 +107,7 @@ pub(crate) fn charge_gas_for_pages<'a>( } // +1 because pages numeration begins from 0 - *max_wasm_page + 1.into() + Ok(max_wasm_page + 1.into()) } else { // Charging gas for initial pages let amount = settings.init_cost * static_pages.0 as u64; @@ -163,19 +120,8 @@ pub(crate) fn charge_gas_for_pages<'a>( return Err(ExecutionErrorReason::InitialMemoryGasExceeded); } - static_pages - }; - - if mem_size < static_pages { - log::error!( - "Mem size less then static pages num: mem_size = {:?}, static_pages = {:?}", - mem_size, - static_pages - ); - return Err(ExecutionErrorReason::InsufficientMemorySize); + Ok(static_pages) } - - Ok(()) } /// Writes initial pages data to memory and prepare memory for execution. @@ -273,6 +219,7 @@ pub fn execute_wasm, + memory_size: WasmPageNumber, dispatch: IncomingDispatch, context: WasmExecutionContext, settings: ExecutionSettings, @@ -293,35 +240,31 @@ pub fn execute_wasm mem_size, - Err(reason) => { - return Err(ExecutionError { - program_id, - gas_amount: gas_counter.into(), - reason, - }) - } - }; + Err(reason) => return Err(ExecutionError { + program_id, + gas_amount: gas_counter.into(), + reason, + }), + _ => (), + } // Creating allocations context. let allocations_context = AllocationsContext::new( - program.get_allocations().clone(), + allocations.clone(), static_pages, settings.max_pages(), ); @@ -361,7 +304,7 @@ pub fn execute_wasm size, + Err(reason) => { + log::debug!("failed to charge for memory pages: {:?}", reason); + return PrepareResult::Error(process_error(dispatch, program_id, gas_counter.burned(), reason)); + } + }; PrepareResult::Ok{ context: PreparedMessageExecutionContext { @@ -103,6 +107,7 @@ pub fn prepare( origin, balance, program: data.program, + memory_size, }, pages_with_data: data.pages_with_data, } @@ -138,6 +143,7 @@ pub fn process Date: Wed, 20 Jul 2022 14:30:22 +0400 Subject: [PATCH 04/16] adjust calculate_gas_info to ... the case when program's memory already has been loaded. --- core-processor/src/configs.rs | 2 ++ core-processor/src/executor.rs | 20 +++++++++++--------- core-processor/src/processor.rs | 9 ++++++++- pallets/gear/src/lib.rs | 33 ++++++++++++++++++++++++++++----- pallets/gear/src/manager/mod.rs | 18 +++++++++++++++++- pallets/gear/src/tests.rs | 9 ++++++--- 6 files changed, 72 insertions(+), 19 deletions(-) diff --git a/core-processor/src/configs.rs b/core-processor/src/configs.rs index c38d9374641..ac4343ca403 100644 --- a/core-processor/src/configs.rs +++ b/core-processor/src/configs.rs @@ -159,4 +159,6 @@ pub struct MessageExecutionContext { pub origin: ProgramId, /// Gas allowance. pub gas_allowance: u64, + /// The program is being executed the second or next time in the block. + pub subsequent_execution: bool, } diff --git a/core-processor/src/executor.rs b/core-processor/src/executor.rs index b794604dc02..1b7455a3400 100644 --- a/core-processor/src/executor.rs +++ b/core-processor/src/executor.rs @@ -73,6 +73,7 @@ pub(crate) fn charge_gas_for_pages( allocations: &BTreeSet, static_pages: WasmPageNumber, initial_execution: bool, + subsequent_execution: bool, ) -> Result { if !initial_execution { let max_wasm_page = if let Some(page) = allocations.iter().next_back() { @@ -83,15 +84,16 @@ pub(crate) fn charge_gas_for_pages( return Ok(0.into()); }; - // Charging gas for loaded pages - let amount = settings.load_page_cost * allocations.len() as u64; - - if gas_allowance_counter.charge(amount) != ChargeResult::Enough { - return Err(ExecutionErrorReason::LoadMemoryBlockGasExceeded); - } + if !subsequent_execution { + // Charging gas for loaded pages + let amount = settings.load_page_cost * (allocations.len() as u64 + static_pages.0 as u64); + if gas_allowance_counter.charge(amount) != ChargeResult::Enough { + return Err(ExecutionErrorReason::LoadMemoryBlockGasExceeded); + } - if gas_counter.charge(amount) != ChargeResult::Enough { - return Err(ExecutionErrorReason::LoadMemoryGasExceeded); + if gas_counter.charge(amount) != ChargeResult::Enough { + return Err(ExecutionErrorReason::LoadMemoryGasExceeded); + } } // Charging gas for mem size @@ -113,7 +115,7 @@ pub(crate) fn charge_gas_for_pages( let amount = settings.init_cost * static_pages.0 as u64; if gas_allowance_counter.charge(amount) != ChargeResult::Enough { - return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); + return Err(ExecutionErrorReason::InitialMemoryBlockGasExceeded); } if gas_counter.charge(amount) != ChargeResult::Enough { diff --git a/core-processor/src/processor.rs b/core-processor/src/processor.rs index 9b430f5a78c..9735dfa1449 100644 --- a/core-processor/src/processor.rs +++ b/core-processor/src/processor.rs @@ -52,6 +52,12 @@ pub struct PreparedMessageExecutionContext { memory_size: WasmPageNumber, } +impl PreparedMessageExecutionContext { + pub fn gas_counter(&self) -> &GasCounter { + &self.gas_counter + } +} + pub enum PrepareResult { Ok { context: PreparedMessageExecutionContext, @@ -70,6 +76,7 @@ pub fn prepare( dispatch, origin, gas_allowance, + subsequent_execution, } = execution_context; let Actor { balance, @@ -91,7 +98,7 @@ pub fn prepare( } let mut gas_allowance_counter = GasAllowanceCounter::new(gas_allowance); - let memory_size = match executor::charge_gas_for_pages(&block_config.allocations_config, &mut gas_counter, &mut gas_allowance_counter, program.get_allocations(), program.static_pages(), dispatch.context().is_none() && matches!(dispatch.kind(), DispatchKind::Init)) { + let memory_size = match executor::charge_gas_for_pages(&block_config.allocations_config, &mut gas_counter, &mut gas_allowance_counter, program.get_allocations(), program.static_pages(), dispatch.context().is_none() && matches!(dispatch.kind(), DispatchKind::Init), subsequent_execution) { Ok(size) => size, Err(reason) => { log::debug!("failed to charge for memory pages: {:?}", reason); diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index 705aa652c32..f887e4c3858 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -120,6 +120,8 @@ pub struct GasInfo { pub reserved: u64, /// Contains number of gas burned during message processing. pub burned: u64, + /// The value may be returned if a program happens to be executed the second or next time in a block. + pub may_be_returned: u64, } #[frame_support::pallet] @@ -640,11 +642,12 @@ pub mod pallet { ) .map( |GasInfo { - reserved, burned, .. + reserved, burned, may_be_returned, .. }| GasInfo { min_limit, reserved, burned, + may_be_returned, }, ) .map_err(|e| { @@ -758,6 +761,7 @@ pub mod pallet { let mut min_limit = 0; let mut reserved = 0; let mut burned = 0; + let mut may_be_returned = 0; let mut ext_manager = ExtManager::::default(); @@ -770,7 +774,7 @@ pub mod pallet { cfg!(feature = "lazy-pages") && lazy_pages::try_to_enable_lazy_pages(); let actor = ext_manager - .get_actor(actor_id, !lazy_pages_enabled) + .get_actor(actor_id) .ok_or_else(|| b"Program not found in the storage".to_vec())?; let dispatch_id = queued_dispatch.id(); @@ -781,16 +785,22 @@ pub mod pallet { b"Internal error: unable to get gas limit after execution".to_vec() })?; + let subsequent_execution = ext_manager.program_pages_loaded(&actor_id); let message_execution_context = MessageExecutionContext { actor, dispatch: queued_dispatch.into_incoming(gas_limit), origin: ProgramId::from_origin(source), gas_allowance: u64::MAX, + subsequent_execution, }; + let may_be_returned_context = (!subsequent_execution && actor_id == main_program_id).then(|| MessageExecutionContext { + subsequent_execution: true, + ..message_execution_context.clone() + }); + let journal = match core_processor::prepare(&block_config, message_execution_context) { PrepareResult::Ok{ context, pages_with_data } => { - // load memory pages let memory_pages = if lazy_pages_enabled { Default::default() } else { @@ -809,6 +819,17 @@ pub mod pallet { } }; + ext_manager.insert_program_id_loaded_pages(actor_id); + + may_be_returned += may_be_returned_context.map(|c| { + let burned = match core_processor::prepare(&block_config, c) { + PrepareResult::Ok { context, .. } => context.gas_counter().burned(), + _ => context.gas_counter().burned(), + }; + + context.gas_counter().burned() - burned + }).unwrap_or(0); + if lazy_pages_enabled { core_processor::process::>( &block_config, @@ -895,6 +916,7 @@ pub mod pallet { min_limit, reserved, burned, + may_be_returned, }) } @@ -1194,12 +1216,11 @@ pub mod pallet { dispatch: dispatch.into_incoming(gas_limit), origin: ProgramId::from_origin(external.into_origin()), gas_allowance: GasAllowanceOf::::get(), + subsequent_execution: ext_manager.program_pages_loaded(&program_id), }; let journal = match core_processor::prepare(&block_config, message_execution_context) { PrepareResult::Ok{ context, pages_with_data } => { - // load memory pages - // todo!(); let memory_pages = if lazy_pages_enabled { Default::default() } else { @@ -1217,6 +1238,8 @@ pub mod pallet { } } }; + + ext_manager.insert_program_id_loaded_pages(program_id); if lazy_pages_enabled { core_processor::process::>( diff --git a/pallets/gear/src/manager/mod.rs b/pallets/gear/src/manager/mod.rs index fe7154a49d7..059a4edfaff 100644 --- a/pallets/gear/src/manager/mod.rs +++ b/pallets/gear/src/manager/mod.rs @@ -80,6 +80,8 @@ pub struct ExtManager { users: BTreeSet, /// Ids checked that they are programs. programs: BTreeSet, + /// Ids of programs which memory pages have been loaded earlier during processing a block. + program_loaded_pages: BTreeSet, /// Messages dispatches. dispatch_statuses: BTreeMap, /// Programs, which state changed. @@ -114,6 +116,7 @@ where _phantom: PhantomData, users: Default::default(), programs: Default::default(), + program_loaded_pages: Default::default(), dispatch_statuses: Default::default(), state_changes: Default::default(), } @@ -145,9 +148,22 @@ where !self.check_program_id(id) } + /// Checks if memory pages of a program were loaded. + pub fn program_pages_loaded(&self, id: &ProgramId) -> bool { + self.program_loaded_pages.contains(id) + } + + /// Adds program's id to the collection of programs with + /// loaded memory pages. + pub fn insert_program_id_loaded_pages(&mut self, id: ProgramId) { + assert!(self.check_program_id(&id)); + + self.program_loaded_pages.insert(id); + } + /// NOTE: By calling this function we can't differ whether `None` returned, because /// program with `id` doesn't exist or it's terminated - pub fn get_actor(&self, id: ProgramId, with_pages: bool) -> Option { + pub fn get_actor(&self, id: ProgramId) -> Option { let active: ActiveProgram = common::get_program(id.into_origin())?.try_into().ok()?; let program = { let code_id = CodeId::from_origin(active.code_hash); diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 39c55c119ac..85a06e6e204 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -69,6 +69,7 @@ fn unstoppable_block_execution_works() { let GasInfo { burned: expected_burned_gas, + may_be_returned, .. } = Gear::calculate_gas_info( USER_1.into_origin(), @@ -91,7 +92,7 @@ fn unstoppable_block_execution_works() { )); } - let real_gas_to_burn = expected_burned_gas * executions_amount; + let real_gas_to_burn = expected_burned_gas + executions_amount.saturating_sub(1) * (expected_burned_gas - may_be_returned); assert!(balance_for_each_execution * executions_amount > real_gas_to_burn); @@ -1566,7 +1567,9 @@ fn claim_value_from_mailbox_works() { assert!(!MailboxOf::::is_empty(&USER_1)); let GasInfo { - burned: gas_burned, .. + burned: gas_burned, + may_be_returned, + .. } = Gear::calculate_gas_info( USER_1.into_origin(), HandleKind::Handle(prog_id), @@ -1576,7 +1579,7 @@ fn claim_value_from_mailbox_works() { ) .expect("calculate_gas_info failed"); - let gas_burned = GasPrice::gas_price(gas_burned); + let gas_burned = GasPrice::gas_price(gas_burned - may_be_returned); run_to_block(3, None); From fe3ac64d1117101d9f3c289a9aca47a1eb2e044e Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 20 Jul 2022 17:17:51 +0400 Subject: [PATCH 05/16] pre-commit --- core-processor/src/common.rs | 8 +- core-processor/src/configs.rs | 20 --- core-processor/src/executor.rs | 46 +++-- core-processor/src/lib.rs | 2 +- core-processor/src/processor.rs | 70 ++++++-- gear-test/src/check.rs | 13 +- gear-test/src/manager.rs | 28 ++-- gear-test/src/proc.rs | 36 +++- gtest/src/manager.rs | 43 +++-- pallets/gear/src/benchmarking/mod.rs | 186 +++++++++++++-------- pallets/gear/src/lib.rs | 185 +++++++++++--------- pallets/gear/src/manager/mod.rs | 4 +- pallets/gear/src/tests.rs | 23 +-- utils/gear-runtime-test-cli/src/command.rs | 20 ++- 14 files changed, 409 insertions(+), 275 deletions(-) diff --git a/core-processor/src/common.rs b/core-processor/src/common.rs index 2a2b68e9b8c..4035a6d0b3b 100644 --- a/core-processor/src/common.rs +++ b/core-processor/src/common.rs @@ -26,7 +26,7 @@ use alloc::{ use codec::{Decode, Encode}; use gear_backend_common::TrapExplanation; use gear_core::{ - gas::{GasAmount, GasAllowanceCounter, GasCounter}, + gas::{GasAllowanceCounter, GasAmount, GasCounter}, ids::{CodeId, MessageId, ProgramId}, memory::{PageBuf, PageNumber, WasmPageNumber}, message::{ContextStore, Dispatch, IncomingDispatch, StoredDispatch}, @@ -390,4 +390,10 @@ pub struct WasmExecutionContext { pub gas_counter: GasCounter, /// A counter for gas allowance. pub gas_allowance_counter: GasAllowanceCounter, + /// Program to be executed. + pub program: Program, + /// Memory pages with initial data. + pub pages_initial_data: BTreeMap, + /// Size of the memory block. + pub memory_size: WasmPageNumber, } diff --git a/core-processor/src/configs.rs b/core-processor/src/configs.rs index ac4343ca403..48d84f5ca60 100644 --- a/core-processor/src/configs.rs +++ b/core-processor/src/configs.rs @@ -107,26 +107,6 @@ impl ExecutionSettings { pub fn max_pages(&self) -> WasmPageNumber { self.allocations_config.max_pages } - - /// Cost of initial memory. - pub fn init_cost(&self) -> u64 { - self.allocations_config.init_cost - } - - /// Cost of allocating memory. - pub fn alloc_cost(&self) -> u64 { - self.allocations_config.alloc_cost - } - - /// Memory grow cost. - pub fn mem_grow_cost(&self) -> u64 { - self.allocations_config.mem_grow_cost - } - - /// Load gear page cost. - pub fn load_page_cost(&self) -> u64 { - self.allocations_config.load_page_cost - } } /// Stable parameters for the whole block across processing runs. diff --git a/core-processor/src/executor.rs b/core-processor/src/executor.rs index 1b7455a3400..7efaf559c8a 100644 --- a/core-processor/src/executor.rs +++ b/core-processor/src/executor.rs @@ -18,10 +18,10 @@ use crate::{ common::{ - DispatchResult, DispatchResultKind, ExecutionError, - ExecutionErrorReason, WasmExecutionContext, + DispatchResult, DispatchResultKind, ExecutionError, ExecutionErrorReason, + WasmExecutionContext, }, - configs::{ExecutionSettings, AllocationsConfig}, + configs::{AllocationsConfig, ExecutionSettings}, ext::{ProcessorContext, ProcessorExt}, }; use alloc::{ @@ -34,7 +34,7 @@ use gear_core::{ gas::{ChargeResult, GasAllowanceCounter, GasCounter, ValueCounter}, ids::ProgramId, memory::{AllocationsContext, Memory, PageBuf, PageNumber, WasmPageNumber}, - message::{ContextSettings, IncomingDispatch, MessageContext}, program::Program, + message::{ContextSettings, IncomingDispatch, MessageContext}, }; /// Make checks that everything with memory goes well. @@ -86,7 +86,8 @@ pub(crate) fn charge_gas_for_pages( if !subsequent_execution { // Charging gas for loaded pages - let amount = settings.load_page_cost * (allocations.len() as u64 + static_pages.0 as u64); + let amount = + settings.load_page_cost * (allocations.len() as u64 + static_pages.0 as u64); if gas_allowance_counter.charge(amount) != ChargeResult::Enough { return Err(ExecutionErrorReason::LoadMemoryBlockGasExceeded); } @@ -97,8 +98,7 @@ pub(crate) fn charge_gas_for_pages( } // Charging gas for mem size - let amount = - settings.mem_grow_cost * (max_wasm_page.0 as u64 + 1 - static_pages.0 as u64); + let amount = settings.mem_grow_cost * (max_wasm_page.0 as u64 + 1 - static_pages.0 as u64); if gas_allowance_counter.charge(amount) != ChargeResult::Enough { return Err(ExecutionErrorReason::GrowMemoryBlockGasExceeded); @@ -219,9 +219,6 @@ fn get_pages_to_be_updated( /// Execute wasm with dispatch and return dispatch result. pub fn execute_wasm>( balance: u128, - program: Program, - mut pages_initial_data: BTreeMap, - memory_size: WasmPageNumber, dispatch: IncomingDispatch, context: WasmExecutionContext, settings: ExecutionSettings, @@ -235,41 +232,40 @@ pub fn execute_wasm return Err(ExecutionError { + return Err(ExecutionError { program_id, gas_amount: gas_counter.into(), reason, - }), - _ => (), + }); } // Creating allocations context. - let allocations_context = AllocationsContext::new( - allocations.clone(), - static_pages, - settings.max_pages(), - ); + let allocations_context = + AllocationsContext::new(allocations.clone(), static_pages, settings.max_pages()); // Creating message context. let message_context = MessageContext::new_with_settings( diff --git a/core-processor/src/lib.rs b/core-processor/src/lib.rs index 4a0f51cbdf8..f0708bca72f 100644 --- a/core-processor/src/lib.rs +++ b/core-processor/src/lib.rs @@ -53,4 +53,4 @@ pub const RE_INIT_EXIT_CODE: ExitCode = 3; pub use executor::execute_wasm; pub use ext::{Ext, ProcessorContext, ProcessorError, ProcessorExt}; pub use handler::handle_journal; -pub use processor::{process, prepare, PrepareResult}; +pub use processor::{prepare, process, PrepareResult, PreparedMessageExecutionContext}; diff --git a/core-processor/src/processor.rs b/core-processor/src/processor.rs index 9735dfa1449..623c52b8b37 100644 --- a/core-processor/src/processor.rs +++ b/core-processor/src/processor.rs @@ -25,15 +25,22 @@ use crate::{ executor, ext::ProcessorExt, }; -use alloc::{string::ToString, vec::Vec, collections::{BTreeMap, BTreeSet}}; +use alloc::{ + collections::{BTreeMap, BTreeSet}, + string::ToString, + vec::Vec, +}; use codec::Encode; use gear_backend_common::{Environment, IntoExtInfo}; use gear_core::{ env::Ext as EnvExt, + gas::{GasAllowanceCounter, GasCounter}, ids::{MessageId, ProgramId}, + memory::{PageBuf, PageNumber, WasmPageNumber}, message::{ DispatchKind, ExitCode, IncomingDispatch, ReplyMessage, ReplyPacket, StoredDispatch, - }, gas::{GasCounter, GasAllowanceCounter}, memory::{PageNumber, PageBuf, WasmPageNumber}, program::Program, + }, + program::Program, }; enum SuccessfulDispatchResultKind { @@ -42,6 +49,7 @@ enum SuccessfulDispatchResultKind { Success, } +/// Checked parameters for message execution across processing runs. pub struct PreparedMessageExecutionContext { gas_counter: GasCounter, gas_allowance_counter: GasAllowanceCounter, @@ -53,20 +61,32 @@ pub struct PreparedMessageExecutionContext { } impl PreparedMessageExecutionContext { + /// Returns reference to the GasCounter. pub fn gas_counter(&self) -> &GasCounter { &self.gas_counter } } +/// Defines result variants of the function `prepare`. +#[allow(clippy::large_enum_variant)] pub enum PrepareResult { + /// Successfully precharged for memory pages. Ok { + /// A context for `process` function. context: PreparedMessageExecutionContext, + /// A set with numbers of memory pages which contain some data. pages_with_data: BTreeSet, }, + /// Required function is not exported. The program will not be executed. WontExecute(Vec), + /// Provided actor is not executable or there is not enough gas for memory pages size. Error(Vec), } +/// Prepares environment for the execution of a program. +/// Checks if there is a required export and tries to pre-charge for memory pages. +/// Returns either `PreparedMessageExecutionContext` for `process` or an array of journal notes. +/// See `PrepareResult` for details. pub fn prepare( block_config: &BlockConfig, execution_context: MessageExecutionContext, @@ -85,7 +105,13 @@ pub fn prepare( } = actor; let data = match check_is_executable(executable_data, &dispatch) { - Err(exit_code) => return PrepareResult::Error(process_non_executable(dispatch, destination_program, exit_code)), + Err(exit_code) => { + return PrepareResult::Error(process_non_executable( + dispatch, + destination_program, + exit_code, + )) + } Ok(data) => data, }; @@ -93,20 +119,37 @@ pub fn prepare( let program_id = program.id(); let mut gas_counter = GasCounter::new(dispatch.gas_limit()); if !program.code().exports().contains(&dispatch.kind()) { - return PrepareResult::WontExecute(process_success(SuccessfulDispatchResultKind::Success, - DispatchResult::success(dispatch, program_id, gas_counter.into()))); + return PrepareResult::WontExecute(process_success( + SuccessfulDispatchResultKind::Success, + DispatchResult::success(dispatch, program_id, gas_counter.into()), + )); } let mut gas_allowance_counter = GasAllowanceCounter::new(gas_allowance); - let memory_size = match executor::charge_gas_for_pages(&block_config.allocations_config, &mut gas_counter, &mut gas_allowance_counter, program.get_allocations(), program.static_pages(), dispatch.context().is_none() && matches!(dispatch.kind(), DispatchKind::Init), subsequent_execution) { + let memory_size = match executor::charge_gas_for_pages( + &block_config.allocations_config, + &mut gas_counter, + &mut gas_allowance_counter, + program.get_allocations(), + program.static_pages(), + dispatch.context().is_none() && matches!(dispatch.kind(), DispatchKind::Init), + subsequent_execution, + ) { Ok(size) => size, Err(reason) => { log::debug!("failed to charge for memory pages: {:?}", reason); - return PrepareResult::Error(process_error(dispatch, program_id, gas_counter.burned(), reason)); + return PrepareResult::Error(match reason { + ExecutionErrorReason::InitialMemoryBlockGasExceeded + | ExecutionErrorReason::GrowMemoryBlockGasExceeded + | ExecutionErrorReason::LoadMemoryBlockGasExceeded => { + process_allowance_exceed(dispatch, program_id, gas_counter.burned()) + } + _ => process_error(dispatch, program_id, gas_counter.burned(), reason), + }); } }; - PrepareResult::Ok{ + PrepareResult::Ok { context: PreparedMessageExecutionContext { gas_counter, gas_allowance_counter, @@ -149,22 +192,19 @@ pub fn process( balance, - program, - memory_pages, - memory_size, dispatch.clone(), execution_context, execution_settings, diff --git a/gear-test/src/check.rs b/gear-test/src/check.rs index e0fb9dfab10..49eedacf91b 100644 --- a/gear-test/src/check.rs +++ b/gear-test/src/check.rs @@ -34,7 +34,7 @@ use gear_backend_common::Environment; use gear_core::{ code::Code, ids::{CodeId, MessageId, ProgramId}, - memory::PageNumber, + memory::{PageBuf, PageNumber}, message::*, program::Program, }; @@ -414,15 +414,15 @@ pub fn check_allocations( } pub fn check_memory( - actors_data: &Vec, + actors_data: &Vec<(ExecutableActorData, BTreeMap)>, expected_memory: &[sample::BytesAt], ) -> Result<(), Vec> { let mut errors = Vec::new(); for case in expected_memory { - for data in actors_data { + for (data, memory) in actors_data { if data.program.id() == case.id.to_program_id() { let page = PageNumber::new_from_addr(case.address); - if let Some(page_buf) = data.pages_data.get(&page) { + if let Some(page_buf) = memory.get(&page) { let begin_byte = case.address - page.offset(); let end_byte = begin_byte + case.bytes.len(); if page_buf[begin_byte..end_byte] != case.bytes { @@ -622,7 +622,10 @@ where let data = final_state .actors .into_iter() - .filter_map(|(_, actor)| actor.executable_data) + .filter_map(|(_, actor)| match actor.executable_data { + None => None, + Some(d) => Some((d, actor.memory_pages)), + }) .collect(); if let Err(mem_errors) = check_memory(&data, mem) { errors.push(format!("step: {:?}", exp.step)); diff --git a/gear-test/src/manager.rs b/gear-test/src/manager.rs index ca470a506c8..004361bcb83 100644 --- a/gear-test/src/manager.rs +++ b/gear-test/src/manager.rs @@ -77,20 +77,25 @@ pub trait CollectState { pub struct TestActor { pub balance: u128, pub executable_data: Option, + pub memory_pages: BTreeMap, } impl TestActor { - pub fn into_core(self, dest: ProgramId) -> Actor { + pub fn into_parts(self, dest: ProgramId) -> (Actor, BTreeMap) { let Self { balance, executable_data, + memory_pages, } = self; - Actor { - balance, - destination_program: dest, - executable_data, - } + ( + Actor { + balance, + destination_program: dest, + executable_data, + }, + memory_pages, + ) } } @@ -143,8 +148,9 @@ impl ExecutionContext for InMemoryExtManager { balance: 0, executable_data: Some(ExecutableActorData { program: program.clone(), - pages_data: Default::default(), + pages_with_data: Default::default(), }), + memory_pages: Default::default(), }, ); program @@ -281,14 +287,15 @@ impl JournalHandler for InMemoryExtManager { mut pages_data: BTreeMap, ) { if let TestActor { - executable_data: Some(data), + executable_data: Some(_), + memory_pages, .. } = self .actors .get_mut(&program_id) .expect("Program not found in storage") { - data.pages_data.append(&mut pages_data); + memory_pages.append(&mut pages_data); } else { unreachable!("Can't update page for terminated program"); } @@ -297,6 +304,7 @@ impl JournalHandler for InMemoryExtManager { fn update_allocations(&mut self, program_id: ProgramId, allocations: BTreeSet) { if let TestActor { executable_data: Some(data), + memory_pages, .. } = self .actors @@ -309,7 +317,7 @@ impl JournalHandler for InMemoryExtManager { .difference(&allocations) .flat_map(|p| p.to_gear_pages_iter()) { - data.pages_data.remove(&page); + memory_pages.remove(&page); } *data.program.get_allocations_mut() = allocations; diff --git a/gear-test/src/proc.rs b/gear-test/src/proc.rs index 5b64ac7dfff..67c7d40bfde 100644 --- a/gear-test/src/proc.rs +++ b/gear-test/src/proc.rs @@ -23,7 +23,7 @@ use crate::{ manager::{CollectState, State}, sample::{PayloadVariant, Test}, }; -use core_processor::{common::*, configs::*, Ext}; +use core_processor::{common::*, configs::*, Ext, PrepareResult}; use gear_backend_common::Environment; use gear_core::{ code::{Code, CodeAndId}, @@ -109,15 +109,21 @@ where destination_program: program_id, executable_data: Some(ExecutableActorData { program, - pages_data: Default::default(), + pages_with_data: Default::default(), }), }, dispatch: message.into(), origin: Default::default(), gas_allowance: u64::MAX, + subsequent_execution: false, }; - let journal = core_processor::process::(&block_config, message_execution_context); + let journal = match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, + PrepareResult::Ok { context, .. } => { + core_processor::process::(&block_config, context, Default::default()) + } + }; core_processor::handle_journal(journal, journal_handler); @@ -290,17 +296,25 @@ where let actor = state.actors.get(&program_id).cloned().unwrap_or_else(|| { panic!("Error: Message to user {:?} in dispatch queue!", program_id) }); - let actor = actor.into_core(program_id); + let (actor, memory_pages) = actor.into_parts(program_id); let message_execution_context = MessageExecutionContext { actor, dispatch: dispatch.into_incoming(gas_limit), origin: Default::default(), gas_allowance: u64::MAX, + subsequent_execution: false, }; let journal = - core_processor::process::(&block_config, message_execution_context); + match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => { + journal + } + PrepareResult::Ok { context, .. } => { + core_processor::process::(&block_config, context, memory_pages) + } + }; core_processor::handle_journal(journal, journal_handler); @@ -319,7 +333,7 @@ where let actor = state.actors.get(&program_id).cloned().unwrap_or_else(|| { panic!("Error: Message to user {:?} in dispatch queue!", program_id) }); - let actor = actor.into_core(program_id); + let (actor, memory_pages) = actor.into_parts(program_id); let timestamp = SystemTime::now() .duration_since(UNIX_EPOCH) .map(|d| d.as_millis()) @@ -335,10 +349,16 @@ where dispatch: dispatch.into_incoming(gas_limit), origin: Default::default(), gas_allowance: u64::MAX, + subsequent_execution: false, + }; + + let journal = match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, + PrepareResult::Ok { context, .. } => { + core_processor::process::(&block_config, context, memory_pages) + } }; - let journal = - core_processor::process::(&block_config, message_execution_context); counter += 1; core_processor::handle_journal(journal, journal_handler); diff --git a/gtest/src/manager.rs b/gtest/src/manager.rs index 0549e1b6c04..602360b9f22 100644 --- a/gtest/src/manager.rs +++ b/gtest/src/manager.rs @@ -25,7 +25,7 @@ use crate::{ use core_processor::{ common::*, configs::{BlockConfig, BlockInfo, MessageExecutionContext}, - Ext, + Ext, PrepareResult, }; use gear_backend_wasmtime::WasmtimeEnvironment; use gear_core::{ @@ -116,7 +116,9 @@ impl TestActor { } // Gets a new executable actor derived from the inner program. - fn get_executable_actor_data(&self) -> Option { + fn get_executable_actor_data( + &self, + ) -> Option<(ExecutableActorData, BTreeMap)> { let (program, pages_data) = match self { TestActor::Initialized(Program::Genuine { program, @@ -133,10 +135,13 @@ impl TestActor { ) => (program.clone(), pages_data.clone()), _ => return None, }; - Some(ExecutableActorData { - program, + Some(( + ExecutableActorData { + program, + pages_with_data: pages_data.keys().copied().collect(), + }, pages_data, - }) + )) } } @@ -324,8 +329,8 @@ impl ExtManager { if actor.is_dormant() { self.process_dormant(balance, dispatch); - } else if let Some(data) = actor.get_executable_actor_data() { - self.process_normal(balance, data, dispatch); + } else if let Some((data, memory_pages)) = actor.get_executable_actor_data() { + self.process_normal(balance, data, memory_pages, dispatch); } else if let Some(mock) = actor.take_mock() { self.process_mock(mock, dispatch); } else { @@ -545,19 +550,21 @@ impl ExtManager { &mut self, balance: u128, data: ExecutableActorData, + memory_pages: BTreeMap, dispatch: StoredDispatch, ) { - self.process_dispatch(balance, Some(data), dispatch); + self.process_dispatch(balance, Some(data), memory_pages, dispatch); } fn process_dormant(&mut self, balance: u128, dispatch: StoredDispatch) { - self.process_dispatch(balance, None, dispatch); + self.process_dispatch(balance, None, Default::default(), dispatch); } fn process_dispatch( &mut self, balance: u128, data: Option, + memory_pages: BTreeMap, dispatch: StoredDispatch, ) { let dest = dispatch.destination(); @@ -584,11 +591,16 @@ impl ExtManager { dispatch: dispatch.into_incoming(gas_limit), origin: self.origin, gas_allowance: u64::MAX, + subsequent_execution: false, + }; + + let journal = match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, + PrepareResult::Ok { context, .. } => core_processor::process::< + Ext, + WasmtimeEnvironment, + >(&block_config, context, memory_pages), }; - let journal = core_processor::process::>( - &block_config, - message_execution_context, - ); core_processor::handle_journal(journal, self); } @@ -604,11 +616,10 @@ impl ExtManager { .ok_or(TestError::ActorNotFound(*program_id))?; let code_id = actor.code_id(); - let data = actor + let (data, memory) = actor .get_executable_actor_data() .ok_or(TestError::ActorIsNotExecutable(*program_id))?; - let pages_initial_data = data - .pages_data + let pages_initial_data = memory .into_iter() .map(|(page, data)| (page, Box::new(data))) .collect(); diff --git a/pallets/gear/src/benchmarking/mod.rs b/pallets/gear/src/benchmarking/mod.rs index 69e7caa8054..ff75818978d 100644 --- a/pallets/gear/src/benchmarking/mod.rs +++ b/pallets/gear/src/benchmarking/mod.rs @@ -40,11 +40,17 @@ use codec::Encode; use common::{ benchmarking, lazy_pages, storage::*, CodeMetadata, CodeStorage, GasPrice, GasTree, Origin, }; -use core_processor::configs::{AllocationsConfig, BlockConfig, BlockInfo, MessageExecutionContext}; +use core_processor::{ + configs::{AllocationsConfig, BlockConfig, BlockInfo, MessageExecutionContext}, + PrepareResult, PreparedMessageExecutionContext, +}; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::traits::{Currency, Get, ReservableCurrency}; use frame_system::RawOrigin; -use gear_core::ids::{MessageId, ProgramId}; +use gear_core::{ + ids::{MessageId, ProgramId}, + memory::{PageBuf, PageNumber}, +}; use sp_core::H256; use sp_runtime::{ traits::{Bounded, UniqueSaturatedInto}, @@ -127,7 +133,8 @@ fn caller_funding() -> BalanceOf { struct Exec { ext_manager: ExtManager, block_config: BlockConfig, - message_execution_context: MessageExecutionContext, + context: PreparedMessageExecutionContext, + memory_pages: BTreeMap, } fn prepare( @@ -250,8 +257,7 @@ where if let Some(queued_dispatch) = QueueOf::::dequeue().map_err(|_| "MQ storage corrupted")? { let actor_id = queued_dispatch.destination(); let actor = ext_manager - // get actor without pages data because of lazy pages enabled - .get_actor(actor_id, false) + .get_actor(actor_id) .ok_or("Program not found in the storage")?; let message_execution_context = MessageExecutionContext { @@ -259,12 +265,20 @@ where dispatch: queued_dispatch.into_incoming(initial_gas), origin: ProgramId::from_origin(source), gas_allowance: u64::MAX, + subsequent_execution: false, + }; + + let context = match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::Ok { context, .. } => context, + _ => return Err("core_processor::prepare failed"), }; Ok(Exec { ext_manager, block_config, - message_execution_context, + context, + // actor without pages data because of lazy pages enabled + memory_pages: Default::default(), }) } else { Err("Dispatch not found") @@ -459,13 +473,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } // TODO: benchmark batches and size is bigger than memory limits @@ -521,14 +536,15 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_gas_available { @@ -551,13 +567,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_msg_id { @@ -568,13 +585,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_origin { @@ -585,13 +603,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_program_id { @@ -602,13 +621,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_source { @@ -620,13 +640,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_value { @@ -637,13 +658,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_value_available { @@ -654,13 +676,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_size { @@ -683,13 +706,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_read { @@ -723,13 +747,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_read_per_kb { @@ -767,13 +792,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![0xff; (n * 1024) as usize], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_block_height { @@ -796,13 +822,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_block_timestamp { @@ -825,13 +852,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_send_init { @@ -855,13 +883,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -897,13 +926,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -939,13 +969,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -992,13 +1023,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 10000000u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1045,13 +1077,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 10000000u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1088,13 +1121,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 10000000u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1129,13 +1163,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 10000000u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1171,13 +1206,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 10000000u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_reply_push_per_kb { @@ -1210,13 +1246,14 @@ benchmarks! { let Exec { ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 10000000u32.into())?; }: { core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); } gr_reply_to { @@ -1242,13 +1279,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Reply(msg_id, 0), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1273,13 +1311,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1306,13 +1345,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Reply(msg_id, 0), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1346,13 +1386,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1377,13 +1418,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1408,13 +1450,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1454,13 +1497,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1518,13 +1562,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } @@ -1583,13 +1628,14 @@ benchmarks! { let Exec { mut ext_manager, block_config, - message_execution_context, + context, + memory_pages, } = prepare::(instance.caller.into_origin(), HandleKind::Handle(ProgramId::from_origin(instance.addr)), vec![], 0u32.into())?; }: { let journal = core_processor::process::< ext::LazyPagesExt, SandboxEnvironment, - >(&block_config, message_execution_context); + >(&block_config, context, memory_pages); core_processor::handle_journal(journal, &mut ext_manager); } diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index f887e4c3858..f5acd4fa664 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -642,7 +642,10 @@ pub mod pallet { ) .map( |GasInfo { - reserved, burned, may_be_returned, .. + reserved, + burned, + may_be_returned, + .. }| GasInfo { min_limit, reserved, @@ -794,58 +797,70 @@ pub mod pallet { subsequent_execution, }; - let may_be_returned_context = (!subsequent_execution && actor_id == main_program_id).then(|| MessageExecutionContext { - subsequent_execution: true, - ..message_execution_context.clone() - }); - - let journal = match core_processor::prepare(&block_config, message_execution_context) { - PrepareResult::Ok{ context, pages_with_data } => { - let memory_pages = if lazy_pages_enabled { - Default::default() - } else { - match common::get_program_data_for_pages( - actor_id.into_origin(), - pages_with_data.iter(), - ) { - Ok(data) => data, - Err(err) => { - log::error!( - "Page data in storage is in invalid state: {}", - err - ); - continue; + let may_be_returned_context = (!subsequent_execution + && actor_id == main_program_id) + .then(|| MessageExecutionContext { + subsequent_execution: true, + ..message_execution_context.clone() + }); + + let journal = + match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::Ok { + context, + pages_with_data, + } => { + let memory_pages = if lazy_pages_enabled { + Default::default() + } else { + match common::get_program_data_for_pages( + actor_id.into_origin(), + pages_with_data.iter(), + ) { + Ok(data) => data, + Err(err) => { + log::error!( + "Page data in storage is in invalid state: {}", + err + ); + continue; + } } - } - }; + }; - ext_manager.insert_program_id_loaded_pages(actor_id); + ext_manager.insert_program_id_loaded_pages(actor_id); - may_be_returned += may_be_returned_context.map(|c| { - let burned = match core_processor::prepare(&block_config, c) { - PrepareResult::Ok { context, .. } => context.gas_counter().burned(), - _ => context.gas_counter().burned(), - }; + may_be_returned += may_be_returned_context + .map(|c| { + let burned = match core_processor::prepare(&block_config, c) { + PrepareResult::Ok { context, .. } => { + context.gas_counter().burned() + } + _ => context.gas_counter().burned(), + }; - context.gas_counter().burned() - burned - }).unwrap_or(0); + context.gas_counter().burned() - burned + }) + .unwrap_or(0); - if lazy_pages_enabled { - core_processor::process::>( - &block_config, - context, - memory_pages, - ) - } else { - core_processor::process::>( - &block_config, - context, - memory_pages, - ) + if lazy_pages_enabled { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } else { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } } - } - PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, - }; + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => { + journal + } + }; let get_main_limit = || { GasHandlerOf::::get_limit(main_message_id).map_err(|_| { @@ -1219,44 +1234,50 @@ pub mod pallet { subsequent_execution: ext_manager.program_pages_loaded(&program_id), }; - let journal = match core_processor::prepare(&block_config, message_execution_context) { - PrepareResult::Ok{ context, pages_with_data } => { - let memory_pages = if lazy_pages_enabled { - Default::default() - } else { - match common::get_program_data_for_pages( - program_id.into_origin(), - pages_with_data.iter(), - ) { - Ok(data) => data, - Err(err) => { - log::error!( - "Page data in storage is in invalid state: {}", - err - ); - continue; + let journal = + match core_processor::prepare(&block_config, message_execution_context) { + PrepareResult::Ok { + context, + pages_with_data, + } => { + let memory_pages = if lazy_pages_enabled { + Default::default() + } else { + match common::get_program_data_for_pages( + program_id.into_origin(), + pages_with_data.iter(), + ) { + Ok(data) => data, + Err(err) => { + log::error!( + "Page data in storage is in invalid state: {}", + err + ); + continue; + } } - } - }; + }; - ext_manager.insert_program_id_loaded_pages(program_id); - - if lazy_pages_enabled { - core_processor::process::>( - &block_config, - context, - memory_pages, - ) - } else { - core_processor::process::>( - &block_config, - context, - memory_pages, - ) + ext_manager.insert_program_id_loaded_pages(program_id); + + if lazy_pages_enabled { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } else { + core_processor::process::>( + &block_config, + context, + memory_pages, + ) + } } - } - PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => journal, - }; + PrepareResult::WontExecute(journal) | PrepareResult::Error(journal) => { + journal + } + }; core_processor::handle_journal(journal, &mut ext_manager); diff --git a/pallets/gear/src/manager/mod.rs b/pallets/gear/src/manager/mod.rs index 059a4edfaff..f0d42781fb3 100644 --- a/pallets/gear/src/manager/mod.rs +++ b/pallets/gear/src/manager/mod.rs @@ -177,8 +177,8 @@ where }; let balance = - CurrencyOf::::free_balance(&::from_origin(id.into_origin())) - .unique_saturated_into(); + CurrencyOf::::free_balance(&::from_origin(id.into_origin())) + .unique_saturated_into(); Some(Actor { balance, diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 85a06e6e204..430a82f138b 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -92,7 +92,8 @@ fn unstoppable_block_execution_works() { )); } - let real_gas_to_burn = expected_burned_gas + executions_amount.saturating_sub(1) * (expected_burned_gas - may_be_returned); + let real_gas_to_burn = expected_burned_gas + + executions_amount.saturating_sub(1) * (expected_burned_gas - may_be_returned); assert!(balance_for_each_execution * executions_amount > real_gas_to_burn); @@ -4050,10 +4051,7 @@ fn missing_functions_are_not_executed() { res.expect("submit result was asserted") }; - let GasInfo { - min_limit, - .. - } = Gear::calculate_gas_info( + let GasInfo { min_limit, .. } = Gear::calculate_gas_info( USER_1.into_origin(), HandleKind::Init(ProgramCodeKind::Custom(wat).to_bytes()), EMPTY_PAYLOAD.to_vec(), @@ -4068,7 +4066,10 @@ fn missing_functions_are_not_executed() { // there is no 'init' so memory pages don't get loaded and // no execution is performed at all and hence user was not charged. - assert_eq!(initial_balance, BalancesPallet::::free_balance(USER_1)); + assert_eq!( + initial_balance, + BalancesPallet::::free_balance(USER_1) + ); // this value is actually a constant in the wat. let locked_value = 1_000; @@ -4093,10 +4094,7 @@ fn missing_functions_are_not_executed() { let reply_to_id = get_last_mail(USER_1).id(); - let GasInfo { - min_limit, - .. - } = Gear::calculate_gas_info( + let GasInfo { min_limit, .. } = Gear::calculate_gas_info( USER_1.into_origin(), HandleKind::Reply(reply_to_id, 0), EMPTY_PAYLOAD.to_vec(), @@ -4119,7 +4117,10 @@ fn missing_functions_are_not_executed() { run_to_next_block(None); // there is no 'handle_reply' too - assert_eq!(initial_balance - reply_value, BalancesPallet::::free_balance(USER_1)); + assert_eq!( + initial_balance - reply_value, + BalancesPallet::::free_balance(USER_1) + ); }); } diff --git a/utils/gear-runtime-test-cli/src/command.rs b/utils/gear-runtime-test-cli/src/command.rs index 6af434376b3..a7dc14f9dd6 100644 --- a/utils/gear-runtime-test-cli/src/command.rs +++ b/utils/gear-runtime-test-cli/src/command.rs @@ -422,7 +422,7 @@ fn run_fixture(test: &'_ sample::Test, fixture: &sample::Fixture) -> ColoredStri } } - let actors_data: Vec = snapshot + let actors_data: Vec<_> = snapshot .programs .iter() .filter_map(|p| { @@ -440,13 +440,15 @@ fn run_fixture(test: &'_ sample::Test, fixture: &sample::Fixture) -> ColoredStri .map(|p| p.to_wasm_page()) .collect(); let program = CoreProgram::from_parts(*pid, code, pages, true); - Some(ExecutableActorData { - program, - pages_data: vec_page_data_map_to_page_buf_map( - info.persistent_pages.clone(), - ) - .unwrap(), - }) + let memory = + vec_page_data_map_to_page_buf_map(info.persistent_pages.clone()).unwrap(); + Some(( + ExecutableActorData { + program, + pages_with_data: memory.keys().cloned().collect(), + }, + memory, + )) } else { None } @@ -464,7 +466,7 @@ fn run_fixture(test: &'_ sample::Test, fixture: &sample::Fixture) -> ColoredStri if let Err(alloc_errors) = gear_test::check::check_allocations( &actors_data .into_iter() - .map(|a| a.program) + .map(|(d, _)| d.program) .collect::>(), alloc, ) { From 229d6755abc92c23edff56f6444c8122c17c3f4e Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 20 Jul 2022 17:18:47 +0400 Subject: [PATCH 06/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 3a3b2028ce4..5db112db456 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -122,7 +122,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: 1370, + spec_version: 1380, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From cfbf94129d5394834638b873e92afccaa10c83ba Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 20 Jul 2022 20:00:40 +0400 Subject: [PATCH 07/16] add more gas to message in a test --- pallets/gear/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 430a82f138b..5693ad0f624 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -3259,7 +3259,7 @@ fn test_two_contracts_composition_works() { Origin::signed(USER_1), compose_id, 100_u64.to_le_bytes().to_vec(), - 10_000_000_000, + 30_000_000_000, 0, )); From 56bc6be28da7d6a23f90ec9ff377fd5516daa4b2 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Thu, 21 Jul 2022 16:18:48 +0400 Subject: [PATCH 08/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 5db112db456..e4efb0cddb0 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -122,7 +122,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: 1380, + spec_version: 1390, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 8fe5b5cc719b42c55b53b3df91af60a0edb7d0f6 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Fri, 22 Jul 2022 10:40:47 +0400 Subject: [PATCH 09/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e4efb0cddb0..54930d34ac5 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -122,7 +122,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: 1390, + spec_version: 1400, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From a73f1751700c5c3e2b8451165f1d0284d426bde7 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 27 Jul 2022 10:41:58 +0400 Subject: [PATCH 10/16] fix review remarks --- core-processor/src/common.rs | 4 ++-- core-processor/src/processor.rs | 26 ++++++++++++++------------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/core-processor/src/common.rs b/core-processor/src/common.rs index 4035a6d0b3b..e9106f78205 100644 --- a/core-processor/src/common.rs +++ b/core-processor/src/common.rs @@ -376,9 +376,9 @@ pub struct Actor { /// Executable actor data. #[derive(Clone, Debug, Decode, Encode)] pub struct ExecutableActorData { - /// Program. + /// Program aggregated data. pub program: Program, - /// Numbers of memory pages with some data. + /// Numbers of allocated memory pages that have non-default data. pub pages_with_data: BTreeSet, } diff --git a/core-processor/src/processor.rs b/core-processor/src/processor.rs index 623c52b8b37..4bb645c66c4 100644 --- a/core-processor/src/processor.rs +++ b/core-processor/src/processor.rs @@ -29,6 +29,7 @@ use alloc::{ collections::{BTreeMap, BTreeSet}, string::ToString, vec::Vec, + boxed::Box, }; use codec::Encode; use gear_backend_common::{Environment, IntoExtInfo}; @@ -68,12 +69,11 @@ impl PreparedMessageExecutionContext { } /// Defines result variants of the function `prepare`. -#[allow(clippy::large_enum_variant)] pub enum PrepareResult { /// Successfully precharged for memory pages. Ok { /// A context for `process` function. - context: PreparedMessageExecutionContext, + context: Box, /// A set with numbers of memory pages which contain some data. pages_with_data: BTreeSet, }, @@ -104,7 +104,7 @@ pub fn prepare( executable_data, } = actor; - let data = match check_is_executable(executable_data, &dispatch) { + let (program, pages_with_data) = match check_is_executable(executable_data, &dispatch) { Err(exit_code) => { return PrepareResult::Error(process_non_executable( dispatch, @@ -112,10 +112,9 @@ pub fn prepare( exit_code, )) } - Ok(data) => data, + Ok(ExecutableActorData { program, pages_with_data }) => (program, pages_with_data), }; - let program = &data.program; let program_id = program.id(); let mut gas_counter = GasCounter::new(dispatch.gas_limit()); if !program.code().exports().contains(&dispatch.kind()) { @@ -135,9 +134,12 @@ pub fn prepare( dispatch.context().is_none() && matches!(dispatch.kind(), DispatchKind::Init), subsequent_execution, ) { - Ok(size) => size, + Ok(size) => { + log::debug!("Charged for memory pages. Size: {size:?}"); + size + } Err(reason) => { - log::debug!("failed to charge for memory pages: {:?}", reason); + log::debug!("Failed to charge for memory pages: {reason:?}"); return PrepareResult::Error(match reason { ExecutionErrorReason::InitialMemoryBlockGasExceeded | ExecutionErrorReason::GrowMemoryBlockGasExceeded @@ -150,23 +152,23 @@ pub fn prepare( }; PrepareResult::Ok { - context: PreparedMessageExecutionContext { + context: Box::new(PreparedMessageExecutionContext { gas_counter, gas_allowance_counter, dispatch, origin, balance, - program: data.program, + program, memory_size, - }, - pages_with_data: data.pages_with_data, + }), + pages_with_data, } } /// Process program & dispatch for it and return journal for updates. pub fn process>( block_config: &BlockConfig, - execution_context: PreparedMessageExecutionContext, + execution_context: Box, memory_pages: BTreeMap, ) -> Vec { use SuccessfulDispatchResultKind::*; From aff75c5c13b7dd74e9e17a196f6999aed149ae0d Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 27 Jul 2022 10:55:30 +0400 Subject: [PATCH 11/16] pre-commit --- core-processor/src/processor.rs | 7 +++++-- pallets/gear/src/benchmarking/mod.rs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core-processor/src/processor.rs b/core-processor/src/processor.rs index 4bb645c66c4..29bcf764fe6 100644 --- a/core-processor/src/processor.rs +++ b/core-processor/src/processor.rs @@ -26,10 +26,10 @@ use crate::{ ext::ProcessorExt, }; use alloc::{ + boxed::Box, collections::{BTreeMap, BTreeSet}, string::ToString, vec::Vec, - boxed::Box, }; use codec::Encode; use gear_backend_common::{Environment, IntoExtInfo}; @@ -112,7 +112,10 @@ pub fn prepare( exit_code, )) } - Ok(ExecutableActorData { program, pages_with_data }) => (program, pages_with_data), + Ok(ExecutableActorData { + program, + pages_with_data, + }) => (program, pages_with_data), }; let program_id = program.id(); diff --git a/pallets/gear/src/benchmarking/mod.rs b/pallets/gear/src/benchmarking/mod.rs index ff75818978d..ea49cccdc8c 100644 --- a/pallets/gear/src/benchmarking/mod.rs +++ b/pallets/gear/src/benchmarking/mod.rs @@ -133,7 +133,7 @@ fn caller_funding() -> BalanceOf { struct Exec { ext_manager: ExtManager, block_config: BlockConfig, - context: PreparedMessageExecutionContext, + context: Box, memory_pages: BTreeMap, } From f272d4e3b0989d675209d6d2d56526ccc0ab937a Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Wed, 27 Jul 2022 11:06:46 +0400 Subject: [PATCH 12/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 7349bf29151..6c7fc6ae970 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -122,7 +122,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: 1420, + spec_version: 1430, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From 2e8bff4ece579424c549ef58a265fa96d2e1c1fd Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Thu, 28 Jul 2022 10:18:41 +0400 Subject: [PATCH 13/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index d18f2214720..56e0bc5a229 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -125,7 +125,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("gear-node"), apis: RUNTIME_API_VERSIONS, authoring_version: 1, - spec_version: 1430, + spec_version: 1440, impl_version: 1, transaction_version: 1, state_version: 1, From 4dcf7b5b286bb9106d8aa09df57c9c31871e5f7d Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Fri, 29 Jul 2022 00:16:31 +0400 Subject: [PATCH 14/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 923d49e0f7b..9b25eca4b30 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -125,7 +125,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("gear-node"), apis: RUNTIME_API_VERSIONS, authoring_version: 1, - spec_version: 1450, + spec_version: 1460, impl_version: 1, transaction_version: 1, state_version: 1, From 59ab9d57783059601010f1589152aff2dd926df2 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Fri, 29 Jul 2022 10:02:16 +0400 Subject: [PATCH 15/16] make fmt --- core-processor/src/processor.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core-processor/src/processor.rs b/core-processor/src/processor.rs index 2624f2afb17..3490204a1b4 100644 --- a/core-processor/src/processor.rs +++ b/core-processor/src/processor.rs @@ -38,9 +38,7 @@ use gear_core::{ gas::{GasAllowanceCounter, GasCounter}, ids::ProgramId, memory::{PageBuf, PageNumber, WasmPageNumber}, - message::{ - DispatchKind, ExitCode, IncomingDispatch, ReplyMessage, StoredDispatch, - }, + message::{DispatchKind, ExitCode, IncomingDispatch, ReplyMessage, StoredDispatch}, program::Program, }; From bacebfbfb92a3fc5e9981ec21a9aee87f1e09638 Mon Sep 17 00:00:00 2001 From: Georgy Shepelev Date: Tue, 2 Aug 2022 11:00:39 +0400 Subject: [PATCH 16/16] bump spec version --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 307b04519bb..598f609d9b1 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -125,7 +125,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("gear-node"), apis: RUNTIME_API_VERSIONS, authoring_version: 1, - spec_version: 1470, + spec_version: 1480, impl_version: 1, transaction_version: 1, state_version: 1,