Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow additional account as container chain manager #546

Merged
merged 17 commits into from
May 21, 2024
29 changes: 27 additions & 2 deletions pallets/registrar/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

//! Benchmarking
use {
crate::{Call, Config, DepositBalanceOf, Pallet, RegistrarHooks},
crate::{Call, Config, DepositBalanceOf, EnsureSignedByManager, Pallet, RegistrarHooks},
frame_benchmarking::{account, v2::*},
frame_support::traits::Currency,
frame_support::traits::{Currency, EnsureOriginWithArg},
frame_system::RawOrigin,
sp_core::Get,
sp_std::{vec, vec::Vec},
Expand Down Expand Up @@ -448,5 +448,30 @@ mod benchmarks {
);
}

#[benchmark]
fn set_para_manager() {
let para_id = 1001u32.into();

let origin = EnsureSignedByManager::<T>::try_successful_origin(&para_id)
.expect("failed to create ManagerOrigin");

let manager_address = account("sufficient", 0, 1000);

// Before call: not set as manager
assert_ne!(
crate::ParaManager::<T>::get(para_id).as_ref(),
Some(&manager_address)
);

#[extrinsic_call]
Pallet::<T>::set_para_manager(origin as T::RuntimeOrigin, para_id, manager_address.clone());

// After call: para manager
assert_eq!(
crate::ParaManager::<T>::get(para_id).as_ref(),
Some(&manager_address)
);
}

impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
}
55 changes: 45 additions & 10 deletions pallets/registrar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//!
//! This pallet is in charge of registering containerChains (identified by their Id)
//! that have to be served by the orchestrator chain. Parachains registrations and de-
//! registrations are not immediatly applied, but rather they take T::SessionDelay sessions
//! registrations are not immediately applied, but rather they take T::SessionDelay sessions
//! to be applied.
//!
//! Registered container chains are stored in the PendingParaIds storage item until the session
Expand All @@ -43,7 +43,7 @@ pub use pallet::*;
use {
frame_support::{
pallet_prelude::*,
traits::{Currency, ReservableCurrency},
traits::{Currency, EnsureOriginWithArg, ReservableCurrency},
DefaultNoBound, LOG_TARGET,
},
frame_system::pallet_prelude::*,
Expand Down Expand Up @@ -229,6 +229,10 @@ pub mod pallet {
#[pallet::getter(fn registrar_deposit)]
pub type RegistrarDeposit<T: Config> = StorageMap<_, Blake2_128Concat, ParaId, DepositInfo<T>>;

#[pallet::storage]
pub type ParaManager<T: Config> =
StorageMap<_, Blake2_128Concat, ParaId, T::AccountId, OptionQuery>;
fgamundi marked this conversation as resolved.
Show resolved Hide resolved

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
Expand All @@ -244,6 +248,11 @@ pub mod pallet {
ParaIdUnpaused { para_id: ParaId },
/// Parathread params changed
ParathreadParamsChanged { para_id: ParaId },
/// Para manager has changed
ParaManagerChanged {
para_id: ParaId,
manager_address: T::AccountId,
},
}

#[pallet::error]
Expand All @@ -268,6 +277,8 @@ pub mod pallet {
NotSufficientDeposit,
/// Tried to change parathread params for a para id that is not a registered parathread
NotAParathread,
/// Attempted to execute an extrinsic meant only for the para creator
NotParaCreator,
}

#[pallet::hooks]
Expand Down Expand Up @@ -585,6 +596,30 @@ pub mod pallet {

Ok(())
}

#[pallet::call_index(8)]
#[pallet::weight(T::WeightInfo::set_para_manager())]
pub fn set_para_manager(
fgamundi marked this conversation as resolved.
Show resolved Hide resolved
origin: OriginFor<T>,
para_id: ParaId,
manager_address: T::AccountId,
) -> DispatchResult {
let origin = ensure_signed(origin)?;

let creator =
RegistrarDeposit::<T>::get(para_id).map(|deposit_info| deposit_info.creator);

ensure!(Some(origin) == creator, Error::<T>::NotParaCreator);

ParaManager::<T>::insert(para_id, manager_address.clone());

Self::deposit_event(Event::<T>::ParaManagerChanged {
para_id,
manager_address,
});

Ok(())
}
}

pub struct SessionChangeOutcome<T: Config> {
Expand All @@ -598,11 +633,8 @@ pub mod pallet {
pub fn is_para_manager(para_id: &ParaId, account: &T::AccountId) -> bool {
// This check will only pass if both are true:
// * The para_id has a deposit in pallet_registrar
// * The deposit creator is the signed_account
RegistrarDeposit::<T>::get(para_id)
.map(|deposit_info| deposit_info.creator)
.as_ref()
== Some(account)
// * The signed_account is the para manager
tmpolaczyk marked this conversation as resolved.
Show resolved Hide resolved
ParaManager::<T>::get(para_id).as_ref() == Some(account)
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down Expand Up @@ -693,12 +725,14 @@ pub mod pallet {
RegistrarDeposit::<T>::insert(
para_id,
DepositInfo {
creator: account,
creator: account.clone(),
deposit,
},
);
ParaGenesisData::<T>::insert(para_id, genesis_data);

ParaManager::<T>::insert(para_id, account);

Ok(())
}

Expand Down Expand Up @@ -999,6 +1033,8 @@ pub mod pallet {
T::Currency::unreserve(&asset_info.creator, asset_info.deposit);
}

ParaManager::<T>::remove(para_id);

T::RegistrarHooks::para_deregistered(para_id);
}

Expand Down Expand Up @@ -1112,8 +1148,7 @@ impl RegistrarHooks for () {}

pub struct EnsureSignedByManager<T>(sp_std::marker::PhantomData<T>);

impl<T> frame_support::traits::EnsureOriginWithArg<T::RuntimeOrigin, ParaId>
for EnsureSignedByManager<T>
impl<T> EnsureOriginWithArg<T::RuntimeOrigin, ParaId> for EnsureSignedByManager<T>
where
T: Config,
{
Expand Down
27 changes: 27 additions & 0 deletions pallets/registrar/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub trait WeightInfo {
fn unpause_container_chain(y: u32, ) -> Weight;
fn register_parathread(x: u32, y: u32, z: u32, ) -> Weight;
fn set_parathread_params(y: u32, ) -> Weight;
fn set_para_manager() -> Weight;
}

/// Weights for pallet_registrar using the Substrate node and recommended hardware.
Expand Down Expand Up @@ -263,6 +264,19 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(T::DbWeight::get().reads(3_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
/// Storage: `Registrar::RegistrarDeposit` (r:1 w:0)
/// Proof: `Registrar::RegistrarDeposit` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Registrar::ParaManager` (r:0 w:1)
/// Proof: `Registrar::ParaManager` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn set_para_manager() -> Weight {
// Proof Size summary in bytes:
// Measured: `204`
// Estimated: `3669`
// Minimum execution time: 12_741_000 picoseconds.
Weight::from_parts(13_119_000, 3669)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
}

// For backwards compatibility and tests
Expand Down Expand Up @@ -464,4 +478,17 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(3_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
/// Storage: `Registrar::RegistrarDeposit` (r:1 w:0)
/// Proof: `Registrar::RegistrarDeposit` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Registrar::ParaManager` (r:0 w:1)
/// Proof: `Registrar::ParaManager` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn set_para_manager() -> Weight {
// Proof Size summary in bytes:
// Measured: `204`
// Estimated: `3669`
// Minimum execution time: 12_741_000 picoseconds.
Weight::from_parts(13_119_000, 3669)
.saturating_add(RocksDbWeight::get().reads(1_u64))
.saturating_add(RocksDbWeight::get().writes(1_u64))
}
}
13 changes: 13 additions & 0 deletions runtime/dancebox/src/weights/pallet_registrar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,17 @@ impl<T: frame_system::Config> pallet_registrar::WeightInfo for SubstrateWeight<T
.saturating_add(T::DbWeight::get().writes(1_u64))
.saturating_add(Weight::from_parts(0, 11).saturating_mul(y.into()))
}
/// Storage: `Registrar::RegistrarDeposit` (r:1 w:0)
/// Proof: `Registrar::RegistrarDeposit` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Registrar::ParaManager` (r:0 w:1)
/// Proof: `Registrar::ParaManager` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn set_para_manager() -> Weight {
// Proof Size summary in bytes:
// Measured: `204`
// Estimated: `3669`
// Minimum execution time: 7_683_000 picoseconds.
Weight::from_parts(8_047_000, 3669)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
}
13 changes: 13 additions & 0 deletions runtime/flashbox/src/weights/pallet_registrar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,17 @@ impl<T: frame_system::Config> pallet_registrar::WeightInfo for SubstrateWeight<T
.saturating_add(T::DbWeight::get().writes(1_u64))
.saturating_add(Weight::from_parts(0, 11).saturating_mul(y.into()))
}
/// Storage: `Registrar::RegistrarDeposit` (r:1 w:0)
/// Proof: `Registrar::RegistrarDeposit` (`max_values`: None, `max_size`: None, mode: `Measured`)
/// Storage: `Registrar::ParaManager` (r:0 w:1)
/// Proof: `Registrar::ParaManager` (`max_values`: None, `max_size`: None, mode: `Measured`)
fn set_para_manager() -> Weight {
// Proof Size summary in bytes:
// Measured: `204`
// Estimated: `3669`
// Minimum execution time: 13_268_000 picoseconds.
Weight::from_parts(13_793_000, 3669)
.saturating_add(T::DbWeight::get().reads(1_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
}
77 changes: 77 additions & 0 deletions test/suites/common-tanssi/registrar/test_registrar_para_manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import "@tanssi/api-augment";
import { describeSuite, expect, beforeAll } from "@moonwall/cli";
import { KeyringPair } from "@moonwall/util";
import { ApiPromise } from "@polkadot/api";

describeSuite({
id: "CT0502",
title: "Registrar para manager",
foundationMethods: "dev",
testCases: ({ it, context }) => {
let polkadotJs: ApiPromise;
let alice: KeyringPair;
let bob: KeyringPair;
const paraId = 2002;

beforeAll(() => {
alice = context.keyring.alice;
bob = context.keyring.bob;
polkadotJs = context.polkadotJs();
});

it({
id: "E01",
title: "Para manager can be set and is recognized as ManagerOrigin",
test: async function () {
await context.createBlock();

const emptyGenesisData = () => {
const g = polkadotJs.createType("TpContainerChainGenesisDataContainerChainGenesisData", {
storage: [
{
key: "0x636f6465",
value: "0x010203040506",
},
],
name: "0x436f6e7461696e657220436861696e2032303030",
id: "0x636f6e7461696e65722d636861696e2d32303030",
forkId: null,
extensions: "0x",
properties: {
tokenMetadata: {
tokenSymbol: "0x61626364",
ss58Format: 42,
tokenDecimals: 12,
},
isEthereum: false,
},
});
return g;
};
const containerChainGenesisData = emptyGenesisData();

await context.createBlock([
await polkadotJs.tx.registrar.register(paraId, containerChainGenesisData).signAsync(alice),
]);

// Bob still not a manager, extrinsic requiring ManagerOrigin should fail
const { result } = await context.createBlock(
await polkadotJs.tx.servicesPayment.setRefundAddress(paraId, bob.address).signAsync(bob)
);
expect(result.successful).to.be.false;

// Set bob as manager
await context.createBlock([
await polkadotJs.tx.registrar.setParaManager(paraId, bob.address).signAsync(alice),
]);

// Extrinsic should succeed now
const { result: result2 } = await context.createBlock(
await polkadotJs.tx.servicesPayment.setRefundAddress(paraId, bob.address).signAsync(bob)
);

expect(result2.successful).to.be.true;
},
});
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ApiPromise } from "@polkadot/api";
import { jumpSessions } from "../../../util/block";

describeSuite({
id: "CT0504",
id: "CT0503",
title: "Registrar test suite: pause",
foundationMethods: "dev",
testCases: ({ it, context }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ApiPromise } from "@polkadot/api";
import { jumpSessions } from "util/block";

describeSuite({
id: "DT0605",
id: "DT0604",
title: "Registrar test suite",
foundationMethods: "dev",
testCases: ({ it, context }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ApiPromise } from "@polkadot/api";
import { jumpSessions } from "../../../util/block";

describeSuite({
id: "CT0502",
id: "CT0506",
title: "Registrar test suite",
foundationMethods: "dev",
testCases: ({ it, context }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ApiPromise } from "@polkadot/api";
import { jumpSessions } from "../../../util/block";

describeSuite({
id: "CT0506",
id: "CT0505",
title: "Registrar test suite",
foundationMethods: "dev",
testCases: ({ it, context }) => {
Expand Down
2 changes: 1 addition & 1 deletion test/suites/common-tanssi/registrar/test_utils_rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { chainSpecToContainerChainGenesisData, containerChainGenesisDataToChainS
import "@polkadot/api-augment";

describeSuite({
id: "CT0503",
id: "CT0507",
title: "Test ContainerChainGenesisData utils",
foundationMethods: "dev",
testCases: ({ it, context }) => {
Expand Down
2 changes: 2 additions & 0 deletions typescript-api/src/dancebox/interfaces/augment-api-errors.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading