Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Feat/processor manager #48

Merged
merged 9 commits into from
Feb 15, 2023
65 changes: 65 additions & 0 deletions pallets/acurast-processor-manager/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[package]
name = "pallet-acurast-processor-manager"
version = "0.1.0"
license = "MIT"
homepage = "https://docs.acurast.com/"
edition = "2021"
publish = false
repository = "https://github.com/acurast/"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }

acurast-common = { path = "../acurast/common", default-features = false }

# Benchmarks
frame-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "polkadot-v0.9.36" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.36" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.36" }
parachains-common = { git = "https://github.com/paritytech/cumulus", optional = true, default-features = false, branch = "polkadot-v0.9.36" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.36" }
pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.36" }
pallet-uniques = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.36" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.36" }
hex-literal = { version = "0.3", optional = true }

# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" }
scale-info = { version = "2.2.0", default-features = false, features = [ "derive" ] }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" }

[dev-dependencies]
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
parachains-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.36" }
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
pallet-assets = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
pallet-uniques = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" }
hex-literal = { version = "0.3" }

[features]
default = ["std"]
std = [
"codec/std",
"scale-info/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
"acurast-common/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"sp-io",
"sp-core",
"parachains-common",
"pallet-assets",
"pallet-uniques",
"pallet-timestamp",
"hex-literal",
]
try-runtime = ["frame-support/try-runtime"]
88 changes: 88 additions & 0 deletions pallets/acurast-processor-manager/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//! Benchmarking setup for pallet-acurast-processor-manager

use crate::stub::{alice_account_id, generate_account};

use super::*;

use acurast_common::ListUpdateOperation;
use codec::Encode;
use frame_benchmarking::{benchmarks, whitelist_account};
use frame_support::{
sp_runtime::{
traits::{IdentifyAccount, StaticLookup, Verify},
AccountId32, MultiSignature,
},
traits::{Get, IsType},
};
use frame_system::RawOrigin;
use sp_core::Pair;
use sp_std::prelude::*;

fn generate_pairing_update<T: Config<AccountId = AccountId32, Proof = MultiSignature>>(
operation: ListUpdateOperation,
caller: &T::AccountId,
) -> ProcessorPairingUpdateFor<T> {
let (processor_pair, processor_account_id) = generate_account();
let timestamp = 1657363915002u128;
let message = [caller.encode(), timestamp.encode(), 1u128.encode()].concat();
let signature: MultiSignature = processor_pair.sign(&message).into();
ProcessorPairingUpdateFor::<T> {
operation,
item: ProcessorPairingFor::<T>::new_with_proof(processor_account_id, timestamp, signature),
}
}

benchmarks! {
where_clause { where
T: Config<AccountId = AccountId32, Proof = MultiSignature>,
T::AccountId: IsType<<<T::Proof as Verify>::Signer as IdentifyAccount>::AccountId>,
<<T as frame_system::Config>::Lookup as StaticLookup>::Source: From<AccountId32>,
}

update_processor_pairings {
let x in 1 .. T::MaxPairingUpdates::get();
let mut updates = Vec::<ProcessorPairingUpdateFor<T>>::new();
let caller: T::AccountId = alice_account_id().into();
whitelist_account!(caller);
for i in 0..x {
updates.push(generate_pairing_update::<T>(ListUpdateOperation::Add, &caller));
}
}: _(RawOrigin::Signed(caller), updates)

update_processor_pairings_2 {
let x in 1 .. T::MaxPairingUpdates::get();
let mut updates_add = Vec::<ProcessorPairingUpdateFor<T>>::new();
let caller: T::AccountId = alice_account_id().into();
whitelist_account!(caller);
for i in 0..x {
updates_add.push(generate_pairing_update::<T>(ListUpdateOperation::Add, &caller));
}
Pallet::<T>::update_processor_pairings(RawOrigin::Signed(caller.clone()).into(), updates_add.clone())?;
let updates_remove = updates_add.into_iter().map(|update| ProcessorPairingUpdateFor::<T> {
operation: ListUpdateOperation::Remove,
item: ProcessorPairingFor::<T>::new(update.item.account),
}).collect::<Vec<_>>();
}: update_processor_pairings(RawOrigin::Signed(caller), updates_remove)

pair_with_manager {
let (signer, manager_account) = generate_account();
let (_, processor_account) = generate_account();
let timestamp = 1657363915002u128;
let message = [manager_account.encode(), timestamp.encode(), 1u128.encode()].concat();
let signature: MultiSignature = signer.sign(&message).into();
let item = ProcessorPairingFor::<T>::new_with_proof(manager_account, timestamp, signature);
}: _(RawOrigin::Signed(processor_account), item)

recover_funds {
let caller: T::AccountId = alice_account_id().into();
whitelist_account!(caller);
let update = generate_pairing_update::<T>(ListUpdateOperation::Add, &caller);
Pallet::<T>::update_processor_pairings(RawOrigin::Signed(caller.clone()).into(), vec![update.clone()])?;
}: _(RawOrigin::Signed(caller.clone()), update.item.account.into(), caller.clone().into())

heartbeat {
let caller: T::AccountId = alice_account_id().into();
}: _(RawOrigin::Signed(caller.clone()))

impl_benchmark_test_suite!(Pallet, mock::ExtBuilder::default().build(), mock::Test);
}
78 changes: 78 additions & 0 deletions pallets/acurast-processor-manager/src/functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use frame_support::{
pallet_prelude::DispatchResult,
sp_runtime::{
traits::{CheckedAdd, IdentifyAccount, Verify},
DispatchError,
},
traits::IsType,
};

use crate::{
Config, Error, LastManagerId, ManagedProcessors, ManagerIdProvider, Pallet,
ProcessorToManagerIdIndex,
};

impl<T: Config> Pallet<T>
where
T::AccountId: IsType<<<T::Proof as Verify>::Signer as IdentifyAccount>::AccountId>,
{
/// Returns the manager account id (if any) for the given processor account.
pub fn manager_for_processor(processor_account: &T::AccountId) -> Option<T::AccountId> {
let id = Self::manager_id_for_processor(processor_account)?;
<T::ManagerIdProvider as ManagerIdProvider<T>>::owner_for(id).ok()
}

/// Returns the manager id for the given manager account. If a manager id does not exists it is first created.
pub fn do_get_or_create_manager_id(
manager: &T::AccountId,
) -> Result<(T::ManagerId, bool), DispatchError> {
T::ManagerIdProvider::manager_id_for(manager)
.map(|id| (id, false))
.or_else::<DispatchError, _>(|_| {
let id = <LastManagerId<T>>::get()
.unwrap_or(0u128.into())
.checked_add(&1u128.into())
.ok_or(Error::<T>::FailedToCreateManagerId)?;

T::ManagerIdProvider::create_manager_id(id, manager)?;
<LastManagerId<T>>::set(Some(id));

Ok((id, true))
})
}

/// Adds a pairing between the given processor account and manager id. It fails if the manager id does not exists of
/// if the processor account was already paired.
pub fn do_add_processor_manager_pairing(
processor_account: &T::AccountId,
manager_id: T::ManagerId,
) -> DispatchResult {
if let Some(id) = Self::manager_id_for_processor(&processor_account) {
if id == manager_id {
return Err(Error::<T>::ProcessorAlreadyPaired)?;
}
return Err(Error::<T>::ProcessorPairedWithAnotherManager)?;
}
<ManagedProcessors<T>>::insert(manager_id, &processor_account, ());
<ProcessorToManagerIdIndex<T>>::insert(&processor_account, manager_id);

Ok(())
}

/// Removes the pairing between a processor account and manager id. It fails if the processor account is paired
/// with a different manager id.
pub fn do_remove_processor_manager_pairing(
processor_account: &T::AccountId,
manager_id: T::ManagerId,
) -> DispatchResult {
if let Some(id) = Self::manager_id_for_processor(processor_account) {
if id != manager_id {
return Err(Error::<T>::ProcessorPairedWithAnotherManager)?;
}
<ManagedProcessors<T>>::remove(manager_id, &processor_account);
<ProcessorToManagerIdIndex<T>>::remove(&processor_account);
}

Ok(())
}
}
Loading