From 436fb36f465729163fc1406b004c7151ef7fd560 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 23 Sep 2024 21:28:17 +0400 Subject: [PATCH 01/12] Introduce proxy builtin, add add_proxy method --- Cargo.lock | 12 +++++ Cargo.toml | 1 + gbuiltins/proxy/Cargo.toml | 14 +++++ gbuiltins/proxy/src/lib.rs | 49 ++++++++++++++++++ pallets/gear-builtin/Cargo.toml | 3 ++ pallets/gear-builtin/src/lib.rs | 40 +++++++++++++++ pallets/gear-builtin/src/proxy.rs | 79 +++++++++++++++++++++++++++++ pallets/gear-builtin/src/staking.rs | 42 +-------------- runtime/vara/Cargo.toml | 1 + runtime/vara/src/lib.rs | 14 +++++ 10 files changed, 215 insertions(+), 40 deletions(-) create mode 100644 gbuiltins/proxy/Cargo.toml create mode 100644 gbuiltins/proxy/src/lib.rs create mode 100644 pallets/gear-builtin/src/proxy.rs diff --git a/Cargo.lock b/Cargo.lock index 1de88b5aea0..8b634d3b6ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6270,6 +6270,15 @@ dependencies = [ "scale-info", ] +[[package]] +name = "gbuiltin-proxy" +version = "1.5.0" +dependencies = [ + "derive_more 0.99.18", + "gprimitives", + "scale-info", +] + [[package]] name = "gbuiltin-staking" version = "1.5.0" @@ -11531,6 +11540,7 @@ dependencies = [ "frame-support-test", "frame-system", "gbuiltin-bls381", + "gbuiltin-proxy", "gbuiltin-staking", "gear-common", "gear-core", @@ -11549,6 +11559,7 @@ dependencies = [ "pallet-gear-messenger", "pallet-gear-program", "pallet-gear-scheduler", + "pallet-proxy", "pallet-session", "pallet-staking", "pallet-timestamp", @@ -18855,6 +18866,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", + "gbuiltin-proxy", "gbuiltin-staking", "gear-common", "gear-core", diff --git a/Cargo.toml b/Cargo.toml index a12c7c8740d..15b31a87205 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -213,6 +213,7 @@ galloc = { path = "galloc" } gbuiltin-bls381 = { path = "gbuiltins/bls381", default-features = false } gbuiltin-eth-bridge = { path = "gbuiltins/eth-bridge", default-features = false } gbuiltin-staking = { path = "gbuiltins/staking" } +gbuiltin-proxy = { path = "gbuiltins/proxy" } gcore = { path = "gcore" } gcli = { path = "gcli" } gclient = { path = "gclient" } diff --git a/gbuiltins/proxy/Cargo.toml b/gbuiltins/proxy/Cargo.toml new file mode 100644 index 00000000000..4912223625b --- /dev/null +++ b/gbuiltins/proxy/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "gbuiltin-proxy" +description = "Types and traits to interact with proxy builtin actor." +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +gprimitives.workspace = true +derive_more.workspace = true +scale-info = { workspace = true, features = ["derive"] } diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs new file mode 100644 index 00000000000..c7a2d9caa1c --- /dev/null +++ b/gbuiltins/proxy/src/lib.rs @@ -0,0 +1,49 @@ +// This file is part of Gear. + +// Copyright (C) 2021-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 . + +#![no_std] + +use gprimitives::ActorId; +use scale_info::scale::{self, Decode, Encode}; + +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode)] +#[codec(crate = scale)] +pub enum Request { + AddProxy { + delegate: ActorId, + proxy_type: ProxyType, + delay: u32, + }, + // Announce, + // Proxy, + // ProxyAnnounced +} + +/// Proxy type. +/// +/// The mirror enum for the one defined in vara-runtime crate. +#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode)] +#[codec(crate = scale)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, + IdentityJudgement, + CancelProxy, +} diff --git a/pallets/gear-builtin/Cargo.toml b/pallets/gear-builtin/Cargo.toml index cbb9c77edf4..08a93af2ee9 100644 --- a/pallets/gear-builtin/Cargo.toml +++ b/pallets/gear-builtin/Cargo.toml @@ -30,6 +30,7 @@ common.workspace = true core-processor.workspace = true gbuiltin-bls381.workspace = true gbuiltin-staking.workspace = true +gbuiltin-proxy.workspace = true gear-core.workspace = true gear-core-errors.workspace = true gear-runtime-interface.workspace = true @@ -41,6 +42,7 @@ sp-std.workspace = true sp-runtime = { workspace = true, features = ["serde"] } pallet-gear.workspace = true pallet-staking.workspace = true +pallet-proxy.workspace = true [dev-dependencies] demo-waiting-proxy.workspace = true @@ -81,6 +83,7 @@ std = [ "gear-runtime-interface/std", "pallet-gear/std", "pallet-staking/std", + "pallet-proxy/std", "parity-scale-codec/std", "scale-info/std", "sp-crypto-ec-utils/std", diff --git a/pallets/gear-builtin/src/lib.rs b/pallets/gear-builtin/src/lib.rs index e31069a873e..304db8577a7 100644 --- a/pallets/gear-builtin/src/lib.rs +++ b/pallets/gear-builtin/src/lib.rs @@ -36,6 +36,7 @@ extern crate alloc; pub mod benchmarking; pub mod bls12_381; +pub mod proxy; pub mod staking; pub mod weights; @@ -58,6 +59,7 @@ use core_processor::{ process_execution_error, process_success, SuccessfulDispatchResultKind, SystemReservationContext, }; +use frame_support::dispatch::extract_actual_weight; use gear_core::{ gas::GasCounter, ids::{hash, ProgramId}, @@ -73,6 +75,8 @@ use sp_std::prelude::*; pub use pallet::*; +type CallOf = ::RuntimeCall; + const LOG_TARGET: &str = "gear::builtin"; /// Built-in actor error type @@ -212,6 +216,42 @@ pub mod pallet { pub fn generate_actor_id(builtin_id: u64) -> ProgramId { hash((SEED, builtin_id).encode().as_slice()).into() } + + pub(crate) fn dispatch_call( + origin: T::AccountId, + call: CallOf, + gas_limit: u64, + ) -> (Result<(), BuiltinActorError>, u64) { + let call_info = call.get_dispatch_info(); + + // Necessary upfront gas sufficiency check + if gas_limit < call_info.weight.ref_time() { + return (Err(BuiltinActorError::InsufficientGas), 0_u64); + } + + // Execute call + let res = call.dispatch(frame_system::RawOrigin::Signed(origin).into()); + let actual_gas = extract_actual_weight(&res, &call_info).ref_time(); + + match res { + Ok(_post_info) => { + log::debug!( + target: LOG_TARGET, + "Call dispatched successfully", + ); + (Ok(()), actual_gas) + } + Err(e) => { + log::debug!(target: LOG_TARGET, "Error dispatching call: {:?}", e); + ( + Err(BuiltinActorError::Custom(LimitedStr::from_small_str( + e.into(), + ))), + actual_gas, + ) + } + } + } } } diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs new file mode 100644 index 00000000000..b142a708e4a --- /dev/null +++ b/pallets/gear-builtin/src/proxy.rs @@ -0,0 +1,79 @@ +// 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 . + +//! Proxy builtin actor implementation. + +use super::*; +use common::Origin; +use gbuiltin_proxy::{ProxyType as BuiltinProxyType, Request}; +use pallet_proxy::Config as ProxyConfig; +use sp_runtime::traits::StaticLookup; + +/// Proxy builtin actor. +pub struct Actor(PhantomData); + +impl Actor +where + T::AccountId: Origin, + ::ProxyType: From, + CallOf: From>, +{ + fn cast(request: Request) -> CallOf { + match request { + Request::AddProxy { + delegate, + proxy_type, + delay, + } => { + let delegate = T::Lookup::unlookup(delegate.cast()); + let proxy_type = proxy_type.into(); + let delay = delay.into(); + + pallet_proxy::Call::::add_proxy { + delegate, + proxy_type, + delay, + } + } + } + .into() + } +} + +impl BuiltinActor for Actor +where + T::AccountId: Origin, + ::ProxyType: From, + CallOf: From>, +{ + type Error = BuiltinActorError; + + fn handle(dispatch: &StoredDispatch, gas_limit: u64) -> (Result, u64) { + let Ok(request) = Request::decode(&mut dispatch.payload_bytes()) else { + return (Err(BuiltinActorError::DecodingError), 0); + }; + + let origin = dispatch.source().cast(); + + // todo spend gas + let call = Self::cast(request); + let (result, actual_gas) = Pallet::::dispatch_call(origin, call, gas_limit); + + (result.map(|_| Default::default()), actual_gas) + } +} diff --git a/pallets/gear-builtin/src/staking.rs b/pallets/gear-builtin/src/staking.rs index d6900bb5f68..f03db222f8c 100644 --- a/pallets/gear-builtin/src/staking.rs +++ b/pallets/gear-builtin/src/staking.rs @@ -21,13 +21,10 @@ use super::*; use common::Origin; use core::marker::PhantomData; -use frame_support::dispatch::{extract_actual_weight, GetDispatchInfo}; use gbuiltin_staking::*; use pallet_staking::{Config as StakingConfig, NominationsQuota, RewardDestination}; use parity_scale_codec::Decode; -use sp_runtime::traits::{Dispatchable, StaticLookup, UniqueSaturatedInto}; - -type CallOf = ::RuntimeCall; +use sp_runtime::traits::{StaticLookup, UniqueSaturatedInto}; pub struct Actor(PhantomData); @@ -36,41 +33,6 @@ where T::AccountId: Origin, CallOf: From>, { - fn dispatch_call( - origin: T::AccountId, - call: CallOf, - gas_limit: u64, - ) -> (Result<(), BuiltinActorError>, u64) { - let call_info = call.get_dispatch_info(); - - // Necessary upfront gas sufficiency check - if gas_limit < call_info.weight.ref_time() { - return (Err(BuiltinActorError::InsufficientGas), 0_u64); - } - - // Execute call - let res = call.dispatch(frame_system::RawOrigin::Signed(origin).into()); - let actual_gas = extract_actual_weight(&res, &call_info).ref_time(); - match res { - Ok(_post_info) => { - log::debug!( - target: LOG_TARGET, - "Call dispatched successfully", - ); - (Ok(()), actual_gas) - } - Err(e) => { - log::debug!(target: LOG_TARGET, "Error dispatching call: {:?}", e); - ( - Err(BuiltinActorError::Custom(LimitedStr::from_small_str( - e.into(), - ))), - actual_gas, - ) - } - } - } - fn cast(request: Request) -> CallOf { match request { Request::Bond { value, payee } => { @@ -169,7 +131,7 @@ where // Handle staking requests let call = Self::cast(request); - let (result, gas_spent) = Self::dispatch_call(origin, call, gas_limit); + let (result, gas_spent) = Pallet::::dispatch_call(origin, call, gas_limit); (result.map(|_| Default::default()), gas_spent) } diff --git a/runtime/vara/Cargo.toml b/runtime/vara/Cargo.toml index 512d3bc73c0..fc902592b4c 100644 --- a/runtime/vara/Cargo.toml +++ b/runtime/vara/Cargo.toml @@ -106,6 +106,7 @@ pallet-gear-builtin-rpc-runtime-api.workspace = true pallet-gear-eth-bridge-rpc-runtime-api.workspace = true runtime-primitives.workspace = true gbuiltin-staking.workspace = true +gbuiltin-proxy.workspace = true [dev-dependencies] sp-io.workspace = true diff --git a/runtime/vara/src/lib.rs b/runtime/vara/src/lib.rs index 020dbcc7a1d..ea7aa2d692e 100644 --- a/runtime/vara/src/lib.rs +++ b/runtime/vara/src/lib.rs @@ -65,6 +65,7 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; +use gbuiltin_proxy::ProxyType as BuiltinProxyType; use pallet_election_provider_multi_phase::{GeometricDepositBase, SolutionAccuracyOf}; pub use pallet_gear::manager::{ExtManager, HandleKind}; use pallet_gear_builtin::ActorWithId; @@ -1003,6 +1004,19 @@ impl Default for ProxyType { } } +impl From for ProxyType { + fn from(proxy_type: BuiltinProxyType) -> Self { + match proxy_type { + BuiltinProxyType::Any => ProxyType::Any, + BuiltinProxyType::NonTransfer => ProxyType::NonTransfer, + BuiltinProxyType::Governance => ProxyType::Governance, + BuiltinProxyType::Staking => ProxyType::Staking, + BuiltinProxyType::IdentityJudgement => ProxyType::IdentityJudgement, + BuiltinProxyType::CancelProxy => ProxyType::CancelProxy, + } + } +} + impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { From 12bd116820fd55c13f7855970e5a18ba93636436 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Tue, 24 Sep 2024 18:20:20 +0400 Subject: [PATCH 02/12] Introduce first test --- Cargo.lock | 14 ++++ Cargo.toml | 2 + examples/proxy-broker/Cargo.toml | 24 ++++++ examples/proxy-broker/build.rs | 21 +++++ examples/proxy-broker/src/lib.rs | 33 ++++++++ examples/proxy-broker/src/wasm.rs | 61 ++++++++++++++ pallets/gear-builtin/Cargo.toml | 1 + pallets/gear-builtin/src/mock.rs | 107 +++++++++++++++++++++++- pallets/gear-builtin/src/tests/mod.rs | 1 + pallets/gear-builtin/src/tests/proxy.rs | 85 +++++++++++++++++++ runtime/vara/src/lib.rs | 4 +- 11 files changed, 349 insertions(+), 4 deletions(-) create mode 100644 examples/proxy-broker/Cargo.toml create mode 100644 examples/proxy-broker/build.rs create mode 100644 examples/proxy-broker/src/lib.rs create mode 100644 examples/proxy-broker/src/wasm.rs create mode 100644 pallets/gear-builtin/src/tests/proxy.rs diff --git a/Cargo.lock b/Cargo.lock index 8b634d3b6ad..2c823115876 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3839,6 +3839,19 @@ dependencies = [ "scale-info", ] +[[package]] +name = "demo-proxy-broker" +version = "0.1.0" +dependencies = [ + "gbuiltin-proxy", + "gear-wasm-builder", + "gstd", + "hashbrown 0.14.5", + "hex", + "hex-literal", + "parity-scale-codec", +] + [[package]] name = "demo-proxy-relay" version = "0.1.0" @@ -11529,6 +11542,7 @@ dependencies = [ "ark-scale 0.0.12", "ark-serialize 0.4.2", "ark-std 0.4.0", + "demo-proxy-broker", "demo-staking-broker", "demo-waiting-proxy", "derive_more 0.99.18", diff --git a/Cargo.toml b/Cargo.toml index 15b31a87205..ac0b77c9f9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ members = [ "examples/program-factory", "examples/program-generator", "examples/proxy", + "examples/proxy-broker", "examples/proxy-relay", "examples/proxy-reservation-with-gas", "examples/read-big-state", @@ -486,6 +487,7 @@ demo-rwlock = { path = "examples/rwlock" } demo-send-from-reservation = { path = "examples/send-from-reservation" } demo-signal-entry = { path = "examples/signal-entry", default-features = false } demo-staking-broker = { path = "examples/staking-broker" } +demo-proxy-broker = { path = "examples/proxy-broker" } demo-state-rollback = { path = "examples/state-rollback" } demo-sync-duplicate = { path = "examples/sync-duplicate" } demo-vec = { path = "examples/vec" } diff --git a/examples/proxy-broker/Cargo.toml b/examples/proxy-broker/Cargo.toml new file mode 100644 index 00000000000..f87c48a6a60 --- /dev/null +++ b/examples/proxy-broker/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "demo-proxy-broker" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +gbuiltin-proxy.workspace = true +gstd.workspace = true +hashbrown.workspace = true +hex.workspace = true +hex-literal.workspace = true +parity-scale-codec.workspace = true + +[build-dependencies] +gear-wasm-builder.workspace = true + +[features] +debug = ["gstd/debug"] +std = [] +default = ["std"] diff --git a/examples/proxy-broker/build.rs b/examples/proxy-broker/build.rs new file mode 100644 index 00000000000..6a370b53a71 --- /dev/null +++ b/examples/proxy-broker/build.rs @@ -0,0 +1,21 @@ +// 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 . + +fn main() { + gear_wasm_builder::build(); +} diff --git a/examples/proxy-broker/src/lib.rs b/examples/proxy-broker/src/lib.rs new file mode 100644 index 00000000000..28b7cf0f8c3 --- /dev/null +++ b/examples/proxy-broker/src/lib.rs @@ -0,0 +1,33 @@ +// 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_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "std")] +mod code { + include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +} + +#[cfg(feature = "std")] +pub use code::WASM_BINARY_OPT as WASM_BINARY; + +#[cfg(not(feature = "std"))] +pub const WASM_BINARY: &[u8] = &[]; + +#[cfg(not(feature = "std"))] +pub mod wasm; diff --git a/examples/proxy-broker/src/wasm.rs b/examples/proxy-broker/src/wasm.rs new file mode 100644 index 00000000000..9cd0e8f1987 --- /dev/null +++ b/examples/proxy-broker/src/wasm.rs @@ -0,0 +1,61 @@ +// 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 . + +//! Basic implementation of the proxy-broker for demo purpose only. + +use gbuiltin_proxy::Request; +use gstd::{debug, errors::Error, msg, ActorId}; +use hex_literal::hex; + +// Proxy builtin actor program id (hardcoded for all runtimes); +// +// Calculated as hash((b"built/in", 3u64).encode()) +const BUILTIN_ADDRESS: ActorId = ActorId::new(hex!( + "f2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf" +)); + +#[gstd::async_main] +async fn main() { + let request: Request = msg::load().expect("handle: invalid payload received"); + match request { + add_proxy @ Request::AddProxy { .. } => { + debug!( + "[ProxyBroker]: Sending `add_proxy` request with data {:?}", + add_proxy + ); + let res = msg::send_for_reply(BUILTIN_ADDRESS, add_proxy, 0, 0) + .expect("handle::add_proxy: failed sending message for reply") + .await; + match res { + Ok(_) => { + debug!("[ProxyBroker] Success reply from builtin actor received"); + msg::reply_bytes(b"Success", 0).expect("Failed to send reply"); + } + Err(e) => { + debug!("[ProxyBroker] Error reply from builtin actor received: {e:?}"); + match e { + Error::ErrorReply(payload, _) => { + panic!("{}", payload); + } + _ => panic!("Error in upstream program"), + } + } + } + } + } +} diff --git a/pallets/gear-builtin/Cargo.toml b/pallets/gear-builtin/Cargo.toml index 08a93af2ee9..4430f848c20 100644 --- a/pallets/gear-builtin/Cargo.toml +++ b/pallets/gear-builtin/Cargo.toml @@ -47,6 +47,7 @@ pallet-proxy.workspace = true [dev-dependencies] demo-waiting-proxy.workspace = true demo-staking-broker.workspace = true +demo-proxy-broker.workspace = true gprimitives.workspace = true sp-core = { workspace = true, features = ["std"] } sp-externalities = { workspace = true, features = ["std"] } diff --git a/pallets/gear-builtin/src/mock.rs b/pallets/gear-builtin/src/mock.rs index 98ce908b8b7..bf66e8bdc94 100644 --- a/pallets/gear-builtin/src/mock.rs +++ b/pallets/gear-builtin/src/mock.rs @@ -16,23 +16,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{self as pallet_gear_builtin, bls12_381, ActorWithId, BuiltinActor, BuiltinActorError}; +use crate::{ + self as pallet_gear_builtin, bls12_381, proxy, ActorWithId, BuiltinActor, BuiltinActorError, +}; use common::{GasProvider, GasTree}; use core::cell::RefCell; use frame_support::{ construct_runtime, parameter_types, - traits::{ConstBool, ConstU32, ConstU64, FindAuthor, OnFinalize, OnInitialize}, + traits::{ConstBool, ConstU32, ConstU64, FindAuthor, InstanceFilter, OnFinalize, OnInitialize}, }; use frame_support_test::TestRandomness; use frame_system::{self as system, pallet_prelude::BlockNumberFor}; +use gbuiltin_proxy::ProxyType as BuiltinProxyType; use gear_core::{ ids::ProgramId, message::{Payload, StoredDispatch}, }; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use sp_core::H256; use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, Perbill, Permill, + BuildStorage, Perbill, Permill, RuntimeDebug, }; use sp_std::convert::{TryFrom, TryInto}; @@ -79,6 +83,7 @@ construct_runtime!( Authorship: pallet_authorship, Timestamp: pallet_timestamp, Staking: pallet_staking, + Proxy: pallet_proxy, GearProgram: pallet_gear_program, GearMessenger: pallet_gear_messenger, GearScheduler: pallet_gear_scheduler, @@ -94,12 +99,107 @@ parameter_types! { pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; } +#[derive( + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, +)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, + IdentityJudgement, + CancelProxy, +} + +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} + +impl From for ProxyType { + fn from(proxy_type: BuiltinProxyType) -> Self { + match proxy_type { + BuiltinProxyType::Any => ProxyType::Any, + BuiltinProxyType::NonTransfer => ProxyType::NonTransfer, + BuiltinProxyType::Governance => ProxyType::Governance, + BuiltinProxyType::Staking => ProxyType::Staking, + BuiltinProxyType::IdentityJudgement => ProxyType::IdentityJudgement, + BuiltinProxyType::CancelProxy => ProxyType::CancelProxy, + } + } +} + +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => { + return !matches!(c, RuntimeCall::Balances(..)); + } + ProxyType::CancelProxy => { + matches!( + c, + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) + ) + } + ProxyType::Staking => matches!(c, RuntimeCall::Staking(..)), + ProxyType::Governance | ProxyType::IdentityJudgement => { + unimplemented!("No pallets defined in test runtime") + } + } + } + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + (ProxyType::NonTransfer, _) => true, + _ => false, + } + } +} + common::impl_pallet_system!(Test); common::impl_pallet_balances!(Test); common::impl_pallet_authorship!(Test); common::impl_pallet_timestamp!(Test); common::impl_pallet_staking!(Test); +parameter_types! { + pub const ProxyDepositBase: Balance = 1; + pub const ProxyDepositFactor: Balance = 1; + pub const MaxProxies: u32 = 100; + pub const MaxPending: u32 = 100; + pub const AnnouncementDepositBase: Balance = 1; + pub const AnnouncementDepositFactor: Balance = 1; +} + +impl pallet_proxy::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type MaxProxies = MaxProxies; + type WeightInfo = (); + type MaxPending = MaxPending; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositBase; +} + parameter_types! { pub const BlockGasLimit: u64 = 100_000_000_000; pub const OutgoingLimit: u32 = 1024; @@ -222,6 +322,7 @@ impl pallet_gear_builtin::Config for Test { ActorWithId, ActorWithId, ActorWithId<1, bls12_381::Actor>, + ActorWithId<3, proxy::Actor>, ); type WeightInfo = (); } diff --git a/pallets/gear-builtin/src/tests/mod.rs b/pallets/gear-builtin/src/tests/mod.rs index d071cfd12b6..4ef70e44a06 100644 --- a/pallets/gear-builtin/src/tests/mod.rs +++ b/pallets/gear-builtin/src/tests/mod.rs @@ -21,4 +21,5 @@ pub mod bad_builtin_ids; pub mod basic; pub mod bls381; +mod proxy; pub mod staking; diff --git a/pallets/gear-builtin/src/tests/proxy.rs b/pallets/gear-builtin/src/tests/proxy.rs new file mode 100644 index 00000000000..dbfb96749d2 --- /dev/null +++ b/pallets/gear-builtin/src/tests/proxy.rs @@ -0,0 +1,85 @@ +// This file is part of Gear. + +// Copyright (C) 2021-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 . + +//! Proxy builtin tests. + +use super::basic::init_logger; +use crate::mock::*; +use common::Origin; +use demo_proxy_broker::WASM_BINARY; +use frame_support::assert_ok; +use gbuiltin_proxy::{ProxyType, Request}; +use gear_core::ids::{prelude::*, CodeId, ProgramId}; +use parity_scale_codec::Encode; + +#[test] +fn add_proxy_works() { + init_logger(); + new_test_ext().execute_with(|| { + let proxy_pid = utils::upload_and_initialize_broker(); + + assert_ok!(Gear::send_message( + RuntimeOrigin::signed(SIGNER), + proxy_pid, + Request::AddProxy { + delegate: SIGNER.cast(), + proxy_type: ProxyType::Any, + delay: 1 + } + .encode(), + 10_000_000_000, + 0, + false, + )); + run_to_next_block(); + + log::debug!("EVENTS {:#?}", System::events()); + + // TODO check proxy added + }) +} + +mod utils { + use super::*; + + pub(super) fn upload_and_initialize_broker() -> ProgramId { + let code = WASM_BINARY; + let salt = b"proxy_broker"; + let pid = ProgramId::generate_from_user(CodeId::generate(code), salt); + assert_ok!(Gear::upload_program( + RuntimeOrigin::signed(SIGNER), + code.to_vec(), + salt.to_vec(), + Default::default(), + 10_000_000_000, + 0, + false, + )); + run_to_next_block(); + + // Top up program's account balance by 2000 to allow user claim 1000 from mailbox + assert_ok!(>::transfer( + &1, + &pid.cast(), + 2000, + frame_support::traits::ExistenceRequirement::AllowDeath + )); + + pid + } +} diff --git a/runtime/vara/src/lib.rs b/runtime/vara/src/lib.rs index ea7aa2d692e..f1e0ccbab0f 100644 --- a/runtime/vara/src/lib.rs +++ b/runtime/vara/src/lib.rs @@ -1194,6 +1194,7 @@ impl pallet_gear_messenger::Config for Runtime { pub type BuiltinActors = ( ActorWithId<1, pallet_gear_builtin::bls12_381::Actor>, ActorWithId<2, pallet_gear_builtin::staking::Actor>, + ActorWithId<3, pallet_gear_builtin::proxy::Actor>, ); /// Builtin actors arranged in a tuple. @@ -1201,7 +1202,8 @@ pub type BuiltinActors = ( pub type BuiltinActors = ( ActorWithId<1, pallet_gear_builtin::bls12_381::Actor>, ActorWithId<2, pallet_gear_builtin::staking::Actor>, - ActorWithId<3, pallet_gear_eth_bridge::Actor>, + ActorWithId<3, pallet_gear_builtin::proxy::Actor>, + ActorWithId<4, pallet_gear_eth_bridge::Actor>, ); impl pallet_gear_builtin::Config for Runtime { From 356bf0b4f2a4f7c2c64c7e5910b56352836d8f39 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 25 Sep 2024 15:57:04 +0400 Subject: [PATCH 03/12] Introduce other proxy calls --- examples/proxy-broker/src/wasm.rs | 47 ++++++++++++++--------- gbuiltins/proxy/src/lib.rs | 20 ++++++++-- pallets/gear-builtin/src/proxy.rs | 50 +++++++++++++++++++++---- pallets/gear-builtin/src/tests/proxy.rs | 35 +++++++++++++++-- 4 files changed, 120 insertions(+), 32 deletions(-) diff --git a/examples/proxy-broker/src/wasm.rs b/examples/proxy-broker/src/wasm.rs index 9cd0e8f1987..bdf584fc4cf 100644 --- a/examples/proxy-broker/src/wasm.rs +++ b/examples/proxy-broker/src/wasm.rs @@ -35,26 +35,39 @@ async fn main() { match request { add_proxy @ Request::AddProxy { .. } => { debug!( - "[ProxyBroker]: Sending `add_proxy` request with data {:?}", + "handle: Sending `add_proxy` request with data {:?}", add_proxy ); - let res = msg::send_for_reply(BUILTIN_ADDRESS, add_proxy, 0, 0) - .expect("handle::add_proxy: failed sending message for reply") - .await; - match res { - Ok(_) => { - debug!("[ProxyBroker] Success reply from builtin actor received"); - msg::reply_bytes(b"Success", 0).expect("Failed to send reply"); - } - Err(e) => { - debug!("[ProxyBroker] Error reply from builtin actor received: {e:?}"); - match e { - Error::ErrorReply(payload, _) => { - panic!("{}", payload); - } - _ => panic!("Error in upstream program"), - } + + send_request(add_proxy).await; + } + remove_proxy @ Request::RemoveProxy { .. } => { + debug!( + "handle: Sending `remove_proxy` request with data {:?}", + remove_proxy + ); + + send_request(remove_proxy).await; + } + } +} + +async fn send_request(req: Request) { + let res = msg::send_for_reply(BUILTIN_ADDRESS, req, 0, 0) + .expect("handle::send_request: failed sending message for reply") + .await; + match res { + Ok(_) => { + debug!("handle::send_request: Success reply from builtin actor received"); + msg::reply_bytes(b"Success", 0).expect("Failed to send reply"); + } + Err(e) => { + debug!("handle::send_request: Error reply from builtin actor received: {e:?}"); + match e { + Error::ErrorReply(payload, _) => { + panic!("{}", payload); } + _ => panic!("Error in upstream program"), } } } diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs index c7a2d9caa1c..a9ce220a193 100644 --- a/gbuiltins/proxy/src/lib.rs +++ b/gbuiltins/proxy/src/lib.rs @@ -18,20 +18,34 @@ #![no_std] +extern crate alloc; + +use alloc::vec::Vec; use gprimitives::ActorId; use scale_info::scale::{self, Decode, Encode}; #[derive(Debug, Clone, Eq, PartialEq, Encode, Decode)] #[codec(crate = scale)] pub enum Request { + // todo currently with no delay AddProxy { delegate: ActorId, proxy_type: ProxyType, + }, + RemoveProxy { + delegate: ActorId, + proxy_type: ProxyType, delay: u32, }, - // Announce, - // Proxy, - // ProxyAnnounced + Proxy { + real: ActorId, + force_proxy_type: Option, + encoded_call: Vec, + }, // RemoveProxies, + // Proxy, + // Announce, + // Proxy, + // ProxyAnnounced } /// Proxy type. diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs index b142a708e4a..d5e5c998fd5 100644 --- a/pallets/gear-builtin/src/proxy.rs +++ b/pallets/gear-builtin/src/proxy.rs @@ -33,25 +33,56 @@ where ::ProxyType: From, CallOf: From>, { - fn cast(request: Request) -> CallOf { - match request { + fn cast(request: Request) -> Result, BuiltinActorError> { + Ok(match request { Request::AddProxy { delegate, proxy_type, + } => { + let delegate = T::Lookup::unlookup(delegate.cast()); + let proxy_type = proxy_type.into(); + let delay = 0u32.into(); + + pallet_proxy::Call::::add_proxy { + delegate, + proxy_type, + delay, + } + } + Request::RemoveProxy { + delegate, + proxy_type, delay, } => { let delegate = T::Lookup::unlookup(delegate.cast()); let proxy_type = proxy_type.into(); let delay = delay.into(); - pallet_proxy::Call::::add_proxy { + pallet_proxy::Call::::remove_proxy { delegate, proxy_type, delay, } } + Request::Proxy { + real, + force_proxy_type, + encoded_call, + } => { + let real = T::Lookup::unlookup(real.cast()); + let force_proxy_type = force_proxy_type.map(Into::into); + let runtime_call = + ::RuntimeCall::decode(&mut encoded_call.as_ref()) + .map_err(|_| BuiltinActorError::DecodingError)?; + + pallet_proxy::Call::::proxy { + real, + force_proxy_type, + call: Box::new(runtime_call), + } + } } - .into() + .into()) } } @@ -71,9 +102,12 @@ where let origin = dispatch.source().cast(); // todo spend gas - let call = Self::cast(request); - let (result, actual_gas) = Pallet::::dispatch_call(origin, call, gas_limit); - - (result.map(|_| Default::default()), actual_gas) + match Self::cast(request) { + Ok(call) => { + let (result, actual_gas) = Pallet::::dispatch_call(origin, call, gas_limit); + (result.map(|_| Default::default()), actual_gas) + } + Err(e) => (Err(e), gas_limit), + } } } diff --git a/pallets/gear-builtin/src/tests/proxy.rs b/pallets/gear-builtin/src/tests/proxy.rs index dbfb96749d2..f3c7899b872 100644 --- a/pallets/gear-builtin/src/tests/proxy.rs +++ b/pallets/gear-builtin/src/tests/proxy.rs @@ -25,10 +25,11 @@ use demo_proxy_broker::WASM_BINARY; use frame_support::assert_ok; use gbuiltin_proxy::{ProxyType, Request}; use gear_core::ids::{prelude::*, CodeId, ProgramId}; +use pallet_proxy::Event as ProxyEvent; use parity_scale_codec::Encode; #[test] -fn add_proxy_works() { +fn add_remove_proxy_works() { init_logger(); new_test_ext().execute_with(|| { let proxy_pid = utils::upload_and_initialize_broker(); @@ -48,9 +49,36 @@ fn add_proxy_works() { )); run_to_next_block(); - log::debug!("EVENTS {:#?}", System::events()); + System::assert_has_event(RuntimeEvent::Proxy(ProxyEvent::ProxyAdded { + delegator: proxy_pid.cast(), + delegatee: SIGNER, + proxy_type: ProxyType::Any.into(), + delay: 1, + })); - // TODO check proxy added + System::reset_events(); + + assert_ok!(Gear::send_message( + RuntimeOrigin::signed(SIGNER), + proxy_pid, + Request::RemoveProxy { + delegate: SIGNER.cast(), + proxy_type: ProxyType::Any, + delay: 1 + } + .encode(), + 10_000_000_000, + 0, + false, + )); + run_to_next_block(); + + System::assert_has_event(RuntimeEvent::Proxy(ProxyEvent::ProxyRemoved { + delegator: proxy_pid.cast(), + delegatee: SIGNER, + proxy_type: ProxyType::Any.into(), + delay: 1, + })); }) } @@ -72,7 +100,6 @@ mod utils { )); run_to_next_block(); - // Top up program's account balance by 2000 to allow user claim 1000 from mailbox assert_ok!(>::transfer( &1, &pid.cast(), From c20d411079c592ce228ee6e2ee249d0c56fdc594 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 25 Sep 2024 15:58:23 +0400 Subject: [PATCH 04/12] Minor fix --- gbuiltins/proxy/src/lib.rs | 1 - pallets/gear-builtin/src/proxy.rs | 3 +-- pallets/gear-builtin/src/tests/proxy.rs | 8 ++++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs index a9ce220a193..d872f1436a8 100644 --- a/gbuiltins/proxy/src/lib.rs +++ b/gbuiltins/proxy/src/lib.rs @@ -35,7 +35,6 @@ pub enum Request { RemoveProxy { delegate: ActorId, proxy_type: ProxyType, - delay: u32, }, Proxy { real: ActorId, diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs index d5e5c998fd5..c7e11870838 100644 --- a/pallets/gear-builtin/src/proxy.rs +++ b/pallets/gear-builtin/src/proxy.rs @@ -52,11 +52,10 @@ where Request::RemoveProxy { delegate, proxy_type, - delay, } => { let delegate = T::Lookup::unlookup(delegate.cast()); let proxy_type = proxy_type.into(); - let delay = delay.into(); + let delay = 0u32.into(); pallet_proxy::Call::::remove_proxy { delegate, diff --git a/pallets/gear-builtin/src/tests/proxy.rs b/pallets/gear-builtin/src/tests/proxy.rs index f3c7899b872..214fcbc105c 100644 --- a/pallets/gear-builtin/src/tests/proxy.rs +++ b/pallets/gear-builtin/src/tests/proxy.rs @@ -40,7 +40,6 @@ fn add_remove_proxy_works() { Request::AddProxy { delegate: SIGNER.cast(), proxy_type: ProxyType::Any, - delay: 1 } .encode(), 10_000_000_000, @@ -53,7 +52,7 @@ fn add_remove_proxy_works() { delegator: proxy_pid.cast(), delegatee: SIGNER, proxy_type: ProxyType::Any.into(), - delay: 1, + delay: 0 })); System::reset_events(); @@ -64,7 +63,6 @@ fn add_remove_proxy_works() { Request::RemoveProxy { delegate: SIGNER.cast(), proxy_type: ProxyType::Any, - delay: 1 } .encode(), 10_000_000_000, @@ -77,8 +75,10 @@ fn add_remove_proxy_works() { delegator: proxy_pid.cast(), delegatee: SIGNER, proxy_type: ProxyType::Any.into(), - delay: 1, + delay: 0, })); + + // todo add proxy call }) } From 7f19a31a0f12251784ab387bb12aa28684ce4975 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 25 Sep 2024 17:00:56 +0400 Subject: [PATCH 05/12] Remove redundant --- gbuiltins/proxy/src/lib.rs | 18 ++------- pallets/gear-builtin/src/proxy.rs | 17 --------- pallets/gear-builtin/src/tests/proxy.rs | 51 +++++++++++-------------- 3 files changed, 26 insertions(+), 60 deletions(-) diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs index d872f1436a8..6481e48a41a 100644 --- a/gbuiltins/proxy/src/lib.rs +++ b/gbuiltins/proxy/src/lib.rs @@ -18,13 +18,10 @@ #![no_std] -extern crate alloc; - -use alloc::vec::Vec; use gprimitives::ActorId; use scale_info::scale::{self, Decode, Encode}; -#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode)] #[codec(crate = scale)] pub enum Request { // todo currently with no delay @@ -35,22 +32,13 @@ pub enum Request { RemoveProxy { delegate: ActorId, proxy_type: ProxyType, - }, - Proxy { - real: ActorId, - force_proxy_type: Option, - encoded_call: Vec, - }, // RemoveProxies, - // Proxy, - // Announce, - // Proxy, - // ProxyAnnounced + } } /// Proxy type. /// /// The mirror enum for the one defined in vara-runtime crate. -#[derive(Debug, Clone, Eq, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode)] #[codec(crate = scale)] pub enum ProxyType { Any, diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs index c7e11870838..f30f1a059d8 100644 --- a/pallets/gear-builtin/src/proxy.rs +++ b/pallets/gear-builtin/src/proxy.rs @@ -63,23 +63,6 @@ where delay, } } - Request::Proxy { - real, - force_proxy_type, - encoded_call, - } => { - let real = T::Lookup::unlookup(real.cast()); - let force_proxy_type = force_proxy_type.map(Into::into); - let runtime_call = - ::RuntimeCall::decode(&mut encoded_call.as_ref()) - .map_err(|_| BuiltinActorError::DecodingError)?; - - pallet_proxy::Call::::proxy { - real, - force_proxy_type, - call: Box::new(runtime_call), - } - } } .into()) } diff --git a/pallets/gear-builtin/src/tests/proxy.rs b/pallets/gear-builtin/src/tests/proxy.rs index 214fcbc105c..e5e7359aced 100644 --- a/pallets/gear-builtin/src/tests/proxy.rs +++ b/pallets/gear-builtin/src/tests/proxy.rs @@ -34,19 +34,11 @@ fn add_remove_proxy_works() { new_test_ext().execute_with(|| { let proxy_pid = utils::upload_and_initialize_broker(); - assert_ok!(Gear::send_message( - RuntimeOrigin::signed(SIGNER), - proxy_pid, - Request::AddProxy { - delegate: SIGNER.cast(), - proxy_type: ProxyType::Any, - } - .encode(), - 10_000_000_000, - 0, - false, - )); - run_to_next_block(); + let add_proxy_req = Request::AddProxy { + delegate: SIGNER.cast(), + proxy_type: ProxyType::Any, + }; + utils::send_proxy_request(proxy_pid, add_proxy_req); System::assert_has_event(RuntimeEvent::Proxy(ProxyEvent::ProxyAdded { delegator: proxy_pid.cast(), @@ -57,19 +49,11 @@ fn add_remove_proxy_works() { System::reset_events(); - assert_ok!(Gear::send_message( - RuntimeOrigin::signed(SIGNER), - proxy_pid, - Request::RemoveProxy { - delegate: SIGNER.cast(), - proxy_type: ProxyType::Any, - } - .encode(), - 10_000_000_000, - 0, - false, - )); - run_to_next_block(); + let remove_proxy_req = Request::RemoveProxy { + delegate: SIGNER.cast(), + proxy_type: ProxyType::Any, + }; + utils::send_proxy_request(proxy_pid, remove_proxy_req); System::assert_has_event(RuntimeEvent::Proxy(ProxyEvent::ProxyRemoved { delegator: proxy_pid.cast(), @@ -77,8 +61,6 @@ fn add_remove_proxy_works() { proxy_type: ProxyType::Any.into(), delay: 0, })); - - // todo add proxy call }) } @@ -100,6 +82,7 @@ mod utils { )); run_to_next_block(); + // Top-up balance of the proxy so it can pay adding proxy deposit assert_ok!(>::transfer( &1, &pid.cast(), @@ -109,4 +92,16 @@ mod utils { pid } + + pub(super) fn send_proxy_request(proxy_pid: ProgramId, req: Request) { + assert_ok!(Gear::send_message( + RuntimeOrigin::signed(SIGNER), + proxy_pid, + req.encode(), + 10_000_000_000, + 0, + false, + )); + run_to_next_block(); + } } From 5217ecb38bb5f8ac2d8f597c1b1392a3882530ee Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 25 Sep 2024 17:06:43 +0400 Subject: [PATCH 06/12] Remove todos --- gbuiltins/proxy/src/lib.rs | 4 ++-- pallets/gear-builtin/src/proxy.rs | 1 - pallets/gear-builtin/src/tests/proxy.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs index 6481e48a41a..4de17d84136 100644 --- a/gbuiltins/proxy/src/lib.rs +++ b/gbuiltins/proxy/src/lib.rs @@ -24,7 +24,7 @@ use scale_info::scale::{self, Decode, Encode}; #[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode)] #[codec(crate = scale)] pub enum Request { - // todo currently with no delay + // todo add comment currently with no delay AddProxy { delegate: ActorId, proxy_type: ProxyType, @@ -32,7 +32,7 @@ pub enum Request { RemoveProxy { delegate: ActorId, proxy_type: ProxyType, - } + }, } /// Proxy type. diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs index f30f1a059d8..6665401bdbb 100644 --- a/pallets/gear-builtin/src/proxy.rs +++ b/pallets/gear-builtin/src/proxy.rs @@ -83,7 +83,6 @@ where let origin = dispatch.source().cast(); - // todo spend gas match Self::cast(request) { Ok(call) => { let (result, actual_gas) = Pallet::::dispatch_call(origin, call, gas_limit); diff --git a/pallets/gear-builtin/src/tests/proxy.rs b/pallets/gear-builtin/src/tests/proxy.rs index e5e7359aced..6631c0e5b7b 100644 --- a/pallets/gear-builtin/src/tests/proxy.rs +++ b/pallets/gear-builtin/src/tests/proxy.rs @@ -44,7 +44,7 @@ fn add_remove_proxy_works() { delegator: proxy_pid.cast(), delegatee: SIGNER, proxy_type: ProxyType::Any.into(), - delay: 0 + delay: 0, })); System::reset_events(); From 867ca3db36dbf66e48578a5751da284231ab5881 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Wed, 25 Sep 2024 17:29:44 +0400 Subject: [PATCH 07/12] Add test, change actor ID --- pallets/gear-builtin/src/tests/proxy.rs | 59 +++++++++++++++++++++++-- runtime/vara/src/lib.rs | 7 +-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/pallets/gear-builtin/src/tests/proxy.rs b/pallets/gear-builtin/src/tests/proxy.rs index 6631c0e5b7b..d693d9b902c 100644 --- a/pallets/gear-builtin/src/tests/proxy.rs +++ b/pallets/gear-builtin/src/tests/proxy.rs @@ -22,10 +22,11 @@ use super::basic::init_logger; use crate::mock::*; use common::Origin; use demo_proxy_broker::WASM_BINARY; -use frame_support::assert_ok; +use frame_support::{assert_err, assert_ok}; use gbuiltin_proxy::{ProxyType, Request}; use gear_core::ids::{prelude::*, CodeId, ProgramId}; -use pallet_proxy::Event as ProxyEvent; +use pallet_balances::Call as BalancesCall; +use pallet_proxy::{Error as ProxyError, Event as ProxyEvent}; use parity_scale_codec::Encode; #[test] @@ -34,6 +35,7 @@ fn add_remove_proxy_works() { new_test_ext().execute_with(|| { let proxy_pid = utils::upload_and_initialize_broker(); + // Add proxy let add_proxy_req = Request::AddProxy { delegate: SIGNER.cast(), proxy_type: ProxyType::Any, @@ -49,6 +51,7 @@ fn add_remove_proxy_works() { System::reset_events(); + // Remove proxy let remove_proxy_req = Request::RemoveProxy { delegate: SIGNER.cast(), proxy_type: ProxyType::Any, @@ -61,6 +64,56 @@ fn add_remove_proxy_works() { proxy_type: ProxyType::Any.into(), delay: 0, })); + + // Execute proxy + let dest = 42; + let value = EXISTENTIAL_DEPOSIT * 3; + let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }); + + assert_err!( + Proxy::proxy( + RuntimeOrigin::signed(SIGNER), + proxy_pid.cast(), + None, + Box::new(call) + ), + ProxyError::::NotProxy, + ); + }) +} + +#[test] +fn add_execute_proxy_works() { + init_logger(); + new_test_ext().execute_with(|| { + let proxy_pid = utils::upload_and_initialize_broker(); + + // Add proxy + let add_proxy_req = Request::AddProxy { + delegate: SIGNER.cast(), + proxy_type: ProxyType::Any, + }; + utils::send_proxy_request(proxy_pid, add_proxy_req); + + System::assert_has_event(RuntimeEvent::Proxy(ProxyEvent::ProxyAdded { + delegator: proxy_pid.cast(), + delegatee: SIGNER, + proxy_type: ProxyType::Any.into(), + delay: 0, + })); + + // Execute proxy + let dest = 42; + let value = EXISTENTIAL_DEPOSIT * 3; + let call = RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }); + + assert_ok!(Proxy::proxy( + RuntimeOrigin::signed(SIGNER), + proxy_pid.cast(), + None, + Box::new(call) + )); + assert_eq!(Balances::free_balance(dest), value); }) } @@ -86,7 +139,7 @@ mod utils { assert_ok!(>::transfer( &1, &pid.cast(), - 2000, + 10 * EXISTENTIAL_DEPOSIT, frame_support::traits::ExistenceRequirement::AllowDeath )); diff --git a/runtime/vara/src/lib.rs b/runtime/vara/src/lib.rs index f1e0ccbab0f..f884ab5eb05 100644 --- a/runtime/vara/src/lib.rs +++ b/runtime/vara/src/lib.rs @@ -1194,7 +1194,8 @@ impl pallet_gear_messenger::Config for Runtime { pub type BuiltinActors = ( ActorWithId<1, pallet_gear_builtin::bls12_381::Actor>, ActorWithId<2, pallet_gear_builtin::staking::Actor>, - ActorWithId<3, pallet_gear_builtin::proxy::Actor>, + // The ID = 3 is for the pallet_gear_eth_bridge::Actor. + ActorWithId<4, pallet_gear_builtin::proxy::Actor>, ); /// Builtin actors arranged in a tuple. @@ -1202,8 +1203,8 @@ pub type BuiltinActors = ( pub type BuiltinActors = ( ActorWithId<1, pallet_gear_builtin::bls12_381::Actor>, ActorWithId<2, pallet_gear_builtin::staking::Actor>, - ActorWithId<3, pallet_gear_builtin::proxy::Actor>, - ActorWithId<4, pallet_gear_eth_bridge::Actor>, + ActorWithId<3, pallet_gear_eth_bridge::Actor>, + ActorWithId<4, pallet_gear_builtin::proxy::Actor>, ); impl pallet_gear_builtin::Config for Runtime { From f0acd0bd442b088493839161ab278e272daac37e Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Thu, 26 Sep 2024 10:26:08 +0400 Subject: [PATCH 08/12] Add docs, clean-up --- Cargo.lock | 3 --- examples/proxy-broker/Cargo.toml | 3 --- examples/proxy-broker/src/wasm.rs | 7 ++----- gbuiltins/proxy/src/lib.rs | 16 +++++++++++++++- pallets/gear-builtin/src/mock.rs | 2 +- pallets/gear-builtin/src/proxy.rs | 1 + pallets/gear-builtin/src/tests/mod.rs | 8 ++++---- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c823115876..87b64940492 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3846,9 +3846,6 @@ dependencies = [ "gbuiltin-proxy", "gear-wasm-builder", "gstd", - "hashbrown 0.14.5", - "hex", - "hex-literal", "parity-scale-codec", ] diff --git a/examples/proxy-broker/Cargo.toml b/examples/proxy-broker/Cargo.toml index f87c48a6a60..d0d1a943a99 100644 --- a/examples/proxy-broker/Cargo.toml +++ b/examples/proxy-broker/Cargo.toml @@ -10,9 +10,6 @@ repository.workspace = true [dependencies] gbuiltin-proxy.workspace = true gstd.workspace = true -hashbrown.workspace = true -hex.workspace = true -hex-literal.workspace = true parity-scale-codec.workspace = true [build-dependencies] diff --git a/examples/proxy-broker/src/wasm.rs b/examples/proxy-broker/src/wasm.rs index bdf584fc4cf..8613592f2b9 100644 --- a/examples/proxy-broker/src/wasm.rs +++ b/examples/proxy-broker/src/wasm.rs @@ -19,15 +19,12 @@ //! Basic implementation of the proxy-broker for demo purpose only. use gbuiltin_proxy::Request; -use gstd::{debug, errors::Error, msg, ActorId}; -use hex_literal::hex; +use gstd::{debug, errors::Error, msg, ActorId, actor_id}; // Proxy builtin actor program id (hardcoded for all runtimes); // // Calculated as hash((b"built/in", 3u64).encode()) -const BUILTIN_ADDRESS: ActorId = ActorId::new(hex!( - "f2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf" -)); +const BUILTIN_ADDRESS: ActorId = actor_id!("0xf2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf"); #[gstd::async_main] async fn main() { diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs index 4de17d84136..7ddaa911f6a 100644 --- a/gbuiltins/proxy/src/lib.rs +++ b/gbuiltins/proxy/src/lib.rs @@ -16,19 +16,33 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +//! Types used to communicate with proxy built-in. + #![no_std] use gprimitives::ActorId; use scale_info::scale::{self, Decode, Encode}; +/// Request that can be handled by the proxy builtin. +/// +/// Currently all proxies aren't required to send announcement, +/// i.e. no delays for the delegate actions. #[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode)] #[codec(crate = scale)] pub enum Request { - // todo add comment currently with no delay + /// Add proxy request. + /// + /// Requests to add `delegate` as a delegate for the actions + /// defined by `proxy_type` to be done on behalf of the request + /// sender. AddProxy { delegate: ActorId, proxy_type: ProxyType, }, + /// Remove proxy request. + /// + /// Request sender asks to remove `delegate` with set of allowed actions + /// defined in `proxy_type` from his list of proxies. RemoveProxy { delegate: ActorId, proxy_type: ProxyType, diff --git a/pallets/gear-builtin/src/mock.rs b/pallets/gear-builtin/src/mock.rs index bf66e8bdc94..22261d4eab8 100644 --- a/pallets/gear-builtin/src/mock.rs +++ b/pallets/gear-builtin/src/mock.rs @@ -145,7 +145,7 @@ impl InstanceFilter for ProxyType { match self { ProxyType::Any => true, ProxyType::NonTransfer => { - return !matches!(c, RuntimeCall::Balances(..)); + !matches!(c, RuntimeCall::Balances(..)) } ProxyType::CancelProxy => { matches!( diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs index 6665401bdbb..a1c1b28d672 100644 --- a/pallets/gear-builtin/src/proxy.rs +++ b/pallets/gear-builtin/src/proxy.rs @@ -33,6 +33,7 @@ where ::ProxyType: From, CallOf: From>, { + /// Casts received request to a runtime call. fn cast(request: Request) -> Result, BuiltinActorError> { Ok(match request { Request::AddProxy { diff --git a/pallets/gear-builtin/src/tests/mod.rs b/pallets/gear-builtin/src/tests/mod.rs index 4ef70e44a06..99ab57e66a4 100644 --- a/pallets/gear-builtin/src/tests/mod.rs +++ b/pallets/gear-builtin/src/tests/mod.rs @@ -18,8 +18,8 @@ //! Builtin actor pallet tests. -pub mod bad_builtin_ids; -pub mod basic; -pub mod bls381; +mod bad_builtin_ids; +mod basic; +mod bls381; mod proxy; -pub mod staking; +mod staking; From a3d5668700f9864fab93ef8e43fe82bfdc90437d Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Thu, 26 Sep 2024 10:26:31 +0400 Subject: [PATCH 09/12] Fmt --- examples/proxy-broker/src/wasm.rs | 5 +++-- gbuiltins/proxy/src/lib.rs | 10 +++++----- pallets/gear-builtin/src/mock.rs | 4 +--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/examples/proxy-broker/src/wasm.rs b/examples/proxy-broker/src/wasm.rs index 8613592f2b9..f3f9225360e 100644 --- a/examples/proxy-broker/src/wasm.rs +++ b/examples/proxy-broker/src/wasm.rs @@ -19,12 +19,13 @@ //! Basic implementation of the proxy-broker for demo purpose only. use gbuiltin_proxy::Request; -use gstd::{debug, errors::Error, msg, ActorId, actor_id}; +use gstd::{actor_id, debug, errors::Error, msg, ActorId}; // Proxy builtin actor program id (hardcoded for all runtimes); // // Calculated as hash((b"built/in", 3u64).encode()) -const BUILTIN_ADDRESS: ActorId = actor_id!("0xf2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf"); +const BUILTIN_ADDRESS: ActorId = + actor_id!("0xf2816ced0b15749595392d3a18b5a2363d6fefe5b3b6153739f218151b7acdbf"); #[gstd::async_main] async fn main() { diff --git a/gbuiltins/proxy/src/lib.rs b/gbuiltins/proxy/src/lib.rs index 7ddaa911f6a..49eecad834b 100644 --- a/gbuiltins/proxy/src/lib.rs +++ b/gbuiltins/proxy/src/lib.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Types used to communicate with proxy built-in. +//! Types used to communicate with proxy built-in. #![no_std] @@ -24,14 +24,14 @@ use gprimitives::ActorId; use scale_info::scale::{self, Decode, Encode}; /// Request that can be handled by the proxy builtin. -/// +/// /// Currently all proxies aren't required to send announcement, /// i.e. no delays for the delegate actions. #[derive(Debug, Clone, Copy, Eq, PartialEq, Encode, Decode)] #[codec(crate = scale)] pub enum Request { /// Add proxy request. - /// + /// /// Requests to add `delegate` as a delegate for the actions /// defined by `proxy_type` to be done on behalf of the request /// sender. @@ -40,9 +40,9 @@ pub enum Request { proxy_type: ProxyType, }, /// Remove proxy request. - /// + /// /// Request sender asks to remove `delegate` with set of allowed actions - /// defined in `proxy_type` from his list of proxies. + /// defined in `proxy_type` from his list of proxies. RemoveProxy { delegate: ActorId, proxy_type: ProxyType, diff --git a/pallets/gear-builtin/src/mock.rs b/pallets/gear-builtin/src/mock.rs index 22261d4eab8..77d22b0809b 100644 --- a/pallets/gear-builtin/src/mock.rs +++ b/pallets/gear-builtin/src/mock.rs @@ -144,9 +144,7 @@ impl InstanceFilter for ProxyType { fn filter(&self, c: &RuntimeCall) -> bool { match self { ProxyType::Any => true, - ProxyType::NonTransfer => { - !matches!(c, RuntimeCall::Balances(..)) - } + ProxyType::NonTransfer => !matches!(c, RuntimeCall::Balances(..)), ProxyType::CancelProxy => { matches!( c, From f55b40421ce6ab09de49e752da601bfe5dd0bd58 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 30 Sep 2024 11:45:38 +0400 Subject: [PATCH 10/12] Test CI --- .github/workflows/check.yml | 5 ++++- Cargo.lock | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index fe9618cceba..650f427ed33 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -55,7 +55,10 @@ jobs: run: ./scripts/gear.sh format doc --check - name: "Check clippy: Gear" - run: ./scripts/gear.sh clippy gear --all-targets --all-features --locked + run: ./scripts/gear.sh clippy gear --all-targets --all-features + + - name: "Check diff" + run: git diff - name: "Check clippy: Examples" run: ./scripts/gear.sh clippy examples --all-targets --locked diff --git a/Cargo.lock b/Cargo.lock index 16c806a2755..02c20e7cf4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6286,7 +6286,7 @@ dependencies = [ [[package]] name = "gbuiltin-proxy" -version = "1.5.0" +version = "1.6.1" dependencies = [ "derive_more 0.99.18", "gprimitives", From cfc393023557e94f44d0d2e093aa5c7c96885de7 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Mon, 30 Sep 2024 12:05:31 +0400 Subject: [PATCH 11/12] update CI --- .github/workflows/check.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 650f427ed33..fe9618cceba 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -55,10 +55,7 @@ jobs: run: ./scripts/gear.sh format doc --check - name: "Check clippy: Gear" - run: ./scripts/gear.sh clippy gear --all-targets --all-features - - - name: "Check diff" - run: git diff + run: ./scripts/gear.sh clippy gear --all-targets --all-features --locked - name: "Check clippy: Examples" run: ./scripts/gear.sh clippy examples --all-targets --locked From 819e654cb3b1cd347e699af4bd74d9301ad8efd9 Mon Sep 17 00:00:00 2001 From: Sabaun Taraki Date: Fri, 11 Oct 2024 10:15:03 +0300 Subject: [PATCH 12/12] Apply review --- pallets/gear-builtin/src/lib.rs | 10 +++++++--- pallets/gear-builtin/src/proxy.rs | 2 +- pallets/gear-builtin/src/staking.rs | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pallets/gear-builtin/src/lib.rs b/pallets/gear-builtin/src/lib.rs index 304db8577a7..4109567c7ad 100644 --- a/pallets/gear-builtin/src/lib.rs +++ b/pallets/gear-builtin/src/lib.rs @@ -176,6 +176,7 @@ impl BuiltinCollection for Tuple { #[frame_support::pallet] pub mod pallet { use super::*; + use common::Origin; use frame_support::{ dispatch::{GetDispatchInfo, PostDispatchInfo}, pallet_prelude::*, @@ -218,10 +219,13 @@ pub mod pallet { } pub(crate) fn dispatch_call( - origin: T::AccountId, + origin: ProgramId, call: CallOf, gas_limit: u64, - ) -> (Result<(), BuiltinActorError>, u64) { + ) -> (Result<(), BuiltinActorError>, u64) + where + T::AccountId: Origin, + { let call_info = call.get_dispatch_info(); // Necessary upfront gas sufficiency check @@ -230,7 +234,7 @@ pub mod pallet { } // Execute call - let res = call.dispatch(frame_system::RawOrigin::Signed(origin).into()); + let res = call.dispatch(frame_system::RawOrigin::Signed(origin.cast()).into()); let actual_gas = extract_actual_weight(&res, &call_info).ref_time(); match res { diff --git a/pallets/gear-builtin/src/proxy.rs b/pallets/gear-builtin/src/proxy.rs index a1c1b28d672..0a68ca2c5c2 100644 --- a/pallets/gear-builtin/src/proxy.rs +++ b/pallets/gear-builtin/src/proxy.rs @@ -82,7 +82,7 @@ where return (Err(BuiltinActorError::DecodingError), 0); }; - let origin = dispatch.source().cast(); + let origin = dispatch.source(); match Self::cast(request) { Ok(call) => { diff --git a/pallets/gear-builtin/src/staking.rs b/pallets/gear-builtin/src/staking.rs index f03db222f8c..a5a24370cd5 100644 --- a/pallets/gear-builtin/src/staking.rs +++ b/pallets/gear-builtin/src/staking.rs @@ -108,7 +108,7 @@ where fn handle(dispatch: &StoredDispatch, gas_limit: u64) -> (Result, u64) { let message = dispatch.message(); - let origin: T::AccountId = dispatch.source().cast(); + let origin = dispatch.source(); let mut payload = message.payload_bytes(); // Rule out payloads that exceed the largest reasonable size.