From 5c90a3424de2285b6bf1b972b651ce623cd42e56 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Mon, 4 Dec 2023 12:44:57 +0100 Subject: [PATCH] feat(pallet-gear-rpc): Introduce gas spent for vouchers --- pallets/gear/rpc/runtime-api/src/lib.rs | 8 +- pallets/gear/rpc/src/lib.rs | 124 ++++++++++++++++++++++++ pallets/gear/src/lib.rs | 3 + pallets/gear/src/runtime_api.rs | 54 ++++++++--- pallets/gear/src/tests.rs | 1 + runtime/common/src/apis.rs | 3 +- 6 files changed, 176 insertions(+), 17 deletions(-) diff --git a/pallets/gear/rpc/runtime-api/src/lib.rs b/pallets/gear/rpc/runtime-api/src/lib.rs index 1cd1adcbda7..099d8998b3a 100644 --- a/pallets/gear/rpc/runtime-api/src/lib.rs +++ b/pallets/gear/rpc/runtime-api/src/lib.rs @@ -26,10 +26,10 @@ use sp_runtime::traits::Block as BlockT; use sp_std::vec::Vec; sp_api::decl_runtime_apis! { - #[api_version(2)] + #[api_version(3)] pub trait GearApi { #[allow(clippy::too_many_arguments)] - fn calculate_gas_info(source: H256, kind: HandleKind, payload: Vec, value: u128, allow_other_panics: bool, initial_gas: Option, allowance_multiplier: Option) -> Result>; + fn calculate_gas_info(source: H256, kind: HandleKind, payload: Vec, value: u128, is_prepaid: bool, allow_other_panics: bool, initial_gas: Option, allowance_multiplier: Option) -> Result>; /// Generate inherent-like extrinsic that runs message queue processing. fn gear_run_extrinsic(max_gas: Option) -> ::Extrinsic; @@ -43,6 +43,10 @@ sp_api::decl_runtime_apis! { // DEPRECATED APIS + #[allow(clippy::too_many_arguments)] + #[changed_in(3)] + fn calculate_gas_info(source: H256, kind: HandleKind, payload: Vec, value: u128, allow_other_panics: bool, initial_gas: Option, allowance_multiplier: Option) -> Result>; + #[allow(clippy::too_many_arguments)] #[changed_in(2)] fn calculate_gas_info(source: H256, kind: HandleKind, payload: Vec, value: u128, allow_other_panics: bool, initial_gas: Option) -> Result>; diff --git a/pallets/gear/rpc/src/lib.rs b/pallets/gear/rpc/src/lib.rs index 3f7b72c4bdb..dc5384531cc 100644 --- a/pallets/gear/rpc/src/lib.rs +++ b/pallets/gear/rpc/src/lib.rs @@ -95,6 +95,28 @@ pub trait GearApi { at: Option, ) -> RpcResult; + #[method(name = "unstable_gear_voucher_calculateHandleGas")] + fn get_voucher_handle_gas_spent( + &self, + source: H256, + dest: H256, + payload: Bytes, + value: u128, + allow_other_panics: bool, + at: Option, + ) -> RpcResult; + + #[method(name = "unstable_gear_voucher_calculateReplyGas")] + fn get_voucher_reply_gas_spent( + &self, + source: H256, + message_id: H256, + payload: Bytes, + value: u128, + allow_other_panics: bool, + at: Option, + ) -> RpcResult; + #[method(name = "gear_readState")] fn read_state( &self, @@ -197,6 +219,7 @@ where kind: HandleKind, payload: Vec, value: u128, + is_prepaid: bool, allow_other_panics: bool, min_limit: Option, ) -> RpcResult { @@ -214,6 +237,18 @@ where allow_other_panics, min_limit, ) + } else if api_version < 3 { + #[allow(deprecated)] + api.calculate_gas_info_before_version_3( + at_hash, + source, + kind, + payload, + value, + allow_other_panics, + min_limit, + Some(self.allowance_multiplier), + ) } else { api.calculate_gas_info( at_hash, @@ -221,6 +256,7 @@ where kind, payload, value, + is_prepaid, allow_other_panics, min_limit, Some(self.allowance_multiplier), @@ -258,6 +294,8 @@ where C: 'static + ProvideRuntimeApi + HeaderBackend, C::Api: GearRuntimeApi, { + // Calculate gas spent + fn get_init_create_gas_spent( &self, source: H256, @@ -275,6 +313,7 @@ where HandleKind::InitByHash(CodeId::from_origin(code_id)), payload.to_vec(), value, + false, allow_other_panics, None, )?; @@ -285,6 +324,7 @@ where HandleKind::InitByHash(CodeId::from_origin(code_id)), payload.to_vec(), value, + false, allow_other_panics, Some(min_limit), ) @@ -307,6 +347,7 @@ where HandleKind::Init(code.to_vec()), payload.to_vec(), value, + false, allow_other_panics, None, )?; @@ -317,6 +358,7 @@ where HandleKind::Init(code.to_vec()), payload.to_vec(), value, + false, allow_other_panics, Some(min_limit), ) @@ -339,6 +381,7 @@ where HandleKind::Handle(ProgramId::from_origin(dest)), payload.to_vec(), value, + false, allow_other_panics, None, )?; @@ -349,6 +392,7 @@ where HandleKind::Handle(ProgramId::from_origin(dest)), payload.to_vec(), value, + false, allow_other_panics, Some(min_limit), ) @@ -374,6 +418,7 @@ where ), payload.to_vec(), value, + false, allow_other_panics, None, )?; @@ -387,11 +432,90 @@ where ), payload.to_vec(), value, + false, allow_other_panics, Some(min_limit), ) } + // Voucher + + fn get_voucher_reply_gas_spent( + &self, + source: H256, + message_id: H256, + payload: Bytes, + value: u128, + allow_other_panics: bool, + at: Option<::Hash>, + ) -> RpcResult { + let at_hash = at.unwrap_or_else(|| self.client.info().best_hash); + + let GasInfo { min_limit, .. } = self.calculate_gas_info( + at_hash, + source, + HandleKind::Reply( + MessageId::from_origin(message_id), + ReplyCode::Success(SuccessReplyReason::Manual), + ), + payload.to_vec(), + value, + true, + allow_other_panics, + None, + )?; + + self.calculate_gas_info( + at_hash, + source, + HandleKind::Reply( + MessageId::from_origin(message_id), + ReplyCode::Success(SuccessReplyReason::Manual), + ), + payload.to_vec(), + value, + true, + allow_other_panics, + Some(min_limit), + ) + } + + fn get_voucher_handle_gas_spent( + &self, + source: H256, + dest: H256, + payload: Bytes, + value: u128, + allow_other_panics: bool, + at: Option<::Hash>, + ) -> RpcResult { + let at_hash = at.unwrap_or_else(|| self.client.info().best_hash); + + let GasInfo { min_limit, .. } = self.calculate_gas_info( + at_hash, + source, + HandleKind::Handle(ProgramId::from_origin(dest)), + payload.to_vec(), + value, + true, + allow_other_panics, + None, + )?; + + self.calculate_gas_info( + at_hash, + source, + HandleKind::Handle(ProgramId::from_origin(dest)), + payload.to_vec(), + value, + true, + allow_other_panics, + Some(min_limit), + ) + } + + // Read state + fn read_state( &self, program_id: H256, diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index 28ede177994..be05a35a5e4 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -722,6 +722,7 @@ pub mod pallet { kind: HandleKind, payload: Vec, value: u128, + is_prepaid: bool, allow_other_panics: bool, initial_gas: Option, gas_allowance: Option, @@ -732,6 +733,7 @@ pub mod pallet { initial_gas.unwrap_or_else(BlockGasLimitOf::::get), payload, value, + is_prepaid, allow_other_panics, false, gas_allowance, @@ -762,6 +764,7 @@ pub mod pallet { initial_gas, payload.clone(), value, + false, allow_other_panics, allow_skip_zero_replies, None, diff --git a/pallets/gear/src/runtime_api.rs b/pallets/gear/src/runtime_api.rs index 8885c6d44ff..cf482a34173 100644 --- a/pallets/gear/src/runtime_api.rs +++ b/pallets/gear/src/runtime_api.rs @@ -50,6 +50,7 @@ where initial_gas: u64, payload: Vec, value: u128, + is_prepaid: bool, allow_other_panics: bool, allow_skip_zero_replies: bool, allowance_multiplier: Option, @@ -64,23 +65,32 @@ where + value.unique_saturated_into(); CurrencyOf::::deposit_creating(&account, max_balance.saturating_sub(balance)); - let who = frame_support::dispatch::RawOrigin::Signed(account); let value: BalanceOf = value.unique_saturated_into(); QueueOf::::clear(); match kind { HandleKind::Init(code) => { + let origin = frame_support::dispatch::RawOrigin::Signed(account); let salt = b"calculate_gas_salt".to_vec(); - Self::upload_program(who.into(), code, salt, payload, initial_gas, value, false) - .map_err(|e| { - format!("Internal error: upload_program failed with '{e:?}'").into_bytes() - })?; + Self::upload_program( + origin.into(), + code, + salt, + payload, + initial_gas, + value, + false, + ) + .map_err(|e| { + format!("Internal error: upload_program failed with '{e:?}'").into_bytes() + })?; } HandleKind::InitByHash(code_id) => { + let origin = frame_support::dispatch::RawOrigin::Signed(account); let salt = b"calculate_gas_salt".to_vec(); Self::create_program( - who.into(), + origin.into(), code_id, salt, payload, @@ -93,16 +103,32 @@ where })?; } HandleKind::Handle(destination) => { - Self::send_message(who.into(), destination, payload, initial_gas, value, false) - .map_err(|e| { - format!("Internal error: send_message failed with '{e:?}'").into_bytes() - })?; + Self::send_message_impl( + account, + destination, + payload, + initial_gas, + value, + is_prepaid, + false, + ) + .map_err(|e| { + format!("Internal error: send_message failed with '{e:?}'").into_bytes() + })?; } HandleKind::Reply(reply_to_id, _status_code) => { - Self::send_reply(who.into(), reply_to_id, payload, initial_gas, value, false) - .map_err(|e| { - format!("Internal error: send_reply failed with '{e:?}'").into_bytes() - })?; + Self::send_reply_impl( + account, + reply_to_id, + payload, + initial_gas, + value, + is_prepaid, + false, + ) + .map_err(|e| { + format!("Internal error: send_reply failed with '{e:?}'").into_bytes() + })?; } HandleKind::Signal(_signal_from, _status_code) => { return Err(b"Gas calculation for `handle_signal` is not supported".to_vec()); diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 2bbb59d5f83..b45815df911 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -13995,6 +13995,7 @@ fn calculate_gas_fails_when_calculation_limit_exceeded() { BlockGasLimitOf::::get(), Command::ConsumeReservationsFromList.encode(), 0, + false, true, false, Some(64), diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 32292bbea35..b4f867fa469 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -155,11 +155,12 @@ macro_rules! impl_runtime_apis_plus_common { kind: HandleKind, payload: Vec, value: u128, + is_prepaid: bool, allow_other_panics: bool, initial_gas: Option, gas_allowance: Option, ) -> Result> { - Gear::calculate_gas_info(account_id, kind, payload, value, allow_other_panics, initial_gas, gas_allowance) + Gear::calculate_gas_info(account_id, kind, payload, value, is_prepaid, allow_other_panics, initial_gas, gas_allowance) } fn gear_run_extrinsic(max_gas: Option) -> ::Extrinsic {