From 1f79c15ff5bf6f71a1bfaf58fef5387ab835e9f9 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Mon, 4 Dec 2023 17:22:39 +0100 Subject: [PATCH 1/8] Remove `PaymentVoucher` trait --- common/src/lib.rs | 16 ---------------- pallets/gear-voucher/src/benchmarking.rs | 4 ++-- pallets/gear-voucher/src/lib.rs | 15 ++------------- pallets/gear-voucher/src/tests.rs | 8 ++++---- pallets/gear/src/lib.rs | 17 +++++------------ pallets/gear/src/mock.rs | 2 +- pallets/gear/src/pallet_tests.rs | 7 ------- pallets/gear/src/tests.rs | 4 ++-- pallets/payment/src/mock.rs | 5 ++--- pallets/payment/src/tests.rs | 2 +- runtime/vara/src/lib.rs | 8 +++----- 11 files changed, 22 insertions(+), 66 deletions(-) diff --git a/common/src/lib.rs b/common/src/lib.rs index e8fdff55497..e243e05b206 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -347,19 +347,3 @@ where self.function.clone() } } - -pub trait PaymentVoucher { - type VoucherId; - type Error; - - fn voucher_id(who: AccountId, program: ProgramId) -> Self::VoucherId; -} - -impl PaymentVoucher for () { - type VoucherId = AccountId; - type Error = &'static str; - - fn voucher_id(_who: AccountId, _program: ProgramId) -> Self::VoucherId { - unimplemented!() - } -} diff --git a/pallets/gear-voucher/src/benchmarking.rs b/pallets/gear-voucher/src/benchmarking.rs index 38aac81bf34..0f02593f473 100644 --- a/pallets/gear-voucher/src/benchmarking.rs +++ b/pallets/gear-voucher/src/benchmarking.rs @@ -48,9 +48,9 @@ benchmarks! { let holder_lookup = T::Lookup::unlookup(holder.clone()); }: _(RawOrigin::Signed(issuer), holder_lookup, program_id, 10_000_000_000_000_u128.unique_saturated_into()) verify { - let voucher_account_id = GearVoucher::::voucher_account_id(&holder, &program_id); + let voucher_id = GearVoucher::::voucher_id(&holder, &program_id); assert_eq!( - CurrencyOf::::free_balance(&voucher_account_id), + CurrencyOf::::free_balance(&voucher_id), 10_000_000_000_000_u128.unique_saturated_into(), ); } diff --git a/pallets/gear-voucher/src/lib.rs b/pallets/gear-voucher/src/lib.rs index c3257765888..f4d90f930d4 100644 --- a/pallets/gear-voucher/src/lib.rs +++ b/pallets/gear-voucher/src/lib.rs @@ -57,7 +57,6 @@ mod mock; #[cfg(test)] mod tests; -use common::PaymentVoucher; use frame_support::{ pallet_prelude::*, traits::{Currency, ExistenceRequirement, ReservableCurrency, StorageVersion}, @@ -158,7 +157,7 @@ pub mod pallet { let to = T::Lookup::lookup(to)?; // Generate unique account id corresponding to the pair (user, program) - let voucher_id = Self::voucher_account_id(&to, &program); + let voucher_id = Self::voucher_id(&to, &program); // Transfer funds to the keyless account T::Currency::transfer(&who, &voucher_id, value, ExistenceRequirement::KeepAlive) @@ -192,23 +191,13 @@ pub mod pallet { impl Pallet { /// Derive a synthesized account ID from an account ID and a program ID. - pub fn voucher_account_id(who: &T::AccountId, program_id: &ProgramId) -> T::AccountId { + pub fn voucher_id(who: &T::AccountId, program_id: &ProgramId) -> T::AccountId { let entropy = (b"modlpy/voucher__", who, program_id).using_encoded(blake2_256); Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) .expect("infinite length input; no invalid inputs for type; qed") } } -impl PaymentVoucher> for Pallet { - type VoucherId = T::AccountId; - type Error = DispatchError; - - #[inline] - fn voucher_id(who: T::AccountId, program: ProgramId) -> Self::VoucherId { - Self::voucher_account_id(&who, &program) - } -} - #[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq, PartialOrd, Ord)] pub enum PrepaidCall { SendMessage { diff --git a/pallets/gear-voucher/src/tests.rs b/pallets/gear-voucher/src/tests.rs index a46cfe97ac4..fd2701f0902 100644 --- a/pallets/gear-voucher/src/tests.rs +++ b/pallets/gear-voucher/src/tests.rs @@ -26,7 +26,7 @@ use primitive_types::H256; fn voucher_issue_works() { new_test_ext().execute_with(|| { let program_id = ProgramId::from_origin(H256::from(b"some//quasy//random//program//id")); - let synthesized = Voucher::voucher_account_id(&BOB, &program_id); + let synthesized = Voucher::voucher_id(&BOB, &program_id); assert_ok!(Voucher::issue( RuntimeOrigin::signed(ALICE), @@ -56,7 +56,7 @@ fn voucher_issue_works() { fn voucher_redemption_works() { new_test_ext().execute_with(|| { let program_id = ProgramId::from_origin(H256::from(b"some//quasy//random//program//id")); - let synthesized = Voucher::voucher_account_id(&BOB, &program_id); + let synthesized = Voucher::voucher_id(&BOB, &program_id); assert_ok!(Voucher::issue( RuntimeOrigin::signed(ALICE), @@ -69,13 +69,13 @@ fn voucher_redemption_works() { // Redemption ok assert_ok!(Balances::reserve( - &Voucher::voucher_id(BOB, program_id), + &Voucher::voucher_id(&BOB, &program_id), 2_000 )); // Redemption fails assert_noop!( - Balances::reserve(&Voucher::voucher_id(BOB, program_id), 100_000_000), + Balances::reserve(&Voucher::voucher_id(&BOB, &program_id), 100_000_000), pallet_balances::Error::::InsufficientBalance ); }); diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index 28ede177994..64edea70fb7 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -54,7 +54,7 @@ use alloc::{format, string::String}; use common::{ self, event::*, gas_provider::GasNodeId, paused_program_storage::SessionId, scheduler::*, storage::*, BlockLimiter, CodeMetadata, CodeStorage, GasProvider, GasTree, Origin, - PausedProgramStorage, PaymentVoucher, Program, ProgramState, ProgramStorage, QueueRunner, + PausedProgramStorage, Program, ProgramState, ProgramStorage, QueueRunner, }; use core::marker::PhantomData; use core_processor::{ @@ -119,7 +119,6 @@ pub type RentFreePeriodOf = ::ProgramRentFreePeriod; pub type RentCostPerBlockOf = ::ProgramRentCostPerBlock; pub type ResumeMinimalPeriodOf = ::ProgramResumeMinimalRentPeriod; pub type ResumeSessionDurationOf = ::ProgramResumeSessionDuration; -pub(crate) type VoucherOf = ::Voucher; pub(crate) type GearBank = pallet_gear_bank::Pallet; /// The current storage version. @@ -240,14 +239,6 @@ pub mod pallet { /// Message Queue processing routing provider. type QueueRunner: QueueRunner>; - /// Type that allows to check caller's eligibility for using voucher for payment. - type Voucher: PaymentVoucher< - Self::AccountId, - ProgramId, - BalanceOf, - VoucherId = Self::AccountId, - >; - /// The free of charge period of rent. #[pallet::constant] type ProgramRentFreePeriod: Get>; @@ -1862,7 +1853,8 @@ pub mod pallet { let external_node = if prepaid { // If voucher is used, we attempt to reserve funds on the respective account. // If no such voucher exists, the call is invalidated. - let voucher_id = VoucherOf::::voucher_id(who.clone(), destination); + // TODO (breathx): replace. + let voucher_id = AccountIdOf::::from_origin(0.into_origin()); GearBank::::deposit_gas(&voucher_id, gas_limit, keep_alive).map_err(|e| { log::debug!( @@ -1964,7 +1956,8 @@ pub mod pallet { let external_node = if prepaid { // If voucher is used, we attempt to reserve funds on the respective account. // If no such voucher exists, the call is invalidated. - let voucher_id = VoucherOf::::voucher_id(origin.clone(), destination); + // TODO (breathx): replace. + let voucher_id = AccountIdOf::::from_origin(0.into_origin()); GearBank::::deposit_gas(&voucher_id, gas_limit, keep_alive).map_err(|e| { log::debug!( diff --git a/pallets/gear/src/mock.rs b/pallets/gear/src/mock.rs index 84d3a630975..bb4b9aa6b2d 100644 --- a/pallets/gear/src/mock.rs +++ b/pallets/gear/src/mock.rs @@ -93,7 +93,7 @@ pallet_gear_program::impl_config!(Test); pallet_gear_messenger::impl_config!(Test, CurrentBlockNumber = Gear); pallet_gear_scheduler::impl_config!(Test); pallet_gear_bank::impl_config!(Test); -pallet_gear::impl_config!(Test, Schedule = DynamicSchedule, Voucher = GearVoucher); +pallet_gear::impl_config!(Test, Schedule = DynamicSchedule); pallet_gear_gas::impl_config!(Test); common::impl_pallet_balances!(Test); common::impl_pallet_authorship!(Test); diff --git a/pallets/gear/src/pallet_tests.rs b/pallets/gear/src/pallet_tests.rs index 7cd98cb72c7..ccc6d78ece6 100644 --- a/pallets/gear/src/pallet_tests.rs +++ b/pallets/gear/src/pallet_tests.rs @@ -56,7 +56,6 @@ macro_rules! impl_config_inner { type BlockLimiter = GearGas; type Scheduler = GearScheduler; type QueueRunner = Gear; - type Voucher = GearConfigVoucher; type ProgramRentFreePeriod = RentFreePeriod; type ProgramResumeMinimalRentPeriod = ResumeMinimalPeriod; type ProgramRentCostPerBlock = RentCostPerBlock; @@ -72,12 +71,6 @@ macro_rules! impl_config_inner { $crate::impl_config_inner!($runtime, $($( $rest )*)?); }; - ($runtime:ty, Voucher = $voucher:ty $(, $( $rest:tt )*)?) => { - type GearConfigVoucher = $voucher; - - $crate::impl_config_inner!($runtime, $($( $rest )*)?); - }; - ($runtime:ty, DebugInfo = $debug_info:ty $(, $( $rest:tt )*)?) => { type GearConfigDebugInfo = $debug_info; diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 63cfa56dfc9..367c54f657d 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -14335,7 +14335,7 @@ fn send_gasless_message_works() { // Balance check // Voucher has been issued, but not used yet, so funds should be still in the respective account - let voucher_id = GearVoucher::voucher_account_id(&USER_2, &program_id); + let voucher_id = GearVoucher::voucher_id(&USER_2, &program_id); assert_eq!( Balances::free_balance(voucher_id), gas_price(DEFAULT_GAS_LIMIT) @@ -14417,7 +14417,7 @@ fn send_gasless_reply_works() { prog_id, gas_price(DEFAULT_GAS_LIMIT), )); - let voucher_id = GearVoucher::voucher_account_id(&USER_1, &prog_id); + let voucher_id = GearVoucher::voucher_id(&USER_1, &prog_id); run_to_block(3, None); diff --git a/pallets/payment/src/mock.rs b/pallets/payment/src/mock.rs index b989c655a8d..393a9c18004 100644 --- a/pallets/payment/src/mock.rs +++ b/pallets/payment/src/mock.rs @@ -166,9 +166,8 @@ impl DelegateFee for DelegateFeeAccountBuilder { }) => Some(FEE_PAYER), RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { call: pallet_gear_voucher::PrepaidCall::SendReply { reply_to_id, .. }, - }) => as common::storage::Mailbox>::peek(who, reply_to_id).map( - |stored_message| GearVoucher::voucher_account_id(who, &stored_message.source()), - ), + }) => as common::storage::Mailbox>::peek(who, reply_to_id) + .map(|stored_message| GearVoucher::voucher_id(who, &stored_message.source())), _ => None, } } diff --git a/pallets/payment/src/tests.rs b/pallets/payment/src/tests.rs index 067c4db71a4..a1343dc50ce 100644 --- a/pallets/payment/src/tests.rs +++ b/pallets/payment/src/tests.rs @@ -648,7 +648,7 @@ fn reply_with_voucher_pays_fee_from_voucher_ok() { program_id, 200_000_000, )); - let voucher_id = GearVoucher::voucher_account_id(&BOB, &program_id); + let voucher_id = GearVoucher::voucher_id(&BOB, &program_id); run_to_block(2); diff --git a/runtime/vara/src/lib.rs b/runtime/vara/src/lib.rs index 784f3a7b435..e6408f6d923 100644 --- a/runtime/vara/src/lib.rs +++ b/runtime/vara/src/lib.rs @@ -994,7 +994,6 @@ impl pallet_gear::Config for Runtime { type BlockLimiter = GearGas; type Scheduler = GearScheduler; type QueueRunner = Gear; - type Voucher = GearVoucher; type ProgramRentFreePeriod = ConstU32<{ MONTHS * RENT_FREE_PERIOD_MONTH_FACTOR }>; type ProgramResumeMinimalRentPeriod = ConstU32<{ WEEKS * RENT_RESUME_WEEK_FACTOR }>; type ProgramRentCostPerBlock = ConstU128; @@ -1060,12 +1059,11 @@ impl DelegateFee for DelegateFeeAccountBuilder { match call { RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { call: pallet_gear_voucher::PrepaidCall::SendMessage { destination, .. }, - }) => Some(GearVoucher::voucher_account_id(who, destination)), + }) => Some(GearVoucher::voucher_id(who, destination)), RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { call: pallet_gear_voucher::PrepaidCall::SendReply { reply_to_id, .. }, - }) => <::Mailbox as Mailbox>::peek(who, reply_to_id).map( - |stored_message| GearVoucher::voucher_account_id(who, &stored_message.source()), - ), + }) => <::Mailbox as Mailbox>::peek(who, reply_to_id) + .map(|stored_message| GearVoucher::voucher_id(who, &stored_message.source())), _ => None, } } From 43d85b9221acb462b49c2bab1c9393f0d8717146 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Mon, 4 Dec 2023 18:26:16 +0100 Subject: [PATCH 2/8] Refactor inner gear calls impls --- pallets/gear/src/lib.rs | 69 +++++++++------------------------------ pallets/gear/src/tests.rs | 27 +++++++-------- 2 files changed, 30 insertions(+), 66 deletions(-) diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index 64edea70fb7..911abcb5658 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -441,8 +441,6 @@ pub mod pallet { ResumePeriodLessThanMinimal, /// Program with the specified id is not found. ProgramNotFound, - /// Voucher can't be redeemed - FailureRedeemingVoucher, /// Gear::run() already included in current block. GearRunAlreadyInBlock, /// The program rent logic is disabled. @@ -1481,8 +1479,8 @@ pub mod pallet { payload, gas_limit, value, - false, keep_alive, + None, ) } @@ -1518,8 +1516,8 @@ pub mod pallet { payload, gas_limit, value, - false, keep_alive, + None, ) } @@ -1818,8 +1816,8 @@ pub mod pallet { payload: Vec, gas_limit: u64, value: BalanceOf, - prepaid: bool, keep_alive: bool, + gas_sponsor: Option>, ) -> DispatchResultWithPostInfo { let payload = payload .try_into() @@ -1850,28 +1848,11 @@ pub mod pallet { // a voucher exists. The latter can only be used to pay for gas or transaction fee. GearBank::::deposit_value(&who, value, keep_alive)?; - let external_node = if prepaid { - // If voucher is used, we attempt to reserve funds on the respective account. - // If no such voucher exists, the call is invalidated. - // TODO (breathx): replace. - let voucher_id = AccountIdOf::::from_origin(0.into_origin()); - - GearBank::::deposit_gas(&voucher_id, gas_limit, keep_alive).map_err(|e| { - log::debug!( - "Failed to redeem voucher for user {who:?} and program {destination:?}: {e:?}" - ); - Error::::FailureRedeemingVoucher - })?; - - voucher_id - } else { - // If voucher is not used, we reserve gas limit on the user's account. - GearBank::::deposit_gas(&who, gas_limit, keep_alive)?; - - who.clone() - }; - - Self::create(external_node, message.id(), gas_limit, false); + // If voucher or any other prepaid mechanism is not used, + // gas limit is taken from user's account. + let gas_sponsor = gas_sponsor.unwrap_or_else(|| who.clone()); + GearBank::::deposit_gas(&gas_sponsor, gas_limit, keep_alive)?; + Self::create(gas_sponsor, message.id(), gas_limit, false); let message = message.into_stored_dispatch(ProgramId::from_origin(origin)); @@ -1921,8 +1902,8 @@ pub mod pallet { payload: Vec, gas_limit: u64, value: BalanceOf, - prepaid: bool, keep_alive: bool, + gas_sponsor: Option>, ) -> DispatchResultWithPostInfo { let payload = payload .try_into() @@ -1953,29 +1934,11 @@ pub mod pallet { GearBank::::deposit_value(&origin, value, keep_alive)?; - let external_node = if prepaid { - // If voucher is used, we attempt to reserve funds on the respective account. - // If no such voucher exists, the call is invalidated. - // TODO (breathx): replace. - let voucher_id = AccountIdOf::::from_origin(0.into_origin()); - - GearBank::::deposit_gas(&voucher_id, gas_limit, keep_alive).map_err(|e| { - log::debug!( - "Failed to redeem voucher for user {origin:?} and program {destination:?}: {e:?}" - ); - Error::::FailureRedeemingVoucher - })?; - - voucher_id - } else { - // If voucher is not used, we reserve gas limit on the user's account. - GearBank::::deposit_gas(&origin, gas_limit, keep_alive)?; - - origin.clone() - }; - - // Following up with a gas node creation. - Self::create(external_node, reply_id, gas_limit, true); + // If voucher or any other prepaid mechanism is not used, + // gas limit is taken from user's account. + let gas_sponsor = gas_sponsor.unwrap_or_else(|| origin.clone()); + GearBank::::deposit_gas(&gas_sponsor, gas_limit, keep_alive)?; + Self::create(gas_sponsor, reply_id, gas_limit, true); // Creating reply message. let message = ReplyMessage::from_packet( @@ -2044,8 +2007,8 @@ pub mod pallet { payload, gas_limit, value, - true, keep_alive, + None, // TODO (breathx): replace. ), PrepaidCall::SendReply { reply_to_id, @@ -2059,8 +2022,8 @@ pub mod pallet { payload, gas_limit, value, - true, keep_alive, + None, // TODO (breathx): replace. ), } } diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 367c54f657d..887e16a8109 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -14300,19 +14300,20 @@ fn send_gasless_message_works() { // Test 1: USER_2 sends a gasless message to the program (intending to use a voucher). // Expect failure because USER_2 has no voucher. - assert_noop!( - GearVoucher::call( - RuntimeOrigin::signed(USER_2), - PrepaidCall::SendMessage { - destination: program_id, - payload: EMPTY_PAYLOAD.to_vec(), - gas_limit: DEFAULT_GAS_LIMIT, - value: 0, - keep_alive: false, - } - ), - Error::::FailureRedeemingVoucher - ); + // TODO (breathx): replace. + // assert_noop!( + // GearVoucher::call( + // RuntimeOrigin::signed(USER_2), + // PrepaidCall::SendMessage { + // destination: program_id, + // payload: EMPTY_PAYLOAD.to_vec(), + // gas_limit: DEFAULT_GAS_LIMIT, + // value: 0, + // keep_alive: false, + // } + // ), + // Error::::FailureRedeemingVoucher + // ); // USER_1 as the program owner issues a voucher for USER_2 enough to send a message assert_ok!(GearVoucher::issue( From 130f1c558d4a785cd395f44256ca9ace42452e6f Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Wed, 13 Dec 2023 17:38:57 +0400 Subject: [PATCH 3/8] Add `sponsor_id` to dispatcher trait --- pallets/gear-voucher/src/lib.rs | 27 +++++++++++++++++++-------- pallets/gear-voucher/src/mock.rs | 1 + pallets/gear/src/lib.rs | 5 +++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pallets/gear-voucher/src/lib.rs b/pallets/gear-voucher/src/lib.rs index f4d90f930d4..a986ba1e9f8 100644 --- a/pallets/gear-voucher/src/lib.rs +++ b/pallets/gear-voucher/src/lib.rs @@ -184,17 +184,27 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; - T::CallsDispatcher::dispatch(origin, call) + let sponsor = Self::sponsor_of(&origin, &call); + + T::CallsDispatcher::dispatch(origin, sponsor, call) } } -} -impl Pallet { - /// Derive a synthesized account ID from an account ID and a program ID. - pub fn voucher_id(who: &T::AccountId, program_id: &ProgramId) -> T::AccountId { - let entropy = (b"modlpy/voucher__", who, program_id).using_encoded(blake2_256); - Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) - .expect("infinite length input; no invalid inputs for type; qed") + impl Pallet { + /// Derive a synthesized account ID from an account ID and a program ID. + pub fn voucher_id(who: &T::AccountId, program_id: &ProgramId) -> T::AccountId { + let entropy = (b"modlpy/voucher__", who, program_id).using_encoded(blake2_256); + Decode::decode(&mut TrailingZeroInput::new(entropy.as_ref())) + .expect("infinite length input; no invalid inputs for type; qed") + } + + /// Return synthesized account ID based on call data. + pub fn sponsor_of(who: &T::AccountId, call: &PrepaidCall>) -> T::AccountId { + match call { + PrepaidCall::SendMessage { destination, .. } => Self::voucher_id(who, destination), + PrepaidCall::SendReply { .. } => todo!("TODO (breathx): extract mailbox here"), + } + } } } @@ -224,6 +234,7 @@ pub trait PrepaidCallsDispatcher { fn dispatch( account_id: Self::AccountId, + sponsor_id: Self::AccountId, call: PrepaidCall, ) -> DispatchResultWithPostInfo; } diff --git a/pallets/gear-voucher/src/mock.rs b/pallets/gear-voucher/src/mock.rs index 418dedc28bc..c8d6f6dfc2f 100644 --- a/pallets/gear-voucher/src/mock.rs +++ b/pallets/gear-voucher/src/mock.rs @@ -71,6 +71,7 @@ impl crate::PrepaidCallsDispatcher for () { } fn dispatch( _account_id: Self::AccountId, + _sponsor_id: Self::AccountId, _call: pallet_gear_voucher::PrepaidCall, ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo { unimplemented!() diff --git a/pallets/gear/src/lib.rs b/pallets/gear/src/lib.rs index 911abcb5658..b69659d8420 100644 --- a/pallets/gear/src/lib.rs +++ b/pallets/gear/src/lib.rs @@ -1992,6 +1992,7 @@ pub mod pallet { fn dispatch( account_id: Self::AccountId, + sponsor_id: Self::AccountId, call: PrepaidCall, ) -> DispatchResultWithPostInfo { match call { @@ -2008,7 +2009,7 @@ pub mod pallet { gas_limit, value, keep_alive, - None, // TODO (breathx): replace. + Some(sponsor_id), ), PrepaidCall::SendReply { reply_to_id, @@ -2023,7 +2024,7 @@ pub mod pallet { gas_limit, value, keep_alive, - None, // TODO (breathx): replace. + Some(sponsor_id), ), } } From b61bc0448bec2b3f3979d645c52974963bf40c3e Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Wed, 13 Dec 2023 18:02:56 +0400 Subject: [PATCH 4/8] Replace error expected in test --- pallets/gear/src/tests.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/pallets/gear/src/tests.rs b/pallets/gear/src/tests.rs index 8be7661fecd..9ceea5eac7f 100644 --- a/pallets/gear/src/tests.rs +++ b/pallets/gear/src/tests.rs @@ -14284,20 +14284,19 @@ fn send_gasless_message_works() { // Test 1: USER_2 sends a gasless message to the program (intending to use a voucher). // Expect failure because USER_2 has no voucher. - // TODO (breathx): replace. - // assert_noop!( - // GearVoucher::call( - // RuntimeOrigin::signed(USER_2), - // PrepaidCall::SendMessage { - // destination: program_id, - // payload: EMPTY_PAYLOAD.to_vec(), - // gas_limit: DEFAULT_GAS_LIMIT, - // value: 0, - // keep_alive: false, - // } - // ), - // Error::::FailureRedeemingVoucher - // ); + assert_noop!( + GearVoucher::call( + RuntimeOrigin::signed(USER_2), + PrepaidCall::SendMessage { + destination: program_id, + payload: EMPTY_PAYLOAD.to_vec(), + gas_limit: DEFAULT_GAS_LIMIT, + value: 0, + keep_alive: false, + } + ), + pallet_gear_bank::Error::::InsufficientBalance + ); // USER_1 as the program owner issues a voucher for USER_2 enough to send a message assert_ok!(GearVoucher::issue( From 4e719c1fa8606f62b6396c9779ac9ccaf1652730 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Wed, 13 Dec 2023 18:08:44 +0400 Subject: [PATCH 5/8] Make `sponsor_of` optional --- pallets/gear-voucher/src/lib.rs | 17 +++++++++++------ pallets/gear-voucher/src/tests.rs | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pallets/gear-voucher/src/lib.rs b/pallets/gear-voucher/src/lib.rs index a986ba1e9f8..4ce86957214 100644 --- a/pallets/gear-voucher/src/lib.rs +++ b/pallets/gear-voucher/src/lib.rs @@ -123,8 +123,8 @@ pub mod pallet { // Gas pallet error. #[pallet::error] pub enum Error { - FailureToCreateVoucher, - FailureToRedeemVoucher, + InsufficientBalance, + InvalidVoucher, } #[pallet::hooks] @@ -163,7 +163,7 @@ pub mod pallet { T::Currency::transfer(&who, &voucher_id, value, ExistenceRequirement::KeepAlive) .map_err(|e| { log::debug!("Failed to transfer funds to the voucher account: {:?}", e); - Error::::FailureToCreateVoucher + Error::::InsufficientBalance })?; Self::deposit_event(Event::VoucherIssued { @@ -184,7 +184,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let origin = ensure_signed(origin)?; - let sponsor = Self::sponsor_of(&origin, &call); + let sponsor = Self::sponsor_of(&origin, &call).ok_or(Error::::InvalidVoucher)?; T::CallsDispatcher::dispatch(origin, sponsor, call) } @@ -199,9 +199,14 @@ pub mod pallet { } /// Return synthesized account ID based on call data. - pub fn sponsor_of(who: &T::AccountId, call: &PrepaidCall>) -> T::AccountId { + pub fn sponsor_of( + who: &T::AccountId, + call: &PrepaidCall>, + ) -> Option { match call { - PrepaidCall::SendMessage { destination, .. } => Self::voucher_id(who, destination), + PrepaidCall::SendMessage { destination, .. } => { + Some(Self::voucher_id(who, destination)) + } PrepaidCall::SendReply { .. } => todo!("TODO (breathx): extract mailbox here"), } } diff --git a/pallets/gear-voucher/src/tests.rs b/pallets/gear-voucher/src/tests.rs index 41674d54ed5..5d16c90ab5e 100644 --- a/pallets/gear-voucher/src/tests.rs +++ b/pallets/gear-voucher/src/tests.rs @@ -47,7 +47,7 @@ fn voucher_issue_works() { // Insufficient funds assert_noop!( Voucher::issue(RuntimeOrigin::signed(ALICE), BOB, program_id, 100_000_000,), - Error::::FailureToCreateVoucher + Error::::InsufficientBalance ); }); } From 9baedba0d40e39411490a159304a0207b6d1fdc4 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Wed, 13 Dec 2023 18:24:43 +0400 Subject: [PATCH 6/8] Add associated type representing mailbox to vouchers --- common/src/storage/complex/mailbox.rs | 5 ++++ pallets/gear-voucher/src/lib.rs | 4 ++++ pallets/gear-voucher/src/mock.rs | 33 +++++++++++++++++++++++++++ pallets/gear/src/mock.rs | 1 + pallets/payment/src/mock.rs | 1 + runtime/vara/src/lib.rs | 1 + 6 files changed, 45 insertions(+) diff --git a/common/src/storage/complex/mailbox.rs b/common/src/storage/complex/mailbox.rs index 0dd98ac590e..da73ebdba30 100644 --- a/common/src/storage/complex/mailbox.rs +++ b/common/src/storage/complex/mailbox.rs @@ -99,6 +99,11 @@ pub trait MailboxError { fn element_not_found() -> Self; } +impl MailboxError for () { + fn duplicate_key() -> Self {} + fn element_not_found() -> Self {} +} + /// `Mailbox` implementation based on `DoubleMapStorage`. /// /// Generic parameter `Error` requires `MailboxError` implementation. diff --git a/pallets/gear-voucher/src/lib.rs b/pallets/gear-voucher/src/lib.rs index 4ce86957214..34ed574687c 100644 --- a/pallets/gear-voucher/src/lib.rs +++ b/pallets/gear-voucher/src/lib.rs @@ -81,7 +81,9 @@ const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); #[frame_support::pallet] pub mod pallet { use super::*; + use common::storage::Mailbox; use frame_system::pallet_prelude::*; + use gear_core::message::UserStoredMessage; #[pallet::config] pub trait Config: frame_system::Config { @@ -102,6 +104,8 @@ pub mod pallet { AccountId = Self::AccountId, Balance = BalanceOf, >; + + type Mailbox: Mailbox; } #[pallet::pallet] diff --git a/pallets/gear-voucher/src/mock.rs b/pallets/gear-voucher/src/mock.rs index c8d6f6dfc2f..8224c66199d 100644 --- a/pallets/gear-voucher/src/mock.rs +++ b/pallets/gear-voucher/src/mock.rs @@ -17,10 +17,12 @@ // along with this program. If not, see . use crate as pallet_gear_voucher; +use common::storage::{Interval, Mailbox}; use frame_support::{ construct_runtime, parameter_types, weights::constants::RocksDbWeight, PalletId, }; use frame_system as system; +use gear_core::{ids::MessageId, message::UserStoredMessage}; use primitive_types::H256; use sp_runtime::{ generic, @@ -78,12 +80,43 @@ impl crate::PrepaidCallsDispatcher for () { } } +pub struct MailboxMock; + +impl Mailbox for MailboxMock { + type BlockNumber = (); + type Error = (); + type Key1 = AccountId; + type Key2 = MessageId; + type Value = UserStoredMessage; + type OutputError = (); + + fn clear() { + unimplemented!() + } + fn contains(_key1: &Self::Key1, _key2: &Self::Key2) -> bool { + unimplemented!() + } + fn insert(_value: Self::Value, _bn: Self::BlockNumber) -> Result<(), Self::OutputError> { + unimplemented!() + } + fn peek(_key1: &Self::Key1, _key2: &Self::Key2) -> Option { + unimplemented!() + } + fn remove( + _key1: Self::Key1, + _key2: Self::Key2, + ) -> Result<(Self::Value, Interval), Self::OutputError> { + unimplemented!() + } +} + impl pallet_gear_voucher::Config for Test { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type PalletId = VoucherPalletId; type WeightInfo = (); type CallsDispatcher = (); + type Mailbox = MailboxMock; } // Build genesis storage according to the mock runtime. diff --git a/pallets/gear/src/mock.rs b/pallets/gear/src/mock.rs index 5932b85898c..107358b2c0c 100644 --- a/pallets/gear/src/mock.rs +++ b/pallets/gear/src/mock.rs @@ -174,6 +174,7 @@ impl pallet_gear_voucher::Config for Test { type PalletId = VoucherPalletId; type WeightInfo = (); type CallsDispatcher = Gear; + type Mailbox = MailboxOf; } // Build genesis storage according to the mock runtime. diff --git a/pallets/payment/src/mock.rs b/pallets/payment/src/mock.rs index 393a9c18004..6e5e71ca7e8 100644 --- a/pallets/payment/src/mock.rs +++ b/pallets/payment/src/mock.rs @@ -189,6 +189,7 @@ impl pallet_gear_voucher::Config for Test { type PalletId = VoucherPalletId; type WeightInfo = (); type CallsDispatcher = Gear; + type Mailbox = MailboxOf; } // Build genesis storage according to the mock runtime. diff --git a/runtime/vara/src/lib.rs b/runtime/vara/src/lib.rs index e6408f6d923..6e91e358501 100644 --- a/runtime/vara/src/lib.rs +++ b/runtime/vara/src/lib.rs @@ -1085,6 +1085,7 @@ impl pallet_gear_voucher::Config for Runtime { type PalletId = VoucherPalletId; type WeightInfo = weights::pallet_gear_voucher::SubstrateWeight; type CallsDispatcher = Gear; + type Mailbox = ::Mailbox; } impl frame_system::offchain::SendTransactionTypes for Runtime From 0e355c44fb212f97e773f278e0b44d74f9b5968b Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Wed, 13 Dec 2023 18:36:05 +0400 Subject: [PATCH 7/8] Remove explicit mailbox dependency --- pallets/gear-voucher/src/lib.rs | 3 ++- pallets/payment/src/mock.rs | 7 +++---- runtime/vara/src/lib.rs | 12 ++++-------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/pallets/gear-voucher/src/lib.rs b/pallets/gear-voucher/src/lib.rs index 34ed574687c..e7e7d0a2980 100644 --- a/pallets/gear-voucher/src/lib.rs +++ b/pallets/gear-voucher/src/lib.rs @@ -211,7 +211,8 @@ pub mod pallet { PrepaidCall::SendMessage { destination, .. } => { Some(Self::voucher_id(who, destination)) } - PrepaidCall::SendReply { .. } => todo!("TODO (breathx): extract mailbox here"), + PrepaidCall::SendReply { reply_to_id, .. } => T::Mailbox::peek(who, reply_to_id) + .map(|stored_message| Self::voucher_id(who, &stored_message.source())), } } } diff --git a/pallets/payment/src/mock.rs b/pallets/payment/src/mock.rs index 6e5e71ca7e8..7cf4809e880 100644 --- a/pallets/payment/src/mock.rs +++ b/pallets/payment/src/mock.rs @@ -164,10 +164,9 @@ impl DelegateFee for DelegateFeeAccountBuilder { RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { call: pallet_gear_voucher::PrepaidCall::SendMessage { .. }, }) => Some(FEE_PAYER), - RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { - call: pallet_gear_voucher::PrepaidCall::SendReply { reply_to_id, .. }, - }) => as common::storage::Mailbox>::peek(who, reply_to_id) - .map(|stored_message| GearVoucher::voucher_id(who, &stored_message.source())), + RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { call }) => { + GearVoucher::sponsor_of(who, call) + } _ => None, } } diff --git a/runtime/vara/src/lib.rs b/runtime/vara/src/lib.rs index 6e91e358501..8b01682a855 100644 --- a/runtime/vara/src/lib.rs +++ b/runtime/vara/src/lib.rs @@ -24,7 +24,7 @@ #[cfg(all(feature = "std", not(feature = "fuzz")))] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use common::storage::{Mailbox, Messenger}; +use common::storage::Messenger; use frame_election_provider_support::{ onchain, ElectionDataProvider, NposSolution, SequentialPhragmen, VoteWeight, }; @@ -1057,13 +1057,9 @@ pub struct DelegateFeeAccountBuilder; impl DelegateFee for DelegateFeeAccountBuilder { fn delegate_fee(call: &RuntimeCall, who: &AccountId) -> Option { match call { - RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { - call: pallet_gear_voucher::PrepaidCall::SendMessage { destination, .. }, - }) => Some(GearVoucher::voucher_id(who, destination)), - RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { - call: pallet_gear_voucher::PrepaidCall::SendReply { reply_to_id, .. }, - }) => <::Mailbox as Mailbox>::peek(who, reply_to_id) - .map(|stored_message| GearVoucher::voucher_id(who, &stored_message.source())), + RuntimeCall::GearVoucher(pallet_gear_voucher::Call::call { call }) => { + GearVoucher::sponsor_of(who, call) + } _ => None, } } From 1b3c7ba282b449c18d224f26c866beda00eff98b Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Wed, 13 Dec 2023 18:54:31 +0400 Subject: [PATCH 8/8] Update `gsdk` metadata --- gsdk/src/metadata/generated.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/gsdk/src/metadata/generated.rs b/gsdk/src/metadata/generated.rs index b64cac4330e..007041e2882 100644 --- a/gsdk/src/metadata/generated.rs +++ b/gsdk/src/metadata/generated.rs @@ -2667,12 +2667,9 @@ pub mod runtime_types { #[doc = "Program with the specified id is not found."] ProgramNotFound, #[codec(index = 14)] - #[doc = "Voucher can't be redeemed"] - FailureRedeemingVoucher, - #[codec(index = 15)] #[doc = "Gear::run() already included in current block."] GearRunAlreadyInBlock, - #[codec(index = 16)] + #[codec(index = 15)] #[doc = "The program rent logic is disabled."] ProgramRentDisabled, } @@ -3339,9 +3336,9 @@ pub mod runtime_types { #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] pub enum Error { #[codec(index = 0)] - FailureToCreateVoucher, + InsufficientBalance, #[codec(index = 1)] - FailureToRedeemVoucher, + InvalidVoucher, } #[derive(Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode)] #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"]