diff --git a/core-processor/src/processing.rs b/core-processor/src/processing.rs index befb3685610..23735a92e91 100644 --- a/core-processor/src/processing.rs +++ b/core-processor/src/processing.rs @@ -503,7 +503,7 @@ pub fn process_non_executable( let source = dispatch.source(); let value = dispatch.value(); - if value != 0 { + if dispatch.context().is_none() && value != 0 { // Send value back journal.push(JournalNote::SendValue { from: dispatch.source(), diff --git a/examples/custom/src/lib.rs b/examples/custom/src/lib.rs index 39db57ca2d1..5971f752bbb 100644 --- a/examples/custom/src/lib.rs +++ b/examples/custom/src/lib.rs @@ -26,8 +26,10 @@ extern crate alloc; pub mod backend_error; pub mod btree; pub mod capacitor; +pub mod wake_after_exit; use alloc::string::String; +use gstd::ActorId; use parity_scale_codec::{Decode, Encode}; #[cfg(feature = "std")] @@ -43,13 +45,14 @@ pub enum InitMessage { Capacitor(String), BTree, BackendError, + WakeAfterExit(ActorId), } #[cfg(not(feature = "std"))] mod wasm { use super::{ backend_error::wasm as backend_error, btree::wasm as btree, capacitor::wasm as capacitor, - InitMessage, + wake_after_exit::wasm as wake_after_exit, InitMessage, }; use gstd::msg; @@ -57,6 +60,7 @@ mod wasm { Capacitor(capacitor::State), BTree(btree::State), BackendError(backend_error::State), + WakeAfterExit, } static mut STATE: Option = None; @@ -68,13 +72,17 @@ mod wasm { InitMessage::Capacitor(payload) => State::Capacitor(capacitor::init(payload)), InitMessage::BTree => State::BTree(btree::init()), InitMessage::BackendError => State::BackendError(backend_error::init()), + InitMessage::WakeAfterExit(addr) => { + unsafe { STATE = Some(State::WakeAfterExit) }; + wake_after_exit::init(addr) + } }; unsafe { STATE = Some(state) }; } #[no_mangle] extern "C" fn handle() { - let state = unsafe { STATE.as_mut().expect("State must be set in handle") }; + let state = unsafe { STATE.as_mut().expect("State must be set") }; match state { State::Capacitor(state) => capacitor::handle(state), State::BTree(state) => btree::handle(state), @@ -82,9 +90,17 @@ mod wasm { } } + #[no_mangle] + extern "C" fn handle_reply() { + let state = unsafe { STATE.as_mut().expect("State must be set") }; + if let State::WakeAfterExit = state { + wake_after_exit::handle_reply(); + } + } + #[no_mangle] extern "C" fn state() { - let state = unsafe { STATE.take().expect("State must be set in handle") }; + let state = unsafe { STATE.take().expect("State must be set") }; if let State::BTree(state) = state { btree::state(state); } diff --git a/examples/custom/src/wake_after_exit.rs b/examples/custom/src/wake_after_exit.rs new file mode 100644 index 00000000000..6291c83d014 --- /dev/null +++ b/examples/custom/src/wake_after_exit.rs @@ -0,0 +1,29 @@ +// This file is part of Gear. + +// Copyright (C) 2024 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#[cfg(not(feature = "std"))] +pub(crate) mod wasm { + pub fn init(addr: gstd::ActorId) -> ! { + let _ = gstd::msg::send_bytes(addr, b"PING", 0).unwrap(); + gstd::exec::wait_up_to(100) + } + + pub fn handle_reply() -> ! { + gstd::exec::exit(gstd::msg::source()) + } +} diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index a51b8adb206..9fb6a898f4e 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -13170,6 +13170,45 @@ fn async_init() { }); } +#[test] +fn wake_after_exit() { + use demo_custom::{InitMessage, WASM_BINARY}; + use demo_ping::WASM_BINARY as PING_BINARY; + + init_logger(); + + new_test_ext().execute_with(|| { + assert_ok!(Gear::upload_program( + RuntimeOrigin::signed(USER_3), + PING_BINARY.to_vec(), + DEFAULT_SALT.to_vec(), + Default::default(), + BlockGasLimitOf::::get(), + 0, + false, + )); + + let ping: [u8; 32] = get_last_program_id().into(); + + assert_ok!(Gear::upload_program( + RuntimeOrigin::signed(USER_1), + WASM_BINARY.to_vec(), + DEFAULT_SALT.to_vec(), + InitMessage::WakeAfterExit(ping.into()).encode(), + BlockGasLimitOf::::get(), + 1000, + false, + )); + + let mid = get_last_message_id(); + + run_to_next_block(None); + + // Execution after wake must be skipped, so status must be NotExecuted. + assert_not_executed(mid); + }); +} + #[test] fn check_gear_stack_end_fail() { // This test checks, that in case user makes WASM file with incorrect