diff --git a/examples/constructor/src/builder.rs b/examples/constructor/src/builder.rs index 344eae01c72..bf871191605 100644 --- a/examples/constructor/src/builder.rs +++ b/examples/constructor/src/builder.rs @@ -325,4 +325,8 @@ impl Calls { pub fn infinite_loop(self) -> Self { self.add_call(Call::Loop) } + + pub fn system_reserve_gas(self, gas: impl Into>) -> Self { + self.add_call(Call::SystemReserveGas(gas.into())) + } } diff --git a/examples/constructor/src/call.rs b/examples/constructor/src/call.rs index 06c0fde0edb..2f14a20030c 100644 --- a/examples/constructor/src/call.rs +++ b/examples/constructor/src/call.rs @@ -42,6 +42,7 @@ pub enum Call { Wake(Arg<[u8; 32]>), MessageId, Loop, + SystemReserveGas(Arg), } #[cfg(not(feature = "wasm-wrapper"))] @@ -317,6 +318,17 @@ mod wasm { Some(msg::id().encode()) } + fn system_reserve_gas(self) -> Option> { + let Self::SystemReserveGas(gas) = self else { + unreachable!() + }; + + let gas = gas.value(); + exec::system_reserve_gas(gas).expect("Failed to reserve gas"); + + None + } + pub(crate) fn process(self, previous: Option) -> CallResult { debug!("\t[CONSTRUCTOR] >> Processing {self:?}"); let call = self.clone(); @@ -347,6 +359,7 @@ mod wasm { Call::MessageId => self.message_id(), #[allow(clippy::empty_loop)] Call::Loop => loop {}, + Call::SystemReserveGas(..) => self.system_reserve_gas(), }; (call, value) diff --git a/examples/constructor/src/scheme/demo_exit_handle.rs b/examples/constructor/src/scheme/demo_exit_handle.rs index a7b6a508057..4a6ba5a3fb2 100644 --- a/examples/constructor/src/scheme/demo_exit_handle.rs +++ b/examples/constructor/src/scheme/demo_exit_handle.rs @@ -22,6 +22,10 @@ pub fn handle_reply() -> Calls { Calls::builder().noop() } +pub fn handle_signal() -> Calls { + Calls::builder().noop() +} + pub fn scheme() -> Scheme { - Scheme::predefined(init(), handle(), handle_reply()) + Scheme::predefined(init(), handle(), handle_reply(), handle_signal()) } diff --git a/examples/constructor/src/scheme/demo_exit_init.rs b/examples/constructor/src/scheme/demo_exit_init.rs index 74a6af4f6bf..9e191c164d4 100644 --- a/examples/constructor/src/scheme/demo_exit_init.rs +++ b/examples/constructor/src/scheme/demo_exit_init.rs @@ -29,6 +29,15 @@ pub fn handle_reply() -> Calls { Calls::builder().noop() } +pub fn handle_signal() -> Calls { + Calls::builder().noop() +} + pub fn scheme(send_before_exit: bool) -> Scheme { - Scheme::predefined(init(send_before_exit), handle(), handle_reply()) + Scheme::predefined( + init(send_before_exit), + handle(), + handle_reply(), + handle_signal(), + ) } diff --git a/examples/constructor/src/scheme/demo_ping.rs b/examples/constructor/src/scheme/demo_ping.rs index c0601efbff5..d05bee2fa01 100644 --- a/examples/constructor/src/scheme/demo_ping.rs +++ b/examples/constructor/src/scheme/demo_ping.rs @@ -29,6 +29,10 @@ pub fn handle_reply() -> Calls { Calls::builder().noop() } +pub fn handle_signal() -> Calls { + Calls::builder().noop() +} + pub fn scheme() -> Scheme { - Scheme::predefined(init(), handle(), handle_reply()) + Scheme::predefined(init(), handle(), handle_reply(), handle_signal()) } diff --git a/examples/constructor/src/scheme/demo_proxy_with_gas.rs b/examples/constructor/src/scheme/demo_proxy_with_gas.rs index 70b7e2a1ba5..7b893716d5e 100644 --- a/examples/constructor/src/scheme/demo_proxy_with_gas.rs +++ b/examples/constructor/src/scheme/demo_proxy_with_gas.rs @@ -65,6 +65,15 @@ pub fn handle_reply() -> Calls { ) } +pub fn handle_signal() -> Calls { + Calls::builder().noop() +} + pub fn scheme(destination: [u8; 32], delay: u32) -> Scheme { - Scheme::predefined(init(destination, delay), handle(), handle_reply()) + Scheme::predefined( + init(destination, delay), + handle(), + handle_reply(), + handle_signal(), + ) } diff --git a/examples/constructor/src/scheme/demo_reply_deposit.rs b/examples/constructor/src/scheme/demo_reply_deposit.rs index a7313e6b23a..5de12a39092 100644 --- a/examples/constructor/src/scheme/demo_reply_deposit.rs +++ b/examples/constructor/src/scheme/demo_reply_deposit.rs @@ -31,10 +31,15 @@ pub fn handle_reply(checker: [u8; 32]) -> Calls { .send_wgas(checker, Arg::bytes(SUCCESS_MESSAGE), 10_000) } +pub fn handle_signal() -> Calls { + Calls::builder().noop() +} + pub fn scheme(checker: [u8; 32], destination: [u8; 32], gas_to_send: u64) -> Scheme { Scheme::predefined( init(), handle(destination, gas_to_send), handle_reply(checker), + handle_signal(), ) } diff --git a/examples/constructor/src/scheme/demo_wait_init_exit_reply.rs b/examples/constructor/src/scheme/demo_wait_init_exit_reply.rs index bea2b68c1b6..e44eb574f62 100644 --- a/examples/constructor/src/scheme/demo_wait_init_exit_reply.rs +++ b/examples/constructor/src/scheme/demo_wait_init_exit_reply.rs @@ -42,6 +42,10 @@ pub fn handle_reply() -> Calls { .exit(source_var) } +pub fn handle_signal() -> Calls { + Calls::builder().noop() +} + pub fn scheme() -> Scheme { - Scheme::predefined(init(), handle(), handle_reply()) + Scheme::predefined(init(), handle(), handle_reply(), handle_signal()) } diff --git a/examples/constructor/src/scheme/mod.rs b/examples/constructor/src/scheme/mod.rs index a13a3379d1a..280c5682875 100644 --- a/examples/constructor/src/scheme/mod.rs +++ b/examples/constructor/src/scheme/mod.rs @@ -26,7 +26,7 @@ pub enum Scheme { /// /// Better to use this scheme if you need common-purpose program that /// executes the same commands across different incoming payloads. - Predefined(Vec, Vec, Vec), + Predefined(Vec, Vec, Vec, Vec), } impl Scheme { @@ -38,8 +38,18 @@ impl Scheme { Self::Direct(init.calls()) } - pub fn predefined(init: Calls, handle: Calls, handle_reply: Calls) -> Self { - Self::Predefined(init.calls(), handle.calls(), handle_reply.calls()) + pub fn predefined( + init: Calls, + handle: Calls, + handle_reply: Calls, + handle_signal: Calls, + ) -> Self { + Self::Predefined( + init.calls(), + handle.calls(), + handle_reply.calls(), + handle_signal.calls(), + ) } pub fn init(&self) -> &Vec { @@ -51,14 +61,21 @@ impl Scheme { pub fn handle(&self) -> Option<&Vec> { match self { - Self::Predefined(_, handle, _) => Some(handle), + Self::Predefined(_, handle, _, _) => Some(handle), _ => None, } } pub fn handle_reply(&self) -> Option<&Vec> { match self { - Self::Predefined(_, _, handle_reply) => Some(handle_reply), + Self::Predefined(_, _, handle_reply, _) => Some(handle_reply), + _ => None, + } + } + + pub fn handle_signal(&self) -> Option<&Vec> { + match self { + Self::Predefined(_, _, _, handle_signal) => Some(handle_signal), _ => None, } } diff --git a/examples/constructor/src/wasm.rs b/examples/constructor/src/wasm.rs index 4461952ba8e..3848d0516ef 100644 --- a/examples/constructor/src/wasm.rs +++ b/examples/constructor/src/wasm.rs @@ -34,3 +34,8 @@ extern "C" fn handle() { extern "C" fn handle_reply() { process_fn(Scheme::handle_reply); } + +#[no_mangle] +extern "C" fn handle_signal() { + process_fn(Scheme::handle_signal); +} diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 5ccae9dc5f5..7ad7c12cd46 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -167,7 +167,12 @@ fn value_counter_set_correctly_for_interruptions() { .send_value(Arg::new([0u8; 32]), Arg::new(vec![]), "value_store") .wait_for(1); - let scheme = Scheme::predefined(Calls::builder().noop(), handle, Calls::builder().noop()); + let scheme = Scheme::predefined( + Calls::builder().noop(), + handle, + Calls::builder().noop(), + Calls::builder().noop(), + ); init_logger(); new_test_ext().execute_with(|| { @@ -5937,7 +5942,12 @@ fn pause_terminated_exited_program() { let (_, terminated_pid) = submit_constructor_with_args( USER_1, DEFAULT_SALT, - Scheme::predefined(init, Default::default(), Default::default()), + Scheme::predefined( + init, + Default::default(), + Default::default(), + Default::default(), + ), 0, ); @@ -8555,7 +8565,7 @@ fn demo_constructor_is_demo_ping() { let handle_reply = Calls::builder().panic("I don't like replies"); - let scheme = Scheme::predefined(init, handle, handle_reply); + let scheme = Scheme::predefined(init, handle, handle_reply, Default::default()); // checking init let (_init_mid, constructor_id) = utils::init_constructor(scheme); @@ -14105,7 +14115,12 @@ fn double_read_works() { .load("read2") .bytes_eq("is_eq", "read1", "read2") .if_else("is_eq", noop_branch, panic_branch); - let predefined_scheme = Scheme::predefined(Default::default(), handle, Default::default()); + let predefined_scheme = Scheme::predefined( + Default::default(), + handle, + Default::default(), + Default::default(), + ); let (_, pid) = utils::init_constructor(predefined_scheme); @@ -14334,7 +14349,7 @@ fn test_send_to_terminated_from_program() { // Using `USER_2` not to pollute `USER_1` mailbox to make test easier. USER_2, b"salt1", - Scheme::predefined(init, handle, Calls::default()), + Scheme::predefined(init, handle, Calls::default(), Calls::default()), 0, ); @@ -14351,7 +14366,7 @@ fn test_send_to_terminated_from_program() { // Using `USER_2` not to pollute `USER_1` mailbox to make test easier. USER_2, b"salt2", - Scheme::predefined(Calls::default(), handle, handle_reply), + Scheme::predefined(Calls::default(), handle, handle_reply, Calls::default()), 0, ); @@ -14650,7 +14665,7 @@ fn test_gas_info_of_terminated_program() { let (_, pid_dead) = utils::submit_constructor_with_args( USER_1, b"salt1", - Scheme::predefined(init_dead, handle_dead, Calls::default()), + Scheme::predefined(init_dead, handle_dead, Calls::default(), Calls::default()), 0, ); @@ -14659,7 +14674,12 @@ fn test_gas_info_of_terminated_program() { let (_, proxy_pid) = utils::submit_constructor_with_args( USER_1, b"salt2", - Scheme::predefined(Calls::default(), handle_proxy, Calls::default()), + Scheme::predefined( + Calls::default(), + handle_proxy, + Calls::default(), + Calls::default(), + ), 0, );